diff --git a/Controller/ArticleController.php b/Controller/ArticleController.php
index c7ff777d1..21144fc23 100644
--- a/Controller/ArticleController.php
+++ b/Controller/ArticleController.php
@@ -375,6 +375,13 @@ public function postTriggerAction($uuid, Request $request)
$data = $this->getDocumentManager()->find($copiedPath, $locale);
break;
+ case 'order':
+ $this->orderPages($this->getRequestParameter($request, 'pages', true), $locale);
+ $this->getDocumentManager()->flush();
+ $this->getDocumentManager()->clear();
+
+ $data = $this->getDocumentManager()->find($uuid, $locale);
+ break;
default:
throw new RestException('Unrecognized action: ' . $action);
}
@@ -393,6 +400,23 @@ public function postTriggerAction($uuid, Request $request)
return $this->handleView($view);
}
+ /**
+ * Ordering given pages.
+ *
+ * @param array $pages
+ * @param string $locale
+ */
+ private function orderPages(array $pages, $locale)
+ {
+ $documentManager = $this->getDocumentManager();
+
+ $tmp = [];
+ for ($i = 0; $i < count($pages); ++$i) {
+ $tmp[] = $document = $documentManager->find($pages[$i], $locale);
+ $documentManager->reorder($document, null);
+ }
+ }
+
/**
* {@inheritdoc}
*/
diff --git a/Document/Subscriber/ArticleSubscriber.php b/Document/Subscriber/ArticleSubscriber.php
index c453afdbc..ace6d4548 100644
--- a/Document/Subscriber/ArticleSubscriber.php
+++ b/Document/Subscriber/ArticleSubscriber.php
@@ -29,8 +29,10 @@
use Sulu\Component\DocumentManager\Event\PublishEvent;
use Sulu\Component\DocumentManager\Event\RemoveDraftEvent;
use Sulu\Component\DocumentManager\Event\RemoveEvent;
+use Sulu\Component\DocumentManager\Event\ReorderEvent;
use Sulu\Component\DocumentManager\Event\UnpublishEvent;
use Sulu\Component\DocumentManager\Events;
+use Sulu\Component\Util\SortUtils;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
@@ -123,6 +125,7 @@ public static function getSubscribedEvents()
['publishChildren', 0],
['persistPageData', -2000],
],
+ Events::REORDER => [['persistPageDataOnReorder', -2000]],
Events::UNPUBLISH => 'handleUnpublish',
Events::REMOVE_DRAFT => [['handleScheduleIndex', -1024], ['removeDraftChildren', 0]],
Events::FLUSH => [['handleFlush', -2048], ['handleFlushLive', -2048]],
@@ -236,6 +239,24 @@ public function publishChildren(PublishEvent $event)
}
}
+ /**
+ * Persist page-data for reordering children.
+ *
+ * @param ReorderEvent $event
+ */
+ public function persistPageDataOnReorder(ReorderEvent $event)
+ {
+ $document = $event->getDocument();
+ if (!$document instanceof ArticlePageDocument) {
+ return;
+ }
+
+ $document = $document->getParent();
+ $node = $this->documentInspector->getNode($document);
+
+ $this->setPageData($document, $node, $document->getLocale());
+ }
+
/**
* Persist page-data.
*
@@ -248,6 +269,18 @@ public function persistPageData($event)
return;
}
+ $this->setPageData($document, $event->getNode(), $event->getLocale());
+ }
+
+ /**
+ * Set page-data for given document on given node.
+ *
+ * @param ArticleDocument $document
+ * @param NodeInterface $node
+ * @param string $locale
+ */
+ private function setPageData(ArticleDocument $document, NodeInterface $node, $locale)
+ {
$pages = [
[
'uuid' => $document->getUuid(),
@@ -270,9 +303,11 @@ public function persistPageData($event)
}
}
+ $pages = SortUtils::multisort($pages, '[pageNumber]');
+
$document->setPages($pages);
- $event->getNode()->setProperty(
- $this->propertyEncoder->localizedSystemName(self::PAGES_PROPERTY, $event->getLocale()),
+ $node->setProperty(
+ $this->propertyEncoder->localizedSystemName(self::PAGES_PROPERTY, $locale),
json_encode($pages)
);
}
diff --git a/Document/Subscriber/PageSubscriber.php b/Document/Subscriber/PageSubscriber.php
index 6253ca2de..f2ecee942 100644
--- a/Document/Subscriber/PageSubscriber.php
+++ b/Document/Subscriber/PageSubscriber.php
@@ -14,10 +14,12 @@
use Sulu\Bundle\ArticleBundle\Document\Behavior\PageBehavior;
use Sulu\Component\DocumentManager\Behavior\Mapping\ChildrenBehavior;
use Sulu\Component\DocumentManager\DocumentInspector;
+use Sulu\Component\DocumentManager\DocumentManagerInterface;
use Sulu\Component\DocumentManager\Event\HydrateEvent;
use Sulu\Component\DocumentManager\Event\PersistEvent;
use Sulu\Component\DocumentManager\Event\PublishEvent;
use Sulu\Component\DocumentManager\Event\RemoveEvent;
+use Sulu\Component\DocumentManager\Event\ReorderEvent;
use Sulu\Component\DocumentManager\Event\RestoreEvent;
use Sulu\Component\DocumentManager\Events;
use Sulu\Component\DocumentManager\PropertyEncoder;
@@ -39,15 +41,24 @@ class PageSubscriber implements EventSubscriberInterface
* @var PropertyEncoder
*/
private $propertyEncoder;
+ /**
+ * @var DocumentManagerInterface
+ */
+ private $documentManager;
/**
* @param DocumentInspector $documentInspector
* @param PropertyEncoder $propertyEncoder
+ * @param DocumentManagerInterface $documentManager
*/
- public function __construct(DocumentInspector $documentInspector, PropertyEncoder $propertyEncoder)
- {
+ public function __construct(
+ DocumentInspector $documentInspector,
+ PropertyEncoder $propertyEncoder,
+ DocumentManagerInterface $documentManager
+ ) {
$this->documentInspector = $documentInspector;
$this->propertyEncoder = $propertyEncoder;
+ $this->documentManager = $documentManager;
}
/**
@@ -60,6 +71,7 @@ public static function getSubscribedEvents()
Events::PERSIST => [['handlePersist', -1024]],
Events::REMOVE => [['handleRemove', 5]],
Events::PUBLISH => [['handlePublishPageNumber', -1024]],
+ Events::REORDER => [['handleReorder', 0]],
Events::RESTORE => [['handleRestore', -1024]],
];
}
@@ -115,6 +127,33 @@ public function handlePersist(PersistEvent $event)
$document->setPageNumber($page);
}
+ /**
+ * Adjust the page-numbers of siblings when reordering a page.
+ *
+ * @param ReorderEvent $event
+ */
+ public function handleReorder(ReorderEvent $event)
+ {
+ $document = $event->getDocument();
+ if (!$document instanceof PageBehavior) {
+ return;
+ }
+
+ $propertyName = $this->propertyEncoder->systemName(static::FIELD);
+ $parentNode = $this->documentInspector->getNode($document->getParent());
+
+ $page = 1;
+ foreach ($parentNode->getNodes() as $childNode) {
+ $child = $this->documentManager->find($childNode->getIdentifier(), $event->getLocale());
+ if (!$child instanceof PageBehavior) {
+ continue;
+ }
+
+ $childNode->setProperty($propertyName, ++$page);
+ $child->setPageNumber($page);
+ }
+ }
+
/**
* Copy page-number to live workspace.
*
diff --git a/Resources/config/services.xml b/Resources/config/services.xml
index 5b0b78763..f45e89ba9 100644
--- a/Resources/config/services.xml
+++ b/Resources/config/services.xml
@@ -125,7 +125,7 @@
class="Sulu\Bundle\ArticleBundle\Document\Subscriber\PageSubscriber">
-
+
diff --git a/Tests/Functional/Controller/ArticleControllerTest.php b/Tests/Functional/Controller/ArticleControllerTest.php
index 2fd7334c3..d3ff4c7a9 100644
--- a/Tests/Functional/Controller/ArticleControllerTest.php
+++ b/Tests/Functional/Controller/ArticleControllerTest.php
@@ -74,6 +74,24 @@ protected function post($title = 'Test-Article', $template = 'default')
return json_decode($client->getResponse()->getContent(), true);
}
+ protected function postPage($article, $pageTitle = 'Test-Page')
+ {
+ $client = $this->createAuthenticatedClient();
+ $client->request(
+ 'POST',
+ '/api/articles/' . $article['id'] . '/pages?locale=de',
+ [
+ 'pageTitle' => $pageTitle,
+ 'template' => $article['template'],
+ 'authored' => '2016-01-01',
+ ]
+ );
+
+ $this->assertHttpStatusCode(200, $client->getResponse());
+
+ return json_decode($client->getResponse()->getContent(), true);
+ }
+
public function testPost($title = 'Test-Article', $template = 'default')
{
$response = $this->post($title, $template);
@@ -1048,6 +1066,33 @@ public function testPostPageTreeRouteGenerateRemovePage()
);
}
+ public function testOrderPages()
+ {
+ $article = $this->post();
+ $pages = [
+ $this->postPage($article, 'Page 1'),
+ $this->postPage($article, 'Page 2'),
+ $this->postPage($article, 'Page 3'),
+ ];
+ $expectedPages = [$pages[1]['id'], $pages[2]['id'], $pages[0]['id']];
+
+ $client = $this->createAuthenticatedClient();
+ $client->request(
+ 'POST',
+ '/api/articles/' . $article['id'] . '?action=order&locale=de',
+ ['pages' => $expectedPages]
+ );
+
+ $this->assertHttpStatusCode(200, $client->getResponse());
+ $response = json_decode($client->getResponse()->getContent(), true);
+
+ $responsePages = $response['_embedded']['pages'];
+ for ($i = 0; $i < count($expectedPages); ++$i) {
+ $this->assertEquals($expectedPages[$i], $responsePages[$i]['id']);
+ $this->assertEquals($i + 2, $responsePages[$i]['pageNumber']);
+ }
+ }
+
private function postPageTreeRoute($routePathData, $title = 'Test Article')
{
$client = $this->createAuthenticatedClient();
diff --git a/Tests/Unit/Document/Subscriber/ArticleSubscriberTest.php b/Tests/Unit/Document/Subscriber/ArticleSubscriberTest.php
index 1b370c8bc..3c8e3e876 100644
--- a/Tests/Unit/Document/Subscriber/ArticleSubscriberTest.php
+++ b/Tests/Unit/Document/Subscriber/ArticleSubscriberTest.php
@@ -29,6 +29,7 @@
use Sulu\Component\DocumentManager\Event\PublishEvent;
use Sulu\Component\DocumentManager\Event\RemoveDraftEvent;
use Sulu\Component\DocumentManager\Event\RemoveEvent;
+use Sulu\Component\DocumentManager\Event\ReorderEvent;
class ArticleSubscriberTest extends \PHPUnit_Framework_TestCase
{
@@ -451,4 +452,56 @@ public function testPersistPageData()
$this->articleSubscriber->persistPageData($event->reveal());
}
+
+ public function testPersistPageDataOnReorder()
+ {
+ $node = $this->prophesize(NodeInterface::class);
+
+ $orderedDocument = $this->prophesize(ArticlePageDocument::class);
+ $orderedDocument->getParent()->willReturn($this->document->reveal());
+ $this->document->getLocale()->willReturn($this->locale);
+ $this->documentInspector->getNode($this->document->reveal())->willReturn($node->reveal());
+
+ $event = $this->prophesize(ReorderEvent::class);
+ $event->getDocument()->willReturn($orderedDocument->reveal());
+
+ $pages = [
+ [
+ 'uuid' => '123-123-123',
+ 'title' => 'Test article: page 1',
+ 'routePath' => '/test-article',
+ 'pageNumber' => 1,
+ ],
+ [
+ 'uuid' => '321-321-321',
+ 'title' => 'Test article: page 2',
+ 'routePath' => '/test-article/page-2',
+ 'pageNumber' => 2,
+ ],
+ ];
+
+ $this->document->getUuid()->willReturn($pages[0]['uuid']);
+ $this->document->getPageTitle()->willReturn($pages[0]['title']);
+ $this->document->getRoutePath()->willReturn($pages[0]['routePath']);
+ $this->document->getPageNumber()->willReturn($pages[0]['pageNumber']);
+
+ $child = $this->prophesize(ArticlePageDocument::class);
+ $child->getUuid()->willReturn($pages[1]['uuid']);
+ $child->getPageTitle()->willReturn($pages[1]['title']);
+ $child->getRoutePath()->willReturn($pages[1]['routePath']);
+ $child->getPageNumber()->willReturn($pages[1]['pageNumber']);
+ $this->document->getChildren()->willReturn(new \ArrayIterator([$child->reveal()]));
+
+ $this->documentInspector->getLocalizationState($child->reveal())->willReturn(LocalizationState::LOCALIZED);
+
+ $propertyName = 'i18n:' . $this->locale . '-' . ArticleSubscriber::PAGES_PROPERTY;
+ $this->propertyEncoder->localizedSystemName(ArticleSubscriber::PAGES_PROPERTY, $this->locale)->willReturn(
+ $propertyName
+ );
+
+ $this->document->setPages($pages)->shouldBeCalled();
+ $node->setProperty($propertyName, json_encode($pages))->shouldBeCalled();
+
+ $this->articleSubscriber->persistPageDataOnReorder($event->reveal());
+ }
}
diff --git a/Tests/Unit/Document/Subscriber/PageSubscriberTest.php b/Tests/Unit/Document/Subscriber/PageSubscriberTest.php
index b450a90fa..6b09e7989 100644
--- a/Tests/Unit/Document/Subscriber/PageSubscriberTest.php
+++ b/Tests/Unit/Document/Subscriber/PageSubscriberTest.php
@@ -16,9 +16,11 @@
use Sulu\Bundle\ArticleBundle\Document\Subscriber\PageSubscriber;
use Sulu\Component\DocumentManager\Behavior\Mapping\ChildrenBehavior;
use Sulu\Component\DocumentManager\DocumentInspector;
+use Sulu\Component\DocumentManager\DocumentManagerInterface;
use Sulu\Component\DocumentManager\Event\PersistEvent;
use Sulu\Component\DocumentManager\Event\PublishEvent;
use Sulu\Component\DocumentManager\Event\RemoveEvent;
+use Sulu\Component\DocumentManager\Event\ReorderEvent;
use Sulu\Component\DocumentManager\Event\RestoreEvent;
use Sulu\Component\DocumentManager\PropertyEncoder;
@@ -34,6 +36,11 @@ class PageSubscriberTest extends \PHPUnit_Framework_TestCase
*/
private $propertyEncoder;
+ /**
+ * @var DocumentManagerInterface
+ */
+ private $documentManager;
+
/**
* @var PageSubscriber
*/
@@ -56,13 +63,13 @@ protected function setUp()
{
$this->documentInspector = $this->prophesize(DocumentInspector::class);
$this->propertyEncoder = $this->prophesize(PropertyEncoder::class);
+ $this->documentManager = $this->prophesize(DocumentManagerInterface::class);
$this->document = $this->prophesize(PageBehavior::class);
$this->node = $this->prophesize(NodeInterface::class);
$this->pageSubscriber = new PageSubscriber(
- $this->documentInspector->reveal(),
- $this->propertyEncoder->reveal()
+ $this->documentInspector->reveal(), $this->propertyEncoder->reveal(), $this->documentManager->reveal()
);
}
@@ -167,4 +174,57 @@ public function testHandleRestore()
$this->pageSubscriber->handleRestore($event->reveal());
}
+
+ public function testHandleReorder()
+ {
+ $parentDocument = $this->prophesize(ChildrenBehavior::class);
+ $this->document->getParent()->willReturn($parentDocument->reveal());
+
+ $nodes = [
+ $this->prophesize(NodeInterface::class),
+ $this->prophesize(NodeInterface::class),
+ $this->prophesize(NodeInterface::class),
+ ];
+
+ $nodes[0]->getIdentifier()->willReturn('1-1-1');
+ $nodes[1]->getIdentifier()->willReturn('1-2-2');
+ $nodes[2]->getIdentifier()->willReturn('1-2-3');
+
+ $parentNode = $this->prophesize(NodeInterface::class);
+ $parentNode->getNodes()->willReturn(
+ array_map(
+ function ($item) {
+ return $item->reveal();
+ },
+ $nodes
+ )
+ );
+
+ $this->documentInspector->getNode($parentDocument->reveal())->willReturn($parentNode->reveal());
+
+ $documents = [
+ $this->prophesize(PageBehavior::class),
+ $this->prophesize(PageBehavior::class),
+ $this->prophesize(PageBehavior::class),
+ ];
+
+ $this->documentManager->find('1-1-1', 'de')->willReturn($documents[0]->reveal());
+ $this->documentManager->find('1-2-2', 'de')->willReturn($documents[1]->reveal());
+ $this->documentManager->find('1-2-3', 'de')->willReturn($documents[2]->reveal());
+
+ $event = $this->prophesize(ReorderEvent::class);
+ $event->getDocument()->willReturn($this->document->reveal());
+ $event->getLocale()->willReturn('de');
+
+ $this->propertyEncoder->systemName(PageSubscriber::FIELD)->willReturn('sulu:' . PageSubscriber::FIELD);
+
+ $documents[0]->setPageNumber(2)->shouldBeCalled();
+ $nodes[0]->setProperty('sulu:' . PageSubscriber::FIELD, 2)->shouldBeCalled();
+ $documents[1]->setPageNumber(3)->shouldBeCalled();
+ $nodes[1]->setProperty('sulu:' . PageSubscriber::FIELD, 3)->shouldBeCalled();
+ $documents[2]->setPageNumber(4)->shouldBeCalled();
+ $nodes[2]->setProperty('sulu:' . PageSubscriber::FIELD, 4)->shouldBeCalled();
+
+ $this->pageSubscriber->handleReorder($event->reveal());
+ }
}
diff --git a/Tests/app/Resources/articles/default.xml b/Tests/app/Resources/articles/default.xml
index 2f5be13b7..27114ddda 100644
--- a/Tests/app/Resources/articles/default.xml
+++ b/Tests/app/Resources/articles/default.xml
@@ -13,5 +13,6 @@
+