view Lib/IMPL/Web/View/TTLoader.pm @ 189:08015e2803f1

IMPL::Vew::Web - fixed memory leaks, more tests
author cin
date Wed, 04 Apr 2012 02:49:45 +0400
parents ae8072f2f2a3
children 4d0e1962161c
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;
}

sub CTOR {
	my ($this,$refOpts,%args) = @_;
	
	$refOpts ||= {};
	
	$this->ext(delete $args{ext});
	$this->initializer(delete $args{initializer});
	
	$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) = @_;
	
	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, loader => $this );
}

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) {
		if ($this->initializer) {
			eval {
				$this->context->process($this->initializer);
			};
			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