ikucheriavenko
8/28/2017 - 11:38 AM

header parser listener

header parser listener

<?php

namespace AppBundle\EventListener;

use FOS\RestBundle\View\View;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class LinkRequestListener
 * @package AppBundle\EventListener
 */
class LinkRequestListener
{
    /**
     * @var ControllerResolverInterface
     */
    private $resolver;

    /**
     * @var UrlMatcherInterface
     */
    private $urlMatcher;

    /**
     * @param ControllerResolverInterface  $controllerResolver
     * @param UrlMatcherInterface          $urlMatcher
     */
    public function __construct(ControllerResolverInterface $controllerResolver, UrlMatcherInterface $urlMatcher)
    {
        $this->resolver = $controllerResolver;
        $this->urlMatcher = $urlMatcher;
    }

    /**
     * Current implementation works for binding an
     * existed Candidate with an existed Job
     *
     * @param GetResponseEvent $event
     */
    public function onKernelRequest(GetResponseEvent $event)
    {
        if (!$event->getRequest()->headers->has('link')) {
            return;
        }

        $links  = array();
        $header = $event->getRequest()->headers->get('link');

        /*
         * Here we divide Link headers on separated header
         * format: http://tools.ietf.org/html/rfc2068#section-19.6.2.4
         */
        while (preg_match('/^((?:[^"]|"[^"]*")*?),/', $header, $matches)) {
            $header  = trim(substr($header, strlen($matches[0])));
            $links[] = $matches[1];
        }

        if ($header) {
            $links[] = $header;
        }

        $requestMethod = $this->urlMatcher->getContext()->getMethod();
        // Explicitly set GET method for candidate retrieving
        $this->urlMatcher->getContext()->setMethod('GET');

        $stubRequest = new Request();

        foreach ($links as $idx => $link) {
            $linkParams = explode(';', trim($link));
            $resource   = array_shift($linkParams);
            $resource   = preg_replace('/<|>/', '', $resource);

            try {
                $route = $this->urlMatcher->match($resource);
            } catch (\Exception $e) {
                continue;
            }

            $stubRequest->attributes->replace($route);

            if (false === $controller = $this->resolver->getController($stubRequest)) {
                continue;
            }

            $arguments = $this->resolver->getArguments($stubRequest, $controller);

            try {
                $result = call_user_func_array($controller, $arguments);

                if (!$result instanceof View) {
                    continue;
                }

                $links[$idx] = $result->getData();
            } catch (\Exception $e) {
                continue;
            }
        }

        $event->getRequest()->attributes->set('link', $links);
        $this->urlMatcher->getContext()->setMethod($requestMethod);
    }
}