# HG changeset patch
# User wizard
# Date 1269018372 -10800
# Node ID 9f5795a10939570629a17197a79f80eb94463f95
# Parent f47f935340054d112ea40976a8a705ac8fde9ae7
Documentation, minor fixes
diff -r f47f93534005 -r 9f5795a10939 Lib/IMPL/Object/Factory.pm
--- a/Lib/IMPL/Object/Factory.pm Thu Mar 18 17:58:33 2010 +0300
+++ b/Lib/IMPL/Object/Factory.pm Fri Mar 19 20:06:12 2010 +0300
@@ -70,14 +70,6 @@
=begin code
-sub ProcessItems {
- my ($factory,$items);
-
- return map $factory->new($_), @$items;
-}
-
-my @users = ProcessItems('MyApp::User',$db->selectUsers);
-
my $factory = new IMPL::Object::Factory(
'MyApp::User',
{
@@ -85,13 +77,35 @@
}
);
+my $class = 'MyApp::User';
+
+my $user;
+
+$user = $class->new(name => 'nobody'); # will create object MyApp::User
+ # and pass parameters (name=>'nobody')
+
+$user = $factory->new(name => 'root'); # will create object MyApp::User
+ # and pass paremeters (isAdmin => 1, name => 'root')
+
=end code
-my @admins = ProcessItems($factory,$db->selectAdmins);
+Или сериализованная форма в XML.
+
+=begin code xml
+
+ MyApp::User,
+
+ 1
+
+
+
+=end code xml
=head1 DESCRIPTION
+C<[Serializable]>
+
Класс, реализующий фабрику классов.
Фабрика классов это любой объект, который имеет метод C< new > вызов которого приводит к созданию нового
@@ -108,16 +122,56 @@
=over
-=item C< factory >
+=item C< CTOR($factory,$parameters) >
+
+Создает новый экземпляр
+
+=over
+
+=item C<$factory>
+
+Либо имя класса, либо другая фабрика.
+
+=item C<$parameters>
+
+Ссылка на параметры для создания объектов, может быть ссылкой на хеш, массив и т.д.
+
+Если является ссылкой на хеш, то при создании объектов данной фабрикой этот хеш
+будет развернут в список и передан параметрами методу C.
+
+Если является ссылкой на массив, то при создании объектов данной фабрикой этот массив
+будет передан в списк и передан параметрами методу C.
+
+Если является любым другим объектом или скаляром, то будет передан параметром методу
+C как есть.
+
+=back
+
+=item C< [get] factory >
Свойство, содержащее фабрику для создание новых объектов текущей фабрикой. Чаще всего оно содержит
имя класса.
-=item C< parameters >
+=item C< [get] parameters >
Свойство, содержит ссылку на параметры для создания объектов, при создании объекта эти параметры будут
развернуты в список и переданы оператору C< new > фабрике из свойства C< factory >, за ними будут
-следовать параметры непосредственно текущей фабрики.
+следовать параметры непосредственно текущей фабрики.
+
+=item C
+
+Создает новый объект, используя свйство C как фабрику и передавая туда параметры
+из свойства C и списка C<@params>. Ниже приведен упрощенный пример, как это происходит.
+
+=begin code
+
+sub new {
+ my ($this,@params) = @_;
+
+ return $this->factory->new(_as_list($this->parameters), @params);
+}
+
+=end code
=back
diff -r f47f93534005 -r 9f5795a10939 Lib/IMPL/Web/Application.pm
--- a/Lib/IMPL/Web/Application.pm Thu Mar 18 17:58:33 2010 +0300
+++ b/Lib/IMPL/Web/Application.pm Fri Mar 19 20:06:12 2010 +0300
@@ -14,7 +14,7 @@
BEGIN {
public property handlerError => prop_all;
- public property factoryAction => prop_all;
+ public property actionFactory => prop_all;
public property handlersQuery => prop_all | prop_list;
public property responseCharset => prop_all;
public property options => prop_all;
@@ -30,7 +30,7 @@
sub CTOR {
my ($this) = @_;
- $this->factoryAction('IMPL::Web::Application::Action') unless $this->factoryAction;
+ $this->actionFactory('IMPL::Web::Application::Action') unless $this->actionFactory;
$this->responseCharset('utf-8') unless $this->responseCharset;
}
@@ -39,7 +39,7 @@
while (my $query = $this->FetchRequest()) {
- my $action = $this->factoryAction->new(
+ my $action = $this->actionFactory->new(
query => $query,
application => $this,
);
@@ -72,8 +72,15 @@
=head1 SYNOPSIS
+=begin code
+
require MyApp;
-MyApp->spawn('app.config')->Run();
+
+my $instance = spawn MyApp('app.config');
+
+$instance->Run();
+
+=end code
=head1 DESCRIPTION
@@ -82,13 +89,94 @@
Процесс обработки запроса состоит из следующих частей
-1. Получение cgi запроса
-2. Вызов модуля для инициализации объекта действия
-3. Инициализация контекста выполнения
-4. Выполнение запроса
-5. Преобразование полученных данных в тело ответа
+=over
+
+=item 1
+
+Получение cgi запроса
+
+=item 2
+Создание объекта C
+=item 3
+Формирование цепочки вызовов при помощи C<< IMPL::Web::Application::Action->ChainHandler >>
+
+=item 4
+
+Выполнение запроса C<< IMPL::Web::Application::Action->Invoke >>
=cut
+
+Также приложение поддерживает отложенное создание объектов, которые по первому обращению
+к свойствам. Это реализовано в базовом классе C< IMPL::Configuration >. Для настройки
+активаторов можно использовать свойство C, в которое должен быть помещен хеш
+со ссылками на активаторы, см. пример ниже C.
+
+=head2 CONFIGURATION
+
+Ниже приведен пример конфигурации приложения
+
+=begin code xml
+
+
+
+
+
+ Sample application
+
+ IMPL::Object
+
+ data
+ nobody
+
+
+
+ IMPL::Object
+
+
+
+
+
+
+
+
+
+
+
+
+ utf-8
+
+
+
+
+
+ IMPL::Web::Application::Action
+
+
+
+
+
+
+ IMPL::Web::Application::Response
+
+
+
+ memory
+
+
+
+
+
+
+
+
+ -
+ cp1251
+
+
+
+
+=end code xml
+
diff -r f47f93534005 -r 9f5795a10939 Lib/IMPL/Web/Application/Action.pm
--- a/Lib/IMPL/Web/Application/Action.pm Thu Mar 18 17:58:33 2010 +0300
+++ b/Lib/IMPL/Web/Application/Action.pm Fri Mar 19 20:06:12 2010 +0300
@@ -87,49 +87,159 @@
=pod
+=head1 NAME
+
+C - Обертка вокруг C запроса.
+
=head1 DESCRIPTION
-Определяет порядок выполнения запроса.
+C<[Infrastructure]>
-Запрос выполняется последовательным вызовом цепочки обработчиков, при этом обработчики
-сами вызывают следующие.
+Определяет порядок выполнения запроса. Запрос выполняется последовательным вызовом
+цепочки обработчиков, при этом обработчики сами вызывают следующие.
+Обработчики выполняются в порядке, обратном их добавлению.
Типичная цепочка может быть такой, в порядке добавления
-SecCallToMethod($target,$method)
-AuthenticateMethod
-TDocumentOut($file)
+=begin code
+
+IMPL::Web::QueryHandler::SecCallToMethod
+IMPL::Web::QueryHandler::AuthenticateCookie
+IMPL::Web::QueryHandler::PageFormat
+
+=end code
что приведет к следующей последовательности
-Action->Invoke() {
- TDocumentOut->Invoke($Action,$nextHandler) {
- my $result = $nextHandler() {
- $AuthenticateMethod($Action,$nextHandler) {
- my $context = $Action->application->security->Authenticate($Action->query,$Action->response);
- return $context->Impersonate($nextHandler) {
- $objSecCallToMethod->Invoke($Action,undef) {
+=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();
+
}
+
}
+
}
}
- $this->format($result,$Action->response->streamBody);
+
+ # some intenals
+ # formatted output to $action->response->streamBody
}
}
+=end code
+
или как альтернатива может быть еще
-$objSecCallToMethod($target,$method)
-$AuthenticateMethod
-$TransfromToSimpleData
-$JSONOut
+=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 запроса
+
+=item C< [get] response >
+
+Ответ на C заспрос C
+
+=item C< [get] responseFactory >
+
+Фабрика ответов на запрос, используется для создания нового ответа
+либо при конструировании текущего объекта C,
+либо при вызове метода C у текущего объекта.
+
+По умолчанию имеет значение C
+
+=back
+
+=head2 METHODS
+
+=over
+
+=item C< ReinitResponse() >
+
+Отмена старого ответа C и создание вместо него нового.
+
+Данная операция обычно проводится при обработке ошибок, когда
+уже сформированный ответ требуется отменить. Следует заметить,
+что эта операция не возможна, если ответ частично или полностью
+отправлен клиенту. Тогда возникает исключение C.
+
+=item C< ChainHandler($handler) >
+
+Добавляет новый обработчик в цепочку. Выполнение цепочки начинается с конца,
+тоесть последний добавленный будет выполнен первым.
+
+=back
+
=head1 HANDLERS
=head2 subroutines
@@ -151,9 +261,9 @@
=back
-=head2 C< IMPL::Web::Application::QueryHandler >
+=head2 C< IMPL::Web::QueryHandler >
-Любой объект наследованный от C< IMPL::Web::Application::QueryHandler > может быть
+Любой объект наследованный от C< IMPL::Web::QueryHandler > может быть
использован в качестве обработчика запроса
=cut
\ No newline at end of file
diff -r f47f93534005 -r 9f5795a10939 Lib/IMPL/Web/Application/Response.pm
--- a/Lib/IMPL/Web/Application/Response.pm Thu Mar 18 17:58:33 2010 +0300
+++ b/Lib/IMPL/Web/Application/Response.pm Fri Mar 19 20:06:12 2010 +0300
@@ -14,6 +14,7 @@
#todo: add binary method to set a binary encoding, set it automatic when type isn't a text
BEGIN {
+ # автозаполнение буде происходить в порядке объявления
public property query => prop_get | owner_set; # cgi query
public property status => prop_all, { validator => \&_checkHeaderPrinted };
public property contentType => prop_all, { validator => \&_checkHeaderPrinted }; # String
@@ -32,11 +33,19 @@
__PACKAGE__->PassThroughArgs;
+our %CTOR = (
+ 'IMPL::Object::Autofill' => sub {
+ my %args = @_;
+
+ $args{query} = CGI->new($args{query} || {});
+
+ %args;
+ }
+);
+
sub CTOR {
my ($this,%args) = @_;
- $this->query(CGI->new($this->query() | {})) unless $this->query;
-
if (lc $this->streamOut eq 'memory') {
my $dummy = '';
open my $hout, '>:encoding(utf8)', \$dummy or die new IMPL::Exception("Failed to create memory stream",$!);
@@ -165,15 +174,23 @@
=pod
+=head1 NAME
+
+C - Ответ веб сервера непосредственно клиенту.
+
=head1 DESCRIPTION
-Ответ сервера на CGI запрос, позволяет сформировать основные свойства заголовка и тело запроса.
+C<[Infrastructure]>
+
+Позволяет сформировать основные свойства заголовка и тело ответа.
+
+Создается объектом C в процессе обработки запроса.
+
+Может использоваться обработчиками C в процессе выполнения запроса.
Объект позволяет буфферизировать вывод в тело ответа, что позволяет отменить или изменить
-ответ в последний момент.
-
-Свойство C< isHeaderPrinted > можно использовать для определения были ли отправлены какие-нибудь
-данные клиенту.
+ответ в последний момент. Свойство C< isHeaderPrinted > используется для определения факта
+отправлки данных клиенту.
=head1 PROPERTIES
@@ -184,27 +201,27 @@
=over
-=item C< query >
+=item C< [get] query >
CGI запрос, который используется для вывода данных, заголовка и пр. Существует всегда.
-=item C< status >
+=item C< [get,set] status >
Код ошибки HTTP. Например, '200 OK'. По умолчанию не установлен, при отправке клиенту бедт отправлен '200 ОК'.
-=item C< contentType >
+=item C< [get,set] contentType >
Тип MIME. По умолчанию не установлен, подразумивается 'text/html'.
-=item C< charset >
+=item C< [get,set] charset >
Кодировка, синоним свойства query->charset.
-=item C< expires >
+=item C< [get,set] expires >
Определяет время жизни контента, например '+10m'. По умолчанию не задано и не передается.
-=item C< cookies >
+=item C< [get,set] cookies >
Хеш массив с cookies, например C< { cart => ['foo','bar'], display => 'list' } >.
@@ -216,7 +233,7 @@
=over
-=item C< buffered >
+=item C< [get,set] buffered >
C< True > - то тело ответа пишется в буффер и будет отправлено при вызове метода C< Complete >,
заголовок также будет отправлен после вызова метода C< Complete >.
@@ -226,15 +243,15 @@
Это свойство можно менять до первого обращения к потоку для записи в тело ответа.
-=item C< streamOut >
+=item C< [get] streamOut >
Стандартный вывод CGI приложения.
-=item C< streamBody >
+=item C< [get] streamBody >
Поток для записи в тело ответа.
-=item C< isHeadPrinted >
+=item C< [get] isHeadPrinted >
Признак того, что заголовок уже был отправлен клиенту.
@@ -255,4 +272,9 @@
=back
+=head1 REMARKS
+
+Данный объект является автозаполняемым, т.е. все его свойства можно задать через
+именованные параметры конструктора.
+
=cut
\ No newline at end of file
diff -r f47f93534005 -r 9f5795a10939 _test/Resources/app.xml
--- a/_test/Resources/app.xml Thu Mar 18 17:58:33 2010 +0300
+++ b/_test/Resources/app.xml Fri Mar 19 20:06:12 2010 +0300
@@ -27,7 +27,7 @@
utf-8
-
+
IMPL::Web::Application::Action
@@ -37,7 +37,7 @@
-
+