Mercurial > pub > Impl
comparison Lib/IMPL/Web/View/TTDocument.pm @ 288:3a9cfea098dd
*TTView refactoring: removed RequireControl method, etc.
| author | sergey |
|---|---|
| date | Tue, 19 Feb 2013 19:58:27 +0400 |
| parents | 2d253e6e4a88 |
| children | 85572f512abc |
comparison
equal
deleted
inserted
replaced
| 287:2d253e6e4a88 | 288:3a9cfea098dd |
|---|---|
| 1 package IMPL::Web::View::TTDocument; | 1 package IMPL::Web::View::TTDocument; |
| 2 use strict; | 2 use strict; |
| 3 | 3 |
| 4 use Scalar::Util qw(weaken); | 4 use Scalar::Util qw(weaken); |
| 5 use IMPL::Const qw(:prop); | 5 use IMPL::Const qw(:prop); |
| 6 use IMPL::lang qw(:hash); | 6 use IMPL::lang qw(:hash is); |
| 7 use Carp qw(carp); | |
| 8 use mro; | |
| 7 | 9 |
| 8 use IMPL::declare { | 10 use IMPL::declare { |
| 9 require => { | 11 require => { |
| 10 TTFactory => 'IMPL::Web::View::TTFactory', | 12 TTFactory => 'IMPL::Web::View::TTFactory', |
| 11 TTControl => 'IMPL::Web::View::TTControl', | 13 TTControl => 'IMPL::Web::View::TTControl', |
| 12 Loader => 'IMPL::Code::Loader' | 14 Loader => 'IMPL::Code::Loader' |
| 13 }, | 15 }, |
| 14 base => [ | 16 base => [ |
| 15 'IMPL::Web::View::TTControl' => sub { | 17 'IMPL::Web::View::TTControl' => sub { |
| 16 my ($template,$ctx) = @_; | 18 my ($template,$ctx) = @_; |
| 17 'document', | 19 $ctx ||= Template::Context->new(); |
| 18 $template, # template | 20 return 'document', $template, $ctx; # context |
| 19 $ctx || Template::Context->new() # context | |
| 20 } | 21 } |
| 21 ], | 22 ], |
| 22 props => [ | 23 props => [ |
| 23 layout => PROP_RW, | 24 layout => PROP_RW, |
| 24 loader => PROP_RW, | 25 loader => PROP_RW, |
| 25 controls => PROP_RO, | 26 controls => PROP_RO, |
| 26 creationArgs => PROP_RO, | |
| 27 | |
| 28 # store the stash separately to make require() method to work correctly | |
| 29 # even when a stash of the context is modified during the processing | |
| 30 stash => PROP_RO | |
| 31 ] | 27 ] |
| 32 }; | 28 }; |
| 33 | 29 |
| 34 BEGIN { | |
| 35 | |
| 36 } | |
| 37 | |
| 38 sub CTOR { | 30 sub CTOR { |
| 39 my ($this,$template,$ctx,$loader,$vars) = @_; | 31 my ($this,$template,$ctx,$loader,$vars) = @_; |
| 40 | 32 |
| 41 $this->controls({}); | 33 $this->controls({}); |
| 42 $this->loader($loader) if $loader; | 34 $this->loader($loader) if $loader; |
| 43 | 35 |
| 44 $this->layout( $template->layout ) unless $this->layout; | 36 $this->layout( $template->layout ) unless $this->layout; |
| 45 | 37 |
| 46 $this->stash($this->context->stash); | 38 $this->context->stash->update($vars) |
| 47 $this->creationArgs($vars); | 39 if ref $vars eq 'HASH'; |
| 48 | 40 |
| 49 my $self = $this; | 41 $this->InitInstance(); |
| 50 weaken($self); | |
| 51 | |
| 52 $this->templateVars(require => sub { | |
| 53 my $doc = $self; | |
| 54 die new IMPL::Exception("A document is destroyed or invalid") unless $doc; | |
| 55 $doc->RequireControl(@_); | |
| 56 }); | |
| 57 | |
| 58 $this->templateVars(document => sub { $self } ); | |
| 59 $this->InitInstance($vars); | |
| 60 } | 42 } |
| 61 | 43 |
| 62 sub templateVars { | 44 sub templateVars { |
| 63 my $this = shift; | 45 my $this = shift; |
| 64 my $name = shift; | 46 my $name = shift; |
| 65 | |
| 66 if (@_) { | 47 if (@_) { |
| 67 return $this->stash->set($name, shift); | 48 return $this->context->stash->set($name, shift); |
| 68 } else { | 49 } else { |
| 69 return $this->stash->get($name); | 50 return $this->context->stash->get($name); |
| 70 } | 51 } |
| 71 } | 52 } |
| 72 | 53 |
| 73 sub RequireControl { | 54 sub RequireControl { |
| 74 my ($this, $control) = @_; | 55 my ($this, $control, $ctx) = @_; |
| 56 | |
| 57 $ctx ||= $this->context; | |
| 75 | 58 |
| 76 if (my $factory = $this->controls->{$control}) { | 59 if (my $factory = $this->controls->{$control}) { |
| 77 return $factory; | 60 return $factory; |
| 78 } else { | 61 } else { |
| 79 | |
| 80 my $path = $control; | 62 my $path = $control; |
| 81 | 63 |
| 82 if ( my $template = $this->loader->template($path) ) { | 64 if ( my $template = $this->loader->template($path) ) { |
| 83 | 65 |
| 84 # factory will create a clone of the stash | |
| 85 # $opts->{STASH} = $this->stash->clone(); | |
| 86 | |
| 87 my $ctx = Template::Context->new({%{$this->context}, STASH => $this->stash });#new Template::Context($opts); | |
| 88 | |
| 89 $factory = new IMPL::Web::View::TTFactory( | 66 $factory = new IMPL::Web::View::TTFactory( |
| 90 $template->class || TTControl, | 67 $template->class || TTControl, |
| 91 $template, | 68 $template, |
| 92 $ctx, | 69 $ctx, |
| 93 join( '/', splice( @{[split(/\//,$path)]}, 0, -1 ) ) | 70 join( '/', splice( @{[split(/\//,$path)]}, 0, -1 ) ) |
| 107 } | 84 } |
| 108 } | 85 } |
| 109 | 86 |
| 110 sub Render { | 87 sub Render { |
| 111 my ($this,$args) = @_; | 88 my ($this,$args) = @_; |
| 112 | 89 |
| 113 $args ||= {}; | 90 $args ||= {}; |
| 114 | 91 |
| 115 my $newArgs = hashMerge($this->creationArgs, $args); | 92 $this->context->localise(); |
| 116 | 93 |
| 117 if ($this->layout) { | 94 my $documentContext; |
| 118 my $text = eval { | 95 my %controls; |
| 119 #$this->context->localise(); | 96 my $require; |
| 97 $require = sub { | |
| 98 my $control = shift; | |
| 99 if (my $factory = $controls{$control}) { | |
| 100 return $factory; | |
| 101 } else { | |
| 102 my $path = $control; | |
| 103 | |
| 104 if ( my $template = $this->loader->template($path) ) { | |
| 105 | |
| 106 $factory = new IMPL::Web::View::TTFactory( | |
| 107 $template->class || TTControl, | |
| 108 $template, | |
| 109 $documentContext, | |
| 110 join( '/', splice( @{[split(/\//,$path)]}, 0, -1 ) ), | |
| 111 $require | |
| 112 ); | |
| 113 | |
| 114 if ($template->class) { | |
| 115 Loader->safe->Require($template->class); | |
| 116 } | |
| 117 | |
| 118 $controls{$control} = $factory; | |
| 119 | |
| 120 return $factory; | |
| 121 | |
| 122 } else { | |
| 123 die new IMPL::KeyNotFoundException($control); | |
| 124 } | |
| 125 } | |
| 126 }; | |
| 127 | |
| 128 $this->context->stash->set(require => $require); | |
| 129 $this->context->stash->set(document => $this); | |
| 130 $documentContext = Template::Context->new( { %{$this->context} } ); | |
| 131 | |
| 132 my $text = eval { | |
| 133 | |
| 134 if ($this->layout) { | |
| 120 my $tlayout = $this->loader->layout($this->layout); | 135 my $tlayout = $this->loader->layout($this->layout); |
| 121 if(my $init = $tlayout->blocks->{INIT}) { | 136 if(my $init = $tlayout->blocks->{INIT}) { |
| 122 $this->context->process( | 137 $this->context->process( |
| 123 $init, | 138 $init, |
| 124 hashMerge( | 139 hashMerge( |
| 125 $newArgs, | 140 $args, |
| 126 { | 141 { |
| 127 template => $this->template | 142 template => $this->template |
| 128 } | 143 } |
| 129 ) | 144 ) |
| 130 ); | 145 ); |
| 131 } | 146 } |
| 147 my $content = $this->next::method($args); | |
| 132 return $this->context->include( | 148 return $this->context->include( |
| 133 $tlayout, | 149 $tlayout, |
| 134 { | 150 { |
| 135 %{$newArgs}, | 151 %{$args}, |
| 136 content => $this->RenderContent($newArgs), | 152 content => $content, |
| 137 this => $this, | 153 this => $this, |
| 138 template => $this->template | 154 template => $this->template |
| 139 } | 155 } |
| 140 ); | 156 ); |
| 141 }; | 157 } else { |
| 142 my $e = $@; | 158 return $this->next::method($args); |
| 143 | 159 } |
| 144 #$this->context->delocalise(); | 160 }; |
| 145 | 161 |
| 146 if ($e) { | 162 $this->context->delocalise(); |
| 147 die $e; | 163 |
| 148 } else { | 164 my $e = $@; |
| 149 return $text; | 165 if ($e) { |
| 150 } | 166 die $e; |
| 151 | |
| 152 } else { | 167 } else { |
| 153 return $this->RenderContent($newArgs); | 168 return $text; |
| 154 } | 169 } |
| 155 } | 170 |
| 156 | 171 |
| 157 sub RenderContent { | |
| 158 my $this = shift; | |
| 159 return $this->SUPER::Render(@_); | |
| 160 } | 172 } |
| 161 | 173 |
| 162 1; | 174 1; |
| 163 | 175 |
| 164 __END__ | 176 __END__ |
