2015-08-17 17:00:26 -07: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\Dumper ;
use Symfony\Component\DependencyInjection\Alias ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface ;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument ;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument ;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument ;
2015-08-17 17:00:26 -07:00
use Symfony\Component\DependencyInjection\ContainerInterface ;
use Symfony\Component\DependencyInjection\Definition ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\DependencyInjection\Exception\RuntimeException ;
2015-08-17 17:00:26 -07:00
use Symfony\Component\DependencyInjection\Parameter ;
use Symfony\Component\DependencyInjection\Reference ;
use Symfony\Component\ExpressionLanguage\Expression ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Yaml\Dumper as YmlDumper ;
use Symfony\Component\Yaml\Parser ;
use Symfony\Component\Yaml\Tag\TaggedValue ;
use Symfony\Component\Yaml\Yaml ;
2015-08-17 17:00:26 -07:00
/**
* YamlDumper dumps a service container as a YAML string .
*
* @ author Fabien Potencier < fabien @ symfony . com >
*/
class YamlDumper extends Dumper
{
private $dumper ;
/**
* Dumps the service container as an YAML string .
*
* @ return string A YAML string representing of the service container
*/
public function dump ( array $options = array ())
{
if ( ! class_exists ( 'Symfony\Component\Yaml\Dumper' )) {
throw new RuntimeException ( 'Unable to dump the container as the Symfony Yaml Component is not installed.' );
}
if ( null === $this -> dumper ) {
$this -> dumper = new YmlDumper ();
}
2018-11-23 12:29:20 +00:00
return $this -> container -> resolveEnvPlaceholders ( $this -> addParameters () . " \n " . $this -> addServices ());
2015-08-17 17:00:26 -07:00
}
/**
* Adds a service .
*
* @ param string $id
* @ param Definition $definition
*
* @ return string
*/
2018-11-23 12:29:20 +00:00
private function addService ( $id , Definition $definition )
2015-08-17 17:00:26 -07:00
{
$code = " $id : \n " ;
2015-10-08 11:40:12 -07:00
if ( $class = $definition -> getClass ()) {
if ( '\\' === substr ( $class , 0 , 1 )) {
$class = substr ( $class , 1 );
}
2016-04-20 09:56:34 -07:00
$code .= sprintf ( " class: %s \n " , $this -> dumper -> dump ( $class ));
2015-08-17 17:00:26 -07:00
}
2018-11-23 12:29:20 +00:00
if ( ! $definition -> isPrivate ()) {
$code .= sprintf ( " public: %s \n " , $definition -> isPublic () ? 'true' : 'false' );
2015-08-17 17:00:26 -07:00
}
$tagsCode = '' ;
foreach ( $definition -> getTags () as $name => $tags ) {
foreach ( $tags as $attributes ) {
$att = array ();
foreach ( $attributes as $key => $value ) {
$att [] = sprintf ( '%s: %s' , $this -> dumper -> dump ( $key ), $this -> dumper -> dump ( $value ));
}
$att = $att ? ', ' . implode ( ', ' , $att ) : '' ;
$tagsCode .= sprintf ( " - { name: %s%s } \n " , $this -> dumper -> dump ( $name ), $att );
}
}
if ( $tagsCode ) {
$code .= " tags: \n " . $tagsCode ;
}
if ( $definition -> getFile ()) {
2016-04-20 09:56:34 -07:00
$code .= sprintf ( " file: %s \n " , $this -> dumper -> dump ( $definition -> getFile ()));
2015-08-17 17:00:26 -07:00
}
if ( $definition -> isSynthetic ()) {
2017-07-03 16:47:07 +01:00
$code .= " synthetic: true \n " ;
2015-08-17 17:00:26 -07:00
}
2016-04-20 09:56:34 -07:00
if ( $definition -> isDeprecated ()) {
2018-11-23 12:29:20 +00:00
$code .= sprintf ( " deprecated: %s \n " , $this -> dumper -> dump ( $definition -> getDeprecationMessage ( '%service_id%' )));
2016-04-20 09:56:34 -07:00
}
if ( $definition -> isAutowired ()) {
$code .= " autowire: true \n " ;
}
$autowiringTypesCode = '' ;
2018-11-23 12:29:20 +00:00
foreach ( $definition -> getAutowiringTypes ( false ) as $autowiringType ) {
2016-04-20 09:56:34 -07:00
$autowiringTypesCode .= sprintf ( " - %s \n " , $this -> dumper -> dump ( $autowiringType ));
}
if ( $autowiringTypesCode ) {
$code .= sprintf ( " autowiring_types: \n %s " , $autowiringTypesCode );
}
2018-11-23 12:29:20 +00:00
if ( $definition -> isAutoconfigured ()) {
$code .= " autoconfigure: true \n " ;
2015-08-17 17:00:26 -07:00
}
2018-11-23 12:29:20 +00:00
if ( $definition -> isAbstract ()) {
$code .= " abstract: true \n " ;
2015-08-17 17:00:26 -07:00
}
2018-11-23 12:29:20 +00:00
if ( $definition -> isLazy ()) {
$code .= " lazy: true \n " ;
2015-08-17 17:00:26 -07:00
}
if ( $definition -> getArguments ()) {
$code .= sprintf ( " arguments: %s \n " , $this -> dumper -> dump ( $this -> dumpValue ( $definition -> getArguments ()), 0 ));
}
if ( $definition -> getProperties ()) {
$code .= sprintf ( " properties: %s \n " , $this -> dumper -> dump ( $this -> dumpValue ( $definition -> getProperties ()), 0 ));
}
if ( $definition -> getMethodCalls ()) {
$code .= sprintf ( " calls: \n %s \n " , $this -> dumper -> dump ( $this -> dumpValue ( $definition -> getMethodCalls ()), 1 , 12 ));
}
2016-04-20 09:56:34 -07:00
if ( ! $definition -> isShared ()) {
$code .= " shared: false \n " ;
}
2015-08-17 17:00:26 -07:00
if ( null !== $decorated = $definition -> getDecoratedService ()) {
2016-04-20 09:56:34 -07:00
list ( $decorated , $renamedId , $priority ) = $decorated ;
2015-08-17 17:00:26 -07:00
$code .= sprintf ( " decorates: %s \n " , $decorated );
if ( null !== $renamedId ) {
$code .= sprintf ( " decoration_inner_name: %s \n " , $renamedId );
}
2016-04-20 09:56:34 -07:00
if ( 0 !== $priority ) {
$code .= sprintf ( " decoration_priority: %s \n " , $priority );
}
2015-08-17 17:00:26 -07:00
}
if ( $callable = $definition -> getFactory ()) {
$code .= sprintf ( " factory: %s \n " , $this -> dumper -> dump ( $this -> dumpCallable ( $callable ), 0 ));
}
if ( $callable = $definition -> getConfigurator ()) {
$code .= sprintf ( " configurator: %s \n " , $this -> dumper -> dump ( $this -> dumpCallable ( $callable ), 0 ));
}
return $code ;
}
/**
* Adds a service alias .
*
* @ param string $alias
* @ param Alias $id
*
* @ return string
*/
2018-11-23 12:29:20 +00:00
private function addServiceAlias ( $alias , Alias $id )
2015-08-17 17:00:26 -07:00
{
2018-11-23 12:29:20 +00:00
if ( $id -> isPrivate ()) {
2015-11-17 13:42:33 -08:00
return sprintf ( " %s: '@%s' \n " , $alias , $id );
2015-08-17 17:00:26 -07:00
}
2015-11-17 13:42:33 -08:00
2018-11-23 12:29:20 +00:00
return sprintf ( " %s: \n alias: %s \n public: %s \n " , $alias , $id , $id -> isPublic () ? 'true' : 'false' );
2015-08-17 17:00:26 -07:00
}
/**
* Adds services .
*
* @ return string
*/
private function addServices ()
{
if ( ! $this -> container -> getDefinitions ()) {
return '' ;
}
$code = " services: \n " ;
foreach ( $this -> container -> getDefinitions () as $id => $definition ) {
$code .= $this -> addService ( $id , $definition );
}
$aliases = $this -> container -> getAliases ();
foreach ( $aliases as $alias => $id ) {
while ( isset ( $aliases [( string ) $id ])) {
$id = $aliases [( string ) $id ];
}
$code .= $this -> addServiceAlias ( $alias , $id );
}
return $code ;
}
/**
* Adds parameters .
*
* @ return string
*/
private function addParameters ()
{
if ( ! $this -> container -> getParameterBag () -> all ()) {
return '' ;
}
2018-11-23 12:29:20 +00:00
$parameters = $this -> prepareParameters ( $this -> container -> getParameterBag () -> all (), $this -> container -> isCompiled ());
2015-08-17 17:00:26 -07:00
return $this -> dumper -> dump ( array ( 'parameters' => $parameters ), 2 );
}
/**
2015-10-08 11:40:12 -07:00
* Dumps callable to YAML format .
2015-08-17 17:00:26 -07:00
*
* @ param callable $callable
*
* @ return callable
*/
private function dumpCallable ( $callable )
{
2018-11-23 12:29:20 +00:00
if ( \is_array ( $callable )) {
2015-08-17 17:00:26 -07:00
if ( $callable [ 0 ] instanceof Reference ) {
$callable = array ( $this -> getServiceCall (( string ) $callable [ 0 ], $callable [ 0 ]), $callable [ 1 ]);
} else {
$callable = array ( $callable [ 0 ], $callable [ 1 ]);
}
}
return $callable ;
}
/**
* Dumps the value to YAML format .
*
* @ param mixed $value
*
* @ return mixed
*
* @ throws RuntimeException When trying to dump object or resource
*/
private function dumpValue ( $value )
{
2018-11-23 12:29:20 +00:00
if ( $value instanceof ServiceClosureArgument ) {
$value = $value -> getValues ()[ 0 ];
}
if ( $value instanceof ArgumentInterface ) {
if ( $value instanceof TaggedIteratorArgument ) {
return new TaggedValue ( 'tagged' , $value -> getTag ());
}
if ( $value instanceof IteratorArgument ) {
$tag = 'iterator' ;
} else {
throw new RuntimeException ( sprintf ( 'Unspecified Yaml tag for type "%s".' , \get_class ( $value )));
}
return new TaggedValue ( $tag , $this -> dumpValue ( $value -> getValues ()));
}
if ( \is_array ( $value )) {
2015-08-17 17:00:26 -07:00
$code = array ();
foreach ( $value as $k => $v ) {
$code [ $k ] = $this -> dumpValue ( $v );
}
return $code ;
} elseif ( $value instanceof Reference ) {
return $this -> getServiceCall (( string ) $value , $value );
} elseif ( $value instanceof Parameter ) {
return $this -> getParameterCall (( string ) $value );
} elseif ( $value instanceof Expression ) {
return $this -> getExpressionCall (( string ) $value );
2018-11-23 12:29:20 +00:00
} elseif ( $value instanceof Definition ) {
return new TaggedValue ( 'service' , ( new Parser ()) -> parse ( " _: \n " . $this -> addService ( '_' , $value ), Yaml :: PARSE_CUSTOM_TAGS )[ '_' ][ '_' ]);
} elseif ( \is_object ( $value ) || \is_resource ( $value )) {
2015-08-17 17:00:26 -07:00
throw new RuntimeException ( 'Unable to dump a service container if a parameter is an object or a resource.' );
}
return $value ;
}
/**
* Gets the service call .
*
* @ param string $id
* @ param Reference $reference
*
* @ return string
*/
private function getServiceCall ( $id , Reference $reference = null )
{
2018-11-23 12:29:20 +00:00
if ( null !== $reference ) {
switch ( $reference -> getInvalidBehavior ()) {
case ContainerInterface :: EXCEPTION_ON_INVALID_REFERENCE : break ;
case ContainerInterface :: IGNORE_ON_UNINITIALIZED_REFERENCE : return sprintf ( '@!%s' , $id );
default : return sprintf ( '@?%s' , $id );
}
2015-08-17 17:00:26 -07:00
}
return sprintf ( '@%s' , $id );
}
/**
* Gets parameter call .
*
* @ param string $id
*
* @ return string
*/
private function getParameterCall ( $id )
{
return sprintf ( '%%%s%%' , $id );
}
private function getExpressionCall ( $expression )
{
return sprintf ( '@=%s' , $expression );
}
/**
* Prepares parameters .
*
* @ param array $parameters
* @ param bool $escape
*
* @ return array
*/
2017-02-02 16:28:38 -08:00
private function prepareParameters ( array $parameters , $escape = true )
2015-08-17 17:00:26 -07:00
{
$filtered = array ();
foreach ( $parameters as $key => $value ) {
2018-11-23 12:29:20 +00:00
if ( \is_array ( $value )) {
2015-08-17 17:00:26 -07:00
$value = $this -> prepareParameters ( $value , $escape );
2018-11-23 12:29:20 +00:00
} elseif ( $value instanceof Reference || \is_string ( $value ) && 0 === strpos ( $value , '@' )) {
2015-08-17 17:00:26 -07:00
$value = '@' . $value ;
}
$filtered [ $key ] = $value ;
}
return $escape ? $this -> escape ( $filtered ) : $filtered ;
}
/**
* Escapes arguments .
*
* @ return array
*/
2017-02-02 16:28:38 -08:00
private function escape ( array $arguments )
2015-08-17 17:00:26 -07:00
{
$args = array ();
foreach ( $arguments as $k => $v ) {
2018-11-23 12:29:20 +00:00
if ( \is_array ( $v )) {
2015-08-17 17:00:26 -07:00
$args [ $k ] = $this -> escape ( $v );
2018-11-23 12:29:20 +00:00
} elseif ( \is_string ( $v )) {
2015-08-17 17:00:26 -07:00
$args [ $k ] = str_replace ( '%' , '%%' , $v );
} else {
$args [ $k ] = $v ;
}
}
return $args ;
}
}