Mercurial > pub > Impl
view Lib/IMPL/Web/View/TTDocument.pm @ 191:78a18a2b6266
IMPL::Web::View improvements (unstable)
author | cin |
---|---|
date | Thu, 05 Apr 2012 17:51:51 +0400 |
parents | cd1ff7029a63 |
children | a9faf883cdce |
line wrap: on
line source
package IMPL::Web::View::TTDocument; use strict; use IMPL::lang qw(:declare :constants); use IMPL::DOM::Property qw(_dom); use IMPL::Web::View::TTFactory(); use IMPL::Web::View::TTControl(); use Scalar::Util qw(weaken); use parent qw( IMPL::DOM::Document IMPL::Web::View::TTControl ); BEGIN { public _dom property layout => PROP_ALL; public property opts => PROP_GET | PROP_OWNERSET; public property loader => PROP_GET | PROP_OWNERSET; public property controls => PROP_GET | PROP_OWNERSET; # store the stash separately to make require() method to work correctly # even when a stash of the context is modified during the processing public property stash => PROP_GET | PROP_OWNERSET; } sub CTOR { my ($this,$template,$refOpts,%args) = @_; $this->controls({}); $this->loader($args{loader}) if $args{loader}; $this->layout( $template->layout ) unless $this->layout; $this->opts($refOpts); $this->stash($this->context->stash); my $self = $this; weaken($self); $this->templateVars('require', sub { my $doc = $self; die new IMPL::Exception("A document is destroyed or invalid") unless $doc; $doc->require(@_); }); $this->templateVars('document', sub { $self } ); $this->InitInstance(); } our %CTOR = ( 'IMPL::Web::View::TTControl' => sub { 'document', $_[0], # template new Template::Context($_[1]) # context }, 'IMPL::DOM::Document' => sub { nodeName => 'document' } ); sub templateVars { my $this = shift; my $name = shift; if (@_) { return $this->stash->set($name, shift); } else { return $this->stash->get($name); } } sub require { my ($this, $control) = @_; if (my $factory = $this->controls->{$control}) { return $factory; } else { my $path = $control; if ( my $template = $this->loader->template($path) ) { my $opts = { %{$this->loader->options} }; $opts->{STASH} = $this->loader->context->stash->clone(); my $ctx = new Template::Context($opts); $factory = new IMPL::Web::View::TTFactory( typeof IMPL::Web::View::TTControl, $template, $ctx, $opts ); my @parts = split(/\/+/,$control); $this->controls->{$control} = $factory; return $factory; } else { die new IMPL::KeyNotFoundException($control); } } } sub renderBlock { $_[0]->template; } sub Render { my ($this,$args) = @_; my $output; if ($this->layout) { $output = $this->context->include( $this->loader->template($this->layout), { content => sub { $output ||= $this->RenderContent($args); } } ); } else { return $this->RenderContent($args); } return $output; } sub RenderContent { my $this = shift; return $this->SUPER::Render(@_); } 1; __END__ =pod =head1 NAME C<IMPL::Web::View::TTDocument> - документ для построения HTML страницы на основе шаблонов TT. =head1 SYNOPSIS =begin code use IMPL::Web::View::TTDocument(); my $doc = new IMPL::Wbe::View::TTDocument($template,$ttOptions); return $doc->Render(); =end code Однако, более предпочтительный способ использовать C<IMPL::Web::View::TTLoader>. =head1 DESCRIPTION Документ для представления данных. Документы представляют собой иерархически организованные данные, элементами данного документа являются данные для отображения, такие как =over =item * Объекты из БД =item * Навигационные цепочки =item * Меню и т.п. =back Скприт шаблона формирует структуру документа, затем сформированная структура форматируется в готовый документ. Процесс преобразования объектной модели в готовый документ может быть выполнена как вручную, так и при помощи вспомогательного шаблона - обертки. Если у шаблона документа указан C<layout> в метаданных, то он будет использован как шаблон для форматирования объектной модели, вывод самого шаблона будет проигнорирован. Если обертка не задана, то результатом будет вывод самого скрипта шаблона. =head2 Порядок обработки документа =over =item 1 Создается документ при помощи метода C<TTLoader::document()> =item 1 При создании документа (в конструкторе), происходит выполнение блока C<CTOR> =item 1 При вызове метода C<TTDocument::Render()> устанавливаются переменные C<this>, C<document> и шаблон обрабатывается при помощи метода C<process()> контекста документа. =back =head2 Загрузка элемента управления =over =item 1 C<require('my/org/input')> =item 1 Загружает шаблон C<my/org/input.tt> =item 1 Создает фабрику элементов управления с собственным контекстом, унаследованным от контекст документа. =item 1 Выполняет шаблон в пространстве имен фабрики =back =head2 Создание элемента управления =over =item 1 C<< my.org.input.new('login') >> =item 1 Если это первый элемент управления, то выполняетя статический конструктор в контексте фабрики =item 1 Создается новый дочерний контекст к контексту фабрики =item 1 Создается экземпляр элемента управления =item 1 Выполняется блок конструктора в контексте элемента управления, параметр C<this> имеет значение нового экземпляра элемента управления =back =head1 MEMBERS =over =item C<CTOR($template, %options)> Создает экземпляр документа с указанным шаблоном и параметрами, параметры =back =cut