[+FEATURE] Extbase (MVC): Added support of @dontvalidate annotations. Relates to...
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / MVC / Controller / Argument.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
6 * All rights reserved
7 *
8 * This class is a backport of the corresponding class of FLOW3.
9 * All credits go to the v5 team.
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * A controller argument
30 *
31 * @package Extbase
32 * @subpackage MVC\Controller
33 * @version $ID:$
34 * @scope prototype
35 */
36 class Tx_Extbase_MVC_Controller_Argument {
37
38 /**
39 * @var Tx_Extbase_Persistence_ManagerInterface
40 */
41 protected $persistenceManager;
42
43 /**
44 * @var Tx_Extbase_Persistence_QueryFactory
45 */
46 protected $queryFactory;
47
48 /**
49 * @var Tx_Extbase_Property_Mapper
50 */
51 protected $propertyMapper;
52
53 /**
54 * Name of this argument
55 * @var string
56 */
57 protected $name = '';
58
59 /**
60 * Short name of this argument
61 * @var string
62 */
63 protected $shortName = NULL;
64
65 /**
66 * Data type of this argument's value
67 * @var string
68 */
69 protected $dataType = 'Text';
70
71 /**
72 * TRUE if this argument is required
73 * @var boolean
74 */
75 protected $isRequired = FALSE;
76
77 /**
78 * Actual value of this argument
79 * @var object
80 */
81 protected $value = NULL;
82
83 /**
84 * Default value. Used if argument is optional.
85 * @var mixed
86 */
87 protected $defaultValue = NULL;
88
89 /**
90 * A custom validator, used supplementary to the base validation
91 * @var Tx_Extbase_Validation_Validator_ValidatorInterface
92 */
93 protected $validator = NULL;
94
95 /**
96 * If validation for this argument is temporarily disabled
97 * @var boolean
98 */
99 protected $validationDisabled = FALSE;
100
101 /**
102 * Uid for the argument, if it has one
103 * @var string
104 */
105 protected $uid = NULL;
106
107 /**
108 * Constructs this controller argument
109 *
110 * @param string $name Name of this argument
111 * @param string $dataType The data type of this argument
112 * @throws InvalidArgumentException if $name is not a string or empty
113 * @api
114 */
115 public function __construct($name, $dataType = 'Text') {
116 $this->propertyMapper = t3lib_div::makeInstance('Tx_Extbase_Property_Mapper');
117 if (!is_string($name) || strlen($name) < 1) throw new InvalidArgumentException('$name must be of type string, ' . gettype($name) . ' given.', 1187951688);
118 $this->name = $name;
119 if (is_array($dataType)) {
120 $this->setNewValidatorConjunction($dataType);
121 } else {
122 $this->setDataType($dataType);
123 }
124 }
125
126 /**
127 * Injects the Persistence Manager
128 *
129 * @param Tx_Extbase_Persistence_ManagerInterface
130 * @return void
131 */
132 public function injectPersistenceManager(Tx_Extbase_Persistence_ManagerInterface $persistenceManager) {
133 $this->persistenceManager = $persistenceManager;
134 }
135
136 /**
137 * Injects a QueryFactory instance
138 *
139 * @param Tx_Extbase_Persistence_QueryFactoryInterface $queryFactory
140 * @return void
141 */
142 public function injectQueryFactory(Tx_Extbase_Persistence_QueryFactoryInterface $queryFactory) {
143 $this->queryFactory = $queryFactory;
144 }
145
146 /**
147 * Returns the name of this argument
148 *
149 * @return string This argument's name
150 * @api
151 */
152 public function getName() {
153 return $this->name;
154 }
155
156 /**
157 * Sets the short name of this argument.
158 *
159 * @param string $shortName A "short name" - a single character
160 * @return Tx_Extbase_MVC_Controller_Argument $this
161 * @throws InvalidArgumentException if $shortName is not a character
162 * @api
163 */
164 public function setShortName($shortName) {
165 if ($shortName !== NULL && (!is_string($shortName) || strlen($shortName) !== 1)) throw new InvalidArgumentException('$shortName must be a single character or NULL', 1195824959);
166 $this->shortName = $shortName;
167 return $this;
168 }
169
170 /**
171 * Returns the short name of this argument
172 *
173 * @return string This argument's short name
174 * @api
175 */
176 public function getShortName() {
177 return $this->shortName;
178 }
179
180 /**
181 * Sets the data type of this argument's value
182 *
183 * @param string $dataType The data type. Can be either a built-in type such as "Text" or "Integer" or a fully qualified object name
184 * @return Tx_Extbase_MVC_Controller_Argument $this
185 * @api
186 */
187 public function setDataType($dataType) {
188 $this->dataType = $dataType;
189 return $this;
190 }
191
192 /**
193 * Returns the data type of this argument's value
194 *
195 * @return string The data type
196 * @api
197 */
198 public function getDataType() {
199 return $this->dataType;
200 }
201
202 /**
203 * Marks this argument to be required
204 *
205 * @param boolean $required TRUE if this argument should be required
206 * @return Tx_Extbase_MVC_Controller_Argument $this
207 * @api
208 */
209 public function setRequired($required) {
210 $this->isRequired = (boolean)$required;
211 return $this;
212 }
213
214 /**
215 * Returns TRUE if this argument is required
216 *
217 * @return boolean TRUE if this argument is required
218 * @api
219 */
220 public function isRequired() {
221 return $this->isRequired;
222 }
223
224 /**
225 * Sets the default value of the argument
226 *
227 * @param mixed $defaultValue Default value
228 * @return void
229 * @api
230 */
231 public function setDefaultValue($defaultValue) {
232 $this->defaultValue = $defaultValue;
233 }
234
235 /**
236 * Returns the default value of this argument
237 *
238 * @return mixed The default value
239 * @api
240 */
241 public function getDefaultValue() {
242 return $this->defaultValue;
243 }
244
245 /**
246 * Sets a custom validator which is used supplementary to the base validation
247 *
248 * @param Tx_Extbase_Validation_Validator_ValidatorInterface $validator The actual validator object
249 * @return Tx_Extbase_MVC_Controller_Argument Returns $this (used for fluent interface)
250 * @api
251 */
252 public function setValidator(Tx_Extbase_Validation_Validator_ValidatorInterface $validator) {
253 $this->validator = $validator;
254 return $this;
255 }
256
257 /**
258 * Create and set a validator chain
259 *
260 * @param array Object names of the validators
261 * @return Tx_Extbase_MVC_Controller_Argument Returns $this (used for fluent interface)
262 * @api
263 */
264 public function setNewValidatorConjunction(array $objectNames) {
265 if ($this->validator === NULL) {
266 $this->validator = t3lib_div::makeInstance('Tx_Extbase_Validation_Validator_ConjunctionValidator');
267 }
268 foreach ($objectNames as $objectName) {
269 if (!class_exists($objectName)) $objectName = 'Tx_Extbase_Validation_Validator_' . $objectName;
270 $this->validator->addValidator(t3lib_div::makeInstance($objectName));
271 }
272 return $this;
273 }
274
275 /**
276 * Returns the set validator
277 *
278 * @return Tx_Extbase_Validation_Validator_ValidatorInterface The set validator, NULL if none was set
279 * @api
280 */
281 public function getValidator() {
282 return $this->validator;
283 }
284
285 /**
286 * Returns TRUE if validation is temporarily disabled for this argument and
287 * FALSE if it's enabled.
288 *
289 * Note that this is flag is only informational and does not have any real impact
290 * on other validation methods of this argument.
291 *
292 * @return boolean If validation is disabled
293 * @api
294 */
295 public function isValidationDisabled() {
296 return $this->validationDisabled;
297 }
298
299 /**
300 * Enables validation for this argument.
301 *
302 * @return void
303 * @api
304 */
305 public function enableValidation() {
306 $this->validationDisabled = FALSE;
307 }
308
309 /**
310 * Disables validation for this argument.
311 *
312 * @return void
313 * @api
314 */
315 public function disableValidation() {
316 $this->validationDisabled = TRUE;
317 }
318
319 /**
320 * Sets the value of this argument.
321 *
322 * @param mixed $value: The value of this argument
323 * @return Tx_Extbase_MVC_Controller_Argument $this
324 * @throws Tx_Extbase_MVC_Exception_InvalidArgumentValue if the argument is not a valid object of type $dataType
325 */
326 public function setValue($value) {
327 if (is_array($value)) {
328 if (isset($value['uid'])) {
329 $existingObject = $this->findObjectByUid($value['uid']);
330 if ($existingObject === FALSE) throw new Tx_Extbase_MVC_Exception_InvalidArgumentValue('Argument "' . $this->name . '": Querying the repository for the specified object was not sucessful.', 1237305720);
331 unset($value['uid']);
332 if (count($value) === 0) {
333 $value = $existingObject;
334 } elseif ($existingObject !== NULL) {
335 $newObject = clone $existingObject;
336 if ($this->propertyMapper->map(array_keys($value), $value, $newObject)) {
337 $value = $newObject;
338 }
339 }
340 } else {
341 $newObject = t3lib_div::makeInstance($this->dataType);
342 if ($this->propertyMapper->map(array_keys($value), $value, $newObject)) {
343 $value = $newObject;
344 }
345 }
346 }
347 $this->value = $value;
348 return $this;
349 }
350
351 /**
352 * Finds an object from the repository by searching for its technical UID.
353 *
354 * @param int $uid The object's uid
355 * @return mixed Either the object matching the uid or, if none or more than one object was found, FALSE
356 */
357 protected function findObjectByUid($uid) {
358 $query = $this->queryFactory->create($this->dataType);
359 $result = $query->matching($query->withUid($uid))->execute();
360 $object = NULL;
361 if (count($result) > 0) {
362 $object = current($result);
363 // TODO Check if the object is an Aggregate Root (this can be quite difficult because we have no Repository registration
364 $this->persistenceManager->getSession()->registerReconstitutedObject($object);
365 }
366 return $object;
367 }
368
369 /**
370 * Returns the value of this argument
371 *
372 * @return object The value of this argument - if none was set, NULL is returned
373 * @api
374 */
375 public function getValue() {
376 if ($this->value === NULL) {
377 return $this->defaultValue;
378 } else {
379 return $this->value;
380 }
381 }
382
383 /**
384 * Checks if this argument has a value set.
385 *
386 * @return boolean TRUE if a value was set, otherwise FALSE
387 */
388 public function isValue() {
389 return $this->value !== NULL;
390 }
391
392 /**
393 * Returns a string representation of this argument's value
394 *
395 * @return string
396 * @api
397 */
398 public function __toString() {
399 return (string)$this->value;
400 }
401 }
402 ?>