Skip to content

Commit

Permalink
feature: add a KNP menu bridge to handle menu management
Browse files Browse the repository at this point in the history
  • Loading branch information
johnkrovitch committed Aug 8, 2024
1 parent eee9201 commit 34dc842
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 150 deletions.
2 changes: 1 addition & 1 deletion src/Bridge/KnpMenu/Builder/AbstractMenuBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use LAG\AdminBundle\Event\Events\MenuEvent;
use LAG\AdminBundle\Event\MenuEvent;
use LAG\AdminBundle\Event\MenuEvents;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

Expand Down
97 changes: 0 additions & 97 deletions src/Bridge/KnpMenu/Builder/ContextualMenuBuilder.php

This file was deleted.

34 changes: 34 additions & 0 deletions src/Bridge/KnpMenu/Builder/EventChainProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace LAG\AdminBundle\Bridge\KnpMenu\Builder;

use Knp\Menu\ItemInterface;
use Knp\Menu\Provider\MenuProviderInterface;
use LAG\AdminBundle\Event\MenuEvent;
use LAG\AdminBundle\Event\MenuEvents;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

final readonly class EventChainProvider implements MenuProviderInterface
{
public function __construct(
private MenuProviderInterface $decorated,
private EventDispatcherInterface $eventDispatcher,
) {
}

public function get(string $name, array $options = []): ItemInterface
{
$menu = $this->decorated->get($name, $options);
$event = new MenuEvent($menu);

$this->eventDispatcher->dispatch($event, MenuEvents::MENU_CREATE);
$this->eventDispatcher->dispatch($event, sprintf(MenuEvents::PRE_EVENT_PATTERN, $name));

return $menu;
}

public function has(string $name, array $options = []): bool
{
return $this->decorated->has($name, $options);
}
}
32 changes: 0 additions & 32 deletions src/Bridge/KnpMenu/Builder/UserMenuBuilder.php

This file was deleted.

47 changes: 47 additions & 0 deletions src/Bridge/KnpMenu/Extension/ResourceExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace LAG\AdminBundle\Bridge\KnpMenu\Extension;

use Knp\Menu\Factory\ExtensionInterface;
use Knp\Menu\ItemInterface;
use LAG\AdminBundle\Resource\Registry\ResourceRegistryInterface;
use LAG\AdminBundle\Routing\UrlGenerator\UrlGeneratorInterface;

final readonly class ResourceExtension implements ExtensionInterface
{
public function __construct(
private ResourceRegistryInterface $registry,
private UrlGeneratorInterface $urlGenerator,
) {
}

public function buildOptions(array $options): array
{
if (!isset($options['resource']) || !isset($options['operation'])) {
return $options;
}

if (!$this->registry->has($options['resource'], $options['application'] ?? null)) {
return $options;
}
$resource = $this->registry->get($options['resource'], $options['application'] ?? null);


if (!$resource->hasOperation($options['operation'])) {
return $options;
}
$operation = $resource->getOperation($options['operation']);
$options['uri'] = $this->urlGenerator->generateOperationUrl($operation);
$options['extras'] = [];

if (empty($options['label'])) {
$options['label'] = $operation->getTitle();
}

return $options;
}

public function buildItem(ItemInterface $item, array $options): void
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,33 @@

declare(strict_types=1);

namespace LAG\AdminBundle\Bridge\KnpMenu\Builder;
namespace LAG\AdminBundle\Menu\Builder;

use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use LAG\AdminBundle\Metadata\GetCollection;
use LAG\AdminBundle\Metadata\Registry\ResourceRegistryInterface;
use LAG\AdminBundle\Resource\Metadata\Index;
use LAG\AdminBundle\Resource\Registry\ResourceRegistryInterface;
use LAG\AdminBundle\Routing\Route\RouteNameGeneratorInterface;
use Symfony\Component\String\Inflector\EnglishInflector;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

use function Symfony\Component\String\u;

class ResourceMenuBuilder extends AbstractMenuBuilder
class ResourceMenuBuilder
{
public function __construct(
private ResourceRegistryInterface $resourceRegistry,
private RouteNameGeneratorInterface $routeNameGenerator,
FactoryInterface $factory,
EventDispatcherInterface $eventDispatcher,
private FactoryInterface $factory,
) {
parent::__construct($factory, $eventDispatcher);
}

public function getName(): string
{
return 'resource';
}

protected function buildMenu(ItemInterface $menu): void
public function build(array $options = []): ItemInterface
{
$menu = $this->factory->createItem('root', $options);
$inflector = new EnglishInflector();

if ($menu->hasChildren()) {
return;
}

foreach ($this->resourceRegistry->all() as $resource) {
foreach ($resource->getOperations() as $operation) {
if (!$operation instanceof GetCollection) {
if (!$operation instanceof Index) {
continue;
}
$label = $inflector->pluralize(u($resource->getName())->snake()->toString())[0];
Expand All @@ -52,5 +40,7 @@ protected function buildMenu(ItemInterface $menu): void
;
}
}

return $menu;
}
}
47 changes: 47 additions & 0 deletions tests/phpunit/Bridge/KnpMenu/Builder/ContextualMenuBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace LAG\AdminBundle\Tests\Bridge\KnpMenu\Builder;

use Knp\Menu\FactoryInterface;
use LAG\AdminBundle\Menu\Builder\ContextualMenuBuilder;
use LAG\AdminBundle\Resource\Context\ResourceContextInterface;
use LAG\AdminBundle\Resource\Registry\ResourceRegistryInterface;
use LAG\AdminBundle\Routing\Route\RouteNameGeneratorInterface;
use LAG\AdminBundle\Tests\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

class ContextualMenuBuilderTest extends TestCase
{
private ContextualMenuBuilder $builder;
private MockObject $resourceContext;
private MockObject $registry;
private MockObject $requestStack;
private MockObject $routeNameGenerator;
private MockObject $factory;
private MockObject $eventDispatcher;

public function testBuildNonResourceMenu(): void
{
$this->builder->build();
}

protected function setUp(): void
{
$this->resourceContext = $this->createMock(ResourceContextInterface::class);
$this->registry = $this->createMock(ResourceRegistryInterface::class);
$this->requestStack = $this->createMock(RequestStack::class);
$this->routeNameGenerator = $this->createMock(RouteNameGeneratorInterface::class);
$this->factory = $this->createMock(FactoryInterface::class);
$this->eventDispatcher = $this->createMock(EventDispatcherInterface::class);
$this->builder = new ContextualMenuBuilder(
$this->resourceContext,
$this->registry,
$this->requestStack,
$this->routeNameGenerator,
$this->factory,
$this->eventDispatcher,
);
}
}

0 comments on commit 34dc842

Please sign in to comment.