It is used most prominently to map incoming HTTP arguments to objects.
Beispiel #1
0
 /**
  * Returns a previously uploaded image.
  * If errors occurred during property mapping for this property, NULL is returned
  *
  * @return Image
  */
 protected function getUploadedImage()
 {
     if ($this->getMappingResultsForProperty()->hasErrors()) {
         return null;
     }
     $image = $this->getValue(false);
     if ($image instanceof Image) {
         return $image;
     }
     return $this->propertyMapper->convert($image, Image::class);
 }
 /**
  * Returns a previously uploaded resource.
  * If errors occurred during property mapping for this property, NULL is returned
  *
  * @return PersistentResource
  */
 protected function getUploadedResource()
 {
     if ($this->getMappingResultsForProperty()->hasErrors()) {
         return null;
     }
     $resourceObject = $this->getValue(false);
     if ($resourceObject instanceof PersistentResource) {
         return $resourceObject;
     }
     return $this->propertyMapper->convert($resourceObject, PersistentResource::class);
 }
 /**
  * Actually convert from $source to $targetType, taking into account the fully
  * built $convertedChildProperties and $configuration.
  *
  * The return value can be one of three types:
  * - an arbitrary object, or a simple type (which has been created while mapping).
  *   This is the normal case.
  * - NULL, indicating that this object should *not* be mapped (i.e. a "File Upload" Converter could return NULL if no file has been uploaded, and a silent failure should occur.
  * - An instance of Error -- This will be a user-visible error message later on.
  * Furthermore, it should throw an Exception if an unexpected failure (like a security error) occurred or a configuration issue happened.
  *
  * @param mixed $source
  * @param string $targetType
  * @param array $convertedChildProperties
  * @param PropertyMappingConfigurationInterface $configuration
  * @return mixed|Error the target type, or an error object if a user-error occurred
  * @throws TypeConverterException thrown in case a developer error occurred
  * @api
  */
 public function convertFrom($source, $targetType, array $convertedChildProperties = [], PropertyMappingConfigurationInterface $configuration = null)
 {
     $result = [];
     $convertElements = $configuration->getConfigurationValue(ArrayTypeConverter::class, self::CONFIGURATION_CONVERT_ELEMENTS);
     foreach ($source as $element) {
         if ($convertElements === true) {
             $element = $this->propertyMapper->convert($element, 'array', $configuration);
         }
         $result[] = $element;
     }
     return $result;
 }
 /**
  * @test
  * @expectedException \Neos\Flow\Property\Exception
  */
 public function entityWithImmutablePropertyCanNotBeUpdatedWhenImmutablePropertyChanged()
 {
     $result = $this->propertyMapper->convert($this->sourceProperties, Fixtures\TestEntityWithImmutableProperty::class);
     $identifier = $this->persistenceManager->getIdentifierByObject($result);
     $this->persistenceManager->add($result);
     $this->persistenceManager->persistAll();
     $this->persistenceManager->clearState();
     $update = ['__identity' => $identifier, 'age' => '25', 'name' => 'Christian D'];
     $result = $this->propertyMapper->convert($update, Fixtures\TestEntityWithImmutableProperty::class);
     $this->assertInstanceOf(Fixtures\TestEntityWithImmutableProperty::class, $result);
     $this->assertEquals('Christian M', $result->getName());
 }
 /**
  * Lists all currently active and registered type converters
  *
  * All active converters are listed with ordered by priority and grouped by
  * source type first and target type second.
  *
  * @return void
  */
 public function listCommand()
 {
     foreach ($this->propertyMapper->getTypeConverters() as $sourceType => $targetTypePriorityAndInstance) {
         $this->outputLine();
         $this->outputLine('<b>Source type "%s":</b>', [$sourceType]);
         foreach ($targetTypePriorityAndInstance as $targetType => $priorityAndInstance) {
             $this->outputFormatted('<b>Target type "%s":</b>', [$targetType], 4);
             krsort($priorityAndInstance);
             foreach ($priorityAndInstance as $priority => $instance) {
                 $this->outputFormatted('%3s: %s', [$priority, get_class($instance)], 8);
             }
             $this->outputLine();
         }
         $this->outputLine();
     }
 }
 /**
  * Converts and adds ImageAdjustments to the ImageVariant
  *
  * @param ImageInterface $asset
  * @param mixed $source
  * @param array $convertedChildProperties
  * @param PropertyMappingConfigurationInterface $configuration
  * @return ImageInterface|NULL
  */
 protected function applyTypeSpecificHandling($asset, $source, array $convertedChildProperties, PropertyMappingConfigurationInterface $configuration)
 {
     if ($asset instanceof ImageVariant) {
         $adjustments = [];
         if (isset($source['adjustments'])) {
             foreach ($source['adjustments'] as $adjustmentType => $adjustmentOptions) {
                 if (isset($adjustmentOptions['__type'])) {
                     $adjustmentType = $adjustmentOptions['__type'];
                     unset($adjustmentOptions['__type']);
                 }
                 $identity = null;
                 if (isset($adjustmentOptions['__identity'])) {
                     $identity = $adjustmentOptions['__identity'];
                     unset($adjustmentOptions['__identity']);
                 }
                 $adjustment = $this->propertyMapper->convert($adjustmentOptions, $adjustmentType, $configuration);
                 if ($identity !== null) {
                     ObjectAccess::setProperty($adjustment, 'persistence_object_identifier', $identity, true);
                 }
                 $adjustments[] = $adjustment;
             }
         } elseif (isset($source['processingInstructions'])) {
             $adjustments = $this->processingInstructionsConverter->convertFrom($source['processingInstructions'], 'array');
         }
         if (count($adjustments) > 0) {
             $asset->addAdjustments($adjustments);
         }
     }
     return $asset;
 }
