Mercurial > pub > Impl
view Lib/DOM/Page.pm @ 16:75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
author | Sergey |
---|---|
date | Tue, 08 Sep 2009 17:29:07 +0400 |
parents | 03e58a454b20 |
children | 16ada169ca75 |
line wrap: on
line source
package DOM::Page; use Common; use Template::Context; use strict; our @ISA = qw(Object); our $AUTOLOAD; BEGIN { DeclareProperty(Title => ACCESS_ALL); DeclareProperty(NavChain => ACCESS_READ); DeclareProperty(Menus => ACCESS_READ); DeclareProperty(Properties => ACCESS_READ); DeclareProperty(Template => ACCESS_READ); DeclareProperty(TemplatesProvider => ACCESS_NONE); DeclareProperty(Site => ACCESS_READ); } sub CTOR { my ($this,%args) = @_; $this->{$Site} = $args{'Site'}; $this->{$TemplatesProvider} = $args{'TemplatesProvider'}; $this->{$Properties} = $args{'Properties'} || {}; $this->{$Title} = $args{'Template'}->Title() || $args{'Properties'}->{'Title'}; $this->{$Template} = $args{'Template'}; $this->{$NavChain} = $args{'NavChain'}; $this->{$Menus} = $args{'Menus'}; } sub Render { my ($this,$hOut) = @_; my $context = new Template::Context({ VARIABLES => $this->{$Site}->Objects(), LOAD_TEMPLATES => $this->{$TemplatesProvider} }); print $hOut $this->{$Template}->process($context); } sub Dispose { my ($this) = @_; undef %$this; $this->SUPER::Dispose; } sub Container { my ($this) = @_; my $nav = $this->{$NavChain}; return $nav->[@{$nav}-1]; } sub AUTOLOAD { my $this = shift; my $name = $AUTOLOAD; $name =~ s/.*://; return $this->{$Properties}->{$name}; } =pod [ { Key => , Name => , Expand => , Value => {[ ...] | - , } } ] =cut package DOM::PageMenu; use Common; our @ISA = qw(Object); BEGIN { DeclareProperty('Items'); # DeclareProperty('Keys'); # , } sub CTOR { my ($this,%args) = @_; if (ref $args{'DATA'} eq 'ARRAY') { foreach my $item (@{$args{'DATA'}}) { if (ref $item eq 'HASH') { $this->Append($item->{'Name'},_ProcessData($item->{'Value'}), Expand => $item->{'Expand'}, Key => $item->{'Key'}, Url => $item->{'Url'}); } elsif (ref $item eq 'ARRAY') { $this->Append($item->[0],_ProcessData($item->[1]), Expand => $item->[2], Key => $item->[3], Url => $item->[4]); } } } } sub Item { my ($this,$index) = @_; return $this->{$Items}[$index]; } sub ItemByKey { my ($this,$key) = @_; return $this->{$Keys}->{$key}; } sub InsertBefore { my ($this,$index,$name,$data,%options) = @_; my $item = {Name => $name, Value => _ProcessData($data), %options}; splice @{$this->{$Items}},$index,0,$item; if ($options{'Key'}) { $this->{$Keys}->{$options{'Key'}} = $item; } } sub Append { my ($this,$name,$data,%options) = @_; my $item = {Name => $name, Value => _ProcessData($data), %options}; push @{$this->{$Items}},$item; if ($options{'Key'}) { $this->{$Keys}->{$options{'Key'}} = $item; } } sub SubMenu { my ($this,$path) = @_; my $item = $this; foreach my $key ( split /\/+/,$path ) { $item = $item->{$Keys}->{$key}; if (not $item ) { die new Exception('Item does\'t exist', $path, $key); } $item = $item->{Value}; if (not UNIVERSAL::isa($item,'DOM::PageMenu')) { $item = ($this->{$Keys}->{$key}->{Value} = new DOM::PageMenu()); } } return $item; } sub Dump { use Data::Dumper; return Dumper(shift); } sub AppendItem { my ($this,$item) = @_; push @{$this->{$Items}},$item; if ($item->{'Key'}) { $this->{$Keys}->{$item->{'Key'}} = $item; } } sub RemoveAt { my ($this,$index) = @_; my $item = splice @{$this->{$Items}},$index,1; if ($item->{'Key'}) { delete $this->{$Keys}->{$item->{'Key'}}; } return 1; } sub ItemsCount { my $this = shift; return scalar(@{$this->{$Items}}); } sub Sort { my $this = shift; $this->{$Items} = \sort { $a->{'Name'} <=> $b->{'Name'} } @{$this->{$Items}}; return 1; } sub as_list { my $this = shift; return $this->{$Items} || []; } sub Merge { my ($this,$that) = @_; foreach my $itemThat ($that->Items) { my $itemThis = $itemThat->{'Key'} ? $this->{$Keys}->{$itemThat->{'Key'}} : undef; if ($itemThis) { $this->MergeItems($itemThis,$itemThat); } else { $this->AppendItem($itemThat); } } } sub MergeItems { my ($this,$itemLeft,$itemRight) = @_; while (my ($prop,$value) = each %{$itemRight}) { if ($prop eq 'Value') { if (UNIVERSAL::isa($itemLeft->{$prop},__PACKAGE__) && UNIVERSAL::isa($value,__PACKAGE__)) { $itemLeft->{$prop}->Merge($value); } else { $itemLeft->{$prop} = $value if defined $value; } } else { $itemLeft->{$prop} = $value if defined $value; } } return 1; } sub _ProcessData { my $refData = shift; if (ref $refData eq 'ARRAY') { return new DOM::PageMenu(DATA => $refData); } else { return $refData; } } 1;