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