[CLEANUP] Replace wrong/old file copyright comments
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Controller / Argument.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc\Controller;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2012 Extbase Team (http://forge.typo3.org/projects/typo3v4-mvc)
8 * Extbase is a backport of TYPO3 Flow. All credits go to the TYPO3 Flow team.
9 * All rights reserved
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 * A copy is found in the textfile GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30 /**
31 * A controller argument
32 *
33 * @api
34 */
35 class Argument {
36
37 /**
38 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
39 */
40 protected $objectManager;
41
42 /**
43 * @var \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory
44 */
45 protected $queryFactory;
46
47 /**
48 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
49 */
50 protected $configurationManager;
51
52 /**
53 * This is the old property mapper, which has been completely rewritten for 1.4.
54 *
55 * @var \TYPO3\CMS\Extbase\Property\Mapper
56 */
57 protected $deprecatedPropertyMapper;
58
59 /**
60 * The new, completely rewritten property mapper since Extbase 1.4.
61 *
62 * @var \TYPO3\CMS\Extbase\Property\PropertyMapper
63 */
64 protected $propertyMapper;
65
66 /**
67 * @var \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationBuilder
68 */
69 protected $propertyMappingConfigurationBuilder;
70
71 /**
72 * @var \TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfiguration
73 */
74 protected $propertyMappingConfiguration;
75
76 /**
77 * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
78 */
79 protected $reflectionService;
80
81 /**
82 * @var \TYPO3\CMS\Extbase\Service\TypeHandlingService
83 */
84 protected $typeHandlingService;
85
86 /**
87 * Name of this argument
88 *
89 * @var string
90 */
91 protected $name = '';
92
93 /**
94 * Short name of this argument
95 *
96 * @var string
97 */
98 protected $shortName = NULL;
99
100 /**
101 * Data type of this argument's value
102 *
103 * @var string
104 */
105 protected $dataType = NULL;
106
107 /**
108 * If the data type is an object, the class schema of the data type class is resolved
109 *
110 * @var \TYPO3\CMS\Extbase\Reflection\ClassSchema
111 */
112 protected $dataTypeClassSchema;
113
114 /**
115 * TRUE if this argument is required
116 *
117 * @var boolean
118 */
119 protected $isRequired = FALSE;
120
121 /**
122 * Actual value of this argument
123 *
124 * @var object
125 */
126 protected $value = NULL;
127
128 /**
129 * Default value. Used if argument is optional.
130 *
131 * @var mixed
132 */
133 protected $defaultValue = NULL;
134
135 /**
136 * A custom validator, used supplementary to the base validation
137 *
138 * @var \TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface
139 */
140 protected $validator = NULL;
141
142 /**
143 * The validation results. This can be asked if the argument has errors.
144 *
145 * @var \TYPO3\CMS\Extbase\Error\Result
146 */
147 protected $validationResults = NULL;
148
149 /**
150 * Uid for the argument, if it has one
151 *
152 * @var string
153 */
154 protected $uid = NULL;
155
156 const ORIGIN_CLIENT = 0;
157 const ORIGIN_PERSISTENCE = 1;
158 const ORIGIN_PERSISTENCE_AND_MODIFIED = 2;
159 const ORIGIN_NEWLY_CREATED = 3;
160
161 /**
162 * The origin of the argument value. This is only meaningful after argument mapping.
163 *
164 * One of the ORIGIN_* constants above
165 *
166 * @var integer
167 */
168 protected $origin = 0;
169
170 /**
171 * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
172 */
173 protected $persistenceManager;
174
175 /**
176 * Constructs this controller argument
177 *
178 * @param string $name Name of this argument
179 * @param string $dataType The data type of this argument
180 * @throws \InvalidArgumentException if $name is not a string or empty
181 * @api
182 */
183 public function __construct($name, $dataType) {
184 if (!is_string($name)) {
185 throw new \InvalidArgumentException('$name must be of type string, ' . gettype($name) . ' given.', 1187951688);
186 }
187 if (strlen($name) === 0) {
188 throw new \InvalidArgumentException('$name must be a non-empty string, ' . strlen($name) . ' characters given.', 1232551853);
189 }
190 $this->name = $name;
191 $this->dataType = $dataType;
192 }
193
194 /**
195 * Injects the object manager
196 *
197 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
198 * @return void
199 */
200 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) {
201 $this->objectManager = $objectManager;
202 }
203
204 /**
205 * @param \TYPO3\CMS\Extbase\Property\Mapper $deprecatedPropertyMapper
206 * @return void
207 */
208 public function injectDeprecatedPropertyMapper(\TYPO3\CMS\Extbase\Property\Mapper $deprecatedPropertyMapper) {
209 $this->deprecatedPropertyMapper = $deprecatedPropertyMapper;
210 }
211
212 /**
213 * @param \TYPO3\CMS\Extbase\Property\PropertyMapper $propertyMapper
214 * @return void
215 */
216 public function injectPropertyMapper(\TYPO3\CMS\Extbase\Property\PropertyMapper $propertyMapper) {
217 $this->propertyMapper = $propertyMapper;
218 }
219
220 /**
221 * @param \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationBuilder $propertyMappingConfigurationBuilder
222 * @return void
223 */
224 public function injectPropertyMappingConfigurationBuilder(\TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationBuilder $propertyMappingConfigurationBuilder) {
225 $this->propertyMappingConfigurationBuilder = $propertyMappingConfigurationBuilder;
226 }
227
228 /**
229 * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService
230 * @return void
231 */
232 public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService) {
233 $this->reflectionService = $reflectionService;
234 // Check for classnames (which have at least one underscore or backslash)
235 $this->dataTypeClassSchema = strpbrk($this->dataType, '_\\') !== FALSE ? $this->reflectionService->getClassSchema($this->dataType) : NULL;
236 }
237
238 /**
239 * Injects the Persistence Manager
240 *
241 * @param \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
242 * @return void
243 */
244 public function injectPersistenceManager(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface $persistenceManager) {
245 $this->persistenceManager = $persistenceManager;
246 }
247
248 /**
249 * Injects a QueryFactory instance
250 *
251 * @param \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface $queryFactory
252 * @return void
253 */
254 public function injectQueryFactory(\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface $queryFactory) {
255 $this->queryFactory = $queryFactory;
256 }
257
258 /**
259 * @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
260 * @return void
261 */
262 public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager) {
263 $this->configurationManager = $configurationManager;
264 }
265
266 /**
267 * Initializer.
268 *
269 * @return void
270 */
271 public function initializeObject() {
272 $this->propertyMappingConfiguration = $this->propertyMappingConfigurationBuilder->build('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\MvcPropertyMappingConfiguration');
273 }
274
275 /**
276 * @param \TYPO3\CMS\Extbase\Service\TypeHandlingService $typeHandlingService
277 * @return void
278 */
279 public function injectTypeHandlingService(\TYPO3\CMS\Extbase\Service\TypeHandlingService $typeHandlingService) {
280 $this->typeHandlingService = $typeHandlingService;
281 $this->dataType = $this->typeHandlingService->normalizeType($this->dataType);
282 }
283
284 /**
285 * Returns the name of this argument
286 *
287 * @return string This argument's name
288 * @api
289 */
290 public function getName() {
291 return $this->name;
292 }
293
294 /**
295 * Sets the short name of this argument.
296 *
297 * @param string $shortName A "short name" - a single character
298 * @throws \InvalidArgumentException if $shortName is not a character
299 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument $this
300 * @api
301 */
302 public function setShortName($shortName) {
303 if ($shortName !== NULL && (!is_string($shortName) || strlen($shortName) !== 1)) {
304 throw new \InvalidArgumentException('$shortName must be a single character or NULL', 1195824959);
305 }
306 $this->shortName = $shortName;
307 return $this;
308 }
309
310 /**
311 * Returns the short name of this argument
312 *
313 * @return string This argument's short name
314 * @api
315 */
316 public function getShortName() {
317 return $this->shortName;
318 }
319
320 /**
321 * Sets the data type of this argument's value
322 *
323 * @param string $dataType The data type. Can be either a built-in type such as "Text" or "Integer" or a fully qualified object name
324 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument $this
325 * @api
326 */
327 public function setDataType($dataType) {
328 $this->dataType = $dataType;
329 $this->dataTypeClassSchema = $this->reflectionService->getClassSchema($dataType);
330 return $this;
331 }
332
333 /**
334 * Returns the data type of this argument's value
335 *
336 * @return string The data type
337 * @api
338 */
339 public function getDataType() {
340 return $this->dataType;
341 }
342
343 /**
344 * Marks this argument to be required
345 *
346 * @param boolean $required TRUE if this argument should be required
347 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument $this
348 * @api
349 */
350 public function setRequired($required) {
351 $this->isRequired = (boolean) $required;
352 return $this;
353 }
354
355 /**
356 * Returns TRUE if this argument is required
357 *
358 * @return boolean TRUE if this argument is required
359 * @api
360 */
361 public function isRequired() {
362 return $this->isRequired;
363 }
364
365 /**
366 * Sets the default value of the argument
367 *
368 * @param mixed $defaultValue Default value
369 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument $this
370 * @api
371 */
372 public function setDefaultValue($defaultValue) {
373 $this->defaultValue = $defaultValue;
374 return $this;
375 }
376
377 /**
378 * Returns the default value of this argument
379 *
380 * @return mixed The default value
381 * @api
382 */
383 public function getDefaultValue() {
384 return $this->defaultValue;
385 }
386
387 /**
388 * Sets a custom validator which is used supplementary to the base validation
389 *
390 * @param \TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface $validator The actual validator object
391 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument Returns $this (used for fluent interface)
392 * @api
393 */
394 public function setValidator(\TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface $validator) {
395 $this->validator = $validator;
396 return $this;
397 }
398
399 /**
400 * Create and set a validator chain
401 *
402 * @param array Object names of the validators
403 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument Returns $this (used for fluent interface)
404 * @api
405 * @deprecated since Extbase 1.4.0, will be removed in Extbase 6.1
406 */
407 public function setNewValidatorConjunction(array $objectNames) {
408 if ($this->validator === NULL) {
409 $this->validator = $this->objectManager->create('TYPO3\\CMS\\Extbase\\Validation\\Validator\\ConjunctionValidator');
410 }
411 foreach ($objectNames as $objectName) {
412 if (!class_exists($objectName)) {
413 $objectName = 'Tx_Extbase_Validation_Validator_' . $objectName;
414 }
415 $this->validator->addValidator($this->objectManager->get($objectName));
416 }
417 return $this;
418 }
419
420 /**
421 * Returns the set validator
422 *
423 * @return \TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface The set validator, NULL if none was set
424 * @api
425 */
426 public function getValidator() {
427 return $this->validator;
428 }
429
430 /**
431 * Get the origin of the argument value. This is only meaningful after argument mapping.
432 *
433 * @return integer one of the ORIGIN_* constants
434 * @author Sebastian Kurfürst <sebastian@typo3.org>
435 * @deprecated since Extbase 1.4.0, will be removed in Extbase 6.1
436 */
437 public function getOrigin() {
438 return $this->origin;
439 }
440
441 /**
442 * Sets the value of this argument.
443 *
444 * @param mixed $rawValue: The value of this argument
445 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument $this
446 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentValueException if the argument is not a valid object of type $dataType
447 */
448 public function setValue($rawValue) {
449 if ($this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) {
450 if ($rawValue === NULL) {
451 $this->value = NULL;
452 return $this;
453 }
454 if (is_object($rawValue) && $rawValue instanceof $this->dataType) {
455 $this->value = $rawValue;
456 return $this;
457 }
458 $this->value = $this->propertyMapper->convert($rawValue, $this->dataType, $this->propertyMappingConfiguration);
459 $this->validationResults = $this->propertyMapper->getMessages();
460 if ($this->validator !== NULL) {
461 // TODO: Validation API has also changed!!!
462 $validationMessages = $this->validator->validate($this->value);
463 $this->validationResults->merge($validationMessages);
464 }
465 return $this;
466 } else {
467 if ($rawValue === NULL || is_object($rawValue) && $rawValue instanceof $this->dataType) {
468 $this->value = $rawValue;
469 } else {
470 $this->value = $this->transformValue($rawValue);
471 }
472 return $this;
473 }
474 }
475
476 /**
477 * Checks if the value is a UUID or an array but should be an object, i.e.
478 * the argument's data type class schema is set. If that is the case, this
479 * method tries to look up the corresponding object instead.
480 *
481 * Additionally, it maps arrays to objects in case it is a normal object.
482 *
483 * @param mixed $value The value of an argument
484 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentValueException
485 * @return mixed
486 * @deprecated since Extbase 1.4.0, will be removed in Extbase 6.1
487 */
488 protected function transformValue($value) {
489 if (!class_exists($this->dataType)) {
490 return $value;
491 }
492 $transformedValue = NULL;
493 if ($this->dataTypeClassSchema !== NULL) {
494 // The target object is an Entity or ValueObject.
495 if (is_numeric($value)) {
496 $this->origin = self::ORIGIN_PERSISTENCE;
497 $transformedValue = $this->findObjectByUid($value);
498 } elseif (is_array($value)) {
499 $this->origin = self::ORIGIN_PERSISTENCE_AND_MODIFIED;
500 $transformedValue = $this->deprecatedPropertyMapper->map(array_keys($value), $value, $this->dataType);
501 }
502 } else {
503 if (!is_array($value)) {
504 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentValueException('The value was a simple type, so we could not map it to an object. Maybe the @entity or @valueobject annotations are missing?', 1251730701);
505 }
506 $this->origin = self::ORIGIN_NEWLY_CREATED;
507 $transformedValue = $this->deprecatedPropertyMapper->map(array_keys($value), $value, $this->dataType);
508 }
509 if (!$transformedValue instanceof $this->dataType && ($transformedValue !== NULL || $this->isRequired())) {
510 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentValueException('The value must be of type "' . $this->dataType . '", but was of type "' . (is_object($transformedValue) ? get_class($transformedValue) : gettype($transformedValue)) . '".' . ($this->deprecatedPropertyMapper->getMappingResults()->hasErrors() ? '<p>' . implode('<br />', $this->deprecatedPropertyMapper->getMappingResults()->getErrors()) . '</p>' : ''), 1251730701);
511 }
512 return $transformedValue;
513 }
514
515 /**
516 * Finds an object from the repository by searching for its technical UID.
517 *
518 * @param integer $uid The object's uid
519 * @return object Either the object matching the uid or, if none or more than one object was found, NULL
520 */
521 protected function findObjectByUid($uid) {
522 $query = $this->queryFactory->create($this->dataType);
523 $query->getQuerySettings()->setRespectSysLanguage(FALSE);
524 $query->getQuerySettings()->setRespectStoragePage(FALSE);
525 return $query->matching($query->equals('uid', $uid))->execute()->getFirst();
526 }
527
528 /**
529 * Returns the value of this argument
530 *
531 * @return object The value of this argument - if none was set, NULL is returned
532 * @api
533 */
534 public function getValue() {
535 if ($this->value === NULL) {
536 return $this->defaultValue;
537 } else {
538 return $this->value;
539 }
540 }
541
542 /**
543 * Checks if this argument has a value set.
544 *
545 * @return boolean TRUE if a value was set, otherwise FALSE
546 * @deprecated since Extbase 1.4.0, will be removed with Extbase 6.1
547 */
548 public function isValue() {
549 return $this->value !== NULL;
550 }
551
552 /**
553 * Return the Property Mapping Configuration used for this argument; can be used by the initialize*action to modify the Property Mapping.
554 *
555 * @return \TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfiguration
556 * @author Sebastian Kurfürst <sebastian@typo3.org>
557 * @api
558 */
559 public function getPropertyMappingConfiguration() {
560 return $this->propertyMappingConfiguration;
561 }
562
563 /**
564 * @return boolean TRUE if the argument is valid, FALSE otherwise
565 * @author Sebastian Kurfürst <sebastian@typo3.org>
566 * @api
567 */
568 public function isValid() {
569 return !$this->validationResults->hasErrors();
570 }
571
572 /**
573 * @return array<\TYPO3\CMS\Extbase\Error\Result> Validation errors which have occured.
574 * @author Sebastian Kurfürst <sebastian@typo3.org>
575 * @api
576 */
577 public function getValidationResults() {
578 return $this->validationResults;
579 }
580
581 /**
582 * Returns a string representation of this argument's value
583 *
584 * @return string
585 * @api
586 */
587 public function __toString() {
588 return (string) $this->value;
589 }
590 }
591
592 ?>