view Lib/IMPL/Web/Application/Action.pm @ 56:117b6956d5a5

Web application in progress
author wizard
date Thu, 04 Mar 2010 15:46:17 +0300
parents 609b59c9f03c
children bf59ee1cd506
line wrap: on
line source

package IMPL::Web::Application::Action;
use strict;

use base qw(IMPL::Object);

use IMPL::Class::Property;

BEGIN {
	public property application => prop_get | owner_set;
	public property request => prop_get | owner_set;
	public property response => prop_get | owner_set;
	
	private property _entryPoint => prop_all;
}

sub Invoke {
	my ($this) = @_;
	
	if ($this->_entryPoint) {
		$this->_entryPoint->();
	} else {
		die new IMPL::InvalidOperationException("At least one handler is required");
	}
}

sub ChainHandler {
	my ($this,$handler) = @_;
	
	my $delegateNext = $this->_entryPoint();
	
	if (ref $handler eq 'CODE') {
		$this->_entryPoint( sub {
			$handler->($this,$delegateNext);			
		} );
	} elsif (UNIVERSAL::isa($handler,'IMPL::Web::Application::QueryHandler')) {
		$this->_entryPoint( sub {
			$handler->Invoke($this,$delegateNext);
		} );
	} elsif ($handler and not ref $handler) {
		my $method = $this->can($handler) or die new IMPL::InvalidArgumentException("An invalid handler supplied");
		
		$this->_entryPoint( sub {
			$method->($this,$delegateNext);			
		} );
	} else {
		die new IMPL::InvalidArgumentException("An invalid handler supplied");
	}
	
}

1;

__END__

=pod

=head1 DESCRIPTION

Определяет порядок выполнения запроса, форматирует результат, инициализирует контекст.

Объект создается обработчиком запросов, таким как C<IMPL::Web::Application::UriController>.
При этом формируется цепочка обработчиков запроса, эта цапочка будет выполняться с последнего добавленного,
причем каждый добавленный обработчик в качестве одного из параметров получает не только текущий запрос,
но и предыдущий обработчик.

Типичная цепочка может быть такой, в порядке добавления

$objSecCallToMethod($target,$method)
$AuthenticateMethod
$TDocumentOut($file)

что приведет к следующей последовательности

Action->Invoke() {
	TDocumentOut->Invoke($Action,$nextHandler) {
		my $result = $nextHandler() {
			$AuthenticateMethod($Action,$nextHandler) {
				my $context = $Action->application->security->Authenticate($Action->request,$Action->response);
				return $context->Impersonate($nextHandler) {
					$objSecCallToMethod->Invoke($Action,undef) {
						IMPL::Security->AccessCheck($target,$method);
						return $target->$method();
					}
				}
			}
		}
		$this->format($result,$Action->response->streamBody);
	}		
}

или как альтернатива может быть еще

$objSecCallToMethod($target,$method)
$AuthenticateMethod
$TransfromToSimpleData
$JSONOut

В данной цепочке также происходит вызов метода, но его результат потом преобразуется
в простые структуры и передается JSON преобразователю. Таким образом модулю логики
не требуется знать о выходном формате, всю работу проделают дополнительные фильтры.

=head1 HANDLERS

=head2 subroutines

=over

=item CODE ref

Ссылка на процедуру может являться обработчиком, при этом функция будет вызвана с
двумя параметрами: ссылкой на action объект, и точкой входа следующего обработчика.

=item Method Name

Имя метода, передается в виде строки. У текущего объекта action ищется метод с
указанным именем, после чего используется ссылка на этот метод для вызова с двумя
параметрами: ссылкой на action объект, и точкой входа следующего обработчика.

Получается вызов идентичный следующему C<< $action->MethodName($nextHandler) >>; 

=back 

=cut