view Lib/IMPL/Web/View/TTLoader.pm @ 345:72799d1211c5

sync
author cin
date Fri, 27 Sep 2013 16:28:27 +0400
parents 9bdccdf1f50b
children
line wrap: on
line source

package IMPL::Web::View::TTLoader;
use strict;

use Template::Constants qw(:status);

use File::Spec();
use IMPL::Const qw(:prop);
use Scalar::Util qw(weaken);

use IMPL::declare {
    require => {
        Provider => 'Template::Provider',
        Context => 'IMPL::Web::View::TTContext',
        TTRegistry => 'IMPL::Web::View::TTRegistry',
        TTFactory => 'IMPL::Web::View::TTFactory',
        TTDocument => '-IMPL::Web::View::TTDocument',
        Exception => 'IMPL::Exception',
        ArgumentException => '-IMPL::InvalidArgumentException',
        KeyNotFoundException => '-IMPL::KeyNotFoundException'
    },
    base => [
        'IMPL::Object' => undef,
        'IMPL::Object::Serializable' => undef
    ],
    props => [
        provider => PROP_RO,
        context => PROP_RO,
        registry => PROP_RO,
        _globals => PROP_RW
    ]
};

sub save {
	my ($this,$context) = @_;
	
	$context->AddVar($_, $this->$_()) for qw(options provider context ext layoutBase);
}

sub restore {
	my ($class,$data,$surrogate) = @_;
	
	my %params = @$data;
	
	my $refOpts = delete $params{options};
	
	if ($surrogate){
		$surrogate->callCTOR($refOpts,%params);
	} else {
		$surrogate = $class->new($refOpts,%params);
	}
	return $surrogate;
}

sub CTOR {
    my ($this,$refOpts,%args) = @_;
    
    $refOpts ||= {};
    
    # to aviod cyclic references we need to do a copy of $refOpts
    $refOpts->{LOAD_TEMPLATES} = Provider->new( { %$refOpts } );
    
    my $ctx = Context->new( { %$refOpts } );
    $this->context($ctx);
    
    $this->_globals(ref $args{globals} eq 'HASH' ? $args{globals} : {});
    
    $ctx->tt_ext($args{ext} || '.tt');
    
    $this->registry(TTRegitry->new($ctx));
    
    weaken($ctx); 
    weaken($this);
    $ctx->stash->update({
    	require => sub {
    		my ($modname) = @_;
    		
    		my @inc;
            push @inc, $ctx->base if $ctx->base;

            my $ti = $ctx->find_template($name,@inc);
            
    		require $this->registry->Require($ti);
    	},
    	inclue => sub {
    		my ($name) = @_;
    		
    		my @inc;
    		push @inc, $ctx->base if $ctx->base;

            my $ti = $ctx->find_template($name,@inc);
            
            return $ctx->include($ti->{template}, {base => $ti->{base}} );
    	}
    });
    
    
}

sub document {
    my ($this,$name,$vars) = @_;
    
    $vars ||= {};
    
    my $factory = $this->registry->Require($name);
    
    return $factory->new(hashMerge($vars, $this->_globals));
}

1;

__END__

=pod

=head1 NAME

C<IMPL::Web::View::TTLoader> - предоставляет глобальный контекст для загрузки шаблонов

=head1 SYNOPSIS

=begin code

use IMPL::Web::View::TTLoader();

my $loader = new IMPL::Web::View::TTLoader(
    {
        INCLUDE_PATH => [
            '/my/app/tt',
            '/my/app/tt/lib'
        ]
    },
    ext => '.tt',
    globals => {
    	images => '//cdn.mysite.net/static/images'
    }
        
);

my $doc = $loader->document('index');

my $html = $doc->Render();

=end code

=head1 DESCRIPTION

Провайдер для загрузки шаблонов и документов. Имеет собственное пространство
имен, контекст выполнения шаблонов. Контект загрузчика инициализируется
шаблоном, в котором определяются глобальные переменные, которые будут доступны
в документах, однако их изменения будут локализованы.

Инициализация контекста провайдера происходит при первой загрузке любого
документа.

=head1 MEMBERS

=head2 C<CTOR($options,%args)>

=over

=item * C<$options>

Параметры контекста загрузчика, контексты документов и элементов управления
также унаследуют эти свойства. Напрямую передаются в конструктор
C<Template::Context>.

=item * C<%args>

Именованные параметы загрузчика.

=over

=item * C<ext>

Расширение, которое будет добавляться к именам шаблонов и документов (если оно
не будет указано явно).

=item * C<initializer>

Имя шаблона, который будет использован для инициализации контекста.

=item * C<globals>

Глобальные переменнын, которые будут переданы в контекст.

=item * C<layoutBase>

Путь к шаблонам для оформления документов. Каждый документ может задавать свой
C<layout> указанный в его C<META> блоке или конструкторе.
См. C<IMPL::View::TTDocument>.

=back

=back

=head2 C<document($docName)>

Загружает документ с именем C<$docName>. При необходимости к нему будет
добавлено расширение, указанное в свойстве C<ext>. Это единственно полезный
метод провайдера.

=cut