Introduced genericHanleRequestLoginFailedRedirect().
[core.git] / inc / classes / main / 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          * Private method to initialize a given filter chain
135          *
136          * @param       $filterChain    Name of the filter chain
137          * @return      void
138          */
139         protected function initFilterChain ($filterChain) {
140                 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONTROLLER: ' . $filterChain . ' init: START');
141                 $this->filterChains[$filterChain] = ObjectFactory::createObjectByConfiguredName('filter_chain_class');
142                 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONTROLLER: ' . $filterChain . ' init: FINISHED');
143         }
144
145         /**
146          * Adds a filter to a given filter chain
147          *
148          * @param       $filterChain    Chain of the filter
149          * @param       $filterInstance         An instance of a filter
150          * @return      void
151          * @throws      InvalidFilterChainException     If the filter chain is invalid
152          */
153         protected function addFilter ($filterChain, Filterable $filterInstance) {
154                 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONTROLLER: ' . $filterChain . ',' . $filterInstance->__toString(). ' add: START');
155
156                 // Test if the filter is there
157                 if (!isset($this->filterChains[$filterChain])) {
158                         // Throw an exception here
159                         throw new InvalidFilterChainException(array($this, $filterChain), self::EXCEPTION_FILTER_CHAIN_INVALID);
160                 } // END - if
161
162                 // Add the filter
163                 $this->filterChains[$filterChain]->addFilter($filterInstance);
164                 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONTROLLER: ' . $filterChain . ',' . $filterInstance->__toString(). ' add: FINISH');
165         }
166
167         /**
168          * Adds a filter to the pre filter chain
169          *
170          * @param       $filterInstance         An instance of a filter
171          * @return      void
172          */
173         public function addPreFilter (Filterable $filterInstance) {
174                 // Add the pre filter
175                 $this->addFilter(self::FILTER_CHAIN_PRE_COMMAND, $filterInstance);
176         }
177
178         /**
179          * Adds a filter to the post filter chain
180          *
181          * @param       $filterInstance         An instance of a filter
182          * @return      void
183          */
184         public function addPostFilter (Filterable $filterInstance) {
185                 // Add the post filter
186                 $this->addFilter(self::FILTER_CHAIN_POST_COMMAND, $filterInstance);
187         }
188
189         /**
190          * Add a shutdown filter
191          *
192          * @param       $filterInstance         A Filterable class
193          * @return      void
194          */
195         public function addShutdownFilter (Filterable $filterInstance) {
196                 $this->addFilter('shutdown', $filterInstance);
197         }
198
199         /**
200          * Executes given filter chain chain
201          *
202          * @param       $filterChain            Chain of the filter to execute
203          * @param       $requestInstance        An instance of a request class
204          * @param       $responseInstance       An instance of a response class
205          * @return      void
206          * @throws      InvalidFilterChainException     If the filter chain is invalid
207          */
208         protected function executeFilters ($filterChain, Requestable $requestInstance, Responseable $responseInstance) {
209                 // Test if the filter is there
210                 if (!isset($this->filterChains[$filterChain])) {
211                         // Throw an exception here
212                         throw new InvalidFilterChainException(array($this, $filterChain), self::EXCEPTION_FILTER_CHAIN_INVALID);
213                 } // END - if
214
215                 // Run all filters
216                 $this->filterChains[$filterChain]->processFilters($requestInstance, $responseInstance);
217         }
218
219         /**
220          * Executes all pre filters
221          *
222          * @param       $requestInstance        An instance of a request class
223          * @param       $responseInstance       An instance of a response class
224          * @return      void
225          */
226         protected function executePreFilters (Requestable $requestInstance, Responseable $responseInstance) {
227                 // Execute all pre filters
228                 $this->executeFilters(self::FILTER_CHAIN_PRE_COMMAND, $requestInstance, $responseInstance);
229         }
230
231         /**
232          * Executes all post filters
233          *
234          * @param       $requestInstance        An instance of a request class
235          * @param       $responseInstance       An instance of a response class
236          * @return      void
237          */
238         protected function executePostFilters (Requestable $requestInstance, Responseable $responseInstance) {
239                 // Execute all post filters
240                 $this->executeFilters(self::FILTER_CHAIN_POST_COMMAND, $requestInstance, $responseInstance);
241         }
242
243         /**
244          * Executes all shutdown filters
245          *
246          * @param       $requestInstance        A Requestable class
247          * @param       $responseInstance       A Responseable class
248          * @return      void
249          */
250         public function executeShutdownFilters (Requestable $requestInstance, Responseable $responseInstance) {
251                 $this->executeFilters('shutdown', $requestInstance, $responseInstance);
252         }
253 }
254
255 // [EOF]
256 ?>