Mercurial > pub > Impl
comparison Lib/IMPL/Web/TT/Document.pm @ 77:9d24db321029
Refactoring Web::TT
docs
author | wizard |
---|---|
date | Fri, 02 Apr 2010 20:18:46 +0400 |
parents | Lib/IMPL/Web/TDocument.pm@b1652a158b2b |
children | 964587c5183c |
comparison
equal
deleted
inserted
replaced
76:b1652a158b2b | 77:9d24db321029 |
---|---|
1 package IMPL::Web::TT::Document; | |
2 use strict; | |
3 use warnings; | |
4 | |
5 use base qw(IMPL::DOM::Document IMPL::Object::Disposable); | |
6 use Template::Context; | |
7 use Template::Provider; | |
8 use IMPL::Class::Property; | |
9 use File::Spec; | |
10 use Scalar::Util qw(blessed); | |
11 | |
12 BEGIN { | |
13 private property _provider => prop_all; | |
14 private property _context => prop_all; | |
15 public property template => prop_get | owner_set; | |
16 public property presenter => prop_all, { validate => \&_validatePresenter }; | |
17 } | |
18 | |
19 our %CTOR = ( | |
20 'IMPL::DOM::Document' => sub { nodeName => 'document' } | |
21 ); | |
22 | |
23 sub provider { | |
24 my ($this,%args) = @_; | |
25 | |
26 if (my $provider = $this->_provider) { | |
27 return $provider; | |
28 } else { | |
29 return $this->_provider(new Template::Provider( | |
30 \%args | |
31 )); | |
32 } | |
33 } | |
34 | |
35 sub context { | |
36 my ($this) = @_; | |
37 | |
38 if (my $ctx = $this->_context) { | |
39 return $ctx; | |
40 } else { | |
41 return $this->_context ( | |
42 new Template::Context( | |
43 VARIABLES => { | |
44 document => $this, | |
45 this => $this, | |
46 render => sub { | |
47 $this->_process(@_); | |
48 } | |
49 }, | |
50 TRIM => 1, | |
51 RECURSION => 1, | |
52 LOAD_TEMPLATES => [$this->provider] | |
53 ) | |
54 ) | |
55 } | |
56 } | |
57 | |
58 sub _validatePresenter { | |
59 my ($this,$value) = @_; | |
60 | |
61 die new IMPL::InvalidArgumentException("A view object is required") unless blessed($value) and $value->isa('Template::View'); | |
62 } | |
63 | |
64 sub LoadFile { | |
65 my ($this,$filePath,$encoding) = @_; | |
66 | |
67 die new IMPL::InvalidArgumentException("A filePath parameter is required") unless $filePath; | |
68 | |
69 $encoding ||= 'utf8'; | |
70 | |
71 $this->_context(undef); | |
72 $this->_provider(undef); | |
73 | |
74 my ($vol,$dir,$fileName) = File::Spec->splitpath($filePath); | |
75 | |
76 my $inc = File::Spec->catpath($vol,$dir,''); | |
77 | |
78 $this->provider( | |
79 ENCODING => $encoding, | |
80 INTERPOLATE => 1, | |
81 PRE_CHOMP => 1, | |
82 POST_CHOMP => 1, | |
83 INCLUDE_PATH => $inc | |
84 ); | |
85 | |
86 $this->template($this->context->template($fileName)); | |
87 } | |
88 | |
89 sub title { | |
90 $_[0]->template->title; | |
91 } | |
92 | |
93 sub Render { | |
94 my ($this) = @_; | |
95 | |
96 return $this->template->process($this->context); | |
97 } | |
98 | |
99 # Формирует представление для произвольных объектов | |
100 sub _process { | |
101 my ($this,@items) = @_; | |
102 | |
103 my @result; | |
104 | |
105 foreach my $item (@items) { | |
106 if (blessed($item) and $item->isa('IMPL::Web::TT::Control')) { | |
107 push @result, $item->Render(); | |
108 } elsif(blessed($item)) { | |
109 if ($this->presenter) { | |
110 push @result, $this->presenter->print($item); | |
111 } else { | |
112 push @result, $this->toString; | |
113 } | |
114 } else { | |
115 push @result, $item; | |
116 } | |
117 } | |
118 | |
119 return join '',@items; | |
120 } | |
121 | |
122 sub Dispose { | |
123 my ($this) = @_; | |
124 | |
125 $this->template(undef); | |
126 $this->_context(undef); | |
127 $this->_provider(undef); | |
128 | |
129 $this->SUPER::Dispose(); | |
130 } | |
131 | |
132 1; | |
133 __END__ | |
134 =pod | |
135 | |
136 =head1 NAME | |
137 | |
138 C<IMPL::Web::TT::Document> - Документ, позволяющий строить представление по шаблону | |
139 | |
140 =head1 SYNOPSIS | |
141 | |
142 =begin code | |
143 | |
144 // create new document | |
145 my $doc = new IMPL::Web::TT::Document; | |
146 | |
147 // load template | |
148 $doc->loadFile('Templates/index.tt'); | |
149 | |
150 // render file | |
151 print $doc->Render(); | |
152 | |
153 =end code | |
154 | |
155 =head1 DESCRIPTION | |
156 | |
157 C<use base qw(IMPL::DOM::Document)> | |
158 | |
159 Документ, основанный на шаблоне Template::Toolkit. Позволяет загрузить шаблон, | |
160 и сформировать окончательный документ. Является наследником C<IMPL::DOM::Node>, | |
161 т.о. может быть использован для реализации DOM модели. | |
162 | |
163 Внутри шаблона переменная C<document> ссылается на объект документа. По этой | |
164 причине образуется циклическая ссылка между объектами шаблона и документом, что | |
165 требует вызова метода C<Dispose> для освобождения документа. | |
166 | |
167 =head1 METHODS | |
168 | |
169 =over | |
170 | |
171 =item C<CTOR()> | |
172 | |
173 Создает новый экземпляр документа, свойство C<nodeName> устанавливается в 'C<document>' | |
174 | |
175 =item C<$doc->LoadFile($fileName,$encoding)> | |
176 | |
177 Загружает шаблон из файла C<$fileName>, используя кодировку C<$encoding>. Если | |
178 кодировка не указана, использует utf-8. | |
179 | |
180 =item C<$doc->Render()> | |
181 | |
182 Возвращает данные построенные на основе загруженного шаблона. | |
183 | |
184 =item C<$doc->Dispose()> | |
185 | |
186 Освобождает ресурсы и помечает объект как освобожденный. | |
187 | |
188 =back | |
189 | |
190 =head1 DOM | |
191 | |
192 =begin code html | |
193 | |
194 [% table = document.Create('env','table') %] | |
195 | |
196 [% FOEACH item in document.result %] | |
197 [% table.rows.Add( item.get('name','value') ) %] | |
198 [% END %] | |
199 | |
200 [% form = document.Create('login','form') %] | |
201 | |
202 | |
203 [% form.template = 'LOGIN_FORM'%] | |
204 | |
205 [% FOREACH item IN document.childNodes %] | |
206 [%render(item)%] | |
207 [% END %] | |
208 | |
209 [% BLOCK LOGIN_FORM %] | |
210 <form method="POST" action='/login.pl'> | |
211 user: [% render(this.item('name')) %] password: [% render(this.item('password')) %] <input type="submit"/> | |
212 </form> | |
213 [% END %] | |
214 | |
215 =end code html | |
216 | |
217 | |
218 =cut |