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