diff --git a/Form/Processor/ContentTypeFormProcessor.php b/Form/Processor/ContentTypeFormProcessor.php index 34bd9d38a..1516d49d8 100644 --- a/Form/Processor/ContentTypeFormProcessor.php +++ b/Form/Processor/ContentTypeFormProcessor.php @@ -10,6 +10,8 @@ namespace EzSystems\PlatformUIBundle\Form\Processor; use eZ\Publish\API\Repository\Values\ContentType\ContentTypeDraft; +use EzSystems\PlatformUIBundle\Notification\NotificationPoolInterface; +use EzSystems\PlatformUIBundle\Notification\TranslatableNotificationMessage; use EzSystems\RepositoryForms\Event\FormActionEvent; use EzSystems\RepositoryForms\Event\RepositoryFormEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -23,19 +25,31 @@ class ContentTypeFormProcessor implements EventSubscriberInterface */ private $router; - public function __construct(RouterInterface $router) + /** + * @var NotificationPoolInterface + */ + private $notificationPool; + + public function __construct(RouterInterface $router, NotificationPoolInterface $notificationPool) { $this->router = $router; + $this->notificationPool = $notificationPool; } public static function getSubscribedEvents() { return [ + RepositoryFormEvents::CONTENT_TYPE_UPDATE => ['processDefaultAction', -10], RepositoryFormEvents::CONTENT_TYPE_PUBLISH => ['processPublishContentType', -10], RepositoryFormEvents::CONTENT_TYPE_REMOVE_DRAFT => ['processRemoveContentTypeDraft', -10], ]; } + public function processDefaultAction(FormActionEvent $event) + { + $this->addNotification('content_type.notification.draft_updated'); + } + public function processPublishContentType(FormActionEvent $event) { $event->setResponse( @@ -44,7 +58,8 @@ public function processPublishContentType(FormActionEvent $event) $event->getOption('languageCode') ) ); - // TODO: Add confirmation flash message. + + $this->addNotification('content_type.notification.published'); } public function processRemoveContentTypeDraft(FormActionEvent $event) @@ -55,6 +70,8 @@ public function processRemoveContentTypeDraft(FormActionEvent $event) $event->getOption('languageCode') ) ); + + $this->addNotification('content_type.notification.draft_removed'); } private function generateRedirectResponse(ContentTypeDraft $contentTypeDraft, $languageCode) @@ -66,4 +83,12 @@ private function generateRedirectResponse(ContentTypeDraft $contentTypeDraft, $l return new RedirectResponse($url); } + + private function addNotification($message) + { + $this->notificationPool->addNotification(new TranslatableNotificationMessage([ + 'message' => $message, + 'domain' => 'content_type' + ])); + } } diff --git a/Notification/Notification.php b/Notification/Notification.php new file mode 100644 index 000000000..9f220b457 --- /dev/null +++ b/Notification/Notification.php @@ -0,0 +1,42 @@ +translator = $translator; + $this->session = $session; + } + + public static function getSubscribedEvents() + { + return [ + KernelEvents::RESPONSE => 'onKernelResponse', + ]; + } + + public function addNotification(NotificationMessage $message, $state = Notification::STATE_DONE) + { + $translatedMessage = $message instanceof TranslatableNotificationMessage ? $this->translateMessage($message) : $message->message; + $this->notifications[] = new Notification([ + 'message' => $translatedMessage, + 'state' => $state, + ]); + } + + /** + * @return Notification[] + */ + public function getNotifications() + { + return $this->notifications; + } + + private function translateMessage(TranslatableNotificationMessage $message) + { + if ($message->number !== null) { + return $this->translator->transChoice( + $message->message, + (int)$message->number, + $message->translationParams, + $message->domain + ); + } + + return $this->translator->trans($message->message, $message->translationParams, $message->domain); + } + + public function onKernelResponse(FilterResponseEvent $event) + { + $this->session->getFlashBag()->set('notification', $this->notifications); + } +} diff --git a/Notification/NotificationPoolInterface.php b/Notification/NotificationPoolInterface.php new file mode 100644 index 000000000..1ad618051 --- /dev/null +++ b/Notification/NotificationPoolInterface.php @@ -0,0 +1,21 @@ +content_type.default_children_sorting Default children sorting + + content_type.notification.draft_updated + The ContentType draft was successfully updated. + + + content_type.notification.draft_removed + The ContentType draft was successfully removed. + + + content_type.notification.published + The ContentType draft was successfully updated and published. Related Content has also been updated. + diff --git a/Resources/views/pjax_admin.html.twig b/Resources/views/pjax_admin.html.twig index c05713259..ea143df47 100644 --- a/Resources/views/pjax_admin.html.twig +++ b/Resources/views/pjax_admin.html.twig @@ -25,3 +25,13 @@ {% block content %}{% endblock %} + +{% block notification %} + +{% endblock %} diff --git a/Tests/Notification/NotificationPoolTest.php b/Tests/Notification/NotificationPoolTest.php new file mode 100644 index 000000000..cbfe87301 --- /dev/null +++ b/Tests/Notification/NotificationPoolTest.php @@ -0,0 +1,189 @@ +translator = $this->getMock('\Symfony\Component\Translation\TranslatorInterface'); + $this->session = $this->getMock('\Symfony\Component\HttpFoundation\Session\Session'); + + $this->pool = new NotificationPool($this->translator, $this->session); + } + + public function testGetSubscribedEvents() + { + self::assertSame( + [KernelEvents::RESPONSE => 'onKernelResponse'], + NotificationPool::getSubscribedEvents() + ); + } + + public function testAddNotificationsWithoutTranslation() + { + $message1 = 'foo1'; + $state1 = Notification::STATE_DONE; + $this->pool->addNotification(new NotificationMessage(['message' => $message1]), $state1); + + $message2 = 'foo2'; + $state2 = Notification::STATE_ERROR; + $this->pool->addNotification(new NotificationMessage(['message' => $message2]), $state2); + + $message3 = 'foo3'; + $state3 = Notification::STATE_STARTED; + $this->pool->addNotification(new NotificationMessage(['message' => $message3]), $state3); + + $message4 = 'foo4'; + $state4 = 'some_random_state'; + $this->pool->addNotification(new NotificationMessage(['message' => $message4]), $state4); + + $expected = [ + new Notification(['message' => $message1, 'state' => $state1]), + new Notification(['message' => $message2, 'state' => $state2]), + new Notification(['message' => $message3, 'state' => $state3]), + new Notification(['message' => $message4, 'state' => $state4]), + ]; + self::assertEquals($expected, $this->pool->getNotifications()); + } + + public function testAddNotificationSimpleTranslation() + { + $message = 'foo'; + $params = ['some' => 'thing']; + $domain = 'my_domain'; + $state = Notification::STATE_ERROR; + $translation = 'bar'; + + $this->translator + ->expects($this->never()) + ->method('transChoice'); + $this->translator + ->expects($this->once()) + ->method('trans') + ->with($message, $params, $domain) + ->willReturn($translation); + $this->pool->addNotification( + new TranslatableNotificationMessage([ + 'message' => $message, + 'translationParams' => $params, + 'domain' => $domain + ]), + $state + ); + + $expected = [new Notification(['message' => $translation, 'state' => $state])]; + self::assertEquals($expected, $this->pool->getNotifications()); + } + + public function testAddNotificationTransChoice() + { + $message = 'foo'; + $params = ['some' => 'thing']; + $domain = 'my_domain'; + $number = 4; + $state = Notification::STATE_ERROR; + $translation = 'bar'; + + $this->translator + ->expects($this->never()) + ->method('trans'); + $this->translator + ->expects($this->once()) + ->method('transChoice') + ->with($message, $number, $params, $domain) + ->willReturn($translation); + $this->pool->addNotification( + new TranslatableNotificationMessage([ + 'message' => $message, + 'translationParams' => $params, + 'domain' => $domain, + 'number' => $number, + ]), + $state + ); + + $expected = [new Notification(['message' => $translation, 'state' => $state])]; + self::assertEquals($expected, $this->pool->getNotifications()); + } + + public function testOnKernelResponse() + { + $flashBag = $this->getMock('\Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface'); + $this->session + ->expects($this->once()) + ->method('getFlashBag') + ->willReturn($flashBag); + + $message1 = 'foo1'; + $state1 = Notification::STATE_DONE; + $this->pool->addNotification(new NotificationMessage(['message' => $message1]), $state1); + + $message2 = 'foo2'; + $state2 = Notification::STATE_ERROR; + $this->pool->addNotification(new NotificationMessage(['message' => $message2]), $state2); + + $message3 = 'foo3'; + $state3 = Notification::STATE_STARTED; + $this->pool->addNotification(new NotificationMessage(['message' => $message3]), $state3); + + $message4 = 'foo4'; + $state4 = 'some_random_state'; + $this->pool->addNotification(new NotificationMessage(['message' => $message4]), $state4); + + $notifications = [ + new Notification(['message' => $message1, 'state' => $state1]), + new Notification(['message' => $message2, 'state' => $state2]), + new Notification(['message' => $message3, 'state' => $state3]), + new Notification(['message' => $message4, 'state' => $state4]), + ]; + + $flashBag + ->expects($this->once()) + ->method('set') + ->with('notification', $notifications); + + $this->pool->onKernelResponse( + new FilterResponseEvent( + $this->getMock('\Symfony\Component\HttpKernel\HttpKernelInterface'), + new Request(), + HttpKernelInterface::MASTER_REQUEST, + new Response() + ) + ); + } +}