diff --git a/Controller/ReorderController.php b/Controller/ReorderController.php
index 5dcd399..a46a211 100644
--- a/Controller/ReorderController.php
+++ b/Controller/ReorderController.php
@@ -12,12 +12,18 @@
namespace FSi\Bundle\AdminTreeBundle\Controller;
use FSi\Bundle\AdminBundle\Admin\CRUD\DataIndexerElement;
-use FSi\Bundle\AdminBundle\Doctrine\Admin\Element;
+use FSi\Bundle\AdminBundle\Admin\Element as AdminElement;
+use FSi\Bundle\AdminBundle\Doctrine\Admin\Element as AdminDoctrineElement;
+use FSi\Bundle\AdminBundle\Event\AdminEvent;
+use FSi\Bundle\AdminTreeBundle\Event\MovedDownTreeEvent;
+use FSi\Bundle\AdminTreeBundle\Event\MovedUpTreeEvent;
use Gedmo\Tree\Entity\Repository\NestedTreeRepository;
use InvalidArgumentException;
+use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
-use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\RouterInterface;
use function get_class;
@@ -30,27 +36,64 @@ class ReorderController
*/
private $router;
- public function __construct(RouterInterface $router)
+ /**
+ * @var EventDispatcherInterface|PsrEventDispatcherInterface
+ */
+ private $eventDispatcher;
+
+ public function __construct(RouterInterface $router, EventDispatcherInterface $eventDispatcher)
{
$this->router = $router;
+ $this->eventDispatcher = $eventDispatcher;
}
+ /**
+ * @param DataIndexerElement&AdminDoctrineElement $element
+ * @param mixed $id
+ * @param Request $request
+ * @return Response
+ */
public function moveUpAction(DataIndexerElement $element, $id, Request $request): Response
{
- $this->getRepository($element)->moveUp($this->getEntity($element, $id));
- $this->flush($element);
+ $entity = $this->getEntity($element, $id);
+
+ $this->getRepository($element)->moveUp($entity);
+ $element->getObjectManager()->flush();
+
+ $this->dispatchEvent(new MovedUpTreeEvent($element, $request, $entity));
return $this->getRedirectResponse($element, $request);
}
+ /**
+ * @param DataIndexerElement&AdminDoctrineElement $element
+ * @param mixed $id
+ * @param Request $request
+ * @return Response
+ */
public function moveDownAction(DataIndexerElement $element, $id, Request $request): Response
{
- $this->getRepository($element)->moveDown($this->getEntity($element, $id));
- $this->flush($element);
+ $entity = $this->getEntity($element, $id);
+
+ $this->getRepository($element)->moveDown($entity);
+ $element->getObjectManager()->flush();
+
+ $this->dispatchEvent(new MovedDownTreeEvent($element, $request, $entity));
return $this->getRedirectResponse($element, $request);
}
+ private function dispatchEvent(AdminEvent $event): void
+ {
+ if (true === interface_exists(PsrEventDispatcherInterface::class)
+ && true === $this->eventDispatcher instanceof PsrEventDispatcherInterface
+ ) {
+ $this->eventDispatcher->dispatch($event);
+ } else {
+ $this->eventDispatcher->dispatch(get_class($event), $event);
+ }
+ }
+
/**
* @param DataIndexerElement $element
* @param mixed $id
@@ -71,7 +114,7 @@ private function getEntity(DataIndexerElement $element, $id)
return $entity;
}
- private function getRepository(Element $element): NestedTreeRepository
+ private function getRepository(AdminDoctrineElement $element): NestedTreeRepository
{
$repository = $element->getRepository();
if (false === $repository instanceof NestedTreeRepository) {
@@ -85,15 +128,11 @@ private function getRepository(Element $element): NestedTreeRepository
return $repository;
}
- private function flush(Element $element): void
- {
- $element->getObjectManager()->flush();
- }
-
- private function getRedirectResponse(DataIndexerElement $element, Request $request): RedirectResponse
+ private function getRedirectResponse(AdminElement $element, Request $request): RedirectResponse
{
- if ($request->query->get('redirect_uri')) {
- $uri = $request->query->get('redirect_uri');
+ $redirectUri = $request->query->get('redirect_uri');
+ if (null !== $redirectUri && '' !== $redirectUri) {
+ $uri = $redirectUri;
} else {
$uri = $this->router->generate($element->getRoute(), $element->getRouteParameters());
}
diff --git a/DependencyInjection/FSiAdminTreeExtension.php b/DependencyInjection/FSiAdminTreeExtension.php
index d9b757d..1bf9bd4 100644
--- a/DependencyInjection/FSiAdminTreeExtension.php
+++ b/DependencyInjection/FSiAdminTreeExtension.php
@@ -18,6 +18,11 @@
final class FSiAdminTreeExtension extends Extension
{
+ /**
+ * @param array $configs
+ * @param ContainerBuilder $container
+ * @return void
+ */
public function load(array $configs, ContainerBuilder $container)
{
$loader = new Loader\XmlFileLoader(
diff --git a/Event/MovedDownTreeEvent.php b/Event/MovedDownTreeEvent.php
new file mode 100644
index 0000000..6c820f9
--- /dev/null
+++ b/Event/MovedDownTreeEvent.php
@@ -0,0 +1,52 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace FSi\Bundle\AdminTreeBundle\Event;
+
+use FSi\Bundle\AdminBundle\Admin\Element;
+use FSi\Bundle\AdminBundle\Event\AdminEvent;
+use InvalidArgumentException;
+use Symfony\Component\HttpFoundation\Request;
+
+final class MovedDownTreeEvent extends AdminEvent
+{
+ /**
+ * @var object
+ */
+ private $entity;
+
+ /**
+ * @param Element $element
+ * @param Request $request
+ * @param mixed $entity
+ * @throws InvalidArgumentException
+ */
+ public function __construct(Element $element, Request $request, $entity)
+ {
+ if (false === is_object($entity)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Expected an object, got "%s" instead',
+ gettype($entity)
+ ));
+ }
+
+ parent::__construct($element, $request);
+ $this->entity = $entity;
+ }
+
+ /**
+ * @return object
+ */
+ public function getEntity()
+ {
+ return $this->entity;
+ }
+}
diff --git a/Event/MovedUpTreeEvent.php b/Event/MovedUpTreeEvent.php
new file mode 100644
index 0000000..172c17e
--- /dev/null
+++ b/Event/MovedUpTreeEvent.php
@@ -0,0 +1,54 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace FSi\Bundle\AdminTreeBundle\Event;
+
+use FSi\Bundle\AdminBundle\Admin\Element;
+use FSi\Bundle\AdminBundle\Event\AdminEvent;
+use InvalidArgumentException;
+use Symfony\Component\HttpFoundation\Request;
+use function gettype;
+use function is_object;
+
+final class MovedUpTreeEvent extends AdminEvent
+{
+ /**
+ * @var object
+ */
+ private $entity;
+
+ /**
+ * @param Element $element
+ * @param Request $request
+ * @param mixed $entity
+ * @throws InvalidArgumentException
+ */
+ public function __construct(Element $element, Request $request, $entity)
+ {
+ if (false === is_object($entity)) {
+ throw new InvalidArgumentException(sprintf(
+ 'Expected an object, got "%s" instead',
+ gettype($entity)
+ ));
+ }
+
+ parent::__construct($element, $request);
+ $this->entity = $entity;
+ }
+
+ /**
+ * @return object
+ */
+ public function getEntity()
+ {
+ return $this->entity;
+ }
+}
diff --git a/Resources/config/services.xml b/Resources/config/services.xml
index e4f3dde..781b444 100644
--- a/Resources/config/services.xml
+++ b/Resources/config/services.xml
@@ -11,6 +11,7 @@
+
diff --git a/Resources/doc/usage.md b/Resources/doc/usage.md
index 1f0b615..83b41ef 100644
--- a/Resources/doc/usage.md
+++ b/Resources/doc/usage.md
@@ -28,3 +28,13 @@ columns:
content:
url_attr: { class: "btn btn-warning btn-sm" }
```
+
+## Events
+
+Since version 2.2, an event of respective class name is fired after moving an
+item up or down the tree:
+
+- FSi\Bundle\AdminTreeBundle\Event\MovedUpTreeEvent
+- FSi\Bundle\AdminTreeBundle\Event\MovedDownTreeEvent
+
+Both contain the object that was being moved.
diff --git a/composer.json b/composer.json
index 9d9f286..2df63a9 100644
--- a/composer.json
+++ b/composer.json
@@ -41,7 +41,8 @@
},
"extra": {
"branch-alias": {
- "dev-master": "2.1-dev",
+ "dev-master": "2.2-dev",
+ "2.1": "2.1-dev",
"2.0": "2.0-dev",
"1.0": "1.0-dev"
}
diff --git a/spec/FSi/Bundle/AdminTreeBundle/Controller/ReorderControllerSpec.php b/spec/FSi/Bundle/AdminTreeBundle/Controller/ReorderControllerSpec.php
index 5aa5808..3f6a0a2 100644
--- a/spec/FSi/Bundle/AdminTreeBundle/Controller/ReorderControllerSpec.php
+++ b/spec/FSi/Bundle/AdminTreeBundle/Controller/ReorderControllerSpec.php
@@ -15,13 +15,17 @@
use Doctrine\ORM\EntityRepository;
use FSi\Bundle\AdminBundle\Doctrine\Admin\CRUDElement;
use FSi\Bundle\AdminTreeBundle\Controller\ReorderController;
+use FSi\Bundle\AdminTreeBundle\Event\MovedDownTreeEvent;
+use FSi\Bundle\AdminTreeBundle\Event\MovedUpTreeEvent;
use FSi\Component\DataIndexer\DoctrineDataIndexer;
use FSi\Component\DataIndexer\Exception\RuntimeException;
use Gedmo\Tree\Entity\Repository\NestedTreeRepository;
use InvalidArgumentException;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
+use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface;
use stdClass;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
@@ -31,6 +35,7 @@ final class ReorderControllerSpec extends ObjectBehavior
{
public function let(
RouterInterface $router,
+ EventDispatcherInterface $eventDispatcher,
CRUDElement $element,
DoctrineDataIndexer $indexer,
ObjectManager $om,
@@ -46,7 +51,7 @@ public function let(
$element->getRoute()->willReturn('fsi_admin_crud_list');
$element->getRouteParameters()->willReturn(['element' => 'category']);
- $this->beConstructedWith($router);
+ $this->beConstructedWith($router, $eventDispatcher);
}
public function it_is_initializable(): void
@@ -61,6 +66,7 @@ public function it_moves_up_item_when_move_up_action_called(
ObjectManager $om,
RouterInterface $router,
DoctrineDataIndexer $indexer,
+ EventDispatcherInterface $eventDispatcher,
Request $request
): void {
$indexer->getData(1)->willReturn($category);
@@ -69,6 +75,15 @@ public function it_moves_up_item_when_move_up_action_called(
$om->flush()->shouldBeCalled();
+ if (true === is_subclass_of(EventDispatcherInterface::class, PsrEventDispatcherInterface::class)) {
+ $eventDispatcher->dispatch(Argument::type(MovedUpTreeEvent::class))->shouldBeCalled();
+ } else {
+ $eventDispatcher->dispatch(
+ 'FSi\Bundle\AdminTreeBundle\Event\MovedUpTreeEvent',
+ Argument::type(MovedUpTreeEvent::class)
+ )->shouldBeCalled();
+ }
+
$router->generate(
'fsi_admin_crud_list',
Argument::withEntry('element', 'category')
@@ -86,6 +101,7 @@ public function it_moves_down_item_when_move_down_action_called(
ObjectManager $om,
RouterInterface $router,
DoctrineDataIndexer $indexer,
+ EventDispatcherInterface $eventDispatcher,
Request $request
): void {
$indexer->getData(1)->willReturn($category);
@@ -94,6 +110,15 @@ public function it_moves_down_item_when_move_down_action_called(
$om->flush()->shouldBeCalled();
+ if (true === is_subclass_of(EventDispatcherInterface::class, PsrEventDispatcherInterface::class)) {
+ $eventDispatcher->dispatch(Argument::type(MovedDownTreeEvent::class))->shouldBeCalled();
+ } else {
+ $eventDispatcher->dispatch(
+ 'FSi\Bundle\AdminTreeBundle\Event\MovedDownTreeEvent',
+ Argument::type(MovedDownTreeEvent::class)
+ )->shouldBeCalled();
+ }
+
$router->generate(
'fsi_admin_crud_list',
Argument::withEntry('element', 'category')
@@ -130,6 +155,7 @@ public function it_throws_exception_when_entity_doesnt_have_correct_repository(
}
public function it_redirects_to_redirect_uri_parameter_after_operation(
+ EventDispatcherInterface $eventDispatcher,
CRUDElement $element,
DoctrineDataIndexer $indexer,
stdClass $category,
@@ -139,10 +165,28 @@ public function it_redirects_to_redirect_uri_parameter_after_operation(
$query->get('redirect_uri')->willReturn('some_redirect_uri');
$indexer->getData(1)->willReturn($category);
+ if (true === is_subclass_of(EventDispatcherInterface::class, PsrEventDispatcherInterface::class)) {
+ $eventDispatcher->dispatch(Argument::type(MovedUpTreeEvent::class))->shouldBeCalled();
+ } else {
+ $eventDispatcher->dispatch(
+ 'FSi\Bundle\AdminTreeBundle\Event\MovedUpTreeEvent',
+ Argument::type(MovedUpTreeEvent::class)
+ )->shouldBeCalled();
+ }
+
$response = $this->moveUpAction($element, 1, $request);
$response->shouldHaveType(RedirectResponse::class);
$response->getTargetUrl()->shouldReturn('some_redirect_uri');
+ if (true === is_subclass_of(EventDispatcherInterface::class, PsrEventDispatcherInterface::class)) {
+ $eventDispatcher->dispatch(Argument::type(MovedDownTreeEvent::class))->shouldBeCalled();
+ } else {
+ $eventDispatcher->dispatch(
+ 'FSi\Bundle\AdminTreeBundle\Event\MovedDownTreeEvent',
+ Argument::type(MovedDownTreeEvent::class)
+ )->shouldBeCalled();
+ }
+
$response = $this->moveDownAction($element, 1, $request);
$response->shouldHaveType(RedirectResponse::class);
$response->getTargetUrl()->shouldReturn('some_redirect_uri');