Beispiel #7
0
 /**
  * @return \DateTime
  */
 protected function getSelectedDate()
 {
     $date = $this->getValue();
     if ($date instanceof \DateTime) {
         return $date;
     }
     if ($date !== null) {
         $date = $this->propertyMapper->convert($date, 'DateTime');
         if (!$date instanceof \DateTime) {
             return null;
         }
         return $date;
     }
     if ($this->hasArgument('initialDate')) {
         return new \DateTime($this->arguments['initialDate']);
     }
 }
Beispiel #8
0
 /**
  * @test
  */
 public function getTargetPropertyNameShouldReturnTheUnmodifiedPropertyNameWithoutConfiguration()
 {
     $defaultConfiguration = $this->propertyMapper->buildPropertyMappingConfiguration();
     $this->assertTrue($defaultConfiguration->getConfigurationValue(\Neos\Flow\Property\TypeConverter\PersistentObjectConverter::class, \Neos\Flow\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED));
     $this->assertTrue($defaultConfiguration->getConfigurationValue(\Neos\Flow\Property\TypeConverter\PersistentObjectConverter::class, \Neos\Flow\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED));
     $this->assertNull($defaultConfiguration->getConfigurationFor('foo')->getConfigurationValue(\Neos\Flow\Property\TypeConverter\PersistentObjectConverter::class, \Neos\Flow\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED));
     $this->assertNull($defaultConfiguration->getConfigurationFor('foo')->getConfigurationValue(\Neos\Flow\Property\TypeConverter\PersistentObjectConverter::class, \Neos\Flow\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED));
 }
 /**
  * @test
  */
 public function handleMergesInternalArgumentsWithRoutingMatchResults()
 {
     $this->mockHttpRequest->expects($this->any())->method('getArguments')->will($this->returnValue(['__internalArgument1' => 'request', '__internalArgument2' => 'request', '__internalArgument3' => 'request']));
     $this->mockHttpRequest->expects(self::any())->method('getContent')->willReturn('requestBody');
     $this->mockPropertyMapper->expects($this->any())->method('convert')->will($this->returnValue(['__internalArgument2' => 'requestBody', '__internalArgument3' => 'requestBody']));
     $this->mockComponentContext->expects($this->atLeastOnce())->method('getParameter')->with(RoutingComponent::class, 'matchResults')->will($this->returnValue(['__internalArgument3' => 'routing']));
     $this->mockActionRequest->expects($this->once())->method('setArguments')->with(['__internalArgument1' => 'request', '__internalArgument2' => 'requestBody', '__internalArgument3' => 'routing']);
     $this->dispatchComponent->handle($this->mockComponentContext);
 }
