changeset 77:9d24db321029

Refactoring Web::TT docs
author wizard
date Fri, 02 Apr 2010 20:18:46 +0400
parents b1652a158b2b
children a5cb84374d40
files Lib/IMPL/DOM/Document.pm Lib/IMPL/Web/QueryHandler.pm Lib/IMPL/Web/QueryHandler/PageFormat.pm Lib/IMPL/Web/TDocument.pm Lib/IMPL/Web/TT/Document.pm _test/Resources/simple.tt _test/Test/Web/TDocument.pm _test/Test/Web/TT.pm _test/Web.t
diffstat 9 files changed, 308 insertions(+), 219 deletions(-) [+]
line wrap: on
line diff
--- a/Lib/IMPL/DOM/Document.pm	Wed Mar 31 16:17:13 2010 +0400
+++ b/Lib/IMPL/DOM/Document.pm	Fri Apr 02 20:18:46 2010 +0400
@@ -36,15 +36,58 @@
 
 =pod
 
+=head1 NAME
+
+C<IMPL::DOM::Document> DOM документ.
+
 =head1 DESCRIPTION
 
+Документ, позволяет создавать узлы определенных типов, что позволяет абстрагироваться
+от механизмов реального создания объектов. Т.о. например C<IMPL::DOM::Navigator::Builder>
+может формировать произвольные документы.
+
+=head1 SYNOPSIS
+
+=begin code
+
+package MyDocument;
+use base qw(IMPL::DOM::Document);
+
+sub Create {
+	my $this = shift;
+	my ($name,$class,$hashProps) = @_;
+	
+	if ($class eq 'Info') {
+		return MyInfo->new($name,$hashProps->{date},$hashProps->{description});
+	} else {
+		# leave as it is
+		return $this->SUPER::Create(@_);
+	}
+}
+
+=end code
+
 =head1 METHODS
 
 =over
 
-=item C<<$doc->Create>>
+=item C< Create($nodeName,$class,$hashProps) >
+
+Реализация по умолчанию. Создает узел определеннго типа с определенным именем и свойствами.
+
+=begin code
 
-Создает узел определеннго типа с определенным именем и свойствами.
+sub Create {
+	my ($this,$nodeName,$class,$hashProps) = @_;
+	
+	return $class->new (
+		nodeName => $nodeName,
+		document => $this,
+		%$hashProps
+	);
+}
+
+=end code
 
 =back
 
--- a/Lib/IMPL/Web/QueryHandler.pm	Wed Mar 31 16:17:13 2010 +0400
+++ b/Lib/IMPL/Web/QueryHandler.pm	Fri Apr 02 20:18:46 2010 +0400
@@ -18,7 +18,7 @@
 }
 
 sub Process {
-	die new NotImplementedException("The method isn't implemented", __PACKAGE__, 'Process');
+	die new IMPL::NotImplementedException("The method isn't implemented", __PACKAGE__, 'Process');
 }
 
 1;
--- a/Lib/IMPL/Web/QueryHandler/PageFormat.pm	Wed Mar 31 16:17:13 2010 +0400
+++ b/Lib/IMPL/Web/QueryHandler/PageFormat.pm	Fri Apr 02 20:18:46 2010 +0400
@@ -4,7 +4,7 @@
 __PACKAGE__->PassThroughArgs;
 
 use IMPL::Class::Property;
-use IMPL::Web::TDocument;
+use IMPL::Web::TT::Document;
 use File::Spec;
 use Error qw(:try);
 
@@ -23,12 +23,12 @@
 sub Process {
 	my ($this,$action,$nextHandler) = @_;
 	
-	my $doc = new IMPL::Web::TDocument();
+	my $doc = new IMPL::Web::TT::Document();
 	
 	try {
 		my @path = split /\//, $ENV{PATH_TRANSLATED};
 		
-		$doc->loadFile ( File::Spec->catfile($this->templatesBase,@path), $this->templatesCharset );
+		$doc->LoadFile ( File::Spec->catfile($this->templatesBase,@path), $this->templatesCharset );
 		
 		$action->response->contentType('text/html');
 		my $hOut = $action->response->streamBody;
--- a/Lib/IMPL/Web/TDocument.pm	Wed Mar 31 16:17:13 2010 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
-package IMPL::Web::TDocument;
-use strict;
-use warnings;
-
-use base qw(IMPL::DOM::Document IMPL::Object::Disposable);
-use Template::Context;
-use Template::Provider;
-use IMPL::Class::Property;
-use File::Spec;
-
-BEGIN {
-    private property _Provider => prop_all;
-    private property _Context => prop_all;
-    public property Template => prop_get | owner_set;
-}
-
-our %CTOR = (
-    'IMPL::DOM::Document' => sub { nodeName => 'document' }
-);
-
-sub Provider {
-    my ($this,%args) = @_;
-    
-    if (my $provider = $this->_Provider) {
-        return $provider;
-    } else {
-        return $this->_Provider(new Template::Provider(
-            \%args
-        ));
-    }
-}
-
-sub Context {
-    my ($this) = @_;
-    
-    if (my $ctx = $this->_Context) {
-        return $ctx;
-    } else {
-        return $this->_Context (
-            new Template::Context(
-                VARIABLES => {
-                    document => $this
-                },
-                TRIM => 1,
-                RECURSION => 1,
-                LOAD_TEMPLATES => [$this->Provider]
-            )
-        )
-    }
-}
-
-sub loadFile {
-    my ($this,$filePath,$encoding) = @_;
-    
-    die new IMPL::InvalidArgumentException("A filePath parameter is required") unless $filePath;
-    
-    $encoding ||= 'utf8';
-    
-    $this->_Context(undef);
-    $this->_Provider(undef);
-    
-    my ($vol,$dir,$fileName) = File::Spec->splitpath($filePath);
-    
-    my $inc = File::Spec->catpath($vol,$dir,'');
-    
-    $this->Provider(
-        ENCODING => $encoding,
-        INTERPOLATE => 1,
-        PRE_CHOMP => 1,
-        POST_CHOMP => 1,
-        INCLUDE_PATH => $inc
-    );
-    
-    $this->Template($this->Context->template($fileName));
-}
-
-sub Title {
-    $_[0]->Template->Title;
-}
-
-sub Render {
-    my ($this) = @_;
-    
-    return $this->Template->process($this->Context);
-}
-
-sub Dispose {
-    my ($this) = @_;
-    
-    $this->Template(undef);
-    $this->_Context(undef);
-    $this->_Provider(undef);
-    
-    $this->SUPER::Dispose();
-}
-
-1;
-__END__
-=pod
-
-=head1 SYNOPSIS
-
-=begin code 
-
-// create new document
-my $doc = new IMPL::Web::TDocument;
-
-// load template
-$doc->loadFile('Templates/index.tt');
-
-// render file
-print $doc->Render();
-
-=end code
-
-=head1 DESCRIPTION
-
-Документ, основанный на шаблоне Template::Toolkit. Позволяет загрузить шаблон,
-и сформировать окончательный документ. Является наследником C<IMPL::DOM::Node>,
-т.о. может быть использован для реализации DOM модели.
-
-Внутри шаблона переменная C<document> ссылается на объект документа. По этой
-причине образуется циклическая ссылка между объектами шаблона и документом, что
-требует вызова метода C<Dispose> для освобождения документа.
-
-=head1 METHODS
-
-=level 4
-
-=item C<new()>
-
-Создает новый экземпляр документа
-
-=item C<$doc->loadFile($fileName,$encoding)>
-
-Загружает шаблон из файла C<$fileName>, используя кодировку C<$encoding>. Если
-кодировка не указана, использует utf-8.
-
-=item C<$doc->Render()>
-
-Возвращает данные построенные на основе загруженного шаблона.
-
-=item C<$doc->Dispose()>
-
-Освобождает ресурсы и помечает объект как освобожденный.
-
-=back
-
-=head1 DOM
-
-=begin text
-
-[% table = document.tables.Add('env') %]
-
-[% FOEACH item in document.result %]
-	[% table.rows.Add( item.get('name','value') ) %]
-[% END %]
-
-[% form = document.forms.Add('login') %]
-
-[% form.loadValues( {user => 'guest', password => ''} ) %]
-
-[% form.template = BLOCK %]
-	[% %]
-	[% END %]
-[% END %]
-	
-
-=end text
-
-
-=cut
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/IMPL/Web/TT/Document.pm	Fri Apr 02 20:18:46 2010 +0400
@@ -0,0 +1,218 @@
+package IMPL::Web::TT::Document;
+use strict;
+use warnings;
+
+use base qw(IMPL::DOM::Document IMPL::Object::Disposable);
+use Template::Context;
+use Template::Provider;
+use IMPL::Class::Property;
+use File::Spec;
+use Scalar::Util qw(blessed);
+
+BEGIN {
+    private property _provider => prop_all;
+    private property _context => prop_all;
+    public property template => prop_get | owner_set;
+    public property presenter => prop_all, { validate => \&_validatePresenter };
+}
+
+our %CTOR = (
+    'IMPL::DOM::Document' => sub { nodeName => 'document' }
+);
+
+sub provider {
+    my ($this,%args) = @_;
+    
+    if (my $provider = $this->_provider) {
+        return $provider;
+    } else {
+        return $this->_provider(new Template::Provider(
+            \%args
+        ));
+    }
+}
+
+sub context {
+    my ($this) = @_;
+    
+    if (my $ctx = $this->_context) {
+        return $ctx;
+    } else {
+        return $this->_context (
+            new Template::Context(
+                VARIABLES => {
+                    document => $this,
+                    this => $this,
+                    render => sub {
+                    	$this->_process(@_);
+                    }
+                },
+                TRIM => 1,
+                RECURSION => 1,
+                LOAD_TEMPLATES => [$this->provider]
+            )
+        )
+    }
+}
+
+sub _validatePresenter {
+	my ($this,$value) = @_;
+	
+	die new IMPL::InvalidArgumentException("A view object is required") unless blessed($value) and $value->isa('Template::View');
+}
+
+sub LoadFile {
+    my ($this,$filePath,$encoding) = @_;
+    
+    die new IMPL::InvalidArgumentException("A filePath parameter is required") unless $filePath;
+    
+    $encoding ||= 'utf8';
+    
+    $this->_context(undef);
+    $this->_provider(undef);
+    
+    my ($vol,$dir,$fileName) = File::Spec->splitpath($filePath);
+    
+    my $inc = File::Spec->catpath($vol,$dir,'');
+    
+    $this->provider(
+        ENCODING => $encoding,
+        INTERPOLATE => 1,
+        PRE_CHOMP => 1,
+        POST_CHOMP => 1,
+        INCLUDE_PATH => $inc
+    );
+    
+    $this->template($this->context->template($fileName));
+}
+
+sub title {
+    $_[0]->template->title;
+}
+
+sub Render {
+    my ($this) = @_;
+    
+    return $this->template->process($this->context);
+}
+
+# Формирует представление для произвольных объектов 
+sub _process {
+	my ($this,@items) = @_;
+	
+	my @result;
+	
+	foreach my $item (@items) {
+		if (blessed($item) and $item->isa('IMPL::Web::TT::Control')) {
+			push @result, $item->Render();	
+		} elsif(blessed($item)) {
+			if ($this->presenter) {
+				push @result, $this->presenter->print($item);
+			} else {
+				push @result, $this->toString;
+			}
+		} else {
+			push @result, $item;
+		}
+	}
+	
+	return join '',@items;
+}
+
+sub Dispose {
+    my ($this) = @_;
+    
+    $this->template(undef);
+    $this->_context(undef);
+    $this->_provider(undef);
+    
+    $this->SUPER::Dispose();
+}
+
+1;
+__END__
+=pod
+
+=head1 NAME
+
+C<IMPL::Web::TT::Document> - Документ, позволяющий строить представление по шаблону
+
+=head1 SYNOPSIS
+
+=begin code 
+
+// create new document
+my $doc = new IMPL::Web::TT::Document;
+
+// load template
+$doc->loadFile('Templates/index.tt');
+
+// render file
+print $doc->Render();
+
+=end code
+
+=head1 DESCRIPTION
+
+C<use base qw(IMPL::DOM::Document)>
+
+Документ, основанный на шаблоне Template::Toolkit. Позволяет загрузить шаблон,
+и сформировать окончательный документ. Является наследником C<IMPL::DOM::Node>,
+т.о. может быть использован для реализации DOM модели.
+
+Внутри шаблона переменная C<document> ссылается на объект документа. По этой
+причине образуется циклическая ссылка между объектами шаблона и документом, что
+требует вызова метода C<Dispose> для освобождения документа.
+
+=head1 METHODS
+
+=over
+
+=item C<CTOR()>
+
+Создает новый экземпляр документа, свойство C<nodeName> устанавливается в 'C<document>'
+
+=item C<$doc->LoadFile($fileName,$encoding)>
+
+Загружает шаблон из файла C<$fileName>, используя кодировку C<$encoding>. Если
+кодировка не указана, использует utf-8.
+
+=item C<$doc->Render()>
+
+Возвращает данные построенные на основе загруженного шаблона.
+
+=item C<$doc->Dispose()>
+
+Освобождает ресурсы и помечает объект как освобожденный.
+
+=back
+
+=head1 DOM
+
+=begin code html
+
+[% table = document.Create('env','table') %]
+
+[% FOEACH item in document.result %]
+	[% table.rows.Add( item.get('name','value') ) %]
+[% END %]
+
+[% form = document.Create('login','form') %]
+
+
+[% form.template = 'LOGIN_FORM'%]
+
+[% FOREACH item IN document.childNodes %]
+	[%render(item)%]
+[% END %]
+	
+[% BLOCK LOGIN_FORM %]
+<form method="POST" action='/login.pl'>
+	user: [% render(this.item('name')) %] password: [% render(this.item('password')) %] <input type="submit"/>
+</form>
+[% END %]
+
+=end code html
+
+
+=cut
--- a/_test/Resources/simple.tt	Wed Mar 31 16:17:13 2010 +0400
+++ b/_test/Resources/simple.tt	Fri Apr 02 20:18:46 2010 +0400
@@ -1,2 +1,2 @@
-[% META Title = "Документ 1" %]
-Текст докуметна $document.Title
\ No newline at end of file
+[% META title = "Документ 1" %]
+Текст докуметна $document.title
\ No newline at end of file
--- a/_test/Test/Web/TDocument.pm	Wed Mar 31 16:17:13 2010 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-package Test::Web::TDocument;
-use strict;
-use warnings;
-use encoding 'cp1251';
-
-use base qw(IMPL::Test::Unit);
-use IMPL::Test qw(test failed);
-use IMPL::Web::TDocument;
-__PACKAGE__->PassThroughArgs;
-
-test Creation => sub {
-    my $document = new IMPL::Web::TDocument();
-    
-    failed "Failed to create document" unless $document;
-    
-    $document->Dispose();
-};
-
-test SimpleTemplate => sub {
-    my $document = new IMPL::Web::TDocument();
-    
-    failed "Failed to create document" unless $document;
-    
-    $document->loadFile('Resources/simple.tt','cp1251');
-    
-    my $out = $document->Render;
-    
-    open my $hFile,'<:encoding(cp1251)',"Resources/simple.txt" or die "Failed to open etalon file: $!";
-    local $/;
-    my $eta = <$hFile>;
-    
-    failed "Rendered data doesn't match the etalon data","Expected:\n$eta","Actual:\n$out" if $out ne $eta;
-    
-    $document->Dispose();
-};
-
-
-1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_test/Test/Web/TT.pm	Fri Apr 02 20:18:46 2010 +0400
@@ -0,0 +1,38 @@
+package Test::Web::TT;
+use strict;
+use warnings;
+use encoding 'cp1251';
+
+use base qw(IMPL::Test::Unit);
+use IMPL::Test qw(test failed);
+use IMPL::Web::TT::Document;
+__PACKAGE__->PassThroughArgs;
+
+test Creation => sub {
+    my $document = new IMPL::Web::TT::Document();
+    
+    failed "Failed to create document" unless $document;
+    
+    $document->Dispose();
+};
+
+test SimpleTemplate => sub {
+    my $document = new IMPL::Web::TT::Document();
+    
+    failed "Failed to create document" unless $document;
+    
+    $document->LoadFile('Resources/simple.tt','cp1251');
+    
+    my $out = $document->Render;
+    
+    open my $hFile,'<:encoding(cp1251)',"Resources/simple.txt" or die "Failed to open etalon file: $!";
+    local $/;
+    my $eta = <$hFile>;
+    
+    failed "Rendered data doesn't match the etalon data","Expected:\n$eta","Actual:\n$out" if $out ne $eta;
+    
+    $document->Dispose();
+};
+
+
+1;
--- a/_test/Web.t	Wed Mar 31 16:17:13 2010 +0400
+++ b/_test/Web.t	Fri Apr 02 20:18:46 2010 +0400
@@ -7,7 +7,7 @@
 use IMPL::Test::TAPListener;
 
 my $plan = new IMPL::Test::Plan qw(
-    Test::Web::TDocument
+    Test::Web::TT
     Test::Web::Application
 );