view Lib/IMPL/Web/View/TTDocument.pm @ 304:2ff513227cb4

*TTView: refactoring. Added control registry for the document.
author cin
date Mon, 15 Apr 2013 07:44:50 +0400
parents a5eb64c6e6f7
children b5d5793f348e
line wrap: on
line source

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

use Scalar::Util qw(weaken);
use IMPL::Const qw(:prop);
use IMPL::lang qw(:hash is);
use Carp qw(carp);
use mro;

use IMPL::declare {
    require => {
        TTFactory => 'IMPL::Web::View::TTFactory',
        TTControl =>  'IMPL::Web::View::TTControl',
        Loader => 'IMPL::Code::Loader'
    },
    base => [
        'IMPL::Web::View::TTControl' => sub {
            my ($template,$ctx) = @_;
            $ctx ||= Template::Context->new();
            return $template, $ctx;  # context
        }
    ],
    props => [
        layout => PROP_RW,
        loader => PROP_RW,
    ]
};

sub CTOR {
    my ($this,$template,$ctx,$loader,$vars) = @_;
    
    $this->loader($loader) if $loader;
    $this->layout( $template->layout ) unless $this->layout;
    $this->title( $template->title ) unless $this->title;
    
    $this->context->stash->update($vars)
        if ref $vars eq 'HASH';
}

sub Render {
    my ($this,$args) = @_;

    $args ||= {};

    my %controls;
    my $require;
    my $documentContext;
    
    my $self = $this;
    
    $require = sub {
        my $control = shift;
        
        unless($self) {
            carp("Cant load control $control outside the document rendering process");
            return;
        }
        
        if (my $factory = $controls{$control}) {
            return $factory;
        } else {
            my $path = $control;
            
            if ( my $template = $self->loader->template($path) ) {
                
                $documentContext->localise();
                my $ctx = _clone_context($documentContext);
                $documentContext->delocalise();
               
                $factory = new IMPL::Web::View::TTFactory(
                    $template,
                    $ctx,
                    join( '/', splice( @{[split(/\//,$path)]}, 0, -1 ) ),
                    $require
                );
                
                $controls{$control} = $factory;
                            
                return $factory;
    
            } else {
                die new IMPL::KeyNotFoundException($control);
            }
        }
    };
    
    $this->context->localise();
    $documentContext = _clone_context( $this->context );
    
    $this->context->stash->set(require => $require);
    $this->context->stash->set(document => sub { $self });
    
    my $text = eval {
    
        if ($this->layout) {
        	my $tlayout = $this->loader->layout($this->layout);
        	if(my $init = $tlayout->blocks->{INIT}) {
        		$this->context->process(
                    $init,
                    hashMerge(
                        $args,
                        {
                           	template => $this->template
                        }
                    )
                );
        	}
        	my $content = $this->next::method($args);
            return $this->context->include(
                $tlayout,
                {
                	%{$args},
                    content => $content,
                    this => $this,
                    template => $this->template
                }
            );
	    } else {
	        return $this->next::method($args);
	    }
    };
    
    my $e = $@;

    undef $require;
    undef $documentContext;    
    undef %controls;
    undef $self;
    $this->context->delocalise();
    
    if ($e) {
        die $e;
    } else {
        return $text;
    }
}

sub GetTemplate {
    my ($this,$name) = @_;
    
    $this->template->blocks->{$name};
}

sub _clone_context {
    my $args = { %{shift || {}} };
    delete $args->{CONFIG};
    
    return Template::Context->new($args);
}

1;

__END__

=pod

=head1 NAME

C<IMPL::Web::View::TTDocument> - документ для построения HTML страницы на основе шаблонов TT.

=head1 SYNOPSIS

=begin code


=end code

=head1 DESCRIPTION


=over


=cut