Mercurial > pub > Impl
diff lib/IMPL/DOM/Transform/PostToDOM.pm @ 407:c6e90e02dd17 ref20150831
renamed Lib->lib
author | cin |
---|---|
date | Fri, 04 Sep 2015 19:40:23 +0300 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/IMPL/DOM/Transform/PostToDOM.pm Fri Sep 04 19:40:23 2015 +0300 @@ -0,0 +1,161 @@ +package IMPL::DOM::Transform::PostToDOM; +use strict; +use warnings; + +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + Builder => 'IMPL::DOM::Navigator::Builder' + }, + base => [ + 'IMPL::Transform' => sub { + -plain => \&TransformPlain, + HASH => \&TransformContainer, + CGI => \&TransformCGI, + CGIWrapper => \&TransformCGI + } + ], + props => [ + documentClass => PROP_RO, + documentSchema => PROP_RO, + prefix => PROP_RO, + _navi => PROP_RW, + errors => PROP_RW | PROP_LIST, + _schema => PROP_RW + ] +}; + +sub CTOR { + my ($this,$docClass,$docSchema,$prefix) = @_; + $docClass ||= 'IMPL::DOM::Document'; + + $this->_navi( + IMPL::DOM::Navigator::Builder->new( + $docClass, + $docSchema + ) + ); + $this->_schema($docSchema); + $this->prefix($prefix) if $prefix; +} + +sub TransformContainer { + my ($this,$data) = @_; + + my $navi = $this->_navi; + + foreach my $key ( + sort { $a->[1] cmp $b->[1] || $a->[2] <=> $b->[2]} + map [$_,/(\w+)(?:\[(\d+)\])?/], keys %$data + ){ + my $value = $data->{$key->[0]}; + my $node = $navi->NavigateCreate($key->[1]); + + $node->nodeProperty(instanceId => $key->[2]) if defined $key->[2]; + + $this->Transform($value); + + $navi->Back(); + } + + return $navi->Current; +} + +sub TransformPlain { + my ($this,$data) = @_; + + $this->_navi->Current->nodeValue( $this->_navi->inflateValue($data) ); +} + +sub TransformCGI { + my ($this,$query) = @_; + + my $data={}; + + my $prefix = $this->prefix; + my $delim = $this->delimiter; + + foreach my $param (grep index($_,$prefix) >= 0 , $query->param()) { + length (my $value = $query->param($param)) or next; + + my @parts = split /\//,$param; + + my $node = $data; + while ( my $part = shift @parts ) { + if (@parts) { + $node = ($node->{$part} ||= {}); + } else { + $node->{$part} = $value; + } + } + } + + if (keys %$data > 1) { + $data = { document => $data }; + } + + my $doc = $this->Transform($data); + $doc->nodeProperty( query => $query ); + $this->errors->Append( $this->_navi->BuildErrors); + $this->errors->Append( $this->_schema->Validate($doc)); + return $doc; +} + +1; + +__END__ + +=pod + +=head1 NAME + +C<IMPL::DOM::Transform::PostToDOM> - Преобразование объекта C<CGI> в DOM документ. + +=head1 SINOPSYS + +=begin code + + my $schema = IMPL::DOM::Schema->LoadSchema('Data/user.add.schema.xml'); + + my $transform = IMPL::DOM::Transform::PostToDOM->new( + undef, # default class + $schema, + $schema->selectSingleNode('ComplexNode')->name + ); + + my $doc = $transform->Transform( + CGI->new({ + 'user/login' => 'bob', + 'user/fullName' => 'Bob Marley', + 'user/password' => 'secret', + 'user/password_retype' => 'secret', + 'user/birthday' => '1978-12-17', + 'user/email[1]' => 'bob@marley.com', + 'user/email[2]' => 'bob.marley@google.com', + process => 1 + }) + ); + +=end code + +=head1 DESCRIPTION + +Используется для преобразования CGI запроса в DOM документ. Для этого используются параметры запроса, имена которых +начинаются со значение из свойства C<prefix>. + +Имена параметров интерпретируются следующим образом + +=over + +=item 1 Имя параметра составляется из имени узла, имен всех его родителей и указанием номера экземпляра. + +=item 2 Имена узлов могут содержать только буквы, цифры и символ _ + +=item 3 В случае когда узел может повторяться несколько раз, в квадратных скобках указывается +послеовательный номер экземпляра. + +=item 4 Имена параметров объединяются через символ '/' + +=back + +=cut