comparison 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
comparison
equal deleted inserted replaced
358:248f95c1762a 359:833e663796c4
21 ] 21 ]
22 }; 22 };
23 23
24 BEGIN { 24 BEGIN {
25 no strict 'refs'; 25 no strict 'refs';
26 # modules is a global (for the whole document) templates cache
27 # tt_cache is a local (for the current context only) templtes cache
28 # view is a special variable, which will be cloned and passed to the nested context
26 foreach my $prop (qw( 29 foreach my $prop (qw(
27 root 30 root
28 base 31 base
29 tt_ext 32 tt_ext
30 tt_cache 33 tt_cache
33 cache 36 cache
34 includes 37 includes
35 modules 38 modules
36 aliases 39 aliases
37 id 40 id
41 view
38 )) { 42 )) {
39 my $t = $prop; 43 my $t = $prop;
40 44
41 *{__PACKAGE__ . '::' . $prop} = sub { 45 *{__PACKAGE__ . '::' . $prop} = sub {
42 my $this = shift; 46 my $this = shift;
73 $this->stash->set('document.nextId', $id + 1); 77 $this->stash->set('document.nextId', $id + 1);
74 return "w-$id"; 78 return "w-$id";
75 } 79 }
76 80
77 sub find_template { 81 sub find_template {
78 my ($this,$name) = @_; 82 my ($this,$name, $nothrow) = @_;
79 83
80 my $cache = $this->tt_cache; 84 my $cache = $this->tt_cache;
81 85
82 $this->tt_cache($cache = {}) unless $cache; 86 $this->tt_cache($cache = {}) unless $cache;
83 87
127 $this->modules->{$file} = undef; 131 $this->modules->{$file} = undef;
128 } 132 }
129 } 133 }
130 } 134 }
131 135
132 $this->throw(Template::Constants::ERROR_FILE, "$name: not found"); 136 $this->throw(Template::Constants::ERROR_FILE, "$name: not found")
133 } 137 unless $nothrow;
134 138 return;
135 sub display { 139 }
140
141 sub display_for {
136 my $this = shift; 142 my $this = shift;
137 my $model = shift; 143 my $model = shift;
138 my ($template, $args); 144 my ($template, $args);
139 145
140 if (ref $_[0] eq 'HASH') { 146 if (ref $_[0] eq 'HASH') {
201 $args 207 $args
202 ) 208 )
203 ); 209 );
204 } 210 }
205 211
212 # обеспечивает необходимый уровень изоляции между контекстами
213 # $code - код, который нужно выполнить в новом контексте
214 # $env - хеш с переменными, которые будут переданы в новый контекст
215 # в процессе будет создан клон корневого контекста, со всеми его свойствами
216 # затем новый контекст будет локализован и в него будут добавлены новые переменные из $env
217 # созданный контекст будет передан параметром в $code
206 sub invoke_environment { 218 sub invoke_environment {
207 my ($this,$code,$env) = @_; 219 my ($this,$code,$env) = @_;
208 220
209 $env ||= {}; 221 $env ||= {};
210 222
211 my $ctx = ($this->root || $this)->clone(); 223 my $ctx = ($this->root || $this)->clone();
212 224
225 my @includes = @{$this->includes || []};
226
227 if ($this->base) {
228 unshift @includes, $this->base;
229 }
230
231 my $view = $this->view;
232 $view = ref $view eq 'HASH' ? { %{$view} } : {};
233
234 hashApply($view, delete $env->{view});
235
213 my $out = eval { 236 my $out = eval {
214 $ctx->localise( 237 $ctx->localise(
215 hashApply( 238 hashApply(
216 { 239 {
240 includes => \@includes,
217 aliases => $this->aliases || {}, 241 aliases => $this->aliases || {},
218 root => $this->root || $ctx, 242 root => $this->root || $ctx,
219 modules => $this->modules || {}, 243 modules => $this->modules || {},
220 cache => TypeKeyedCollection->new(), 244 cache => TypeKeyedCollection->new(),
221 display => sub { 245 display_for => sub {
222 $ctx->display(@_); 246 $ctx->display_for(@_);
223 }, 247 },
224 render => sub { 248 render => sub {
225 $ctx->render(@_); 249 $ctx->render(@_);
226 }, 250 },
227 display_model => sub { 251 display_model => sub {
228 $ctx->display_model(@_); 252 $ctx->display_model(@_);
229 }, 253 },
230 tt_cache => {} 254 tt_cache => {},
255 view => $view
231 }, 256 },
232 $env 257 $env
233 ) 258 )
234 ); 259 );
235 260
242 die $e if $e; 267 die $e if $e;
243 268
244 return $out; 269 return $out;
245 } 270 }
246 271
272 # использует указанный шаблон для создания фрагмента документа
273 # шаблон может быть как именем, так и хешем, содержащим информацию
274 # о шаблоне.
275 # отдельно следует отметить, что данный метод создает новый контекст
276 # для выполнения шаблона в котором задает переменные base, parent, id
277 # а также создает переменные для строковых констант из labels
278 # хеш с переменными $args будет передан самому шаблону в момент выполнения
279 # если у шаблона указан класс элемента управления, то при выполнении шаблона
280 # будет создан экземпляр этого класса и процесс выполнения шаблона будет
281 # делегирован методу Render этого экземпляра.
247 sub render { 282 sub render {
248 my ($this,$template,$args) = @_; 283 my ($this,$template,$args) = @_;
249 284
250 $args ||= {}; 285 $args ||= {};
251 286
274 $ctx->leave(); 309 $ctx->leave();
275 } 310 }
276 } 311 }
277 312
278 if (my $class = $info->{class}) { 313 if (my $class = $info->{class}) {
279 $class->new($ctx,$info->{template},$args)->Render($args); 314 $class->new($ctx,$info->{template},$args)->Render({});
280 } else { 315 } else {
281 return $ctx->include($info->{template},$args); 316 return $ctx->include($info->{template},$args);
282 } 317 }
283 }, 318 },
284 hashMerge( 319 hashMerge(
311 prefix => $this->prefix ? $this->prefix . ".$prefix" : $prefix 346 prefix => $this->prefix ? $this->prefix . ".$prefix" : $prefix
312 }; 347 };
313 } 348 }
314 349
315 sub find_template_for { 350 sub find_template_for {
316 my ($this,$model) = @_; 351 my ($this,$model, $nothrow) = @_;
317 352
318 my $type = typeof($model); 353 my $type = typeof($model);
319 354
320 return $this->find_template('templates/plain') unless $type; 355 return $this->find_template('templates/plain') unless $type;
321 356
329 364
330 while (@isa) { 365 while (@isa) {
331 my $sclass = shift @isa; 366 my $sclass = shift @isa;
332 367
333 (my $name = $sclass) =~ s/:+/_/g; 368 (my $name = $sclass) =~ s/:+/_/g;
334 369 my ($shortName) = ($sclass =~ m/(\w+)$/);
335 $template = $this->find_template("templates/$name"); 370
371 $template = $this->find_template("templates/$name",1) || $this->find_template("templates/$shortName",1);
336 372
337 if ($template) { 373 if ($template) {
338 $this->cache->Set($sclass,$template); 374 $this->cache->Set($sclass,$template);
339 return $template; 375 return $template;
340 } 376 }
341 377
342 push @isa, @{"${sclass}::ISA"}; 378 push @isa, @{"${sclass}::ISA"};
343 } 379 }
344 380
345 } 381 }
346 382 $this->throw(Template::Constants::ERROR_FILE, "can't find a template for the model " . typeof($model))
383 unless $nothrow;
384
347 return; 385 return;
348 } 386 }
349 387
350 sub get_real_file { 388 sub get_real_file {
351 my ($this,$fname) = @_; 389 my ($this,$fname) = @_;