237
|
1 package IMPL::DOM::Transform::QueryToDOM;
|
|
2 use strict;
|
|
3
|
|
4 use IMPL::Const qw(:prop);
|
|
5 use IMPL::declare {
|
|
6 base => [
|
|
7 'IMPL::DOM::Transform::ObjectToDOM' => '@_'
|
|
8 ],
|
|
9 props => [
|
|
10 prefix => PROP_RO,
|
238
|
11 delimiter => PROP_RO
|
237
|
12 ]
|
|
13 };
|
|
14
|
|
15 sub CTOR {
|
|
16 my ($this) = @_;
|
|
17
|
264
|
18 $this->templates->{'CGI'} = 'TransformCGI';
|
244
|
19
|
238
|
20 $this->delimiter('[.]');
|
|
21 $this->prefix('');
|
237
|
22 }
|
|
23
|
250
|
24 # inflate simple properties
|
|
25 sub TransformPlain {
|
|
26 my ($this,$data) = @_;
|
|
27
|
|
28 $this->currentNode->nodeProperty( rawValue => $data );
|
|
29 $this->currentNode->nodeValue( $this->inflateNodeValue($data) );
|
|
30 return $this->currentNode;
|
|
31 }
|
|
32
|
|
33 # do not store complex data as node values
|
|
34 sub StoreObject {
|
|
35 my ($this,$node,$data) = @_;
|
|
36
|
|
37 return $node;
|
|
38 }
|
|
39
|
264
|
40 #TODO: support a.b[0][1].c[1]
|
|
41
|
237
|
42 sub TransformCGI {
|
|
43 my ($this,$query) = @_;
|
|
44
|
|
45 my $data={};
|
|
46
|
|
47 my $prefix = $this->prefix;
|
|
48 my $delim = $this->delimiter;
|
|
49
|
|
50 foreach my $param (grep index($_,$prefix) >= 0 , $query->param()) {
|
244
|
51
|
|
52 my @value = grep length($_), $query->param($param) or next;
|
237
|
53
|
238
|
54 my @parts = split /$delim/,$param;
|
237
|
55
|
|
56 my $node = $data;
|
|
57 while ( my $part = shift @parts ) {
|
238
|
58 if (my ($name,$index) = ($part =~ m/^(\w+)(?:\[(\d+)\])?$/) ) {
|
|
59 if (@parts) {
|
|
60 if(defined $index) {
|
|
61 $node = ($node->{$name}[$index] ||= {});
|
|
62 } else {
|
|
63 $node = ($node->{$name} ||= {});
|
|
64 }
|
|
65 } else {
|
|
66 if(defined $index) {
|
244
|
67 $node->{$name}[$index] = (@value == 1 ? $value[0] : \@value);
|
238
|
68 } else {
|
244
|
69 $node->{$name} = (@value == 1 ? $value[0] : \@value);
|
238
|
70 }
|
|
71 }
|
237
|
72 }
|
|
73 }
|
|
74 }
|
|
75
|
|
76 return $this->Transform($data);
|
238
|
77 }
|
|
78
|
264
|
79 1;
|
|
80
|
|
81 __END__
|
|
82
|
|
83 =pod
|
|
84
|
|
85 =head1 NAME
|
|
86
|
|
87 C<IMPL::DOM::Transform::QueryToDOM> - преобразование CGI запроса в DOM документ.
|
|
88
|
|
89 =head1 SYNOPSIS
|
|
90
|
|
91 =begin code
|
|
92
|
|
93 use CGI();
|
|
94 use IMPL::require {
|
|
95 Schema => 'IMPL::DOM::Schema',
|
|
96 Config => 'IMPL::Config',
|
|
97 QueryToDOM => 'IMPL::DOM::Transform::QueryToDOM'
|
|
98 }
|
|
99
|
|
100 my $q = CGI->new();
|
|
101
|
|
102 my $schema = Schema->LoadSchema(Config->AppBase('schemas','person.xml'));
|
|
103 my $transorm = QueryToDOM->new('edit', $schema);
|
|
104
|
|
105 my $form = $transform->Transform($q);
|
|
106
|
|
107 my @errors;
|
|
108
|
|
109 push @errors, $transform->buildErrors;
|
|
110 push @errors, $schema->Validate($doc);
|
|
111
|
|
112
|
|
113 =end code
|
|
114
|
|
115 =head1 DESCRIPTION
|
|
116
|
|
117 Наследует C<IMPL::DOM::Transform::ObjectToDOM>. Добавляет метод
|
|
118 C<TransformCGI> который применятеся к объектам типа C<CGI> (и производных).
|
|
119
|
|
120 Запрос C<CGI> сначала приводится к хешу, затем полученный хеш преобразуется
|
|
121 в DOM документ при помощи вызова метода C<Transform>.
|
|
122
|
|
123 Для этого выбираются параметры запроса, затем, имя каждого параметра
|
|
124 рассматривается в виде пути к свойству, создается структура из хешей и массивов
|
|
125 в которую по указанному пути кладется значение.
|
|
126
|
|
127 Если параметр имеет несколько значений, значит свойство является массивом.
|
|
128
|
|
129 Также изменено поведение некоторых методов преобразования.
|
|
130
|
|
131 =over
|
|
132
|
|
133 =item * C<TransformPlain($value)>
|
|
134
|
|
135 Преобразование для простого значения свойства. Посокльку в запросе передаются
|
|
136 строковые значения, а схема документа может предполпгать другие типы, при
|
|
137 преобразовании значения параметра из запроса к значению узла используется
|
|
138 метод C<< $this->inflateNodeValue($value) >>, также помимо значения
|
|
139 C<< $this->currentNode->nodeValue >> задается атрибут
|
|
140 C<< $this->currentNode->nodeProperty( rawValue => $value) >>, для того, чтобы
|
|
141 была возможность получить оригинальное значение параметра запроса (например,
|
|
142 в случае когда его формат был не верным и C<nodeValue> будет C<undef>).
|
|
143
|
|
144 =item * C<StoreObject($node,$object)>
|
|
145
|
|
146 Данный метод вызывается если текущий узел (переданный в параметре C<$node>)
|
|
147 предполагает простое значение, однако в запросе для него было передано сложное
|
|
148 содержимое. Данная реализация просто игнорирует переданный объект C<$object>
|
|
149 и возвращает C<$node> без изменений.
|
|
150
|
|
151 =back
|
|
152
|
|
153 =head1 MEMBERS
|
|
154
|
|
155 =head2 C<[get]delimiter>
|
|
156
|
|
157 REGEX. Разделитель свойств в имени параметра, по-умолчанию C<'[.]'>
|
|
158
|
|
159 =head2 C<[get]prefix>
|
|
160
|
|
161 Строка, префикс имен параметров, которые участвуют в формировании документа.
|
|
162 По-умолчанию пусто.
|
|
163
|
|
164 =cut |