comparison Lib/IMPL/Web/TT/Document.pm @ 194:4d0e1962161c

Replaced tabs with spaces IMPL::Web::View - fixed document model, new features (control classes, document constructor parameters)
author cin
date Tue, 10 Apr 2012 20:08:29 +0400
parents d1676be8afcc
children
comparison
equal deleted inserted replaced
193:8e8401c0aea4 194:4d0e1962161c
28 our %CTOR = ( 28 our %CTOR = (
29 'IMPL::DOM::Document' => sub { nodeName => 'document' } 29 'IMPL::DOM::Document' => sub { nodeName => 'document' }
30 ); 30 );
31 31
32 sub CTOR { 32 sub CTOR {
33 my ($this,%args) = @_; 33 my ($this,%args) = @_;
34 34
35 $this->_controlClassMap({}); 35 $this->_controlClassMap({});
36 $this->registerControlClass( Control => 'IMPL::Web::TT::Control' ); 36 $this->registerControlClass( Control => 'IMPL::Web::TT::Control' );
37 $this->appendChild( $this->Create(body => 'IMPL::Web::TT::Collection') ); 37 $this->appendChild( $this->Create(body => 'IMPL::Web::TT::Collection') );
38 $this->appendChild( $this->Create(head => 'IMPL::Web::TT::Collection') ); 38 $this->appendChild( $this->Create(head => 'IMPL::Web::TT::Collection') );
39 $this->cache($args{cache}) if $args{cache}; 39 $this->cache($args{cache}) if $args{cache};
40 $this->preprocess($args{preprocess}) if $args{preprocess}; 40 $this->preprocess($args{preprocess}) if $args{preprocess};
41 } 41 }
42 42
43 sub CreateControl { 43 sub CreateControl {
44 my ($this,$name,$class,$args) = @_; 44 my ($this,$name,$class,$args) = @_;
45 45
46 $args = {} unless ref $args eq 'HASH'; 46 $args = {} unless ref $args eq 'HASH';
47 47
48 if (my $info = $this->_controlClassMap->{$class}) { 48 if (my $info = $this->_controlClassMap->{$class}) {
49 my %nodeArgs = (%{$info->{args}},%$args); 49 my %nodeArgs = (%{$info->{args}},%$args);
50 $nodeArgs{controlClass} = $class; 50 $nodeArgs{controlClass} = $class;
51 51
52 return $this->Create($name,$info->{type},\%nodeArgs); 52 return $this->Create($name,$info->{type},\%nodeArgs);
53 } else { 53 } else {
54 die new IMPL::Exception('A control is\'t registered', $class, $name); 54 die new IMPL::Exception('A control is\'t registered', $class, $name);
55 } 55 }
56 } 56 }
57 57
58 sub provider { 58 sub provider {
59 my ($this,%args) = @_; 59 my ($this,%args) = @_;
60 60
77 new Template::Context( 77 new Template::Context(
78 VARIABLES => { 78 VARIABLES => {
79 document => $this, 79 document => $this,
80 this => $this, 80 this => $this,
81 render => sub { 81 render => sub {
82 $this->_process(@_); 82 $this->_process(@_);
83 }, 83 },
84 encode => sub { 84 encode => sub {
85 Encode::encode('utf8',shift); 85 Encode::encode('utf8',shift);
86 }, 86 },
87 dump => sub { 87 dump => sub {
88 Dumper(shift); 88 Dumper(shift);
89 }, 89 },
90 as_list => sub { 90 as_list => sub {
91 [ map ref($_) eq 'ARRAY' ? @$_ : $_, @_ ] 91 [ map ref($_) eq 'ARRAY' ? @$_ : $_, @_ ]
92 } 92 }
93 }, 93 },
94 RECURSION => 1, 94 RECURSION => 1,
95 LOAD_TEMPLATES => [$this->provider] 95 LOAD_TEMPLATES => [$this->provider]
96 ) 96 )
97 ) 97 )
98 } 98 }
99 } 99 }
100 100
101 sub resolveVar { 101 sub resolveVar {
102 my ($this,$var) = @_; 102 my ($this,$var) = @_;
103 103
104 return $this->context->stash->get($var); 104 return $this->context->stash->get($var);
105 } 105 }
106 106
107 sub registerControlClass { 107 sub registerControlClass {
108 my ($this, $controlClass, $type, $args) = @_; 108 my ($this, $controlClass, $type, $args) = @_;
109 109
110 $type ||= 'IMPL::Web::TT::Control'; 110 $type ||= 'IMPL::Web::TT::Control';
111 111
112 die new IMPL::InvalidArgumentException("A controlClass must be a single word",$controlClass) unless $controlClass =~ /^\w+$/; 112 die new IMPL::InvalidArgumentException("A controlClass must be a single word",$controlClass) unless $controlClass =~ /^\w+$/;
113 113
114 eval "require $type; 1;" or die new IMPL::Exception("Failed to load a module",$type,"$@") unless eval { $type->can('new') }; 114 eval "require $type; 1;" or die new IMPL::Exception("Failed to load a module",$type,"$@") unless eval { $type->can('new') };
115 115
116 die new IMPL::InvalidArgumentException("A type must be subclass of IMPL::DOM::Node",$type) unless $type->isa('IMPL::DOM::Node'); 116 die new IMPL::InvalidArgumentException("A type must be subclass of IMPL::DOM::Node",$type) unless $type->isa('IMPL::DOM::Node');
117 117
118 # resolve template name to a real template 118 # resolve template name to a real template
119 $args->{template} = $this->context->template($args->{template}) if $args->{template}; 119 $args->{template} = $this->context->template($args->{template}) if $args->{template};
120 120
121 $this->_controlClassMap->{$controlClass} = { 121 $this->_controlClassMap->{$controlClass} = {
122 controlClass => $controlClass, 122 controlClass => $controlClass,
123 type => $type, 123 type => $type,
124 args => ref $args eq 'HASH' ? $args : {} 124 args => ref $args eq 'HASH' ? $args : {}
125 }; 125 };
126 } 126 }
127 127
128 sub require { 128 sub require {
129 my ($this,$template) = @_; 129 my ($this,$template) = @_;
130 130
131 my $doc = $this->context->template($template); 131 my $doc = $this->context->template($template);
132 132
133 die new IMPL::InvalidOperationException("A specified template isn't a document",$template) unless eval{ $doc -> isa('Template::Document') }; 133 die new IMPL::InvalidOperationException("A specified template isn't a document",$template) unless eval{ $doc -> isa('Template::Document') };
134 134
135 my $controlClass = $doc->class; 135 my $controlClass = $doc->class;
136 my $type = $doc->nativeType; 136 my $type = $doc->nativeType;
137 my $controlTemplate; 137 my $controlTemplate;
138 my $out = ""; 138 my $out = "";
139 139
140 die new IMPL::InvalidOperationException("A specified template isn't a control",$template) unless $controlClass; 140 die new IMPL::InvalidOperationException("A specified template isn't a control",$template) unless $controlClass;
141 141
142 if (not $this->isControlClass($controlClass)) { 142 if (not $this->isControlClass($controlClass)) {
143 if ($doc->template) { 143 if ($doc->template) {
144 $controlTemplate = $doc->blocks()->{$doc->template} || $this->context->template($doc->template); 144 $controlTemplate = $doc->blocks()->{$doc->template} || $this->context->template($doc->template);
145 $out = $this->context->include($doc); 145 $out = $this->context->include($doc);
146 } else { 146 } else {
147 $controlTemplate = $doc; 147 $controlTemplate = $doc;
148 } 148 }
149 $this->registerControlClass($controlClass,$type,{ template => $controlTemplate } ); 149 $this->registerControlClass($controlClass,$type,{ template => $controlTemplate } );
150 } 150 }
151 151
152 return $out; 152 return $out;
153 } 153 }
154 154
155 sub isControlClass { 155 sub isControlClass {
156 my ($this,$name) = @_; 156 my ($this,$name) = @_;
157 return $this->_controlClassMap->{$name} ? 1 : 0; 157 return $this->_controlClassMap->{$name} ? 1 : 0;
158 } 158 }
159 159
160 sub _getControls { 160 sub _getControls {
161 my ($this) = @_; 161 my ($this) = @_;
162 162
163 my ($node) = $this->selectNodes('controls'); 163 my ($node) = $this->selectNodes('controls');
164 return $node; 164 return $node;
165 } 165 }
166 166
167 sub _validatePresenter { 167 sub _validatePresenter {
168 my ($this,$value) = @_; 168 my ($this,$value) = @_;
169 169
170 die new IMPL::InvalidArgumentException("A view object is required") unless blessed($value) and $value->isa('Template::View'); 170 die new IMPL::InvalidArgumentException("A view object is required") unless blessed($value) and $value->isa('Template::View');
171 } 171 }
172 172
173 sub LoadFile { 173 sub LoadFile {
174 my ($this,$src,$encoding,$includes,$vars) = @_; 174 my ($this,$src,$encoding,$includes,$vars) = @_;
175 175
181 181
182 $this->_context(undef); 182 $this->_context(undef);
183 $this->_provider(undef); 183 $this->_provider(undef);
184 184
185 if (not ref $src) { 185 if (not ref $src) {
186 my ($vol,$dir,$fileName) = File::Spec->splitpath($src); 186 my ($vol,$dir,$fileName) = File::Spec->splitpath($src);
187 unshift @$includes, File::Spec->catpath($vol,$dir,''); 187 unshift @$includes, File::Spec->catpath($vol,$dir,'');
188 $src = $fileName; 188 $src = $fileName;
189 } 189 }
190 190
191 $this->provider( 191 $this->provider(
192 ENCODING => $encoding, 192 ENCODING => $encoding,
193 INTERPOLATE => 1, 193 INTERPOLATE => 1,
198 COMPILE_DIR => $this->cache, 198 COMPILE_DIR => $this->cache,
199 INCLUDE_PATH => $includes 199 INCLUDE_PATH => $includes
200 ); 200 );
201 201
202 if ($vars) { 202 if ($vars) {
203 while ( my ($var,$val) = each %$vars ) { 203 while ( my ($var,$val) = each %$vars ) {
204 $this->AddVar($var,$val); 204 $this->AddVar($var,$val);
205 } 205 }
206 } 206 }
207 207
208 $this->context->process($_) foreach $this->preprocess; 208 $this->context->process($_) foreach $this->preprocess;
209 209
210 my $template = $this->context->template($src); 210 my $template = $this->context->template($src);
211 $this->title($template->title); 211 $this->title($template->title);
212 if ( $template->template ) { 212 if ( $template->template ) {
213 $this->context->process($template); 213 $this->context->process($template);
214 $this->template($template->template); 214 $this->template($template->template);
215 } else { 215 } else {
216 $this->template($template); 216 $this->template($template);
217 } 217 }
218 218
219 } 219 }
220 220
221 sub AddVar { 221 sub AddVar {
222 my ($this,$name,$value) = @_; 222 my ($this,$name,$value) = @_;
223 223
224 $this->context->stash->set($name,$value); 224 $this->context->stash->set($name,$value);
225 } 225 }
226 226
227 sub Render { 227 sub Render {
228 my ($this) = @_; 228 my ($this) = @_;
229 229
230 return $this->context->process($this->template); 230 return $this->context->process($this->template);
231 } 231 }
232 232
233 # Формирует представление для произвольных объектов 233 # Формирует представление для произвольных объектов
234 sub _process { 234 sub _process {
235 my ($this,@items) = @_; 235 my ($this,@items) = @_;
236 236
237 my @result; 237 my @result;
238 238
239 foreach my $item (@items) { 239 foreach my $item (@items) {
240 if (blessed($item) and $item->isa('IMPL::Web::TT::Control')) { 240 if (blessed($item) and $item->isa('IMPL::Web::TT::Control')) {
241 push @result, $item->Render(); 241 push @result, $item->Render();
242 } elsif(blessed($item)) { 242 } elsif(blessed($item)) {
243 if ($this->presenter) { 243 if ($this->presenter) {
244 push @result, $this->presenter->print($item); 244 push @result, $this->presenter->print($item);
245 } else { 245 } else {
246 push @result, $this->toString; 246 push @result, $this->toString;
247 } 247 }
248 } else { 248 } else {
249 push @result, $item; 249 push @result, $item;
250 } 250 }
251 } 251 }
252 252
253 return join '',@result; 253 return join '',@result;
254 } 254 }
255 255
256 our $AUTOLOAD; 256 our $AUTOLOAD;
257 sub AUTOLOAD { 257 sub AUTOLOAD {
258 my $this = shift; 258 my $this = shift;
259 my ($method) = ($AUTOLOAD =~ /(\w+)$/); 259 my ($method) = ($AUTOLOAD =~ /(\w+)$/);
260 260
261 if($method =~ /^create(\w+)/) { 261 if($method =~ /^create(\w+)/) {
262 my ($name,$args) = @_; 262 my ($name,$args) = @_;
263 return $this->CreateControl($name,$1,$args); 263 return $this->CreateControl($name,$1,$args);
264 } 264 }
265 265
266 my @result = $this->selectNodes($method); 266 my @result = $this->selectNodes($method);
267 267
268 return $result[0] if @result; 268 return $result[0] if @result;
269 carp "Looks like you have a mistake, the document doesn't have a such property or child: $method"; 269 carp "Looks like you have a mistake, the document doesn't have a such property or child: $method";
270 return; 270 return;
271 } 271 }
272 272
273 sub Dispose { 273 sub Dispose {
274 my ($this) = @_; 274 my ($this) = @_;
275 275
358 [% CALL document.registerClass( 'Form' )%] 358 [% CALL document.registerClass( 'Form' )%]
359 359
360 [% table = document.сreateTable('env') %] 360 [% table = document.сreateTable('env') %]
361 361
362 [% FOEACH item in document.result %] 362 [% FOEACH item in document.result %]
363 [% table.rows.Add( item.get('name','value') ) %] 363 [% table.rows.Add( item.get('name','value') ) %]
364 [% END %] 364 [% END %]
365 365
366 [% form = document.createForm('login') %] 366 [% form = document.createForm('login') %]
367 [% form.template = 'LOGIN_FORM'%] 367 [% form.template = 'LOGIN_FORM'%]
368 368
369 [% FOREACH item IN document.childNodes %] 369 [% FOREACH item IN document.childNodes %]
370 [%render(item)%] 370 [%render(item)%]
371 [% END %] 371 [% END %]
372 372
373 [% BLOCK LOGIN_FORM %] 373 [% BLOCK LOGIN_FORM %]
374 <form method="POST" action='/login.pl'> 374 <form method="POST" action='/login.pl'>
375 user: [% render(this.item('name')) %] password: [% render(this.item('password')) %] <input type="submit"/> 375 user: [% render(this.item('name')) %] password: [% render(this.item('password')) %] <input type="submit"/>
376 </form> 376 </form>
377 [% END %] 377 [% END %]
378 378
379 =end code html 379 =end code html
380 380