2015-08-18 00:00:26 +00:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . com >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Symfony\Component\Routing\Loader ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Config\Loader\FileLoader ;
2015-08-18 00:00:26 +00:00
use Symfony\Component\Config\Resource\FileResource ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Routing\Route ;
use Symfony\Component\Routing\RouteCollection ;
2015-10-08 18:40:12 +00:00
use Symfony\Component\Yaml\Exception\ParseException ;
2015-08-18 00:00:26 +00:00
use Symfony\Component\Yaml\Parser as YamlParser ;
/**
* YamlFileLoader loads Yaml routing files .
*
* @ author Fabien Potencier < fabien @ symfony . com >
* @ author Tobias Schultze < http :// tobion . de >
*/
class YamlFileLoader extends FileLoader
{
private static $availableKeys = array (
2018-11-23 12:29:20 +00:00
'resource' , 'type' , 'prefix' , 'path' , 'host' , 'schemes' , 'methods' , 'defaults' , 'requirements' , 'options' , 'condition' , 'controller' ,
2015-08-18 00:00:26 +00:00
);
private $yamlParser ;
/**
* Loads a Yaml file .
*
* @ param string $file A Yaml file path
* @ param string | null $type The resource type
*
* @ return RouteCollection A RouteCollection instance
*
* @ throws \InvalidArgumentException When a route can ' t be parsed because YAML is invalid
*/
public function load ( $file , $type = null )
{
$path = $this -> locator -> locate ( $file );
if ( ! stream_is_local ( $path )) {
throw new \InvalidArgumentException ( sprintf ( 'This is not a local file "%s".' , $path ));
}
if ( ! file_exists ( $path )) {
throw new \InvalidArgumentException ( sprintf ( 'File "%s" not found.' , $path ));
}
if ( null === $this -> yamlParser ) {
$this -> yamlParser = new YamlParser ();
}
2018-11-23 12:29:20 +00:00
$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 ;
});
2015-10-08 18:40:12 +00:00
try {
2018-11-23 12:29:20 +00:00
$parsedConfig = $this -> yamlParser -> parseFile ( $path );
2015-10-08 18:40:12 +00:00
} catch ( ParseException $e ) {
throw new \InvalidArgumentException ( sprintf ( 'The file "%s" does not contain valid YAML.' , $path ), 0 , $e );
2018-11-23 12:29:20 +00:00
} finally {
restore_error_handler ();
2015-10-08 18:40:12 +00:00
}
2015-08-18 00:00:26 +00:00
$collection = new RouteCollection ();
$collection -> addResource ( new FileResource ( $path ));
// empty file
2015-11-17 21:42:33 +00:00
if ( null === $parsedConfig ) {
2015-08-18 00:00:26 +00:00
return $collection ;
}
// not an array
2018-11-23 12:29:20 +00:00
if ( ! \is_array ( $parsedConfig )) {
2015-08-18 00:00:26 +00:00
throw new \InvalidArgumentException ( sprintf ( 'The file "%s" must contain a YAML array.' , $path ));
}
2015-11-17 21:42:33 +00:00
foreach ( $parsedConfig as $name => $config ) {
2015-08-18 00:00:26 +00:00
$this -> validate ( $config , $name , $path );
if ( isset ( $config [ 'resource' ])) {
$this -> parseImport ( $collection , $config , $path , $file );
} else {
$this -> parseRoute ( $collection , $name , $config , $path );
}
}
return $collection ;
}
/**
* { @ inheritdoc }
*/
public function supports ( $resource , $type = null )
{
2018-11-23 12:29:20 +00:00
return \is_string ( $resource ) && \in_array ( pathinfo ( $resource , PATHINFO_EXTENSION ), array ( 'yml' , 'yaml' ), true ) && ( ! $type || 'yaml' === $type );
2015-08-18 00:00:26 +00:00
}
/**
* 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
*/
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 ();
$host = isset ( $config [ 'host' ]) ? $config [ 'host' ] : '' ;
$schemes = isset ( $config [ 'schemes' ]) ? $config [ 'schemes' ] : array ();
$methods = isset ( $config [ 'methods' ]) ? $config [ 'methods' ] : array ();
$condition = isset ( $config [ 'condition' ]) ? $config [ 'condition' ] : null ;
2018-11-23 12:29:20 +00:00
if ( isset ( $config [ 'controller' ])) {
$defaults [ '_controller' ] = $config [ 'controller' ];
2015-08-27 19:03:05 +00:00
}
2015-08-18 00:00:26 +00:00
$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
*/
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 ();
$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 ;
2018-11-23 12:29:20 +00:00
if ( isset ( $config [ 'controller' ])) {
$defaults [ '_controller' ] = $config [ 'controller' ];
2015-08-18 00:00:26 +00:00
}
2018-11-23 12:29:20 +00:00
$this -> setCurrentDir ( \dirname ( $path ));
$imported = $this -> import ( $config [ 'resource' ], $type , false , $file );
if ( ! \is_array ( $imported )) {
$imported = array ( $imported );
2015-08-18 00:00:26 +00:00
}
2018-11-23 12:29:20 +00:00
foreach ( $imported as $subCollection ) {
/* @var $subCollection RouteCollection */
$subCollection -> addPrefix ( $prefix );
if ( null !== $host ) {
$subCollection -> setHost ( $host );
}
if ( null !== $condition ) {
$subCollection -> setCondition ( $condition );
}
if ( null !== $schemes ) {
$subCollection -> setSchemes ( $schemes );
}
if ( null !== $methods ) {
$subCollection -> setMethods ( $methods );
}
$subCollection -> addDefaults ( $defaults );
$subCollection -> addRequirements ( $requirements );
$subCollection -> addOptions ( $options );
$collection -> addCollection ( $subCollection );
}
2015-08-18 00:00:26 +00:00
}
/**
* Validates the route configuration .
*
* @ param array $config A resource config
* @ param string $name The config key
* @ param string $path The loaded file path
*
* @ throws \InvalidArgumentException If one of the provided config keys is not supported ,
* something is missing or the combination is nonsense
*/
protected function validate ( $config , $name , $path )
{
2018-11-23 12:29:20 +00:00
if ( ! \is_array ( $config )) {
2015-08-18 00:00:26 +00:00
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 )) {
2018-11-23 12:29:20 +00:00
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 )));
2015-08-18 00:00:26 +00:00
}
if ( isset ( $config [ 'resource' ]) && isset ( $config [ 'path' ])) {
2018-11-23 12:29:20 +00:00
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 ));
2015-08-18 00:00:26 +00:00
}
if ( ! isset ( $config [ 'resource' ]) && isset ( $config [ 'type' ])) {
2018-11-23 12:29:20 +00:00
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 ));
2015-08-18 00:00:26 +00:00
}
if ( ! isset ( $config [ 'resource' ]) && ! isset ( $config [ 'path' ])) {
2018-11-23 12:29:20 +00:00
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 ));
2015-08-18 00:00:26 +00:00
}
}
}