Skip to content

Commit

Permalink
Request events
Browse files Browse the repository at this point in the history
  • Loading branch information
alanpoulain committed Mar 2, 2019
1 parent d86f956 commit b7dbb8f
Show file tree
Hide file tree
Showing 39 changed files with 1,014 additions and 255 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"doctrine/inflector": "^1.0",
"psr/cache": "^1.0",
"psr/container": "^1.0",
"symfony/event-dispatcher": "^3.4 || ^4.0",
"symfony/http-foundation": "^3.4 || ^4.0",
"symfony/http-kernel": "^3.4 || ^4.0",
"symfony/property-access": "^3.4 || ^4.0",
Expand Down Expand Up @@ -61,7 +62,6 @@
"symfony/dependency-injection": "^3.4 || ^4.0",
"symfony/doctrine-bridge": "^3.4 || ^4.0",
"symfony/dom-crawler": "^3.4 || ^4.0",
"symfony/event-dispatcher": "^3.4 || ^4.0",
"symfony/expression-language": "^3.4 || ^4.0",
"symfony/finder": "^3.4 || ^4.0",
"symfony/form": "^3.4 || ^4.0",
Expand Down
23 changes: 22 additions & 1 deletion src/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,37 @@

namespace ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener;

use ApiPlatform\Core\Event\EventInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

final class SwaggerUiListener
{
/**
* Sets SwaggerUiAction as controller if the requested format is HTML.
*
* @deprecated since version 2.5, to be removed in 3.0.
*/
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
@trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED);

$this->handleEvent($event);
}

/**
* Sets SwaggerUiAction as controller if the requested format is HTML.
*/
public function handleEvent(/*EventInterface */$event)
{
if ($event instanceof EventInterface) {
$request = $event->getContext()['request'];
} elseif ($event instanceof GetResponseEvent) {
@trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED);

$request = $event->getRequest();
} else {
return;
}
if (
'html' !== $request->getRequestFormat('') ||
(!$request->attributes->has('_api_resource_class') && !$request->attributes->has('_api_respond'))
Expand Down
88 changes: 88 additions & 0 deletions src/Bridge/Symfony/Bundle/EventSubscriber/EventDispatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Core\Bridge\Symfony\Bundle\EventSubscriber;

use ApiPlatform\Core\Event\DeserializeEvent;
use ApiPlatform\Core\Event\FormatAddEvent;
use ApiPlatform\Core\Event\PostDeserializeEvent;
use ApiPlatform\Core\Event\PostReadEvent;
use ApiPlatform\Core\Event\PreDeserializeEvent;
use ApiPlatform\Core\Event\PreReadEvent;
use ApiPlatform\Core\Event\QueryParameterValidateEvent;
use ApiPlatform\Core\Event\ReadEvent;
use ApiPlatform\Core\Events;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
* @internal
*
* @author Alan Poulain <contact@alanpoulain.eu>
*/
final class EventDispatcher implements EventSubscriberInterface
{
private const INTERNAL_EVENTS_CONFIGURATION = [
KernelEvents::REQUEST => [
QueryParameterValidateEvent::class => Events::QUERY_PARAMETER_VALIDATE,
FormatAddEvent::class => Events::FORMAT_ADD,

PreReadEvent::class => Events::PRE_READ,
ReadEvent::class => Events::READ,
PostReadEvent::class => Events::POST_READ,

PreDeserializeEvent::class => Events::PRE_DESERIALIZE,
DeserializeEvent::class => Events::DESERIALIZE,
PostDeserializeEvent::class => Events::POST_DESERIALIZE,
],
];

private $dispatcher;

public function __construct(EventDispatcherInterface $dispatcher)
{
$this->dispatcher = $dispatcher;
}

public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => 'dispatch',
];
}

public function dispatch(Event $event, string $eventName): void
{
$internalEventData = null;
$internalEventContext = [];

switch (true) {
case $event instanceof GetResponseEvent:
$internalEventContext = ['request' => $event->getRequest()];
}

foreach ($this->getInternalEventData($eventName) as $internalEventClass => $internalEventName) {
$internalEvent = new $internalEventClass($internalEventData, $internalEventContext);

$this->dispatcher->dispatch($internalEventName, $internalEvent);
}
}

private function getInternalEventData(string $eventName): \Generator
{
yield from self::INTERNAL_EVENTS_CONFIGURATION[$eventName];
}
}
15 changes: 11 additions & 4 deletions src/Bridge/Symfony/Bundle/Resources/config/api.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,21 @@
<service id="api_platform.path_segment_name_generator.underscore" class="ApiPlatform\Core\Operation\UnderscorePathSegmentNameGenerator" public="false" />
<service id="api_platform.path_segment_name_generator.dash" class="ApiPlatform\Core\Operation\DashPathSegmentNameGenerator" public="false" />

<!-- Event dispatcher -->

<service id="api_platform.dispatcher.internal_events" class="ApiPlatform\Core\Bridge\Symfony\Bundle\EventSubscriber\EventDispatcher">
<argument type="service" id="event_dispatcher" />

<tag name="kernel.event_subscriber" />
</service>

<!-- Event listeners -->

<!-- kernel.request priority must be < 8 to be executed after the Firewall -->
<service id="api_platform.listener.request.add_format" class="ApiPlatform\Core\EventListener\AddFormatListener">
<argument type="service" id="api_platform.negotiator" />
<argument type="service" id="api_platform.formats_provider" />

