‪TYPO3CMS  ‪main
AbstractEnhancer.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
24 
28 abstract class ‪AbstractEnhancer implements ‪EnhancerInterface
29 {
33  protected ‪$aspects = [];
34 
38  protected ‪$variableProcessor;
39 
44  protected function ‪applyRouteAspects(‪Route $route, array ‪$aspects, string $namespace = null)
45  {
46  if (empty(‪$aspects)) {
47  return;
48  }
50  ->deflateKeys($aspects, $namespace, $route->‪getArguments());
51  $route->‪setAspects(‪$aspects);
52  }
53 
57  protected function ‪applyRequirements(‪Route $route, array $requirements, string $namespace = null)
58  {
59  $requirements = $this->‪getVariableProcessor()
60  ->deflateKeys($requirements, $namespace, $route->‪getArguments());
61  // only keep requirements that are actually part of the current route path
62  $requirements = $this->‪filterValuesByPathVariables($route, $requirements);
63  // Symfony's behavior on applying pattern for parameters just concerns values
64  // to be passed either to URL or to internal parameters - they are always the
65  // same, without any transformation.
66  //
67  // TYPO3 extends ("enhances") this behavior by making a difference between values
68  // for generation (resulting in a URL) and matching (resulting in query parameters)
69  // having the following implications and meaning:
70  //
71  // + since requirements in classic Symfony focus on parameters in URLs
72  // and aspects define a mapping between URL part (e.g. 'some-example-news')
73  // and the corresponding internal argument (e.g. 'tx_news_pi1[news]=123')
74  // + thus, the requirement definition cannot be used for resolving and generating
75  // a route at the same time (it would have to be e.g. `[\w_._]+` AND `\d+`)
76  //
77  // Symfony's default regular expression pattern `[^/]+` (see
78  // `RouteCompiler::compilePattern()`) has to be overridden with `.+` to
79  // allow URI parameters like `some-example-news/january` as well.
80  //
81  // Existing `requirements` for TYPO3 route enhancers are not modified, only those
82  // that are not defined and would use Symfony's default pattern.
83  $requirements = $this->‪defineValuesByAspect($route, $requirements, '.+');
84  $route->setRequirements($requirements);
85  }
86 
97  protected function ‪filterValuesByPathVariables(‪Route $route, array $values): array
98  {
99  return array_intersect_key(
100  $values,
101  array_flip($route->compile()->getPathVariables())
102  );
103  }
104 
109  protected function ‪overrideValuesByAspect(‪Route $route, array $values, string $targetValue): array
110  {
111  foreach (array_keys($route->‪getAspects()) as $variableName) {
112  $values[$variableName] = $targetValue;
113  }
114  return $values;
115  }
116 
121  protected function ‪defineValuesByAspect(‪Route $route, array $values, string $targetValue): array
122  {
123  foreach (array_keys($route->‪getAspects()) as $variableName) {
124  if (isset($values[$variableName])) {
125  continue;
126  }
127  $values[$variableName] = $targetValue;
128  }
129  return $values;
130  }
131 
140  protected function ‪modifyRoutePath(string $routePath): string
141  {
142  $substitutes = [];
143  foreach ($this->aspects as $variableName => $aspect) {
144  if (!$aspect instanceof ‪ModifiableAspectInterface) {
145  continue;
146  }
147  $value = $aspect->modify();
148  if ($value !== null) {
149  $substitutes['{' . $variableName . '}'] = $value;
150  $substitutes['{!' . $variableName . '}'] = $value;
151  }
152  }
153  return str_replace(
154  array_keys($substitutes),
155  array_values($substitutes),
156  $routePath
157  );
158  }
159 
165  protected function ‪resolveType(‪Route $route, array &$remainingQueryParameters): string
166  {
167  $type = $remainingQueryParameters['type'] ?? 0;
168  $decoratedParameters = $route->getOption('_decoratedParameters');
169  if (isset($decoratedParameters['type'])) {
170  $type = $decoratedParameters['type'];
171  unset($decoratedParameters['type']);
172  $remainingQueryParameters = array_replace_recursive(
173  $remainingQueryParameters,
174  $decoratedParameters
175  );
176  }
177  return (string)$type;
178  }
179 
180  protected function ‪getVariableProcessor(): ‪VariableProcessor
181  {
182  if (isset($this->variableProcessor)) {
184  }
185  return $this->variableProcessor = GeneralUtility::makeInstance(VariableProcessor::class);
186  }
187 
191  public function ‪setAspects(array ‪$aspects): void
192  {
193  $this->aspects = ‪$aspects;
194  }
195 
199  public function ‪getAspects(): array
200  {
201  return ‪$this->aspects;
202  }
203 }
‪TYPO3\CMS\Core\Routing\Route\getArguments
‪getArguments()
Definition: Route.php:60
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\getAspects
‪getAspects()
Definition: AbstractEnhancer.php:197
‪TYPO3\CMS\Core\Routing\Aspect\AspectInterface
Definition: AspectInterface.php:23
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\filterValuesByPathVariables
‪filterValuesByPathVariables(Route $route, array $values)
Definition: AbstractEnhancer.php:95
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\applyRequirements
‪applyRequirements(Route $route, array $requirements, string $namespace=null)
Definition: AbstractEnhancer.php:55
‪TYPO3\CMS\Core\Routing\Enhancer\VariableProcessor
Definition: VariableProcessor.php:24
‪TYPO3\CMS\Core\Routing\Route\setAspects
‪$this setAspects(array $aspects)
Definition: Route.php:88
‪TYPO3\CMS\Core\Routing\Enhancer
Definition: AbstractEnhancer.php:18
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\$variableProcessor
‪VariableProcessor null $variableProcessor
Definition: AbstractEnhancer.php:36
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer
Definition: AbstractEnhancer.php:29
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\applyRouteAspects
‪applyRouteAspects(Route $route, array $aspects, string $namespace=null)
Definition: AbstractEnhancer.php:42
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\getVariableProcessor
‪getVariableProcessor()
Definition: AbstractEnhancer.php:178
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\overrideValuesByAspect
‪overrideValuesByAspect(Route $route, array $values, string $targetValue)
Definition: AbstractEnhancer.php:107
‪TYPO3\CMS\Core\Routing\Route
Definition: Route.php:32
‪TYPO3\CMS\Core\Routing\Route\getAspects
‪array getAspects()
Definition: Route.php:75
‪TYPO3\CMS\Core\Routing\Aspect\ModifiableAspectInterface
Definition: ModifiableAspectInterface.php:25
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\modifyRoutePath
‪modifyRoutePath(string $routePath)
Definition: AbstractEnhancer.php:138
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\resolveType
‪resolveType(Route $route, array &$remainingQueryParameters)
Definition: AbstractEnhancer.php:163
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\setAspects
‪setAspects(array $aspects)
Definition: AbstractEnhancer.php:189
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\$aspects
‪AspectInterface[] $aspects
Definition: AbstractEnhancer.php:32
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\defineValuesByAspect
‪defineValuesByAspect(Route $route, array $values, string $targetValue)
Definition: AbstractEnhancer.php:119
‪TYPO3\CMS\Core\Routing\Enhancer\EnhancerInterface
Definition: EnhancerInterface.php:27