[TASK] Replace inject methods with @inject
[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-2013 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 * @inject
40 */
41 protected $objectManager;
42
43 /**
44 * @var \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory
45 * @inject
46 */
47 protected $queryFactory;
48
49 /**
50 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
51 * @inject
52 */
53 protected $configurationManager;
54
55 /**
56 * This is the old property mapper, which has been completely rewritten for 1.4.
57 * @inject
58 *
59 * @var \TYPO3\CMS\Extbase\Property\Mapper
60 */
61 protected $deprecatedPropertyMapper;
62
63 /**
64 * The new, completely rewritten property mapper since Extbase 1.4.
65 *
66 * @var \TYPO3\CMS\Extbase\Property\PropertyMapper
67 * @inject
68 */
69 protected $propertyMapper;
70
71 /**
72 * @var \TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfiguration
73 * @inject
74 */
75 protected $propertyMappingConfiguration;
76
77 /**
78 * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
79 */
80 protected $reflectionService;
81
82 /**
83 * @var \TYPO3\CMS\Extbase\Service\TypeHandlingService
84 */
85 protected $typeHandlingService;
86
87 /**
88 * Name of this argument
89 *
90 * @var string
91 */
92 protected $name = '';
93
94 /**
95 * Short name of this argument
96 *
97 * @var string
98 */
99 protected $shortName = NULL;
100
101 /**
102 * Data type of this argument's value
103 *
104 * @var string
105 */
106 protected $dataType = NULL;
107
108 /**
109 * If the data type is an object, the class schema of the data type class is resolved
110 *
111 * @var \TYPO3\CMS\Extbase\Reflection\ClassSchema
112 */
113 protected $dataTypeClassSchema;
114
115 /**
116 * TRUE if this argument is required
117 *
118 * @var boolean
119 */
120 protected $isRequired = FALSE;
121
122 /**
123 * Actual value of this argument
124 *
125 * @var object
126 */
127 protected $value = NULL;
128
129 /**
130 * Default value. Used if argument is optional.
131 *
132 * @var mixed
133 */
134 protected $defaultValue = NULL;
135
136 /**
137 * A custom validator, used supplementary to the base validation
138 *
139 * @var \TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface
140 */
141 protected $validator = NULL;
142
143 /**
144 * The validation results. This can be asked if the argument has errors.
145 *
146 * @var \TYPO3\CMS\Extbase\Error\Result
147 */
148 protected $validationResults = NULL;
149
150 /**
151 * Uid for the argument, if it has one
152 *
153 * @var string
154 */
155 protected $uid = NULL;
156
157 const ORIGIN_CLIENT = 0;
158 const ORIGIN_PERSISTENCE = 1;
159 const ORIGIN_PERSISTENCE_AND_MODIFIED = 2;
160 const ORIGIN_NEWLY_CREATED = 3;
161
162 /**
163 * The origin of the argument value. This is only meaningful after argument mapping.
164 *
165 * One of the ORIGIN_* constants above
166 *
167 * @var integer
168 */
169 protected $origin = 0;
170
171 /**
172 * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
173 * @inject
174 */
175 protected $persistenceManager;
176
177 /**
178 * Constructs this controller argument
179 *
180 * @param string $name Name of this argument
181 * @param string $dataType The data type of this argument
182 * @throws \InvalidArgumentException if $name is not a string or empty
183 * @api
184 */
185 public function __construct($name, $dataType) {
186 if (!is_string($name)) {
187 throw new \InvalidArgumentException('$name must be of type string, ' . gettype($name) . ' given.', 1187951688);
188 }
189 if (strlen($name) === 0) {
190 throw new \InvalidArgumentException('$name must be a non-empty string, ' . strlen($name) . ' characters given.', 1232551853);
191 }
192 $this->name = $name;
193 $this->dataType = $dataType;
194 }
195
196 /**
197 * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService
198 * @return void
199 */
200 public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService) {
201 $this->reflectionService = $reflectionService;
202 // Check for classnames (which have at least one underscore or backslash)
203 $this->dataTypeClassSchema = strpbrk($this->dataType, '_\\') !== FALSE ? $this->reflectionService->getClassSchema($this->dataType) : NULL;
204 }
205
206 /**
207 * @param \TYPO3\CMS\Extbase\Service\TypeHandlingService $typeHandlingService
208 * @return void
209 */
210 public function injectTypeHandlingService(\TYPO3\CMS\Extbase\Service\TypeHandlingService $typeHandlingService) {
211 $this->typeHandlingService = $typeHandlingService;
212 $this->dataType = $this->typeHandlingService->normalizeType($this->dataType);
213 }
214
215 /**
216 * Returns the name of this argument
217 *
218 * @return string This argument's name
219 * @api
220 */
221 public function getName() {
222 return $this->name;
223 }
224
225 /**
226 * Sets the short name of this argument.
227 *
228 * @param string $shortName A "short name" - a single character
229 * @throws \InvalidArgumentException if $shortName is not a character
230 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument $this
231 * @api
232 */
233 public function setShortName($shortName) {
234 if ($shortName !== NULL && (!is_string($shortName) || strlen($shortName) !== 1)) {
235 throw new \InvalidArgumentException('$shortName must be a single character or NULL', 1195824959);
236 }
237 $this->shortName = $shortName;
238 return $this;
239 }
240
241 /**
242 * Returns the short name of this argument
243 *
244 * @return string This argument's short name
245 * @api
246 */
247 public function getShortName() {
248 return $this->shortName;
249 }
250
251 /**
252 * Sets the data type of this argument's value
253 *
254 * @param string $dataType The data type. Can be either a built-in type such as "Text" or "Integer" or a fully qualified object name
255 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument $this
256 * @api
257 */
258 public function setDataType($dataType) {
259 $this->dataType = $dataType;
260 $this->dataTypeClassSchema = $this->reflectionService->getClassSchema($dataType);
261 return $this;
262 }
263
264 /**
265 * Returns the data type of this argument's value
266 *
267 * @return string The data type
268 * @api
269 */
270 public function getDataType() {
271 return $this->dataType;
272 }
273
274 /**
275 * Marks this argument to be required
276 *
277 * @param boolean $required TRUE if this argument should be required
278 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument $this
279 * @api
280 */
281 public function setRequired($required) {
282 $this->isRequired = (boolean) $required;
283 return $this;
284 }
285
286 /**
287 * Returns TRUE if this argument is required
288 *
289 * @return boolean TRUE if this argument is required
290 * @api
291 */
292 public function isRequired() {
293 return $this->isRequired;
294 }
295
296 /**
297 * Sets the default value of the argument
298 *
299 * @param mixed $defaultValue Default value
300 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument $this
301 * @api
302 */
303 public function setDefaultValue($defaultValue) {
304 $this->defaultValue = $defaultValue;
305 return $this;
306 }
307
308 /**
309 * Returns the default value of this argument
310 *
311 * @return mixed The default value
312 * @api
313 */
314 public function getDefaultValue() {
315 return $this->defaultValue;
316 }
317
318 /**
319 * Sets a custom validator which is used supplementary to the base validation
320 *
321 * @param \TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface $validator The actual validator object
322 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument Returns $this (used for fluent interface)
323 * @api
324 */
325 public function setValidator(\TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface $validator) {
326 $this->validator = $validator;
327 return $this;
328 }
329
330 /**
331 * Create and set a validator chain
332 *
333 * @param array $objectNames Object names of the validators
334 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument Returns $this (used for fluent interface)
335 * @api
336 * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
337 */
338 public function setNewValidatorConjunction(array $objectNames) {
339 if ($this->validator === NULL) {
340 $this->validator = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Validation\\Validator\\ConjunctionValidator');
341 }
342 foreach ($objectNames as $objectName) {
343 if (!class_exists($objectName)) {
344 $objectName = 'Tx_Extbase_Validation_Validator_' . $objectName;
345 }
346 $this->validator->addValidator($this->objectManager->get($objectName));
347 }
348 return $this;
349 }
350
351 /**
352 * Returns the set validator
353 *
354 * @return \TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface The set validator, NULL if none was set
355 * @api
356 */
357 public function getValidator() {
358 return $this->validator;
359 }
360
361 /**
362 * Get the origin of the argument value. This is only meaningful after argument mapping.
363 *
364 * @return integer one of the ORIGIN_* constants
365 * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
366 */
367 public function getOrigin() {
368 return $this->origin;
369 }
370
371 /**
372 * Sets the value of this argument.
373 *
374 * @param mixed $rawValue The value of this argument
375 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument
376 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentValueException if the argument is not a valid object of type $dataType
377 */
378 public function setValue($rawValue) {
379 if ($this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) {
380 if ($rawValue === NULL) {
381 $this->value = NULL;
382 return $this;
383 }
384 if (is_object($rawValue) && $rawValue instanceof $this->dataType) {
385 $this->value = $rawValue;
386 return $this;
387 }
388 $this->value = $this->propertyMapper->convert($rawValue, $this->dataType, $this->propertyMappingConfiguration);
389 $this->validationResults = $this->propertyMapper->getMessages();
390 if ($this->validator !== NULL) {
391 // TODO: Validation API has also changed!!!
392 $validationMessages = $this->validator->validate($this->value);
393 $this->validationResults->merge($validationMessages);
394 }
395 return $this;
396 } else {
397 if ($rawValue === NULL || is_object($rawValue) && $rawValue instanceof $this->dataType) {
398 $this->value = $rawValue;
399 } else {
400 $this->value = $this->transformValue($rawValue);
401 }
402 return $this;
403 }
404 }
405
406 /**
407 * Checks if the value is a UUID or an array but should be an object, i.e.
408 * the argument's data type class schema is set. If that is the case, this
409 * method tries to look up the corresponding object instead.
410 *
411 * Additionally, it maps arrays to objects in case it is a normal object.
412 *
413 * @param mixed $value The value of an argument
414 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentValueException
415 * @return mixed
416 * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
417 */
418 protected function transformValue($value) {
419 if (!class_exists($this->dataType)) {
420 return $value;
421 }
422 $transformedValue = NULL;
423 if ($this->dataTypeClassSchema !== NULL) {
424 // The target object is an Entity or ValueObject.
425 if (is_numeric($value)) {
426 $this->origin = self::ORIGIN_PERSISTENCE;
427 $transformedValue = $this->findObjectByUid($value);
428 } elseif (is_array($value)) {
429 $this->origin = self::ORIGIN_PERSISTENCE_AND_MODIFIED;
430 $transformedValue = $this->deprecatedPropertyMapper->map(array_keys($value), $value, $this->dataType);
431 }
432 } else {
433 if (!is_array($value)) {
434 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);
435 }
436 $this->origin = self::ORIGIN_NEWLY_CREATED;
437 $transformedValue = $this->deprecatedPropertyMapper->map(array_keys($value), $value, $this->dataType);
438 }
439 if (!$transformedValue instanceof $this->dataType && ($transformedValue !== NULL || $this->isRequired())) {
440 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);
441 }
442 return $transformedValue;
443 }
444
445 /**
446 * Finds an object from the repository by searching for its technical UID.
447 *
448 * @param integer $uid The object's uid
449 * @return object Either the object matching the uid or, if none or more than one object was found, NULL
450 */
451 protected function findObjectByUid($uid) {
452 $query = $this->queryFactory->create($this->dataType);
453 $query->getQuerySettings()->setRespectSysLanguage(FALSE);
454 $query->getQuerySettings()->setRespectStoragePage(FALSE);
455 return $query->matching($query->equals('uid', $uid))->execute()->getFirst();
456 }
457
458 /**
459 * Returns the value of this argument
460 *
461 * @return object The value of this argument - if none was set, NULL is returned
462 * @api
463 */
464 public function getValue() {
465 if ($this->value === NULL) {
466 return $this->defaultValue;
467 } else {
468 return $this->value;
469 }
470 }
471
472 /**
473 * Checks if this argument has a value set.
474 *
475 * @return boolean TRUE if a value was set, otherwise FALSE
476 * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1
477 */
478 public function isValue() {
479 return $this->value !== NULL;
480 }
481
482 /**
483 * Return the Property Mapping Configuration used for this argument; can be used by the initialize*action to modify the Property Mapping.
484 *
485 * @return \TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfiguration
486 * @api
487 */
488 public function getPropertyMappingConfiguration() {
489 return $this->propertyMappingConfiguration;
490 }
491
492 /**
493 * @return boolean TRUE if the argument is valid, FALSE otherwise
494 * @api
495 */
496 public function isValid() {
497 return !$this->validationResults->hasErrors();
498 }
499
500 /**
501 * @return array<\TYPO3\CMS\Extbase\Error\Result> Validation errors which have occured.
502 * @api
503 */
504 public function getValidationResults() {
505 return $this->validationResults;
506 }
507
508 /**
509 * Returns a string representation of this argument's value
510 *
511 * @return string
512 * @api
513 */
514 public function __toString() {
515 return (string) $this->value;
516 }
517 }
518
519 ?>