1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* File containing the DefaultRouter 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\Bundle\EzPublishCoreBundle\Routing; |
10
|
|
|
|
11
|
|
|
use eZ\Publish\Core\MVC\ConfigResolverInterface; |
12
|
|
|
use eZ\Publish\Core\MVC\Symfony\Routing\SimplifiedRequest; |
13
|
|
|
use eZ\Publish\Core\MVC\Symfony\SiteAccess; |
14
|
|
|
use eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessAware; |
15
|
|
|
use eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessRouterInterface; |
16
|
|
|
use eZ\Publish\Core\MVC\Symfony\SiteAccess\URILexer; |
17
|
|
|
use Symfony\Bundle\FrameworkBundle\Routing\Router; |
18
|
|
|
use Symfony\Component\HttpFoundation\Request; |
19
|
|
|
use Symfony\Component\Routing\Exception\RouteNotFoundException; |
20
|
|
|
use Symfony\Component\Routing\Matcher\RequestMatcherInterface; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Extension of Symfony default router implementing RequestMatcherInterface. |
24
|
|
|
*/ |
25
|
|
|
class DefaultRouter extends Router implements RequestMatcherInterface, SiteAccessAware |
26
|
|
|
{ |
27
|
|
|
/** |
28
|
|
|
* @var SiteAccess |
29
|
|
|
*/ |
30
|
|
|
protected $siteAccess; |
31
|
|
|
|
32
|
|
|
protected $nonSiteAccessAwareRoutes = array(); |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var \eZ\Publish\Core\MVC\ConfigResolverInterface |
36
|
|
|
*/ |
37
|
|
|
protected $configResolver; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var \eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessRouterInterface |
41
|
|
|
*/ |
42
|
|
|
protected $siteAccessRouter; |
43
|
|
|
|
44
|
|
|
public function setConfigResolver(ConfigResolverInterface $configResolver) |
45
|
|
|
{ |
46
|
|
|
$this->configResolver = $configResolver; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
public function setSiteAccess(SiteAccess $siteAccess = null) |
50
|
|
|
{ |
51
|
|
|
$this->siteAccess = $siteAccess; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Injects route names that are not supposed to be SiteAccess aware. |
56
|
|
|
* i.e. Routes pointing to asset generation (like assetic). |
57
|
|
|
* |
58
|
|
|
* @param array $routes |
59
|
|
|
*/ |
60
|
|
|
public function setNonSiteAccessAwareRoutes(array $routes) |
61
|
|
|
{ |
62
|
|
|
$this->nonSiteAccessAwareRoutes = $routes; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* @param \eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessRouterInterface $siteAccessRouter |
67
|
|
|
*/ |
68
|
|
|
public function setSiteAccessRouter(SiteAccessRouterInterface $siteAccessRouter) |
69
|
|
|
{ |
70
|
|
|
$this->siteAccessRouter = $siteAccessRouter; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
public function matchRequest(Request $request) |
74
|
|
|
{ |
75
|
|
|
return $this->match($request->attributes->get('semanticPathinfo', $request->getPathInfo())); |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) |
79
|
|
|
{ |
80
|
|
|
$siteAccess = $this->siteAccess; |
81
|
|
|
$originalContext = $context = $this->getContext(); |
82
|
|
|
$isSiteAccessAware = $this->isSiteAccessAwareRoute($name); |
83
|
|
|
|
84
|
|
|
// Retrieving the appropriate SiteAccess to generate the link for. |
85
|
|
View Code Duplication |
if (isset($parameters['siteaccess']) && $isSiteAccessAware) { |
|
|
|
|
86
|
|
|
$siteAccess = $this->siteAccessRouter->matchByName($parameters['siteaccess']); |
87
|
|
|
if ($siteAccess instanceof SiteAccess && $siteAccess->matcher instanceof SiteAccess\VersatileMatcher) { |
88
|
|
|
// Switch request context for link generation. |
89
|
|
|
$context = $this->getContextBySimplifiedRequest($siteAccess->matcher->getRequest()); |
90
|
|
|
$this->setContext($context); |
91
|
|
|
} elseif ($this->logger) { |
92
|
|
|
$siteAccess = $this->siteAccess; |
93
|
|
|
$this->logger->notice("Could not generate a link using provided 'siteaccess' parameter: {$parameters['siteaccess']}. Generating using current context."); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
unset($parameters['siteaccess']); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
try { |
100
|
|
|
$url = parent::generate($name, $parameters, $referenceType); |
101
|
|
|
} catch (RouteNotFoundException $e) { |
102
|
|
|
// Switch back to original context, for next links generation. |
103
|
|
|
$this->setContext($originalContext); |
104
|
|
|
throw $e; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
// Now putting back SiteAccess URI if needed. |
108
|
|
|
if ($isSiteAccessAware && $siteAccess && $siteAccess->matcher instanceof URILexer) { |
109
|
|
|
if ($referenceType === self::ABSOLUTE_URL || $referenceType === self::NETWORK_PATH) { |
110
|
|
|
$scheme = $context->getScheme(); |
111
|
|
|
$port = ''; |
112
|
|
|
if ($scheme === 'http' && $this->context->getHttpPort() != 80) { |
113
|
|
|
$port = ':' . $this->context->getHttpPort(); |
114
|
|
|
} elseif ($scheme === 'https' && $this->context->getHttpsPort() != 443) { |
115
|
|
|
$port = ':' . $this->context->getHttpsPort(); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
$base = $context->getHost() . $port . $context->getBaseUrl(); |
119
|
|
|
} else { |
120
|
|
|
$base = $context->getBaseUrl(); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
$linkUri = $base ? substr($url, strpos($url, $base) + strlen($base)) : $url; |
124
|
|
|
$url = str_replace($linkUri, $siteAccess->matcher->analyseLink($linkUri), $url); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
// Switch back to original context, for next links generation. |
128
|
|
|
$this->setContext($originalContext); |
129
|
|
|
|
130
|
|
|
return $url; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Checks if $routeName is a siteAccess aware route, and thus needs to have siteAccess URI prepended. |
135
|
|
|
* Will be used for link generation, only in the case of URI SiteAccess matching. |
136
|
|
|
* |
137
|
|
|
* @param $routeName |
138
|
|
|
* |
139
|
|
|
* @return bool |
140
|
|
|
*/ |
141
|
|
|
protected function isSiteAccessAwareRoute($routeName) |
142
|
|
|
{ |
143
|
|
|
foreach ($this->nonSiteAccessAwareRoutes as $ignoredPrefix) { |
144
|
|
|
if (strpos($routeName, $ignoredPrefix) === 0) { |
145
|
|
|
return false; |
146
|
|
|
} |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
return true; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Merges context from $simplifiedRequest into a clone of the current context. |
154
|
|
|
* |
155
|
|
|
* @param \eZ\Publish\Core\MVC\Symfony\Routing\SimplifiedRequest $simplifiedRequest |
156
|
|
|
* |
157
|
|
|
* @return \Symfony\Component\Routing\RequestContext |
158
|
|
|
*/ |
159
|
|
View Code Duplication |
public function getContextBySimplifiedRequest(SimplifiedRequest $simplifiedRequest) |
160
|
|
|
{ |
161
|
|
|
$context = clone $this->context; |
162
|
|
|
if ($simplifiedRequest->scheme) { |
163
|
|
|
$context->setScheme($simplifiedRequest->scheme); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
if ($simplifiedRequest->port) { |
167
|
|
|
$context->setHttpPort($simplifiedRequest->port); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
if ($simplifiedRequest->host) { |
171
|
|
|
$context->setHost($simplifiedRequest->host); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
if ($simplifiedRequest->pathinfo) { |
175
|
|
|
$context->setPathInfo($simplifiedRequest->pathinfo); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
return $context; |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
|
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.