TYPO3 API  SVNRelease
Argument.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
00006 *  All rights reserved
00007 *
00008 *  This class is a backport of the corresponding class of FLOW3.
00009 *  All credits go to the v5 team.
00010 *
00011 *  This script is part of the TYPO3 project. The TYPO3 project is
00012 *  free software; you can redistribute it and/or modify
00013 *  it under the terms of the GNU General Public License as published by
00014 *  the Free Software Foundation; either version 2 of the License, or
00015 *  (at your option) any later version.
00016 *
00017 *  The GNU General Public License can be found at
00018 *  http://www.gnu.org/copyleft/gpl.html.
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00027 
00028 /**
00029  * A controller argument
00030  *
00031  * @package Extbase
00032  * @subpackage MVC\Controller
00033  * @version $ID:$
00034  * @scope prototype
00035  * @api
00036  */
00037 class Tx_Extbase_MVC_Controller_Argument {
00038 
00039     /**
00040      * @var Tx_Extbase_Object_ObjectManagerInterface
00041      */
00042     protected $objectManager;
00043 
00044     /**
00045      * @var Tx_Extbase_Persistence_QueryFactory
00046      */
00047     protected $queryFactory;
00048 
00049     /**
00050      * @var Tx_Extbase_Property_Mapper
00051      */
00052     protected $propertyMapper;
00053 
00054     /**
00055      * @var Tx_Extbase_Reflection_Service
00056      */
00057     protected $reflectionService;
00058 
00059     /**
00060      * Name of this argument
00061      * @var string
00062      */
00063     protected $name = '';
00064 
00065     /**
00066      * Short name of this argument
00067      * @var string
00068      */
00069     protected $shortName = NULL;
00070 
00071     /**
00072      * Data type of this argument's value
00073      * @var string
00074      */
00075     protected $dataType = NULL;
00076 
00077     /**
00078      * If the data type is an object, the class schema of the data type class is resolved
00079      * @var Tx_Extbase_Reflection_ClassSchema
00080      */
00081     protected $dataTypeClassSchema;
00082 
00083     /**
00084      * TRUE if this argument is required
00085      * @var boolean
00086      */
00087     protected $isRequired = FALSE;
00088 
00089     /**
00090      * Actual value of this argument
00091      * @var object
00092      */
00093     protected $value = NULL;
00094 
00095     /**
00096      * Default value. Used if argument is optional.
00097      * @var mixed
00098      */
00099     protected $defaultValue = NULL;
00100 
00101     /**
00102      * A custom validator, used supplementary to the base validation
00103      * @var Tx_Extbase_Validation_Validator_ValidatorInterface
00104      */
00105     protected $validator = NULL;
00106 
00107     /**
00108      * Uid for the argument, if it has one
00109      * @var string
00110      */
00111     protected $uid = NULL;
00112 
00113     const ORIGIN_CLIENT = 0;
00114     const ORIGIN_PERSISTENCE = 1;
00115     const ORIGIN_PERSISTENCE_AND_MODIFIED = 2;
00116     const ORIGIN_NEWLY_CREATED = 3;
00117 
00118     /**
00119      * The origin of the argument value. This is only meaningful after argument mapping.
00120      *
00121      * One of the ORIGIN_* constants above
00122      * @var integer
00123      */
00124     protected $origin = 0;
00125 
00126     /**
00127      * Constructs this controller argument
00128      *
00129      * @param string $name Name of this argument
00130      * @param string $dataType The data type of this argument
00131      * @throws InvalidArgumentException if $name is not a string or empty
00132      * @api
00133      */
00134     public function __construct($name, $dataType) {
00135         if (!is_string($name)) throw new InvalidArgumentException('$name must be of type string, ' . gettype($name) . ' given.', 1187951688);
00136         if (strlen($name) === 0) throw new InvalidArgumentException('$name must be a non-empty string, ' . strlen($name) . ' characters given.', 1232551853);
00137         $this->name = $name;
00138         $this->dataType = $dataType;
00139     }
00140 
00141     /**
00142      * Injects the object manager
00143      *
00144      * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
00145      * @return void
00146      */
00147     public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
00148         $this->objectManager = $objectManager;
00149     }
00150 
00151     /**
00152      * @param Tx_Extbase_Property_Mapper $propertyMapper
00153      * @return void
00154      */
00155     public function injectPropertyMapper(Tx_Extbase_Property_Mapper $propertyMapper) {
00156         $this->propertyMapper = $propertyMapper;
00157     }
00158 
00159     /**
00160      * @param Tx_Extbase_Reflection_Service $reflectionService
00161      * @return void
00162      */
00163     public function injectReflectionService(Tx_Extbase_Reflection_Service $reflectionService) {
00164         $this->reflectionService = $reflectionService;
00165         $this->dataTypeClassSchema = (strstr($this->dataType, '_') !== FALSE) ? $this->reflectionService->getClassSchema($this->dataType) : NULL;
00166     }
00167 
00168     /**
00169      * Injects the Persistence Manager
00170      *
00171      * @param Tx_Extbase_Persistence_ManagerInterface
00172      * @return void
00173      */
00174     public function injectPersistenceManager(Tx_Extbase_Persistence_ManagerInterface $persistenceManager) {
00175         $this->persistenceManager = $persistenceManager;
00176     }
00177 
00178     /**
00179      * Injects a QueryFactory instance
00180      *
00181      * @param Tx_Extbase_Persistence_QueryFactoryInterface $queryFactory
00182      * @return void
00183      */
00184     public function injectQueryFactory(Tx_Extbase_Persistence_QueryFactoryInterface $queryFactory) {
00185         $this->queryFactory = $queryFactory;
00186     }
00187 
00188     /**
00189      * Returns the name of this argument
00190      *
00191      * @return string This argument's name
00192      * @api
00193      */
00194     public function getName() {
00195         return $this->name;
00196     }
00197 
00198     /**
00199      * Sets the short name of this argument.
00200      *
00201      * @param string $shortName A "short name" - a single character
00202      * @return Tx_Extbase_MVC_Controller_Argument $this
00203      * @throws InvalidArgumentException if $shortName is not a character
00204      * @api
00205      */
00206     public function setShortName($shortName) {
00207         if ($shortName !== NULL && (!is_string($shortName) || strlen($shortName) !== 1)) throw new InvalidArgumentException('$shortName must be a single character or NULL', 1195824959);
00208         $this->shortName = $shortName;
00209         return $this;
00210     }
00211 
00212     /**
00213      * Returns the short name of this argument
00214      *
00215      * @return string This argument's short name
00216      * @api
00217      */
00218     public function getShortName() {
00219         return $this->shortName;
00220     }
00221 
00222     /**
00223      * Sets the data type of this argument's value
00224      *
00225      * @param string $dataType The data type. Can be either a built-in type such as "Text" or "Integer" or a fully qualified object name
00226      * @return Tx_Extbase_MVC_Controller_Argument $this
00227      * @api
00228      */
00229     public function setDataType($dataType) {
00230         $this->dataType = $dataType;
00231         $this->dataTypeClassSchema = $this->reflectionService->getClassSchema($dataType);
00232         return $this;
00233     }
00234 
00235     /**
00236      * Returns the data type of this argument's value
00237      *
00238      * @return string The data type
00239      * @api
00240      */
00241     public function getDataType() {
00242         return $this->dataType;
00243     }
00244 
00245     /**
00246      * Marks this argument to be required
00247      *
00248      * @param boolean $required TRUE if this argument should be required
00249      * @return Tx_Extbase_MVC_Controller_Argument $this
00250      * @api
00251      */
00252     public function setRequired($required) {
00253         $this->isRequired = (boolean)$required;
00254         return $this;
00255     }
00256 
00257     /**
00258      * Returns TRUE if this argument is required
00259      *
00260      * @return boolean TRUE if this argument is required
00261      * @api
00262      */
00263     public function isRequired() {
00264         return $this->isRequired;
00265     }
00266 
00267     /**
00268      * Sets the default value of the argument
00269      *
00270      * @param mixed $defaultValue Default value
00271      * @return void
00272      * @api
00273      */
00274     public function setDefaultValue($defaultValue) {
00275         $this->defaultValue = $defaultValue;
00276     }
00277 
00278     /**
00279      * Returns the default value of this argument
00280      *
00281      * @return mixed The default value
00282      * @api
00283      */
00284     public function getDefaultValue() {
00285         return $this->defaultValue;
00286     }
00287 
00288     /**
00289      * Sets a custom validator which is used supplementary to the base validation
00290      *
00291      * @param Tx_Extbase_Validation_Validator_ValidatorInterface $validator The actual validator object
00292      * @return Tx_Extbase_MVC_Controller_Argument Returns $this (used for fluent interface)
00293      * @api
00294      */
00295     public function setValidator(Tx_Extbase_Validation_Validator_ValidatorInterface $validator) {
00296         $this->validator = $validator;
00297         return $this;
00298     }
00299 
00300     /**
00301      * Create and set a validator chain
00302      *
00303      * @param array Object names of the validators
00304      * @return Tx_Extbase_MVC_Controller_Argument Returns $this (used for fluent interface)
00305      * @api
00306      */
00307     public function setNewValidatorConjunction(array $objectNames) {
00308         if ($this->validator === NULL) {
00309             $this->validator = $this->objectManager->create('Tx_Extbase_Validation_Validator_ConjunctionValidator');
00310         }
00311         foreach ($objectNames as $objectName) {
00312             if (!class_exists($objectName)) {
00313                 $objectName = 'Tx_Extbase_Validation_Validator_' . $objectName;
00314             }
00315             $this->validator->addValidator($this->objectManager->get($objectName));
00316         }
00317         return $this;
00318     }
00319 
00320     /**
00321      * Returns the set validator
00322      *
00323      * @return Tx_Extbase_Validation_Validator_ValidatorInterface The set validator, NULL if none was set
00324      * @api
00325      */
00326     public function getValidator() {
00327         return $this->validator;
00328     }
00329 
00330     /**
00331      * Get the origin of the argument value. This is only meaningful after argument mapping.
00332      *
00333      * @return integer one of the ORIGIN_* constants
00334      * @author Sebastian Kurfürst <sebastian@typo3.org>
00335      */
00336     public function getOrigin() {
00337         return $this->origin;
00338     }
00339 
00340     /**
00341      * Sets the value of this argument.
00342      *
00343      * @param mixed $value: The value of this argument
00344      * @return Tx_Extbase_MVC_Controller_Argument $this
00345      * @throws Tx_Extbase_MVC_Exception_InvalidArgumentValue if the argument is not a valid object of type $dataType
00346      */
00347     public function setValue($value) {
00348         $this->value = $this->transformValue($value);
00349 
00350         return $this;
00351     }
00352 
00353     /**
00354      * Checks if the value is a UUID or an array but should be an object, i.e.
00355      * the argument's data type class schema is set. If that is the case, this
00356      * method tries to look up the corresponding object instead.
00357      *
00358      * Additionally, it maps arrays to objects in case it is a normal object.
00359      *
00360      * @param mixed $value The value of an argument
00361      * @return mixed
00362      */
00363     protected function transformValue($value) {
00364         if ($value === NULL) {
00365             return NULL;
00366         }
00367         if (!class_exists($this->dataType)) {
00368             return $value;
00369         }
00370         $transformedValue = NULL;
00371         if ($this->dataTypeClassSchema !== NULL) {
00372             // The target object is an Entity or ValueObject.
00373             if (is_numeric($value)) {
00374                 $this->origin = self::ORIGIN_PERSISTENCE;
00375                 $transformedValue = $this->findObjectByUid($value);
00376             } elseif (is_array($value)) {
00377                 $this->origin = self::ORIGIN_PERSISTENCE_AND_MODIFIED;
00378                 $transformedValue = $this->propertyMapper->map(array_keys($value), $value, $this->dataType);
00379             }
00380         } else {
00381             if (!is_array($value)) {
00382                 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);
00383             }
00384             $this->origin = self::ORIGIN_NEWLY_CREATED;
00385             $transformedValue = $this->propertyMapper->map(array_keys($value), $value, $this->dataType);
00386         }
00387 
00388         if (!($transformedValue instanceof $this->dataType) && !($transformedValue === NULL && !$this->isRequired())) {
00389             throw new Tx_Extbase_MVC_Exception_InvalidArgumentValue('The value must be of type "' . $this->dataType . '", but was of type "' . (is_object($transformedValue) ? get_class($transformedValue) : gettype($transformedValue)) . '".', 1251730701);
00390         }
00391         return $transformedValue;
00392     }
00393 
00394     /**
00395      * Finds an object from the repository by searching for its technical UID.
00396      *
00397      * @param int $uid The object's uid
00398      * @return object Either the object matching the uid or, if none or more than one object was found, NULL
00399      */
00400     protected function findObjectByUid($uid) {
00401         $query = $this->queryFactory->create($this->dataType);
00402         $query->getQuerySettings()->setRespectSysLanguage(FALSE);
00403         $query->getQuerySettings()->setRespectStoragePage(FALSE);
00404         return $query->matching(
00405             $query->equals('uid', $uid))
00406             ->execute()
00407             ->getFirst();
00408     }
00409 
00410     /**
00411      * Returns the value of this argument
00412      *
00413      * @return object The value of this argument - if none was set, NULL is returned
00414      * @api
00415      */
00416     public function getValue() {
00417         if ($this->value === NULL) {
00418             return $this->defaultValue;
00419         } else {
00420             return $this->value;
00421         }
00422     }
00423 
00424     /**
00425      * Checks if this argument has a value set.
00426      *
00427      * @return boolean TRUE if a value was set, otherwise FALSE
00428      */
00429     public function isValue() {
00430         return $this->value !== NULL;
00431     }
00432 
00433     /**
00434      * Returns a string representation of this argument's value
00435      *
00436      * @return string
00437      * @api
00438      */
00439     public function __toString() {
00440         return (string)$this->value;
00441     }
00442 }
00443 ?>