Skip to content

Commit

Permalink
feat: Added new ExplorerEntityListEvent dispatched on all AjaxExplo…
Browse files Browse the repository at this point in the history
…rer controllers when they use EntityListManager to allow overriding
  • Loading branch information
ambroisemaupate committed Jan 16, 2025
1 parent f7bac41 commit d475cb6
Show file tree
Hide file tree
Showing 13 changed files with 256 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace RZ\Roadiz\CoreBundle\Explorer\Event;

use RZ\Roadiz\Core\AbstractEntities\PersistableInterface;
use Symfony\Contracts\EventDispatcher\Event;

class ExplorerEntityListEvent extends Event
{
/**
* @param class-string<PersistableInterface> $entityName
*/
public function __construct(
private string $entityName,
private array $criteria = [],
private array $ordering = [],
) {
}

/**
* @return class-string<PersistableInterface>
*/
public function getEntityName(): string
{
return $this->entityName;
}

/**
* @param class-string<PersistableInterface> $entityName
*/
public function setEntityName(string $entityName): ExplorerEntityListEvent
{
$this->entityName = $entityName;

return $this;
}

public function getCriteria(): array
{
return $this->criteria;
}

public function setCriteria(array $criteria): ExplorerEntityListEvent
{
$this->criteria = $criteria;

return $this;
}

public function getOrdering(): array
{
return $this->ordering;
}

public function setOrdering(array $ordering): ExplorerEntityListEvent
{
$this->ordering = $ordering;

return $this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace RZ\Roadiz\CoreBundle\Explorer\EventSubscriber;

use RZ\Roadiz\CoreBundle\Entity\Node;
use RZ\Roadiz\CoreBundle\Entity\NodeType;
use RZ\Roadiz\CoreBundle\Explorer\Event\ExplorerEntityListEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

final class NodeExplorerEntityListEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
ExplorerEntityListEvent::class => ['onNodeExplorerEntityList', 100],
];
}

public function onNodeExplorerEntityList(ExplorerEntityListEvent $event): void
{
$entity = $event->getEntityName();

if (Node::class !== $entity) {
return;
}

$criteria = $event->getCriteria();
$ordering = $event->getOrdering();

if (
!isset($criteria['nodeType'])
|| 1 !== count($criteria['nodeType'])
|| !$criteria['nodeType'][0] instanceof NodeType
) {
return;
}

$event->setEntityName($criteria['nodeType'][0]->getSourceEntityFullQualifiedClassName());
unset($criteria['nodeType']);
$nodeFields = ['position', 'visible', 'locked', 'status', 'nodeName', 'createdAt', 'updatedAt'];

// Prefix all criteria array keys names with "node." and recompose criteria array
$event->setCriteria(array_combine(
array_map(function ($key) use ($nodeFields) {
if (in_array($key, $nodeFields)) {
return 'node.'.$key;
}

return $key;
}, array_keys($criteria)),
array_values($criteria)
));
$event->setOrdering(array_combine(
array_map(function ($key) use ($nodeFields) {
if (in_array($key, $nodeFields)) {
return 'node.'.$key;
}

return $key;
}, array_keys($ordering)),
array_values($ordering)
));
}
}
29 changes: 29 additions & 0 deletions lib/Rozier/src/AjaxControllers/AbstractAjaxExplorerController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Themes\Rozier\AjaxControllers;

use RZ\Roadiz\CoreBundle\Explorer\Event\ExplorerEntityListEvent;
use RZ\Roadiz\CoreBundle\Explorer\ExplorerItemFactoryInterface;
use RZ\Roadiz\CoreBundle\ListManager\EntityListManagerInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

