# HG changeset patch # User sergey # Date 1361289507 -14400 # Node ID 3a9cfea098ddaf50eb1c9a03cb97a85e573ef897 # Parent 2d253e6e4a88c99941daac12263e678587253d6e *TTView refactoring: removed RequireControl method, etc. diff -r 2d253e6e4a88 -r 3a9cfea098dd Lib/IMPL/Web/View/TTDocument.pm --- a/Lib/IMPL/Web/View/TTDocument.pm Tue Feb 19 03:05:10 2013 +0400 +++ b/Lib/IMPL/Web/View/TTDocument.pm Tue Feb 19 19:58:27 2013 +0400 @@ -3,7 +3,9 @@ use Scalar::Util qw(weaken); use IMPL::Const qw(:prop); -use IMPL::lang qw(:hash); +use IMPL::lang qw(:hash is); +use Carp qw(carp); +use mro; use IMPL::declare { require => { @@ -14,27 +16,17 @@ base => [ 'IMPL::Web::View::TTControl' => sub { my ($template,$ctx) = @_; - 'document', - $template, # template - $ctx || Template::Context->new() # context + $ctx ||= Template::Context->new(); + return 'document', $template, $ctx; # context } ], props => [ layout => PROP_RW, loader => PROP_RW, controls => PROP_RO, - creationArgs => PROP_RO, - - # store the stash separately to make require() method to work correctly - # even when a stash of the context is modified during the processing - stash => PROP_RO ] }; -BEGIN { - -} - sub CTOR { my ($this,$template,$ctx,$loader,$vars) = @_; @@ -43,49 +35,34 @@ $this->layout( $template->layout ) unless $this->layout; - $this->stash($this->context->stash); - $this->creationArgs($vars); - - my $self = $this; - weaken($self); + $this->context->stash->update($vars) + if ref $vars eq 'HASH'; - $this->templateVars(require => sub { - my $doc = $self; - die new IMPL::Exception("A document is destroyed or invalid") unless $doc; - $doc->RequireControl(@_); - }); - - $this->templateVars(document => sub { $self } ); - $this->InitInstance($vars); + $this->InitInstance(); } sub templateVars { my $this = shift; my $name = shift; - if (@_) { - return $this->stash->set($name, shift); + return $this->context->stash->set($name, shift); } else { - return $this->stash->get($name); + return $this->context->stash->get($name); } } sub RequireControl { - my ($this, $control) = @_; + my ($this, $control, $ctx) = @_; + + $ctx ||= $this->context; if (my $factory = $this->controls->{$control}) { return $factory; } else { - my $path = $control; if ( my $template = $this->loader->template($path) ) { - - # factory will create a clone of the stash - # $opts->{STASH} = $this->stash->clone(); - - my $ctx = Template::Context->new({%{$this->context}, STASH => $this->stash });#new Template::Context($opts); - + $factory = new IMPL::Web::View::TTFactory( $template->class || TTControl, $template, @@ -109,54 +86,89 @@ sub Render { my ($this,$args) = @_; - + $args ||= {}; + + $this->context->localise(); - my $newArgs = hashMerge($this->creationArgs, $args); + my $documentContext; + my %controls; + my $require; + $require = sub { + my $control = shift; + if (my $factory = $controls{$control}) { + return $factory; + } else { + my $path = $control; + + if ( my $template = $this->loader->template($path) ) { + + $factory = new IMPL::Web::View::TTFactory( + $template->class || TTControl, + $template, + $documentContext, + join( '/', splice( @{[split(/\//,$path)]}, 0, -1 ) ), + $require + ); + + if ($template->class) { + Loader->safe->Require($template->class); + } + + $controls{$control} = $factory; + + return $factory; - if ($this->layout) { - my $text = eval { - #$this->context->localise(); + } else { + die new IMPL::KeyNotFoundException($control); + } + } + }; + + $this->context->stash->set(require => $require); + $this->context->stash->set(document => $this); + $documentContext = Template::Context->new( { %{$this->context} } ); + + my $text = eval { + + if ($this->layout) { my $tlayout = $this->loader->layout($this->layout); if(my $init = $tlayout->blocks->{INIT}) { $this->context->process( $init, hashMerge( - $newArgs, + $args, { - template => $this->template + template => $this->template } ) ); } + my $content = $this->next::method($args); return $this->context->include( $tlayout, { - %{$newArgs}, - content => $this->RenderContent($newArgs), + %{$args}, + content => $content, this => $this, template => $this->template } ); - }; - my $e = $@; - - #$this->context->delocalise(); - - if ($e) { - die $e; - } else { - return $text; - } - + } else { + return $this->next::method($args); + } + }; + + $this->context->delocalise(); + + my $e = $@; + if ($e) { + die $e; } else { - return $this->RenderContent($newArgs); + return $text; } -} - -sub RenderContent { - my $this = shift; - return $this->SUPER::Render(@_); + + } 1; diff -r 2d253e6e4a88 -r 3a9cfea098dd Lib/IMPL/Web/View/TTFactory.pm --- a/Lib/IMPL/Web/View/TTFactory.pm Tue Feb 19 03:05:10 2013 +0400 +++ b/Lib/IMPL/Web/View/TTFactory.pm Tue Feb 19 19:58:27 2013 +0400 @@ -17,12 +17,13 @@ template => PROP_RW, context => PROP_RW, instances => PROP_RW, - base => PROP_RW + base => PROP_RW, + require => PROP_RO ] }; sub CTOR { - my ($this,$factory,$template,$context,$base) = @_; + my ($this,$factory,$template,$context,$base,$require) = @_; die IMPL::ArgumentException("A template is required") unless $template; @@ -32,6 +33,7 @@ $this->context($context); $this->base($base); $this->instances(0); + $this->require($require); } our %CTOR = ( @@ -52,14 +54,14 @@ $this->context->delocalise(); my $stash = $ctx->stash; - weaken($stash); - + my $require = $this->require; + $stash->update({ require => sub { my ($module) = @_; $module =~ s/^\.\//$base\//; - return $stash->get('document')->RequireControl($module); + return $require->($module); } }); diff -r 2d253e6e4a88 -r 3a9cfea098dd _test/Resources/TTView/complex.tt --- a/_test/Resources/TTView/complex.tt Tue Feb 19 03:05:10 2013 +0400 +++ b/_test/Resources/TTView/complex.tt Tue Feb 19 19:58:27 2013 +0400 @@ -5,7 +5,6 @@ this.childNodes = [ TPanel.new('information', data = data ) ]; %] - [% FOREACH node IN this.childNodes() %]
[% node.Render() %]
[% END %] diff -r 2d253e6e4a88 -r 3a9cfea098dd _test/Test/Web/View.pm --- a/_test/Test/Web/View.pm Tue Feb 19 03:05:10 2013 +0400 +++ b/_test/Test/Web/View.pm Tue Feb 19 19:58:27 2013 +0400 @@ -9,7 +9,7 @@ use File::Slurp; use Scalar::Util qw(weaken); - +use Data::Dumper; use IMPL::lang; use IMPL::Test qw(assert assertarray test GetCallerSourceLine); use IMPL::Web::View::TTLoader(); @@ -112,6 +112,10 @@ assert($doc->templateVars('user') eq 'test_user'); # global data assert($doc->templateVars('templateVar') eq ''); # defined in CTOR block, should be local assert($doc->templateVars('dynamic') eq 'this is a dynamic value'); + assert($doc->context->stash->get('user') eq 'test_user' ); # runtime context should be derived from documentContext + $doc->context->stash->set('user', 'nobody'); + assert($doc->templateVars('user') eq 'test_user'); # isolated + $doc->context->stash->set('user', 'test_user'); my $text = $doc->Render(); my $expected = read_file($this->GetResourceFile('Resources','TTView.Output','simple.txt'), binmode => ':utf8'); @@ -160,6 +164,12 @@ assert($text eq $expected, '$ctl->Render(): Bad output', "Got: $text", "Expected: $expected"); + my $doc2 = $loader->document('simple'); + + assert( $doc2->documentContext->stash->get( ['require',['My/Org/Panel'] ] ) ); + print Dumper($doc2->context->stash); + assert( $doc2->context->stash->get( ['require',['My/Org/Panel'] ] ) ); + }; @@ -197,7 +207,9 @@ assert(ref $loader->context->stash->get([ 'dojo', 0, 'require', 0]) eq 'ARRAY'); assertarray($loader->context->stash->get([ 'dojo', 0, 'require', 0]),[]); - assert($loader->context->stash != $doc->stash); + assert($loader->context->stash != $doc->context->stash); + assert($loader->context->stash != $doc->documentContext->stash); + assert($doc->context->stash != $doc->documentContext->stash); assert(defined $doc);