view Lib/IMPL/Web/View/TTLoader.pm @ 194:4d0e1962161c

Replaced tabs with spaces IMPL::Web::View - fixed document model, new features (control classes, document constructor parameters)
author cin
date Tue, 10 Apr 2012 20:08:29 +0400
parents ae8072f2f2a3
children 7a920771fd8e
line wrap: on
line source

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

use IMPL::lang qw(:declare :constants);

use Template::Provider();
use Template::Context();
use Template::Constants qw(:status);

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

use parent qw(
    IMPL::Object
);

BEGIN {
    public property options => PROP_ALL;
    public property provider => PROP_GET | PROP_OWNERSET;
    public property context => PROP_GET | PROP_OWNERSET;
    public property ext => PROP_ALL;
    
    public property isInitialized => PROP_GET | PROP_OWNERSET;
    public property initializer => PROP_GET | PROP_OWNERSET;
    
    private property _globals => PROP_ALL;
}

sub CTOR {
    my ($this,$refOpts,%args) = @_;
    
    $refOpts ||= {};
    
    $this->ext($args{ext}) if $args{ext};
    $this->initializer($args{initializer}) if $args{initializer};
    $this->_globals(ref $args{globals} eq 'HASH' ? $args{globals} : {});
    
    $this->options($refOpts);
    
    # to aviod cyclic references we need to do a copy of $refOpts
    $refOpts->{LOAD_TEMPLATES} = $this->provider(new Template::Provider( { %$refOpts } ));
    
    $this->context(new Template::Context($refOpts));
}

sub document {
    my ($this,$name,$vars) = @_;
    
    my $tt = $this->template($name);
        
    $this->_init();
    
    my $opts = { %{ $this->options } };
    
    $opts->{STASH} = $this->context->stash->clone();
    $opts->{LOAD_TEMPLATES} = $this->provider;
    
    return new IMPL::Web::View::TTDocument( $tt, $opts, $this, $vars );
}

sub template {
    my ($this,$name) = @_;
    
    $name =~ s/^\s+|\s+$//g;
    
    die new IMPL::ArgumentException("A valid template name is required") unless length $name;
    
    $name = $this->_appendExt($name);
    
    my ($tt,$error) = $this->provider->fetch($name);
    
    if (defined $error and $error == STATUS_DECLINED) {
        die new IMPL::KeyNotFoundException($name);
    } elsif (defined $error and $error == STATUS_ERROR) {
        die new IMPL::Exception("Failed to load a template", $name, $tt);
    }
    
    return $tt;
}

sub _appendExt {
    my ($this,$name) = @_;
    
    return $name unless $this->ext;
    
    if (length $this->ext and substr( $name, -length($this->ext) ) eq $this->ext) {
        return $name;
    } else {
        return $name . $this->ext;
    }
}

sub _init {
    my ($this) = @_;
    
    if (!$this->isInitialized) {
        my $initializer = $this->initializer || sub {};
        
        eval {
            $this->context->process($initializer,$this->_globals);
        };
        if (my $e = $@) {
            die new IMPL::Exception("Failed to process an initializer", $this->initializer, $e);
        }
        
        $this->isInitialized(1);
    }
}

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',
    initializer => 'shared/global'
        
);

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

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

=end code

=head1 DESCRIPTION

=head1 MEMBERS

=head2 C<document($docName)>

=cut