diff --git a/Command/MovePageTreeCommand.php b/Command/MovePageTreeCommand.php
new file mode 100644
index 000000000..e42f4df8c
--- /dev/null
+++ b/Command/MovePageTreeCommand.php
@@ -0,0 +1,58 @@
+setName('sulu:article:page-tree:move')
+ ->addArgument('source-segment', InputArgument::REQUIRED)
+ ->addArgument('destination-segment', InputArgument::REQUIRED)
+ ->addArgument('webspace-key', InputArgument::REQUIRED)
+ ->addArgument('locale', InputArgument::REQUIRED);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $source = $input->getArgument('source-segment');
+ $destination = $input->getArgument('destination-segment');
+ $webspaceKey = $input->getArgument('webspace-key');
+ $locale = $input->getArgument('locale');
+
+ $mover = $this->getContainer()->get('sulu_article.page_tree_route.mover');
+ $strategyPool = $this->getContainer()->get('sulu.content.resource_locator.strategy_pool');
+ $documentManager = $this->getContainer()->get('sulu_document_manager.document_manager');
+ $strategy = $strategyPool->getStrategyByWebspaceKey($webspaceKey);
+
+ $destinationUuid = $strategy->loadByResourceLocator($destination, $webspaceKey, $locale);
+ $document = $documentManager->find($destinationUuid, $locale);
+
+ $mover->move($source, $document);
+
+ $documentManager->flush();
+ }
+}
diff --git a/DependencyInjection/SuluArticleExtension.php b/DependencyInjection/SuluArticleExtension.php
index 80ab70bcd..b4e048e4c 100644
--- a/DependencyInjection/SuluArticleExtension.php
+++ b/DependencyInjection/SuluArticleExtension.php
@@ -163,6 +163,7 @@ public function load(array $configs, ContainerBuilder $container)
'sulu_article.page_tree_route.updater.' . $config['content_types']['page_tree_route']['page_route_cascade']
);
+ $loader->load('page_tree_move.xml');
if ($config['content_types']['page_tree_route']['page_route_cascade'] !== 'off') {
$loader->load('page_tree_update.xml');
}
diff --git a/PageTree/PageTreeMoverInterface.php b/PageTree/PageTreeMoverInterface.php
new file mode 100644
index 000000000..814af1ace
--- /dev/null
+++ b/PageTree/PageTreeMoverInterface.php
@@ -0,0 +1,26 @@
+findLinkedArticles($document->getUuid(), $document->getLocale());
+ $articles = $this->findLinkedArticles('page', $document->getUuid(), $document->getLocale());
foreach ($articles as $article) {
- $this->updateArticle($article, $document->getResourceSegment(), $document->getLocale());
+ $this->updateArticle($article, $document);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function move($source, BasePageDocument $document)
+ {
+ $articles = $this->findLinkedArticles('page-path', $source, $document->getLocale());
+ foreach ($articles as $article) {
+ $this->updateArticle($article, $document);
}
}
/**
* Find articles linked to the given page.
*
- * @param string $uuid
+ * @param string $field
+ * @param string $value
* @param string $locale
*
* @return ArticleInterface[]
*/
- private function findLinkedArticles($uuid, $locale)
+ private function findLinkedArticles($field, $value, $locale)
{
$where = [];
foreach ($this->metadataFactory->getStructures('article') as $metadata) {
@@ -98,11 +110,12 @@ private function findLinkedArticles($uuid, $locale)
}
$where[] = sprintf(
- '([%s] = "%s" AND [%s-page] = "%s")',
+ '([%s] = "%s" AND [%s-%s] = "%s")',
$this->propertyEncoder->localizedSystemName('template', $locale),
$metadata->getName(),
$this->propertyEncoder->localizedContentName($property->getName(), $locale),
- $uuid
+ $field,
+ $value
);
}
@@ -125,15 +138,18 @@ private function findLinkedArticles($uuid, $locale)
* Update route of given article.
*
* @param ArticleDocument $article
- * @param string $resourceSegment
- * @param string $locale
+ * @param BasePageDocument $document
*/
- private function updateArticle(ArticleDocument $article, $resourceSegment, $locale)
+ private function updateArticle(ArticleDocument $article, BasePageDocument $document)
{
+ $locale = $document->getLocale();
+ $resourceSegment = $document->getResourceSegment();
+
$property = $this->getRoutePathPropertyNameByStructureType($article->getStructureType());
$propertyName = $this->propertyEncoder->localizedContentName($property->getName(), $locale);
$node = $this->documentInspector->getNode($article);
+ $node->setProperty($propertyName . '-page', $document->getUuid());
$node->setProperty($propertyName . '-page-path', $resourceSegment);
$suffix = $node->getPropertyValueWithDefault($propertyName . '-suffix', null);
diff --git a/Resources/config/page_tree_move.xml b/Resources/config/page_tree_move.xml
new file mode 100644
index 000000000..8390fc1d9
--- /dev/null
+++ b/Resources/config/page_tree_move.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Resources/config/page_tree_update.xml b/Resources/config/page_tree_update.xml
index 3c417f08a..7971005ee 100644
--- a/Resources/config/page_tree_update.xml
+++ b/Resources/config/page_tree_update.xml
@@ -16,7 +16,7 @@
+ class="Sulu\Bundle\ArticleBundle\PageTree\PageTreeRepository">
diff --git a/Tests/Functional/PageTree/PageTreeRepositoryTest.php b/Tests/Functional/PageTree/PageTreeRepositoryTest.php
new file mode 100644
index 000000000..f27c86c99
--- /dev/null
+++ b/Tests/Functional/PageTree/PageTreeRepositoryTest.php
@@ -0,0 +1,188 @@
+initPhpcr();
+ $this->purgeDatabase();
+
+ $this->documentManager = $this->getContainer()->get('sulu_document_manager.document_manager');
+ $this->pageTreeRepository = new PageTreeRepository(
+ $this->documentManager,
+ $this->getContainer()->get('sulu_content.structure.factory'),
+ $this->getContainer()->get('sulu_document_manager.property_encoder'),
+ $this->getContainer()->get('sulu_document_manager.document_inspector')
+ );
+ }
+
+ public function testUpdate()
+ {
+ $pages = [
+ $this->createPage('Test 1', '/test-1'),
+ $this->createPage('Test 2', '/test-2'),
+ ];
+
+ $articles = [
+ $this->createArticle($this->getPathData($pages[0], 'article-1')),
+ $this->createArticle($this->getPathData($pages[0], 'article-2')),
+ $this->createArticle($this->getPathData($pages[1], 'article-3')),
+ ];
+ $this->documentManager->flush();
+
+ $pages[0]->setResourceSegment('/test-3');
+ $this->documentManager->persist($pages[0], $this->locale);
+ $this->documentManager->publish($pages[0], $this->locale);
+ $this->documentManager->flush();
+ $this->documentManager->clear();
+
+ $this->pageTreeRepository->update($pages[0]);
+ $this->documentManager->flush();
+ $this->documentManager->clear();
+
+ $result = [
+ $this->documentManager->find($articles[0]['id'], $this->locale),
+ $this->documentManager->find($articles[1]['id'], $this->locale),
+ $this->documentManager->find($articles[2]['id'], $this->locale),
+ ];
+
+ $this->assertEquals('/test-3/article-1', $result[0]->getRoutePath());
+ $this->assertEquals('/test-3/article-2', $result[1]->getRoutePath());
+ $this->assertEquals('/test-2/article-3', $result[2]->getRoutePath());
+ }
+
+ public function testMove()
+ {
+ $pages = [
+ $this->createPage('Test 1', '/test-1'),
+ $this->createPage('Test 2', '/test-2'),
+ $this->createPage('Test 3', '/test-3'),
+ ];
+
+ $articles = [
+ $this->createArticle($this->getPathData($pages[0], 'article-1')),
+ $this->createArticle($this->getPathData($pages[0], 'article-2')),
+ $this->createArticle($this->getPathData($pages[1], 'article-3')),
+ ];
+
+ $this->documentManager->flush();
+ $this->documentManager->clear();
+
+ $this->pageTreeRepository->move('/test-1', $pages[2]);
+ $this->documentManager->flush();
+ $this->documentManager->clear();
+
+ $result = [
+ $this->documentManager->find($articles[0]['id'], $this->locale),
+ $this->documentManager->find($articles[1]['id'], $this->locale),
+ $this->documentManager->find($articles[2]['id'], $this->locale),
+ ];
+
+ $this->assertEquals('/test-3/article-1', $result[0]->getRoutePath());
+ $this->assertEquals('/test-3/article-2', $result[1]->getRoutePath());
+ $this->assertEquals('/test-2/article-3', $result[2]->getRoutePath());
+ }
+
+ private function getPathData(PageDocument $page, $suffix)
+ {
+ return [
+ 'page' => [
+ 'uuid' => $page->getUuid(),
+ 'path' => $page->getResourceSegment(),
+ ],
+ 'suffix' => $suffix,
+ 'path' => $page->getResourceSegment() . '/' . $suffix,
+ ];
+ }
+
+ /**
+ * Create a new article.
+ *
+ * @param array $routePathData
+ * @param string $title
+ *
+ * @return array
+ */
+ private function createArticle(array $routePathData, $title = 'Test Article')
+ {
+ $client = $this->createAuthenticatedClient();
+ $client->request(
+ 'POST',
+ '/api/articles?locale=' . $this->locale . '&action=publish',
+ [
+ 'title' => $title,
+ 'template' => 'page_tree_route',
+ 'routePath' => $routePathData,
+ 'authored' => '2016-01-01',
+ ]
+ );
+
+ return json_decode($client->getResponse()->getContent(), true);
+ }
+
+ /**
+ * Create a new page.
+ *
+ * @param string $title
+ * @param string $resourceSegment
+ *
+ * @return PageDocument
+ */
+ private function createPage($title = 'Test Page', $resourceSegment = '/test-page')
+ {
+ $sessionManager = $this->getContainer()->get('sulu.phpcr.session');
+ $page = $this->documentManager->create('page');
+
+ $uuidReflection = new \ReflectionProperty(PageDocument::class, 'uuid');
+ $uuidReflection->setAccessible(true);
+ $uuidReflection->setValue($page, Uuid::uuid4()->toString());
+
+ $page->setTitle($title);
+ $page->setStructureType('default');
+ $page->setParent($this->documentManager->find($sessionManager->getContentPath('sulu_io')));
+ $page->setResourceSegment($resourceSegment);
+
+ $this->documentManager->persist($page, $this->locale);
+ $this->documentManager->publish($page, $this->locale);
+ $this->documentManager->flush();
+
+ return $page;
+ }
+}