188 lines
5.2 KiB
PHP
188 lines
5.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* This file is part of the TYPO3 CMS project.
|
|
*
|
|
* It is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License, either version 2
|
|
* of the License, or any later version.
|
|
*
|
|
* For the full copyright and license information, please read the
|
|
* LICENSE.txt file that was distributed with this source code.
|
|
*
|
|
* The TYPO3 project - inspiring people to share!
|
|
*/
|
|
|
|
namespace TYPO3\CMS\Core\Routing;
|
|
|
|
use Symfony\Component\Routing\CompiledRoute;
|
|
use Symfony\Component\Routing\Route as SymfonyRoute;
|
|
use TYPO3\CMS\Core\Routing\Aspect\AspectInterface;
|
|
use TYPO3\CMS\Core\Routing\Enhancer\EnhancerInterface;
|
|
|
|
/**
|
|
* TYPO3's route is built on top of Symfony's route with some special handling
|
|
* of "Aspects" built on top of a route
|
|
*
|
|
* @internal as this is tightly coupled to Symfony's Routing and we try to encapsulate this, please note that this might change if we change the under-the-hood implementation.
|
|
*/
|
|
class Route extends SymfonyRoute
|
|
{
|
|
/**
|
|
* @var CompiledRoute|null
|
|
*/
|
|
protected $compiled;
|
|
|
|
/**
|
|
* @var array<string, AspectInterface>
|
|
*/
|
|
protected $aspects = [];
|
|
|
|
public function __construct(
|
|
string $path,
|
|
array $defaults = [],
|
|
array $requirements = [],
|
|
array $options = [],
|
|
?string $host = '',
|
|
$schemes = [],
|
|
$methods = [],
|
|
?string $condition = '',
|
|
array $aspects = []
|
|
) {
|
|
parent::__construct($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
|
$this->setAspects($aspects);
|
|
}
|
|
|
|
/**
|
|
* @todo '_arguments' are added implicitly, make it explicit in enhancers
|
|
*/
|
|
public function getArguments(): array
|
|
{
|
|
return $this->getOption('_arguments') ?? [];
|
|
}
|
|
|
|
public function getEnhancer(): ?EnhancerInterface
|
|
{
|
|
return $this->getOption('_enhancer') ?? null;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, AspectInterface>
|
|
*/
|
|
public function getAspects(): array
|
|
{
|
|
return $this->aspects;
|
|
}
|
|
|
|
/**
|
|
* Sets the aspects and removes existing ones.
|
|
*
|
|
* This method implements a fluent interface.
|
|
*
|
|
* @param array<string, AspectInterface> $aspects
|
|
* @return $this
|
|
*/
|
|
public function setAspects(array $aspects): self
|
|
{
|
|
$this->aspects = [];
|
|
return $this->addAspects($aspects);
|
|
}
|
|
|
|
/**
|
|
* Adds aspects to the existing maps.
|
|
*
|
|
* This method implements a fluent interface.
|
|
*
|
|
* @param array<string, AspectInterface> $aspects
|
|
* @return $this
|
|
*/
|
|
public function addAspects(array $aspects): self
|
|
{
|
|
foreach ($aspects as $key => $aspect) {
|
|
if (isset($this->aspects[$key])) {
|
|
throw new \OverflowException(
|
|
sprintf('Cannot override aspect %s', $key),
|
|
1538326791
|
|
);
|
|
}
|
|
$this->aspects[$key] = $aspect;
|
|
}
|
|
$this->compiled = null;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Returns the aspect for the given key.
|
|
*
|
|
* @param string $key The key
|
|
* @return AspectInterface|null The regex or null when not given
|
|
*/
|
|
public function getAspect(string $key): ?AspectInterface
|
|
{
|
|
return $this->aspects[$key] ?? null;
|
|
}
|
|
|
|
/**
|
|
* Checks if an aspect is set for the given key.
|
|
*
|
|
* @param string $key A variable name
|
|
* @return bool true if an aspect is specified, false otherwise
|
|
*/
|
|
public function hasAspect(string $key): bool
|
|
{
|
|
return array_key_exists($key, $this->aspects);
|
|
}
|
|
|
|
/**
|
|
* Sets an aspect for the given key.
|
|
*
|
|
* @param string $key The key
|
|
* @return $this
|
|
*/
|
|
public function setAspect(string $key, AspectInterface $aspect): self
|
|
{
|
|
$this->aspects[$key] = $aspect;
|
|
$this->compiled = null;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param string[] $classNames All (logical AND) class names that must match
|
|
* (including interfaces, abstract classes and traits)
|
|
* @param string[] $variableNames Variable names to be filtered
|
|
* @return AspectInterface[]
|
|
*/
|
|
public function filterAspects(array $classNames, array $variableNames = []): array
|
|
{
|
|
$aspects = $this->aspects;
|
|
if (empty($classNames) && empty($variableNames)) {
|
|
return $aspects;
|
|
}
|
|
if (!empty($variableNames)) {
|
|
$aspects = array_filter(
|
|
$this->aspects,
|
|
static function (string $variableName) use ($variableNames) {
|
|
return in_array($variableName, $variableNames, true);
|
|
},
|
|
ARRAY_FILTER_USE_KEY
|
|
);
|
|
}
|
|
return array_filter(
|
|
$aspects,
|
|
static function (AspectInterface $aspect) use ($classNames) {
|
|
$uses = class_uses($aspect) ?: [];
|
|
foreach ($classNames as $className) {
|
|
if (!is_a($aspect, $className)
|
|
&& !in_array($className, $uses, true)
|
|
) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
);
|
|
}
|
|
}
|