49
|
1 package DOM::Page;
|
|
2 use Common;
|
|
3 use Template::Context;
|
|
4 use strict;
|
|
5
|
|
6 our @ISA = qw(Object);
|
|
7 our $AUTOLOAD;
|
|
8
|
|
9 BEGIN {
|
|
10 DeclareProperty(Title => ACCESS_ALL);
|
|
11 DeclareProperty(NavChain => ACCESS_READ);
|
|
12 DeclareProperty(Menus => ACCESS_READ);
|
|
13 DeclareProperty(Properties => ACCESS_READ);
|
|
14 DeclareProperty(Template => ACCESS_READ);
|
|
15 DeclareProperty(TemplatesProvider => ACCESS_NONE);
|
|
16 DeclareProperty(Site => ACCESS_READ);
|
|
17 }
|
|
18
|
|
19 sub CTOR {
|
|
20 my ($this,%args) = @_;
|
|
21 $this->{$Site} = $args{'Site'};
|
|
22 $this->{$TemplatesProvider} = $args{'TemplatesProvider'};
|
|
23 $this->{$Properties} = $args{'Properties'} || {};
|
|
24 $this->{$Title} = $args{'Template'}->Title() || $args{'Properties'}->{'Title'};
|
|
25 $this->{$Template} = $args{'Template'};
|
|
26 $this->{$NavChain} = $args{'NavChain'};
|
|
27 $this->{$Menus} = $args{'Menus'};
|
|
28 }
|
|
29
|
|
30 sub Render {
|
|
31 my ($this,$hOut) = @_;
|
|
32
|
|
33 my $context = new Template::Context({
|
|
34 VARIABLES => $this->{$Site}->Objects(),
|
|
35 LOAD_TEMPLATES => $this->{$TemplatesProvider}
|
|
36 });
|
|
37
|
|
38 print $hOut $this->{$Template}->process($context);
|
|
39 }
|
|
40
|
|
41 sub Dispose {
|
|
42 my ($this) = @_;
|
|
43
|
|
44 undef %$this;
|
|
45
|
|
46 $this->SUPER::Dispose;
|
|
47 }
|
|
48
|
|
49 sub Container {
|
|
50 my ($this) = @_;
|
|
51 my $nav = $this->{$NavChain};
|
|
52 return $nav->[@{$nav}-1];
|
|
53 }
|
|
54
|
|
55 sub AUTOLOAD {
|
|
56 my $this = shift;
|
|
57
|
|
58 my $name = $AUTOLOAD;
|
|
59 $name =~ s/.*://;
|
|
60
|
|
61 return $this->{$Properties}->{$name};
|
|
62 }
|
|
63
|
|
64 =pod
|
|
65 Меню
|
|
66 [
|
|
67 Элемент меню
|
|
68 {
|
|
69 Key => Ключ пункта меню, для быстрого обращения к элементу и слиянии меню
|
|
70 Name => Имя пункта меню, которое будет видель пользователь
|
|
71 Expand => флаг того, что меню выбрано
|
|
72 Value => {[ элемент меню ...] | что-то еще, обычно урл}
|
|
73 }
|
|
74 ]
|
|
75 =cut
|
|
76
|
|
77 package DOM::PageMenu;
|
|
78 use Common;
|
|
79
|
|
80 our @ISA = qw(Object);
|
|
81
|
|
82 BEGIN {
|
|
83 DeclareProperty('Items'); # массив
|
|
84 DeclareProperty('Keys'); # ключи для пунктов меню, если таковые имеются
|
|
85 }
|
|
86
|
|
87 sub CTOR {
|
|
88 my ($this,%args) = @_;
|
|
89 if (ref $args{'DATA'} eq 'ARRAY') {
|
|
90 foreach my $item (@{$args{'DATA'}}) {
|
|
91 if (ref $item eq 'HASH') {
|
|
92 $this->Append($item->{'Name'},_ProcessData($item->{'Value'}), Expand => $item->{'Expand'}, Key => $item->{'Key'}, Url => $item->{'Url'});
|
|
93 } elsif (ref $item eq 'ARRAY') {
|
|
94 $this->Append($item->[0],_ProcessData($item->[1]), Expand => $item->[2], Key => $item->[3], Url => $item->[4]);
|
|
95 }
|
|
96 }
|
|
97 }
|
|
98 }
|
|
99
|
|
100 sub Item {
|
|
101 my ($this,$index) = @_;
|
|
102
|
|
103 return $this->{$Items}[$index];
|
|
104 }
|
|
105
|
|
106 sub ItemByKey {
|
|
107 my ($this,$key) = @_;
|
|
108
|
|
109 return $this->{$Keys}->{$key};
|
|
110 }
|
|
111
|
|
112 sub InsertBefore {
|
|
113 my ($this,$index,$name,$data,%options) = @_;
|
|
114
|
|
115 my $item = {Name => $name, Value => _ProcessData($data), %options};
|
|
116 splice @{$this->{$Items}},$index,0,$item;
|
|
117
|
|
118 if ($options{'Key'}) {
|
|
119 $this->{$Keys}->{$options{'Key'}} = $item;
|
|
120 }
|
|
121 }
|
|
122
|
|
123 sub Append {
|
|
124 my ($this,$name,$data,%options) = @_;
|
|
125
|
|
126 my $item = {Name => $name, Value => _ProcessData($data), %options};
|
|
127
|
|
128 push @{$this->{$Items}},$item;
|
|
129
|
|
130 if ($options{'Key'}) {
|
|
131 $this->{$Keys}->{$options{'Key'}} = $item;
|
|
132 }
|
|
133 }
|
|
134
|
|
135 sub SubMenu {
|
|
136 my ($this,$path) = @_;
|
|
137 my $item = $this;
|
|
138 foreach my $key ( split /\/+/,$path ) {
|
|
139 $item = $item->{$Keys}->{$key};
|
|
140 if (not $item ) {
|
|
141 die new Exception('Item does\'t exist', $path, $key);
|
|
142 }
|
|
143 $item = $item->{Value};
|
|
144 if (not UNIVERSAL::isa($item,'DOM::PageMenu')) {
|
|
145 $item = ($this->{$Keys}->{$key}->{Value} = new DOM::PageMenu());
|
|
146 }
|
|
147 }
|
|
148
|
|
149 return $item;
|
|
150 }
|
|
151
|
|
152 sub Dump {
|
|
153 use Data::Dumper;
|
|
154
|
|
155 return Dumper(shift);
|
|
156 }
|
|
157
|
|
158 sub AppendItem {
|
|
159 my ($this,$item) = @_;
|
|
160
|
|
161 push @{$this->{$Items}},$item;
|
|
162
|
|
163 if ($item->{'Key'}) {
|
|
164 $this->{$Keys}->{$item->{'Key'}} = $item;
|
|
165 }
|
|
166 }
|
|
167
|
|
168 sub RemoveAt {
|
|
169 my ($this,$index) = @_;
|
|
170
|
|
171 my $item = splice @{$this->{$Items}},$index,1;
|
|
172
|
|
173 if ($item->{'Key'}) {
|
|
174 delete $this->{$Keys}->{$item->{'Key'}};
|
|
175 }
|
|
176
|
|
177 return 1;
|
|
178 }
|
|
179
|
|
180 sub ItemsCount {
|
|
181 my $this = shift;
|
|
182 return scalar(@{$this->{$Items}});
|
|
183 }
|
|
184
|
|
185 sub Sort {
|
|
186 my $this = shift;
|
|
187
|
|
188 $this->{$Items} = \sort { $a->{'Name'} <=> $b->{'Name'} } @{$this->{$Items}};
|
|
189
|
|
190 return 1;
|
|
191 }
|
|
192
|
|
193 sub as_list {
|
|
194 my $this = shift;
|
|
195 return $this->{$Items} || [];
|
|
196 }
|
|
197
|
|
198 sub Merge {
|
|
199 my ($this,$that) = @_;
|
|
200
|
|
201 foreach my $itemThat ($that->Items) {
|
|
202 my $itemThis = $itemThat->{'Key'} ? $this->{$Keys}->{$itemThat->{'Key'}} : undef;
|
|
203 if ($itemThis) {
|
|
204 $this->MergeItems($itemThis,$itemThat);
|
|
205 } else {
|
|
206 $this->AppendItem($itemThat);
|
|
207 }
|
|
208 }
|
|
209 }
|
|
210
|
|
211 sub MergeItems {
|
|
212 my ($this,$itemLeft,$itemRight) = @_;
|
|
213
|
|
214 while (my ($prop,$value) = each %{$itemRight}) {
|
|
215 if ($prop eq 'Value') {
|
|
216 if (UNIVERSAL::isa($itemLeft->{$prop},__PACKAGE__) && UNIVERSAL::isa($value,__PACKAGE__)) {
|
|
217 $itemLeft->{$prop}->Merge($value);
|
|
218 } else {
|
|
219 $itemLeft->{$prop} = $value if defined $value;
|
|
220 }
|
|
221 } else {
|
|
222 $itemLeft->{$prop} = $value if defined $value;
|
|
223 }
|
|
224 }
|
|
225
|
|
226 return 1;
|
|
227 }
|
|
228
|
|
229 sub _ProcessData {
|
|
230 my $refData = shift;
|
|
231
|
|
232 if (ref $refData eq 'ARRAY') {
|
|
233 return new DOM::PageMenu(DATA => $refData);
|
|
234 } else {
|
|
235 return $refData;
|
|
236 }
|
|
237 }
|
|
238
|
|
239
|
|
240
|
|
241 1;
|