# HG changeset patch # User sergey # Date 1350521395 -14400 # Node ID f48a1a9f4fa2cd57522ceeb4c53a2621d2153b29 # Parent abc7c26bf6159a565eaa66b0944f0d8eab119909 +Added ViewResult to allow implementation of the view environment. *TTDocuments now storing creation parameters *TTControls automatically propagating layout and title meta to their attributes +Added UnauthorizaedException web exception *minor fixes diff -r abc7c26bf615 -r f48a1a9f4fa2 Lib/IMPL/DOM/Schema/Node.pm --- a/Lib/IMPL/DOM/Schema/Node.pm Wed Oct 17 17:41:29 2012 +0400 +++ b/Lib/IMPL/DOM/Schema/Node.pm Thu Oct 18 04:49:55 2012 +0400 @@ -57,6 +57,18 @@ } } +sub isOptional { + my ($this) = @_; + + return $this->{$minOccur} ? 0 : 1; +} + +sub isMultiple { + my ($this) = @_; + + return ($this->{$maxOccur} eq 'unbounded' || $this->{$maxOccur} > 1 ) ? 1 : 0; +} + sub inflateValue { $_[1]; } diff -r abc7c26bf615 -r f48a1a9f4fa2 Lib/IMPL/Web/Handler/JSONView.pm --- a/Lib/IMPL/Web/Handler/JSONView.pm Wed Oct 17 17:41:29 2012 +0400 +++ b/Lib/IMPL/Web/Handler/JSONView.pm Thu Oct 18 04:49:55 2012 +0400 @@ -4,7 +4,8 @@ use IMPL::declare { require => { - HttpResponse => 'IMPL::Web::HttpResponse' + HttpResponse => 'IMPL::Web::HttpResponse', + ViewResult => '-IMPL::Web::ViewResult' }, base => [ 'IMPL::Object' => undef, @@ -21,14 +22,18 @@ my ($this,$action,$next) = @_; my $result = $next ? $next->($action) : undef; - $result = [$result] unless ref $result; + - $action->response->contentType($this->contentType); - + my $model = ( ref $result and eval { $result->isa(ViewResult) } ) + ? $result->model + : $result; + + $model = [$model] unless ref $model; + return HttpResponse->new({ type => $this->contentType, charset => 'utf-8', - body => JSON->new->utf8->pretty->encode($result) + body => JSON->new->utf8->pretty->encode($model) }); } diff -r abc7c26bf615 -r f48a1a9f4fa2 Lib/IMPL/Web/Handler/TTView.pm --- a/Lib/IMPL/Web/Handler/TTView.pm Wed Oct 17 17:41:29 2012 +0400 +++ b/Lib/IMPL/Web/Handler/TTView.pm Thu Oct 18 04:49:55 2012 +0400 @@ -6,7 +6,9 @@ use IMPL::declare { require => { Factory => 'IMPL::Web::View::ObjectFactory', - HttpResponse => 'IMPL::Web::HttpResponse' + HttpResponse => 'IMPL::Web::HttpResponse', + Loader => 'IMPL::Code::Loader', + ViewResult => '-IMPL::Web::ViewResult' }, base => [ 'IMPL::Object' => undef, @@ -36,20 +38,27 @@ my ( $this, $action, $next ) = @_; my $result = $next ? $next->($action) : undef; + + my ($model,$view); + if( ref $result and eval { $result->isa(ViewResult) } ) { + $model = $result->model; + $view = $result; + } else { + $model = $result; + $view = ViewResult->new(model => $model); + } + my $vars = { - model => $result, + view => $view, + model => $model, action => $action, app => $action->application, ImportClass => sub { my $class = shift; - my $module = $class; - - $module =~ s/::/\//g; - $module .= ".pm"; - - require $module; + $class = Loader->safe->Require($class); + return Factory->new($class); } }; @@ -61,7 +70,7 @@ return HttpResponse->new( type => $this->contentType, charset => $this->contentCharset, - body => $doc->Render($vars) + body => $doc->Render() ); } diff -r abc7c26bf615 -r f48a1a9f4fa2 Lib/IMPL/Web/UnauthorizedException.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/IMPL/Web/UnauthorizedException.pm Thu Oct 18 04:49:55 2012 +0400 @@ -0,0 +1,24 @@ +package IMPL::Web::UnauthorizedException; +use strict; + +use IMPL::declare { + base => { + 'IMPL::Web::Exception' => '@_' + } +}; + +sub status { + "401 Unauthorized" +} + +1; + +__END__ + +=pod + +=head1 NAME + +C - запрос требует идентификации пользователя. + +=cut \ No newline at end of file diff -r abc7c26bf615 -r f48a1a9f4fa2 Lib/IMPL/Web/View/TTControl.pm --- a/Lib/IMPL/Web/View/TTControl.pm Wed Oct 17 17:41:29 2012 +0400 +++ b/Lib/IMPL/Web/View/TTControl.pm Thu Oct 18 04:49:55 2012 +0400 @@ -2,6 +2,8 @@ use strict; use IMPL::Const qw(:prop); +use IMPL::lang qw(:hash); +use Scalar::Util qw(blessed); use IMPL::declare { require => { TTContext => 'Template::Context', @@ -10,7 +12,7 @@ OperationException => '-IMPL::InvalidOperationException' }, base => [ - 'IMPL::Object' => '@_' + 'IMPL::Object' => undef ], props => [ id => PROP_RO, @@ -30,6 +32,7 @@ } our $AutoloadRegex = qr/^[a-z]/; +our @REFLECT_META = qw(title layout); sub CTOR { my ($this,$name,$template,$context,$refProps) = @_; @@ -44,11 +47,20 @@ $this->name($name); $this->attributes({}); - if (ref $refProps eq 'HASH') { - while (my($key,$value) = each %$refProps) { - $this->SetAttribute($key,$value); + my %attrs; + + foreach my $meta ( @REFLECT_META ) { + next if $meta =~ /^_/; + if( my $value = $template->$meta() ) { + $attrs{$meta} = $value; } } + + hashApply(\%attrs,$refProps) if ref $refProps eq 'HASH'; + + while (my($key,$value) = each %attrs) { + $this->SetAttribute($key,$value); + } } sub InitInstance { @@ -94,7 +106,7 @@ $args = {} unless ref $args eq 'HASH'; if(my $body = $this->GetRenderBlock ) { - return $this->context->include( $body, { %$args, this => $this, template => $this->template, document => $this->document } ); + return $this->context->include( $body, { %$args, this => $this, template => $this->template } ); } else { return ""; } @@ -109,6 +121,8 @@ if ($method =~ /$AutoloadRegex/) { my $this = shift; + + die OperationException->new("can't invoke method '$method' on an unblessed reference") unless blessed $this; return @_ ? $this->SetAttribute($method,@_) : $this->GetAttribute($method); } else { diff -r abc7c26bf615 -r f48a1a9f4fa2 Lib/IMPL/Web/View/TTDocument.pm --- a/Lib/IMPL/Web/View/TTDocument.pm Wed Oct 17 17:41:29 2012 +0400 +++ b/Lib/IMPL/Web/View/TTDocument.pm Thu Oct 18 04:49:55 2012 +0400 @@ -3,6 +3,7 @@ use Scalar::Util qw(weaken); use IMPL::Const qw(:prop); +use IMPL::lang qw(:hash); use IMPL::declare { require => { @@ -23,6 +24,7 @@ opts => PROP_RO, loader => PROP_RW, controls => PROP_RO, + creationArgs => PROP_RO, # store the stash separately to make require() method to work correctly # even when a stash of the context is modified during the processing @@ -44,17 +46,20 @@ $this->opts($refOpts); $this->stash($this->context->stash); + $this->creationArgs($vars); my $self = $this; weaken($self); - $this->templateVars('require', sub { + $this->templateVars(require => sub { my $doc = $self; die new IMPL::Exception("A document is destroyed or invalid") unless $doc; $doc->RequireControl(@_); }); - $this->templateVars('document', sub { $self } ); + $this->templateVars(context => $vars); + + $this->templateVars(document => sub { $self } ); $this->InitInstance($vars); } @@ -114,23 +119,23 @@ sub Render { my ($this,$args) = @_; - my $output; + $args ||= {}; + + my $newArgs = hashMerge($this->creationArgs, $args); if ($this->layout) { - $output = $this->context->include( + return $this->context->include( $this->loader->layout($this->layout), { - %{$args || {}}, - content => sub { $this->RenderContent($args); }, + %{$newArgs}, + content => sub { $this->RenderContent($newArgs); }, this => $this, template => $this->template } ); } else { - return $this->RenderContent($args); + return $this->RenderContent($newArgs); } - - return $output; } sub RenderContent { diff -r abc7c26bf615 -r f48a1a9f4fa2 Lib/IMPL/Web/ViewResult.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/IMPL/Web/ViewResult.pm Thu Oct 18 04:49:55 2012 +0400 @@ -0,0 +1,16 @@ +package IMPL::Web::ViewResult; +use strict; + +use IMPL::Const qw(:prop); + +use IMPL::declare { + base => [ + 'IMPL::Object' => undef, + 'IMPL::Object::Autofill' => '@_' + ], + props => [ + model => PROP_RW + ] +}; + +1; \ No newline at end of file diff -r abc7c26bf615 -r f48a1a9f4fa2 Lib/IMPL/lang.pm --- a/Lib/IMPL/lang.pm Wed Oct 17 17:41:29 2012 +0400 +++ b/Lib/IMPL/lang.pm Thu Oct 18 04:49:55 2012 +0400 @@ -160,6 +160,8 @@ sub hashApply { my ($target,$diff) = @_; + return $target unless ref $diff eq 'HASH'; + while ( my ($key,$value) = each %$diff) { $key =~ /^(\+|-)?(.*)$/; my $op = $1 || '+';