Mercurial > pub > Impl
comparison Lib/IMPL/Web/Handler/TTView.pm @ 204:d63f9a92d6d4
+IMPL::Config::Include - simple way to include external config
*IMPL::Web::Handler::TTView - finished template selecting mechanism (not tested)
author | sergey |
---|---|
date | Wed, 02 May 2012 17:42:47 +0400 |
parents | 68a59c3358ff |
children | 891c04080658 |
comparison
equal
deleted
inserted
replaced
203:68a59c3358ff | 204:d63f9a92d6d4 |
---|---|
1 package IMPL::Web::Handler::TTView; | 1 package IMPL::Web::Handler::TTView; |
2 use strict; | 2 use strict; |
3 | 3 |
4 use List::Util qw(first); | |
4 use IMPL::lang qw(:declare :constants); | 5 use IMPL::lang qw(:declare :constants); |
5 use IMPL::declare { | 6 use IMPL::declare { |
6 base => { | 7 base => { |
7 'IMPL::Object' => undef, | 8 'IMPL::Object' => undef, |
8 'IMPL::Object::Autofill' => '@_', | 9 'IMPL::Object::Autofill' => '@_', |
15 public property loader => PROP_GET | PROP_OWNERSET; | 16 public property loader => PROP_GET | PROP_OWNERSET; |
16 public property selectors => PROP_GET | PROP_LIST | PROP_OWNERSET; | 17 public property selectors => PROP_GET | PROP_LIST | PROP_OWNERSET; |
17 public property defaultDocument => PROP_ALL; | 18 public property defaultDocument => PROP_ALL; |
18 public property indexResource => PROP_ALL; | 19 public property indexResource => PROP_ALL; |
19 private property _selectorsCache => PROP_ALL; | 20 private property _selectorsCache => PROP_ALL; |
21 private property _classTemplates => PROP_ALL; | |
20 } | 22 } |
21 | 23 |
22 sub CTOR { | 24 sub CTOR { |
23 my ($this) = @_; | 25 my ($this) = @_; |
24 | 26 |
29 my ($this,$action,$next) = @_; | 31 my ($this,$action,$next) = @_; |
30 | 32 |
31 my $result = $next ? $next->($action) : undef; | 33 my $result = $next ? $next->($action) : undef; |
32 | 34 |
33 my $doc = $this->loader->document( | 35 my $doc = $this->loader->document( |
34 'default', | 36 $this->SelectView($action,ref $result), |
35 { | 37 { |
36 data => $result, | 38 data => $result, |
37 action => $action, | 39 action => $action, |
38 app => $action->application | 40 app => $action->application |
39 } | 41 } |
52 my $last = pop @path; | 54 my $last = pop @path; |
53 $last =~ s/\.\w+$//; | 55 $last =~ s/\.\w+$//; |
54 $last = $this->indexResource; | 56 $last = $this->indexResource; |
55 push @path,$last; | 57 push @path,$last; |
56 | 58 |
59 $this->BuildCache unless $this->_selectorsCache; | |
57 my $cache = $this->_selectorsCache; | 60 my $cache = $this->_selectorsCache; |
61 | |
62 foreach my $subclass ( $class ? (_GetHierarchy($class), '-default') : '-plain') { | |
63 my @results; | |
64 push @results, { data => $this->_classTemplates->{$subclass} } if $this->_classTemplates->{$subclass}; | |
65 my $alternatives = [ { selectors => $cache->{$subclass}, immediate => 1 } ]; | |
66 $alternatives = $this->MatchAlternatives($_,$alternatives,\@results) foreach @path; | |
58 | 67 |
59 my $alternatives = [ map { | 68 if (@results) { |
60 {selectors => $cache->{$_}, immediate => 1} | 69 return shift sort { $b->{level} <=> $a->{level} } @results; |
61 } grep $cache->{$_}, ( $class ? (_GetHierarchy($class), '-default') : '-plain' ) | 70 } |
62 ]; | 71 } |
63 | 72 |
64 my @results; | 73 return $this->defaultDocument; |
65 | |
66 $alternatives = $this->MatchAlternatives($_,$alternatives,\@results) foreach @path; | |
67 | |
68 @results = sort { $b->{level} <=> $a->{level} } @results; | |
69 } | 74 } |
70 | 75 |
71 sub _GetHierarchy { | 76 sub _GetHierarchy { |
72 my ($class) = @_; | 77 my ($class) = @_; |
73 return unless $class; | 78 return unless $class; |
80 sub BuildCache { | 85 sub BuildCache { |
81 my ($this) = @_; | 86 my ($this) = @_; |
82 | 87 |
83 my @selectors; | 88 my @selectors; |
84 | 89 |
90 my $cache = $this->_selectorsCache({}); | |
91 $this->_classTemplates({}); | |
92 | |
85 foreach my $selector ($this->selectors) { | 93 foreach my $selector ($this->selectors) { |
86 if (not ref $selector) { | 94 if (not ref $selector) { |
87 | 95 |
88 my ($path,$data) = split(/\s*=>\s*/, $selector); | 96 my ($path,$data) = split(/\s*=>\s*/, $selector); |
89 | 97 |
90 my @path = split(/\s+/,$path); | 98 my @path = split(/\s+/,$path); |
91 | 99 |
92 my $class; | 100 my $class; |
93 | 101 |
102 # if this selector has a class part | |
94 if ($path[$#path-1] =~ m/^\@(.*)/) { | 103 if ($path[$#path-1] =~ m/^\@(.*)/) { |
95 $class = $1; | 104 $class = $1; |
96 shift @path; | 105 shift @path; |
97 } else { | 106 } else { |
98 $class = '-default'; | 107 $class = '-default'; |
99 } | 108 } |
100 | 109 |
110 #if this selector has a path | |
101 if (@path) { | 111 if (@path) { |
102 | |
103 @path = reverse @path; | 112 @path = reverse @path; |
104 my $last = pop @path; | 113 my $last = pop @path; |
114 my $t = ( $cache->{$class} ||= {} ); | |
115 my $level = 1; | |
116 foreach my $prim (@path ) { | |
117 $t = ($t->{$prim}->{next} ||= {}); | |
118 $level ++; | |
119 } | |
120 $t->{$last}->{level} = $level; | |
121 $t->{$last}->{data} = $data; | |
105 | 122 |
106 } else { | 123 } else { |
107 # todo | 124 # we dont have a selector, only class |
125 | |
126 $this->_classTemplates->{$class} = $data; | |
108 } | 127 } |
109 | 128 |
110 } | 129 } |
111 } | |
112 | |
113 foreach my $selector( | |
114 { path => [qw( foo bar )], data => 'teo' }, | |
115 { path => [qw( {x:.*} zoo bar )], data => 'view/{x}'}, | |
116 { path => [qw( foo >zoo >bar )], data => 'ilo' }, | |
117 { path => [qw( bar )], data => 'duo' }, | |
118 { path => [qw( wee )], data => 'iwy'}, | |
119 { path => [qw( foo wee )], data => 'fwy'}, | |
120 { path => [qw( {x:\w+} )], data => 'x:{x}'}, | |
121 { path => [qw( boo {x:\w+} )], data => 'boo/{x}'}, | |
122 ) { | |
123 my $t = $tree; | |
124 my @path = reverse @{$selector->{path}}; | |
125 my $last = pop @path; | |
126 my $level = 1; | |
127 foreach my $prim (@path ) { | |
128 $t = ($t->{$prim}->{next} ||= {}); | |
129 $level ++; | |
130 } | |
131 $t->{$last}->{level} = $level; | |
132 $t->{$last}->{data} = $selector->{data}; | |
133 } | 130 } |
134 } | 131 } |
135 | 132 |
136 sub MatchAlternatives { | 133 sub MatchAlternatives { |
137 my ($this,$segment,$alternatives,$results) = @_; | 134 my ($this,$segment,$alternatives,$results) = @_; |
245 [url-template] [class] => template | 242 [url-template] [class] => template |
246 | 243 |
247 shoes * => product/list | 244 shoes * => product/list |
248 {action:*.} @My::Data::Product => product/{action} | 245 {action:*.} @My::Data::Product => product/{action} |
249 | 246 |
250 stuff/list => product/list | 247 stuff list => product/list |
251 /123/details => product/details | 248 details => product/details |
252 | 249 |
253 =end text | 250 =end text |
254 | 251 |
255 | 252 |
256 =cut | 253 =cut |