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\DependencyInjection\ParameterBag ;
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException ;
2015-08-18 00:00:26 +00:00
use Symfony\Component\DependencyInjection\Exception\RuntimeException ;
/**
* Holds parameters .
*
* @ author Fabien Potencier < fabien @ symfony . com >
*/
class ParameterBag implements ParameterBagInterface
{
protected $parameters = array ();
protected $resolved = false ;
2018-11-23 12:29:20 +00:00
private $normalizedNames = array ();
2015-08-18 00:00:26 +00:00
/**
* @ param array $parameters An array of parameters
*/
public function __construct ( array $parameters = array ())
{
$this -> add ( $parameters );
}
/**
* Clears all parameters .
*/
public function clear ()
{
$this -> parameters = array ();
}
/**
* Adds parameters to the service container parameters .
*
* @ param array $parameters An array of parameters
*/
public function add ( array $parameters )
{
foreach ( $parameters as $key => $value ) {
2018-11-23 12:29:20 +00:00
$this -> set ( $key , $value );
2015-08-18 00:00:26 +00:00
}
}
/**
2017-02-03 00:28:38 +00:00
* { @ inheritdoc }
2015-08-18 00:00:26 +00:00
*/
public function all ()
{
return $this -> parameters ;
}
/**
2017-02-03 00:28:38 +00:00
* { @ inheritdoc }
2015-08-18 00:00:26 +00:00
*/
public function get ( $name )
{
2018-11-23 12:29:20 +00:00
$name = $this -> normalizeName ( $name );
2015-08-18 00:00:26 +00:00
if ( ! array_key_exists ( $name , $this -> parameters )) {
if ( ! $name ) {
throw new ParameterNotFoundException ( $name );
}
$alternatives = array ();
foreach ( $this -> parameters as $key => $parameterValue ) {
$lev = levenshtein ( $name , $key );
2018-11-23 12:29:20 +00:00
if ( $lev <= \strlen ( $name ) / 3 || false !== strpos ( $key , $name )) {
2015-08-18 00:00:26 +00:00
$alternatives [] = $key ;
}
}
2018-11-23 12:29:20 +00:00
$nonNestedAlternative = null ;
if ( ! \count ( $alternatives ) && false !== strpos ( $name , '.' )) {
$namePartsLength = array_map ( 'strlen' , explode ( '.' , $name ));
$key = substr ( $name , 0 , - 1 * ( 1 + array_pop ( $namePartsLength )));
while ( \count ( $namePartsLength )) {
if ( $this -> has ( $key )) {
if ( \is_array ( $this -> get ( $key ))) {
$nonNestedAlternative = $key ;
}
break ;
}
$key = substr ( $key , 0 , - 1 * ( 1 + array_pop ( $namePartsLength )));
}
}
throw new ParameterNotFoundException ( $name , null , null , null , $alternatives , $nonNestedAlternative );
2015-08-18 00:00:26 +00:00
}
return $this -> parameters [ $name ];
}
/**
* Sets a service container parameter .
*
* @ param string $name The parameter name
* @ param mixed $value The parameter value
*/
public function set ( $name , $value )
{
2018-11-23 12:29:20 +00:00
$this -> parameters [ $this -> normalizeName ( $name )] = $value ;
2015-08-18 00:00:26 +00:00
}
/**
2017-02-03 00:28:38 +00:00
* { @ inheritdoc }
2015-08-18 00:00:26 +00:00
*/
public function has ( $name )
{
2018-11-23 12:29:20 +00:00
return array_key_exists ( $this -> normalizeName ( $name ), $this -> parameters );
2015-08-18 00:00:26 +00:00
}
/**
* Removes a parameter .
*
* @ param string $name The parameter name
*/
public function remove ( $name )
{
2018-11-23 12:29:20 +00:00
unset ( $this -> parameters [ $this -> normalizeName ( $name )]);
2015-08-18 00:00:26 +00:00
}
/**
2017-02-03 00:28:38 +00:00
* { @ inheritdoc }
2015-08-18 00:00:26 +00:00
*/
public function resolve ()
{
if ( $this -> resolved ) {
return ;
}
$parameters = array ();
foreach ( $this -> parameters as $key => $value ) {
try {
$value = $this -> resolveValue ( $value );
$parameters [ $key ] = $this -> unescapeValue ( $value );
} catch ( ParameterNotFoundException $e ) {
$e -> setSourceKey ( $key );
throw $e ;
}
}
$this -> parameters = $parameters ;
$this -> resolved = true ;
}
/**
* Replaces parameter placeholders ( % name % ) by their values .
*
* @ param mixed $value A value
* @ param array $resolving An array of keys that are being resolved ( used internally to detect circular references )
*
* @ return mixed The resolved value
*
* @ throws ParameterNotFoundException if a placeholder references a parameter that does not exist
* @ throws ParameterCircularReferenceException if a circular reference if detected
2018-11-23 12:29:20 +00:00
* @ throws RuntimeException when a given parameter has a type problem
2015-08-18 00:00:26 +00:00
*/
public function resolveValue ( $value , array $resolving = array ())
{
2018-11-23 12:29:20 +00:00
if ( \is_array ( $value )) {
2015-08-18 00:00:26 +00:00
$args = array ();
foreach ( $value as $k => $v ) {
2018-11-23 12:29:20 +00:00
$args [ \is_string ( $k ) ? $this -> resolveValue ( $k , $resolving ) : $k ] = $this -> resolveValue ( $v , $resolving );
2015-08-18 00:00:26 +00:00
}
return $args ;
}
2018-11-23 12:29:20 +00:00
if ( ! \is_string ( $value ) || 2 > \strlen ( $value )) {
2015-08-18 00:00:26 +00:00
return $value ;
}
return $this -> resolveString ( $value , $resolving );
}
/**
* Resolves parameters inside a string .
*
* @ param string $value The string to resolve
* @ param array $resolving An array of keys that are being resolved ( used internally to detect circular references )
*
* @ return string The resolved string
*
* @ throws ParameterNotFoundException if a placeholder references a parameter that does not exist
* @ throws ParameterCircularReferenceException if a circular reference if detected
2018-11-23 12:29:20 +00:00
* @ throws RuntimeException when a given parameter has a type problem
2015-08-18 00:00:26 +00:00
*/
public function resolveString ( $value , array $resolving = array ())
{
// we do this to deal with non string values (Boolean, integer, ...)
// as the preg_replace_callback throw an exception when trying
// a non-string in a parameter value
if ( preg_match ( '/^%([^%\s]+)%$/' , $value , $match )) {
2018-11-23 12:29:20 +00:00
$key = $match [ 1 ];
$lcKey = strtolower ( $key ); // strtolower() to be removed in 4.0
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
if ( isset ( $resolving [ $lcKey ])) {
2015-08-18 00:00:26 +00:00
throw new ParameterCircularReferenceException ( array_keys ( $resolving ));
}
2018-11-23 12:29:20 +00:00
$resolving [ $lcKey ] = true ;
2015-08-18 00:00:26 +00:00
return $this -> resolved ? $this -> get ( $key ) : $this -> resolveValue ( $this -> get ( $key ), $resolving );
}
2018-11-23 12:29:20 +00:00
return preg_replace_callback ( '/%%|%([^%\s]+)%/' , function ( $match ) use ( $resolving , $value ) {
2015-08-18 00:00:26 +00:00
// skip %%
if ( ! isset ( $match [ 1 ])) {
return '%%' ;
}
2018-11-23 12:29:20 +00:00
$key = $match [ 1 ];
$lcKey = strtolower ( $key ); // strtolower() to be removed in 4.0
if ( isset ( $resolving [ $lcKey ])) {
2015-08-18 00:00:26 +00:00
throw new ParameterCircularReferenceException ( array_keys ( $resolving ));
}
2018-11-23 12:29:20 +00:00
$resolved = $this -> get ( $key );
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
if ( ! \is_string ( $resolved ) && ! is_numeric ( $resolved )) {
throw new RuntimeException ( sprintf ( 'A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".' , $key , \gettype ( $resolved ), $value ));
2015-08-18 00:00:26 +00:00
}
$resolved = ( string ) $resolved ;
2018-11-23 12:29:20 +00:00
$resolving [ $lcKey ] = true ;
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
return $this -> isResolved () ? $resolved : $this -> resolveString ( $resolved , $resolving );
2015-08-18 00:00:26 +00:00
}, $value );
}
public function isResolved ()
{
return $this -> resolved ;
}
/**
* { @ inheritdoc }
*/
public function escapeValue ( $value )
{
2018-11-23 12:29:20 +00:00
if ( \is_string ( $value )) {
2015-08-18 00:00:26 +00:00
return str_replace ( '%' , '%%' , $value );
}
2018-11-23 12:29:20 +00:00
if ( \is_array ( $value )) {
2015-08-18 00:00:26 +00:00
$result = array ();
foreach ( $value as $k => $v ) {
$result [ $k ] = $this -> escapeValue ( $v );
}
return $result ;
}
return $value ;
}
2017-02-03 00:28:38 +00:00
/**
* { @ inheritdoc }
*/
2015-08-18 00:00:26 +00:00
public function unescapeValue ( $value )
{
2018-11-23 12:29:20 +00:00
if ( \is_string ( $value )) {
2015-08-18 00:00:26 +00:00
return str_replace ( '%%' , '%' , $value );
}
2018-11-23 12:29:20 +00:00
if ( \is_array ( $value )) {
2015-08-18 00:00:26 +00:00
$result = array ();
foreach ( $value as $k => $v ) {
$result [ $k ] = $this -> unescapeValue ( $v );
}
return $result ;
}
return $value ;
}
2018-11-23 12:29:20 +00:00
private function normalizeName ( $name )
{
if ( isset ( $this -> normalizedNames [ $normalizedName = strtolower ( $name )])) {
$normalizedName = $this -> normalizedNames [ $normalizedName ];
if (( string ) $name !== $normalizedName ) {
@ trigger_error ( sprintf ( 'Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.4.' , $name , $normalizedName ), E_USER_DEPRECATED );
}
} else {
$normalizedName = $this -> normalizedNames [ $normalizedName ] = ( string ) $name ;
}
return $normalizedName ;
}
2015-08-18 00:00:26 +00:00
}