RequestContextFactory::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
/*
4
 *
5
 * (c) Yaroslav Honcharuk <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Yarhon\RouteGuardBundle\Security\Http;
12
13
use Symfony\Component\HttpFoundation\RequestStack;
14
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
15
use Yarhon\RouteGuardBundle\Routing\RouteContextInterface;
16
use Yarhon\RouteGuardBundle\Routing\GeneratedUrlAwareInterface;
17
18
/**
19
 * @author Yaroslav Honcharuk <[email protected]>
20
 */
21
class RequestContextFactory
22
{
23
    /**
24
     * @var RequestStack
25
     */
26
    private $requestStack;
27
28
    /**
29
     * @var UrlGeneratorInterface
30
     */
31
    private $urlGenerator;
32
33
    /**
34
     * @param RequestStack          $requestStack
35
     * @param UrlGeneratorInterface $urlGenerator
36
     */
37 26
    public function __construct(RequestStack $requestStack, UrlGeneratorInterface $urlGenerator)
38
    {
39 26
        $this->requestStack = $requestStack;
40 26
        $this->urlGenerator = $urlGenerator;
41 26
    }
42
43
    /**
44
     * @param RouteContextInterface $routeContext
45
     *
46
     * @return RequestContext
47
     */
48 12
    public function createContext(RouteContextInterface $routeContext)
49
    {
50 12
        $urlGenerator = $this->urlGenerator;
51 12
        $urlGeneratorContext = $this->urlGenerator->getContext();
52
53
        $generateUrlClosure = function () use ($routeContext, $urlGenerator) {
54 10
            static $generated;
55
56 10
            if (null !== $generated) {
57
                return $generated;
58
            }
59
60 10
            if (!($routeContext instanceof GeneratedUrlAwareInterface) || null === $routeContext->getReferenceType()) {
61 1
                return $generated = $urlGenerator->generate($routeContext->getName(), $routeContext->getParameters(), UrlGeneratorInterface::ABSOLUTE_PATH);
62
            }
63
64 9
            $referenceType = $routeContext->getReferenceType();
65
66
            // We need to parse path and host from the generated url, that depends on reference type.
67
            // When using ABSOLUTE_URL or NETWORK_PATH, generated url will contain both path and host.
68
            //
69
            // When using ABSOLUTE_PATH or RELATIVE_PATH, generated url will contain only path.
70
            // If route has some specific host assigned, the UrlGenerator will force reference type to
71
            // ABSOLUTE_URL or NETWORK_PATH, that would produce url with host.
72
            // So, with ABSOLUTE_PATH or RELATIVE_PATH, if generated url does not contains host, we can be sure
73
            // that the host is the "current" host, and grab it from UrlGenerator context.
74
            // Finally, with RELATIVE_PATH we can't simply determine path (absolute), so we force generation to
75
            // ABSOLUTE_URL, and don't save the generated url.
76
77 9
            if (UrlGeneratorInterface::RELATIVE_PATH === $referenceType) {
78 1
                $referenceType = UrlGeneratorInterface::ABSOLUTE_URL;
79
            }
80
81 9
            $generated = $urlGenerator->generate($routeContext->getName(), $routeContext->getParameters(), $referenceType);
82
83 9
            if (UrlGeneratorInterface::RELATIVE_PATH !== $routeContext->getReferenceType()) {
84 8
                $routeContext->setGeneratedUrl($generated);
85
            }
86
87 9
            return $generated;
88 12
        };
89
90
        $pathInfoClosure = function () use ($generateUrlClosure, $urlGeneratorContext) {
91 8
            $url = $generateUrlClosure();
92 8
            $pathInfo = parse_url($url, PHP_URL_PATH);
93 8
            $pathInfo = substr($pathInfo, strlen($urlGeneratorContext->getBaseUrl()));
94
95
            // See \Symfony\Component\HttpFoundation\Request::preparePathInfo
96 8
            if (false === $pathInfo || '' === $pathInfo) {
97 1
                $pathInfo = '/';
98
            }
99
100 8
            return $pathInfo;
101 12
        };
102
103
        $hostClosure = function () use ($generateUrlClosure, $urlGeneratorContext) {
104 2
            $url = $generateUrlClosure();
105 2
            $host = parse_url($url, PHP_URL_HOST) ?: $urlGeneratorContext->getHost();
106
107 2
            return $host;
108 12
        };
109
110 12
        $request = $this->requestStack->getCurrentRequest();
111
112 12
        $requestContext = new RequestContext($pathInfoClosure, $hostClosure, $routeContext->getMethod(), $request->getClientIp());
113
114 12
        return $requestContext;
115
    }
116
}
117