Mercurial > pub > Impl
view Lib/IMPL/Web/Application/ControllerUnit.pm @ 120:41e9d9ea3db5
Merge with 79cdd6c86409806bd1de092d9f0fb2b048775720
author | wizard |
---|---|
date | Mon, 07 Jun 2010 17:45:14 +0400 (2010-06-07) |
parents | 7b14e0122b79 |
children | c8dfbbdd8005 |
line wrap: on
line source
package IMPL::Web::Application::ControllerUnit; use strict; use base qw(IMPL::Object); use IMPL::Class::Property; use IMPL::DOM::Transform::PostToDOM; use IMPL::DOM::Schema; use Class::Inspector; use File::Spec; use constant { CONTROLLER_METHODS => 'controller_methods', STATE_CORRECT => 'correct', STATE_NEW => 'new', STATE_INVALID => 'invalid' }; BEGIN { public property action => prop_get | owner_set; public property application => prop_get | owner_set; public property query => prop_get | owner_set; public property formData => prop_get | owner_set; public property formSchema => prop_get | owner_set; public property formErrors => prop_get | owner_set; } __PACKAGE__->class_data(CONTROLLER_METHODS,{}); sub CTOR { my ($this,$action,$args) = @_; $this->action($action); $this->application($action->application); $this->query($action->query); $this->$_($args->{$_}) foreach qw(formData formSchema formErrors); } sub forms { my ($self,%forms) = @_; while ( my ($method,$info) = each %forms ) { die new IMPL::Exception("A method doesn't exists in the controller",$self,$method) unless $self->can($method); if ( not ref $info ) { $self->class_data(CONTROLLER_METHODS)->{$method} = { wrapper => 'FormWrapper', schema => $info }; } elsif (ref $info eq 'HASH') { die new IMPL::Exception("A schema must be specified",$self,$method) unless $info->{schema}; $self->class_data(CONTROLLER_METHODS)->{$method} = { wrapper => 'FormWrapper', schema => $info->{schema} }; } else { die new IMPL::Exception("Unsupported method information",$self,$method); } } } sub transactions { my ($self,@names) = @_; $self->class_data(CONTROLLER_METHODS)->{$_} = {} foreach @names; } sub InvokeAction { my ($self,$method,$action) = @_; if (my $methodInfo = $self->class_data(CONTROLLER_METHODS)->{$method}) { if (my $wrapper = $methodInfo->{wrapper}) { return $self->$wrapper($method,$action,$methodInfo); } else { return $self->TransactionWrapper($method,$action,$methodInfo); } } else { die new IMPL::InvalidOperationException("Invalid method call",$self,$method); } } sub TransactionWrapper { my ($self,$method,$action,$methodInfo) = @_; my $unit = $self->new($action); return $unit->$method(); } sub FormWrapper { my ($self,$method,$action,$methodInfo) = @_; my $schema = $self->loadSchema($methodInfo->{schema}); my $process = $action->query->param('process') || 0; my $form = $methodInfo->{form} || $action->query->param('form') || $schema->selectSingleNode('ComplexNode')->name or die new IMPL::Exception('No situable form name could be determined',$self,$method); my %result; my $transform = IMPL::DOM::Transform::PostToDOM->new( undef, $schema, $form ); $result{formSchema} = $schema; $result{formData} = $transform->Transform($self->query); if ($process) { $result{formErrors} = $transform->Errors->as_list; if ($transform->Errors->Count) { $result{state} = STATE_INVALID; } else { $result{state} = STATE_CORRECT; my $unit = $self->new($action,\%result); $result{result} = $unit->method(); } } else { $result{state} = STATE_NEW; } return \%result; } sub loadSchema { my ($self,$name) = @_; my ($vol,$dir,$file) = File::Spec->splitpath( Class::Inspector->resolved_filename(ref $self || $self) ); return IMPL::DOM::Schema->LoadSchema(File::Spec->catfile($vol,$dir,$name)); } 1; __END__ =pod =head1 NAME C<IMPL::Web::Application::ControllerUnit> - ������� ����� ��� ����������� ���������� � ������ �����������. =head1 DESCRIPTION ������, ����������� �� ������� ������ ���������� ������� ����������. ����� ������� � ����� ������ ����������� ��� ���������� ��� ������ ������� C<transaction>, C<form>. ����� ����������� ���������� ��������� ��������� �������, � ������ �������� ����� ��������� ����������. ��� ����� ���������� ����� C<InvokeAction($method,$action)>, ������� �������/��������������� �������� ����������. ���������� �� ������ ������ ������� �� ������� � �����. =head2 ������� ���������� ������� ���������� ������� ������ ������, ��� ��������������� ���������, � ������������ ��������� �������� ���������� ������������. =head2 ����� ��� ������������� ���� ������ �������������� ��������������, ��� ��������� DOM ��������� � ������� �����. ��� ������������ DOM ��������� ������������ �����. ��� ���� ���������� �������� �������������� �������� C<formData>, C<formSchema>, C<formErrors>. ��������� ���������� ���������� �� ������������ �������� ������������, � ���������� � ����� �����, ������� �������� ��������� ������� =begin code { state => '{ new | correct | invalid }', result => $transactionResult, formData => $formDOM, formSchema => $formSchema, formErrors => @errors } =end code =over =item C<state> ��������� ����������� �����. =over =item C<new> �������������� ���������� �����, ��� ����� ���� ������������, �� ��� ���������. � ������ ��������� ���������� ������ �� �����������. =item C<correct> ������ ����� ���������, ���������� ���������, � �� ��������� �������� ����� ���� C<result> =item C<invalid> ���������� ����� �� ������ �����������, ������ �������� ����� ���� C<formErrors>. ���������� �� �����������. =back =item C<result> ��������� ���������� ����������, ���� ������� ������� �����������. =item C<formData> ��� �������� � ������� �������. �������� ���������� ������, �� �������� �� ��� ������������, ����� ���� ����������� ��� ���������� �����, ��� ����������� �����������. =item C<formSchema> ����� ������ �����, ����� �������������� ��� ���������� ������������ ����. =item C<formErrors> ������ ����������� ������, ���� ������� ���� =back =head1 MEMBERS =over =item C<[get] application> =item C<[get] query> =item C<[get] response> =item C<[get] formData> =item C<[get] formSchema> =item C<[get] formErrors> =item C<InvokeAction($method,$action)> ������������ �������� ���������� ����������, ����� ���� ������������� ��� ��������������� ��������� �� ����� ��������. =item C<TransactionWrapper($method,$action,$methodInfo)> ������� ��� ��������������� ������� ����������, ����� ���� ������������� ��� ��������������� ��������� �� ����� ��������. =item C<FormWrapper($method,$action,$methodInfo)> ������� ��� ��������������� ����, ����� ���� ������������� ��� ��������������� ��������� �� ����� ��������. =back =head1 EXAMPLE =begin code package MyBooksUnit; use strict; use base qw(IMPL::Web::Application::ControllerUnit); __PACKAGE__->PassThroughArgs; __PACKAGE__->transactions(qw( find info )); __PACKAGE__->forms( create => 'books.create.xml' ); sub find { my ($this) = @_; return $this->application->dataSource->resultset('Books')->find({author => $this->query->param('author')}); } sub info { my ($this) = @_; return $this->application->dataSource->resultset('Books')->find({id => $this->query->param('id')}); } sub create { my ($this) = @_; my %book = map { $_ => $this->formData->selectSingleNode($_)->nodeValue } qw(author_id title year ISBN); return $this->application->datasource->resultset('Books')->create(\%book); } =end code =cut