# HG changeset patch # User wizard # Date 1274395091 -14400 # Node ID 7b14e0122b79ab986e8405f37442bec74404d699 # Parent 0ed8e2541b1c40c92a603f4aaa9ab398fa3032a9 Updated PostToDOM transformation added selectSingleNode method to IMPL::DOM::Node Implemented FormWrapper in the Web::Application::ControllerUnit diff -r 0ed8e2541b1c -r 7b14e0122b79 Lib/IMPL/DOM/Navigator/Builder.pm --- a/Lib/IMPL/DOM/Navigator/Builder.pm Tue May 18 17:59:31 2010 +0400 +++ b/Lib/IMPL/DOM/Navigator/Builder.pm Fri May 21 02:38:11 2010 +0400 @@ -84,6 +84,8 @@ sub inflateValue { my ($this,$value,$node) = @_; + $node ||= $this->Current; + my $nodeSchema = $this->{$_schemaNavi}->Current; my $result = eval { $nodeSchema->inflateValue($value) }; diff -r 0ed8e2541b1c -r 7b14e0122b79 Lib/IMPL/DOM/Node.pm --- a/Lib/IMPL/DOM/Node.pm Tue May 18 17:59:31 2010 +0400 +++ b/Lib/IMPL/DOM/Node.pm Fri May 21 02:38:11 2010 +0400 @@ -202,6 +202,12 @@ return wantarray ? @set : \@set; } +sub selectSingleNode { + my $this = shift; + my @result = $this->selectNodes(@_); + return $result[0]; +} + sub selectNodesRef { my $this = shift; diff -r 0ed8e2541b1c -r 7b14e0122b79 Lib/IMPL/DOM/Transform/PostToDOM.pm --- a/Lib/IMPL/DOM/Transform/PostToDOM.pm Tue May 18 17:59:31 2010 +0400 +++ b/Lib/IMPL/DOM/Transform/PostToDOM.pm Fri May 21 02:38:11 2010 +0400 @@ -10,17 +10,22 @@ BEGIN { public property documentClass => prop_get | owner_set; public property documentSchema => prop_get | owner_set; + public property prefix => prop_get | owner_set; private property _navi => prop_all; + public property Errors => prop_all | prop_list; + private property _schema => prop_all; } our %CTOR = ( 'IMPL::Transform' => sub { - HASH => \&TransfromPostData + -plain => \&TransformPlain, + HASH => \&TransformContainer, + CGI => \&TransformCGI } ); sub CTOR { - my ($this,$docClass,$docSchema) = @_; + my ($this,$docClass,$docSchema,$prefix) = @_; $docClass ||= 'IMPL::DOM::Document'; $this->_navi( @@ -29,30 +34,60 @@ $docSchema ) ); + $this->_schema($docSchema); + $this->prefix($prefix) if $prefix; } -sub TransformPostData { +sub TransformContainer { my ($this,$data) = @_; my $navi = $this->_navi; - - my % - + while (my ($key,$value) = each %$data) { - # TODO: review - $navi->save; - my $node = $navi->Navigate(split /\//, $key); - $node->nodeValue($value); - $navi->resore; + + $navi->NavigateCreate($key); + + $this->Transform($value); + + $navi->Back(); } - return $navi->Document; + return $navi->Current; +} + +sub TransformPlain { + my ($this,$data) = @_; + + $this->_navi->Current->nodeValue( $this->_navi->inflateValue($data) ); } -sub - -sub TransformErrors { - return $_[0]->_navi->BuildErrors; +sub TransformCGI { + my ($this,$query) = @_; + + my $data={}; + + my $prefix = $this->prefix; + $prefix = qr/$prefix/; + + foreach my $param (grep $_=~/$prefix/, $query->param()) { + my $value = $query->param($param); + + my @parts = split /\//,$param; + + my $node = $data; + while ( my $part = shift @parts ) { + if (@parts) { + $node = ($node->{$part} ||= {}); + } else { + $node->{$part} = $value; + } + } + } + + my $doc = $this->Transform($data); + $this->Errors->Append( $this->_navi->BuildErrors); + $this->Errors->Append( $this->_schema->Validate($doc)); + return $doc; } 1; diff -r 0ed8e2541b1c -r 7b14e0122b79 Lib/IMPL/DOM/XMLReader.pm --- a/Lib/IMPL/DOM/XMLReader.pm Tue May 18 17:59:31 2010 +0400 +++ b/Lib/IMPL/DOM/XMLReader.pm Fri May 21 02:38:11 2010 +0400 @@ -57,7 +57,7 @@ sub _OnEnd { my ($this,$element) = @_; - $this->{$_current}->nodeValue($this->Navigator->inflateValue( $this->{$_text}, $this->{$_current} ) ) if length $this->{$_text}; + $this->{$_current}->nodeValue($this->Navigator->inflateValue( $this->{$_text} ) ) if length $this->{$_text}; $this->{$_text} = pop @{$this->{$_textHistory}}; $this->{$_current} = $this->Navigator->Back; } diff -r 0ed8e2541b1c -r 7b14e0122b79 Lib/IMPL/Web/Application/ControllerUnit.pm --- a/Lib/IMPL/Web/Application/ControllerUnit.pm Tue May 18 17:59:31 2010 +0400 +++ b/Lib/IMPL/Web/Application/ControllerUnit.pm Fri May 21 02:38:11 2010 +0400 @@ -5,6 +5,8 @@ use IMPL::Class::Property; use IMPL::DOM::Transform::PostToDOM; use IMPL::DOM::Schema; +use Class::Inspector; +use File::Spec; use constant { CONTROLLER_METHODS => 'controller_methods', @@ -22,6 +24,8 @@ public property formErrors => prop_get | owner_set; } +__PACKAGE__->class_data(CONTROLLER_METHODS,{}); + sub CTOR { my ($this,$action,$args) = @_; @@ -56,7 +60,9 @@ } sub transactions { + my ($self,@names) = @_; + $self->class_data(CONTROLLER_METHODS)->{$_} = {} foreach @names; } sub InvokeAction { @@ -81,17 +87,49 @@ } sub FormWrapper { - my ($this,$method,$action,$methodInfo) = @_; + my ($self,$method,$action,$methodInfo) = @_; + + my $schema = $self->loadSchema($methodInfo->{schema}); + + my $process = $action->query->param('process') || 0; + my $form = $methodInfo->{form} + || $action->query->param('form') + || $schema->selectSingleNode('ComplexNode')->name + or die new IMPL::Exception('No situable form name could be determined',$self,$method); - my $schema = $this->loadSchema($methodInfo->{schema}); + my %result; - my $process = $this->query->param('process') || 0; + my $transform = IMPL::DOM::Transform::PostToDOM->new( + undef, + $schema, + $form + ); + + $result{formSchema} = $schema; + $result{formData} = $transform->Transform($self->query); - + if ($process) { + $result{formErrors} = $transform->Errors->as_list; + if ($transform->Errors->Count) { + $result{state} = STATE_INVALID; + } else { + $result{state} = STATE_CORRECT; + my $unit = $self->new($action,\%result); + $result{result} = $unit->method(); + } + } else { + $result{state} = STATE_NEW; + } - my %result = ( - - ); + return \%result; +} + +sub loadSchema { + my ($self,$name) = @_; + + my ($vol,$dir,$file) = File::Spec->splitpath( Class::Inspector->resolved_filename(ref $self || $self) ); + + return IMPL::DOM::Schema->LoadSchema(File::Spec->catfile($vol,$dir,$name)); } 1; @@ -106,9 +144,8 @@ =head1 DESCRIPTION -Классы, наследуемые от данного класса используются для выполнения транзакций, которые приходят -через контроллер запросов. Как правило один класс представляет собой пакет транзакций, каждая -из которых является независимой от другой. +Классы, наследуемые от данного класса называется пакетом транзакций. Часть методов в таком классе +объявляются как транзакции при помощи методов C, C
. Перед выполнением транзакции создается экземпляр объекта, в рамках которого будет выполнена транзакция. Для этого вызывается метод C, который создает/восстанавливает контекст