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