updated backend
This commit is contained in:
parent
1fea0f4fe7
commit
11521c2339
3459 changed files with 72735 additions and 168535 deletions
|
|
@ -15,6 +15,7 @@ use Doctrine\Common\Annotations\Reader;
|
|||
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||
use Symfony\Component\Config\Loader\LoaderResolverInterface;
|
||||
use Symfony\Component\Config\Resource\FileResource;
|
||||
use Symfony\Component\Routing\Annotation\Route as RouteAnnotation;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
|
|
@ -32,7 +33,6 @@ use Symfony\Component\Routing\RouteCollection;
|
|||
* recognizes several parameters: requirements, options, defaults, schemes,
|
||||
* methods, host, and name. The name parameter is mandatory.
|
||||
* Here is an example of how you should be able to use it:
|
||||
*
|
||||
* /**
|
||||
* * @Route("/Blog")
|
||||
* * /
|
||||
|
|
@ -44,7 +44,6 @@ use Symfony\Component\Routing\RouteCollection;
|
|||
* public function index()
|
||||
* {
|
||||
* }
|
||||
*
|
||||
* /**
|
||||
* * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"})
|
||||
* * /
|
||||
|
|
@ -120,11 +119,9 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||
}
|
||||
|
||||
if (0 === $collection->count() && $class->hasMethod('__invoke')) {
|
||||
$globals = $this->resetGlobals();
|
||||
foreach ($this->reader->getClassAnnotations($class) as $annot) {
|
||||
if ($annot instanceof $this->routeAnnotationClass) {
|
||||
$globals['path'] = '';
|
||||
$globals['name'] = '';
|
||||
|
||||
$this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke'));
|
||||
}
|
||||
}
|
||||
|
|
@ -133,6 +130,10 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RouteAnnotation $annot or an object that exposes a similar interface
|
||||
* @param array $globals
|
||||
*/
|
||||
protected function addRoute(RouteCollection $collection, $annot, $globals, \ReflectionClass $class, \ReflectionMethod $method)
|
||||
{
|
||||
$name = $annot->getName();
|
||||
|
|
@ -141,13 +142,16 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||
}
|
||||
$name = $globals['name'].$name;
|
||||
|
||||
$defaults = array_replace($globals['defaults'], $annot->getDefaults());
|
||||
foreach ($method->getParameters() as $param) {
|
||||
if (false !== strpos($globals['path'].$annot->getPath(), sprintf('{%s}', $param->getName())) && !isset($defaults[$param->getName()]) && $param->isDefaultValueAvailable()) {
|
||||
$defaults[$param->getName()] = $param->getDefaultValue();
|
||||
$requirements = $annot->getRequirements();
|
||||
|
||||
foreach ($requirements as $placeholder => $requirement) {
|
||||
if (\is_int($placeholder)) {
|
||||
@trigger_error(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName()), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
$requirements = array_replace($globals['requirements'], $annot->getRequirements());
|
||||
|
||||
$defaults = array_replace($globals['defaults'], $annot->getDefaults());
|
||||
$requirements = array_replace($globals['requirements'], $requirements);
|
||||
$options = array_replace($globals['options'], $annot->getOptions());
|
||||
$schemes = array_merge($globals['schemes'], $annot->getSchemes());
|
||||
$methods = array_merge($globals['methods'], $annot->getMethods());
|
||||
|
|
@ -162,11 +166,57 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||
$condition = $globals['condition'];
|
||||
}
|
||||
|
||||
$route = $this->createRoute($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
$path = $annot->getLocalizedPaths() ?: $annot->getPath();
|
||||
$prefix = $globals['localized_paths'] ?: $globals['path'];
|
||||
$paths = [];
|
||||
|
||||
$this->configureRoute($route, $class, $method, $annot);
|
||||
if (\is_array($path)) {
|
||||
if (!\is_array($prefix)) {
|
||||
foreach ($path as $locale => $localePath) {
|
||||
$paths[$locale] = $prefix.$localePath;
|
||||
}
|
||||
} elseif ($missing = array_diff_key($prefix, $path)) {
|
||||
throw new \LogicException(sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing))));
|
||||
} else {
|
||||
foreach ($path as $locale => $localePath) {
|
||||
if (!isset($prefix[$locale])) {
|
||||
throw new \LogicException(sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name));
|
||||
}
|
||||
|
||||
$collection->add($name, $route);
|
||||
$paths[$locale] = $prefix[$locale].$localePath;
|
||||
}
|
||||
}
|
||||
} elseif (\is_array($prefix)) {
|
||||
foreach ($prefix as $locale => $localePrefix) {
|
||||
$paths[$locale] = $localePrefix.$path;
|
||||
}
|
||||
} else {
|
||||
$paths[] = $prefix.$path;
|
||||
}
|
||||
|
||||
foreach ($method->getParameters() as $param) {
|
||||
if (isset($defaults[$param->name]) || !$param->isDefaultValueAvailable()) {
|
||||
continue;
|
||||
}
|
||||
foreach ($paths as $locale => $path) {
|
||||
if (preg_match(sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) {
|
||||
$defaults[$param->name] = $param->getDefaultValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($paths as $locale => $path) {
|
||||
$route = $this->createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
$this->configureRoute($route, $class, $method, $annot);
|
||||
if (0 !== $locale) {
|
||||
$route->setDefault('_locale', $locale);
|
||||
$route->setDefault('_canonical_route', $name);
|
||||
$collection->add($name.'.'.$locale, $route);
|
||||
} else {
|
||||
$collection->add($name, $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -194,14 +244,12 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||
/**
|
||||
* Gets the default route name for a class method.
|
||||
*
|
||||
* @param \ReflectionClass $class
|
||||
* @param \ReflectionMethod $method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method)
|
||||
{
|
||||
$name = strtolower(str_replace('\\', '_', $class->name).'_'.$method->name);
|
||||
$name = str_replace('\\', '_', $class->name).'_'.$method->name;
|
||||
$name = \function_exists('mb_strtolower') && preg_match('//u', $name) ? mb_strtolower($name, 'UTF-8') : strtolower($name);
|
||||
if ($this->defaultRouteIndex > 0) {
|
||||
$name .= '_'.$this->defaultRouteIndex;
|
||||
}
|
||||
|
|
@ -212,17 +260,7 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||
|
||||
protected function getGlobals(\ReflectionClass $class)
|
||||
{
|
||||
$globals = array(
|
||||
'path' => '',
|
||||
'requirements' => array(),
|
||||
'options' => array(),
|
||||
'defaults' => array(),
|
||||
'schemes' => array(),
|
||||
'methods' => array(),
|
||||
'host' => '',
|
||||
'condition' => '',
|
||||
'name' => '',
|
||||
);
|
||||
$globals = $this->resetGlobals();
|
||||
|
||||
if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) {
|
||||
if (null !== $annot->getName()) {
|
||||
|
|
@ -233,6 +271,8 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||
$globals['path'] = $annot->getPath();
|
||||
}
|
||||
|
||||
$globals['localized_paths'] = $annot->getLocalizedPaths();
|
||||
|
||||
if (null !== $annot->getRequirements()) {
|
||||
$globals['requirements'] = $annot->getRequirements();
|
||||
}
|
||||
|
|
@ -260,11 +300,33 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
|||
if (null !== $annot->getCondition()) {
|
||||
$globals['condition'] = $annot->getCondition();
|
||||
}
|
||||
|
||||
foreach ($globals['requirements'] as $placeholder => $requirement) {
|
||||
if (\is_int($placeholder)) {
|
||||
@trigger_error(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName()), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $globals;
|
||||
}
|
||||
|
||||
private function resetGlobals()
|
||||
{
|
||||
return [
|
||||
'path' => null,
|
||||
'localized_paths' => [],
|
||||
'requirements' => [],
|
||||
'options' => [],
|
||||
'defaults' => [],
|
||||
'schemes' => [],
|
||||
'methods' => [],
|
||||
'host' => '',
|
||||
'condition' => '',
|
||||
'name' => '',
|
||||
];
|
||||
}
|
||||
|
||||
protected function createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition)
|
||||
{
|
||||
return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class AnnotationFileLoader extends FileLoader
|
|||
public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader)
|
||||
{
|
||||
if (!\function_exists('token_get_all')) {
|
||||
throw new \RuntimeException('The Tokenizer extension is required for the routing annotation loaders.');
|
||||
throw new \LogicException('The Tokenizer extension is required for the routing annotation loaders.');
|
||||
}
|
||||
|
||||
parent::__construct($locator);
|
||||
|
|
@ -46,7 +46,7 @@ class AnnotationFileLoader extends FileLoader
|
|||
* @param string $file A PHP file path
|
||||
* @param string|null $type The resource type
|
||||
*
|
||||
* @return RouteCollection A RouteCollection instance
|
||||
* @return RouteCollection|null A RouteCollection instance
|
||||
*
|
||||
* @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed
|
||||
*/
|
||||
|
|
@ -56,13 +56,16 @@ class AnnotationFileLoader extends FileLoader
|
|||
|
||||
$collection = new RouteCollection();
|
||||
if ($class = $this->findClass($path)) {
|
||||
$refl = new \ReflectionClass($class);
|
||||
if ($refl->isAbstract()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$collection->addResource(new FileResource($path));
|
||||
$collection->addCollection($this->loader->load($class, $type));
|
||||
}
|
||||
if (\PHP_VERSION_ID >= 70000) {
|
||||
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
|
||||
gc_mem_caches();
|
||||
}
|
||||
|
||||
gc_mem_caches();
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
|
@ -105,7 +108,7 @@ class AnnotationFileLoader extends FileLoader
|
|||
|
||||
if (true === $namespace && T_STRING === $token[0]) {
|
||||
$namespace = $token[1];
|
||||
while (isset($tokens[++$i][1]) && \in_array($tokens[$i][0], array(T_NS_SEPARATOR, T_STRING))) {
|
||||
while (isset($tokens[++$i][1]) && \in_array($tokens[$i][0], [T_NS_SEPARATOR, T_STRING])) {
|
||||
$namespace .= $tokens[$i][1];
|
||||
}
|
||||
$token = $tokens[$i];
|
||||
|
|
@ -122,7 +125,7 @@ class AnnotationFileLoader extends FileLoader
|
|||
if (T_DOUBLE_COLON === $tokens[$j][0] || T_NEW === $tokens[$j][0]) {
|
||||
$skipClassToken = true;
|
||||
break;
|
||||
} elseif (!\in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) {
|
||||
} elseif (!\in_array($tokens[$j][0], [T_WHITESPACE, T_DOC_COMMENT, T_COMMENT])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,14 +12,17 @@
|
|||
namespace Symfony\Component\Routing\Loader\DependencyInjection;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\Routing\Loader\ContainerLoader;
|
||||
use Symfony\Component\Routing\Loader\ObjectRouteLoader;
|
||||
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ServiceRouterLoader::class, ContainerLoader::class), E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* A route loader that executes a service to load the routes.
|
||||
*
|
||||
* This depends on the DependencyInjection component.
|
||||
*
|
||||
* @author Ryan Weaver <ryan@knpuniversity.com>
|
||||
*
|
||||
* @deprecated since Symfony 4.4, use Symfony\Component\Routing\Loader\ContainerLoader instead.
|
||||
*/
|
||||
class ServiceRouterLoader extends ObjectRouteLoader
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,16 +11,16 @@
|
|||
|
||||
namespace Symfony\Component\Routing\Loader;
|
||||
|
||||
use Symfony\Component\Config\Loader\Loader;
|
||||
use Symfony\Component\Config\Resource\FileResource;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ObjectRouteLoader::class, ObjectLoader::class), E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* A route loader that calls a method on an object to load the routes.
|
||||
*
|
||||
* @author Ryan Weaver <ryan@knpuniversity.com>
|
||||
*
|
||||
* @deprecated since Symfony 4.4, use ObjectLoader instead.
|
||||
*/
|
||||
abstract class ObjectRouteLoader extends Loader
|
||||
abstract class ObjectRouteLoader extends ObjectLoader
|
||||
{
|
||||
/**
|
||||
* Returns the object that the method will be called on to load routes.
|
||||
|
|
@ -34,48 +34,6 @@ abstract class ObjectRouteLoader extends Loader
|
|||
*/
|
||||
abstract protected function getServiceObject($id);
|
||||
|
||||
/**
|
||||
* Calls the service that will load the routes.
|
||||
*
|
||||
* @param mixed $resource Some value that will resolve to a callable
|
||||
* @param string|null $type The resource type
|
||||
*
|
||||
* @return RouteCollection
|
||||
*/
|
||||
public function load($resource, $type = null)
|
||||
{
|
||||
$parts = explode(':', $resource);
|
||||
if (2 != \count($parts)) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the "service" route loader: use the format "service_name:methodName"', $resource));
|
||||
}
|
||||
|
||||
$serviceString = $parts[0];
|
||||
$method = $parts[1];
|
||||
|
||||
$loaderObject = $this->getServiceObject($serviceString);
|
||||
|
||||
if (!\is_object($loaderObject)) {
|
||||
throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', \get_class($this), \gettype($loaderObject)));
|
||||
}
|
||||
|
||||
if (!method_exists($loaderObject, $method)) {
|
||||
throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s"', $method, \get_class($loaderObject), $resource));
|
||||
}
|
||||
|
||||
$routeCollection = \call_user_func(array($loaderObject, $method), $this);
|
||||
|
||||
if (!$routeCollection instanceof RouteCollection) {
|
||||
$type = \is_object($routeCollection) ? \get_class($routeCollection) : \gettype($routeCollection);
|
||||
|
||||
throw new \LogicException(sprintf('The %s::%s method must return a RouteCollection: %s returned', \get_class($loaderObject), $method, $type));
|
||||
}
|
||||
|
||||
// make the service file tracked so that if it changes, the cache rebuilds
|
||||
$this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection);
|
||||
|
||||
return $routeCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
@ -84,12 +42,11 @@ abstract class ObjectRouteLoader extends Loader
|
|||
return 'service' === $type;
|
||||
}
|
||||
|
||||
private function addClassResource(\ReflectionClass $class, RouteCollection $collection)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getObject(string $id)
|
||||
{
|
||||
do {
|
||||
if (is_file($class->getFileName())) {
|
||||
$collection->addResource(new FileResource($class->getFileName()));
|
||||
}
|
||||
} while ($class = $class->getParentClass());
|
||||
return $this->getServiceObject($id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,15 +40,15 @@ class PhpFileLoader extends FileLoader
|
|||
|
||||
// the closure forbids access to the private scope in the included file
|
||||
$loader = $this;
|
||||
$load = \Closure::bind(function ($file) use ($loader) {
|
||||
$load = \Closure::bind(static function ($file) use ($loader) {
|
||||
return include $file;
|
||||
}, null, ProtectedPhpFileLoader::class);
|
||||
|
||||
$result = $load($path);
|
||||
|
||||
if ($result instanceof \Closure) {
|
||||
if (\is_object($result) && \is_callable($result)) {
|
||||
$collection = new RouteCollection();
|
||||
$result(new RoutingConfigurator($collection, $this, $path, $file), $this);
|
||||
$result(new RoutingConfigurator($collection, $this, $path, $file));
|
||||
} else {
|
||||
$collection = $result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,10 +63,9 @@ class XmlFileLoader extends FileLoader
|
|||
/**
|
||||
* Parses a node from a loaded XML file.
|
||||
*
|
||||
* @param RouteCollection $collection Collection to associate with the node
|
||||
* @param \DOMElement $node Element to parse
|
||||
* @param string $path Full path of the XML file being processed
|
||||
* @param string $file Loaded file name
|
||||
* @param \DOMElement $node Element to parse
|
||||
* @param string $path Full path of the XML file being processed
|
||||
* @param string $file Loaded file name
|
||||
*
|
||||
* @throws \InvalidArgumentException When the XML is invalid
|
||||
*/
|
||||
|
|
@ -99,34 +98,49 @@ class XmlFileLoader extends FileLoader
|
|||
/**
|
||||
* Parses a route and adds it to the RouteCollection.
|
||||
*
|
||||
* @param RouteCollection $collection RouteCollection instance
|
||||
* @param \DOMElement $node Element to parse that represents a Route
|
||||
* @param string $path Full path of the XML file being processed
|
||||
* @param \DOMElement $node Element to parse that represents a Route
|
||||
* @param string $path Full path of the XML file being processed
|
||||
*
|
||||
* @throws \InvalidArgumentException When the XML is invalid
|
||||
*/
|
||||
protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path)
|
||||
{
|
||||
if ('' === ($id = $node->getAttribute('id')) || !$node->hasAttribute('path')) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "path" attribute.', $path));
|
||||
if ('' === $id = $node->getAttribute('id')) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" attribute.', $path));
|
||||
}
|
||||
|
||||
$schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY);
|
||||
$methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
|
||||
list($defaults, $requirements, $options, $condition, $paths) = $this->parseConfigs($node, $path);
|
||||
|
||||
$route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
|
||||
$collection->add($id, $route);
|
||||
if (!$paths && '' === $node->getAttribute('path')) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have a "path" attribute or <path> child nodes.', $path));
|
||||
}
|
||||
|
||||
if ($paths && '' !== $node->getAttribute('path')) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must not have both a "path" attribute and <path> child nodes.', $path));
|
||||
}
|
||||
|
||||
if (!$paths) {
|
||||
$route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
|
||||
$collection->add($id, $route);
|
||||
} else {
|
||||
foreach ($paths as $locale => $p) {
|
||||
$defaults['_locale'] = $locale;
|
||||
$defaults['_canonical_route'] = $id;
|
||||
$route = new Route($p, $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
|
||||
$collection->add($id.'.'.$locale, $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an import and adds the routes in the resource to the RouteCollection.
|
||||
*
|
||||
* @param RouteCollection $collection RouteCollection instance
|
||||
* @param \DOMElement $node Element to parse that represents a Route
|
||||
* @param string $path Full path of the XML file being processed
|
||||
* @param string $file Loaded file name
|
||||
* @param \DOMElement $node Element to parse that represents a Route
|
||||
* @param string $path Full path of the XML file being processed
|
||||
* @param string $file Loaded file name
|
||||
*
|
||||
* @throws \InvalidArgumentException When the XML is invalid
|
||||
*/
|
||||
|
|
@ -141,20 +155,72 @@ class XmlFileLoader extends FileLoader
|
|||
$host = $node->hasAttribute('host') ? $node->getAttribute('host') : null;
|
||||
$schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null;
|
||||
$methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null;
|
||||
$trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : true;
|
||||
|
||||
list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
|
||||
list($defaults, $requirements, $options, $condition, /* $paths */, $prefixes) = $this->parseConfigs($node, $path);
|
||||
|
||||
if ('' !== $prefix && $prefixes) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must not have both a "prefix" attribute and <prefix> child nodes.', $path));
|
||||
}
|
||||
|
||||
$exclude = [];
|
||||
foreach ($node->childNodes as $child) {
|
||||
if ($child instanceof \DOMElement && $child->localName === $exclude && self::NAMESPACE_URI === $child->namespaceURI) {
|
||||
$exclude[] = $child->nodeValue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($node->hasAttribute('exclude')) {
|
||||
if ($exclude) {
|
||||
throw new \InvalidArgumentException('You cannot use both the attribute "exclude" and <exclude> tags at the same time.');
|
||||
}
|
||||
$exclude = [$node->getAttribute('exclude')];
|
||||
}
|
||||
|
||||
$this->setCurrentDir(\dirname($path));
|
||||
|
||||
$imported = $this->import($resource, ('' !== $type ? $type : null), false, $file);
|
||||
/** @var RouteCollection[] $imported */
|
||||
$imported = $this->import($resource, ('' !== $type ? $type : null), false, $file, $exclude) ?: [];
|
||||
|
||||
if (!\is_array($imported)) {
|
||||
$imported = array($imported);
|
||||
$imported = [$imported];
|
||||
}
|
||||
|
||||
foreach ($imported as $subCollection) {
|
||||
/* @var $subCollection RouteCollection */
|
||||
$subCollection->addPrefix($prefix);
|
||||
if ('' !== $prefix || !$prefixes) {
|
||||
$subCollection->addPrefix($prefix);
|
||||
if (!$trailingSlashOnRoot) {
|
||||
$rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath();
|
||||
foreach ($subCollection->all() as $route) {
|
||||
if ($route->getPath() === $rootPath) {
|
||||
$route->setPath(rtrim($rootPath, '/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($prefixes as $locale => $localePrefix) {
|
||||
$prefixes[$locale] = trim(trim($localePrefix), '/');
|
||||
}
|
||||
foreach ($subCollection->all() as $name => $route) {
|
||||
if (null === $locale = $route->getDefault('_locale')) {
|
||||
$subCollection->remove($name);
|
||||
foreach ($prefixes as $locale => $localePrefix) {
|
||||
$localizedRoute = clone $route;
|
||||
$localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
|
||||
$localizedRoute->setDefault('_locale', $locale);
|
||||
$localizedRoute->setDefault('_canonical_route', $name);
|
||||
$subCollection->add($name.'.'.$locale, $localizedRoute);
|
||||
}
|
||||
} elseif (!isset($prefixes[$locale])) {
|
||||
throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix when imported in "%s".', $name, $locale, $path));
|
||||
} else {
|
||||
$route->setPath($prefixes[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
|
||||
$subCollection->add($name, $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $host) {
|
||||
$subCollection->setHost($host);
|
||||
}
|
||||
|
|
@ -171,6 +237,10 @@ class XmlFileLoader extends FileLoader
|
|||
$subCollection->addRequirements($requirements);
|
||||
$subCollection->addOptions($options);
|
||||
|
||||
if ($namePrefix = $node->getAttribute('name-prefix')) {
|
||||
$subCollection->addNamePrefix($namePrefix);
|
||||
}
|
||||
|
||||
$collection->addCollection($subCollection);
|
||||
}
|
||||
}
|
||||
|
|
@ -194,26 +264,30 @@ class XmlFileLoader extends FileLoader
|
|||
/**
|
||||
* Parses the config elements (default, requirement, option).
|
||||
*
|
||||
* @param \DOMElement $node Element to parse that contains the configs
|
||||
* @param string $path Full path of the XML file being processed
|
||||
*
|
||||
* @return array An array with the defaults as first item, requirements as second and options as third
|
||||
*
|
||||
* @throws \InvalidArgumentException When the XML is invalid
|
||||
*/
|
||||
private function parseConfigs(\DOMElement $node, $path)
|
||||
private function parseConfigs(\DOMElement $node, string $path): array
|
||||
{
|
||||
$defaults = array();
|
||||
$requirements = array();
|
||||
$options = array();
|
||||
$defaults = [];
|
||||
$requirements = [];
|
||||
$options = [];
|
||||
$condition = null;
|
||||
$prefixes = [];
|
||||
$paths = [];
|
||||
|
||||
/** @var \DOMElement $n */
|
||||
foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
|
||||
if ($node !== $n->parentNode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($n->localName) {
|
||||
case 'path':
|
||||
$paths[$n->getAttribute('locale')] = trim($n->textContent);
|
||||
break;
|
||||
case 'prefix':
|
||||
$prefixes[$n->getAttribute('locale')] = trim($n->textContent);
|
||||
break;
|
||||
case 'default':
|
||||
if ($this->isElementValueNull($n)) {
|
||||
$defaults[$n->getAttribute('key')] = null;
|
||||
|
|
@ -226,7 +300,7 @@ class XmlFileLoader extends FileLoader
|
|||
$requirements[$n->getAttribute('key')] = trim($n->textContent);
|
||||
break;
|
||||
case 'option':
|
||||
$options[$n->getAttribute('key')] = trim($n->textContent);
|
||||
$options[$n->getAttribute('key')] = XmlUtils::phpize(trim($n->textContent));
|
||||
break;
|
||||
case 'condition':
|
||||
$condition = trim($n->textContent);
|
||||
|
|
@ -245,22 +319,28 @@ class XmlFileLoader extends FileLoader
|
|||
|
||||
$defaults['_controller'] = $controller;
|
||||
}
|
||||
if ($node->hasAttribute('locale')) {
|
||||
$defaults['_locale'] = $node->getAttribute('locale');
|
||||
}
|
||||
if ($node->hasAttribute('format')) {
|
||||
$defaults['_format'] = $node->getAttribute('format');
|
||||
}
|
||||
if ($node->hasAttribute('utf8')) {
|
||||
$options['utf8'] = XmlUtils::phpize($node->getAttribute('utf8'));
|
||||
}
|
||||
|
||||
return array($defaults, $requirements, $options, $condition);
|
||||
return [$defaults, $requirements, $options, $condition, $paths, $prefixes];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the "default" elements.
|
||||
*
|
||||
* @param \DOMElement $element The "default" element to parse
|
||||
* @param string $path Full path of the XML file being processed
|
||||
*
|
||||
* @return array|bool|float|int|string|null The parsed value of the "default" element
|
||||
*/
|
||||
private function parseDefaultsConfig(\DOMElement $element, $path)
|
||||
private function parseDefaultsConfig(\DOMElement $element, string $path)
|
||||
{
|
||||
if ($this->isElementValueNull($element)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check for existing element nodes in the default element. There can
|
||||
|
|
@ -287,17 +367,14 @@ class XmlFileLoader extends FileLoader
|
|||
/**
|
||||
* Recursively parses the value of a "default" element.
|
||||
*
|
||||
* @param \DOMElement $node The node value
|
||||
* @param string $path Full path of the XML file being processed
|
||||
*
|
||||
* @return array|bool|float|int|string The parsed value
|
||||
*
|
||||
* @throws \InvalidArgumentException when the XML is invalid
|
||||
*/
|
||||
private function parseDefaultNode(\DOMElement $node, $path)
|
||||
private function parseDefaultNode(\DOMElement $node, string $path)
|
||||
{
|
||||
if ($this->isElementValueNull($node)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
switch ($node->localName) {
|
||||
|
|
@ -310,7 +387,7 @@ class XmlFileLoader extends FileLoader
|
|||
case 'string':
|
||||
return trim($node->nodeValue);
|
||||
case 'list':
|
||||
$list = array();
|
||||
$list = [];
|
||||
|
||||
foreach ($node->childNodes as $element) {
|
||||
if (!$element instanceof \DOMElement) {
|
||||
|
|
@ -326,7 +403,7 @@ class XmlFileLoader extends FileLoader
|
|||
|
||||
return $list;
|
||||
case 'map':
|
||||
$map = array();
|
||||
$map = [];
|
||||
|
||||
foreach ($node->childNodes as $element) {
|
||||
if (!$element instanceof \DOMElement) {
|
||||
|
|
@ -346,7 +423,7 @@ class XmlFileLoader extends FileLoader
|
|||
}
|
||||
}
|
||||
|
||||
private function isElementValueNull(\DOMElement $element)
|
||||
private function isElementValueNull(\DOMElement $element): bool
|
||||
{
|
||||
$namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance';
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use Symfony\Component\Routing\Route;
|
|||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Yaml\Exception\ParseException;
|
||||
use Symfony\Component\Yaml\Parser as YamlParser;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* YamlFileLoader loads Yaml routing files.
|
||||
|
|
@ -26,9 +27,9 @@ use Symfony\Component\Yaml\Parser as YamlParser;
|
|||
*/
|
||||
class YamlFileLoader extends FileLoader
|
||||
{
|
||||
private static $availableKeys = array(
|
||||
'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller',
|
||||
);
|
||||
private static $availableKeys = [
|
||||
'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', 'name_prefix', 'trailing_slash_on_root', 'locale', 'format', 'utf8', 'exclude',
|
||||
];
|
||||
private $yamlParser;
|
||||
|
||||
/**
|
||||
|
|
@ -57,18 +58,10 @@ class YamlFileLoader extends FileLoader
|
|||
$this->yamlParser = new YamlParser();
|
||||
}
|
||||
|
||||
$prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($file, &$prevErrorHandler) {
|
||||
$message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$file.'"$0', $message) : $message;
|
||||
|
||||
return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false;
|
||||
});
|
||||
|
||||
try {
|
||||
$parsedConfig = $this->yamlParser->parseFile($path);
|
||||
$parsedConfig = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT);
|
||||
} catch (ParseException $e) {
|
||||
throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
$collection = new RouteCollection();
|
||||
|
|
@ -102,71 +95,138 @@ class YamlFileLoader extends FileLoader
|
|||
*/
|
||||
public function supports($resource, $type = null)
|
||||
{
|
||||
return \is_string($resource) && \in_array(pathinfo($resource, PATHINFO_EXTENSION), array('yml', 'yaml'), true) && (!$type || 'yaml' === $type);
|
||||
return \is_string($resource) && \in_array(pathinfo($resource, PATHINFO_EXTENSION), ['yml', 'yaml'], true) && (!$type || 'yaml' === $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a route and adds it to the RouteCollection.
|
||||
*
|
||||
* @param RouteCollection $collection A RouteCollection instance
|
||||
* @param string $name Route name
|
||||
* @param array $config Route definition
|
||||
* @param string $path Full path of the YAML file being processed
|
||||
* @param string $name Route name
|
||||
* @param array $config Route definition
|
||||
* @param string $path Full path of the YAML file being processed
|
||||
*/
|
||||
protected function parseRoute(RouteCollection $collection, $name, array $config, $path)
|
||||
{
|
||||
$defaults = isset($config['defaults']) ? $config['defaults'] : array();
|
||||
$requirements = isset($config['requirements']) ? $config['requirements'] : array();
|
||||
$options = isset($config['options']) ? $config['options'] : array();
|
||||
$defaults = isset($config['defaults']) ? $config['defaults'] : [];
|
||||
$requirements = isset($config['requirements']) ? $config['requirements'] : [];
|
||||
$options = isset($config['options']) ? $config['options'] : [];
|
||||
$host = isset($config['host']) ? $config['host'] : '';
|
||||
$schemes = isset($config['schemes']) ? $config['schemes'] : array();
|
||||
$methods = isset($config['methods']) ? $config['methods'] : array();
|
||||
$schemes = isset($config['schemes']) ? $config['schemes'] : [];
|
||||
$methods = isset($config['methods']) ? $config['methods'] : [];
|
||||
$condition = isset($config['condition']) ? $config['condition'] : null;
|
||||
|
||||
foreach ($requirements as $placeholder => $requirement) {
|
||||
if (\is_int($placeholder)) {
|
||||
@trigger_error(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config['controller'])) {
|
||||
$defaults['_controller'] = $config['controller'];
|
||||
}
|
||||
if (isset($config['locale'])) {
|
||||
$defaults['_locale'] = $config['locale'];
|
||||
}
|
||||
if (isset($config['format'])) {
|
||||
$defaults['_format'] = $config['format'];
|
||||
}
|
||||
if (isset($config['utf8'])) {
|
||||
$options['utf8'] = $config['utf8'];
|
||||
}
|
||||
|
||||
$route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
if (\is_array($config['path'])) {
|
||||
$route = new Route('', $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
|
||||
$collection->add($name, $route);
|
||||
foreach ($config['path'] as $locale => $path) {
|
||||
$localizedRoute = clone $route;
|
||||
$localizedRoute->setDefault('_locale', $locale);
|
||||
$localizedRoute->setDefault('_canonical_route', $name);
|
||||
$localizedRoute->setPath($path);
|
||||
$collection->add($name.'.'.$locale, $localizedRoute);
|
||||
}
|
||||
} else {
|
||||
$route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
$collection->add($name, $route);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an import and adds the routes in the resource to the RouteCollection.
|
||||
*
|
||||
* @param RouteCollection $collection A RouteCollection instance
|
||||
* @param array $config Route definition
|
||||
* @param string $path Full path of the YAML file being processed
|
||||
* @param string $file Loaded file name
|
||||
* @param array $config Route definition
|
||||
* @param string $path Full path of the YAML file being processed
|
||||
* @param string $file Loaded file name
|
||||
*/
|
||||
protected function parseImport(RouteCollection $collection, array $config, $path, $file)
|
||||
{
|
||||
$type = isset($config['type']) ? $config['type'] : null;
|
||||
$prefix = isset($config['prefix']) ? $config['prefix'] : '';
|
||||
$defaults = isset($config['defaults']) ? $config['defaults'] : array();
|
||||
$requirements = isset($config['requirements']) ? $config['requirements'] : array();
|
||||
$options = isset($config['options']) ? $config['options'] : array();
|
||||
$defaults = isset($config['defaults']) ? $config['defaults'] : [];
|
||||
$requirements = isset($config['requirements']) ? $config['requirements'] : [];
|
||||
$options = isset($config['options']) ? $config['options'] : [];
|
||||
$host = isset($config['host']) ? $config['host'] : null;
|
||||
$condition = isset($config['condition']) ? $config['condition'] : null;
|
||||
$schemes = isset($config['schemes']) ? $config['schemes'] : null;
|
||||
$methods = isset($config['methods']) ? $config['methods'] : null;
|
||||
$trailingSlashOnRoot = $config['trailing_slash_on_root'] ?? true;
|
||||
$exclude = $config['exclude'] ?? null;
|
||||
|
||||
if (isset($config['controller'])) {
|
||||
$defaults['_controller'] = $config['controller'];
|
||||
}
|
||||
if (isset($config['locale'])) {
|
||||
$defaults['_locale'] = $config['locale'];
|
||||
}
|
||||
if (isset($config['format'])) {
|
||||
$defaults['_format'] = $config['format'];
|
||||
}
|
||||
if (isset($config['utf8'])) {
|
||||
$options['utf8'] = $config['utf8'];
|
||||
}
|
||||
|
||||
$this->setCurrentDir(\dirname($path));
|
||||
|
||||
$imported = $this->import($config['resource'], $type, false, $file);
|
||||
$imported = $this->import($config['resource'], $type, false, $file, $exclude) ?: [];
|
||||
|
||||
if (!\is_array($imported)) {
|
||||
$imported = array($imported);
|
||||
$imported = [$imported];
|
||||
}
|
||||
|
||||
foreach ($imported as $subCollection) {
|
||||
/* @var $subCollection RouteCollection */
|
||||
$subCollection->addPrefix($prefix);
|
||||
if (!\is_array($prefix)) {
|
||||
$subCollection->addPrefix($prefix);
|
||||
if (!$trailingSlashOnRoot) {
|
||||
$rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath();
|
||||
foreach ($subCollection->all() as $route) {
|
||||
if ($route->getPath() === $rootPath) {
|
||||
$route->setPath(rtrim($rootPath, '/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($prefix as $locale => $localePrefix) {
|
||||
$prefix[$locale] = trim(trim($localePrefix), '/');
|
||||
}
|
||||
foreach ($subCollection->all() as $name => $route) {
|
||||
if (null === $locale = $route->getDefault('_locale')) {
|
||||
$subCollection->remove($name);
|
||||
foreach ($prefix as $locale => $localePrefix) {
|
||||
$localizedRoute = clone $route;
|
||||
$localizedRoute->setDefault('_locale', $locale);
|
||||
$localizedRoute->setDefault('_canonical_route', $name);
|
||||
$localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
|
||||
$subCollection->add($name.'.'.$locale, $localizedRoute);
|
||||
}
|
||||
} elseif (!isset($prefix[$locale])) {
|
||||
throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix when imported in "%s".', $name, $locale, $file));
|
||||
} else {
|
||||
$route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
|
||||
$subCollection->add($name, $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $host) {
|
||||
$subCollection->setHost($host);
|
||||
}
|
||||
|
|
@ -183,6 +243,10 @@ class YamlFileLoader extends FileLoader
|
|||
$subCollection->addRequirements($requirements);
|
||||
$subCollection->addOptions($options);
|
||||
|
||||
if (isset($config['name_prefix'])) {
|
||||
$subCollection->addNamePrefix($config['name_prefix']);
|
||||
}
|
||||
|
||||
$collection->addCollection($subCollection);
|
||||
}
|
||||
}
|
||||
|
|
@ -203,28 +267,16 @@ class YamlFileLoader extends FileLoader
|
|||
throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path));
|
||||
}
|
||||
if ($extraKeys = array_diff(array_keys($config), self::$availableKeys)) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".',
|
||||
$path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys)
|
||||
));
|
||||
throw new \InvalidArgumentException(sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys)));
|
||||
}
|
||||
if (isset($config['resource']) && isset($config['path'])) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.',
|
||||
$path, $name
|
||||
));
|
||||
throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name));
|
||||
}
|
||||
if (!isset($config['resource']) && isset($config['type'])) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.',
|
||||
$name, $path
|
||||
));
|
||||
throw new \InvalidArgumentException(sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path));
|
||||
}
|
||||
if (!isset($config['resource']) && !isset($config['path'])) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'You must define a "path" for the route "%s" in file "%s".',
|
||||
$name, $path
|
||||
));
|
||||
throw new \InvalidArgumentException(sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path));
|
||||
}
|
||||
if (isset($config['controller']) && isset($config['defaults']['_controller'])) {
|
||||
throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name));
|
||||
|
|
|
|||
|
|
@ -24,6 +24,14 @@
|
|||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="localized-path">
|
||||
<xsd:simpleContent>
|
||||
<xsd:extension base="xsd:string">
|
||||
<xsd:attribute name="locale" type="xsd:string" use="required" />
|
||||
</xsd:extension>
|
||||
</xsd:simpleContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:group name="configs">
|
||||
<xsd:choice>
|
||||
<xsd:element name="default" nillable="true" type="default" />
|
||||
|
|
@ -34,26 +42,40 @@
|
|||
</xsd:group>
|
||||
|
||||
<xsd:complexType name="route">
|
||||
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
||||
|
||||
<xsd:sequence>
|
||||
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="path" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="path" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="path" type="xsd:string" />
|
||||
<xsd:attribute name="host" type="xsd:string" />
|
||||
<xsd:attribute name="schemes" type="xsd:string" />
|
||||
<xsd:attribute name="methods" type="xsd:string" />
|
||||
<xsd:attribute name="controller" type="xsd:string" />
|
||||
<xsd:attribute name="locale" type="xsd:string" />
|
||||
<xsd:attribute name="format" type="xsd:string" />
|
||||
<xsd:attribute name="utf8" type="xsd:boolean" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="import">
|
||||
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
||||
|
||||
<xsd:sequence maxOccurs="unbounded" minOccurs="0">
|
||||
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="prefix" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="exclude" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="resource" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="exclude" type="xsd:string" />
|
||||
<xsd:attribute name="prefix" type="xsd:string" />
|
||||
<xsd:attribute name="name-prefix" type="xsd:string" />
|
||||
<xsd:attribute name="host" type="xsd:string" />
|
||||
<xsd:attribute name="schemes" type="xsd:string" />
|
||||
<xsd:attribute name="methods" type="xsd:string" />
|
||||
<xsd:attribute name="controller" type="xsd:string" />
|
||||
<xsd:attribute name="locale" type="xsd:string" />
|
||||
<xsd:attribute name="format" type="xsd:string" />
|
||||
<xsd:attribute name="trailing-slash-on-root" type="xsd:boolean" />
|
||||
<xsd:attribute name="utf8" type="xsd:boolean" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="default" mixed="true">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue