2 /***************************************************************
5 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
8 * This class is a backport of the corresponding class of FLOW3.
9 * All credits go to the v5 team.
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.
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
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.
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
29 * A controller argument
32 * @subpackage MVC\Controller
37 class Tx_Extbase_MVC_Controller_Argument
{
40 * @var Tx_Extbase_Persistence_QueryFactory
42 protected $queryFactory;
45 * @var Tx_Extbase_Property_Mapper
47 protected $propertyMapper;
50 * @var Tx_Extbase_Reflection_Service
52 protected $reflectionService;
55 * Name of this argument
61 * Short name of this argument
64 protected $shortName = NULL;
67 * Data type of this argument's value
70 protected $dataType = NULL;
73 * If the data type is an object, the class schema of the data type class is resolved
74 * @var Tx_Extbase_Reflection_ClassSchema
76 protected $dataTypeClassSchema;
79 * TRUE if this argument is required
82 protected $isRequired = FALSE;
85 * Actual value of this argument
88 protected $value = NULL;
91 * Default value. Used if argument is optional.
94 protected $defaultValue = NULL;
97 * A custom validator, used supplementary to the base validation
98 * @var Tx_Extbase_Validation_Validator_ValidatorInterface
100 protected $validator = NULL;
103 * Uid for the argument, if it has one
106 protected $uid = NULL;
108 const ORIGIN_CLIENT
= 0;
109 const ORIGIN_PERSISTENCE
= 1;
110 const ORIGIN_PERSISTENCE_AND_MODIFIED
= 2;
111 const ORIGIN_NEWLY_CREATED
= 3;
114 * The origin of the argument value. This is only meaningful after argument mapping.
116 * One of the ORIGIN_* constants above
119 protected $origin = 0;
122 * Constructs this controller argument
124 * @param string $name Name of this argument
125 * @param string $dataType The data type of this argument
126 * @throws InvalidArgumentException if $name is not a string or empty
129 public function __construct($name, $dataType) {
130 if (!is_string($name)) throw new InvalidArgumentException('$name must be of type string, ' . gettype($name) . ' given.', 1187951688);
131 if (strlen($name) === 0) throw new InvalidArgumentException('$name must be a non-empty string, ' . strlen($name) . ' characters given.', 1232551853);
133 $this->dataType
= $dataType;
137 * Initializes this object
141 public function initializeObject() {
142 $this->reflectionService
= t3lib_div
::makeInstance('Tx_Extbase_Reflection_Service');
143 $this->propertyMapper
= t3lib_div
::makeInstance('Tx_Extbase_Property_Mapper');
144 $this->propertyMapper
->injectReflectionService($this->reflectionService
);
145 $this->dataTypeClassSchema
= (strstr($this->dataType
, '_') !== FALSE) ?
$this->reflectionService
->getClassSchema($this->dataType
) : NULL;
149 * Injects the Persistence Manager
151 * @param Tx_Extbase_Persistence_ManagerInterface
154 public function injectPersistenceManager(Tx_Extbase_Persistence_ManagerInterface
$persistenceManager) {
155 $this->persistenceManager
= $persistenceManager;
159 * Injects a QueryFactory instance
161 * @param Tx_Extbase_Persistence_QueryFactoryInterface $queryFactory
164 public function injectQueryFactory(Tx_Extbase_Persistence_QueryFactoryInterface
$queryFactory) {
165 $this->queryFactory
= $queryFactory;
169 * Returns the name of this argument
171 * @return string This argument's name
174 public function getName() {
179 * Sets the short name of this argument.
181 * @param string $shortName A "short name" - a single character
182 * @return Tx_Extbase_MVC_Controller_Argument $this
183 * @throws InvalidArgumentException if $shortName is not a character
186 public function setShortName($shortName) {
187 if ($shortName !== NULL && (!is_string($shortName) ||
strlen($shortName) !== 1)) throw new InvalidArgumentException('$shortName must be a single character or NULL', 1195824959);
188 $this->shortName
= $shortName;
193 * Returns the short name of this argument
195 * @return string This argument's short name
198 public function getShortName() {
199 return $this->shortName
;
203 * Sets the data type of this argument's value
205 * @param string $dataType The data type. Can be either a built-in type such as "Text" or "Integer" or a fully qualified object name
206 * @return Tx_Extbase_MVC_Controller_Argument $this
209 public function setDataType($dataType) {
210 $this->dataType
= $dataType;
211 $this->dataTypeClassSchema
= $this->reflectionService
->getClassSchema($dataType);
216 * Returns the data type of this argument's value
218 * @return string The data type
221 public function getDataType() {
222 return $this->dataType
;
226 * Marks this argument to be required
228 * @param boolean $required TRUE if this argument should be required
229 * @return Tx_Extbase_MVC_Controller_Argument $this
232 public function setRequired($required) {
233 $this->isRequired
= (boolean
)$required;
238 * Returns TRUE if this argument is required
240 * @return boolean TRUE if this argument is required
243 public function isRequired() {
244 return $this->isRequired
;
248 * Sets the default value of the argument
250 * @param mixed $defaultValue Default value
254 public function setDefaultValue($defaultValue) {
255 $this->defaultValue
= $defaultValue;
259 * Returns the default value of this argument
261 * @return mixed The default value
264 public function getDefaultValue() {
265 return $this->defaultValue
;
269 * Sets a custom validator which is used supplementary to the base validation
271 * @param Tx_Extbase_Validation_Validator_ValidatorInterface $validator The actual validator object
272 * @return Tx_Extbase_MVC_Controller_Argument Returns $this (used for fluent interface)
275 public function setValidator(Tx_Extbase_Validation_Validator_ValidatorInterface
$validator) {
276 $this->validator
= $validator;
281 * Create and set a validator chain
283 * @param array Object names of the validators
284 * @return Tx_Extbase_MVC_Controller_Argument Returns $this (used for fluent interface)
287 public function setNewValidatorConjunction(array $objectNames) {
288 if ($this->validator
=== NULL) {
289 $this->validator
= t3lib_div
::makeInstance('Tx_Extbase_Validation_Validator_ConjunctionValidator');
291 foreach ($objectNames as $objectName) {
292 if (!class_exists($objectName)) $objectName = 'Tx_Extbase_Validation_Validator_' . $objectName;
293 $this->validator
->addValidator(t3lib_div
::makeInstance($objectName));
299 * Returns the set validator
301 * @return Tx_Extbase_Validation_Validator_ValidatorInterface The set validator, NULL if none was set
304 public function getValidator() {
305 return $this->validator
;
309 * Get the origin of the argument value. This is only meaningful after argument mapping.
311 * @return integer one of the ORIGIN_* constants
312 * @author Sebastian Kurfürst <sebastian@typo3.org>
314 public function getOrigin() {
315 return $this->origin
;
319 * Sets the value of this argument.
321 * @param mixed $value: The value of this argument
322 * @return Tx_Extbase_MVC_Controller_Argument $this
323 * @throws Tx_Extbase_MVC_Exception_InvalidArgumentValue if the argument is not a valid object of type $dataType
325 public function setValue($value) {
326 $this->value
= $this->transformValue($value);
332 * Checks if the value is a UUID or an array but should be an object, i.e.
333 * the argument's data type class schema is set. If that is the case, this
334 * method tries to look up the corresponding object instead.
336 * Additionally, it maps arrays to objects in case it is a normal object.
338 * @param mixed $value The value of an argument
341 protected function transformValue($value) {
342 if ($value === NULL) {
345 if (!class_exists($this->dataType
)) {
348 $transformedValue = NULL;
349 if ($this->dataTypeClassSchema
!== NULL) {
350 // The target object is an Entity or ValueObject.
351 if (is_numeric($value)) {
352 $this->origin
= self
::ORIGIN_PERSISTENCE
;
353 $transformedValue = $this->findObjectByUid($value);
354 } elseif (is_array($value)) {
355 $this->origin
= self
::ORIGIN_PERSISTENCE_AND_MODIFIED
;
356 $transformedValue = $this->propertyMapper
->map(array_keys($value), $value, $this->dataType
);
359 if (!is_array($value)) {
360 throw new Tx_Extbase_MVC_Exception_InvalidArgumentValue('The value was a simple type, so we could not map it to an object. Maybe the @entity or @valueobject annotations are missing?', 1251730701);
362 $this->origin
= self
::ORIGIN_NEWLY_CREATED
;
363 $transformedValue = $this->propertyMapper
->map(array_keys($value), $value, $this->dataType
);
366 if (!($transformedValue instanceof $this->dataType
)) {
367 if (is_object($transformedValue)) {
368 throw new Tx_Extbase_MVC_Exception_InvalidArgumentValue('The value must be of type "' . $this->dataType
. '", but was of type "' . get_class($transformedValue) . '".', 1251730701);
370 throw new Tx_Extbase_MVC_Exception_InvalidArgumentValue('The value must be of type "' . $this->dataType
. '", but was of type "' . gettype($transformedValue) . '".', 1251730702);
373 return $transformedValue;
377 * Finds an object from the repository by searching for its technical UID.
379 * @param int $uid The object's uid
380 * @return mixed Either the object matching the uid or, if none or more than one object was found, FALSE
382 protected function findObjectByUid($uid) {
383 $query = $this->queryFactory
->create($this->dataType
);
384 $query->getQuerySettings()->setRespectSysLanguage(FALSE);
385 $result = $query->matching($query->withUid($uid))->execute();
387 if (count($result) > 0) {
388 $object = current($result);
394 * Returns the value of this argument
396 * @return object The value of this argument - if none was set, NULL is returned
399 public function getValue() {
400 if ($this->value
=== NULL) {
401 return $this->defaultValue
;
408 * Checks if this argument has a value set.
410 * @return boolean TRUE if a value was set, otherwise FALSE
412 public function isValue() {
413 return $this->value
!== NULL;
417 * Returns a string representation of this argument's value
422 public function __toString() {
423 return (string)$this->value
;