/** * @test */ public function overridingFromTypoScriptInFilesystemFollowingNodePathsWorks() { $typoScriptService = $this->objectManager->get('TYPO3\\TYPO3\\Domain\\Service\\TypoScriptService'); ObjectAccess::setProperty($typoScriptService, 'typoScriptsPathPattern', __DIR__ . '/Fixtures/ResourcesFixture/TypoScripts', TRUE); $objectTree = $typoScriptService->getMergedTypoScriptObjectTree($this->homeNode, $this->homeNode->getNode('about-us/history')); $this->assertEquals('Root', $objectTree['text1']['value']); $this->assertEquals('AboutUs', $objectTree['text2']['value']); $this->assertEquals('History', $objectTree['text3']['value']); $this->assertEquals('Additional', $objectTree['text4']['value']); }
public function setUp() { parent::setUp(); $nodeRepository = $this->objectManager->get('TYPO3\\TYPO3CR\\Domain\\Repository\\NodeRepository'); \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($nodeRepository, 'context', new \TYPO3\TYPO3\Domain\Service\ContentContext('live'), TRUE); $siteImportService = $this->objectManager->get('TYPO3\\TYPO3\\Domain\\Service\\SiteImportService'); $siteImportService->importSitesFromFile(__DIR__ . '/Fixtures/NodeStructure.xml'); $this->persistenceManager->persistAll(); $propertyMapper = $this->objectManager->get('TYPO3\\FLOW3\\Property\\PropertyMapper'); $this->node = $propertyMapper->convert('/sites/example/home', 'TYPO3\\TYPO3CR\\Domain\\Model\\Node'); $this->assertFalse($propertyMapper->getMessages()->hasErrors()); }
/** * Sets the given properties on the object. * * @param object $object The object to set properties on * @param string $identifier The identifier of the object * @param array $objectData * @return void * @throws \TYPO3\FLOW3\Persistence\Exception\UnknownObjectException */ public function thawProperties($object, $identifier, array $objectData) { $classSchema = $this->reflectionService->getClassSchema($objectData['classname']); foreach ($objectData['properties'] as $propertyName => $propertyData) { if (!$classSchema->hasProperty($propertyName)) { continue; } $propertyValue = NULL; if ($propertyData['value'] !== NULL) { switch ($propertyData['type']) { case 'integer': $propertyValue = (int) $propertyData['value']; break; case 'float': $propertyValue = (double) $propertyData['value']; break; case 'boolean': $propertyValue = (bool) $propertyData['value']; break; case 'string': $propertyValue = (string) $propertyData['value']; break; case 'array': $propertyValue = $this->mapArray($propertyData['value']); break; case 'Doctrine\\Common\\Collections\\Collection': case 'Doctrine\\Common\\Collections\\ArrayCollection': $propertyValue = new \Doctrine\Common\Collections\ArrayCollection($this->mapArray($propertyData['value'])); break; case 'SplObjectStorage': $propertyMetaData = $classSchema->getProperty($propertyName); $propertyValue = $this->mapSplObjectStorage($propertyData['value'], $propertyMetaData['lazy']); break; case 'DateTime': $propertyValue = $this->mapDateTime($propertyData['value']); break; default: if ($propertyData['value'] === FALSE) { throw new \TYPO3\FLOW3\Persistence\Exception\UnknownObjectException('An expected object was not found by the backend. It was expected for ' . $objectData['classname'] . '::' . $propertyName, 1289509867); } $propertyValue = $this->mapToObject($propertyData['value']); break; } } else { switch ($propertyData['type']) { case 'NULL': continue; break; case 'array': $propertyValue = $this->mapArray(NULL); break; case 'Doctrine\\Common\\Collections\\Collection': case 'Doctrine\\Common\\Collections\\ArrayCollection': $propertyValue = new \Doctrine\Common\Collections\ArrayCollection(); break; case 'SplObjectStorage': $propertyValue = $this->mapSplObjectStorage(NULL); break; } } \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($object, $propertyName, $propertyValue, TRUE); } if (isset($objectData['metadata'])) { $object->FLOW3_Persistence_Metadata = $objectData['metadata']; } \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($object, 'FLOW3_Persistence_Identifier', $identifier, TRUE); }
/** * @test */ public function setPropertyCanDirectlySetValuesInAnArrayObjectOrArray() { $arrayObject = new \ArrayObject(); $array = array(); \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($arrayObject, 'publicProperty', 4242); \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($array, 'key', 'value'); $this->assertEquals(4242, $arrayObject['publicProperty']); $this->assertEquals('value', $array['key']); }
/** * @test */ public function validatePasswordWillUseStrategyIdentifierFromHashedPassword() { $settings = array('security' => array('cryptography' => array('hashingStrategies' => array('TestStrategy' => 'TYPO3\\FLOW3\\Test\\TestStrategy')))); $this->hashService->injectSettings($settings); $mockStrategy = $this->getMock('TYPO3\\FLOW3\\Security\\Cryptography\\PasswordHashingStrategyInterface'); $mockObjectManager = $this->getMock('TYPO3\\FLOW3\\Object\\ObjectManagerInterface'); $mockObjectManager->expects($this->any())->method('get')->will($this->returnValue($mockStrategy)); \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($this->hashService, 'objectManager', $mockObjectManager, TRUE); $mockStrategy->expects($this->atLeastOnce())->method('validatePassword')->with('myTestPassword', '---hashed-password---')->will($this->returnValue(TRUE)); $result = $this->hashService->validatePassword('myTestPassword', 'TestStrategy=>---hashed-password---'); $this->assertEquals(TRUE, $result); }
/** * Convert an object from $source to an entity or a value object. * * @param mixed $source * @param string $targetType * @param array $convertedChildProperties * @param \TYPO3\FLOW3\Property\PropertyMappingConfigurationInterface $configuration * @return object the target type * @throws \TYPO3\FLOW3\Property\Exception\InvalidTargetException * @throws \InvalidArgumentException */ public function convertFrom($source, $targetType, array $convertedChildProperties = array(), \TYPO3\FLOW3\Property\PropertyMappingConfigurationInterface $configuration = NULL) { if (is_array($source)) { if ($this->reflectionService->isClassAnnotatedWith($targetType, 'TYPO3\\FLOW3\\Annotations\\ValueObject')) { // Unset identity for valueobject to use constructor mapping, since the identity is determined from // constructor arguments unset($source['__identity']); } $object = $this->handleArrayData($source, $targetType, $convertedChildProperties, $configuration); } elseif (is_string($source)) { if ($source === '') { return NULL; } $object = $this->fetchObjectFromPersistence($source, $targetType); } else { throw new \InvalidArgumentException('Only strings and arrays are accepted.', 1305630314); } foreach ($convertedChildProperties as $propertyName => $propertyValue) { $result = \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($object, $propertyName, $propertyValue); if ($result === FALSE) { throw new \TYPO3\FLOW3\Property\Exception\InvalidTargetException('Property "' . $propertyName . '" having a value of type "' . (is_object($propertyValue) ? get_class($propertyValue) : gettype($propertyValue)) . '" could not be set in target object of type "' . $targetType . '".', 1297935345); } } return $object; }
/** * @test */ public function collectionValidatorIsValidEarlyReturnsOnUnitializedDoctrinePersistenceCollections() { $entityManager = $this->getMock('Doctrine\\ORM\\EntityManager', array(), array(), '', FALSE); $collection = new \Doctrine\Common\Collections\ArrayCollection(array()); $persistentCollection = new \Doctrine\ORM\PersistentCollection($entityManager, '', $collection); \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($persistentCollection, 'initialized', FALSE, TRUE); $this->mockValidatorResolver->expects($this->never())->method('createValidator'); $this->validator->validate($persistentCollection); }
/** * After returning advice, generates the value hash for the object * * @param \TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint The current join point * @return void * @FLOW3\Before("classAnnotatedWith(TYPO3\FLOW3\Annotations\ValueObject) && method(.*->__construct())") */ public function generateValueHash(\TYPO3\FLOW3\Aop\JoinPointInterface $joinPoint) { $proxy = $joinPoint->getProxy(); $hashSource = get_class($proxy); if (property_exists($proxy, 'FLOW3_Persistence_Identifier')) { $hashSource .= \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($proxy, 'FLOW3_Persistence_Identifier', TRUE); } foreach ($joinPoint->getMethodArguments() as $argumentValue) { if (is_array($argumentValue)) { $hashSource .= $this->useIgBinary === TRUE ? igbinary_serialize($argumentValue) : serialize($argumentValue); } elseif (!is_object($argumentValue)) { $hashSource .= $argumentValue; } elseif (property_exists($argumentValue, 'FLOW3_Persistence_Identifier')) { $hashSource .= \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($argumentValue, 'FLOW3_Persistence_Identifier', TRUE); } elseif ($argumentValue instanceof \DateTime) { $hashSource .= $argumentValue->getTimestamp(); } } $proxy = $joinPoint->getProxy(); \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($proxy, 'FLOW3_Persistence_Identifier', sha1($hashSource), TRUE); }
/** * Converts the specified node path into a Node. * * The node path must be an absolute context node path and can be specified as a string or as an array item with the * key "__contextNodePath". The latter case is for updating existing nodes. * * This conversion method does not support / allow creation of new nodes because new nodes should be created through * the createNode() method of an existing reference node. * * Also note that the context's "current node" is not affected by this object converter, you will need to set it to * whatever node your "current" node is, if any. * * All elements in the source array which start with two underscores (like __contextNodePath) are specially treated * by this converter. * * All elements in the source array which start with a *single underscore (like _hidden) are *directly* set on the Node * object. * * All other elements, not being prefixed with underscore, are properties of the node. * * @param string|array $source Either a string or array containing the absolute context node path which identifies the node. For example "/sites/mysitecom/homepage/about@user-admin" * @param string $targetType not used * @param array $subProperties not used * @param \TYPO3\FLOW3\Property\PropertyMappingConfigurationInterface $configuration not used * @return mixed An object or \TYPO3\FLOW3\Error\Error if the input format is not supported or could not be converted for other reasons * @throws \Exception */ public function convertFrom($source, $targetType, array $subProperties = array(), \TYPO3\FLOW3\Property\PropertyMappingConfigurationInterface $configuration = NULL) { if (is_string($source)) { $source = array('__contextNodePath' => $source); } if (!is_array($source) || !isset($source['__contextNodePath'])) { return new Error('Could not convert ' . gettype($source) . ' to Node object, a valid absolute context node path as a string or array is expected.', 1302879936); } preg_match(NodeInterface::MATCH_PATTERN_CONTEXTPATH, $source['__contextNodePath'], $matches); if (!isset($matches['NodePath'])) { return new Error('Could not convert array to Node object because the node path was invalid.', 1285162903); } $nodePath = $matches['NodePath']; if ($this->nodeRepository->getContext() === NULL) { $workspaceName = isset($matches['WorkspaceName']) ? $matches['WorkspaceName'] : 'live'; $contentContext = new ContentContext($workspaceName); $this->nodeRepository->setContext($contentContext); } else { $contentContext = $this->nodeRepository->getContext(); $workspaceName = $contentContext->getWorkspace()->getName(); } if ($workspaceName !== 'live') { $contentContext->setInvisibleContentShown(TRUE); if ($configuration->getConfigurationValue('TYPO3\\TYPO3\\Routing\\NodeObjectConverter', self::REMOVED_CONTENT_SHOWN) === TRUE) { $contentContext->setRemovedContentShown(TRUE); } } $workspace = $contentContext->getWorkspace(FALSE); if (!$workspace) { return new Error(sprintf('Could not convert %s to Node object because the workspace "%s" as specified in the context node path does not exist.', $source['__contextNodePath'], $workspaceName), 1285162905); } $currentAccessModeFromContext = $contentContext->isInaccessibleContentShown(); $contentContext->setInaccessibleContentShown(TRUE); $node = $contentContext->getNode($nodePath); $contentContext->setInaccessibleContentShown($currentAccessModeFromContext); if (!$node) { return new Error(sprintf('Could not convert array to Node object because the node "%s" does not exist.', $nodePath), 1285162908); } $contentTypeProperties = $node->getContentType()->getProperties(); foreach ($source as $nodePropertyKey => $nodePropertyValue) { if (substr($nodePropertyKey, 0, 2) === '__') { continue; } if ($nodePropertyKey[0] === '_') { $propertyName = substr($nodePropertyKey, 1); // TODO: Hack: we need to create DateTime objects for some properties of Node if (($propertyName === 'hiddenBeforeDateTime' || $propertyName === 'hiddenAfterDateTime') && is_string($nodePropertyValue)) { if ($nodePropertyValue !== '') { $nodePropertyValue = \DateTime::createFromFormat('!Y-m-d', $nodePropertyValue); } else { $nodePropertyValue = NULL; } } \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($node, $propertyName, $nodePropertyValue); } else { if (!isset($contentTypeProperties[$nodePropertyKey])) { throw new \Exception('TODO: content type XY does not have a property YY according to the schema'); } if (isset($contentTypeProperties[$nodePropertyKey]['type'])) { $targetType = $contentTypeProperties[$nodePropertyKey]['type']; if ($this->objectManager->isRegistered($targetType)) { $nodePropertyValue = $this->propertyMapper->convert(json_decode($nodePropertyValue, TRUE), $targetType); } } $node->setProperty($nodePropertyKey, $nodePropertyValue); } } return $node; }
/** * Convert an object from $source to an object. * * @param mixed $source * @param string $targetType * @param array $convertedChildProperties * @param \TYPO3\FLOW3\Property\PropertyMappingConfigurationInterface $configuration * @return object the target type * @throws \TYPO3\FLOW3\Property\Exception\InvalidTargetException * @throws \TYPO3\FLOW3\Property\Exception\InvalidDataTypeException * @throws \TYPO3\FLOW3\Property\Exception\InvalidPropertyMappingConfigurationException */ public function convertFrom($source, $targetType, array $convertedChildProperties = array(), \TYPO3\FLOW3\Property\PropertyMappingConfigurationInterface $configuration = NULL) { $effectiveTargetType = $targetType; if (isset($source['__type'])) { if ($configuration->getConfigurationValue('TYPO3\\FLOW3\\Property\\TypeConverter\\ObjectConverter', self::CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED) !== TRUE) { throw new \TYPO3\FLOW3\Property\Exception\InvalidPropertyMappingConfigurationException('Override of target type not allowed. To enable this, you need to set the PropertyMappingConfiguration Value "CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED" to TRUE.', 1317051258); } $effectiveTargetType = $source['__type']; } $object = $this->buildObject($convertedChildProperties, $effectiveTargetType); if ($effectiveTargetType !== $targetType && !$object instanceof $targetType) { throw new \TYPO3\FLOW3\Property\Exception\InvalidDataTypeException('The given type "' . $source['__type'] . '" is not a subtype of "' . $targetType . '"', 1317051266); } foreach ($convertedChildProperties as $propertyName => $propertyValue) { $result = \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($object, $propertyName, $propertyValue); if ($result === FALSE) { throw new \TYPO3\FLOW3\Property\Exception\InvalidTargetException('Property "' . $propertyName . '" having a value of type "' . (is_object($propertyValue) ? get_class($propertyValue) : gettype($propertyValue)) . '" could not be set in target object of type "' . $targetType . '".', 1304538165); } } return $object; }
/** * An onFlush event listener used to validate entities upon persistence. * * @param \Doctrine\ORM\Event\OnFlushEventArgs $eventArgs * @return void */ public function onFlush(\Doctrine\ORM\Event\OnFlushEventArgs $eventArgs) { $unitOfWork = $this->entityManager->getUnitOfWork(); $entityInsertions = $unitOfWork->getScheduledEntityInsertions(); $validatedInstancesContainer = new \SplObjectStorage(); $knownValueObjects = array(); foreach ($entityInsertions as $entity) { if ($this->reflectionService->getClassSchema($entity)->getModelType() === \TYPO3\FLOW3\Reflection\ClassSchema::MODELTYPE_VALUEOBJECT) { $identifier = $this->getIdentifierByObject($entity); $className = $this->reflectionService->getClassNameByObject($entity); if (isset($knownValueObjects[$className][$identifier]) || $unitOfWork->getEntityPersister($className)->exists($entity)) { unset($entityInsertions[spl_object_hash($entity)]); continue; } $knownValueObjects[$className][$identifier] = TRUE; } $this->validateObject($entity, $validatedInstancesContainer); } \TYPO3\FLOW3\Reflection\ObjectAccess::setProperty($unitOfWork, 'entityInsertions', $entityInsertions, TRUE); foreach ($unitOfWork->getScheduledEntityUpdates() as $entity) { $this->validateObject($entity, $validatedInstancesContainer); } }