‪TYPO3CMS  ‪main
ExtbasePluginEnhancer.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 
23 
42 {
46  protected ‪$routesOfPlugin;
47 
48  public function ‪__construct(array ‪$configuration)
49  {
50  parent::__construct(‪$configuration);
51  $this->routesOfPlugin = $this->configuration['routes'] ?? [];
52  // Only set the namespace if the plugin+extension keys are given. This allows to also use "namespace" property
53  // instead from the parent constructor.
54  if (
55  $this->namespace === ''
56  && isset($this->configuration['extension'])
57  && isset($this->configuration['plugin'])
58  ) {
59  $extensionName = $this->configuration['extension'];
60  $pluginName = $this->configuration['plugin'];
61  $extensionName = str_replace(' ', '', ucwords(str_replace('_', ' ', $extensionName)));
62  $pluginSignature = strtolower($extensionName . '_' . $pluginName);
63  $this->namespace = 'tx_' . $pluginSignature;
64  }
65  return;
66  }
67 
71  public function ‪enhanceForMatching(‪RouteCollection $collection): void
72  {
73  $i = 0;
75  $defaultPageRoute = $collection->get('default');
76  foreach ($this->routesOfPlugin as ‪$configuration) {
77  $route = $this->‪getVariant($defaultPageRoute, ‪$configuration);
78  $collection->‪add($this->namespace . '_' . $i++, $route);
79  }
80  }
81 
85  protected function ‪getVariant(Route $defaultPageRoute, array ‪$configuration): Route
86  {
87  $arguments = ‪$configuration['_arguments'] ?? [];
88  unset(‪$configuration['_arguments']);
89 
91  $routePath = $this->‪modifyRoutePath($configuration['routePath']);
92  $routePath = ‪$variableProcessor->‪deflateRoutePath($routePath, $this->namespace, $arguments);
93  unset(‪$configuration['routePath']);
94  $options = array_merge($defaultPageRoute->getOptions(), ['_enhancer' => $this, 'utf8' => true, '_arguments' => $arguments]);
95  $route = new Route(rtrim($defaultPageRoute->getPath(), '/') . '/' . ltrim($routePath, '/'), [], [], $options);
96 
97  $defaults = array_merge_recursive(
98  $defaultPageRoute->getDefaults(),
99  ‪$variableProcessor->‪deflateKeys($this->configuration['defaults'] ?? [], $this->namespace, $arguments)
100  );
101  // only keep `defaults` that are actually used in `routePath`
102  $defaults = $this->‪filterValuesByPathVariables(
103  $route,
104  $defaults
105  );
106  // apply '_controller' to route defaults
107  $defaults = array_merge_recursive(
108  $defaults,
109  array_intersect_key(‪$configuration, ['_controller' => true])
110  );
111  $route->setDefaults($defaults);
112  $this->‪applyRouteAspects($route, $this->aspects ?? [], $this->namespace);
113  $this->‪applyRequirements($route, $this->configuration['requirements'] ?? [], $this->namespace);
114  return $route;
115  }
116 
120  public function ‪enhanceForGeneration(RouteCollection $collection, array $originalParameters): void
121  {
122  if (!is_array($originalParameters[$this->namespace] ?? null)) {
123  return;
124  }
125  // apply default controller and action names if not set in parameters
126  if (!$this->‪hasControllerActionValues($originalParameters[$this->namespace])
127  && !empty($this->configuration['defaultController'])
128  ) {
130  $this->configuration['defaultController'],
131  $originalParameters[$this->namespace],
132  true
133  );
134  }
135 
136  $i = 0;
138  $defaultPageRoute = $collection->get('default');
139  foreach ($this->routesOfPlugin as ‪$configuration) {
140  $variant = $this->‪getVariant($defaultPageRoute, ‪$configuration);
141  // The enhancer tells us: This given route does not match the parameters
142  if (!$this->‪verifyRequiredParameters($variant, $originalParameters)) {
143  continue;
144  }
145  $parameters = $originalParameters;
146  unset($parameters[$this->namespace]['action']);
147  unset($parameters[$this->namespace]['controller']);
148  $compiledRoute = $variant->compile();
149  // contains all given parameters, even if not used as variables in route
150  $deflatedParameters = $this->‪deflateParameters($variant, $parameters);
151  $variables = array_flip($compiledRoute->getPathVariables());
152  $mergedParams = array_replace($variant->getDefaults(), $deflatedParameters);
153  // all params must be given, otherwise we exclude this variant
154  // (it is allowed that $variables is empty - in this case variables are
155  // "given" implicitly through controller-action pair in `_controller`)
156  if (array_diff_key($variables, $mergedParams)) {
157  continue;
158  }
159  $variant->addOptions(['deflatedParameters' => $deflatedParameters]);
160  $collection->add($this->namespace . '_' . $i++, $variant);
161  }
162  }
163 
171  public function ‪inflateParameters(array $parameters, array $internals = []): array
172  {
173  $parameters = $this->‪getVariableProcessor()
174  ->inflateNamespaceParameters($parameters, $this->namespace);
175  $parameters[‪$this->namespace] = $parameters[‪$this->namespace] ?? [];
176 
177  // Invalid if there is no controller given, so this enhancers does not do anything
178  if (empty($internals['_controller'] ?? null)) {
179  return $parameters;
180  }
182  $internals['_controller'],
183  $parameters[$this->namespace],
184  false
185  );
186  return $parameters;
187  }
188 
192  protected function ‪verifyRequiredParameters(Route $route, array $parameters): bool
193  {
194  if (!is_array($parameters[$this->namespace])) {
195  return false;
196  }
197  if (!$route->hasDefault('_controller')) {
198  return false;
199  }
200  $controller = $route->getDefault('_controller');
201  [$controllerName, $actionName] = explode('::', $controller);
202  if (!isset($parameters[$this->namespace]['controller']) || $controllerName !== $parameters[$this->namespace]['controller']) {
203  return false;
204  }
205  if (!isset($parameters[$this->namespace]['action']) || $actionName !== $parameters[$this->namespace]['action']) {
206  return false;
207  }
208  return true;
209  }
213  protected function ‪hasControllerActionValues(array $target): bool
214  {
215  return !empty($target['controller']) && !empty($target['action']);
216  }
217 
224  protected function ‪applyControllerActionValues(string $controllerActionValue, array &$target, bool $tryUpdate = false)
225  {
226  if (!str_contains($controllerActionValue, '::')) {
227  return;
228  }
229  [$controllerName, $actionName] = explode('::', $controllerActionValue, 2);
230  // use default action name if controller matches
231  if ($tryUpdate && empty($target['action']) && $controllerName === ($target['controller'] ?? null)) {
232  $target['action'] = $actionName;
233  // use default controller name if action is defined (implies: non-default-controllers must be given)
234  } elseif ($tryUpdate && empty($target['controller']) && !empty($target['action'])) {
235  $target['controller'] = $controllerName;
236  // fallback and override
237  } else {
238  $target['controller'] = $controllerName;
239  $target['action'] = $actionName;
240  }
241  }
242 }
‪TYPO3\CMS\Extbase\Routing\ExtbasePluginEnhancer\applyControllerActionValues
‪applyControllerActionValues(string $controllerActionValue, array &$target, bool $tryUpdate=false)
Definition: ExtbasePluginEnhancer.php:223
‪TYPO3\CMS\Extbase\Routing\ExtbasePluginEnhancer\inflateParameters
‪inflateParameters(array $parameters, array $internals=[])
Definition: ExtbasePluginEnhancer.php:170
‪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\Extbase\Routing\ExtbasePluginEnhancer\verifyRequiredParameters
‪verifyRequiredParameters(Route $route, array $parameters)
Definition: ExtbasePluginEnhancer.php:191
‪TYPO3\CMS\Extbase\Routing\ExtbasePluginEnhancer\getVariant
‪getVariant(Route $defaultPageRoute, array $configuration)
Definition: ExtbasePluginEnhancer.php:84
‪TYPO3\CMS\Core\Routing\RouteCollection
Definition: RouteCollection.php:30
‪TYPO3\CMS\Extbase\Routing\ExtbasePluginEnhancer\$routesOfPlugin
‪array $routesOfPlugin
Definition: ExtbasePluginEnhancer.php:45
‪TYPO3\CMS\Extbase\Routing\ExtbasePluginEnhancer\enhanceForGeneration
‪enhanceForGeneration(RouteCollection $collection, array $originalParameters)
Definition: ExtbasePluginEnhancer.php:119
‪TYPO3\CMS\Core\Routing\Enhancer\VariableProcessor\deflateRoutePath
‪deflateRoutePath(string $routePath, string $namespace=null, array $arguments=[])
Definition: VariableProcessor.php:124
‪TYPO3\CMS\Extbase\Routing\ExtbasePluginEnhancer\hasControllerActionValues
‪hasControllerActionValues(array $target)
Definition: ExtbasePluginEnhancer.php:212
‪TYPO3\CMS\Core\Routing\RouteCollection\add
‪add(string $name, Typo3Route|SymfonyRoute $route, int $priority=0)
Definition: RouteCollection.php:31
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\$variableProcessor
‪VariableProcessor null $variableProcessor
Definition: AbstractEnhancer.php:36
‪TYPO3\CMS\Core\Routing\Enhancer\PluginEnhancer
Definition: PluginEnhancer.php:43
‪TYPO3\CMS\Core\Routing\Enhancer\PluginEnhancer\deflateParameters
‪deflateParameters(Route $route, array $parameters)
Definition: PluginEnhancer.php:153
‪TYPO3\CMS\Extbase\Routing\ExtbasePluginEnhancer
Definition: ExtbasePluginEnhancer.php:42
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\applyRouteAspects
‪applyRouteAspects(Route $route, array $aspects, string $namespace=null)
Definition: AbstractEnhancer.php:42
‪TYPO3\CMS\Extbase\Routing\ExtbasePluginEnhancer\__construct
‪__construct(array $configuration)
Definition: ExtbasePluginEnhancer.php:47
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\getVariableProcessor
‪getVariableProcessor()
Definition: AbstractEnhancer.php:178
‪TYPO3\CMS\Core\Routing\Enhancer\VariableProcessor\deflateKeys
‪deflateKeys(array $items, string $namespace=null, array $arguments=[], bool $hash=true)
Definition: VariableProcessor.php:218
‪TYPO3\CMS\Extbase\Routing\ExtbasePluginEnhancer\enhanceForMatching
‪enhanceForMatching(RouteCollection $collection)
Definition: ExtbasePluginEnhancer.php:70
‪TYPO3\CMS\Extbase\Routing
Definition: ExtbasePluginEnhancer.php:18
‪TYPO3\CMS\Core\Routing\Route
Definition: Route.php:32
‪TYPO3\CMS\Core\Routing\Enhancer\AbstractEnhancer\modifyRoutePath
‪modifyRoutePath(string $routePath)
Definition: AbstractEnhancer.php:138
‪TYPO3\CMS\Core\Routing\Enhancer\PluginEnhancer\$namespace
‪string $namespace
Definition: PluginEnhancer.php:50
‪TYPO3\CMS\Core\Routing\Enhancer\PluginEnhancer\$configuration
‪array $configuration
Definition: PluginEnhancer.php:46