diff --git a/Neos.ContentRepository/Classes/Domain/Service/ImportExport/NodeImportService.php b/Neos.ContentRepository/Classes/Domain/Service/ImportExport/NodeImportService.php index 5bd0088e13a..0e30589d743 100644 --- a/Neos.ContentRepository/Classes/Domain/Service/ImportExport/NodeImportService.php +++ b/Neos.ContentRepository/Classes/Domain/Service/ImportExport/NodeImportService.php @@ -180,9 +180,15 @@ class NodeImportService public function import(\XMLReader $xmlReader, $targetPath, $resourceLoadPath = null) { $this->propertyMappingConfiguration = new ImportExportPropertyMappingConfiguration($resourceLoadPath); - $this->nodeNameStack = ($targetPath === '/') ? array() : array_map(function ($pathSegment) { - return Utility::renderValidNodeName($pathSegment); - }, explode('/', $targetPath)); + $this->nodeNameStack = []; + + if ($targetPath !== '/') { + $pathSegments = explode('/', $targetPath); + array_shift($pathSegments); + $this->nodeNameStack = array_map(function ($pathSegment) { + return Utility::renderValidNodeName($pathSegment); + }, $pathSegments); + } $formatVersion = $this->determineFormatVersion($xmlReader); switch ($formatVersion) { @@ -267,7 +273,7 @@ protected function parseElement(\XMLReader $xmlReader) $this->nodeIdentifierStack[] = $xmlReader->getAttribute('identifier'); // update current path $nodeName = $xmlReader->getAttribute('nodeName'); - if ($nodeName !== '/') { + if ($nodeName !== '/' && $nodeName !== '') { $this->nodeNameStack[] = Utility::renderValidNodeName($nodeName); } break; @@ -583,7 +589,7 @@ protected function parseEndElement(\XMLReader $reader) protected function getCurrentPath() { $path = implode('/', $this->nodeNameStack); - return ($path === '') ? '/' : $path; + return '/' . $path; } /** diff --git a/Neos.ContentRepository/Classes/Utility.php b/Neos.ContentRepository/Classes/Utility.php index 5608c1812ee..0a3171c5a05 100644 --- a/Neos.ContentRepository/Classes/Utility.php +++ b/Neos.ContentRepository/Classes/Utility.php @@ -35,6 +35,8 @@ public static function renderValidNodeName($name) return $name; } + $originalName = $name; + // Transliterate (transform 北京 to 'Bei Jing') $name = Transliterator::transliterate($name); @@ -44,6 +46,11 @@ public static function renderValidNodeName($name) // Ensure only allowed characters are left $name = preg_replace('/[^a-z0-9\-]/', '', $name); + // Make sure we don't have an empty string left. + if ($name === '') { + $name = 'node-' . strtolower(md5($originalName)); + } + return $name; } diff --git a/Neos.ContentRepository/Tests/Unit/Domain/Service/ImportExport/NodeImportServiceTest.php b/Neos.ContentRepository/Tests/Unit/Domain/Service/ImportExport/NodeImportServiceTest.php index 5f556562fde..46e98aa6d2b 100644 --- a/Neos.ContentRepository/Tests/Unit/Domain/Service/ImportExport/NodeImportServiceTest.php +++ b/Neos.ContentRepository/Tests/Unit/Domain/Service/ImportExport/NodeImportServiceTest.php @@ -14,7 +14,6 @@ use Neos\Flow\Property\PropertyMapper; use Neos\Flow\Security\Context; use Neos\Flow\Tests\UnitTestCase; -use Neos\Flow\Utility\Now; use Neos\ContentRepository\Domain\Service\ImportExport\NodeImportService; class NodeImportServiceTest extends UnitTestCase @@ -63,8 +62,8 @@ public function importSingleNode() 'removed' => false, 'hidden' => false, 'hiddenInIndex' => false, - 'path' => 'neosdemoio', - 'pathHash' => '0423106850d41d93150a4e8e3ecd68b3', + 'path' => '/neosdemoio', + 'pathHash' => '9204ab1d1079b1d950fffecf874955c3', 'parentPath' => '/', 'parentPathHash' => '6666cd76f96956469e7be39d750cc7d9', 'properties' => array( @@ -129,8 +128,8 @@ public function importSingleNodeWithoutIdentifier() 'removed' => false, 'hidden' => false, 'hiddenInIndex' => false, - 'path' => 'neosdemoio', - 'pathHash' => '0423106850d41d93150a4e8e3ecd68b3', + 'path' => '/neosdemoio', + 'pathHash' => '9204ab1d1079b1d950fffecf874955c3', 'parentPath' => '/', 'parentPathHash' => '6666cd76f96956469e7be39d750cc7d9', 'properties' => array( @@ -184,8 +183,8 @@ public function importWithEmptyPropertyImportsAllProperties() 'removed' => false, 'hidden' => false, 'hiddenInIndex' => false, - 'path' => 'neosdemoio', - 'pathHash' => '0423106850d41d93150a4e8e3ecd68b3', + 'path' => '/neosdemoio', + 'pathHash' => '9204ab1d1079b1d950fffecf874955c3', 'parentPath' => '/', 'parentPathHash' => '6666cd76f96956469e7be39d750cc7d9', 'properties' => array( @@ -259,8 +258,8 @@ public function importWithEmptyPropertyImportsAllProperties() 'removed' => false, 'hidden' => false, 'hiddenInIndex' => false, - 'path' => 'node53a18fb53bdf2', - 'pathHash' => '3f1d4fea7c0b21d21098960149de9c80', + 'path' => '/node53a18fb53bdf2', + 'pathHash' => 'adb885c51ef09d0d4beec84adff97355', 'parentPath' => '/', 'parentPathHash' => '6666cd76f96956469e7be39d750cc7d9', 'properties' => array( @@ -352,8 +351,8 @@ public function importWithArrayPropertiesImportsCorrectly() 'removed' => false, 'hidden' => false, 'hiddenInIndex' => false, - 'path' => 'node53a18fb53bdf2', - 'pathHash' => '3f1d4fea7c0b21d21098960149de9c80', + 'path' => '/node53a18fb53bdf2', + 'pathHash' => 'adb885c51ef09d0d4beec84adff97355', 'parentPath' => '/', 'parentPathHash' => '6666cd76f96956469e7be39d750cc7d9', 'properties' => array( diff --git a/Neos.ContentRepository/Tests/Unit/UtilityTest.php b/Neos.ContentRepository/Tests/Unit/UtilityTest.php index fb3ffde53a8..91b0a4fca2c 100644 --- a/Neos.ContentRepository/Tests/Unit/UtilityTest.php +++ b/Neos.ContentRepository/Tests/Unit/UtilityTest.php @@ -39,7 +39,9 @@ public function sourcesAndNodeNames() ['ελληνικά', 'ellenika'], ['မြန်မာဘာသာ', 'm-n-maabhaasaa'], [' हिन्दी', 'hindii'], - [' x- ', 'x'] + [' x- ', 'x'], + ['', 'node-' . md5('')], + [',.~', 'node-' . md5(',.~')] ]; } diff --git a/Neos.Media/Classes/Domain/Service/AssetService.php b/Neos.Media/Classes/Domain/Service/AssetService.php index 24a723b0fe6..2632bec62b0 100644 --- a/Neos.Media/Classes/Domain/Service/AssetService.php +++ b/Neos.Media/Classes/Domain/Service/AssetService.php @@ -251,9 +251,9 @@ public function replaceAssetResource(AssetInterface $asset, PersistentResource $ $uriMapping = []; $redirectHandlerEnabled = isset($options['generateRedirects']) && (boolean)$options['generateRedirects'] === true && $this->packageManager->isPackageAvailable('Neos.RedirectHandler'); if ($redirectHandlerEnabled) { - $uriMapping[ - $this->resourceManager->getPublicPersistentResourceUri($originalAssetResource) - ] = $this->resourceManager->getPublicPersistentResourceUri($asset->getResource()); + $originalAssetResourceUri = new Uri($this->resourceManager->getPublicPersistentResourceUri($originalAssetResource)); + $newAssetResourceUri = new Uri($this->resourceManager->getPublicPersistentResourceUri($asset->getResource())); + $uriMapping[$originalAssetResourceUri->getPath()] = $newAssetResourceUri->getPath(); } if (method_exists($asset, 'getVariants')) { @@ -272,9 +272,9 @@ public function replaceAssetResource(AssetInterface $asset, PersistentResource $ } if ($redirectHandlerEnabled) { - $uriMapping[ - $this->resourceManager->getPublicPersistentResourceUri($originalVariantResource) - ] = $this->resourceManager->getPublicPersistentResourceUri($variant->getResource()); + $originalVariantResourceUri = new Uri($this->resourceManager->getPublicPersistentResourceUri($originalVariantResource)); + $newVariantResourceUri = new Uri($this->resourceManager->getPublicPersistentResourceUri($variant->getResource())); + $uriMapping[$originalVariantResourceUri->getPath()] = $newVariantResourceUri->getPath(); } $this->getRepository($variant)->update($variant);