# HG changeset patch # User sergey # Date 1386630121 -14400 # Node ID cbf4febf09304ed4f158b361aa7be8e8e2764abf # Parent 7c784144d2f120c848b4d41efe6415e3ac01a954 ObjectMeta, Tests, migrating to the new metadata model. diff -r 7c784144d2f1 -r cbf4febf0930 Lib/IMPL/Web/View/Metadata/ObjectMeta.pm --- a/Lib/IMPL/Web/View/Metadata/ObjectMeta.pm Mon Dec 09 17:35:34 2013 +0400 +++ b/Lib/IMPL/Web/View/Metadata/ObjectMeta.pm Tue Dec 10 03:02:01 2013 +0400 @@ -1,6 +1,7 @@ -package IMPL::Web::View::Metadata::FormMeta; +package IMPL::Web::View::Metadata::ObjectMeta; use strict; +use IMPL::lang; use IMPL::Const qw(:prop); use IMPL::declare { require => { @@ -11,7 +12,11 @@ AbstractObject => '-IMPL::Object::Abstract' }, base => [ - 'IMPL::Web::View::Metadata::BaseMeta' => '@_' + 'IMPL::Web::View::Metadata::BaseMeta' => sub { + my ($model,$type,$args) = @_; + $type ||= typeof($model); + return ($model,$type,$args); + } ], props => [ isMultiple => PROP_RO, @@ -26,8 +31,9 @@ sub CTOR { my ($this,$model,$type,$args) = @_; - $type ||= typeof($model); - $args->{isMultiple} ||= $type eq 'ARRAY'; + $type = $this->modelType; + + $args->{isMultiple} ||= $type && $type eq 'ARRAY'; if ($args) { $this->$_($args->{$_}) foreach grep $args->{$_}, qw(isMultiple holdingType); @@ -58,7 +64,7 @@ push @props, Meta->new($pv, $pt, \%args); } - } elsif ( $modelType eq 'HASH' ) { + } elsif ( $modelType && $modelType eq 'HASH' ) { while ( my ($k,$v) = each %{$this->model || {}} ) { push @props, Meta->new($v,undef,{name => $k}); } diff -r 7c784144d2f1 -r cbf4febf0930 Lib/IMPL/Web/View/TTContext.pm --- a/Lib/IMPL/Web/View/TTContext.pm Mon Dec 09 17:35:34 2013 +0400 +++ b/Lib/IMPL/Web/View/TTContext.pm Tue Dec 10 03:02:01 2013 +0400 @@ -25,7 +25,6 @@ no strict 'refs'; # modules is a global (for the whole document) templates cache # tt_cache is a local (for the current context only) templtes cache - # view is a special variable, which will be cloned and passed to the nested context foreach my $prop (qw( root base @@ -37,8 +36,10 @@ includes modules aliases + id - view + metadata + model )) { my $t = $prop; @@ -140,7 +141,7 @@ sub display_for { my $this = shift; - my $model = shift; + my $path = shift; my ($template, $args); if (ref $_[0] eq 'HASH') { @@ -153,15 +154,11 @@ my $prefix = $this->prefix; my $info; + my $meta = $this->resolve_model($path,$args); - if (not(($args and delete $args->{_no_resolve}) or ref $model)) { - $info = $this->resolve_model($model,$args); - } else { - $info = { - model => $model, - prefix => "" - }; - } + $info->{prefix} = $prefix ? $prefix . '.' . $path : $path; + $info->{model} = $meta->model; + $info->{metadata} = $meta; $template ||= $info->{template}; $template = $template ? $this->find_template($template) : $this->find_template_for($info->{model}); @@ -228,11 +225,6 @@ unshift @includes, $this->base; } - my $view = $this->view; - $view = ref $view eq 'HASH' ? { %{$view} } : {}; - - hashApply($view, delete $env->{view}); - my $out = eval { $ctx->localise( hashApply( @@ -251,8 +243,7 @@ display_model => sub { $ctx->display_model(@_); }, - tt_cache => {}, - view => $view + tt_cache => {} }, $env ) @@ -328,29 +319,31 @@ } sub resolve_model { - my ($this,$prefix,$args) = @_; + my ($this,$prefix) = @_; die ArgException->new(prefix => "the prefix must be specified") unless defined $prefix; - - - if (my $res = $this->stash->get(['resolve', [$this,$prefix,$args]] ) ) { - return $res; + my $meta = $this->metadata; + foreach my $part (grep length($_), split(/\.|\[(\d+)\]/, $prefix)) { + last unless $meta; + if ($part =~ /^\d+$/) { + $meta = $meta->GetItem($part); + } else { + $meta = $meta->GetProperty($part); + } } - my @comp = map { $_, 0 } grep length($_), split(/\.|\[(\d+)\]/, $prefix); - - return { - model => $this->stash->get(['model',0,@comp]), - prefix => $this->prefix ? $this->prefix . ".$prefix" : $prefix - }; + return $meta; } sub find_template_for { - my ($this,$model, $nothrow) = @_; + my ($this,$meta, $nothrow) = @_; - my $type = typeof($model); + return $this->find_template($meta->template) + if ($meta->template); + + my $type = $meta->modelType; return $this->find_template('templates/plain') unless $type; @@ -374,12 +367,13 @@ $this->cache->Set($sclass,$template); return $template; } - + + #todo $meta->GetISA push @isa, @{"${sclass}::ISA"}; } } - $this->throw(Template::Constants::ERROR_FILE, "can't find a template for the model " . typeof($model)) + $this->throw(Template::Constants::ERROR_FILE, "can't find a template for the model $type") unless $nothrow; return; diff -r 7c784144d2f1 -r cbf4febf0930 _test/Test/Web/View.pm --- a/_test/Test/Web/View.pm Mon Dec 09 17:35:34 2013 +0400 +++ b/_test/Test/Web/View.pm Tue Dec 10 03:02:01 2013 +0400 @@ -15,10 +15,10 @@ FormMeta => 'IMPL::Web::View::Metadata::FormMeta', ObjectMeta => 'IMPL::Web::View::Metadata::ObjectMeta', Schema => 'IMPL::DOM::Schema', - Builder => 'IMPL::DOM::Navigator::Builder', Document => 'IMPL::DOM::Document', XMLReader => 'IMPL::DOM::XMLReader', - MProfiler => '-IMPL::Profiler::Memory' + MProfiler => '-IMPL::Profiler::Memory', + PersonModel => '-Test::Web::View::Model::Person' }, base => [ 'IMPL::Test::Unit' => '@_' @@ -108,8 +108,49 @@ test TestObjectMetadata => sub { my ($this) = @_; + my $meta = ObjectMeta->new( + PersonModel->new( + name => 'alex', + age => 29, + address => [ + { city => 'city 17', street => 'doomed' }, + { city => 'gropher', street => 'caveroad' } + ] + ) + ); + assert($meta->modelType eq PersonModel); + + my $prop = $meta->GetProperty('name'); + assert($prop); + assert($prop->model eq 'alex'); + + $prop = $meta->GetProperty('address'); + + assert($prop->isMultiple); + assert($prop->name eq 'address'); + assert($prop->modelType eq 'ARRAY'); + + my $items = $prop->GetItems(); + assert(@$items == 2); + assertarray( + [map $_->GetProperty('city')->model, @$items], + ['city 17', 'gropher'] + ); }; +package Test::Web::View::Model::Person; +use IMPL::Const qw(:prop); +use IMPL::declare { + base => [ + 'IMPL::Object' => undef, + 'IMPL::Object::Autofill' => '@_' + ], + props => [ + name => PROP_RW, + age => PROP_RW, + address => PROP_RW | PROP_LIST + ] +}; 1; \ No newline at end of file