3 namespace Org\Mxchange\CoreFramework\Controller;
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\Response\Responseable;
16 * A generic controller class. You should extend this base class if you want to
17 * write your own controller. You get the advantage that you can use the pre and
20 * @author Roland Haeder <webmaster@shipsimu.org>
22 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team
23 * @license GNU GPL 3.0 or any newer version
24 * @link http://www.shipsimu.org
26 * This program is free software: you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation, either version 3 of the License, or
29 * (at your option) any later version.
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public License
37 * along with this program. If not, see <http://www.gnu.org/licenses/>.
39 abstract class BaseController extends BaseFrameworkSystem implements Registerable {
40 // Exception constants
41 const EXCEPTION_FILTER_CHAIN_INVALID = 0xf10;
43 // Names of controller's own filter chains
44 const FILTER_CHAIN_PRE_COMMAND = 'controller_pre_command';
45 const FILTER_CHAIN_POST_COMMAND = 'controller_post_command';
48 * Generic filter chains
50 private $filterChains = array();
53 * Protected constructor
55 * @param $className Name of the class
58 protected function __construct ($className) {
59 // Call parent constructor
60 parent::__construct($className);
62 // Initialize both filter chains
63 $this->initFilterChain(self::FILTER_CHAIN_PRE_COMMAND);
64 $this->initFilterChain(self::FILTER_CHAIN_POST_COMMAND);
66 // Add this controller to the registry
67 GenericRegistry::getRegistry()->addInstance('controller', $this);
71 * Executes a command with pre and post filters
73 * @param $requestInstance A Requestable class
74 * @param $responseInstance A Responseable class
77 public function executeGenericPrePostCommand (Requestable $requestInstance, Responseable $responseInstance) {
78 // Get the command instance from the resolver by sending a request instance to the resolver
79 $commandInstance = $this->getResolverInstance()->resolveCommandByRequest($requestInstance);
81 // Add more filters by the command
82 $commandInstance->addExtraFilters($this, $requestInstance);
84 // Run the pre filters
85 $this->executePreFilters($requestInstance, $responseInstance);
87 // This request was valid! :-D
88 $requestInstance->requestIsValid();
90 // Execute the command
91 $commandInstance->execute($requestInstance, $responseInstance);
93 // Run the post filters
94 $this->executePostFilters($requestInstance, $responseInstance);
96 // Flush the response out
97 $responseInstance->flushBuffer();
101 * Handles the given request and response, redirects to login_failed if
102 * UserAuthorizationException is thrown.
104 * @param $requestInstance An instance of a Requestable class
105 * @param $responseInstance An instance of a Responseable class
108 public function genericHanleRequestLoginFailedRedirect (Requestable $requestInstance, Responseable $responseInstance) {
109 // Get the "form action"
110 $formAction = $requestInstance->getRequestElement('form');
112 // Get command instance from resolver
113 $commandInstance = $this->getResolverInstance()->resolveCommand($formAction);
115 // Add more filters by the command
116 $commandInstance->addExtraFilters($this, $requestInstance);
118 // Try to run the pre filters, if auth exceptions come through redirect here
120 // Run the pre filters
121 $this->executePreFilters($requestInstance, $responseInstance);
122 } catch (UserAuthorizationException $e) {
123 // Redirect to main page
124 $responseInstance->redirectToConfiguredUrl('login_failed');
131 * Is the request still valid? Post filters shall only be executed of
132 * the request is valid
134 if ($requestInstance->isRequestValid()) {
135 // Execute the command
136 $commandInstance->execute($requestInstance, $responseInstance);
138 // Execute *very* generic post filters
139 $this->executePostFilters($requestInstance, $responseInstance);
142 // Flush the buffer out
143 $responseInstance->flushBuffer();
147 * Generic execute of the command: pre and post filters with redirect
148 * but request becomes valid after pre-filters run.
150 * @param $requestInstance An instance of a Requestable class
151 * @param $responseInstance An instance of a Responseable class
154 public function genericHanleRequestLoginAreaFailedRedirect (Requestable $requestInstance, Responseable $responseInstance) {
155 // Get the command instance from the resolver by sending a request instance to the resolver
156 $commandInstance = $this->getResolverInstance()->resolveCommandByRequest($requestInstance);
158 // Add more filters by the command
159 $commandInstance->addExtraFilters($this, $requestInstance);
161 // Try to run the pre filters, if auth exceptions come through redirect here
163 // Run the pre filters
164 $this->executePreFilters($requestInstance, $responseInstance);
165 } catch (UserAuthorizationException $e) {
166 // Redirect to main page
167 $responseInstance->redirectToConfiguredUrl('login_failed');
173 // This request was valid! :-D
174 $requestInstance->requestIsValid();
176 // Execute the command
177 $commandInstance->execute($requestInstance, $responseInstance);
179 // Run the post filters
180 $this->executePostFilters($requestInstance, $responseInstance);
182 // Flush the response out
183 $responseInstance->flushBuffer();
187 * Private method to initialize a given filter chain
189 * @param $filterChain Name of the filter chain
192 protected function initFilterChain ($filterChain) {
193 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ' init: START');
194 $this->filterChains[$filterChain] = ObjectFactory::createObjectByConfiguredName('filter_chain_class');
195 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ' init: FINISHED');
199 * Adds a filter to a given filter chain
201 * @param $filterChain Chain of the filter
202 * @param $filterInstance An instance of a filter
204 * @throws InvalidFilterChainException If the filter chain is invalid
206 protected function addFilter ($filterChain, Filterable $filterInstance) {
207 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ',' . $filterInstance->__toString(). ' add: START');
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);
216 $this->filterChains[$filterChain]->addFilter($filterInstance);
217 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('CONTROLLER: ' . $filterChain . ',' . $filterInstance->__toString(). ' add: FINISH');
221 * Adds a filter to the pre filter chain
223 * @param $filterInstance An instance of a filter
226 public function addPreFilter (Filterable $filterInstance) {
227 // Add the pre filter
228 $this->addFilter(self::FILTER_CHAIN_PRE_COMMAND, $filterInstance);
232 * Adds a filter to the post filter chain
234 * @param $filterInstance An instance of a filter
237 public function addPostFilter (Filterable $filterInstance) {
238 // Add the post filter
239 $this->addFilter(self::FILTER_CHAIN_POST_COMMAND, $filterInstance);
243 * Add a shutdown filter
245 * @param $filterInstance A Filterable class
248 public function addShutdownFilter (Filterable $filterInstance) {
249 $this->addFilter('shutdown', $filterInstance);
253 * Executes given filter chain chain
255 * @param $filterChain Chain of the filter to execute
256 * @param $requestInstance An instance of a Requestable class
257 * @param $responseInstance An instance of a Responseable class
259 * @throws InvalidFilterChainException If the filter chain is invalid
261 protected function executeFilters ($filterChain, Requestable $requestInstance, Responseable $responseInstance) {
262 // Test if the filter is there
263 if (!isset($this->filterChains[$filterChain])) {
264 // Throw an exception here
265 throw new InvalidFilterChainException(array($this, $filterChain), self::EXCEPTION_FILTER_CHAIN_INVALID);
269 $this->filterChains[$filterChain]->processFilters($requestInstance, $responseInstance);
273 * Executes all pre filters
275 * @param $requestInstance An instance of a Requestable class
276 * @param $responseInstance An instance of a Responseable class
279 protected function executePreFilters (Requestable $requestInstance, Responseable $responseInstance) {
280 // Execute all pre filters
281 $this->executeFilters(self::FILTER_CHAIN_PRE_COMMAND, $requestInstance, $responseInstance);
285 * Executes all post filters
287 * @param $requestInstance An instance of a Requestable class
288 * @param $responseInstance An instance of a Responseable class
291 protected function executePostFilters (Requestable $requestInstance, Responseable $responseInstance) {
292 // Execute all post filters
293 $this->executeFilters(self::FILTER_CHAIN_POST_COMMAND, $requestInstance, $responseInstance);
297 * Executes all shutdown filters
299 * @param $requestInstance A Requestable class
300 * @param $responseInstance A Responseable class
303 public function executeShutdownFilters (Requestable $requestInstance, Responseable $responseInstance) {
304 $this->executeFilters('shutdown', $requestInstance, $responseInstance);