ExtBase:
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / MVC / Controller / ActionController.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25 /**
26 * A multi action controller
27 *
28 * @package TYPO3
29 * @subpackage extbase
30 * @version $ID:$
31 */
32 class Tx_ExtBase_MVC_Controller_ActionController extends Tx_ExtBase_MVC_Controller_AbstractController {
33
34 /**
35 * @var boolean If initializeView() should be called on an action invocation.
36 */
37 protected $initializeView = TRUE;
38
39 /**
40 * @var Tx_ExtBase_MVC_View_AbstractView By default a view with the same name as the current action is provided. Contains NULL if none was found.
41 */
42 protected $view = NULL;
43
44 /**
45 * By default a matching view will be resolved. If this property is set, automatic resolving is disabled and the specified object is used instead.
46 * @var string
47 */
48 protected $defaultViewObjectName = 'Tx_Fluid_View_TemplateView';
49
50 /**
51 * Pattern after which the view object name is built
52 *
53 * @var string
54 */
55 // SK: Decision: Do we support "format"?
56 protected $viewObjectNamePattern = 'Tx_@extension_View_@controller@action';
57
58 /**
59 * Name of the action method
60 * @var string
61 */
62 protected $actionMethodName = 'indexAction';
63
64 /**
65 * Name of the special error action method which is called in case of errors
66 * @var string
67 */
68 protected $errorMethodName = 'errorAction';
69
70 /**
71 * Handles a request. The result output is returned by altering the given response.
72 *
73 * @param Tx_ExtBase_MVC_Request $request The request object
74 * @param Tx_ExtBase_MVC_Response $response The response, modified by this handler
75 * @return void
76 */
77 public function processRequest(Tx_ExtBase_MVC_Request $request, Tx_ExtBase_MVC_Response $response) {
78 $this->request = $request;
79 $this->request->setDispatched(TRUE);
80 $this->response = $response;
81
82 $this->actionMethodName = $this->resolveActionMethodName();
83 $this->initializeActionMethodArguments();
84 $this->initializeArguments();
85 $this->mapRequestArgumentsToLocalArguments();
86 if ($this->initializeView) $this->initializeView();
87 $this->initializeAction();
88 $this->callActionMethod();
89 }
90
91 /**
92 * Implementation of the arguments initilization in the action controller:
93 * Automatically registers arguments of the current action
94 *
95 * Don't override this method - use initializeArguments() instead.
96 *
97 * @return void
98 * @author Robert Lemke <robert@typo3.org>
99 * @see initializeArguments()
100 * @internal
101 */
102 protected function initializeActionMethodArguments() {
103 $reflectionService = t3lib_div::makeInstance('Tx_ExtBase_Reflection_Service');
104 $methodParameters = $reflectionService->getMethodParameters(get_class($this), $this->actionMethodName);
105 foreach ($methodParameters as $parameterName => $parameterInfo) {
106 $dataType = 'Text';
107 if (isset($parameterInfo['type'])) {
108 $dataType = $parameterInfo['type'];
109 } elseif ($parameterInfo['array']) {
110 $dataType = 'array';
111 }
112
113 switch($dataType) {
114 case 'string':
115 $dataType = 'Text';
116 break;
117 case 'integer':
118 case 'int':
119 $dataType = 'Integer';
120 break;
121 }
122
123 $defaultValue = (isset($parameterInfo['defaultValue']) ? $parameterInfo['defaultValue'] : NULL);
124
125 $this->arguments->addNewArgument($parameterName, $dataType, ($parameterInfo['optional'] === FALSE), $defaultValue);
126 }
127 }
128
129 /**
130 * Determines the action method and assures that the method exists.
131 *
132 * @return string The action method name
133 * @throws Tx_ExtBase_Exception_NoSuchAction if the action specified in the request object does not exist (and if there's no default action either).
134 */
135 protected function resolveActionMethodName() {
136 $actionMethodName = $this->request->getControllerActionName() . 'Action';
137 if (!method_exists($this, $actionMethodName)) throw new Tx_ExtBase_Exception_NoSuchAction('An action "' . $actionMethodName . '" does not exist in controller "' . get_class($this) . '".', 1186669086);
138 return $actionMethodName;
139 }
140
141 /**
142 * Calls the specified action method and passes the arguments.
143 * If the action returns a string, it is appended to the content in the
144 * response object.
145 *
146 * @return void
147 * @internal
148 */
149 protected function callActionMethod() {
150 $preparedArguments = array();
151 foreach ($this->arguments as $argument) {
152 $this->preProcessArgument($argument);
153 $preparedArguments[] = $argument->getValue();
154 }
155 if (!$this->arguments->areValid()) {
156 $actionResult = call_user_func(array($this, $this->errorMethodName));
157 } else {
158 $actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments);
159 }
160 if ($actionResult === NULL && $this->view instanceof Tx_ExtBase_MVC_View_ViewInterface) {
161 $this->response->appendContent($this->view->render());
162 } elseif (is_string($actionResult) && strlen($actionResult) > 0) {
163 $this->response->appendContent($actionResult);
164 }
165 }
166
167 /**
168 * This is a template method to process unvalid arguments. Overwrite this method in your concrete controller.
169 *
170 * @param Tx_ExtBase_MVC_Controller_Argument $argument The argument
171 * @return void
172 */
173 protected function preProcessArgument(Tx_ExtBase_MVC_Controller_Argument $argument) {
174 }
175
176 /**
177 * Prepares a view for the current action and stores it in $this->view.
178 * By default, this method tries to locate a view with a name matching
179 * the current action.
180 *
181 * @return void
182 */
183 protected function initializeView() {
184 $viewObjectName = ($this->defaultViewObjectName === NULL) ? $this->resolveViewObjectName() : $this->defaultViewObjectName;
185 if (!class_exists($viewObjectName)) $viewObjectName = 'Tx_ExtBase_MVC_View_EmptyView';
186
187 $this->view = t3lib_div::makeInstance($viewObjectName);
188 $this->view->setRequest($this->request);
189 $this->view->initializeView();
190 }
191
192 /**
193 * Determines the fully qualified view object name.
194 *
195 * @return string The fully qualified view object name
196 */
197 protected function resolveViewObjectName() {
198 $possibleViewName = $this->viewObjectNamePattern;
199 $extensionName = $this->request->getExtensionName();
200 $possibleViewName = str_replace('@extension', $extensionName, $possibleViewName);
201 $possibleViewName = str_replace('@controller', $this->request->getControllerName(), $possibleViewName);
202 $possibleViewName = str_replace('@action', ucfirst($this->request->getControllerActionName()), $possibleViewName);
203 return $possibleViewName;
204 }
205
206 /**
207 * Initializes the controller before invoking an action method.
208 *
209 * Override this method to solve tasks which all actions have in
210 * common.
211 *
212 * @return void
213 */
214 protected function initializeAction() {
215 }
216
217 /**
218 * A special action which is called if the originally intended action could
219 * not be called, for example if the arguments were not valid.
220 *
221 * @return string
222 */
223 protected function errorAction() {
224 $message = 'An error occurred while trying to call ' . get_class($this) . '->' . $this->actionMethodName . '(). <br />' . PHP_EOL;
225 foreach ($this->arguments as $argument) {
226 if (!$argument->isValid()) {
227 foreach ($argument->getErrors() as $errorMessage) {
228 $message .= 'Error: ' . $errorMessage . '<br />' . PHP_EOL;
229 }
230 }
231 }
232 return $message;
233 }
234 }
235 ?>