示例#1
0
 /**
  * Builds a data map by adding column maps for all the configured columns in the $TCA.
  * It also resolves the type of values the column is holding and the typo of relation the column
  * represents.
  *
  * @param string $className The class name you want to fetch the Data Map for
  * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidClassException
  * @return \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap The data map
  */
 protected function buildDataMapInternal($className)
 {
     if (!class_exists($className)) {
         throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidClassException('Could not find class definition for name "' . $className . '". This could be caused by a mis-spelling of the class name in the class definition.', 1476045117);
     }
     $recordType = null;
     $subclasses = [];
     $tableName = $this->resolveTableName($className);
     $columnMapping = [];
     $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
     $classSettings = $frameworkConfiguration['persistence']['classes'][$className];
     if ($classSettings !== null) {
         if (isset($classSettings['subclasses']) && is_array($classSettings['subclasses'])) {
             $subclasses = $this->resolveSubclassesRecursive($frameworkConfiguration['persistence']['classes'], $classSettings['subclasses']);
         }
         if (isset($classSettings['mapping']['recordType']) && $classSettings['mapping']['recordType'] !== '') {
             $recordType = $classSettings['mapping']['recordType'];
         }
         if (isset($classSettings['mapping']['tableName']) && $classSettings['mapping']['tableName'] !== '') {
             $tableName = $classSettings['mapping']['tableName'];
         }
         $classHierarchy = array_merge([$className], class_parents($className));
         foreach ($classHierarchy as $currentClassName) {
             if (in_array($currentClassName, [\TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class, \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject::class])) {
                 break;
             }
             $currentClassSettings = $frameworkConfiguration['persistence']['classes'][$currentClassName];
             if ($currentClassSettings !== null) {
                 if (isset($currentClassSettings['mapping']['columns']) && is_array($currentClassSettings['mapping']['columns'])) {
                     \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($columnMapping, $currentClassSettings['mapping']['columns'], true, false);
                 }
             }
         }
     }
     /** @var $dataMap \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap */
     $dataMap = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap::class, $className, $tableName, $recordType, $subclasses);
     $dataMap = $this->addMetaDataColumnNames($dataMap, $tableName);
     // $classPropertyNames = $this->reflectionService->getClassPropertyNames($className);
     $tcaColumnsDefinition = $this->getColumnsDefinition($tableName);
     \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($tcaColumnsDefinition, $columnMapping);
     // @todo Is this is too powerful?
     foreach ($tcaColumnsDefinition as $columnName => $columnDefinition) {
         if (isset($columnDefinition['mapOnProperty'])) {
             $propertyName = $columnDefinition['mapOnProperty'];
         } else {
             $propertyName = \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToLowerCamelCase($columnName);
         }
         // if (in_array($propertyName, $classPropertyNames)) {
         // @todo Enable check for property existence
         $columnMap = $this->createColumnMap($columnName, $propertyName);
         $propertyMetaData = $this->reflectionService->getClassSchema($className)->getProperty($propertyName);
         $columnMap = $this->setType($columnMap, $columnDefinition['config']);
         $columnMap = $this->setRelations($columnMap, $columnDefinition['config'], $propertyMetaData);
         $columnMap = $this->setFieldEvaluations($columnMap, $columnDefinition['config']);
         $dataMap->addColumnMap($columnMap);
     }
     return $dataMap;
 }
示例#2
0
 /**
  * Returns the type of a child object.
  *
  * @param string $parentClassName The class name of the object this proxy is part of
  * @param string $propertyName The name of the proxied property in it's parent
  * @throws UnexpectedTypeException
  * @return string The class name of the child object
  */
 public function getType($parentClassName, $propertyName)
 {
     $propertyMetaData = $this->reflectionService->getClassSchema($parentClassName)->getProperty($propertyName);
     if (!empty($propertyMetaData['elementType'])) {
         $type = $propertyMetaData['elementType'];
     } elseif (!empty($propertyMetaData['type'])) {
         $type = $propertyMetaData['type'];
     } else {
         throw new UnexpectedTypeException('Could not determine the child object type.', 1251315967);
     }
     return $type;
 }
示例#3
0
 /**
  * Remove related objects
  *
  * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object The object to scanned for related objects
  * @return void
  */
 protected function removeRelatedObjects(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object)
 {
     $className = get_class($object);
     $dataMap = $this->dataMapper->getDataMap($className);
     $classSchema = $this->reflectionService->getClassSchema($className);
     $properties = $object->_getProperties();
     foreach ($properties as $propertyName => $propertyValue) {
         $columnMap = $dataMap->getColumnMap($propertyName);
         $propertyMetaData = $classSchema->getProperty($propertyName);
         if ($propertyMetaData['cascade'] === 'remove') {
             if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) {
                 foreach ($propertyValue as $containedObject) {
                     $this->removeEntity($containedObject);
                 }
             } elseif ($propertyValue instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) {
                 $this->removeEntity($propertyValue);
             }
         }
     }
 }
