[FEATURE] Run CommandController commands through Scheduler
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Scheduler / FieldProvider.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2011 Claus Due, Wildside A/S <claus@wildside.dk>
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 * Field provider for Extbase CommandController Scheduler task
27 *
28 * @package Extbase
29 * @subpackage Scheduler
30 */
31 class Tx_Extbase_Scheduler_FieldProvider implements Tx_Scheduler_AdditionalFieldProvider {
32
33 /**
34 * @var Tx_Extbase_MVC_CLI_CommandManager
35 */
36 protected $commandManager;
37
38 /**
39 * @var Tx_Extbase_Object_ObjectManagerInterface
40 */
41 protected $objectManager;
42
43 /**
44 * @var Tx_Extbase_Reflection_Service
45 */
46 protected $reflectionService;
47
48 /**
49 * @var Tx_Extbase_Scheduler_Task
50 */
51 protected $task;
52
53 /**
54 * Constructor
55 *
56 * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
57 * @param Tx_Extbase_MVC_CLI_CommandManager $commandManager
58 * @param Tx_Extbase_Reflection_Service $reflectionService
59 */
60 public function __construct(Tx_Extbase_Object_ObjectManagerInterface $objectManager = NULL, Tx_Extbase_MVC_CLI_CommandManager $commandManager = NULL, Tx_Extbase_Reflection_Service $reflectionService = NULL) {
61 $this->objectManager = $objectManager !== NULL ? $objectManager : t3lib_div::makeInstance('Tx_Extbase_Object_ObjectManager');
62 $this->commandManager = $commandManager !== NULL ? $commandManager : $this->objectManager->get('Tx_Extbase_MVC_CLI_CommandManager');
63 $this->reflectionService = $reflectionService !== NULL ? $reflectionService : $this->objectManager->get('Tx_Extbase_Reflection_Service');
64 }
65
66 /**
67 * Render additional information fields within the scheduler backend.
68 *
69 * @param array $taskInfo Array information of task to return
70 * @param mixed $task Tx_Extbase_Scheduler_Task or tx_scheduler_Execution instance
71 * @param Tx_Scheduler_Module $schedulerModule Reference to the calling object (BE module of the Scheduler)
72 * @return array Additional fields
73 * @see interfaces/tx_scheduler_AdditionalFieldProvider#getAdditionalFields($taskInfo, $task, $schedulerModule)
74 */
75 public function getAdditionalFields(array &$taskInfo, $task, Tx_Scheduler_Module $schedulerModule) {
76 $this->task = $task;
77 if ($this->task !== NULL) {
78 $this->task->setScheduler();
79 }
80 $fields = array();
81 $fields['action'] = $this->getCommandControllerActionField();
82 if ($this->task !== NULL && $this->task->getCommandIdentifier()) {
83 $command = $this->commandManager->getCommandByIdentifier($this->task->getCommandIdentifier());
84 $fields['description'] = $this->getCommandControllerActionDescriptionField();
85 $argumentFields = $this->getCommandControllerActionArgumentFields($command->getArgumentDefinitions());
86 $fields = array_merge($fields, $argumentFields);
87 $this->task->save();
88 }
89 return $fields;
90 }
91
92 /**
93 * Validates additional selected fields
94 *
95 * @param array $submittedData
96 * @param Tx_Scheduler_Module $schedulerModule
97 * @return boolean
98 */
99 public function validateAdditionalFields(array &$submittedData, Tx_Scheduler_Module $schedulerModule) {
100 return TRUE;
101 }
102
103 /**
104 * Saves additional field values
105 *
106 * @param array $submittedData
107 * @param Tx_Scheduler_Task $task
108 * @return boolean
109 */
110 public function saveAdditionalFields(array $submittedData, Tx_Scheduler_Task $task) {
111 $task->setCommandIdentifier($submittedData['task_extbase']['action']);
112 $task->setArguments($submittedData['task_extbase']['arguments']);
113 return TRUE;
114 }
115
116 /**
117 * Get description of selected command
118 *
119 * @return string
120 */
121 protected function getCommandControllerActionDescriptionField() {
122 $command = $this->commandManager->getCommandByIdentifier($this->task->getCommandIdentifier());
123 return array(
124 'code' => '',
125 'label' => '<strong>' . $command->getDescription() . '</strong>'
126 );
127 }
128
129 /**
130 * Gets a select field containing all possible CommandController actions
131 *
132 * @return array
133 */
134 protected function getCommandControllerActionField() {
135 $commands = $this->commandManager->getAvailableCommands();
136 $options = array();
137 foreach ($commands as $command) {
138 if ($command->isInternal() === FALSE) {
139 $classNameParts = explode('_', $command->getControllerClassName());
140 $identifier = $command->getCommandIdentifier();
141 $options[$identifier] = $classNameParts[1] . ' ' . str_replace('CommandController', '', $classNameParts[3]) . ': ' . $command->getControllerCommandName();
142 }
143 }
144 $name = "action";
145 $currentlySelectedCommand = $this->task !== NULL ? $this->task->getCommandIdentifier() : NULL;
146 return array(
147 'code' => $this->renderSelectField($name, $options, $currentlySelectedCommand),
148 'label' => $this->getActionLabel()
149 );
150 }
151
152 /**
153 * Gets a set of fields covering arguments which must be sent to $currentControllerAction.
154 * Also registers the default values of those fields with the Task, allowing
155 * them to be read upon execution.
156 *
157 * @param array $argumentDefinitions
158 * @return array
159 */
160 protected function getCommandControllerActionArgumentFields(array $argumentDefinitions) {
161 $fields = array();
162 $argumentValues = $this->task->getArguments();
163 foreach ($argumentDefinitions as $index=>$argument) {
164 $name = $argument->getName();
165 $defaultValue = $this->getDefaultArgumentValue($argument);
166 $this->task->addDefaultValue($name, $defaultValue);
167 $value = isset($argumentValues[$name]) ? $argumentValues[$name] : $defaultValue;
168 $fields[$name] = array(
169 'code' => $this->renderField($argument, $value),
170 'label' => $this->getArgumentLabel($argument)
171 );
172 }
173 return $fields;
174 }
175
176 /**
177 * Gets a label for $key based on either provided extension or currently
178 * selected CommandController extension,ยด
179 *
180 * @param string $localLanguageKey
181 * @param string $extensionName
182 * @return string
183 */
184 protected function getLanguageLabel($localLanguageKey, $extensionName = NULL) {
185 if (!$extensionName) {
186 list ($extensionName, $commandControllerName, $commandName) = explode(':', $this->task->getCommandIdentifier());
187 }
188 $label = Tx_Extbase_Utility_Localization::translate($localLanguageKey, $extensionName);
189 return $label;
190 }
191
192 /**
193 * Gets the data type required for the argument value
194 *
195 * @param Tx_Extbase_MVC_CLI_CommandArgumentDefinition $argument
196 * @return string the argument type
197 */
198 protected function getArgumentType(Tx_Extbase_MVC_CLI_CommandArgumentDefinition $argument) {
199 $command = $this->commandManager->getCommandByIdentifier($this->task->getCommandIdentifier());
200 $controllerClassName = $command->getControllerClassName();
201 $methodName = $command->getControllerCommandName() . 'Command';
202 $tags = $this->reflectionService->getMethodTagsValues($controllerClassName, $methodName);
203 foreach ($tags['param'] as $tag) {
204 list ($argumentType, $argumentVariableName) = explode(' ', $tag);
205 if (substr($argumentVariableName, 1) === $argument->getName()) {
206 return $argumentType;
207 }
208 }
209 }
210
211 /**
212 * Get a human-readable label for a command argument
213 *
214 * @param Tx_Extbase_MVC_CLI_CommandArgumentDefinition $argument
215 * @return string
216 */
217 protected function getArgumentLabel(Tx_Extbase_MVC_CLI_CommandArgumentDefinition $argument) {
218 $argumentName = $argument->getName();
219 list ($extensionName, $commandControllerName, $commandName) = explode(':', $this->task->getCommandIdentifier());
220 $path = array('command', $commandControllerName, $commandName, 'arguments', $argumentName);
221 $labelNameIndex = implode('.', $path);
222 $label = $this->getLanguageLabel($labelNameIndex);
223 if (!$label) {
224 $label = 'Argument: ' . $argumentName;
225 }
226 $descriptionIndex = $labelNameIndex . '.description';
227 $description = $this->getLanguageLabel($descriptionIndex);
228 if (strlen($description) === 0) {
229 $description = $argument->getDescription();
230 }
231 if (strlen($description) > 0) {
232 $label .= '. <em>' . htmlspecialchars($description) . '</em>';
233 }
234 return $label;
235 }
236
237 /**
238 * Gets the default value of argument
239 *
240 * @param Tx_Extbase_MVC_CLI_CommandArgumentDefinition $argument
241 * @return mixed
242 */
243 protected function getDefaultArgumentValue(Tx_Extbase_MVC_CLI_CommandArgumentDefinition $argument) {
244 $type = $this->getArgumentType($argument);
245 $argumentName = $argument->getName();
246 $command = $this->commandManager->getCommandByIdentifier($this->task->getCommandIdentifier());
247 $argumentReflection = $this->reflectionService->getMethodParameters($command->getControllerClassName(), $command->getControllerCommandName() . 'Command');
248 $defaultValue = $argumentReflection[$argumentName]['defaultValue'];
249 if ($type === 'boolean') {
250 $defaultValue = ((bool) $defaultValue) ? 1 : 0;
251 }
252 return $defaultValue;
253 }
254
255 /**
256 * Get a human-readable label for the action field
257 *
258 * @return string
259 */
260 protected function getActionLabel() {
261 $index = 'task.action';
262 $label = $this->getLanguageLabel($index, 'extbase');
263 if (!$label) {
264 $label = 'CommandController Command. <em>Save and reopen to define command arguments</em>';
265 }
266 return $label;
267 }
268
269 /**
270 * Render a select field with name $name and options $options
271 *
272 * @param string $name
273 * @param array $options
274 * @param string $selectedOptionValue
275 * @return string
276 */
277 protected function renderSelectField($name, array $options, $selectedOptionValue) {
278 $html = array(
279 '<select name="tx_scheduler[task_extbase][' . htmlspecialchars($name) . ']">'
280 );
281 foreach ($options as $optionValue=>$optionLabel) {
282 $selected = $optionValue === $selectedOptionValue ? ' selected="selected"' : '';
283 array_push($html, '<option title="test" value="' . htmlspecialchars($optionValue) . '"' . $selected . '>' . htmlspecialchars($optionLabel) . '</option>');
284 }
285 array_push($html, '</select>');
286 return implode(LF, $html);
287 }
288
289 /**
290 * Renders a field for defining an argument's value
291 *
292 * @param Tx_Extbase_MVC_CLI_CommandArgumentDefinition $argument
293 * @param mixed $currentValue
294 * @return string
295 */
296 protected function renderField(Tx_Extbase_MVC_CLI_CommandArgumentDefinition $argument, $currentValue) {
297 $type = $this->getArgumentType($argument);
298 $name = $argument->getName();
299 $fieldName = 'tx_scheduler[task_extbase][arguments][' . htmlspecialchars($name) . ']';
300 if ($type === 'boolean') {
301 // checkbox field for boolean values.
302 $html = '<input type="hidden" name="' . $fieldName . '" value="0" />';
303 $html .= '<input type="checkbox" name="' . $fieldName . '" value="1" ' . ((boolean)$currentValue ? ' checked="checked"' : '') . '/>';
304 } else {
305 // regular string, also the default field type
306 $html = '<input type="text" name="' . $fieldName . '" value="' . htmlspecialchars($currentValue) . '" /> ';
307 }
308 return $html;
309 }
310
311 }
312
313 ?>