Mercurial > pub > Impl
annotate Lib/IMPL/Web/View/TTContext.pm @ 362:715b9959b207
WebView: initial work on metadata providers
author | cin |
---|---|
date | Thu, 28 Nov 2013 20:00:20 +0400 |
parents | 833e663796c4 |
children | cbf4febf0930 |
rev | line source |
---|---|
343 | 1 package IMPL::Web::View::TTContext; |
2 use strict; | |
3 use Template::Base; | |
348 | 4 use Carp qw(carp); |
349 | 5 use File::Spec(); |
6 use IMPL::Resources::Format qw(FormatMessage); | |
7 use IMPL::Resources::Strings(); | |
343 | 8 |
348 | 9 use IMPL::Exception(); |
349 | 10 use IMPL::lang qw(is typeof hashApply hashMerge); |
343 | 11 use IMPL::declare { |
348 | 12 require => { |
13 Document => '-Template::Document', | |
14 TypeKeyedCollection => 'IMPL::TypeKeyedCollection', | |
349 | 15 ArgException => '-IMPL::InvalidArgumentException', |
352 | 16 Resources => 'IMPL::Resources', |
17 Loader => 'IMPL::Code::Loader' | |
348 | 18 }, |
19 base => [ | |
343 | 20 'Template::Context' => '@_' |
348 | 21 ] |
343 | 22 }; |
23 | |
347 | 24 BEGIN { |
348 | 25 no strict 'refs'; |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
26 # modules is a global (for the whole document) templates cache |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
27 # tt_cache is a local (for the current context only) templtes cache |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
28 # view is a special variable, which will be cloned and passed to the nested context |
347 | 29 foreach my $prop (qw( |
348 | 30 root |
347 | 31 base |
32 tt_ext | |
348 | 33 tt_cache |
347 | 34 parent |
35 prefix | |
348 | 36 cache |
37 includes | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
38 modules |
352 | 39 aliases |
356 | 40 id |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
41 view |
347 | 42 )) { |
43 my $t = $prop; | |
44 | |
348 | 45 *{__PACKAGE__ . '::' . $prop} = sub { |
347 | 46 my $this = shift; |
47 return @_ ? $this->stash->set($t, @_) : $this->stash->get($t); | |
48 } | |
49 } | |
50 } | |
51 | |
343 | 52 sub clone { |
53 my $this = shift; | |
347 | 54 my $params = shift; |
343 | 55 |
56 $this->localise(); | |
57 | |
58 my $args = { %{$this} }; | |
59 | |
60 $this->delocalise(); | |
61 | |
348 | 62 my $class = ref($this); |
343 | 63 |
64 delete $args->{CONFIG}; | |
65 | |
347 | 66 my $clone = $class->new($args); |
67 | |
68 $clone->stash->update($params) if $params; | |
69 | |
70 return $clone; | |
345 | 71 } |
72 | |
356 | 73 sub get_next_id { |
74 my ($this) = @_; | |
75 | |
76 my $id = $this->stash->get('document.nextId') || 0; | |
77 $this->stash->set('document.nextId', $id + 1); | |
78 return "w-$id"; | |
79 } | |
80 | |
345 | 81 sub find_template { |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
82 my ($this,$name, $nothrow) = @_; |
348 | 83 |
84 my $cache = $this->tt_cache; | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
85 |
348 | 86 $this->tt_cache($cache = {}) unless $cache; |
345 | 87 |
348 | 88 if(my $tpl = $cache->{$name}) { |
89 return $tpl; | |
90 } | |
91 | |
92 my @inc = ($this->base, @{$this->includes || []}); | |
93 | |
345 | 94 my $ext = $this->tt_ext || ""; |
348 | 95 |
96 my $file; | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
97 |
345 | 98 foreach my $dir (@inc) { |
348 | 99 $file = $dir ? "$dir/$name" : $name; |
100 | |
101 my $base = join('/',splice([split(/\/+/,$file)],0,-1)); | |
102 | |
103 $file = $ext ? "$file.$ext" : $file; | |
104 | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
105 if (exists($this->modules->{$file})) { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
106 my $info = $this->modules->{$file}; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
107 return $cache->{$name} = $info |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
108 if $info; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
109 } else { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
110 if( my $tt = eval { $this->template($file) } ) { |
352 | 111 my $class; |
112 if ($class = $tt->class) { | |
113 $class = $this->aliases->{$class} || $class; | |
114 Loader->safe->Require($class); | |
115 } | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
116 my $info = { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
117 base => $base, |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
118 labels => $this->load_labels($file), |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
119 template => $tt, |
352 | 120 initialized => 0, |
121 class => $class | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
122 }; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
123 $this->modules->{$file} = $info; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
124 return $cache->{$name} = $info; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
125 } else { |
353 | 126 my $err = $@; |
127 | |
128 for(my $t = $err; is($t,'Template::Exception'); $t = $t->info ) { | |
129 die $err unless $t->type eq Template::Constants::ERROR_FILE; | |
130 } | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
131 $this->modules->{$file} = undef; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
132 } |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
133 } |
345 | 134 } |
135 | |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
136 $this->throw(Template::Constants::ERROR_FILE, "$name: not found") |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
137 unless $nothrow; |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
138 return; |
345 | 139 } |
140 | |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
141 sub display_for { |
347 | 142 my $this = shift; |
143 my $model = shift; | |
348 | 144 my ($template, $args); |
347 | 145 |
146 if (ref $_[0] eq 'HASH') { | |
147 $args = shift; | |
148 } else { | |
149 $template = shift; | |
150 $args = shift; | |
151 } | |
152 | |
348 | 153 my $prefix = $this->prefix; |
154 | |
354 | 155 my $info; |
156 | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
157 if (not(($args and delete $args->{_no_resolve}) or ref $model)) { |
354 | 158 $info = $this->resolve_model($model,$args); |
348 | 159 } else { |
354 | 160 $info = { |
161 model => $model, | |
162 prefix => "" | |
163 }; | |
348 | 164 } |
165 | |
355
8dfb9df07d02
added support for the custom resolvers for the TTView
sergey
parents:
354
diff
changeset
|
166 $template ||= $info->{template}; |
354 | 167 $template = $template ? $this->find_template($template) : $this->find_template_for($info->{model}); |
348 | 168 |
169 return $this->render( | |
170 $template, | |
171 hashApply( | |
354 | 172 $info, |
348 | 173 $args |
174 ) | |
175 ); | |
176 } | |
177 | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
178 sub display_model { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
179 my $this = shift; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
180 my $model = shift; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
181 my ($template, $args); |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
182 |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
183 if (ref $_[0] eq 'HASH') { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
184 $args = shift; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
185 } else { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
186 $template = shift; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
187 $args = shift; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
188 } |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
189 |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
190 $args ||= {}; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
191 |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
192 my $prefix = delete $args->{prefix} || $this->prefix; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
193 |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
194 if (my $rel = delete $args->{rel}) { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
195 $prefix = $prefix ? "${prefix}.${rel}" : $rel; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
196 } |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
197 |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
198 $template = $template ? $this->find_template($template) : $this->find_template_for($model); |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
199 |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
200 return $this->render( |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
201 $template, |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
202 hashApply( |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
203 { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
204 prefix => $prefix, |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
205 model => $model, |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
206 }, |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
207 $args |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
208 ) |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
209 ); |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
210 } |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
211 |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
212 # обеспечивает необходимый уровень изоляции между контекстами |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
213 # $code - код, который нужно выполнить в новом контексте |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
214 # $env - хеш с переменными, которые будут переданы в новый контекст |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
215 # в процессе будет создан клон корневого контекста, со всеми его свойствами |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
216 # затем новый контекст будет локализован и в него будут добавлены новые переменные из $env |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
217 # созданный контекст будет передан параметром в $code |
348 | 218 sub invoke_environment { |
219 my ($this,$code,$env) = @_; | |
220 | |
221 $env ||= {}; | |
222 | |
354 | 223 my $ctx = ($this->root || $this)->clone(); |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
224 |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
225 my @includes = @{$this->includes || []}; |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
226 |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
227 if ($this->base) { |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
228 unshift @includes, $this->base; |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
229 } |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
230 |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
231 my $view = $this->view; |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
232 $view = ref $view eq 'HASH' ? { %{$view} } : {}; |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
233 |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
234 hashApply($view, delete $env->{view}); |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
235 |
348 | 236 my $out = eval { |
354 | 237 $ctx->localise( |
348 | 238 hashApply( |
239 { | |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
240 includes => \@includes, |
352 | 241 aliases => $this->aliases || {}, |
354 | 242 root => $this->root || $ctx, |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
243 modules => $this->modules || {}, |
348 | 244 cache => TypeKeyedCollection->new(), |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
245 display_for => sub { |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
246 $ctx->display_for(@_); |
348 | 247 }, |
248 render => sub { | |
354 | 249 $ctx->render(@_); |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
250 }, |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
251 display_model => sub { |
354 | 252 $ctx->display_model(@_); |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
253 }, |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
254 tt_cache => {}, |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
255 view => $view |
348 | 256 }, |
257 $env | |
258 ) | |
259 ); | |
260 | |
354 | 261 &$code($ctx); |
348 | 262 }; |
263 | |
264 my $e = $@; | |
354 | 265 $ctx->delocalise(); |
348 | 266 |
267 die $e if $e; | |
268 | |
269 return $out; | |
270 } | |
271 | |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
272 # использует указанный шаблон для создания фрагмента документа |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
273 # шаблон может быть как именем, так и хешем, содержащим информацию |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
274 # о шаблоне. |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
275 # отдельно следует отметить, что данный метод создает новый контекст |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
276 # для выполнения шаблона в котором задает переменные base, parent, id |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
277 # а также создает переменные для строковых констант из labels |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
278 # хеш с переменными $args будет передан самому шаблону в момент выполнения |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
279 # если у шаблона указан класс элемента управления, то при выполнении шаблона |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
280 # будет создан экземпляр этого класса и процесс выполнения шаблона будет |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
281 # делегирован методу Render этого экземпляра. |
348 | 282 sub render { |
283 my ($this,$template,$args) = @_; | |
284 | |
285 $args ||= {}; | |
286 | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
287 my $info = ref $template ? $template : $this->find_template($template); |
348 | 288 |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
289 if (ref($info) ne 'HASH') { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
290 carp "got an invalid template object: $info (" . ref($info) . ")"; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
291 $info = { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
292 template => $info, |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
293 base => $this->base, |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
294 initialized => 1 |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
295 }; |
348 | 296 } |
297 | |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
298 return $this->invoke_environment( |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
299 sub { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
300 my $ctx = shift; |
352 | 301 |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
302 unless($info->{initialized}) { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
303 if(my $init = $info->{template}->blocks->{INIT}) { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
304 $info->{initialized} = 1; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
305 eval { |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
306 $ctx->visit($info->{template}->blocks); |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
307 $ctx->include($init); |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
308 }; |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
309 $ctx->leave(); |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
310 } |
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
311 } |
352 | 312 |
313 if (my $class = $info->{class}) { | |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
314 $class->new($ctx,$info->{template},$args)->Render({}); |
352 | 315 } else { |
316 return $ctx->include($info->{template},$args); | |
317 } | |
348 | 318 }, |
349 | 319 hashMerge( |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
320 $info->{labels} || {}, |
349 | 321 { |
351
cfd7570c2af2
working on TTView: created TTView class for rendering models
cin
parents:
349
diff
changeset
|
322 base => $info->{base}, |
356 | 323 parent => $this, |
324 id => $this->get_next_id | |
349 | 325 } |
326 ) | |
348 | 327 ) |
328 } | |
329 | |
330 sub resolve_model { | |
354 | 331 my ($this,$prefix,$args) = @_; |
348 | 332 |
333 die ArgException->new(prefix => "the prefix must be specified") | |
334 unless defined $prefix; | |
335 | |
356 | 336 |
348 | 337 |
356 | 338 if (my $res = $this->stash->get(['resolve', [$this,$prefix,$args]] ) ) { |
355
8dfb9df07d02
added support for the custom resolvers for the TTView
sergey
parents:
354
diff
changeset
|
339 return $res; |
354 | 340 } |
341 | |
348 | 342 my @comp = map { $_, 0 } grep length($_), split(/\.|\[(\d+)\]/, $prefix); |
347 | 343 |
354 | 344 return { |
345 model => $this->stash->get(['model',0,@comp]), | |
346 prefix => $this->prefix ? $this->prefix . ".$prefix" : $prefix | |
347 }; | |
348 | 348 } |
349 | |
350 sub find_template_for { | |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
351 my ($this,$model, $nothrow) = @_; |
347 | 352 |
348 | 353 my $type = typeof($model); |
347 | 354 |
348 | 355 return $this->find_template('templates/plain') unless $type; |
356 | |
357 if (my $template = $this->cache->Get($type)) { | |
358 return $template; | |
359 } else { | |
360 | |
361 no strict 'refs'; | |
362 | |
363 my @isa = $type; | |
364 | |
365 while (@isa) { | |
366 my $sclass = shift @isa; | |
367 | |
368 (my $name = $sclass) =~ s/:+/_/g; | |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
369 my ($shortName) = ($sclass =~ m/(\w+)$/); |
348 | 370 |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
371 $template = $this->find_template("templates/$name",1) || $this->find_template("templates/$shortName",1); |
348 | 372 |
373 if ($template) { | |
374 $this->cache->Set($sclass,$template); | |
375 return $template; | |
376 } | |
377 | |
378 push @isa, @{"${sclass}::ISA"}; | |
379 } | |
380 | |
381 } | |
359
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
382 $this->throw(Template::Constants::ERROR_FILE, "can't find a template for the model " . typeof($model)) |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
383 unless $nothrow; |
833e663796c4
TTView: added view variable to pass rendering context between controls
sergey
parents:
356
diff
changeset
|
384 |
348 | 385 return; |
347 | 386 } |
387 | |
349 | 388 sub get_real_file { |
389 my ($this,$fname) = @_; | |
390 | |
391 my @path = split(/\/+/,$fname); | |
392 | |
393 foreach my $provider (@{$this->load_templates || []}) { | |
394 foreach my $dir (@{$provider->paths || []}) { | |
395 my $realName = File::Spec->catfile($dir,@path); | |
396 return $realName if -f $realName; | |
397 } | |
398 } | |
399 } | |
400 | |
401 sub load_labels { | |
402 my ($this,$fname) = @_; | |
403 | |
404 $fname = $this->get_real_file($fname); | |
405 | |
406 my %vars; | |
407 | |
408 my $flabels = "$fname.labels"; | |
409 | |
410 if (-f $flabels) { | |
411 | |
412 my %labels; | |
413 $labels{default} = IMPL::Resources::Strings::ParseStringsMap($flabels); | |
414 | |
415 while(my($label,$text) = each %{$labels{default}}) { | |
416 $vars{$label} = sub { | |
417 my ($params) = @_; | |
418 my $locale = Resources->currentLocale; | |
419 | |
420 unless ($labels{$locale}) { | |
421 $labels{$locale} = -f "$fname.$locale" ? | |
422 IMPL::Resources::Strings::ParseStringsMap("$fname.$locale") : | |
423 {}; | |
424 } | |
425 | |
426 return FormatMessage(($labels{$locale}{$label} || $text),$params); | |
427 } | |
428 } | |
429 } | |
430 | |
431 return \%vars; | |
432 } | |
433 | |
345 | 434 1; |
435 | |
436 __END__ | |
437 | |
438 =pod | |
439 | |
440 =head1 NAME | |
441 | |
442 C<IMPL::Web::View::TTContext> - доработанная версия контекста | |
443 | |
444 =head1 DESCRIPTION | |
445 | |
446 Расширяет функции C<Template::Context> | |
447 | |
448 =begin plantuml | |
449 | |
450 @startuml | |
451 | |
348 | 452 object RootContext { |
345 | 453 document |
346 | 454 globals |
345 | 455 } |
456 | |
457 object DocumentContext { | |
346 | 458 base |
459 extends | |
460 } | |
461 | |
462 object ControlContext { | |
463 base | |
464 extends | |
345 | 465 } |
466 | |
348 | 467 RootContext o-- DocumentContext |
468 RootContext o-- ControlContext | |
345 | 469 |
346 | 470 Document -- DocumentContext |
471 Control - ControlContext | |
345 | 472 |
348 | 473 Loader . RootContext: <<creates>> |
346 | 474 Loader . Document: <<creates>> |
475 Loader -up- Registry | |
345 | 476 |
477 @enduml | |
478 | |
479 =end plantuml | |
480 | |
481 =head1 MEMBERS | |
482 | |
483 =head2 C<[get,set]base> | |
484 | |
485 Префикс пути для поиска шаблонов | |
486 | |
487 =head2 C<template($name)> | |
488 | |
489 Сначала пытается загрузить шаблон используя префикс C<base>, затем без префикса. | |
490 | |
491 =head2 C<clone()> | |
492 | |
493 Создает копию контекста, при этом C<stash> локализуется, таким образом | |
494 клонированный контекст имеет собственное пространство имен, вложенное в | |
495 пространство родительского контекста. | |
496 | |
497 =cut |