abstract class AbstractAjaxExplorerController extends AbstractAjaxController
{
public function __construct(
protected readonly ExplorerItemFactoryInterface $explorerItemFactory,
protected readonly EventDispatcherInterface $eventDispatcher,
SerializerInterface $serializer,
) {
parent::__construct($serializer);
}

public function createEntityListManager(string $entity, array $criteria = [], array $ordering = []): EntityListManagerInterface
{
$event = $this->eventDispatcher->dispatch(new ExplorerEntityListEvent($entity, $criteria, $ordering));

return parent::createEntityListManager($event->getEntityName(), $event->getCriteria(), $event->getOrdering());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,14 @@
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Exception\NotSupported;
use RZ\Roadiz\CoreBundle\Entity\CustomForm;
use RZ\Roadiz\CoreBundle\Explorer\ExplorerItemFactoryInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Exception\InvalidParameterException;
use Symfony\Component\Serializer\SerializerInterface;

final class AjaxCustomFormsExplorerController extends AbstractAjaxController
final class AjaxCustomFormsExplorerController extends AbstractAjaxExplorerController
{
public function __construct(
private readonly ExplorerItemFactoryInterface $explorerItemFactory,
SerializerInterface $serializer,
) {
parent::__construct($serializer);
}

/**
* @return Response JSON response
*/
public function indexAction(Request $request): Response
public function indexAction(Request $request): JsonResponse
{
$this->denyAccessUnlessGranted('ROLE_ACCESS_CUSTOMFORMS');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,12 @@

use RZ\Roadiz\CoreBundle\Entity\Document;
use RZ\Roadiz\CoreBundle\Entity\Folder;
use RZ\Roadiz\CoreBundle\Explorer\ExplorerItemFactoryInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\InvalidParameterException;
use Symfony\Component\Serializer\SerializerInterface;

final class AjaxDocumentsExplorerController extends AbstractAjaxController
final class AjaxDocumentsExplorerController extends AbstractAjaxExplorerController
{
public function __construct(
private readonly ExplorerItemFactoryInterface $explorerItemFactory,
SerializerInterface $serializer,
) {
parent::__construct($serializer);
}

public function indexAction(Request $request): JsonResponse
{
$this->denyAccessUnlessGranted('ROLE_ACCESS_DOCUMENTS');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,14 @@
use RZ\Roadiz\Core\AbstractEntities\PersistableInterface;
use RZ\Roadiz\CoreBundle\Configuration\JoinNodeTypeFieldConfiguration;
use RZ\Roadiz\CoreBundle\Entity\NodeTypeField;
use RZ\Roadiz\CoreBundle\Explorer\ExplorerItemFactoryInterface;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Yaml\Yaml;

final class AjaxEntitiesExplorerController extends AbstractAjaxController
final class AjaxEntitiesExplorerController extends AbstractAjaxExplorerController
{
public function __construct(
private readonly ExplorerItemFactoryInterface $explorerItemFactory,
SerializerInterface $serializer,
) {
parent::__construct($serializer);
}

protected function getFieldConfiguration(NodeTypeField $nodeTypeField): array
{
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

/**
* Only used to display folders list in document explorer filtering aside.
*/
final class AjaxFoldersExplorerController extends AbstractAjaxController
{
public function indexAction(Request $request): JsonResponse
Expand Down
30 changes: 14 additions & 16 deletions lib/Rozier/src/AjaxControllers/AjaxNodesExplorerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Exception\NotSupported;
use RZ\Roadiz\CoreBundle\Bag\NodeTypes;
use RZ\Roadiz\CoreBundle\Entity\Node;
use RZ\Roadiz\CoreBundle\Entity\NodesSources;
use RZ\Roadiz\CoreBundle\Entity\NodeType;
use RZ\Roadiz\CoreBundle\Entity\Tag;
use RZ\Roadiz\CoreBundle\EntityApi\NodeTypeApi;
use RZ\Roadiz\CoreBundle\Enum\NodeStatus;
use RZ\Roadiz\CoreBundle\Explorer\AbstractExplorerItem;
use RZ\Roadiz\CoreBundle\Explorer\ExplorerItemFactoryInterface;
Expand All @@ -19,20 +20,21 @@
use RZ\Roadiz\CoreBundle\Security\Authorization\Voter\NodeVoter;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Exception\InvalidParameterException;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

final class AjaxNodesExplorerController extends AbstractAjaxController
final class AjaxNodesExplorerController extends AbstractAjaxExplorerController
{
public function __construct(
private readonly ExplorerItemFactoryInterface $explorerItemFactory,
private readonly ClientRegistry $clientRegistry,
private readonly NodeSourceSearchHandlerInterface $nodeSourceSearchHandler,
private readonly NodeTypeApi $nodeTypeApi,
private readonly NodeTypes $nodeTypesBag,
ExplorerItemFactoryInterface $explorerItemFactory,
EventDispatcherInterface $eventDispatcher,
SerializerInterface $serializer,
) {
parent::__construct($serializer);
parent::__construct($explorerItemFactory, $eventDispatcher, $serializer);
}

protected function getItemPerPage(): int
Expand All @@ -45,10 +47,7 @@ protected function isSearchEngineAvailable(Request $request): bool
return '' !== $request->get('search') && null !== $this->clientRegistry->getClient();
}

/**
* @return Response JSON response
*/
public function indexAction(Request $request): Response
public function indexAction(Request $request): JsonResponse
{
// Only requires Search permission for nodes
$this->denyAccessUnlessGranted(NodeVoter::SEARCH);
Expand Down Expand Up @@ -87,13 +86,12 @@ protected function parseFilterFromRequest(Request $request): array
}

if ($request->query->has('nodeTypes') && count($request->get('nodeTypes')) > 0) {
$nodeTypeNames = array_map('trim', $request->get('nodeTypes'));

$nodeTypes = $this->nodeTypeApi->getBy([
'name' => $nodeTypeNames,
]);
/** @var NodeType[] $nodeTypes */
$nodeTypes = array_filter(array_map(function ($nodeTypeName) {
return $this->nodeTypesBag->get(trim($nodeTypeName));
}, $request->get('nodeTypes')));

if (null !== $nodeTypes && count($nodeTypes) > 0) {
if (count($nodeTypes) > 0) {
$arrayFilter['nodeType'] = $nodeTypes;
}
}
Expand Down
1 change: 0 additions & 1 deletion lib/Rozier/src/Resources/app/api/FolderExplorerApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export function getFolders() {
}
})
.catch((error) => {
// TODO
// Log request error or display a message
throw new Error(error)
})
Expand Down
53 changes: 53 additions & 0 deletions src/GeneratedEntity/NSArticle.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,24 @@ class NSArticle extends NodesSources
#[JMS\Type('string')]
private ?string $onlyOnWebresponse = null;

/**
* relatedArticleSources NodesSources direct field buffer.
* @var \App\GeneratedEntity\NSArticle[]|null
* Related article.
* Default values:
* Article
*/
#[JMS\Exclude]
#[Serializer\SerializedName(serializedName: 'relatedArticle')]
#[Serializer\Groups(['nodes_sources', 'nodes_sources_default', 'nodes_sources_nodes'])]
#[ApiProperty(description: 'Related article')]
#[Serializer\MaxDepth(2)]
#[Serializer\Context(
normalizationContext: ['groups' => ['related_articles']],
groups: ['nodes_sources', 'nodes_sources_default', 'nodes_sources_nodes'],
)]
private ?array $relatedArticleSources = null;

/**
* @return string|null
*/
Expand Down Expand Up @@ -189,6 +207,41 @@ public function setOnlyOnWebresponse(?string $onlyOnWebresponse): static
return $this;
}

/**
* @return \App\GeneratedEntity\NSArticle[]
*/
#[JMS\Groups(['nodes_sources', 'nodes_sources_default', 'nodes_sources_nodes'])]
#[JMS\MaxDepth(2)]
#[JMS\VirtualProperty]
#[JMS\SerializedName('relatedArticle')]
#[JMS\Type('array<RZ\Roadiz\CoreBundle\Entity\NodesSources>')]
public function getRelatedArticleSources(): array
{
if (null === $this->relatedArticleSources) {
if (null !== $this->objectManager) {
$this->relatedArticleSources = $this->objectManager
->getRepository(\App\GeneratedEntity\NSArticle::class)
->findByNodesSourcesAndFieldNameAndTranslation(
$this,
'related_article'
);
} else {
$this->relatedArticleSources = [];
}
}
return $this->relatedArticleSources;
}

/**
* @param \App\GeneratedEntity\NSArticle[]|null $relatedArticleSources
* @return $this
*/
public function setRelatedArticleSources(?array $relatedArticleSources): static
{
$this->relatedArticleSources = $relatedArticleSources;
return $this;
}

#[JMS\VirtualProperty]
#[JMS\Groups(['nodes_sources', 'nodes_sources_default'])]
#[JMS\SerializedName('@type')]
Expand Down
Loading

0 comments on commit d475cb6

Please sign in to comment.