2010-01-04 14:26:20 +00:00
< ? php
/*
2011-01-15 13:29:43 +00:00
* This file is part of the Symfony package .
2010-01-04 14:26:20 +00:00
*
2011-03-06 11:40:06 +00:00
* ( c ) Fabien Potencier < fabien @ symfony . com >
2010-01-04 14:26:20 +00:00
*
2011-01-15 13:29:43 +00:00
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
2010-01-04 14:26:20 +00:00
*/
2011-01-15 13:29:43 +00:00
namespace Symfony\Component\DependencyInjection\Loader ;
2017-02-03 19:41:28 +00:00
use Symfony\Component\DependencyInjection\ChildDefinition ;
2011-01-15 13:29:43 +00:00
use Symfony\Component\DependencyInjection\ContainerBuilder ;
2017-01-14 11:46:46 +00:00
use Symfony\Component\DependencyInjection\Definition ;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException ;
2011-02-10 15:15:51 +00:00
use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader ;
2012-08-07 08:39:30 +01:00
use Symfony\Component\Config\FileLocatorInterface ;
2011-01-15 13:29:43 +00:00
2010-01-04 14:26:20 +00:00
/**
* FileLoader is the abstract class used by all built - in loaders that are file based .
*
2011-03-06 11:40:06 +00:00
* @ author Fabien Potencier < fabien @ symfony . com >
2010-01-04 14:26:20 +00:00
*/
2011-02-10 15:15:51 +00:00
abstract class FileLoader extends BaseFileLoader
2010-01-04 14:26:20 +00:00
{
2011-02-10 15:15:51 +00:00
protected $container ;
2017-02-03 19:41:28 +00:00
protected $isLoadingInstanceof = false ;
protected $instanceof = array ();
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
/**
2014-10-13 20:09:32 +01:00
* @ param ContainerBuilder $container A ContainerBuilder instance
* @ param FileLocatorInterface $locator A FileLocator instance
2010-05-06 12:25:53 +01:00
*/
2012-08-07 08:39:30 +01:00
public function __construct ( ContainerBuilder $container , FileLocatorInterface $locator )
2010-01-04 14:26:20 +00:00
{
2011-02-10 15:15:51 +00:00
$this -> container = $container ;
2010-07-16 08:12:58 +01:00
2011-02-10 15:15:51 +00:00
parent :: __construct ( $locator );
2010-07-18 10:26:47 +01:00
}
2017-01-14 11:46:46 +00:00
/**
* Registers a set of classes as services using PSR - 4 for discovery .
*
* @ param Definition $prototype A definition to use as template
* @ param string $namespace The namespace prefix of classes in the scanned directory
* @ param string $resource The directory to look for classes , glob - patterns allowed
*/
public function registerClasses ( Definition $prototype , $namespace , $resource )
{
if ( '\\' !== substr ( $namespace , - 1 )) {
throw new InvalidArgumentException ( sprintf ( 'Namespace prefix must end with a "\\": %s.' , $namespace ));
}
if ( ! preg_match ( '/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\\\)++$/' , $namespace )) {
throw new InvalidArgumentException ( sprintf ( 'Namespace is not a valid PSR-4 prefix: %s.' , $namespace ));
}
$classes = $this -> findClasses ( $namespace , $resource );
// prepare for deep cloning
$prototype = serialize ( $prototype );
foreach ( $classes as $class ) {
2017-02-03 19:41:28 +00:00
$this -> setDefinition ( $class , unserialize ( $prototype ));
}
}
/**
2017-04-05 08:26:56 +01:00
* Registers a definition in the container with its instanceof - conditionals .
*
* @ param string $id
* @ param Definition $definition
2017-02-03 19:41:28 +00:00
*/
protected function setDefinition ( $id , Definition $definition )
{
if ( $this -> isLoadingInstanceof ) {
if ( ! $definition instanceof ChildDefinition ) {
throw new InvalidArgumentException ( sprintf ( 'Invalid type definition "%s": ChildDefinition expected, "%s" given.' , $id , get_class ( $definition )));
}
$this -> instanceof [ $id ] = $definition ;
} else {
$this -> container -> setDefinition ( $id , $definition -> setInstanceofConditionals ( $this -> instanceof ));
2017-01-14 11:46:46 +00:00
}
}
private function findClasses ( $namespace , $resource )
{
2017-04-11 11:58:51 +01:00
$parameterBag = $this -> container -> getParameterBag ();
$resource = $parameterBag -> unescapeValue ( $parameterBag -> resolveValue ( $resource ));
2017-01-14 11:46:46 +00:00
$classes = array ();
$extRegexp = defined ( 'HHVM_VERSION' ) ? '/\\.(?:php|hh)$/' : '/\\.php$/' ;
2017-02-15 13:40:32 +00:00
$prefixLen = null ;
foreach ( $this -> glob ( $resource , true , $prefix ) as $path => $info ) {
if ( null === $prefixLen ) {
$prefixLen = strlen ( $prefix );
}
2017-01-14 11:46:46 +00:00
2017-01-17 13:46:23 +00:00
if ( ! preg_match ( $extRegexp , $path , $m ) || ! $info -> isReadable ()) {
2017-01-14 11:46:46 +00:00
continue ;
}
$class = $namespace . ltrim ( str_replace ( '/' , '\\' , substr ( $path , $prefixLen , - strlen ( $m [ 0 ]))), '\\' );
if ( ! preg_match ( '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/' , $class )) {
continue ;
}
2017-04-26 04:23:29 +01:00
// check to make sure the expected class exists
if ( ! $r = $this -> container -> getReflectionClass ( $class )) {
throw new InvalidArgumentException ( sprintf ( 'Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.' , $class , $path , $resource ));
2017-01-14 11:46:46 +00:00
}
if ( ! $r -> isInterface () && ! $r -> isTrait ()) {
$classes [] = $class ;
}
}
2017-02-15 13:40:32 +00:00
if ( null !== $prefix ) {
// track directories only for new & removed files
$this -> container -> fileExists ( $prefix , '/^$/' );
2017-01-14 11:46:46 +00:00
}
2017-02-15 13:40:32 +00:00
return $classes ;
2017-01-14 11:46:46 +00:00
}
2010-01-04 14:26:20 +00:00
}