comparison lib/IMPL/Web/Handler/ViewSelector.pm @ 407:c6e90e02dd17 ref20150831

renamed Lib->lib
author cin
date Fri, 04 Sep 2015 19:40:23 +0300
parents
children
comparison
equal deleted inserted replaced
406:f23fcb19d3c1 407:c6e90e02dd17
1 package IMPL::Web::Handler::ViewSelector;
2 use strict;
3
4 use IMPL::Const qw(:prop);
5
6 use IMPL::declare {
7 require => {
8 NotAcceptable => 'IMPL::Web::NotAcceptableException',
9 HttpResponse => 'IMPL::Web::HttpResponse'
10 },
11 base => [
12 'IMPL::Object' => undef,
13 'IMPL::Object::Autofill' => '@_',
14 'IMPL::Object::Serializable' => undef
15 ],
16 props => [
17 views => PROP_RW | PROP_LIST,
18 fallback => PROP_RW,
19 types => PROP_RW
20 ]
21 };
22
23 sub Invoke {
24 my ( $this, $action, $next ) = @_;
25
26 my $result = $next ? $next->($action) : undef;
27
28 my $model;
29
30 return $result if eval { $result->isa(HttpResponse) };
31
32 my $handler;
33 my $path = $action->pathInfo;
34
35 if ( $this->types and $path =~ m/\.(\w+)$/ ) {
36 my $forced;
37 if ( $forced = $this->types->{$1} and $action->query->Accept($forced) )
38 {
39 ($handler) =
40 grep eval { $_->can('contentType') }
41 && $_->contentType eq $forced, $this->views;
42 }
43 }
44
45 if ( not $handler ) {
46
47 my @handlers =
48 sort { $b->{preference} <=> $a->{preference} } map {
49 {
50 handler => $_,
51 preference => eval { $_->can('contentType') }
52 ? $action->query->Accept( $_->contentType )
53 : 0
54 }
55 } $this->views;
56
57 my $info = shift @handlers;
58 $handler = $info ? $info->{handler} : undef;
59
60 }
61
62 die NotAcceptable->new(
63 map {
64 eval { $_->can('contentType') } ? $_->contentType : ()
65 } $this->views
66 ) unless $handler;
67
68 return $handler->Invoke( $action, sub { $result } );
69 }
70
71 1;
72
73 __END__
74
75 =pod
76
77 =head1 NAME
78
79 C<IMPL::Web::Handler::ViewSelector> - Выбор нужного представления на основе заголовка C<Accept>
80
81 =head1 DESCRIPTION
82
83 Использует заголовок запроса C<Accept> для выбора подходящего представления, если задано свойство C<types>,
84 пытается в первую очередь по расширению определить, какое представление подходит.
85
86 В случаях, когда не требуется строить представление для данных (например, при перенаправлении к другому
87 ресурсу или если нет данных), нужно, чтобы данному обработчику был возвращен
88 L<IMPL::Web::Application::ActionResult>, который будет просто передан далее.
89
90 =head1 MEMBERS
91
92 =head2 C<[get,set,list]views>
93
94 Список представлений, которые могут быть возвращены.
95
96 =head2 C<[get,set]types>
97
98 Хеш с соотвествием между расширением и типом содержимого, для подсказки при выборе представления.
99
100 =cut