e1215a5a00f5237dfebbb6fd3546daccb93c1138
[core.git] / inc / main / classes / controller / class_BaseController.php
1 <?php
2 // Own namespace
3 namespace CoreFramework\Controller;
4
5 // Import framework stuff
6 use CoreFramework\Factory\ObjectFactory;
7 use CoreFramework\Object\BaseFrameworkSystem;
8 use CoreFramework\Registry\Generic\Registry;
9 use CoreFramework\Registry\Registerable;
10 use CoreFramework\Request\Requestable;
11
12 /**
13  * A generic controller class. You should extend this base class if you want to
14  * write your own controller. You get the advantage that you can use the pre and
15  * post filters.
16  *
17  * @author              Roland Haeder <webmaster@shipsimu.org>
18  * @version             0.0.0
19  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
20  * @license             GNU GPL 3.0 or any newer version
21  * @link                http://www.shipsimu.org
22  *
23  * This program is free software: you can redistribute it and/or modify
24  * it under the terms of the GNU General Public License as published by
25  * the Free Software Foundation, either version 3 of the License, or
26  * (at your option) any later version.
27  *
28  * This program is distributed in the hope that it will be useful,
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31  * GNU General Public License for more details.
32  *
33  * You should have received a copy of the GNU General Public License
34  * along with this program. If not, see <http://www.gnu.org/licenses/>.
35  */
36 class BaseController extends BaseFrameworkSystem implements Registerable {
37         // Exception constants
38         const EXCEPTION_FILTER_CHAIN_INVALID = 0xf10;
39
40         // Names of controller's own filter chains
41         const FILTER_CHAIN_PRE_COMMAND  = 'controller_pre_command';
42         const FILTER_CHAIN_POST_COMMAND = 'controller_post_command';
43
44         /**
45          * Generic filter chains
46          */
47         private $filterChains = array();
48
49         /**
50          * Protected constructor
51          *
52          * @param       $className      Name of the class
53          * @return      void
54          */
55         protected function __construct ($className) {
56                 // Call parent constructor
57                 parent::__construct($className);
58
59                 // Initialize both filter chains
60                 $this->initFilterChain(self::FILTER_CHAIN_PRE_COMMAND);
61                 $this->initFilterChain(self::FILTER_CHAIN_POST_COMMAND);
62
63                 // Add this controller to the registry
64                 Registry::getRegistry()->addInstance('controller', $this);
65         }
66
67         /**
68          * Executes a command with pre and post filters
69          *
70          * @param       $requestInstance        A Requestable class
71          * @param       $responseInstance       A Responseable class
72          * @return      void
73          */
74         public function executeGenericPrePostCommand (Requestable $requestInstance, Responseable $responseInstance) {
75                 // Get the command instance from the resolver by sending a request instance to the resolver
76                 $commandInstance = $this->getResolverInstance()->resolveCommandByRequest($requestInstance);
77
78                 // Add more filters by the command
79                 $commandInstance->addExtraFilters($this, $requestInstance);
80
81                 // Run the pre filters
82                 $this->executePreFilters($requestInstance, $responseInstance);
83
84                 // This request was valid! :-D
85                 $requestInstance->requestIsValid();
86
87                 // Execute the command
88                 $commandInstance->execute($requestInstance, $responseInstance);
89
90                 // Run the post filters
91                 $this->executePostFilters($requestInstance, $responseInstance);
92
93                 // Flush the response out
94                 $responseInstance->flushBuffer();
95         }
96
97         /**
98          * Handles the given request and response, redirects to login_failed if
99          * UserAuthorizationException is thrown.
100          *
101          * @param       $requestInstance        An instance of a Requestable class
102          * @param       $responseInstance       An instance of a Responsable class
103          * @return      void
104          */
105         public function genericHanleRequestLoginFailedRedirect (Requestable $requestInstance, Responseable $responseInstance) {
106                 // Get the "form action"
107                 $formAction = $requestInstance->getRequestElement('form');
108
109                 // Get command instance from resolver
110                 $commandInstance = $this->getResolverInstance()->resolveCommand($formAction);
111
112                 // Add more filters by the command
113                 $commandInstance->addExtraFilters($this, $requestInstance);
114
115                 // Try to run the pre filters, if auth exceptions come through redirect here
116                 try {
117                         // Run the pre filters
118                         $this->executePreFilters($requestInstance, $responseInstance);
119                 } catch (UserAuthorizationException $e) {
120                         // Redirect to main page
121                         $responseInstance->redirectToConfiguredUrl('login_failed');
122
123                         // Exit here
124                         exit();
125                 }
126
127                 /*
128                  * Is the request still valid? Post filters shall only be executed of
129                  * the request is valid
130                  */
131                 if ($requestInstance->isRequestValid()) {
132                         // Execute the command
133                         $commandInstance->execute($requestInstance, $responseInstance);
134
135                         // Execute *very* generic ppost filters
136                         $this->executePostFilters($requestInstance, $responseInstance);
137                 } // END - if
138
139                 // Flush the buffer out
140                 $responseInstance->flushBuffer();
141         }
142
143         /**
144          * Generic execute of the command: pre and post filters with redirect
145          * but request becomes valid after pre-filters run.
146          *
147          * @param       $requestInstance        An instance of a Requestable class
148          * @param       $responseInstance       An instance of a Responsable class
149          * @return      void
150          */
151         public function genericHanleRequestLoginAreaFailedRedirect (Requestable $requestInstance, Responseable $responseInstance) {
152                 // Get the command instance from the resolver by sending a request instance to the resolver
153                 $commandInstance = $this->getResolverInstance()->resolveCommandByRequest($requestInstance);
154
155                 // Add more filters by the command
156                 $commandInstance->addExtraFilters($this, $requestInstance);
157
158                 // Try to run the pre filters, if auth exceptions come through redirect here
159                 try {
160                         // Run the pre filters
161                         $this->executePreFilters($requestInstance, $responseInstance);
162                 } catch (UserAuthorizationException $e) {
163                         // Redirect to main page
164                         $responseInstance->redirectToConfiguredUrl('login_failed');
165
166                         // Exit here
167                         exit();
168                 }
169
170                 // This request was valid! :-D
171                 $requestInstance->requestIsValid();
172
173                 // Execute the command
174                 $commandInstance->execute($requestInstance, $responseInstance);
175
176                 // Run the pre filters
177                 $this->executePostFilters($requestInstance, $responseInstance);
178
179                 // Flush the response out
180                 $responseInstance->flushBuffer();
181         }
182
183         /**
184          * Private method to initialize a given filter chain
185          *
186          * @param       $filterChain    Name of the filter chain
187          * @return      void
188          */
189         protected function initFilterChain ($filterChain) {
190                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ' init: START');
191                 $this->filterChains[$filterChain] = ObjectFactory::createObjectByConfiguredName('filter_chain_class');
192                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ' init: FINISHED');
193         }
194
195         /**
196          * Adds a filter to a given filter chain
197          *
198          * @param       $filterChain    Chain of the filter
199          * @param       $filterInstance         An instance of a filter
200          * @return      void
201          * @throws      InvalidFilterChainException     If the filter chain is invalid
202          */
203         protected function addFilter ($filterChain, Filterable $filterInstance) {
204                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ',' . $filterInstance->__toString(). ' add: START');
205
206                 // Test if the filter is there
207                 if (!isset($this->filterChains[$filterChain])) {
208                         // Throw an exception here
209                         throw new InvalidFilterChainException(array($this, $filterChain), self::EXCEPTION_FILTER_CHAIN_INVALID);
210                 } // END - if
211
212                 // Add the filter
213                 $this->filterChains[$filterChain]->addFilter($filterInstance);
214                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ',' . $filterInstance->__toString(). ' add: FINISH');
215         }
216
217         /**
218          * Adds a filter to the pre filter chain
219          *
220          * @param       $filterInstance         An instance of a filter
221          * @return      void
222          */
223         public function addPreFilter (Filterable $filterInstance) {
224                 // Add the pre filter
225                 $this->addFilter(self::FILTER_CHAIN_PRE_COMMAND, $filterInstance);
226         }
227
228         /**
229          * Adds a filter to the post filter chain
230          *
231          * @param       $filterInstance         An instance of a filter
232          * @return      void
233          */
234         public function addPostFilter (Filterable $filterInstance) {
235                 // Add the post filter
236                 $this->addFilter(self::FILTER_CHAIN_POST_COMMAND, $filterInstance);
237         }
238
239         /**
240          * Add a shutdown filter
241          *
242          * @param       $filterInstance         A Filterable class
243          * @return      void
244          */
245         public function addShutdownFilter (Filterable $filterInstance) {
246                 $this->addFilter('shutdown', $filterInstance);
247         }
248
249         /**
250          * Executes given filter chain chain
251          *
252          * @param       $filterChain            Chain of the filter to execute
253          * @param       $requestInstance        An instance of a Requestable class
254          * @param       $responseInstance       An instance of a Responsable class
255          * @return      void
256          * @throws      InvalidFilterChainException     If the filter chain is invalid
257          */
258         protected function executeFilters ($filterChain, Requestable $requestInstance, Responseable $responseInstance) {
259                 // Test if the filter is there
260                 if (!isset($this->filterChains[$filterChain])) {
261                         // Throw an exception here
262                         throw new InvalidFilterChainException(array($this, $filterChain), self::EXCEPTION_FILTER_CHAIN_INVALID);
263                 } // END - if
264
265                 // Run all filters
266                 $this->filterChains[$filterChain]->processFilters($requestInstance, $responseInstance);
267         }
268
269         /**
270          * Executes all pre filters
271          *
272          * @param       $requestInstance        An instance of a Requestable class
273          * @param       $responseInstance       An instance of a Responsable class
274          * @return      void
275          */
276         protected function executePreFilters (Requestable $requestInstance, Responseable $responseInstance) {
277                 // Execute all pre filters
278                 $this->executeFilters(self::FILTER_CHAIN_PRE_COMMAND, $requestInstance, $responseInstance);
279         }
280
281         /**
282          * Executes all post filters
283          *
284          * @param       $requestInstance        An instance of a Requestable class
285          * @param       $responseInstance       An instance of a Responsable class
286          * @return      void
287          */
288         protected function executePostFilters (Requestable $requestInstance, Responseable $responseInstance) {
289                 // Execute all post filters
290                 $this->executeFilters(self::FILTER_CHAIN_POST_COMMAND, $requestInstance, $responseInstance);
291         }
292
293         /**
294          * Executes all shutdown filters
295          *
296          * @param       $requestInstance        A Requestable class
297          * @param       $responseInstance       A Responseable class
298          * @return      void
299          */
300         public function executeShutdownFilters (Requestable $requestInstance, Responseable $responseInstance) {
301                 $this->executeFilters('shutdown', $requestInstance, $responseInstance);
302         }
303
304 }