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