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