Beispiel #10
0
 /**
  * @test
  */
 public function processConvertsValueIfDataTypeIsSpecified()
 {
     $this->processingRule->setDataType('SomeDataType');
     $mockPropertyMappingConfiguration = $this->getMockBuilder(\Neos\Flow\Property\PropertyMappingConfiguration::class)->getMock();
     $this->processingRule->_set('propertyMappingConfiguration', $mockPropertyMappingConfiguration);
     $this->mockPropertyMapper->expects($this->once())->method('convert')->with('Some Value', 'SomeDataType', $mockPropertyMappingConfiguration)->will($this->returnValue('Converted Value'));
     $this->mockPropertyMapper->expects($this->any())->method('getMessages')->will($this->returnValue(new \Neos\Error\Messages\Result()));
     $this->assertEquals('Converted Value', $this->processingRule->process('Some Value'));
 }
 /**
  * @param array $contextArray
  * @return array
  */
 public function unserializeContext(array $contextArray)
 {
     $unserializedContext = [];
     foreach ($contextArray as $variableName => $typeAndValue) {
         $value = $this->propertyMapper->convert($typeAndValue['value'], $typeAndValue['type']);
         $unserializedContext[$variableName] = $value;
     }
     return $unserializedContext;
 }
 /**
  * Generates an array of strings from the given array of context variables
  *
  * @param array $contextVariables
  * @return array
  * @throws \InvalidArgumentException
  */
 protected function serializeContext(array $contextVariables)
 {
     $serializedContextArray = [];
     foreach ($contextVariables as $variableName => $contextValue) {
         // TODO This relies on a converter being available from the context value type to string
         if ($contextValue !== null) {
             $serializedContextArray[$variableName]['type'] = $this->getTypeForContextValue($contextValue);
             $serializedContextArray[$variableName]['value'] = $this->propertyMapper->convert($contextValue, 'string');
         }
     }
     return $serializedContextArray;
 }
Beispiel #13
0
 /**
  * @param mixed $value
  * @return mixed
  */
 public function process($value)
 {
     if ($this->dataType !== null) {
         $value = $this->propertyMapper->convert($value, $this->dataType, $this->propertyMappingConfiguration);
         $messages = $this->propertyMapper->getMessages();
     } else {
         $messages = new \Neos\Error\Messages\Result();
     }
     $validationResult = $this->validator->validate($value);
     $messages->merge($validationResult);
     $this->processingMessages->merge($messages);
     return $value;
 }
 /**
  * Parses the request body according to the media type.
  *
  * @param HttpRequest $httpRequest
  * @return array
  */
 protected function parseRequestBody(HttpRequest $httpRequest)
 {
     $requestBody = $httpRequest->getContent();
     if ($requestBody === null || $requestBody === '') {
         return [];
     }
     $mediaTypeConverter = $this->objectManager->get(MediaTypeConverterInterface::class);
     $propertyMappingConfiguration = new PropertyMappingConfiguration();
     $propertyMappingConfiguration->setTypeConverter($mediaTypeConverter);
     $propertyMappingConfiguration->setTypeConverterOption(MediaTypeConverterInterface::class, MediaTypeConverterInterface::CONFIGURATION_MEDIA_TYPE, $httpRequest->getHeader('Content-Type'));
     $arguments = $this->propertyMapper->convert($requestBody, 'array', $propertyMappingConfiguration);
     return $arguments;
 }
 /**
  * Calls a behat step method
  *
  * @Flow\Internal
  * @param string $testHelperObjectName
  * @param string $methodName
  * @param boolean $withoutSecurityChecks
  */
 public function callBehatStepCommand($testHelperObjectName, $methodName, $withoutSecurityChecks = false)
 {
     $testHelper = $this->objectManager->get($testHelperObjectName);
     $rawMethodArguments = $this->request->getExceedingArguments();
     $mappedArguments = [];
     for ($i = 0; $i < count($rawMethodArguments); $i += 2) {
         $mappedArguments[] = $this->propertyMapper->convert($rawMethodArguments[$i + 1], $rawMethodArguments[$i]);
     }
     $result = null;
     try {
         if ($withoutSecurityChecks === true) {
             $this->securityContext->withoutAuthorizationChecks(function () use($testHelper, $methodName, $mappedArguments, &$result) {
                 $result = call_user_func_array([$testHelper, $methodName], $mappedArguments);
             });
         } else {
             $result = call_user_func_array([$testHelper, $methodName], $mappedArguments);
         }
     } catch (\Exception $exception) {
         $this->outputLine('EXCEPTION: %s %d %s in %s:%s %s', [get_class($exception), $exception->getCode(), $exception->getMessage(), $exception->getFile(), $exception->getLine(), $exception->getTraceAsString()]);
         return;
     }
     $this->output('SUCCESS: %s', [$result]);
 }
 /**
  * @test
  */
 public function convertFromUsesPropertyMapperToConvertNodePropertyOfArrayType()
 {
     $contextPath = '/foo/bar@user-demo';
     $nodePath = '/foo/bar';
     $nodeTypeProperties = array('assets' => array('type' => 'array<Neos\\Media\\Domain\\Model\\Asset>'));
     $decodedPropertyValue = array('8aaf4dd2-bd85-11e3-ae3d-14109fd7a2dd', '8febe94a-bd85-11e3-8401-14109fd7a2dd');
     $source = array('__contextNodePath' => $contextPath, 'assets' => json_encode($decodedPropertyValue));
     $convertedPropertyValue = array(new \stdClass(), new \stdClass());
     $mockNode = $this->setUpNodeWithNodeType($nodePath, $nodeTypeProperties);
     $this->mockObjectManager->expects($this->any())->method('isRegistered')->with(Asset::class)->will($this->returnValue(true));
     $this->mockPropertyMapper->expects($this->once())->method('convert')->with($decodedPropertyValue, $nodeTypeProperties['assets']['type'])->will($this->returnValue($convertedPropertyValue));
     $mockNode->expects($this->once())->method('setProperty')->with('assets', $convertedPropertyValue);
     $this->nodeConverter->convertFrom($source, null, array(), $this->mockConverterConfiguration);
 }
 /**
  *
  * @param string $workspaceName
  * @return NodeInterface
  */
 protected function getLastVisitedNode($workspaceName)
 {
     if (!$this->session->isStarted() || !$this->session->hasKey('lastVisitedNode')) {
         return null;
     }
     try {
         $lastVisitedNode = $this->propertyMapper->convert($this->session->getData('lastVisitedNode'), NodeInterface::class);
         $q = new FlowQuery([$lastVisitedNode]);
         $lastVisitedNodeUserWorkspace = $q->context(['workspaceName' => $workspaceName])->get(0);
         return $lastVisitedNodeUserWorkspace;
     } catch (\Exception $exception) {
         return null;
     }
 }
