Mercurial > pub > Impl
comparison Lib/IMPL/Web/View/TTLoader.pm @ 345:72799d1211c5
sync
| author | cin |
|---|---|
| date | Fri, 27 Sep 2013 16:28:27 +0400 |
| parents | 9bdccdf1f50b |
| children |
comparison
equal
deleted
inserted
replaced
| 344:f1d67615a5b1 | 345:72799d1211c5 |
|---|---|
| 3 | 3 |
| 4 use Template::Constants qw(:status); | 4 use Template::Constants qw(:status); |
| 5 | 5 |
| 6 use File::Spec(); | 6 use File::Spec(); |
| 7 use IMPL::Const qw(:prop); | 7 use IMPL::Const qw(:prop); |
| 8 use Scalar::Util qw(weaken); | |
| 9 | |
| 8 use IMPL::declare { | 10 use IMPL::declare { |
| 9 require => { | 11 require => { |
| 10 Provider => 'Template::Provider', | 12 Provider => 'Template::Provider', |
| 11 Context => 'IMPL::Web::View::TTContext', | 13 Context => 'IMPL::Web::View::TTContext', |
| 12 TTRegistry => 'IMPL::Web::View::TTRegistry', | 14 TTRegistry => 'IMPL::Web::View::TTRegistry', |
| 19 base => [ | 21 base => [ |
| 20 'IMPL::Object' => undef, | 22 'IMPL::Object' => undef, |
| 21 'IMPL::Object::Serializable' => undef | 23 'IMPL::Object::Serializable' => undef |
| 22 ], | 24 ], |
| 23 props => [ | 25 props => [ |
| 24 options => PROP_RO, | |
| 25 provider => PROP_RO, | 26 provider => PROP_RO, |
| 26 context => PROP_RO, | 27 context => PROP_RO, |
| 27 ext => PROP_RO, | 28 registry => PROP_RO, |
| 28 layoutBase => PROP_RO, | |
| 29 isInitialized => PROP_RO, | |
| 30 initializer => PROP_RO, | |
| 31 _globals => PROP_RW | 29 _globals => PROP_RW |
| 32 ] | 30 ] |
| 33 }; | 31 }; |
| 34 | 32 |
| 35 sub save { | 33 sub save { |
| 56 sub CTOR { | 54 sub CTOR { |
| 57 my ($this,$refOpts,%args) = @_; | 55 my ($this,$refOpts,%args) = @_; |
| 58 | 56 |
| 59 $refOpts ||= {}; | 57 $refOpts ||= {}; |
| 60 | 58 |
| 61 $this->ext($args{ext}) if $args{ext}; | 59 # to aviod cyclic references we need to do a copy of $refOpts |
| 62 $this->initializer($args{initializer}) if $args{initializer}; | 60 $refOpts->{LOAD_TEMPLATES} = Provider->new( { %$refOpts } ); |
| 61 | |
| 62 my $ctx = Context->new( { %$refOpts } ); | |
| 63 $this->context($ctx); | |
| 64 | |
| 63 $this->_globals(ref $args{globals} eq 'HASH' ? $args{globals} : {}); | 65 $this->_globals(ref $args{globals} eq 'HASH' ? $args{globals} : {}); |
| 64 | 66 |
| 65 $this->options($refOpts); | 67 $ctx->tt_ext($args{ext} || '.tt'); |
| 66 $this->layoutBase($args{layoutBase}) if $args{layoutBase}; | 68 |
| 67 | 69 $this->registry(TTRegitry->new($ctx)); |
| 68 # to aviod cyclic references we need to do a copy of $refOpts | 70 |
| 69 $refOpts->{LOAD_TEMPLATES} = $this->provider(Provider->new( { %$refOpts } )); | 71 weaken($ctx); |
| 70 | 72 weaken($this); |
| 71 $this->context(Context->new($refOpts)); | 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 }); | |
| 95 | |
| 96 | |
| 72 } | 97 } |
| 73 | 98 |
| 74 sub document { | 99 sub document { |
| 75 my ($this,$name,$vars) = @_; | 100 my ($this,$name,$vars) = @_; |
| 76 | 101 |
| 77 $vars ||= {}; | 102 $vars ||= {}; |
| 78 | 103 |
| 79 my $tt = $this->template($name); | 104 my $factory = $this->registry->Require($name); |
| 80 | 105 |
| 81 $this->_init(); | 106 return $factory->new(hashMerge($vars, $this->_globals)); |
| 82 | |
| 83 my $opts = { %{ $this->options } }; | |
| 84 | |
| 85 my $ctx = $this->context->clone(); | |
| 86 | |
| 87 $ctx->stash->update($vars); | |
| 88 | |
| 89 my $registry = TTRegistry->new($this, $ctx); | |
| 90 | |
| 91 my $factory = TTFactory->new($tt->class || TTDocument, $tt, $ctx, $name, $registry); | |
| 92 | |
| 93 $vars->{registry} = $registry; | |
| 94 $vars->{layoutBase} = $this->layoutBase; | |
| 95 | |
| 96 return $factory->new( $vars ); | |
| 97 } | |
| 98 | |
| 99 | |
| 100 sub template { | |
| 101 my ($this,$name) = @_; | |
| 102 | |
| 103 $name =~ s/^\s+|\s+$//g; | |
| 104 | |
| 105 die ArgumentException->new("A valid template name is required") unless length $name; | |
| 106 | |
| 107 $name = $this->_appendExt($name); | |
| 108 | |
| 109 my ($tt,$error) = $this->provider->fetch($name); | |
| 110 | |
| 111 if (defined $error and $error == STATUS_DECLINED) { | |
| 112 die KeyNotFoundException->new($name); | |
| 113 } elsif (defined $error and $error == STATUS_ERROR) { | |
| 114 die Exception->new("Failed to load a template", $name, $tt); | |
| 115 } | |
| 116 | |
| 117 return $tt; | |
| 118 } | |
| 119 | |
| 120 sub ResolveFileName { | |
| 121 my ($this,$fname) = @_; | |
| 122 | |
| 123 $fname = $this->_appendExt($fname); | |
| 124 | |
| 125 my @files = grep -f , map File::Spec->catfile($_,$fname), @{$this->provider->paths()}; | |
| 126 return shift @files; | |
| 127 } | |
| 128 | |
| 129 sub _appendExt { | |
| 130 my ($this,$name) = @_; | |
| 131 | |
| 132 return $name unless $this->ext; | |
| 133 | |
| 134 if (length $this->ext and substr( $name, -length($this->ext) ) eq $this->ext) { | |
| 135 return $name; | |
| 136 } else { | |
| 137 return $name . $this->ext; | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 sub _init { | |
| 142 my ($this) = @_; | |
| 143 | |
| 144 if (!$this->isInitialized) { | |
| 145 my $initializer = $this->initializer || sub {}; | |
| 146 | |
| 147 eval { | |
| 148 $this->context->process($initializer,$this->_globals); | |
| 149 }; | |
| 150 if (my $e = $@) { | |
| 151 die Exception->new("Failed to process an initializer", $this->initializer, $e); | |
| 152 } | |
| 153 | |
| 154 $this->isInitialized(1); | |
| 155 } | |
| 156 } | 107 } |
| 157 | 108 |
| 158 1; | 109 1; |
| 159 | 110 |
| 160 __END__ | 111 __END__ |
| 177 '/my/app/tt', | 128 '/my/app/tt', |
| 178 '/my/app/tt/lib' | 129 '/my/app/tt/lib' |
| 179 ] | 130 ] |
| 180 }, | 131 }, |
| 181 ext => '.tt', | 132 ext => '.tt', |
| 182 initializer => 'shared/global' | 133 globals => { |
| 134 images => '//cdn.mysite.net/static/images' | |
| 135 } | |
| 183 | 136 |
| 184 ); | 137 ); |
| 185 | 138 |
| 186 my $doc = $loader->document('index'); | 139 my $doc = $loader->document('index'); |
| 187 | 140 |
