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 |