Beispiel #18
0
 /**
  * Checks if the optionally given node context path, affected node context path and typoscript path are set
  * and overrides the rendering to use those. Will also add a "X-Neos-AffectedNodePath" header in case the
  * actually affected node is different from the one routing resolved.
  * This is used in out of band rendering for the backend.
  *
  * @return void
  * @throws NodeNotFoundException
  */
 protected function overrideViewVariablesFromInternalArguments()
 {
     if (($nodeContextPath = $this->request->getInternalArgument('__nodeContextPath')) !== null) {
         $node = $this->propertyMapper->convert($nodeContextPath, NodeInterface::class);
         if (!$node instanceof NodeInterface) {
             throw new NodeNotFoundException(sprintf('The node with context path "%s" could not be resolved', $nodeContextPath), 1437051934);
         }
         $this->view->assign('value', $node);
     }
     if (($affectedNodeContextPath = $this->request->getInternalArgument('__affectedNodeContextPath')) !== null) {
         $this->response->setHeader('X-Neos-AffectedNodePath', $affectedNodeContextPath);
     }
     if (($typoScriptPath = $this->request->getInternalArgument('__typoScriptPath')) !== null) {
         $this->view->setTypoScriptPath($typoScriptPath);
     }
 }
 /**
  * Sets the value of this argument.
  *
  * @param mixed $rawValue The value of this argument
  * @return Argument $this
  */
 public function setValue($rawValue)
 {
     if ($rawValue === null) {
         $this->value = null;
         return $this;
     }
     if (is_object($rawValue) && $rawValue instanceof $this->dataType) {
         $this->value = $rawValue;
         return $this;
     }
     $this->value = $this->propertyMapper->convert($rawValue, $this->dataType, $this->getPropertyMappingConfiguration());
     $this->validationResults = $this->propertyMapper->getMessages();
     if ($this->validator !== null) {
         $validationMessages = $this->validator->validate($this->value);
         $this->validationResults->merge($validationMessages);
     }
     return $this;
 }
 /**
  * Returns a previously uploaded resource, or the resource specified via "value" argument if no resource has been uploaded before
  * If errors occurred during property mapping for this property, NULL is returned
  *
  * @return PersistentResource or NULL if no resource was uploaded and the "value" argument is not set
  */
 protected function getUploadedResource()
 {
     $resource = null;
     if ($this->hasMappingErrorOccurred()) {
         $resource = $this->getLastSubmittedFormData();
     } elseif ($this->hasArgument('value')) {
         $resource = $this->arguments['value'];
     } elseif ($this->isObjectAccessorMode()) {
         $resource = $this->getPropertyValue();
     }
     if ($resource === null) {
         return null;
     }
     if ($resource instanceof PersistentResource) {
         return $resource;
     }
     return $this->propertyMapper->convert($resource, PersistentResource::class);
 }
 /**
  * Returns the specified property.
  *
  * If the node has a content object attached, the property will be fetched
  * there if it is gettable.
  *
  * @param string $propertyName Name of the property
  * @param boolean $returnNodesAsIdentifiers If enabled, references to nodes are returned as node identifiers instead of NodeInterface instances
  * @return mixed value of the property
  * @api
  */
 public function getProperty($propertyName, $returnNodesAsIdentifiers = false)
 {
     $value = $this->nodeData->getProperty($propertyName);
     if (empty($value)) {
         return null;
     }
     $nodeType = $this->getNodeType();
     if (!$nodeType->hasConfiguration('properties.' . $propertyName)) {
         return $value;
     }
     $expectedPropertyType = $nodeType->getPropertyType($propertyName);
     if ($expectedPropertyType === 'references') {
         return $returnNodesAsIdentifiers ? $value : $this->resolvePropertyReferences($value);
     }
     if ($expectedPropertyType === 'reference') {
         return $returnNodesAsIdentifiers ? $value : $this->context->getNodeByIdentifier($value);
     }
     return $this->propertyMapper->convert($value, $expectedPropertyType);
 }
 /**
  * @param mixed $propertyValue
  * @param string $dataType
  * @return mixed
  * @throws PropertyException
  */
 protected function convertValue($propertyValue, $dataType)
 {
     $rawType = TypeHandling::truncateElementType($dataType);
     // This hardcoded handling is to circumvent rewriting PropertyMappers that convert objects. Usually they expect the source to be an object already and break if not.
     if (!TypeHandling::isSimpleType($rawType) && !is_object($propertyValue) && !is_array($propertyValue)) {
         return null;
     }
     if ($rawType === 'array') {
         $conversionTargetType = 'array<string>';
     } elseif (TypeHandling::isSimpleType($rawType)) {
         $conversionTargetType = TypeHandling::normalizeType($rawType);
     } else {
         $conversionTargetType = 'array';
     }
     $propertyMappingConfiguration = $this->createConfiguration($dataType);
     $convertedValue = $this->propertyMapper->convert($propertyValue, $conversionTargetType, $propertyMappingConfiguration);
     if ($convertedValue instanceof \Neos\Error\Messages\Error) {
         throw new PropertyException($convertedValue->getMessage(), $convertedValue->getCode());
     }
     return $convertedValue;
 }
 /**
  * @test
  */
 public function hiddenFieldContainsDataOfAPreviouslyUploadedResource()
 {
     $mockResourceUuid = '79ecda60-1a27-69ca-17bf-a5d9e80e6c39';
     $submittedData = array('foo' => array('bar' => array('name' => 'someFilename.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/some/tmp/name', 'error' => 0, 'size' => 123)));
     /** @var Result|\PHPUnit_Framework_MockObject_MockObject $mockValidationResults */
     $mockValidationResults = $this->getMockBuilder(Result::class)->disableOriginalConstructor()->getMock();
     $mockValidationResults->expects($this->atLeastOnce())->method('hasErrors')->will($this->returnValue(true));
     $this->request->expects($this->at(0))->method('getInternalArgument')->with('__submittedArgumentValidationResults')->will($this->returnValue($mockValidationResults));
     $this->request->expects($this->at(1))->method('getInternalArgument')->with('__submittedArguments')->will($this->returnValue($submittedData));
     /** @var PersistentResource|\PHPUnit_Framework_MockObject_MockObject $mockResource */
     $mockResource = $this->getMockBuilder(PersistentResource::class)->disableOriginalConstructor()->getMock();
     $mockPersistenceManager = $this->createMock(PersistenceManagerInterface::class);
     $mockPersistenceManager->expects($this->once())->method('getIdentifierByObject')->with($mockResource)->will($this->returnValue($mockResourceUuid));
     $this->inject($this->viewHelper, 'persistenceManager', $mockPersistenceManager);
     $this->mockPropertyMapper->expects($this->atLeastOnce())->method('convert')->with($submittedData['foo']['bar'], PersistentResource::class)->will($this->returnValue($mockResource));
     $mockValueResource = $this->getMockBuilder(PersistentResource::class)->disableOriginalConstructor()->getMock();
     $this->viewHelper->setArguments(array('name' => 'foo[bar]', 'value' => $mockValueResource));
     $expectedResult = '<input type="hidden" name="foo[bar][originallySubmittedResource][__identity]" value="' . $mockResourceUuid . '" />';
     $this->viewHelper->initialize();
     $actualResult = $this->viewHelper->render();
     $this->assertSame($expectedResult, $actualResult);
 }
 /**
  */
 public function setUp()
 {
     $this->ajaxWidgetComponent = new AjaxWidgetComponent();
     $this->mockObjectManager = $this->createMock(\Neos\Flow\ObjectManagement\ObjectManagerInterface::class);
     $this->inject($this->ajaxWidgetComponent, 'objectManager', $this->mockObjectManager);
     $this->mockComponentContext = $this->getMockBuilder(\Neos\Flow\Http\Component\ComponentContext::class)->disableOriginalConstructor()->getMock();
     $this->mockHttpRequest = $this->getMockBuilder(\Neos\Flow\Http\Request::class)->disableOriginalConstructor()->getMock();
     $this->mockHttpRequest->expects($this->any())->method('getArguments')->will($this->returnValue(array()));
     $this->mockComponentContext->expects($this->any())->method('getHttpRequest')->will($this->returnValue($this->mockHttpRequest));
     $this->mockHttpResponse = $this->getMockBuilder(\Neos\Flow\Http\Response::class)->disableOriginalConstructor()->getMock();
     $this->mockComponentContext->expects($this->any())->method('getHttpResponse')->will($this->returnValue($this->mockHttpResponse));
     $this->mockAjaxWidgetContextHolder = $this->getMockBuilder(\Neos\FluidAdaptor\Core\Widget\AjaxWidgetContextHolder::class)->getMock();
     $this->inject($this->ajaxWidgetComponent, 'ajaxWidgetContextHolder', $this->mockAjaxWidgetContextHolder);
     $this->mockHashService = $this->getMockBuilder(\Neos\Flow\Security\Cryptography\HashService::class)->getMock();
     $this->inject($this->ajaxWidgetComponent, 'hashService', $this->mockHashService);
     $this->mockDispatcher = $this->getMockBuilder(\Neos\Flow\Mvc\Dispatcher::class)->getMock();
     $this->inject($this->ajaxWidgetComponent, 'dispatcher', $this->mockDispatcher);
     $this->mockSecurityContext = $this->getMockBuilder(\Neos\Flow\Security\Context::class)->getMock();
     $this->inject($this->ajaxWidgetComponent, 'securityContext', $this->mockSecurityContext);
     $this->mockPropertyMapper = $this->getMockBuilder(\Neos\Flow\Property\PropertyMapper::class)->disableOriginalConstructor()->getMock();
     $this->mockPropertyMapper->expects($this->any())->method('convert')->with('', 'array', $this->mockPropertyMappingConfiguration)->will($this->returnValue(array()));
     $this->inject($this->ajaxWidgetComponent, 'propertyMapper', $this->mockPropertyMapper);
 }
 /**
  * @test
  */
 public function importWithLinebreakInDateTimeImportsCorrectly()
 {
     $xmlReader = new \XMLReader();
     $result = $xmlReader->open(__DIR__ . '/Fixtures/SingleNodeWithLinebreaks.xml', null, LIBXML_PARSEHUGE);
     $this->assertTrue($result);
     /** @var \Neos\ContentRepository\Domain\Service\ImportExport\NodeImportService $nodeImportService */
     $nodeImportService = $this->getMockBuilder(\Neos\ContentRepository\Domain\Service\ImportExport\NodeImportService::class)->setMethods(array('persistNodeData'))->getMock();
     $this->inject($nodeImportService, 'propertyMapper', $this->mockPropertyMapper);
     $this->inject($nodeImportService, 'securityContext', $this->mockSecurityContext);
     $expectedNodeDatas = array(array('creationDateTime' => array('source' => '2015-12-21T21:56:53+00:00')));
     $nodeImportService->expects($this->atLeastOnce())->method('persistNodeData')->will($this->returnCallback(function ($nodeData) use(&$actualNodeDatas) {
         unset($nodeData['Persistence_Object_Identifier']);
         $actualNodeDatas[] = $nodeData;
         return true;
     }));
     $this->mockPropertyMapper->expects($this->any())->method('convert')->will($this->returnCallback(function ($source, $targetType) {
         return array('targetType' => $targetType, 'source' => $source);
     }));
     $this->mockPropertyMapper->expects($this->any())->method('getMessages')->willReturn(new \Neos\Error\Messages\Result());
     $nodeImportService->import($xmlReader, '/');
     $this->assertCount(1, $actualNodeDatas);
     $this->assertArraySubset($expectedNodeDatas[0]['creationDateTime'], $actualNodeDatas[0]['creationDateTime'], true);
 }
 /**
  * Publishes or discards the given nodes
  *
  * @param array $nodes <\Neos\ContentRepository\Domain\Model\NodeInterface> $nodes
  * @param string $action
  * @param Workspace $selectedWorkspace
  * @throws \Exception
  * @throws \Neos\Flow\Property\Exception
  * @throws \Neos\Flow\Security\Exception
  */
 public function publishOrDiscardNodesAction(array $nodes, $action, Workspace $selectedWorkspace = null)
 {
     $propertyMappingConfiguration = $this->propertyMappingConfigurationBuilder->build();
     $propertyMappingConfiguration->setTypeConverterOption(NodeConverter::class, NodeConverter::REMOVED_CONTENT_SHOWN, true);
     foreach ($nodes as $key => $node) {
         $nodes[$key] = $this->propertyMapper->convert($node, NodeInterface::class, $propertyMappingConfiguration);
     }
     switch ($action) {
         case 'publish':
             foreach ($nodes as $node) {
                 $this->publishingService->publishNode($node);
             }
             $this->addFlashMessage($this->translator->translateById('workspaces.selectedChangesHaveBeenPublished', [], null, null, 'Modules', 'Neos.Neos'));
             break;
         case 'discard':
             $this->publishingService->discardNodes($nodes);
             $this->addFlashMessage($this->translator->translateById('workspaces.selectedChangesHaveBeenDiscarded', [], null, null, 'Modules', 'Neos.Neos'));
             break;
         default:
             throw new \RuntimeException('Invalid action "' . htmlspecialchars($action) . '" given.', 1346167441);
     }
     $this->redirect('show', null, null, ['workspace' => $selectedWorkspace]);
 }
 /**
  * Convert an element to the value it represents.
  *
  * @param \XMLReader $reader
  * @param string $currentType current element (userland) type
  * @param string $currentEncoding date encoding of element
  * @param string $currentClassName class name of element
  * @param string $currentNodeIdentifier identifier of the node
  * @param string $currentProperty current property name
  * @return mixed
  * @throws ImportException
  */
 protected function convertElementToValue(\XMLReader $reader, $currentType, $currentEncoding, $currentClassName, $currentNodeIdentifier, $currentProperty)
 {
     switch ($currentType) {
         case 'object':
             if ($currentClassName === 'DateTime') {
                 $stringValue = trim($reader->value);
                 $value = $this->propertyMapper->convert($stringValue, $currentClassName, $this->propertyMappingConfiguration);
                 if ($this->propertyMapper->getMessages()->hasErrors()) {
                     throw new ImportException(sprintf('Could not convert element <%s> to DateTime for node %s', $currentProperty, $currentNodeIdentifier), 1472992032);
                 }
             } elseif ($currentEncoding === 'json') {
                 $decodedJson = json_decode($reader->value, true);
                 if (json_last_error() !== JSON_ERROR_NONE) {
                     throw new ImportException(sprintf('Could not parse encoded JSON in element <%s> for node %s: %s', $currentProperty, $currentNodeIdentifier, json_last_error_msg()), 1472992033);
                 }
                 $value = $this->propertyMapper->convert($decodedJson, $currentClassName, $this->propertyMappingConfiguration);
                 if ($this->propertyMapper->getMessages()->hasErrors()) {
                     throw new ImportException(sprintf('Could not convert element <%s> to %s for node %s', $currentProperty, $currentClassName, $currentNodeIdentifier), 1472992034);
                 }
             } else {
                 throw new ImportException(sprintf('Unsupported encoding "%s"', $currentEncoding), 1404397061);
             }
             break;
         case 'string':
             $value = $reader->value;
             break;
         default:
             $value = $this->propertyMapper->convert($reader->value, $currentType, $this->propertyMappingConfiguration);
             if ($this->propertyMapper->getMessages()->hasErrors()) {
                 throw new ImportException(sprintf('Could not convert element <%s> to %s for node %s', $currentProperty, $currentType, $currentNodeIdentifier), 1472992035);
             }
             return $value;
     }
     $this->persistEntities($value);
     return $value;
 }
 /**
  * @test
  */
 public function viewHelperRendersUriViaGivenNodeObject()
 {
     $targetNode = $this->propertyMapper->convert('/sites/example/home', Node::class);
     $this->assertSame('<a href="/en/home.html">' . $targetNode->getLabel() . '</a>', $this->viewHelper->render($targetNode));
 }
 /**
  * @test
  */
 public function viewHelperRendersUriViaGivenNodeObject()
 {
     $targetNode = $this->propertyMapper->convert('/sites/example/home', Node::class);
     $this->assertOutputLinkValid('home.html', $this->viewHelper->render($targetNode));
 }
 /**
  * Remove broken entity references
  *
  * This removes references from nodes to entities which don't exist anymore.
  *
  * @param string $workspaceName
  * @param boolean $dryRun
  * @return void
  */
 public function removeBrokenEntityReferences($workspaceName, $dryRun)
 {
     $this->output->outputLine('Checking for broken entity references ...');
     /** @var \Neos\ContentRepository\Domain\Model\Workspace $workspace */
     $workspace = $this->workspaceRepository->findByIdentifier($workspaceName);
     $nodeTypesWithEntityReferences = array();
     foreach ($this->nodeTypeManager->getNodeTypes() as $nodeType) {
         /** @var NodeType $nodeType */
         foreach (array_keys($nodeType->getProperties()) as $propertyName) {
             $propertyType = $nodeType->getPropertyType($propertyName);
             if (strpos($propertyType, '\\') !== false) {
                 if (!isset($nodeTypesWithEntityReferences[$nodeType->getName()])) {
                     $nodeTypesWithEntityReferences[$nodeType->getName()] = array();
                 }
                 $nodeTypesWithEntityReferences[$nodeType->getName()][$propertyName] = $propertyType;
             }
         }
     }
     $nodesWithBrokenEntityReferences = array();
     $brokenReferencesCount = 0;
     foreach ($nodeTypesWithEntityReferences as $nodeTypeName => $properties) {
         $nodeDatas = $this->nodeDataRepository->findByParentAndNodeTypeRecursively('/', $nodeTypeName, $workspace);
         foreach ($nodeDatas as $nodeData) {
             /** @var NodeData $nodeData */
             foreach ($properties as $propertyName => $propertyType) {
                 $propertyValue = $nodeData->getProperty($propertyName);
                 $convertedProperty = null;
                 if (is_object($propertyValue)) {
                     $convertedProperty = $propertyValue;
                 }
                 if (is_string($propertyValue) && strlen($propertyValue) === 36) {
                     $convertedProperty = $this->propertyMapper->convert($propertyValue, $propertyType);
                     if ($convertedProperty === null) {
                         $nodesWithBrokenEntityReferences[$nodeData->getIdentifier()][$propertyName] = $nodeData;
                         $this->output->outputLine('Broken reference in "%s", property "%s" (%s) referring to %s.', array($nodeData->getPath(), $nodeData->getIdentifier(), $propertyName, $propertyType, $propertyValue));
                         $brokenReferencesCount++;
                     }
                 }
                 if ($convertedProperty instanceof Proxy) {
                     try {
                         $convertedProperty->__load();
                     } catch (EntityNotFoundException $e) {
                         $nodesWithBrokenEntityReferences[$nodeData->getIdentifier()][$propertyName] = $nodeData;
                         $this->output->outputLine('Broken reference in "%s", property "%s" (%s) referring to %s.', array($nodeData->getPath(), $nodeData->getIdentifier(), $propertyName, $propertyType, $propertyValue));
                         $brokenReferencesCount++;
                     }
                 }
             }
         }
     }
     if ($brokenReferencesCount > 0) {
         $this->output->outputLine();
         if (!$dryRun) {
             $self = $this;
             $this->askBeforeExecutingTask('Do you want to remove the broken entity references?', function () use($self, $nodesWithBrokenEntityReferences, $brokenReferencesCount, $workspaceName, $dryRun) {
                 foreach ($nodesWithBrokenEntityReferences as $nodeIdentifier => $properties) {
                     foreach ($properties as $propertyName => $nodeData) {
                         /** @var NodeData $nodeData */
                         $nodeData->setProperty($propertyName, null);
                     }
                 }
                 $self->output->outputLine('Removed %s broken entity reference%s.', array($brokenReferencesCount, $brokenReferencesCount > 1 ? 's' : ''));
             });
         } else {
             $this->output->outputLine('Found %s broken entity reference%s to be removed.', array($brokenReferencesCount, $brokenReferencesCount > 1 ? 's' : ''));
         }
         $this->output->outputLine();
         $this->persistenceManager->persistAll();
     }
 }