示例#4
0
 /**
  * Loads the model with the given identifier
  *
  * @param mixed		$identifier The identifier
  * @param string	$path		The path
  * @return mixed|null|object
  */
 protected function getModelWithIdentityForPath($identifier, $path)
 {
     $repository = $this->getRepositoryForPath($path);
     // Tries to fetch the object by UID
     $object = $repository->findByUid($identifier);
     if ($object) {
         return $object;
     }
     // Fetch the first identity property and search the repository for it
     $type = NULL;
     $property = NULL;
     try {
         $classSchema = $this->reflectionService->getClassSchema($this->getModelClassForPath($path));
         $identityProperties = $classSchema->getIdentityProperties();
         $type = reset($identityProperties);
         $property = key($identityProperties);
     } catch (\Exception $exception) {
     }
     switch ($type) {
         case 'string':
             $typeMatching = is_string($identifier);
             break;
         case 'boolean':
             $typeMatching = is_bool($identifier);
             break;
         case 'integer':
             $typeMatching = is_int($identifier);
             break;
         case 'float':
             $typeMatching = is_float($identifier);
             break;
         case 'array':
         default:
             $typeMatching = FALSE;
     }
     if ($typeMatching) {
         $findMethod = 'findOneBy' . ucfirst($property);
         return call_user_func(array($repository, $findMethod), $identifier);
     }
     return NULL;
 }
示例#5
0
 /**
  * Sets the data type of this argument's value
  *
  * @param string $dataType The data type. Can be either a built-in type such as "Text" or "Integer" or a fully qualified object name
  * @return \TYPO3\CMS\Extbase\Mvc\Controller\Argument $this
  * @api
  */
 public function setDataType($dataType)
 {
     $this->dataType = $dataType;
     $this->dataTypeClassSchema = $this->reflectionService->getClassSchema($dataType);
     return $this;
 }
示例#6
0
 /**
  * Maps the given properties to the target object WITHOUT VALIDATING THE RESULT.
  * If the properties could be set, this method returns TRUE, otherwise FALSE.
  * Returning TRUE does not mean that the target object is valid and secure!
  *
  * Only use this method if you're sure that you don't need validation!
  *
  * @param array $propertyNames Names of the properties to map.
  * @param mixed $source Source containing the properties to map to the target object. Must either be an array, ArrayObject or any other object.
  * @param object|array|string $target The target object
  * @param array $optionalPropertyNames Names of optional properties. If a property is specified here and it doesn't exist in the source, no error is issued.
  * @throws Exception\InvalidSourceException
  * @throws Exception\InvalidTargetException
  * @return boolean TRUE if the properties could be mapped, otherwise FALSE, or the object in case it could be resolved
  * @see mapAndValidate()
  * @api
  */
 public function map(array $propertyNames, $source, $target, $optionalPropertyNames = array())
 {
     if (!is_object($source) && !is_array($source)) {
         throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidSourceException('The source object must be a valid object or array, ' . gettype($target) . ' given.', 1187807099);
     }
     if (is_string($target) && strpbrk($target, '_\\') !== FALSE) {
         return $this->transformToObject($source, $target, '--none--');
     }
     if (!is_object($target) && !is_array($target)) {
         throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException('The target object must be a valid object or array, ' . gettype($target) . ' given.', 1187807100);
     }
     $this->mappingResults = new \TYPO3\CMS\Extbase\Property\MappingResults();
     if (is_object($target)) {
         $targetClassSchema = $this->reflectionService->getClassSchema(get_class($target));
     } else {
         $targetClassSchema = NULL;
     }
     foreach ($propertyNames as $propertyName) {
         $propertyValue = NULL;
         if (is_array($source) || $source instanceof \ArrayAccess) {
             if (isset($source[$propertyName])) {
                 $propertyValue = $source[$propertyName];
             }
         } else {
             $propertyValue = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($source, $propertyName);
         }
         if ($propertyValue === NULL && !in_array($propertyName, $optionalPropertyNames)) {
             $this->mappingResults->addError(new \TYPO3\CMS\Extbase\Error\Error("Required property '{$propertyName}' does not exist.", 1236785359), $propertyName);
         } else {
             if ($targetClassSchema !== NULL && $targetClassSchema->hasProperty($propertyName)) {
                 $propertyMetaData = $targetClassSchema->getProperty($propertyName);
                 if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE) && (strpbrk($propertyMetaData['elementType'], '_\\') !== FALSE || $propertyValue === '')) {
                     $objects = array();
                     if (is_array($propertyValue)) {
                         foreach ($propertyValue as $value) {
                             $transformedObject = $this->transformToObject($value, $propertyMetaData['elementType'], $propertyName);
                             if ($transformedObject !== NULL) {
                                 $objects[] = $transformedObject;
                             }
                         }
                     }
                     // make sure we hand out what is expected
                     if ($propertyMetaData['type'] === 'ArrayObject') {
                         $propertyValue = new \ArrayObject($objects);
                     } elseif (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
                         $propertyValue = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
                         foreach ($objects as $object) {
                             $propertyValue->attach($object);
                         }
                     } else {
                         $propertyValue = $objects;
                     }
                 } elseif ($propertyMetaData['type'] === 'DateTime' || strpbrk($propertyMetaData['type'], '_\\') !== FALSE) {
                     $propertyValue = $this->transformToObject($propertyValue, $propertyMetaData['type'], $propertyName);
                     if ($propertyValue === NULL) {
                         continue;
                     }
                 }
             } elseif ($targetClassSchema !== NULL && is_subclass_of($target, 'TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity') && is_subclass_of($target, 'TYPO3\\CMS\\Extbase\\DomainObject\\AbstractValueObject')) {
                 $this->mappingResults->addError(new \TYPO3\CMS\Extbase\Error\Error("Property '{$propertyName}' does not exist in target class schema.", 1251813614), $propertyName);
             }
             if (is_array($target)) {
                 $target[$propertyName] = $propertyValue;
             } elseif (\TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($target, $propertyName, $propertyValue) === FALSE) {
                 $this->mappingResults->addError(new \TYPO3\CMS\Extbase\Error\Error("Property '{$propertyName}' could not be set.", 1236783102), $propertyName);
             }
         }
     }
     return !$this->mappingResults->hasErrors();
 }