<?php
namespace Can\RestBundle\EventListener;
use Can\RestBundle\CanRestBundle;
use Can\RestBundle\Http\Header\Prefer;
use Can\RestBundle\Preference\PreferenceConfiguration;
use Can\RestBundle\Preference\PreferenceEventDispatcher;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use InvalidArgumentException;
/**
* A listener which collects client preferences, specified through the the
* HTTP Prefer request header.
*
* @group preference
*
* @package can/rest-bundle
* @author lechecacharro <lechecacharro@gmail.com>
*/
class PreferenceListener
{
/**
* @var PreferenceConfiguration
*/
protected $configuration;
/**
* @var PreferenceEventDispatcher
*/
protected $dispatcher;
/**
* PreferenceListener constructor.
*
* @param PreferenceConfiguration $configuration
* @param PreferenceEventDispatcher $dispatcher
*/
public function __construct(PreferenceConfiguration $configuration, PreferenceEventDispatcher $dispatcher)
{
$this->configuration = $configuration;
$this->dispatcher = $dispatcher;
}
/**
* @param RequestEvent $event
*/
public function onRequest(RequestEvent $event): void
{
// Skip processing if the component is not enabled
if (! $this->configuration->isEnabled()) {
return;
}
// Do process only the master request
if (! $event->isMasterRequest()) {
return;
}
$request = $event->getRequest();
// Skip processing if not in the service zone
if (! $request->attributes->get(CanRestBundle::ATTR_SERVICE_ZONE)) {
return;
}
$this->setPreferences($request);
}
/**
* Sets the list of requested preferences via the HTTP Prefer header as the
* {@link CanRestBundle::ATTR_PREFERENCES} request attribute.
*
* @param Request $request the HTTP request
*
* @throws BadRequestHttpException if the Prefer header is invalid
*/
protected function setPreferences(Request $request): void
{
try {
$preferenceList = Prefer::parseHeader($request->headers->get('Prefer'));
} catch (InvalidArgumentException $e) {
throw new BadRequestHttpException('Invalid Prefer header', $e);
}
// Allow third parties to modify the list of requested preferences
$event = $this->dispatcher->dispatchPreferencesRequested($preferenceList);
$request->attributes->set(CanRestBundle::ATTR_PREFERENCES, $event->getPreferenceList());
}
}