]> 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\Object\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\Response\Responseable;
14 use Org\Mxchange\CoreFramework\Traits\Resolver\ResolverTrait;
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 - 2023 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         // Load traits
42         use ResolverTrait;
43
44         // Exception constants
45         const EXCEPTION_FILTER_CHAIN_INVALID = 0xf10;
46
47         // Names of controller's own filter chains
48         const FILTER_CHAIN_PRE_COMMAND  = 'controller_pre_command';
49         const FILTER_CHAIN_POST_COMMAND = 'controller_post_command';
50
51         /**
52          * Generic filter chains
53          */
54         private $filterChains = [];
55
56         /**
57          * Protected constructor
58          *
59          * @param       $className      Name of the class
60          * @return      void
61          */
62         protected function __construct (string $className) {
63                 // Call parent constructor
64                 parent::__construct($className);
65
66                 // Initialize both filter chains
67                 $this->initFilterChain(self::FILTER_CHAIN_PRE_COMMAND);
68                 $this->initFilterChain(self::FILTER_CHAIN_POST_COMMAND);
69
70                 // Add this controller to the registry
71                 GenericRegistry::getRegistry()->addInstance('controller', $this);
72         }
73
74         /**
75          * Executes a command with pre and post filters
76          *
77          * @param       $requestInstance        A Requestable class
78          * @param       $responseInstance       A Responseable class
79          * @return      void
80          */
81         public function executeGenericPrePostCommand (Requestable $requestInstance, Responseable $responseInstance) {
82                 // Get the command instance from the resolver by sending a request instance to the resolver
83                 $commandInstance = $this->getResolverInstance()->resolveCommandByRequest($requestInstance);
84
85                 // Add more filters by the command
86                 $commandInstance->addExtraFilters($this, $requestInstance);
87
88                 // Run the pre filters
89                 $this->executePreFilters($requestInstance, $responseInstance);
90
91                 // This request was valid! :-D
92                 $requestInstance->setIsRequestValid(TRUE);
93
94                 // Execute the command
95                 $commandInstance->execute($requestInstance, $responseInstance);
96
97                 // Run the post filters
98                 $this->executePostFilters($requestInstance, $responseInstance);
99
100                 // Flush the response out
101                 $responseInstance->flushBuffer();
102         }
103
104         /**
105          * Handles the given request and response, redirects to login_failed if
106          * UserAuthorizationException is thrown.
107          *
108          * @param       $requestInstance        An instance of a Requestable class
109          * @param       $responseInstance       An instance of a Responseable class
110          * @return      void
111          */
112         public function genericHanleRequestLoginFailedRedirect (Requestable $requestInstance, Responseable $responseInstance) {
113                 // Get the "form action"
114                 $formAction = $requestInstance->getRequestElement('form');
115
116                 // Get command instance from resolver
117                 $commandInstance = $this->getResolverInstance()->resolveCommand('Org\Mxchange\CoreFramework\Command\Failed', $formAction);
118
119                 // Add more filters by the command
120                 $commandInstance->addExtraFilters($this, $requestInstance);
121
122                 // Try to run the pre filters, if auth exceptions come through redirect here
123                 try {
124                         // Run the pre filters
125                         $this->executePreFilters($requestInstance, $responseInstance);
126                 } catch (UserAuthorizationException $e) {
127                         // Redirect to main page
128                         $responseInstance->redirectToConfiguredUrl('login_failed');
129
130                         // Exit here
131                         exit();
132                 }
133
134                 /*
135                  * Is the request still valid? Post filters shall only be executed of
136                  * the request is valid
137                  */
138                 if ($requestInstance->isRequestValid()) {
139                         // Execute the command
140                         $commandInstance->execute($requestInstance, $responseInstance);
141
142                         // Execute *very* generic post filters
143                         $this->executePostFilters($requestInstance, $responseInstance);
144                 }
145
146                 // Flush the buffer out
147                 $responseInstance->flushBuffer();
148         }
149
150         /**
151          * Generic execute of the command: pre and post filters with redirect
152          * but request becomes valid after pre-filters run.
153          *
154          * @param       $requestInstance        An instance of a Requestable class
155          * @param       $responseInstance       An instance of a Responseable class
156          * @return      void
157          */
158         public function genericHanleRequestLoginAreaFailedRedirect (Requestable $requestInstance, Responseable $responseInstance) {
159                 // Get the command instance from the resolver by sending a request instance to the resolver
160                 $commandInstance = $this->getResolverInstance()->resolveCommandByRequest($requestInstance);
161
162                 // Add more filters by the command
163                 $commandInstance->addExtraFilters($this, $requestInstance);
164
165                 // Try to run the pre filters, if auth exceptions come through redirect here
166                 try {
167                         // Run the pre filters
168                         $this->executePreFilters($requestInstance, $responseInstance);
169                 } catch (UserAuthorizationException $e) {
170                         // Redirect to main page
171                         $responseInstance->redirectToConfiguredUrl('login_failed');
172
173                         // Exit here
174                         exit();
175                 }
176
177                 // This request was valid! :-D
178                 $requestInstance->setIsRequestValid(TRUE);
179
180                 // Execute the command
181                 $commandInstance->execute($requestInstance, $responseInstance);
182
183                 // Run the post filters
184                 $this->executePostFilters($requestInstance, $responseInstance);
185
186                 // Flush the response out
187                 $responseInstance->flushBuffer();
188         }
189
190         /**
191          * Private method to initialize a given filter chain
192          *
193          * @param       $filterChain    Name of the filter chain
194          * @return      void
195          */
196         protected function initFilterChain (string $filterChain) {
197                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ' init: START');
198                 $this->filterChains[$filterChain] = ObjectFactory::createObjectByConfiguredName('filter_chain_class');
199                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ' init: FINISHED');
200         }
201
202         /**
203          * Adds a filter to a given filter chain
204          *
205          * @param       $filterChain    Chain of the filter
206          * @param       $filterInstance         An instance of a filter
207          * @return      void
208          * @throws      InvalidFilterChainException     If the filter chain is invalid
209          */
210         protected function addFilter (string $filterChain, Filterable $filterInstance) {
211                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ',' . $filterInstance->__toString(). ' add: START');
212
213                 // Test if the filter is there
214                 if (!isset($this->filterChains[$filterChain])) {
215                         // Throw an exception here
216                         throw new InvalidFilterChainException(array($this, $filterChain), self::EXCEPTION_FILTER_CHAIN_INVALID);
217                 }
218
219                 // Add the filter
220                 $this->filterChains[$filterChain]->addFilter($filterInstance);
221                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ',' . $filterInstance->__toString(). ' add: FINISH');
222         }
223
224         /**
225          * Adds a filter to the pre filter chain
226          *
227          * @param       $filterInstance         An instance of a filter
228          * @return      void
229          */
230         public function addPreFilter (Filterable $filterInstance) {
231                 // Add the pre filter
232                 $this->addFilter(self::FILTER_CHAIN_PRE_COMMAND, $filterInstance);
233         }
234
235         /**
236          * Adds a filter to the post filter chain
237          *
238          * @param       $filterInstance         An instance of a filter
239          * @return      void
240          */
241         public function addPostFilter (Filterable $filterInstance) {
242                 // Add the post filter
243                 $this->addFilter(self::FILTER_CHAIN_POST_COMMAND, $filterInstance);
244         }
245
246         /**
247          * Add a shutdown filter
248          *
249          * @param       $filterInstance         A Filterable class
250          * @return      void
251          */
252         public function addShutdownFilter (Filterable $filterInstance) {
253                 $this->addFilter('shutdown', $filterInstance);
254         }
255
256         /**
257          * Executes given filter chain chain
258          *
259          * @param       $filterChain            Chain of the filter to execute
260          * @param       $requestInstance        An instance of a Requestable class
261          * @param       $responseInstance       An instance of a Responseable class
262          * @return      void
263          * @throws      InvalidFilterChainException     If the filter chain is invalid
264          */
265         protected function executeFilters (string $filterChain, Requestable $requestInstance, Responseable $responseInstance) {
266                 // Test if the filter is there
267                 if (!isset($this->filterChains[$filterChain])) {
268                         // Throw an exception here
269                         throw new InvalidFilterChainException(array($this, $filterChain), self::EXCEPTION_FILTER_CHAIN_INVALID);
270                 }
271
272                 // Run all filters
273                 $this->filterChains[$filterChain]->processFilters($requestInstance, $responseInstance);
274         }
275
276         /**
277          * Executes all pre filters
278          *
279          * @param       $requestInstance        An instance of a Requestable class
280          * @param       $responseInstance       An instance of a Responseable class
281          * @return      void
282          */
283         protected function executePreFilters (Requestable $requestInstance, Responseable $responseInstance) {
284                 // Execute all pre filters
285                 $this->executeFilters(self::FILTER_CHAIN_PRE_COMMAND, $requestInstance, $responseInstance);
286         }
287
288         /**
289          * Executes all post filters
290          *
291          * @param       $requestInstance        An instance of a Requestable class
292          * @param       $responseInstance       An instance of a Responseable class
293          * @return      void
294          */
295         protected function executePostFilters (Requestable $requestInstance, Responseable $responseInstance) {
296                 // Execute all post filters
297                 $this->executeFilters(self::FILTER_CHAIN_POST_COMMAND, $requestInstance, $responseInstance);
298         }
299
300         /**
301          * Executes all shutdown filters
302          *
303          * @param       $requestInstance        A Requestable class
304          * @param       $responseInstance       A Responseable class
305          * @return      void
306          */
307         public function executeShutdownFilters (Requestable $requestInstance, Responseable $responseInstance) {
308                 $this->executeFilters('shutdown', $requestInstance, $responseInstance);
309         }
310
311 }