changeset 288:3a9cfea098dd

*TTView refactoring: removed RequireControl method, etc.
author sergey
date Tue, 19 Feb 2013 19:58:27 +0400
parents 2d253e6e4a88
children 85572f512abc
files Lib/IMPL/Web/View/TTDocument.pm Lib/IMPL/Web/View/TTFactory.pm _test/Resources/TTView/complex.tt _test/Test/Web/View.pm
diffstat 4 files changed, 96 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- 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;
--- 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);
         }        
     });
     
--- 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() %]
 	<div>[% node.Render() %]</div>
 [% END %]
--- 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);