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