diff --git a/config/forms/event_details.xml b/config/forms/event_details.xml
index 40d88648..87ad09f9 100644
--- a/config/forms/event_details.xml
+++ b/config/forms/event_details.xml
@@ -14,6 +14,14 @@
+
+
+
+
+
+
+ sulu_admin.url
+
diff --git a/config/packages/app_event_admin.yaml b/config/packages/app_event_admin.yaml
index 3e0a60c1..63311681 100644
--- a/config/packages/app_event_admin.yaml
+++ b/config/packages/app_event_admin.yaml
@@ -4,3 +4,11 @@ sulu_admin:
routes:
list: 'app.get_events'
detail: 'app.get_event'
+
+sulu_route:
+ mappings:
+ App\Entity\Event:
+ generator: schema
+ options:
+ route_schema: /events/{implode("-", object)}
+ resource_key: events
diff --git a/config/services.yaml b/config/services.yaml
index bd73083f..9d831d35 100644
--- a/config/services.yaml
+++ b/config/services.yaml
@@ -13,6 +13,7 @@ services:
Sulu\Bundle\SnippetBundle\Snippet\DefaultSnippetManagerInterface: '@sulu_snippet.default_snippet.manager'
Sulu\Component\PHPCR\PathCleanupInterface: '@sulu.content.path_cleaner'
Doctrine\ORM\EntityManagerInterface: '@doctrine.orm.entity_manager'
+ Sulu\Bundle\RouteBundle\Entity\RouteRepositoryInterface: '@sulu.repository.route'
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
@@ -47,3 +48,6 @@ services:
App\Content\Type\AlbumSelection:
tags: [{name: 'sulu.content.type', alias: 'album_selection'}]
+
+ App\Routing\EventRouteDefaultsProvider:
+ tags: [{ name: 'sulu_route.defaults_provider' }]
diff --git a/src/Controller/Admin/EventController.php b/src/Controller/Admin/EventController.php
index 4a596a9b..4f1d8935 100644
--- a/src/Controller/Admin/EventController.php
+++ b/src/Controller/Admin/EventController.php
@@ -10,8 +10,11 @@
use FOS\RestBundle\View\ViewHandlerInterface;
use HandcraftedInTheAlps\RestRoutingBundle\Controller\Annotations\RouteResource;
use HandcraftedInTheAlps\RestRoutingBundle\Routing\ClassResourceInterface;
+use Sulu\Bundle\RouteBundle\Entity\RouteRepositoryInterface;
+use Sulu\Bundle\RouteBundle\Manager\RouteManagerInterface;
use Sulu\Component\Rest\AbstractRestController;
use Sulu\Component\Security\SecuredControllerInterface;
+use Sulu\Component\Webspace\Manager\WebspaceManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -24,15 +27,24 @@ class EventController extends AbstractRestController implements ClassResourceInt
{
private DoctrineListRepresentationFactory $doctrineListRepresentationFactory;
private EntityManagerInterface $entityManager;
+ private WebspaceManagerInterface $webspaceManager;
+ private RouteManagerInterface $routeManager;
+ private RouteRepositoryInterface $routeRepository;
public function __construct(
DoctrineListRepresentationFactory $doctrineListRepresentationFactory,
EntityManagerInterface $entityManager,
+ WebspaceManagerInterface $webspaceManager,
+ RouteManagerInterface $routeManager,
+ RouteRepositoryInterface $routeRepository,
ViewHandlerInterface $viewHandler,
?TokenStorageInterface $tokenStorage = null
) {
$this->doctrineListRepresentationFactory = $doctrineListRepresentationFactory;
$this->entityManager = $entityManager;
+ $this->webspaceManager = $webspaceManager;
+ $this->routeManager = $routeManager;
+ $this->routeRepository = $routeRepository;
parent::__construct($viewHandler, $tokenStorage);
}
@@ -64,6 +76,7 @@ public function putAction(Request $request, int $id): Response
}
$this->mapDataToEntity($request->request->all(), $event);
+ $this->updateRoutesForEntity($event);
$this->entityManager->flush();
return $this->handleView($this->view($event));
@@ -77,13 +90,17 @@ public function postAction(Request $request): Response
$this->entityManager->persist($event);
$this->entityManager->flush();
+ $this->updateRoutesForEntity($event);
+ $this->entityManager->flush();
+
return $this->handleView($this->view($event, 201));
}
- public function deleteAction(int $id): Response
+ public function deleteAction(Request $request, int $id): Response
{
/** @var Event $event */
$event = $this->entityManager->getReference(Event::class, $id);
+ $this->removeRoutesForEntity($event);
$this->entityManager->remove($event);
$this->entityManager->flush();
@@ -96,10 +113,40 @@ public function deleteAction(int $id): Response
protected function mapDataToEntity(array $data, Event $entity): void
{
$entity->setName($data['name']);
+ $entity->setRoutePath($data['routePath']);
$entity->setStartDate($data['startDate'] ? new \DateTimeImmutable($data['startDate']) : null);
$entity->setEndDate($data['endDate'] ? new \DateTimeImmutable($data['endDate']) : null);
}
+ protected function updateRoutesForEntity(Event $entity): void
+ {
+ // create route for all locales of the application because event entity is not localized
+ foreach ($this->webspaceManager->getAllLocales() as $locale) {
+ $this->routeManager->createOrUpdateByAttributes(
+ Event::class,
+ (string) $entity->getId(),
+ $locale,
+ $entity->getRoutePath(),
+ );
+ }
+ }
+
+ protected function removeRoutesForEntity(Event $entity): void
+ {
+ // remove route for all locales of the application because event entity is not localized
+ foreach ($this->webspaceManager->getAllLocales() as $locale) {
+ $routes = $this->routeRepository->findAllByEntity(
+ Event::class,
+ (string) $entity->getId(),
+ $locale
+ );
+
+ foreach ($routes as $route) {
+ $this->routeRepository->remove($route);
+ }
+ }
+ }
+
public function getSecurityContext(): string
{
return Event::SECURITY_CONTEXT;
diff --git a/src/Controller/Website/EventController.php b/src/Controller/Website/EventController.php
new file mode 100644
index 00000000..1c87efda
--- /dev/null
+++ b/src/Controller/Website/EventController.php
@@ -0,0 +1,60 @@
+get('sulu_website.resolver.template_attribute')->resolve([
+ 'event' => $event,
+ 'localizations' => $this->getLocalizationsArrayForEntity($event),
+ ]);
+
+ return $this->render('events/event.html.twig', $parameters);
+ }
+
+ /**
+ * @return array
+ */
+ protected function getLocalizationsArrayForEntity(Event $entity): array
+ {
+ $routes = $this->get('sulu.repository.route')->findAllByEntity(Event::class, (string) $entity->getId());
+
+ $localizations = [];
+ foreach ($routes as $route) {
+ $url = $this->get('sulu_core.webspace.webspace_manager')->findUrlByResourceLocator(
+ $route->getPath(),
+ null,
+ $route->getLocale()
+ );
+
+ $localizations[$route->getLocale()] = ['locale' => $route->getLocale(), 'url' => $url];
+ }
+
+ return $localizations;
+ }
+
+ /**
+ * @return string[]
+ */
+ public static function getSubscribedServices()
+ {
+ $subscribedServices = parent::getSubscribedServices();
+
+ $subscribedServices['sulu_core.webspace.webspace_manager'] = WebspaceManagerInterface::class;
+ $subscribedServices['sulu.repository.route'] = RouteRepositoryInterface::class;
+ $subscribedServices['sulu_website.resolver.template_attribute'] = TemplateAttributeResolverInterface::class;
+
+ return $subscribedServices;
+ }
+}
diff --git a/src/Entity/Event.php b/src/Entity/Event.php
index 459ed141..a1e8a01d 100644
--- a/src/Entity/Event.php
+++ b/src/Entity/Event.php
@@ -33,6 +33,13 @@ class Event
*/
private string $name;
+ /**
+ * @ORM\Column(type="string", length=255)
+ *
+ * @Serializer\Expose()
+ */
+ private string $routePath;
+
/**
* @ORM\Column(type="datetime_immutable", nullable=true)
*
@@ -62,6 +69,16 @@ public function setName(string $name): void
$this->name = $name;
}
+ public function getRoutePath(): string
+ {
+ return $this->routePath ?? '';
+ }
+
+ public function setRoutePath(string $routePath): void
+ {
+ $this->routePath = $routePath;
+ }
+
public function getStartDate(): ?\DateTimeImmutable
{
return $this->startDate;
diff --git a/src/Routing/EventRouteDefaultsProvider.php b/src/Routing/EventRouteDefaultsProvider.php
new file mode 100644
index 00000000..0fc06c6e
--- /dev/null
+++ b/src/Routing/EventRouteDefaultsProvider.php
@@ -0,0 +1,40 @@
+entityManager = $entityManager;
+ }
+
+ /**
+ * @return mixed[]
+ */
+ public function getByEntity($entityClass, $id, $locale, $object = null)
+ {
+ return [
+ '_controller' => EventController::class . '::indexAction',
+ 'event' => $object ?: $this->entityManager->getRepository(Event::class)->find($id),
+ ];
+ }
+
+ public function isPublished($entityClass, $id, $locale)
+ {
+ return true;
+ }
+
+ public function supports($entityClass)
+ {
+ return Event::class === $entityClass;
+ }
+}
diff --git a/templates/events/event.html.twig b/templates/events/event.html.twig
new file mode 100644
index 00000000..429821b0
--- /dev/null
+++ b/templates/events/event.html.twig
@@ -0,0 +1,5 @@
+{% extends 'base.html.twig' %}
+
+{% block contentBody %}
+ {{ event.name }}
+{% endblock %}