52
|
1 package IMPL::Web::Application::Action;
|
55
|
2 use strict;
|
52
|
3
|
62
|
4 use base qw(IMPL::Object IMPL::Object::Autofill);
|
52
|
5
|
|
6 use IMPL::Class::Property;
|
|
7
|
|
8 BEGIN {
|
|
9 public property application => prop_get | owner_set;
|
62
|
10 public property query => prop_get | owner_set;
|
52
|
11 public property response => prop_get | owner_set;
|
55
|
12
|
|
13 private property _entryPoint => prop_all;
|
|
14 }
|
|
15
|
|
16 sub Invoke {
|
|
17 my ($this) = @_;
|
|
18
|
|
19 if ($this->_entryPoint) {
|
|
20 $this->_entryPoint->();
|
|
21 } else {
|
|
22 die new IMPL::InvalidOperationException("At least one handler is required");
|
|
23 }
|
|
24 }
|
|
25
|
|
26 sub ChainHandler {
|
|
27 my ($this,$handler) = @_;
|
|
28
|
|
29 my $delegateNext = $this->_entryPoint();
|
|
30
|
|
31 if (ref $handler eq 'CODE') {
|
56
|
32 $this->_entryPoint( sub {
|
55
|
33 $handler->($this,$delegateNext);
|
56
|
34 } );
|
55
|
35 } elsif (UNIVERSAL::isa($handler,'IMPL::Web::Application::QueryHandler')) {
|
56
|
36 $this->_entryPoint( sub {
|
55
|
37 $handler->Invoke($this,$delegateNext);
|
56
|
38 } );
|
|
39 } elsif ($handler and not ref $handler) {
|
|
40 my $method = $this->can($handler) or die new IMPL::InvalidArgumentException("An invalid handler supplied");
|
|
41
|
|
42 $this->_entryPoint( sub {
|
|
43 $method->($this,$delegateNext);
|
|
44 } );
|
55
|
45 } else {
|
|
46 die new IMPL::InvalidArgumentException("An invalid handler supplied");
|
|
47 }
|
|
48
|
52
|
49 }
|
|
50
|
|
51 1;
|
|
52
|
|
53 __END__
|
|
54
|
|
55 =pod
|
|
56
|
|
57 =head1 DESCRIPTION
|
|
58
|
57
|
59 Определяет порядок выполнения запроса.
|
52
|
60
|
57
|
61 Запрос выполняется последовательным вызовом цепочки обработчиков, при этом обработчики
|
|
62 сами вызывают следующие.
|
52
|
63
|
|
64 Типичная цепочка может быть такой, в порядке добавления
|
|
65
|
57
|
66 SecCallToMethod($target,$method)
|
|
67 AuthenticateMethod
|
|
68 TDocumentOut($file)
|
52
|
69
|
|
70 что приведет к следующей последовательности
|
|
71
|
|
72 Action->Invoke() {
|
|
73 TDocumentOut->Invoke($Action,$nextHandler) {
|
|
74 my $result = $nextHandler() {
|
|
75 $AuthenticateMethod($Action,$nextHandler) {
|
62
|
76 my $context = $Action->application->security->Authenticate($Action->query,$Action->response);
|
52
|
77 return $context->Impersonate($nextHandler) {
|
|
78 $objSecCallToMethod->Invoke($Action,undef) {
|
|
79 IMPL::Security->AccessCheck($target,$method);
|
|
80 return $target->$method();
|
|
81 }
|
|
82 }
|
|
83 }
|
|
84 }
|
|
85 $this->format($result,$Action->response->streamBody);
|
|
86 }
|
|
87 }
|
|
88
|
|
89 или как альтернатива может быть еще
|
|
90
|
|
91 $objSecCallToMethod($target,$method)
|
|
92 $AuthenticateMethod
|
|
93 $TransfromToSimpleData
|
|
94 $JSONOut
|
|
95
|
|
96 В данной цепочке также происходит вызов метода, но его результат потом преобразуется
|
|
97 в простые структуры и передается JSON преобразователю. Таким образом модулю логики
|
|
98 не требуется знать о выходном формате, всю работу проделают дополнительные фильтры.
|
|
99
|
56
|
100 =head1 HANDLERS
|
|
101
|
|
102 =head2 subroutines
|
|
103
|
|
104 =over
|
|
105
|
|
106 =item CODE ref
|
|
107
|
|
108 Ссылка на процедуру может являться обработчиком, при этом функция будет вызвана с
|
|
109 двумя параметрами: ссылкой на action объект, и точкой входа следующего обработчика.
|
|
110
|
|
111 =item Method Name
|
|
112
|
|
113 Имя метода, передается в виде строки. У текущего объекта action ищется метод с
|
|
114 указанным именем, после чего используется ссылка на этот метод для вызова с двумя
|
|
115 параметрами: ссылкой на action объект, и точкой входа следующего обработчика.
|
|
116
|
|
117 Получается вызов идентичный следующему C<< $action->MethodName($nextHandler) >>;
|
|
118
|
|
119 =back
|
|
120
|
57
|
121 =head2 C< IMPL::Web::Application::QueryHandler >
|
|
122
|
|
123 Любой объект наследованный от C< IMPL::Web::Application::QueryHandler > может быть
|
|
124 использован в качестве обработчика запроса
|
|
125
|
52
|
126 =cut |