/** * Copy a singe object based on field annotations about how to copy the object * * @param Tx_Extbase_DomainObject_DomainObjectInterface $object The object to be copied * @return Tx_Extbase_DomainObject_DomainObjectInterface $copy * @api */ public function copy($object) { $className = get_class($object); $this->recursionService->in(); $this->recursionService->check($className); $copy = $this->objectManager->get($className); $properties = $this->reflectionService->getClassPropertyNames($className); foreach ($properties as $propertyName) { $tags = $this->reflectionService->getPropertyTagsValues($className, $propertyName); $getter = 'get' . ucfirst($propertyName); $setter = 'set' . ucfirst($propertyName); $copyMethod = $tags['copy'][0]; $copiedValue = NULL; if ($copyMethod !== NULL && $copyMethod !== 'ignore') { $originalValue = $object->{$getter}(); if ($copyMethod == 'reference') { $copiedValue = $this->copyAsReference($originalValue); } elseif ($copyMethod == 'clone') { $copiedValue = $this->copyAsClone($originalValue); } if ($copiedValue != NULL) { $copy->{$setter}($copiedValue); } } } $this->recursionService->out(); return $copy; }
/** * Returns an array of property names and values by searching the $object * for annotations based on $annotation and $value. If $annotation is provided * but $value is not, All properties which simply have the annotation present. * Relational values which have the annotation are parsed through the same * function - sub-elements' properties are exported based on the same * annotation and value * * @param mixed $object The object or classname to read * @param string $annotation The annotation on which to base output * @param string|boolean $value The value to search for; multiple values may be used in the annotation; $value must be present among them. If TRUE, all properties which have the annotation are returned * @param boolean $addUid If TRUE, the UID of the DomainObject will be force-added to the output regardless of annotation * @return array * @api */ public function getValuesByAnnotation($object, $annotation = 'json', $value = TRUE, $addUid = TRUE) { if (is_array($object)) { $array = array(); foreach ($object as $k => $v) { $array[$k] = $this->getValuesByAnnotation($v, $annotation, $value, $addUid); } return $array; } if (is_object($object)) { $className = get_class($object); } else { $className = $object; $object = $this->objectManager->get($className); } $this->recursionService->in(); $this->recursionService->check($className); $properties = $this->reflectionService->getClassPropertyNames($className); $return = array(); if ($addUid === TRUE) { $return['uid'] = $object->getUid(); } foreach ($properties as $propertyName) { $getter = 'get' . ucfirst($propertyName); if (method_exists($object, $getter) === FALSE) { continue; } if ($this->hasAnnotation($className, $propertyName, $annotation, $value)) { $returnValue = $object->{$getter}(); if ($returnValue instanceof Tx_Extbase_Persistence_ObjectStorage) { $array = $returnValue->toArray(); foreach ($array as $k => $v) { $array[$k] = $this->getValuesByAnnotation($v, $annotation, $value, $addUid); } $returnValue = $array; } elseif ($returnValue instanceof Tx_Extbase_DomainObject_DomainObjectInterface) { $returnValue = $this->getValuesByAnnotation($returnValue, $annotation, $value, $addUid); } elseif ($returnValue instanceof DateTime) { $returnValue = $returnValue->format('r'); } $return[$propertyName] = $returnValue; } } $this->recursionService->out(); return $return; }
/** * Builds a base validator conjunction for the given data type. * * The base validation rules are those which were declared directly in a class (typically * a model) through some @validate annotations on properties. * * Additionally, if a custom validator was defined for the class in question, it will be added * to the end of the conjunction. A custom validator is found if it follows the naming convention * "Replace '\Model\' by '\Validator\' and append "Validator". * * Example: $dataType is F3\Foo\Domain\Model\Quux, then the Validator will be found if it has the * name F3\Foo\Domain\Validator\QuuxValidator * * @param string $dataType The data type to build the validation conjunction for. Needs to be the fully qualified object name. * @return Tx_Extbase_Validation_Validator_ConjunctionValidator The validator conjunction or NULL */ protected function buildBaseValidatorConjunction($dataType) { $validatorConjunction = $this->objectManager->get('Tx_Extbase_Validation_Validator_ConjunctionValidator'); // Model based validator if (strstr($dataType, '_') !== FALSE && class_exists($dataType)) { $validatorCount = 0; $objectValidator = $this->createValidator('GenericObject'); foreach ($this->reflectionService->getClassPropertyNames($dataType) as $classPropertyName) { $classPropertyTagsValues = $this->reflectionService->getPropertyTagsValues($dataType, $classPropertyName); if (!isset($classPropertyTagsValues['validate'])) { continue; } foreach ($classPropertyTagsValues['validate'] as $validateValue) { $parsedAnnotation = $this->parseValidatorAnnotation($validateValue); foreach ($parsedAnnotation['validators'] as $validatorConfiguration) { $newValidator = $this->createValidator($validatorConfiguration['validatorName'], $validatorConfiguration['validatorOptions']); if ($newValidator === NULL) { throw new Tx_Extbase_Validation_Exception_NoSuchValidator('Invalid validate annotation in ' . $dataType . '::' . $classPropertyName . ': Could not resolve class name for validator "' . $validatorConfiguration['validatorName'] . '".', 1241098027); } $objectValidator->addPropertyValidator($classPropertyName, $newValidator); $validatorCount++; } } } if ($validatorCount > 0) { $validatorConjunction->addValidator($objectValidator); } } // Custom validator for the class $possibleValidatorClassName = str_replace('_Model_', '_Validator_', $dataType) . 'Validator'; $customValidator = $this->createValidator($possibleValidatorClassName); if ($customValidator !== NULL) { $validatorConjunction->addValidator($customValidator); } return $validatorConjunction; }
/** * Does $propertyName on $instance contain a data type which supports deflation? * * @param object $instance Instance of an object, DomainObject included * @param string $propertyName String name of property on DomainObject instance which is up for assertion * @return boolean * @throws RuntimeException */ protected function assertSupportsDeflation($instance, $propertyName) { $className = get_class($instance); $gettableProperties = $this->reflectionService->getClassPropertyNames($className); if (FALSE === in_array($propertyName, $gettableProperties)) { return FALSE; } try { $value = Tx_Extbase_Reflection_ObjectAccess::getProperty($instance, $propertyName, TRUE); } catch (RuneimeException $error) { $getter = 'get' . ucfirst($propertyName); if (FALSE === method_exists($instance, $getter)) { return FALSE; } t3lib_div::sysLog('MarshallService encountered an error while attempting to retrieve the value of ' . $className . '::$' . $propertyName . ' - assuming safe deflation is possible', 'site', t3lib_div::SYSLOG_SEVERITY_NOTICE); return TRUE; } return FALSE === $value instanceof Closure; }