view Lib/IMPL/Web/Application/Action.pm @ 153:3765adf1803f

minor fixes
author wizard
date Mon, 27 Sep 2010 19:15:34 +0400 (2010-09-27)
parents b04e978d6d5a
children 4267a2ac3d46
line wrap: on
line source
package IMPL::Web::Application::Action;
use strict;

use base qw(IMPL::Object IMPL::Object::Autofill);

__PACKAGE__->PassThroughArgs;

use IMPL::Class::Property;

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

sub CTOR {
	my ($this) = @_;
	
	$this->responseFactory('IMPL::Web::Application::Response') unless $this->responseFactory; 
	$this->response( $this->responseFactory->new(query => $this->query) );
}

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

sub ReinitResponse {
	my ($this) = @_;
	
	die new IMPL::InvalidOperationException("Response already sent") if $this->response->isHeaderPrinted;
	
	$this->response->Discard;
	$this->response($this->responseFactory->new(query => $this->query));
}

sub ChainHandler {
	my ($this,$handler) = @_;
	
	my $delegateNext = $this->_entryPoint();
	
	if (ref $handler eq 'CODE') {
		$this->_entryPoint( sub {
			$handler->($this,$delegateNext);			
		} );
	} elsif (ref $handler and UNIVERSAL::isa($handler,'IMPL::Web::QueryHandler')) {
		$this->_entryPoint( sub {
			$handler->Invoke($this,$delegateNext);
		} );
	} elsif ($handler and not ref $handler) {
		
		if (my $method = $this->can($handler) ) {
			$this->_entryPoint( sub {
				$method->($this,$delegateNext);			
			} );
		} else {
			{
				no strict 'refs';
				eval "require $handler; 1;" or die new IMPL::InvalidArgumentException("An invalid handler supplied",$handler,"Failed to load module") unless keys %{"${handler}::"};
			}
			
			if (UNIVERSAL::isa($handler,'IMPL::Web::QueryHandler')) {
				$this->_entryPoint( sub {
					$handler->Invoke($this,$delegateNext);
				} );	
			} else {
				die new IMPL::InvalidArgumentException("An invalid handler supplied",$handler);
			}
		}
	} else {
		die new IMPL::InvalidArgumentException("An invalid handler supplied",$handler);
	}
	
}

sub cookie {
	my ($this,$name,$rx) = @_;
	
	$this->_launder(scalar( $this->query->cookie($name) ), $rx );
}

sub param {
	my ($this,$name,$rx) = @_;
	
	$this->_launder(scalar( $this->query->param($name) ), $rx );
}

sub _launder {
	my ($this,$value,$rx) = @_;
	
	if ( $value ) {
		if ($rx) {
			if ( my @result = ($value =~ m/$rx/) ) {
				return @result > 1 ? \@result : $result[0];
			} else {
				return undef;
			}
		} else {
			return $value;
		}
	} else {
		return undef;
	}
}

1;

__END__

=pod

=head1 NAME

C<IMPL::Web::Application::Action> - ������� ������ C<CGI> �������.

=head1 DESCRIPTION

C<[Infrastructure]>

���������� ������� ���������� �������. ������ ����������� ���������������� �������
������� ������������, ��� ���� ����������� ���� �������� ���������.
����������� ����������� � �������, �������� �� ����������.

�������� ������� ����� ���� �����, � ������� ����������

=begin code

IMPL::Web::QueryHandler::SecCallToMethod
IMPL::Web::QueryHandler::AuthenticateCookie
IMPL::Web::QueryHandler::PageFormat

=end code

��� �������� � ��������� ������������������

=begin code

# the application creates a new Action object 

my $action = $application->actionFactory->new(
	action => $application, # the application passes self
	query => $query # current CGI query
);

# forms query handlers stack

$action->ChainHandler($_) foreach qw (
	IMPL::Web::QueryHandler::SecCallToMethod
	IMPL::Web::QueryHandler::AuthenticateCookie
	IMPL::Web::QueryHandler::PageFormat
);

# and finally invokes the action

$action->Invoke() {
	
	# some internals
	
	IMPL::Web::QueryHandler::PageFormat->Invoke($action,$nextHandlerIsAuthHandler) {
		
		#some internals
		
		my $result = $nextHandlerIsAuthHandler() {
			
			# some internals

			IMPL::Web::QueryHandler::AuthenticateCookie->Invoke($action,$nextHandlerIsSecCall) {
				
				# some internals
				# do auth and generate security $context 
				
				# impersonate $context and call the next handler				
				return $context->Impersonate($nextHandlerIsSecCall) {
					
					# some internals 
					
					IMPL::Web::QueryHandler::SecCallToMethod->Invoke($action,undef) {
						
						# next handler isn't present as it is the last hanler
						
						# some internals
						# calculate the $method and the $target from CGI request
												
						IMPL::Security->AccessCheck($target,$method);
						return $target->$method();
						
					}
					
				}
				
			}
		}
		
		# some intenals
		# formatted output to $action->response->streamBody		
	}		
}

=end code

��� ��� ������������ ����� ���� ���

=begin code

IMPL::Web::QueryHandler::SecCallToMethod
IMPL::Web::QueryHandler::AuthenticateCookie
IMPL::Web::QueryHandler::Filter->new( target => IMPL::Transform::ObjectToJSON->new() , method => 'Transform')
IMLP::Web::QueryHandler::JSONFormat


=end code

� ������ ������� ����� ���������� ����� ������, �� ��� ��������� ����� �������������
� ������� ��������� � ���������� JSON ���������������. ����� ������� ������ ������
�� ��������� ����� � �������� �������, ��� ������ ��������� �������������� �������.

=head1 MEMBERS

=head2 PROPERTIES

=over

=item C< [get] application>

��������� ���������� ���������� ������� ������

=item C< [get] query >

��������� C<CGI> �������

=item C< [get] response >

����� �� C<CGI> ������� C<IMPL::Web::Application::Response>

=item C< [get] responseFactory >

������� ������� �� ������, ������������ ��� �������� ������ ������
���� ��� ��������������� �������� ������� C<IMPL::Web::Application::Action>,
���� ��� ������ ������ C<ReinitResponse> � �������� �������.

�� ��������� ����� �������� C<IMPL::Web::Application::Response>

=back

=head2 METHODS

=over

=item C< ReinitResponse() >

������ ������� ������ C<response> � �������� ������ ���� ������.

������ �������� ������ ���������� ��� ��������� ������, �����
��� �������������� ����� ��������� ��������. ������� ��������,
��� ��� �������� �� ��������, ���� ����� �������� ��� ���������
��������� �������. ����� ��������� ���������� C<IMPL::InvalidOperationException>.

=item C< ChainHandler($handler) >

��������� ����� ���������� � �������. ���������� ������� ���������� � �����,
������ ��������� ����������� ����� �������� ������. 

=back

=head1 HANDLERS

=head2 subroutines

=over

=item CODE ref

������ �� ��������� ����� �������� ������������, ��� ���� ������� ����� ������� �
����� �����������: ������� �� action ������, � ������ ����� ���������� �����������.

=item Method Name

��� ������, ���������� � ���� ������. � �������� ������� action ������ ����� �
��������� ������, ����� ���� ������������ ������ �� ���� ����� ��� ������ � �����
�����������: ������� �� action ������, � ������ ����� ���������� �����������.

���������� ����� ���������� ���������� C<< $action->MethodName($nextHandler) >>; 

=back 

=head2 C< IMPL::Web::QueryHandler >

����� ������ ������������� �� C< IMPL::Web::QueryHandler > ����� ����
����������� � �������� ����������� �������

=cut