Completed
Push — master ( 692aa1...25e5a7 )
by Paweł
60:22
created

LinkRequestListener::onKernelRequest()   D

Complexity

Conditions 13
Paths 117

Size

Total Lines 98
Code Lines 54

Duplication

Lines 4
Ratio 4.08 %

Code Coverage

Tests 41
CRAP Score 13.5237

Importance

Changes 0
Metric Value
dl 4
loc 98
rs 4.7055
c 0
b 0
f 0
ccs 41
cts 48
cp 0.8542
cc 13
eloc 54
nc 117
nop 3
crap 13.5237

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Superdesk Web Publisher Content Bundle.
5
 *
6
 * Copyright 2015 Sourcefabric z.u. and contributors.
7
 *
8
 * For the full copyright and license information, please see the
9
 * AUTHORS and LICENSE files distributed with this source code.
10
 *
11
 * @copyright 2015 Sourcefabric z.ú
12
 * @license http://www.superdesk.org/license
13
 */
14
15
namespace SWP\Bundle\ContentBundle\EventListener;
16
17
use SWP\Component\Common\Response\ResourcesListResponseInterface;
18
use SWP\Component\Common\Response\SingleResourceResponseInterface;
19
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
20
use Symfony\Component\HttpFoundation\Request;
21
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
22
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
23
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
24
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
25
use Symfony\Component\HttpKernel\HttpKernelInterface;
26
use Symfony\Component\HttpKernel\KernelEvents;
27
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
28
29
class LinkRequestListener
30
{
31
    /**
32
     * @var ControllerResolverInterface
33
     */
34
    protected $resolver;
35
36
    /**
37
     * @var UrlMatcherInterface
38
     */
39
    protected $urlMatcher;
40
41
    /**
42 94
     * @param ControllerResolverInterface $controllerResolver
43
     * @param UrlMatcherInterface         $urlMatcher
44 94
     */
45 94
    public function __construct(ControllerResolverInterface $controllerResolver, UrlMatcherInterface $urlMatcher)
46 94
    {
47
        $this->resolver = $controllerResolver;
48
        $this->urlMatcher = $urlMatcher;
49
    }
50
51
    /**
52
     * @param GetResponseEvent $event
53 94
     *
54
     * @return array
55 94
     */
56 94
    public function onKernelRequest(GetResponseEvent $event, $eventName, EventDispatcherInterface $dispatcher)
0 ignored issues
show
Unused Code introduced by
The parameter $eventName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
57
    {
58
        if (!$event->getRequest()->headers->has('link')) {
59 2
            return;
60 2
        }
61
62
        $links = [];
63
        $header = $event->getRequest()->headers->get('link');
64
65
        /*
66
         * Due to limitations, multiple same-name headers are sent as comma
67
         * separated values.
68
         *
69 2
         * This breaks those headers into Link headers following the format
70 1
         * http://tools.ietf.org/html/rfc2068#section-19.6.2.4
71 1
         */
72
        while (preg_match('/^((?:[^"]|"[^"]*")*?),/', $header, $matches)) {
73
            $header = trim(substr($header, strlen($matches[0])));
74 2
            $links[] = $matches[1];
75 2
        }
76
77
        if ($header) {
78 2
            $links[] = $header;
79
        }
80
81 2
        $requestMethod = $this->urlMatcher->getContext()->getMethod();
82
83 2
        // The controller resolver needs a request to resolve the controller.
84
        $stubRequest = new Request();
85 2
86
        foreach ($links as $idx => $link) {
87 2
            // Force the GET method to avoid the use of the previous method (LINK/UNLINK)
88 2
            $this->urlMatcher->getContext()->setMethod('GET');
89 2
90 2
            $linkParams = explode(';', trim($link));
91 2
            $resourceType = null;
92 View Code Duplication
            if (count($linkParams) > 1) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
93 2
                $resourceType = trim(preg_replace('/<|>/', '', $linkParams[1]));
94 2
                $resourceType = str_replace('"', '', str_replace('rel=', '', $resourceType));
95
            }
96
            $resource = array_shift($linkParams);
97 2
            $resource = preg_replace('/<|>/', '', $resource);
98 1
99
            // Assume that no resource is specified here if there is no path separator, because urlMatcher will return homepage
100 2
            if (strpos($resource, '/') === false) {
101
                continue;
102
            }
103 2
            $tempRequest = Request::create($resource);
104
105
            try {
106
                $route = $this->urlMatcher->match($tempRequest->getRequestUri());
107
            } catch (\Exception $e) {
108
                // If we don't have a matching route we return the original Link header
109 2
                continue;
110 2
            }
111 2
112
            $stubRequest->attributes->replace($route);
113
            $stubRequest->server = $event->getRequest()->server;
114
            if (false === $controller = $this->resolver->getController($stubRequest)) {
115 2
                continue;
116 2
            }
117 2
118 2
            $subEvent = new FilterControllerEvent($event->getKernel(), $controller, $stubRequest, HttpKernelInterface::SUB_REQUEST);
119 2
            $kernelSubEvent = new GetResponseEvent($event->getKernel(), $stubRequest, HttpKernelInterface::SUB_REQUEST);
120
            $dispatcher->dispatch(KernelEvents::REQUEST, $kernelSubEvent);
121 2
            $dispatcher->dispatch(KernelEvents::CONTROLLER, $subEvent);
122 2
            $controller = $subEvent->getController();
123
124
            $argumentResolver = new ArgumentResolver();
125
            $arguments = $argumentResolver->getArguments($stubRequest, $controller);
126 2
127
            try {
128 2
                $result = call_user_func_array($controller, $arguments);
129
                // Our api returns objects for single resources
130 2
                if (!is_object($result)) {
131
                    continue;
132
                }
133
134 2
                // return clean object for LINK requests
135
                if ($result instanceof ResourcesListResponseInterface) {
136
                    $result = $result->getResources();
137
                } elseif ($result instanceof SingleResourceResponseInterface) {
138 2
                    $result = $result->getResource();
139
                }
140
141
                $links[$idx] = ['object' => $result, 'resourceType' => $resourceType];
142 2
            } catch (\Exception $e) {
143 2
                $links[$idx] = ['object' => $e, 'resourceType' => 'exception'];
144
145 2
                continue;
146
            }
147
        }
148
149
        $event->getRequest()->attributes->set('links', $links);
150
        $this->urlMatcher->getContext()->setMethod($requestMethod);
151
152
        return $links;
153
    }
154
}
155