3 namespace CoreFramework\Controller;
5 // Import framework stuff
6 use CoreFramework\Object\BaseFrameworkSystem;
9 * A generic controller class. You should extend this base class if you want to
10 * write your own controller. You get the advantage that you can use the pre and
13 * @author Roland Haeder <webmaster@shipsimu.org>
15 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
16 * @license GNU GPL 3.0 or any newer version
17 * @link http://www.shipsimu.org
19 * This program is free software: you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation, either version 3 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 class BaseController extends BaseFrameworkSystem implements Registerable {
33 // Exception constants
34 const EXCEPTION_FILTER_CHAIN_INVALID = 0xf10;
36 // Names of controller's own filter chains
37 const FILTER_CHAIN_PRE_COMMAND = 'controller_pre_command';
38 const FILTER_CHAIN_POST_COMMAND = 'controller_post_command';
41 * Generic filter chains
43 private $filterChains = array();
46 * Protected constructor
48 * @param $className Name of the class
51 protected function __construct ($className) {
52 // Call parent constructor
53 parent::__construct($className);
55 // Initialize both filter chains
56 $this->initFilterChain(self::FILTER_CHAIN_PRE_COMMAND);
57 $this->initFilterChain(self::FILTER_CHAIN_POST_COMMAND);
59 // Add this controller to the registry
60 Registry::getRegistry()->addInstance('controller', $this);
64 * Executes a command with pre and post filters
66 * @param $requestInstance A Requestable class
67 * @param $responseInstance A Responseable class
70 public function executeGenericPrePostCommand (Requestable $requestInstance, Responseable $responseInstance) {
71 // Get the command instance from the resolver by sending a request instance to the resolver
72 $commandInstance = $this->getResolverInstance()->resolveCommandByRequest($requestInstance);
74 // Add more filters by the command
75 $commandInstance->addExtraFilters($this, $requestInstance);
77 // Run the pre filters
78 $this->executePreFilters($requestInstance, $responseInstance);
80 // This request was valid! :-D
81 $requestInstance->requestIsValid();
83 // Execute the command
84 $commandInstance->execute($requestInstance, $responseInstance);
86 // Run the post filters
87 $this->executePostFilters($requestInstance, $responseInstance);
89 // Flush the response out
90 $responseInstance->flushBuffer();
94 * Handles the given request and response, redirects to login_failed if
95 * UserAuthorizationException is thrown.
97 * @param $requestInstance An instance of a request class
98 * @param $responseInstance An instance of a response class
101 public function genericHanleRequestLoginFailedRedirect (Requestable $requestInstance, Responseable $responseInstance) {
102 // Get the "form action"
103 $formAction = $requestInstance->getRequestElement('form');
105 // Get command instance from resolver
106 $commandInstance = $this->getResolverInstance()->resolveCommand($formAction);
108 // Add more filters by the command
109 $commandInstance->addExtraFilters($this, $requestInstance);
111 // Try to run the pre filters, if auth exceptions come through redirect here
113 // Run the pre filters
114 $this->executePreFilters($requestInstance, $responseInstance);
115 } catch (UserAuthorizationException $e) {
116 // Redirect to main page
117 $responseInstance->redirectToConfiguredUrl('login_failed');
124 * Is the request still valid? Post filters shall only be executed of
125 * the request is valid
127 if ($requestInstance->isRequestValid()) {
128 // Execute the command
129 $commandInstance->execute($requestInstance, $responseInstance);
131 // Execute *very* generic ppost filters
132 $this->executePostFilters($requestInstance, $responseInstance);
135 // Flush the buffer out
136 $responseInstance->flushBuffer();
140 * Generic execute of the command: pre and post filters with redirect
141 * but request becomes valid after pre-filters run.
143 * @param $requestInstance An instance of a request class
144 * @param $responseInstance An instance of a response class
147 public function genericHanleRequestLoginAreaFailedRedirect (Requestable $requestInstance, Responseable $responseInstance) {
148 // Get the command instance from the resolver by sending a request instance to the resolver
149 $commandInstance = $this->getResolverInstance()->resolveCommandByRequest($requestInstance);
151 // Add more filters by the command
152 $commandInstance->addExtraFilters($this, $requestInstance);
154 // Try to run the pre filters, if auth exceptions come through redirect here
156 // Run the pre filters
157 $this->executePreFilters($requestInstance, $responseInstance);
158 } catch (UserAuthorizationException $e) {
159 // Redirect to main page
160 $responseInstance->redirectToConfiguredUrl('login_failed');
166 // This request was valid! :-D
167 $requestInstance->requestIsValid();
169 // Execute the command
170 $commandInstance->execute($requestInstance, $responseInstance);
172 // Run the pre filters
173 $this->executePostFilters($requestInstance, $responseInstance);
175 // Flush the response out
176 $responseInstance->flushBuffer();
180 * Private method to initialize a given filter chain
182 * @param $filterChain Name of the filter chain
185 protected function initFilterChain ($filterChain) {
186 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONTROLLER: ' . $filterChain . ' init: START');
187 $this->filterChains[$filterChain] = ObjectFactory::createObjectByConfiguredName('filter_chain_class');
188 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONTROLLER: ' . $filterChain . ' init: FINISHED');
192 * Adds a filter to a given filter chain
194 * @param $filterChain Chain of the filter
195 * @param $filterInstance An instance of a filter
197 * @throws InvalidFilterChainException If the filter chain is invalid
199 protected function addFilter ($filterChain, Filterable $filterInstance) {
200 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONTROLLER: ' . $filterChain . ',' . $filterInstance->__toString(). ' add: START');
202 // Test if the filter is there
203 if (!isset($this->filterChains[$filterChain])) {
204 // Throw an exception here
205 throw new InvalidFilterChainException(array($this, $filterChain), self::EXCEPTION_FILTER_CHAIN_INVALID);
209 $this->filterChains[$filterChain]->addFilter($filterInstance);
210 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('CONTROLLER: ' . $filterChain . ',' . $filterInstance->__toString(). ' add: FINISH');
214 * Adds a filter to the pre filter chain
216 * @param $filterInstance An instance of a filter
219 public function addPreFilter (Filterable $filterInstance) {
220 // Add the pre filter
221 $this->addFilter(self::FILTER_CHAIN_PRE_COMMAND, $filterInstance);
225 * Adds a filter to the post filter chain
227 * @param $filterInstance An instance of a filter
230 public function addPostFilter (Filterable $filterInstance) {
231 // Add the post filter
232 $this->addFilter(self::FILTER_CHAIN_POST_COMMAND, $filterInstance);
236 * Add a shutdown filter
238 * @param $filterInstance A Filterable class
241 public function addShutdownFilter (Filterable $filterInstance) {
242 $this->addFilter('shutdown', $filterInstance);
246 * Executes given filter chain chain
248 * @param $filterChain Chain of the filter to execute
249 * @param $requestInstance An instance of a request class
250 * @param $responseInstance An instance of a response class
252 * @throws InvalidFilterChainException If the filter chain is invalid
254 protected function executeFilters ($filterChain, Requestable $requestInstance, Responseable $responseInstance) {
255 // Test if the filter is there
256 if (!isset($this->filterChains[$filterChain])) {
257 // Throw an exception here
258 throw new InvalidFilterChainException(array($this, $filterChain), self::EXCEPTION_FILTER_CHAIN_INVALID);
262 $this->filterChains[$filterChain]->processFilters($requestInstance, $responseInstance);
266 * Executes all pre filters
268 * @param $requestInstance An instance of a request class
269 * @param $responseInstance An instance of a response class
272 protected function executePreFilters (Requestable $requestInstance, Responseable $responseInstance) {
273 // Execute all pre filters
274 $this->executeFilters(self::FILTER_CHAIN_PRE_COMMAND, $requestInstance, $responseInstance);
278 * Executes all post filters
280 * @param $requestInstance An instance of a request class
281 * @param $responseInstance An instance of a response class
284 protected function executePostFilters (Requestable $requestInstance, Responseable $responseInstance) {
285 // Execute all post filters
286 $this->executeFilters(self::FILTER_CHAIN_POST_COMMAND, $requestInstance, $responseInstance);
290 * Executes all shutdown filters
292 * @param $requestInstance A Requestable class
293 * @param $responseInstance A Responseable class
296 public function executeShutdownFilters (Requestable $requestInstance, Responseable $responseInstance) {
297 $this->executeFilters('shutdown', $requestInstance, $responseInstance);