181
|
1 package IMPL::Web::View::TTLoader;
|
|
2 use strict;
|
|
3
|
|
4 use Template::Constants qw(:status);
|
|
5
|
336
|
6 use File::Spec();
|
265
|
7 use IMPL::Const qw(:prop);
|
345
|
8 use Scalar::Util qw(weaken);
|
|
9
|
265
|
10 use IMPL::declare {
|
|
11 require => {
|
|
12 Provider => 'Template::Provider',
|
343
|
13 Context => 'IMPL::Web::View::TTContext',
|
309
|
14 TTRegistry => 'IMPL::Web::View::TTRegistry',
|
308
|
15 TTFactory => 'IMPL::Web::View::TTFactory',
|
309
|
16 TTDocument => '-IMPL::Web::View::TTDocument',
|
265
|
17 Exception => 'IMPL::Exception',
|
|
18 ArgumentException => '-IMPL::InvalidArgumentException',
|
|
19 KeyNotFoundException => '-IMPL::KeyNotFoundException'
|
|
20 },
|
|
21 base => [
|
|
22 'IMPL::Object' => undef,
|
|
23 'IMPL::Object::Serializable' => undef
|
|
24 ],
|
|
25 props => [
|
|
26 provider => PROP_RO,
|
|
27 context => PROP_RO,
|
345
|
28 registry => PROP_RO,
|
265
|
29 _globals => PROP_RW
|
|
30 ]
|
|
31 };
|
181
|
32
|
196
|
33 sub save {
|
|
34 my ($this,$context) = @_;
|
|
35
|
|
36 $context->AddVar($_, $this->$_()) for qw(options provider context ext layoutBase);
|
|
37 }
|
|
38
|
|
39 sub restore {
|
|
40 my ($class,$data,$surrogate) = @_;
|
|
41
|
|
42 my %params = @$data;
|
|
43
|
|
44 my $refOpts = delete $params{options};
|
|
45
|
|
46 if ($surrogate){
|
|
47 $surrogate->callCTOR($refOpts,%params);
|
|
48 } else {
|
|
49 $surrogate = $class->new($refOpts,%params);
|
|
50 }
|
206
|
51 return $surrogate;
|
196
|
52 }
|
|
53
|
181
|
54 sub CTOR {
|
194
|
55 my ($this,$refOpts,%args) = @_;
|
|
56
|
|
57 $refOpts ||= {};
|
|
58
|
345
|
59 # to aviod cyclic references we need to do a copy of $refOpts
|
|
60 $refOpts->{LOAD_TEMPLATES} = Provider->new( { %$refOpts } );
|
|
61
|
|
62 my $ctx = Context->new( { %$refOpts } );
|
|
63 $this->context($ctx);
|
|
64
|
194
|
65 $this->_globals(ref $args{globals} eq 'HASH' ? $args{globals} : {});
|
|
66
|
345
|
67 $ctx->tt_ext($args{ext} || '.tt');
|
|
68
|
|
69 $this->registry(TTRegitry->new($ctx));
|
194
|
70
|
345
|
71 weaken($ctx);
|
|
72 weaken($this);
|
|
73 $ctx->stash->update({
|
|
74 require => sub {
|
|
75 my ($modname) = @_;
|
|
76
|
|
77 my @inc;
|
|
78 push @inc, $ctx->base if $ctx->base;
|
|
79
|
|
80 my $ti = $ctx->find_template($name,@inc);
|
|
81
|
|
82 require $this->registry->Require($ti);
|
|
83 },
|
|
84 inclue => sub {
|
|
85 my ($name) = @_;
|
|
86
|
|
87 my @inc;
|
|
88 push @inc, $ctx->base if $ctx->base;
|
|
89
|
|
90 my $ti = $ctx->find_template($name,@inc);
|
|
91
|
|
92 return $ctx->include($ti->{template}, {base => $ti->{base}} );
|
|
93 }
|
|
94 });
|
194
|
95
|
345
|
96
|
181
|
97 }
|
|
98
|
|
99 sub document {
|
194
|
100 my ($this,$name,$vars) = @_;
|
|
101
|
309
|
102 $vars ||= {};
|
308
|
103
|
345
|
104 my $factory = $this->registry->Require($name);
|
194
|
105
|
345
|
106 return $factory->new(hashMerge($vars, $this->_globals));
|
181
|
107 }
|
|
108
|
|
109 1;
|
|
110
|
|
111 __END__
|
|
112
|
|
113 =pod
|
|
114
|
|
115 =head1 NAME
|
|
116
|
|
117 C<IMPL::Web::View::TTLoader> - предоставляет глобальный контекст для загрузки шаблонов
|
|
118
|
|
119 =head1 SYNOPSIS
|
|
120
|
|
121 =begin code
|
|
122
|
|
123 use IMPL::Web::View::TTLoader();
|
|
124
|
|
125 my $loader = new IMPL::Web::View::TTLoader(
|
194
|
126 {
|
|
127 INCLUDE_PATH => [
|
|
128 '/my/app/tt',
|
|
129 '/my/app/tt/lib'
|
|
130 ]
|
|
131 },
|
|
132 ext => '.tt',
|
345
|
133 globals => {
|
|
134 images => '//cdn.mysite.net/static/images'
|
|
135 }
|
194
|
136
|
181
|
137 );
|
|
138
|
|
139 my $doc = $loader->document('index');
|
|
140
|
|
141 my $html = $doc->Render();
|
|
142
|
|
143 =end code
|
|
144
|
|
145 =head1 DESCRIPTION
|
|
146
|
265
|
147 Провайдер для загрузки шаблонов и документов. Имеет собственное пространство
|
|
148 имен, контекст выполнения шаблонов. Контект загрузчика инициализируется
|
|
149 шаблоном, в котором определяются глобальные переменные, которые будут доступны
|
|
150 в документах, однако их изменения будут локализованы.
|
|
151
|
|
152 Инициализация контекста провайдера происходит при первой загрузке любого
|
|
153 документа.
|
|
154
|
182
|
155 =head1 MEMBERS
|
|
156
|
265
|
157 =head2 C<CTOR($options,%args)>
|
|
158
|
|
159 =over
|
|
160
|
|
161 =item * C<$options>
|
|
162
|
|
163 Параметры контекста загрузчика, контексты документов и элементов управления
|
|
164 также унаследуют эти свойства. Напрямую передаются в конструктор
|
|
165 C<Template::Context>.
|
|
166
|
|
167 =item * C<%args>
|
|
168
|
|
169 Именованные параметы загрузчика.
|
|
170
|
|
171 =over
|
|
172
|
|
173 =item * C<ext>
|
|
174
|
|
175 Расширение, которое будет добавляться к именам шаблонов и документов (если оно
|
|
176 не будет указано явно).
|
|
177
|
|
178 =item * C<initializer>
|
|
179
|
|
180 Имя шаблона, который будет использован для инициализации контекста.
|
|
181
|
|
182 =item * C<globals>
|
|
183
|
|
184 Глобальные переменнын, которые будут переданы в контекст.
|
|
185
|
|
186 =item * C<layoutBase>
|
|
187
|
|
188 Путь к шаблонам для оформления документов. Каждый документ может задавать свой
|
|
189 C<layout> указанный в его C<META> блоке или конструкторе.
|
|
190 См. C<IMPL::View::TTDocument>.
|
|
191
|
|
192 =back
|
|
193
|
|
194 =back
|
|
195
|
182
|
196 =head2 C<document($docName)>
|
|
197
|
265
|
198 Загружает документ с именем C<$docName>. При необходимости к нему будет
|
|
199 добавлено расширение, указанное в свойстве C<ext>. Это единственно полезный
|
|
200 метод провайдера.
|
|
201
|
181
|
202 =cut
|
|
203
|