<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="7" />
<tag name="kernel.event_listener" event="api_platform.format_add" method="handleEvent" />
</service>

<service id="api_platform.listener.request.read" class="ApiPlatform\Core\EventListener\ReadListener">
Expand All @@ -155,7 +162,7 @@
<argument type="service" id="api_platform.serializer.context_builder" />
<argument type="service" id="api_platform.identifier.converter" />

<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="4" />
<tag name="kernel.event_listener" event="api_platform.read" method="handleEvent" />
</service>

<service id="api_platform.listener.view.write" class="ApiPlatform\Core\EventListener\WriteListener">
Expand All @@ -171,7 +178,7 @@
<argument type="service" id="api_platform.serializer.context_builder" />
<argument type="service" id="api_platform.formats_provider" />

<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="2" />
<tag name="kernel.event_listener" event="api_platform.deserialize" method="handleEvent" />
</service>

<service id="api_platform.listener.view.serialize" class="ApiPlatform\Core\EventListener\SerializeListener">
Expand Down
8 changes: 4 additions & 4 deletions src/Bridge/Symfony/Bundle/Resources/config/jsonapi.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,22 @@
<!-- Event listener -->

<service id="api_platform.jsonapi.listener.request.transform_pagination_parameters" class="ApiPlatform\Core\JsonApi\EventListener\TransformPaginationParametersListener">
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="5" />
<tag name="kernel.event_listener" event="api_platform.pre_read" method="handleEvent" />
</service>

<service id="api_platform.jsonapi.listener.request.transform_sorting_parameters" class="ApiPlatform\Core\JsonApi\EventListener\TransformSortingParametersListener">
<argument>%api_platform.collection.order_parameter_name%</argument>
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="5" />
<tag name="kernel.event_listener" event="api_platform.pre_read" method="handleEvent" />
</service>

<service id="api_platform.jsonapi.listener.request.transform_fieldsets_parameters" class="ApiPlatform\Core\JsonApi\EventListener\TransformFieldsetsParametersListener">
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />

<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="5" />
<tag name="kernel.event_listener" event="api_platform.pre_read" method="handleEvent" />
</service>

<service id="api_platform.jsonapi.listener.request.transform_filtering_parameters" class="ApiPlatform\Core\JsonApi\EventListener\TransformFilteringParametersListener">
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="5" />
<tag name="kernel.event_listener" event="api_platform.pre_read" method="handleEvent" />
</service>
</services>

Expand Down
2 changes: 1 addition & 1 deletion src/Bridge/Symfony/Bundle/Resources/config/security.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<argument type="service" id="api_platform.security.resource_access_checker" />

<!-- This listener must be executed only when the current object is available -->
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="1" />
<tag name="kernel.event_listener" event="api_platform.post_deserialize" method="handleEvent" />
</service>

<service id="api_platform.security.expression_language_provider" class="ApiPlatform\Core\Security\Core\Authorization\ExpressionLanguageProvider" public="false">
Expand Down
2 changes: 1 addition & 1 deletion src/Bridge/Symfony/Bundle/Resources/config/swagger-ui.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<services>

<service id="api_platform.swagger.listener.ui" class="ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener\SwaggerUiListener">
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
<tag name="kernel.event_listener" event="api_platform.post_deserialize" method="handleEvent" />
</service>

<service id="api_platform.swagger.action.ui" class="ApiPlatform\Core\Bridge\Symfony\Bundle\Action\SwaggerUiAction" public="true">
Expand Down
2 changes: 1 addition & 1 deletion src/Bridge/Symfony/Bundle/Resources/config/validator.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
<argument type="service" id="api_platform.filter_locator" />

<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="16" />
<tag name="kernel.event_listener" event="api_platform.query_parameter_validate" method="handleEvent" />
</service>
</services>

Expand Down
21 changes: 21 additions & 0 deletions src/Event/DeserializeEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Core\Event;

/**
* @author Alan Poulain <contact@alanpoulain.eu>
*/
final class DeserializeEvent extends Event
{
}
51 changes: 51 additions & 0 deletions src/Event/Event.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Core\Event;

use Symfony\Component\EventDispatcher\Event as BaseEvent;

/**
* @author Alan Poulain <contact@alanpoulain.eu>
*/
abstract class Event extends BaseEvent implements EventInterface
{
private $data;
private $context;

public function __construct($data, array $context = [])
{
$this->data = $data;
$this->context = $context;
}

public function getData()
{
return $this->data;
}

public function setData($data): void
{
$this->data = $data;
}

public function getContext(): array
{
return $this->context;
}

public function setContext(array $context): void
{
$this->context = $context;
}
}
28 changes: 28 additions & 0 deletions src/Event/EventInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Core\Event;

/**
* @author Alan Poulain <contact@alanpoulain.eu>
*/
interface EventInterface
{
public function getData();

public function setData($data): void;

public function getContext(): array;

public function setContext(array $context): void;
}
21 changes: 21 additions & 0 deletions src/Event/FormatAddEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Core\Event;

/**
* @author Alan Poulain <contact@alanpoulain.eu>
*/
final class FormatAddEvent extends Event
{
}
21 changes: 21 additions & 0 deletions src/Event/PostDeserializeEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Core\Event;

/**
* @author Alan Poulain <contact@alanpoulain.eu>
*/
final class PostDeserializeEvent extends Event
{
}
Loading

0 comments on commit b7dbb8f

Please sign in to comment.