# HG changeset patch # User wizard # Date 1268750173 -10800 # Node ID 2840c4c85db830fa9852e3565ac2874f69960046 # Parent 259cd3df6e53c7ee3ac22ac7d408041c24889ea2 Application configuration improvements Documentation diff -r 259cd3df6e53 -r 2840c4c85db8 Lib/IMPL/Web/Application.pm --- a/Lib/IMPL/Web/Application.pm Mon Mar 15 17:45:13 2010 +0300 +++ b/Lib/IMPL/Web/Application.pm Tue Mar 16 17:36:13 2010 +0300 @@ -16,6 +16,7 @@ public property handlerError => prop_all; public property factoryAction => prop_all; public property handlersQuery => prop_all | prop_list; + public property responseCharset => prop_all; public property options => prop_all; } @@ -30,6 +31,7 @@ my ($this) = @_; $this->factoryAction('IMPL::Web::Application::Action') unless $this->factoryAction; + $this->responseCharset('utf-8') unless $this->responseCharset; } sub Run { @@ -37,12 +39,12 @@ while (my $query = $this->FetchRequest()) { - # todo: move a creation of the response to the ActionClass my $action = $this->factoryAction->new( query => $query, - response => new IMPL::Web::Application::Response(query => $query), application => $this, - ); + ); + + $action->response->charset($this->responseCharset); $action->ChainHandler($_) foreach $this->handlersQuery; diff -r 259cd3df6e53 -r 2840c4c85db8 Lib/IMPL/Web/Application/Action.pm --- a/Lib/IMPL/Web/Application/Action.pm Mon Mar 15 17:45:13 2010 +0300 +++ b/Lib/IMPL/Web/Application/Action.pm Tue Mar 16 17:36:13 2010 +0300 @@ -11,11 +11,17 @@ 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; } -#todo: make ability to discard old and create new response +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) = @_; @@ -27,6 +33,15 @@ } } +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) = @_; diff -r 259cd3df6e53 -r 2840c4c85db8 Lib/IMPL/Web/Application/Response.pm --- a/Lib/IMPL/Web/Application/Response.pm Mon Mar 15 17:45:13 2010 +0300 +++ b/Lib/IMPL/Web/Application/Response.pm Tue Mar 16 17:36:13 2010 +0300 @@ -37,7 +37,16 @@ $this->query(CGI->new($this->query() | {})) unless $this->query; - $this->streamOut(*STDOUT) unless $this->streamOut; + if (lc $this->streamOut eq 'memory') { + my $dummy = ''; + open my $hout, '>:encoding(utf8)', \$dummy or die new IMPL::Exception("Failed to create memory stream",$!); + $this->streamOut($hout); + } elsif (not $this->streamOut) { + $this->streamOut(*STDOUT); + } else { + die new IMPL::InvalidArgumentException("Invalid parameter value",$this->streamOut); + } + $this->buffered(1) unless defined $this->buffered; binmode $this->streamOut, ":encoding(".$this->charset.")"; } diff -r 259cd3df6e53 -r 2840c4c85db8 Lib/IMPL/Web/QueryHandler.pm --- a/Lib/IMPL/Web/QueryHandler.pm Mon Mar 15 17:45:13 2010 +0300 +++ b/Lib/IMPL/Web/QueryHandler.pm Tue Mar 16 17:36:13 2010 +0300 @@ -1,6 +1,6 @@ package IMPL::Web::QueryHandler; -use base qw(IMPL::Object IMPL::Object::Autofill); +use base qw(IMPL::Object IMPL::Object::Autofill IMPL::Object::Serializable); use IMPL::Class::Property; __PACKAGE__->PassThroughArgs; @@ -10,7 +10,7 @@ sub Invoke { my ($self,$action,$nextHandler) = @_; - if (not ref $self or UNIVERSAL::isa($self,'IMPL::Object::Factory')) { + if (not ref $self) { return $self->new( action => $action )->Invoke($action,$nextHandler); } else { return $self->Process($action,$nextHandler); @@ -27,10 +27,32 @@ =pod -=head1 DESCRIPTION +=head1 NAME Базовый класс для обработчиков запросов. +=head1 SYNOPSIS + +Простой вариант + +=begin code + +package MyHandler; + +use base qw(IMPL::Web::QueryHandler); + +sub CTOR { + my ($this,%args) = @_; + +} + +sub Process { + my ($this,$action,$nextHandler) = @_; + +} + +=end code + =head1 MEMBERS =over 4 @@ -38,16 +60,26 @@ =item C< Invoke($action,$nextHandler) > Вызывается механизмом обработки запроса, для передачи управления обработчику. Данная реализация -проверяет как была вызвана, если как статический метод, то создает экземпляр класса и вызывает +проверяет контекст вызова, если как статический метод, то создает экземпляр класса и вызывает у созданного объекта метод C< Invoke > с параметрами C< $action >, C< $nextHandler >. -Если метод был вызван у объекта, то управление передается методу C< Process > +При создании нового объекта в конструктор передается именованый параметр C. + +Если метод был вызван у объекта, то управление передается методу C< Process >. + +=over -C< $action > Экземпляр запроса +=item C< $action > + +Экземпляр запроса -C< $nextHandler > Делегат для вызова следующего обработчика. Вызывается без параметров, но следующему обработчику +=item C< $nextHandler > + +Делегат для вызова следующего обработчика. Вызывается без параметров, но следующему обработчику втоматически будут переданы необходимые параметры. =back +=back + =cut \ No newline at end of file diff -r 259cd3df6e53 -r 2840c4c85db8 Lib/IMPL/Web/QueryHandler/PageFormat.pm --- a/Lib/IMPL/Web/QueryHandler/PageFormat.pm Mon Mar 15 17:45:13 2010 +0300 +++ b/Lib/IMPL/Web/QueryHandler/PageFormat.pm Tue Mar 16 17:36:13 2010 +0300 @@ -5,16 +5,19 @@ use IMPL::Class::Property; use IMPL::Web::TDocument; +use File::Spec; use Error qw(:try); BEGIN { - public property charsetTemplates => prop_all; + public property templatesCharset => prop_all; + public property templatesBase => prop_all; } sub CTOR { my ($this) = @_; - $this->charsetTemplates('utf-8') unless $this->charsetTemplates; + $this->templatesCharset('utf-8') unless $this->templatesCharset; + $this->templatesBase('.') unless $this->templatesBase; } sub Process { @@ -23,7 +26,9 @@ my $doc = new IMPL::Web::TDocument(); try { - $doc->loadFile ( $ENV{PATH_TRANSLATED}, $this->charsetTemplates ); + my @path = split /\//, $ENV{PATH_TRANSLATED}; + + $doc->loadFile ( File::Spec->catfile($this->templatesBase,@path), $this->templatesCharset ); $action->response->contentType('text/html'); my $hOut = $action->response->streamBody; @@ -34,4 +39,72 @@ }; } -1; \ No newline at end of file +1; + +__END__ + +=pod + +=head1 NAME + +C - Выдача результатов в виде HTML страницы, построенной из шаблона. + +=head1 SYNOPSIS + +В файле конфигурации приложения + +=begin code xml + + + + utf-8 + + + +=end code xml + +Программно + +=begin code + +my $app = new IMPL::Web::Application(); +$app->handlersQuery->Add( + new IMPL::Web::QueryHandler::PageFormat( charsetTemplates=> 'utf-8' ); +); + +=end + +=head1 DESCRIPTION + +Обработчик запроса для веб приложения. Загружает шаблон, путь к котрому берется +из C относительно пути из свойства C. + +Наследуется от C для реализации функционала +обработчика запроса и переопределяет метод C. + +C + +=head1 MEMBERS + +=over + +=item C + +Создает новый экземпляр и заполняет свойства. + +=item C<[get,set] templatesCharset> + +Кодировка шаблонов. По умолчанию utf-8. + +=item C<[get,set] templatesBase> + +Каталог относительно которого ищется шаблон. + +=item C<[override] Process($action,$nextHandler)> + +Метод, переопределяющий CProcess> и которому передается управление +для выполнения действий. + +=back + +=cut \ No newline at end of file diff -r 259cd3df6e53 -r 2840c4c85db8 _doc/make.pl --- a/_doc/make.pl Mon Mar 15 17:45:13 2010 +0300 +++ b/_doc/make.pl Tue Mar 16 17:36:13 2010 +0300 @@ -7,6 +7,7 @@ our $LibDir = '../Lib/IMPL'; our $OutDir = 'html'; +our $level = 0; our $index = { name => 'root' }; @@ -35,6 +36,8 @@ my $pom = $parser->parse_file($hPod); + $level = @path; + print $hOut PodViewHTML->print($pom); } @@ -118,13 +121,51 @@ } sub view_begin { my ($self,$begin) = @_; - $begin->format =~ /code/i ? return "
\n".join ("",$begin->text())."
\n" : return $self->SUPER::view_begin($begin); + $begin->format =~ /code/i ? return "
\n".escape_html(join ("",$begin->text()))."
\n" : return $self->SUPER::view_begin($begin); +} + +sub escape_html { + my %esc = ( + '&' => '&', + '>' => '>', + '<' => '<' + ); + + (my $text = shift) =~ s/([&><])/$esc{$1}/gex; + + return $text; } sub view_seq_link { my ($self,$text) = @_; - $text->text =~ /(?:(\w+)\s+)(\w+(?:\:\:\w+)*)/; + if ($text =~ /^\s*(?:(\w+)\s+)?(\w+(?:\:\:\w+)+)\s*$/) { + my ($keyword, $package) = ($1 || '',$2); + + my @path = split /::/, $package; + + pop @path if $keyword; + shift @path if uc $path[0] eq 'IMPL'; + + if (-f File::Spec->catfile($LibDir,@path).".pm") { + return ''.$text.''; + } + + } elsif ($text =~ /^\s*(\w+(?:\:\:\w+)+)\s*->\s*(\w+)\s*$/) { + my ($package,$member) = ($1,$2); + + my @path = split /::/, $package; + shift @path; + + if (-f File::Spec->catfile($LibDir,@path).".pm") { + return ''.$text.''; + } + } -} \ No newline at end of file + return "$text"; +} + +sub view_seq_code { + goto &view_seq_link; +} diff -r 259cd3df6e53 -r 2840c4c85db8 _test/Resources/app.xml --- a/_test/Resources/app.xml Mon Mar 15 17:45:13 2010 +0300 +++ b/_test/Resources/app.xml Tue Mar 16 17:36:13 2010 +0300 @@ -17,7 +17,21 @@ + utf-8 + + IMPL::Web::Application::Action + + + IMPL::Web::Application::Response + + memory + + + + - IMPL::Web::QueryHandler::PageFormat + + cp1251 + \ No newline at end of file