Mercurial > pub > Impl
view Lib/IMPL/Web/Application/CustomResource.pm @ 334:71221d79e6b4
removing web resources contracts
author | cin |
---|---|
date | Thu, 13 Jun 2013 02:24:57 +0400 |
parents | 04a093f0a5a6 |
children | e8be9062ecf2 |
line wrap: on
line source
package IMPL::Web::Application::CustomResource; use strict; use IMPL::Const qw(:prop); use IMPL::declare { require => { NotAllowedException => 'IMPL::Web::NotAllowedException', HttpResponse => 'IMPL::Web::HttpResponse' }, base => [ 'IMPL::Web::Application::Resource' => '@_' ], props => [ accessCheck => PROP_RW ] }; our %RESOURCE_BINDINGS = ( GET => 'HttpGet', POST => 'HttpPost', PUT => 'HttpPut', DELETE => 'HttpDelete', HEAD => 'HttpHead' ); __PACKAGE__->static_accessor(_rxResourcesMap => undef, 'own'); __PACKAGE__->static_accessor(_nameResourcesMap => undef, 'own'); sub namedResources { shift->_nameResourcesMap; } sub regexResources { shift->_rxResourcesMap; } sub CTOR { my ($this,%args) = @_; $this->accessCheck($args{accessCheck}) if $args{accessCheck}; $this->verbs->{options} ||= \&_HttpOptionsBinding; while(my ($verb,$methodName) = each %RESOURCE_BINDINGS) { $this->verbs->{lc($verb)} ||= sub { my ($resource,$action) = @_; if (eval { $resource->can($methodName) }) { return $resource->$methodName($action); } else { die NotAllowedException->new(allow => join(',', _GetAllowedHttpMethods($resource))); } } } } sub FindChildResourceInfo { my ( $this, $name ) = @_; $this->_PrepareResourcesCache() unless($this->_nameResourcesMap); return $this->next::method($name); } sub PrepareResourcesCache { # suppress default caching mechanisn } sub _PrepareResourcesCache { # a little bit wired my ($self) = @_; my %nameMap; my @rxMap; foreach my $res ($self->GetChildResources()) { #skip resources without contract next unless $res->{contract}; if ( my $name = $res->{name} ) { $nameMap{$name} = $res; } if ( $res->{match} ) { push @rxMap,$res; } } $self->_rxResourcesMap(\@rxMap); $self->_nameResourcesMap(\%nameMap); } sub AccessCheck { my ($this,$verb) = @_; my $handler = $this->accessCheck; if(ref($handler) eq 'CODE') { return &$handler($this,$verb); } } sub GetChildResources { } sub _HttpOptionsBinding { my ($this) = @_; my @allow = $this->_GetAllowedHttpMethods(); return HttpResponse->new( status => '200 OK', headers => { allow => join ( ',', @allow ) } ); } sub _GetAllowedHttpMethods { my ($this) = @_; return grep $this->can($RESOURCE_BINDINGS{$_}), keys %RESOURCE_BINDINGS; } 1; __END__ =pod =head1 NAME C<IMPL::Web::Application::CustomResource> - базовый класс для ресурсов, реальзуемых в коде. =head1 SYNOPSIS =begin code package MyApp::Web::Resources::ProfileResource; use IMPL::declare { base => [ 'IMPL::Web::Application::CustomResource' => '@_' ] } sub HttpGet { my ($this) = @_; return $this->model; } sub HttpPut { my ($this,$action) = @_; my $form = MyApp::Web::Schema::UpdateUser->new(); $this->model->update( $form->Bind($action) ); } sub GetChildResources { return { name => 'create', contract => { class => 'My::Web::FormResource', formName => 'create', schema => 'profile.schema' } }, { match => qr/^(.*)$/, contract => { class => 'My::Web::ItemResource' } } } =end code =head1 MEMBERS =head2 C<[static]contractFactory> Фабрика, используемая для получения контракта ресурса. По умолчанию C<IMPL::Web::Application::CustomResourceContract>. =head2 C<[static]contractInstance> Экземпляр контракта для ресурса. Создается при первом обращении при помощи метода C<InitContract()>. =head2 C<[static]InitContract()> Создает новый экземпляр контракта, используя фабрику из свойства C<contractFactory>. =head2 C<[static]CreateContract(%args)> Создает новый контракт, который при создании ресурсов будет передавать им в конструкторе параметры C<%args>. Реализуется при помощи C<IMPL::Object::Factory> которой задается параметр ссылка на C<%args>, т.о. при создании ресурса, ему в конструкторе будет передан список из ключей и значений хеша C<%args>, а затем остальные аргументы. =head2 C<[static]CreateResource(%args)> Создает контракт по-умолчанию и вызывает у него метод C<CreateResource(%args)>. =head2 C<[static]GetChildResources()> Статический метод, который должны переопределять новые классы ресурсов, у которых есть дочерние ресурсы. =begin code package MyApp::Web::MyResource sub GetChildResources { my $self = shift; return $self->SUPER::GetChildResources(), { name => 'info', contract => $contractInfo }; } =end code Метод возвращает список из хешей, которые будут переданы в качестве параметра C<resources> контракту данного ресурса. =cut