Exponential 5.x Kernel 7.5.40 Exponential New Stack (Symfony-based) Kernel — PHP Class Reference

UrlAliasGenerator.php
Go to the documentation of this file.
1 <?php
2
7 namespace eZ\Publish\Core\MVC\Symfony\Routing\Generator;
8
9 use eZ\Publish\API\Repository\Repository;
10 use eZ\Publish\API\Repository\Values\Content\Location;
11 use eZ\Publish\Core\MVC\ConfigResolverInterface;
12 use eZ\Publish\Core\MVC\Symfony\Routing\Generator;
13 use Symfony\Component\Routing\RouterInterface;
14
20 class UrlAliasGenerator extends Generator
21 {
22 const INTERNAL_LOCATION_ROUTE = '_ezpublishLocation';
23 const INTERNAL_CONTENT_VIEW_ROUTE = '_ez_content_view';
24
26 private $repository;
27
33 private $defaultRouter;
34
36 private $rootLocationId;
37
39 private $excludedUriPrefixes = [];
40
42 private $pathPrefixMap = [];
43
45 private $configResolver;
46
53 private $unsafeCharMap;
54
55 public function __construct(Repository $repository, RouterInterface $defaultRouter, ConfigResolverInterface $configResolver, array $unsafeCharMap = [])
56 {
57 $this->repository = $repository;
58 $this->defaultRouter = $defaultRouter;
59 $this->configResolver = $configResolver;
60 $this->unsafeCharMap = $unsafeCharMap;
61 }
62
72 public function doGenerate($location, array $parameters)
73 {
74 $siteAccess = $parameters['siteaccess'] ?? null;
75
76 unset($parameters['language'], $parameters['contentId'], $parameters['siteaccess']);
77
78 $pathString = $this->createPathString($location, $siteAccess);
79 $queryString = $this->createQueryString($parameters);
80 $url = $pathString . $queryString;
81
82 return $this->filterCharactersOfURL($url);
83 }
84
90 public function setRootLocationId($rootLocationId)
91 {
92 $this->rootLocationId = $rootLocationId;
93 }
94
98 public function setExcludedUriPrefixes(array $excludedUriPrefixes)
99 {
100 $this->excludedUriPrefixes = $excludedUriPrefixes;
101 }
102
112 public function getPathPrefixByRootLocationId($rootLocationId, $languages = null, $siteaccess = null)
113 {
114 if (!$rootLocationId) {
115 return '';
116 }
117
118 if (!isset($this->pathPrefixMap[$siteaccess])) {
119 $this->pathPrefixMap[$siteaccess] = [];
120 }
121
122 if (!isset($this->pathPrefixMap[$siteaccess][$rootLocationId])) {
123 $this->pathPrefixMap[$siteaccess][$rootLocationId] = $this->repository
124 ->getURLAliasService()
125 ->reverseLookup(
126 $this->loadLocation($rootLocationId),
127 null,
128 false,
129 $languages
130 )
131 ->path;
132 }
133
134 return $this->pathPrefixMap[$siteaccess][$rootLocationId];
135 }
136
144 public function isUriPrefixExcluded($uri)
145 {
146 foreach ($this->excludedUriPrefixes as $excludedPrefix) {
147 $excludedPrefix = '/' . trim($excludedPrefix, '/');
148 if (mb_stripos($uri, $excludedPrefix) === 0) {
149 return true;
150 }
151 }
152
153 return false;
154 }
155
164 public function loadLocation($locationId)
165 {
166 return $this->repository->sudo(
167 function (Repository $repository) use ($locationId) {
168 /* @var $repository \eZ\Publish\Core\Repository\Repository */
169 return $repository->getLocationService()->loadLocation($locationId);
170 }
171 );
172 }
173
180 private function createPathString(Location $location, ?string $siteAccess = null): string
181 {
182 $urlAliasService = $this->repository->getURLAliasService();
183
184 if ($siteAccess) {
185 // We generate for a different SiteAccess, so potentially in a different language.
186 $languages = $this->configResolver->getParameter('languages', null, $siteAccess);
187 $urlAliases = $urlAliasService->listLocationAliases($location, false, null, null, $languages);
188 // Use the target SiteAccess root location
189 $rootLocationId = $this->configResolver->getParameter('content.tree_root.location_id', null, $siteAccess);
190 } else {
191 $languages = null;
192 $urlAliases = $urlAliasService->listLocationAliases($location, false);
193 $rootLocationId = $this->rootLocationId;
194 }
195
196 if (!empty($urlAliases)) {
197 $path = $urlAliases[0]->path;
198 // Remove rootLocation's prefix if needed.
199 if ($rootLocationId !== null) {
200 $pathPrefix = $this->getPathPrefixByRootLocationId($rootLocationId, $languages, $siteAccess);
201 // "/" cannot be considered as a path prefix since it's root, so we ignore it.
202 if ($pathPrefix !== '/' && ($path === $pathPrefix || mb_stripos($path, $pathPrefix . '/') === 0)) {
203 $path = mb_substr($path, mb_strlen($pathPrefix));
204 } elseif ($pathPrefix !== '/' && !$this->isUriPrefixExcluded($path) && $this->logger !== null) {
205 // Location path is outside configured content tree and doesn't have an excluded prefix.
206 // This is most likely an error (from content edition or link generation logic).
207 $this->logger->warning("Generating a link to a location outside root content tree: '$path' is outside tree starting to location #$rootLocationId");
208 }
209 }
210 } else {
211 $path = $this->defaultRouter->generate(
212 self::INTERNAL_CONTENT_VIEW_ROUTE,
213 ['contentId' => $location->contentId, 'locationId' => $location->id]
214 );
215 }
216
217 return $path ?: '/';
218 }
219
228 private function createQueryString(array $parameters): string
229 {
230 $queryString = '';
231 $fragment = null;
232 if (isset($parameters['_fragment'])) {
233 $fragment = $parameters['_fragment'];
234 unset($parameters['_fragment']);
235 }
236
237 if (!empty($parameters)) {
238 $queryString = '?' . http_build_query($parameters, '', '&');
239 }
240
241 if ($fragment) {
242 // logic aligned with Symfony 3.4: \Symfony\Component\Routing\Generator\UrlGenerator::doGenerate
243 $queryString .= '#' . strtr(rawurlencode($fragment), ['%2F' => '/', '%3F' => '?']);
244 }
245
246 return $queryString;
247 }
248
256 private function filterCharactersOfURL(string $url): string
257 {
258 return strtr($url, $this->unsafeCharMap);
259 }
260 }
eZ\Publish\API\Repository\Values\Content\Location
Definition: API/Repository/Values/Content/Location.php:32
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator
URL generator for UrlAlias based links.
Definition: UrlAliasGenerator.php:21
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\createQueryString
createQueryString(array $parameters)
Creates query string from parameters.
Definition: UrlAliasGenerator.php:228
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\setExcludedUriPrefixes
setExcludedUriPrefixes(array $excludedUriPrefixes)
Definition: UrlAliasGenerator.php:98
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\filterCharactersOfURL
filterCharactersOfURL(string $url)
Replace potentially unsafe characters with url-encoded counterpart.
Definition: UrlAliasGenerator.php:256
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\getPathPrefixByRootLocationId
getPathPrefixByRootLocationId($rootLocationId, $languages=null, $siteaccess=null)
Returns path corresponding to $rootLocationId.
Definition: UrlAliasGenerator.php:112
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\INTERNAL_LOCATION_ROUTE
const INTERNAL_LOCATION_ROUTE
Definition: UrlAliasGenerator.php:22
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\$repository
$repository
Definition: UrlAliasGenerator.php:26
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\doGenerate
doGenerate($location, array $parameters)
Generates the URL from $urlResource and $parameters.
Definition: UrlAliasGenerator.php:72
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\INTERNAL_CONTENT_VIEW_ROUTE
const INTERNAL_CONTENT_VIEW_ROUTE
Definition: UrlAliasGenerator.php:23
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\$pathPrefixMap
$pathPrefixMap
Definition: UrlAliasGenerator.php:42
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\$configResolver
$configResolver
Definition: UrlAliasGenerator.php:45
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\__construct
__construct(Repository $repository, RouterInterface $defaultRouter, ConfigResolverInterface $configResolver, array $unsafeCharMap=[])
Definition: UrlAliasGenerator.php:55
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\isUriPrefixExcluded
isUriPrefixExcluded($uri)
Checks if passed URI has an excluded prefix, when a root location is defined.
Definition: UrlAliasGenerator.php:144
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\$rootLocationId
$rootLocationId
Definition: UrlAliasGenerator.php:36
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\$defaultRouter
$defaultRouter
Definition: UrlAliasGenerator.php:33
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\$unsafeCharMap
$unsafeCharMap
Definition: UrlAliasGenerator.php:53
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\setRootLocationId
setRootLocationId($rootLocationId)
Injects current root locationId that will be used for link generation.
Definition: UrlAliasGenerator.php:90
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\createPathString
createPathString(Location $location, ?string $siteAccess=null)
Definition: UrlAliasGenerator.php:180
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\$excludedUriPrefixes
$excludedUriPrefixes
Definition: UrlAliasGenerator.php:39
eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator\loadLocation
loadLocation($locationId)
Loads a location by its locationId, regardless to user limitations since the router is invoked BEFORE...
Definition: UrlAliasGenerator.php:164
eZ\Publish\Core\MVC\Symfony\Routing\Generator
Base class for eZ Publish Url generation.
Definition: MVC/Symfony/Routing/Generator.php:20
eZ\Publish\Core\MVC\Symfony\Routing\Generator\$siteAccess
$siteAccess
Definition: MVC/Symfony/Routing/Generator.php:28
eZ\Publish\API\Repository\Repository
Repository interface.
Definition: API/Repository/Repository.php:16
eZ\Publish\Core\MVC\ConfigResolverInterface
Interface for config resolvers.
Definition: ConfigResolverInterface.php:19
eZ\Publish\Core\MVC\Symfony\Routing\Generator
Definition: RouteReferenceGenerator.php:7
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.