diff Lib/IMPL/Web/View/TTContext.pm @ 359:833e663796c4

TTView: added view variable to pass rendering context between controls TTView: display function renamed to display_for WebResource: resources now marked with roles for searching a desired resource by a role in the resource chain
author sergey
date Mon, 25 Nov 2013 02:19:31 +0400
parents 97131d500f16
children cbf4febf0930
line wrap: on
line diff
--- a/Lib/IMPL/Web/View/TTContext.pm	Mon Nov 18 01:25:35 2013 +0400
+++ b/Lib/IMPL/Web/View/TTContext.pm	Mon Nov 25 02:19:31 2013 +0400
@@ -23,6 +23,9 @@
 
 BEGIN {
 	no strict 'refs';
+	# modules is a global (for the whole document) templates cache
+	# tt_cache is a local (for the current context only) templtes cache
+	# view is a special variable, which will be cloned and passed to the nested context
 	foreach my $prop (qw(
 	   root
 	   base
@@ -35,6 +38,7 @@
 	   modules
 	   aliases
 	   id
+	   view
 	)) {
 		my $t = $prop;
 		
@@ -75,7 +79,7 @@
 }
 
 sub find_template {
-	my ($this,$name) = @_;
+	my ($this,$name, $nothrow) = @_;
 	
 	my $cache = $this->tt_cache;
 	
@@ -129,10 +133,12 @@
 		}
 	}
 	
-	$this->throw(Template::Constants::ERROR_FILE, "$name: not found");
+	$this->throw(Template::Constants::ERROR_FILE, "$name: not found")
+		unless $nothrow;
+	return;
 }
 
-sub display {
+sub display_for {
 	my $this = shift;
 	my $model = shift;
 	my ($template, $args);
@@ -203,23 +209,41 @@
     );
 }
 
+# обеспечивает необходимый уровень изоляции между контекстами
+# $code - код, который нужно выполнить в новом контексте
+# $env - хеш с переменными, которые будут переданы в новый контекст
+# в процессе будет создан клон корневого контекста, со всеми его свойствами
+# затем новый контекст будет локализован и в него будут добавлены новые переменные из $env
+# созданный контекст будет передан параметром в $code
 sub invoke_environment {
 	my ($this,$code,$env) = @_;
 	
 	$env ||= {};
 	
 	my $ctx = ($this->root || $this)->clone();
-
+	
+	my @includes = @{$this->includes || []};
+	
+	if ($this->base) {
+		unshift @includes, $this->base;
+	}
+	
+	my $view = $this->view;
+	$view = ref $view eq 'HASH' ? { %{$view} } : {};
+	
+	hashApply($view, delete $env->{view});
+	
 	my $out = eval {
 		$ctx->localise(
             hashApply(
 	            {
+	            	includes => \@includes,
 	            	aliases => $this->aliases || {},
 					root => $this->root || $ctx,
 					modules => $this->modules || {},
 					cache => TypeKeyedCollection->new(),
-		            display => sub {
-		                $ctx->display(@_);
+		            display_for => sub {
+		                $ctx->display_for(@_);
 		            },
 		            render => sub {
 		            	$ctx->render(@_);
@@ -227,7 +251,8 @@
 		            display_model => sub {
 		            	$ctx->display_model(@_);
 		            },
-		            tt_cache => {}
+		            tt_cache => {},
+		            view => $view
 				},
                 $env
             )
@@ -244,6 +269,16 @@
     return $out;
 }
 
+# использует указанный шаблон для создания фрагмента документа
+# шаблон может быть как именем, так и хешем, содержащим информацию
+# о шаблоне.
+# отдельно следует отметить, что данный метод создает новый контекст
+# для выполнения шаблона в котором задает переменные base, parent, id
+# а также создает переменные для строковых констант из labels
+# хеш с переменными $args будет передан самому шаблону в момент выполнения
+# если у шаблона указан класс элемента управления, то при выполнении шаблона
+# будет создан экземпляр этого класса и процесс выполнения шаблона будет
+# делегирован методу Render этого экземпляра. 
 sub render {
 	my ($this,$template,$args) = @_;
 	
@@ -276,7 +311,7 @@
        	    }
        	    
        	    if (my $class = $info->{class}) {
-       	    	$class->new($ctx,$info->{template},$args)->Render($args);
+       	    	$class->new($ctx,$info->{template},$args)->Render({});
        	    } else {
             	return $ctx->include($info->{template},$args);
        	    }
@@ -313,7 +348,7 @@
 }
 
 sub find_template_for {
-	my ($this,$model) = @_;
+	my ($this,$model, $nothrow) = @_;
 	
 	my $type = typeof($model);
 	
@@ -331,8 +366,9 @@
             my $sclass = shift @isa;
             
             (my $name = $sclass) =~ s/:+/_/g;
+            my ($shortName) = ($sclass =~ m/(\w+)$/);
 
-            $template = $this->find_template("templates/$name");
+            $template = $this->find_template("templates/$name",1) || $this->find_template("templates/$shortName",1);
             
             if ($template) {
             	$this->cache->Set($sclass,$template);
@@ -343,7 +379,9 @@
         }
 		
 	}
-	
+	$this->throw(Template::Constants::ERROR_FILE, "can't find a template for the model " . typeof($model))
+		unless $nothrow;
+
 	return;
 }