206
|
1 package IMPL::Web::Handler::ViewSelector;
|
|
2 use strict;
|
|
3
|
|
4 use IMPL::lang qw(:declare :constants);
|
|
5
|
|
6 use IMPL::declare {
|
|
7 require => {
|
|
8 NotAcceptable => 'IMPL::Web::NotAcceptableException'
|
|
9 },
|
|
10 base => {
|
|
11 'IMPL::Object' => undef,
|
|
12 'IMPL::Object::Autofill' => '@_',
|
|
13 'IMPL::Object::Serializable' => undef
|
|
14 }
|
|
15 };
|
|
16
|
|
17 BEGIN {
|
|
18 public property views => PROP_ALL | PROP_LIST;
|
|
19 public property fallback => PROP_ALL;
|
|
20 public property types => PROP_ALL;
|
|
21 }
|
|
22
|
|
23 sub Invoke {
|
|
24 my ($this,$action,$next) = @_;
|
|
25
|
|
26 my $handler;
|
|
27 my $path = $action->query->path_info;
|
|
28
|
|
29 if ($this->types and $path =~ m/\.(\w+)$/) {
|
|
30 my $forced;
|
|
31 if ($forced = $this->types->{$1} and $action->query->Accept($forced) ) {
|
|
32 ($handler) = grep eval { $_->can('contentType') } && $_->contentType eq $forced, $this->views;
|
|
33 }
|
|
34 }
|
|
35
|
|
36 if (not $handler) {
|
|
37
|
|
38 my @handlers =
|
|
39 sort {
|
|
40 $b->{preference} <=> $a->{preference}
|
|
41 } map {
|
|
42 {
|
|
43 handler => $_,
|
|
44 preference =>
|
|
45 eval { $_->can('contentType') } ? $action->query->Accept($_->contentType) : 0
|
|
46 }
|
|
47 } $this->views;
|
|
48
|
|
49 my $info = shift @handlers;
|
|
50 $handler = $info ? $info->{handler} : undef;
|
|
51
|
|
52 }
|
|
53
|
|
54 die NotAcceptable->new(map { eval {$_->can('contentType') } ? $_->contentType : () } $this->views )
|
|
55 unless $handler;
|
|
56
|
|
57 return $handler->Invoke($action,$next);
|
|
58 }
|
|
59
|
208
|
60 1;
|
|
61
|
|
62 __END__
|
|
63
|
|
64 =pod
|
|
65
|
|
66 =head1 NAME
|
|
67
|
|
68 C<IMPL::Web::Handler::ViewSelector> - Выбор нужного представления на основе заголовка C<Accept>
|
|
69
|
|
70 =head1 DESCRIPTION
|
|
71
|
|
72 Использует заголовок запроса C<Accept> для выбора подходящего представления, если задано свойство C<types>,
|
|
73 пытается в первую очередь по расширению определить, какое представление подходит.
|
|
74
|
|
75 =head1 MEMBERS
|
|
76
|
|
77 =head2 C<[get,set,list]views>
|
|
78
|
|
79 Список представлений, которые могут быть возвращены.
|
|
80
|
|
81 =head2 C<[get,set]types>
|
|
82
|
|
83 Хеш с соотвествием между расширением и типом содержимого, для подсказки при выборе представления.
|
|
84
|
|
85 =cut |