Completed
Push — master ( 29f099...87ed20 )
by Łukasz
24:25
created

Generator::generate()   B

Complexity

Conditions 8
Paths 16

Size

Total Lines 32

Duplication

Lines 10
Ratio 31.25 %

Importance

Changes 0
Metric Value
cc 8
nc 16
nop 3
dl 10
loc 32
rs 8.1635
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the Generator class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\MVC\Symfony\Routing;
10
11
use eZ\Publish\Core\MVC\Symfony\SiteAccess;
12
use eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessAware;
13
use eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessRouterInterface;
14
use Psr\Log\LoggerInterface;
15
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
16
use Symfony\Component\Routing\RequestContext;
17
18
/**
19
 * Base class for eZ Publish Url generation.
20
 */
21
abstract class Generator implements SiteAccessAware
22
{
23
    /**
24
     * @var \Symfony\Component\Routing\RequestContext
25
     */
26
    protected $requestContext;
27
28
    /**
29
     * @var \eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessRouterInterface
30
     */
31
    protected $siteAccessRouter;
32
33
    /**
34
     * @var \eZ\Publish\Core\MVC\Symfony\SiteAccess
35
     */
36
    protected $siteAccess;
37
38
    /**
39
     * @var \Psr\Log\LoggerInterface
40
     */
41
    protected $logger;
42
43
    /**
44
     * @param \Symfony\Component\Routing\RequestContext $requestContext
45
     */
46
    public function setRequestContext(RequestContext $requestContext)
47
    {
48
        $this->requestContext = $requestContext;
49
    }
50
51
    /**
52
     * @param \eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessRouterInterface $siteAccessRouter
53
     */
54
    public function setSiteAccessRouter(SiteAccessRouterInterface $siteAccessRouter)
55
    {
56
        $this->siteAccessRouter = $siteAccessRouter;
57
    }
58
59
    /**
60
     * @param \eZ\Publish\Core\MVC\Symfony\SiteAccess $siteAccess
61
     */
62
    public function setSiteAccess(SiteAccess $siteAccess = null)
63
    {
64
        $this->siteAccess = $siteAccess;
65
    }
66
67
    /**
68
     * @param LoggerInterface $logger
69
     */
70
    public function setLogger(LoggerInterface $logger = null)
71
    {
72
        $this->logger = $logger;
73
    }
74
75
    /**
76
     * Triggers URL generation for $urlResource and $parameters.
77
     *
78
     * @param mixed $urlResource Type can be anything, depending on the context. It's up to the router to pass the appropriate value to the implementor.
79
     * @param array $parameters Arbitrary hash of parameters to generate a link.
80
     *                          SiteAccess name can be provided as 'siteaccess' to generate a link to it (cross siteaccess link).
81
     * @param int $referenceType The type of reference to be generated (one of the constants)
82
     *
83
     * @return string
84
     */
85
    public function generate($urlResource, array $parameters, $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
86
    {
87
        $siteAccess = $this->siteAccess;
88
        $requestContext = $this->requestContext;
89
90
        // Retrieving the appropriate SiteAccess to generate the link for.
91 View Code Duplication
        if (isset($parameters['siteaccess'])) {
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...
92
            $siteAccess = $this->siteAccessRouter->matchByName($parameters['siteaccess']);
93
            if ($siteAccess instanceof SiteAccess && $siteAccess->matcher instanceof SiteAccess\VersatileMatcher) {
94
                $requestContext = $this->getContextBySimplifiedRequest($siteAccess->matcher->getRequest());
95
            } elseif ($this->logger) {
96
                $siteAccess = $this->siteAccess;
97
                $this->logger->notice("Could not generate a link using provided 'siteaccess' parameter: {$parameters['siteaccess']}. Generating using current context.");
98
                unset($parameters['siteaccess']);
99
            }
100
        }
101
102
        $url = $this->doGenerate($urlResource, $parameters);
103
104
        // Add the SiteAccess URI back if needed.
105
        if ($siteAccess && $siteAccess->matcher instanceof SiteAccess\URILexer) {
106
            $url = $siteAccess->matcher->analyseLink($url);
107
        }
108
109
        $url = $requestContext->getBaseUrl() . $url;
110
111
        if ($referenceType === UrlGeneratorInterface::ABSOLUTE_URL) {
112
            $url = $this->generateAbsoluteUrl($url, $requestContext);
113
        }
114
115
        return $url;
116
    }
117
118
    /**
119
     * Generates the URL from $urlResource and $parameters.
120
     *
121
     * @param mixed $urlResource
122
     * @param array $parameters
123
     *
124
     * @return string
125
     */
126
    abstract public function doGenerate($urlResource, array $parameters);
127
128
    /**
129
     * Generates an absolute URL from $uri and the request context.
130
     *
131
     * @param string $uri
132
     * @param \Symfony\Component\Routing\RequestContext $requestContext
133
     *
134
     * @return string
135
     */
136
    protected function generateAbsoluteUrl($uri, RequestContext $requestContext)
137
    {
138
        $scheme = $requestContext->getScheme();
139
        $port = '';
140
        if ($scheme === 'http' && $requestContext->getHttpPort() != 80) {
141
            $port = ':' . $requestContext->getHttpPort();
142
        } elseif ($scheme === 'https' && $requestContext->getHttpsPort() != 443) {
143
            $port = ':' . $requestContext->getHttpsPort();
144
        }
145
146
        return $scheme . '://' . $requestContext->getHost() . $port . $uri;
147
    }
148
149
    /**
150
     * Merges context from $simplifiedRequest into a clone of the current context.
151
     *
152
     * @param SimplifiedRequest $simplifiedRequest
153
     *
154
     * @return RequestContext
155
     */
156 View Code Duplication
    private function getContextBySimplifiedRequest(SimplifiedRequest $simplifiedRequest)
157
    {
158
        $context = clone $this->requestContext;
159
        if ($simplifiedRequest->scheme) {
160
            $context->setScheme($simplifiedRequest->scheme);
161
        }
162
163
        if ($simplifiedRequest->port) {
164
            switch ($simplifiedRequest->scheme) {
165
                case 'https':
166
                    $context->setHttpsPort($simplifiedRequest->port);
167
                    break;
168
                default:
169
                    $context->setHttpPort($simplifiedRequest->port);
170
                    break;
171
            }
172
        }
173
174
        if ($simplifiedRequest->host) {
175
            $context->setHost($simplifiedRequest->host);
176
        }
177
178
        if ($simplifiedRequest->pathinfo) {
179
            $context->setPathInfo($simplifiedRequest->pathinfo);
180
        }
181
182
        return $context;
183
    }
184
}
185