view Lib/IMPL/Web/QueryHandler/UrlController.pm @ 213:d6e2ea24af08

sync
author sergey
date Fri, 03 Aug 2012 01:15:15 +0400
parents 4d0e1962161c
children
line wrap: on
line source

package IMPL::Web::QueryHandler::UrlController;
use strict;
use parent qw(IMPL::Web::QueryHandler);

use IMPL::Class::Property;
use IMPL::Exception;
use Carp qw(croak);
use Scalar::Util qw(tainted);

BEGIN {
    public property namespace => prop_all;
}

__PACKAGE__->PassThroughArgs;

sub Process {
    my ($this,$action,$nextHandler) = @_;
    
    my $namespace = $this->namespace || $action->application->typeof;
    
    my @target = grep $_, split /\//, ($ENV{PATH_INFO} || '') or die new IMPL::Exception("No target specified");
    
    my $method = pop @target;
    if ( $method =~ /^(\w+)/ ) {
        $method = $1;
    } else {
        die new IMPL::Exception("Invalid method name",$method);
    }
    
    (/^(\w+)$/ or die new IMPL::Exception("Invalid module name part", $_)) and $_=$1 foreach @target;
    
    my $module = join '::',$namespace,@target;
    
    die new IMPL::Exception("A module name is untrusted", $module) if tainted($module);
    
    eval "require $module; 1;" unless eval{ $module->can('InvokeAction'); };
    if (my $err = $@ ) {
        die new IMPL::Exception("Failed to load module",$module,$err);
    }
    
    if(UNIVERSAL::can($module,'InvokeAction')) {
        $module->InvokeAction($method,$action);
    } else {
        die new IMPL::InvalidOperationException("Failed to invoke action",$ENV{PATH_INFO},$module,$method);
    }
}

1;

__END__

=pod

=head1 NAME

C<IMPL::Web::QueryHandler::UrlController> - вызов метода на основе C<url> запроса.

=head1 DESCRIPTION

Использует переменную C<$ENV{PATH_INFO}> для получения имени и метода модуля.
Например запрос C<http://localhost/User/register.html> интерпретируется как вызов метода C<register>
у модуля C<User>. 

=head1 MEMBERS

=head2 PROPERTIES

=over

=item C<[get,set] namespace>

Пространство имен в котором находится модуль. по умолчению совпадает с именем класса приложения, например C<My::App>

=back

=cut