2010-01-04 14:26:20 +00:00
< ? php
2010-08-20 22:09:55 +01:00
namespace Symfony\Component\DependencyInjection\Dumper ;
2010-01-04 14:26:20 +00:00
2010-08-20 22:09:55 +01:00
use Symfony\Component\DependencyInjection\ContainerBuilder ;
use Symfony\Component\DependencyInjection\Container ;
use Symfony\Component\DependencyInjection\ContainerInterface ;
use Symfony\Component\DependencyInjection\Reference ;
use Symfony\Component\DependencyInjection\Parameter ;
2010-01-04 14:26:20 +00:00
/*
2010-04-07 01:51:29 +01:00
* This file is part of the Symfony framework .
2010-01-04 14:26:20 +00:00
*
* ( c ) Fabien Potencier < fabien . potencier @ symfony - project . com >
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE .
*/
/**
* PhpDumper dumps a service container as a PHP class .
*
* @ author Fabien Potencier < fabien . potencier @ symfony - project . com >
*/
class PhpDumper extends Dumper
{
2010-05-06 12:25:53 +01:00
/**
* Dumps the service container as a PHP class .
*
* Available options :
*
* * class : The class name
* * base_class : The base class name
*
* @ param array $options An array of options
*
* @ return string A PHP class representing of the service container
*/
public function dump ( array $options = array ())
{
$options = array_merge ( array (
'class' => 'ProjectServiceContainer' ,
'base_class' => 'Container' ,
), $options );
return
$this -> startClass ( $options [ 'class' ], $options [ 'base_class' ]) .
$this -> addConstructor () .
$this -> addServices () .
2010-08-05 06:34:53 +01:00
$this -> addTags () .
2010-05-06 12:25:53 +01:00
$this -> addDefaultParametersMethod () .
$this -> endClass ()
;
}
protected function addServiceInclude ( $id , $definition )
{
2010-05-07 15:09:11 +01:00
if ( null !== $definition -> getFile ()) {
2010-05-06 12:25:53 +01:00
return sprintf ( " require_once %s; \n \n " , $this -> dumpValue ( $definition -> getFile ()));
}
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
protected function addServiceShared ( $id , $definition )
2010-01-04 14:26:20 +00:00
{
2010-05-07 15:09:11 +01:00
if ( $definition -> isShared ()) {
2010-05-06 12:25:53 +01:00
return <<< EOF
if ( isset ( \ $this -> shared [ '$id' ])) return \ $this -> shared [ '$id' ];
2010-01-04 14:26:20 +00:00
EOF ;
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
protected function addServiceReturn ( $id , $definition )
{
return <<< EOF
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
return \ $instance ;
}
2010-01-04 14:26:20 +00:00
EOF ;
}
2010-05-06 12:25:53 +01:00
protected function addServiceInstance ( $id , $definition )
2010-01-04 14:26:20 +00:00
{
2010-05-06 12:25:53 +01:00
$class = $this -> dumpValue ( $definition -> getClass ());
2010-03-01 17:37:22 +00:00
2010-07-16 19:59:38 +01:00
if ( 0 === strpos ( $class , " ' " ) && ! preg_match ( '/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/' , $class )) {
2010-09-26 15:59:40 +01:00
throw new \InvalidArgumentException ( sprintf ( '"%s" is not a valid class name for the "%s" service.' , $class , $id ));
2010-07-16 16:45:10 +01:00
}
2010-05-06 12:25:53 +01:00
$arguments = array ();
2010-05-07 15:09:11 +01:00
foreach ( $definition -> getArguments () as $value ) {
2010-05-06 12:25:53 +01:00
$arguments [] = $this -> dumpValue ( $value );
}
2010-03-01 17:37:22 +00:00
2010-07-05 08:47:14 +01:00
if ( null !== $definition -> getFactoryMethod ()) {
2010-07-03 23:35:39 +01:00
if ( null !== $definition -> getFactoryService ()) {
2010-07-04 17:56:48 +01:00
$code = sprintf ( " \$ instance = %s->%s(%s); \n " , $this -> getServiceCall ( $definition -> getFactoryService ()), $definition -> getFactoryMethod (), implode ( ', ' , $arguments ));
2010-07-03 23:35:39 +01:00
} else {
$code = sprintf ( " \$ instance = call_user_func(array(%s, '%s')%s); \n " , $class , $definition -> getFactoryMethod (), $arguments ? ', ' . implode ( ', ' , $arguments ) : '' );
}
2010-05-07 15:09:11 +01:00
} elseif ( $class != " ' " . str_replace ( '\\' , '\\\\' , $definition -> getClass ()) . " ' " ) {
2010-05-06 12:25:53 +01:00
$code = sprintf ( " \$ class = %s; \n \$ instance = new \$ class(%s); \n " , $class , implode ( ', ' , $arguments ));
2010-05-07 15:09:11 +01:00
} else {
2010-05-06 12:25:53 +01:00
$code = sprintf ( " \$ instance = new %s(%s); \n " , $definition -> getClass (), implode ( ', ' , $arguments ));
}
2010-01-04 14:26:20 +00:00
2010-05-07 15:09:11 +01:00
if ( $definition -> isShared ()) {
2010-05-06 12:25:53 +01:00
$code .= sprintf ( " \$ this->shared[' $id '] = \$ instance; \n " );
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
return $code ;
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
protected function addServiceMethodCalls ( $id , $definition )
2010-01-04 14:26:20 +00:00
{
2010-05-06 12:25:53 +01:00
$calls = '' ;
2010-05-07 15:09:11 +01:00
foreach ( $definition -> getMethodCalls () as $call ) {
2010-05-06 12:25:53 +01:00
$arguments = array ();
2010-05-07 15:09:11 +01:00
foreach ( $call [ 1 ] as $value ) {
2010-05-06 12:25:53 +01:00
$arguments [] = $this -> dumpValue ( $value );
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
$calls .= $this -> wrapServiceConditionals ( $call [ 1 ], sprintf ( " \$ instance->%s(%s); \n " , $call [ 0 ], implode ( ', ' , $arguments )));
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
return $calls ;
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
protected function addServiceConfigurator ( $id , $definition )
2010-01-04 14:26:20 +00:00
{
2010-05-07 15:09:11 +01:00
if ( ! $callable = $definition -> getConfigurator ()) {
2010-05-06 12:25:53 +01:00
return '' ;
}
2010-01-04 14:26:20 +00:00
2010-05-07 15:09:11 +01:00
if ( is_array ( $callable )) {
2010-05-08 14:32:30 +01:00
if ( is_object ( $callable [ 0 ]) && $callable [ 0 ] instanceof Reference ) {
2010-05-06 12:25:53 +01:00
return sprintf ( " %s->%s( \$ instance); \n " , $this -> getServiceCall (( string ) $callable [ 0 ]), $callable [ 1 ]);
2010-05-07 15:09:11 +01:00
} else {
2010-05-06 12:25:53 +01:00
return sprintf ( " call_user_func(array(%s, '%s'), \$ instance); \n " , $this -> dumpValue ( $callable [ 0 ]), $callable [ 1 ]);
}
2010-05-07 15:09:11 +01:00
} else {
2010-05-06 12:25:53 +01:00
return sprintf ( " %s( \$ instance); \n " , $callable );
}
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
protected function addService ( $id , $definition )
{
$name = Container :: camelize ( $id );
2010-07-04 17:56:48 +01:00
$return = '' ;
if ( $class = $definition -> getClass ()) {
$return = sprintf ( " @return %s A %s instance. " , 0 === strpos ( $class , '%' ) ? 'Object' : $class , $class );
} elseif ( $definition -> getFactoryService ()) {
$return = sprintf ( '@return Object An instance returned by %s::%s().' , $definition -> getFactoryService (), $definition -> getFactoryMethod ());
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
$doc = '' ;
2010-05-07 15:09:11 +01:00
if ( $definition -> isShared ()) {
2010-05-06 12:25:53 +01:00
$doc = <<< EOF
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
*
* This service is shared .
* This method always returns the same instance of the service .
2010-01-04 14:26:20 +00:00
EOF ;
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
$code = <<< EOF
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
/**
* Gets the '$id' service . $doc
*
2010-07-04 17:56:48 +01:00
* $return
2010-05-06 12:25:53 +01:00
*/
protected function get { $name } Service ()
{
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
EOF ;
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
$code .=
$this -> addServiceInclude ( $id , $definition ) .
$this -> addServiceShared ( $id , $definition ) .
$this -> addServiceInstance ( $id , $definition ) .
$this -> addServiceMethodCalls ( $id , $definition ) .
$this -> addServiceConfigurator ( $id , $definition ) .
$this -> addServiceReturn ( $id , $definition )
;
return $code ;
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
protected function addServiceAlias ( $alias , $id )
{
$name = Container :: camelize ( $alias );
$type = 'Object' ;
2010-01-04 14:26:20 +00:00
2010-05-07 15:09:11 +01:00
if ( $this -> container -> hasDefinition ( $id )) {
2010-05-06 12:25:53 +01:00
$class = $this -> container -> getDefinition ( $id ) -> getClass ();
$type = 0 === strpos ( $class , '%' ) ? 'Object' : $class ;
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
return <<< EOF
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
/**
* Gets the $alias service alias .
*
* @ return $type An instance of the $id service
*/
protected function get { $name } Service ()
2010-01-04 14:26:20 +00:00
{
2010-05-06 12:25:53 +01:00
return { $this -> getServiceCall ( $id )};
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
EOF ;
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
protected function addServices ()
2010-02-09 08:45:23 +00:00
{
2010-05-06 12:25:53 +01:00
$code = '' ;
2010-05-07 15:09:11 +01:00
foreach ( $this -> container -> getDefinitions () as $id => $definition ) {
2010-05-06 12:25:53 +01:00
$code .= $this -> addService ( $id , $definition );
2010-02-09 08:45:23 +00:00
}
2010-05-07 15:09:11 +01:00
foreach ( $this -> container -> getAliases () as $alias => $id ) {
2010-05-06 12:25:53 +01:00
$code .= $this -> addServiceAlias ( $alias , $id );
}
2010-02-09 08:45:23 +00:00
2010-05-06 12:25:53 +01:00
return $code ;
}
2010-02-09 08:45:23 +00:00
2010-08-05 06:34:53 +01:00
protected function addTags ()
2010-05-06 12:25:53 +01:00
{
2010-08-05 06:34:53 +01:00
$tags = array ();
2010-05-07 15:09:11 +01:00
foreach ( $this -> container -> getDefinitions () as $id => $definition ) {
2010-08-05 06:34:53 +01:00
foreach ( $definition -> getTags () as $name => $ann ) {
if ( ! isset ( $tags [ $name ])) {
$tags [ $name ] = array ();
2010-05-06 12:25:53 +01:00
}
2010-08-05 06:34:53 +01:00
$tags [ $name ][ $id ] = $ann ;
2010-05-06 12:25:53 +01:00
}
}
2010-08-05 06:34:53 +01:00
$tags = var_export ( $tags , true );
2010-02-09 08:45:23 +00:00
2010-05-06 12:25:53 +01:00
return <<< EOF
2010-02-09 08:45:23 +00:00
2010-05-06 12:25:53 +01:00
/**
2010-08-05 06:34:53 +01:00
* Returns service ids for a given tag .
2010-05-06 12:25:53 +01:00
*
2010-08-05 06:34:53 +01:00
* @ param string \ $name The tag name
2010-05-06 12:25:53 +01:00
*
2010-08-05 06:34:53 +01:00
* @ return array An array of tags
2010-05-06 12:25:53 +01:00
*/
2010-08-05 06:34:53 +01:00
public function findTaggedServiceIds ( \ $name )
2010-01-04 14:26:20 +00:00
{
2010-08-05 06:34:53 +01:00
static \ $tags = $tags ;
2010-05-06 12:25:53 +01:00
2010-08-05 06:34:53 +01:00
return isset ( \ $tags [ \ $name ]) ? \ $tags [ \ $name ] : array ();
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
EOF ;
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
protected function startClass ( $class , $baseClass )
2010-01-04 14:26:20 +00:00
{
2010-06-27 17:28:29 +01:00
$bagClass = $this -> container -> isFrozen () ? 'FrozenParameterBag' : 'ParameterBag' ;
2010-05-06 12:25:53 +01:00
return <<< EOF
2010-01-04 14:26:20 +00:00
< ? php
2010-08-20 22:09:55 +01:00
use Symfony\Component\DependencyInjection\ContainerInterface ;
use Symfony\Component\DependencyInjection\Container ;
use Symfony\Component\DependencyInjection\Reference ;
use Symfony\Component\DependencyInjection\Parameter ;
use Symfony\Component\DependencyInjection\ParameterBag\\ $bagClass ;
2010-01-04 14:26:20 +00:00
/**
* $class
*
* This class has been auto - generated
2010-07-05 10:08:27 +01:00
* by the Symfony Dependency Injection Component .
2010-01-04 14:26:20 +00:00
*/
class $ class extends $baseClass
{
2010-05-06 12:25:53 +01:00
protected \ $shared = array ();
2010-01-04 14:26:20 +00:00
EOF ;
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
protected function addConstructor ()
2010-01-04 14:26:20 +00:00
{
2010-06-27 17:28:29 +01:00
$bagClass = $this -> container -> isFrozen () ? 'FrozenParameterBag' : 'ParameterBag' ;
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
return <<< EOF
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
/**
* Constructor .
*/
public function __construct ()
{
2010-06-27 17:28:29 +01:00
parent :: __construct ( new $bagClass ( \ $this -> getDefaultParameters ()));
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:26:20 +00:00
EOF ;
}
2010-05-06 12:25:53 +01:00
protected function addDefaultParametersMethod ()
{
2010-06-27 17:28:29 +01:00
if ( ! $this -> container -> getParameterBag () -> all ()) {
2010-05-06 12:25:53 +01:00
return '' ;
}
2010-01-04 14:26:20 +00:00
2010-06-27 17:28:29 +01:00
$parameters = $this -> exportParameters ( $this -> container -> getParameterBag () -> all ());
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
return <<< EOF
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
/**
* Gets the default parameters .
*
* @ return array An array of the default parameters
*/
protected function getDefaultParameters ()
2010-01-04 14:26:20 +00:00
{
2010-05-06 12:25:53 +01:00
return $parameters ;
2010-01-04 14:26:20 +00:00
}
EOF ;
}
2010-05-06 12:25:53 +01:00
protected function exportParameters ( $parameters , $indent = 12 )
2010-01-04 14:26:20 +00:00
{
2010-05-06 12:25:53 +01:00
$php = array ();
2010-05-07 15:09:11 +01:00
foreach ( $parameters as $key => $value ) {
2010-05-08 14:32:30 +01:00
if ( is_array ( $value )) {
2010-05-06 12:25:53 +01:00
$value = $this -> exportParameters ( $value , $indent + 4 );
2010-05-07 15:09:11 +01:00
} elseif ( $value instanceof Reference ) {
2010-05-06 12:25:53 +01:00
throw new \InvalidArgumentException ( sprintf ( 'You cannot dump a container with parameters that contain references to other services (reference to service %s found).' , $value ));
2010-05-07 15:09:11 +01:00
} else {
2010-05-06 12:25:53 +01:00
$value = var_export ( $value , true );
}
$php [] = sprintf ( '%s%s => %s,' , str_repeat ( ' ' , $indent ), var_export ( $key , true ), $value );
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
return sprintf ( " array( \n %s \n %s) " , implode ( " \n " , $php ), str_repeat ( ' ' , $indent - 4 ));
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
protected function endClass ()
2010-01-04 14:26:20 +00:00
{
2010-05-06 12:25:53 +01:00
return <<< EOF
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
EOF ;
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
protected function wrapServiceConditionals ( $value , $code )
2010-01-04 14:26:20 +00:00
{
2010-07-15 14:11:33 +01:00
if ( ! $services = ContainerBuilder :: getServiceConditionals ( $value )) {
2010-05-06 12:25:53 +01:00
return $code ;
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
$conditions = array ();
2010-05-07 15:09:11 +01:00
foreach ( $services as $service ) {
2010-06-27 17:28:29 +01:00
$conditions [] = sprintf ( " \$ this->has('%s') " , $service );
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
// re-indent the wrapped code
$code = implode ( " \n " , array_map ( function ( $line ) { return $line ? ' ' . $line : $line ; }, explode ( " \n " , $code )));
2010-01-04 14:26:20 +00:00
2010-05-07 15:09:11 +01:00
return sprintf ( " if (%s) { \n %s } \n " , implode ( ' && ' , $conditions ), $code );
2010-01-04 14:26:20 +00:00
}
2010-06-27 17:28:29 +01:00
protected function dumpValue ( $value , $interpolate = true )
2010-01-04 14:26:20 +00:00
{
2010-05-07 15:09:11 +01:00
if ( is_array ( $value )) {
2010-05-06 12:25:53 +01:00
$code = array ();
2010-05-07 15:09:11 +01:00
foreach ( $value as $k => $v ) {
2010-06-27 17:28:29 +01:00
$code [] = sprintf ( '%s => %s' , $this -> dumpValue ( $k , $interpolate ), $this -> dumpValue ( $v , $interpolate ));
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:26:20 +00:00
2010-05-06 12:25:53 +01:00
return sprintf ( 'array(%s)' , implode ( ', ' , $code ));
2010-05-07 15:09:11 +01:00
} elseif ( is_object ( $value ) && $value instanceof Reference ) {
2010-05-06 12:25:53 +01:00
return $this -> getServiceCall (( string ) $value , $value );
2010-05-07 15:09:11 +01:00
} elseif ( is_object ( $value ) && $value instanceof Parameter ) {
2010-06-27 17:28:29 +01:00
return $this -> dumpParameter ( $value );
} elseif ( true === $interpolate && is_string ( $value )) {
2010-05-08 14:32:30 +01:00
if ( preg_match ( '/^%([^%]+)%$/' , $value , $match )) {
2010-05-06 12:25:53 +01:00
// we do this to deal with non string values (boolean, integer, ...)
// the preg_replace_callback converts them to strings
2010-06-27 17:28:29 +01:00
return $this -> dumpParameter ( strtolower ( $match [ 1 ]));
2010-05-07 15:09:11 +01:00
} else {
2010-06-27 17:28:29 +01:00
$that = $this ;
$replaceParameters = function ( $match ) use ( $that )
2010-05-06 12:25:53 +01:00
{
2010-06-27 17:28:29 +01:00
return sprintf ( " '. " . $that -> dumpParameter ( strtolower ( $match [ 2 ])) . " .' " );
2010-05-06 12:25:53 +01:00
};
$code = str_replace ( '%%' , '%' , preg_replace_callback ( '/(?<!%)(%)([^%]+)\1/' , $replaceParameters , var_export ( $value , true )));
// optimize string
$code = preg_replace ( array ( " /^'' \ ./ " , " / \ .'' $ / " , " / \ .'' \ ./ " ), array ( '' , '' , '.' ), $code );
return $code ;
}
2010-05-07 15:09:11 +01:00
} elseif ( is_object ( $value ) || is_resource ( $value )) {
2010-05-06 12:25:53 +01:00
throw new \RuntimeException ( 'Unable to dump a service container if a parameter is an object or a resource.' );
2010-05-07 15:09:11 +01:00
} else {
2010-05-06 12:25:53 +01:00
return var_export ( $value , true );
}
2010-01-04 14:26:20 +00:00
}
2010-05-06 12:25:53 +01:00
2010-06-27 17:28:29 +01:00
public function dumpParameter ( $name )
{
2010-09-03 15:18:04 +01:00
if ( $this -> container -> isFrozen () && $this -> container -> hasParameter ( $name )) {
2010-06-27 17:28:29 +01:00
return $this -> dumpValue ( $this -> container -> getParameter ( $name ), false );
}
return sprintf ( " \$ this->getParameter('%s') " , strtolower ( $name ));
}
2010-05-06 12:25:53 +01:00
protected function getServiceCall ( $id , Reference $reference = null )
2010-01-04 14:26:20 +00:00
{
2010-05-07 15:09:11 +01:00
if ( 'service_container' === $id ) {
2010-05-06 12:25:53 +01:00
return '$this' ;
}
2010-06-27 17:28:29 +01:00
if ( null !== $reference && ContainerInterface :: EXCEPTION_ON_INVALID_REFERENCE !== $reference -> getInvalidBehavior ()) {
return sprintf ( '$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)' , $id );
2010-05-07 15:09:11 +01:00
} else {
2010-05-08 14:32:30 +01:00
if ( $this -> container -> hasAlias ( $id )) {
2010-05-06 12:25:53 +01:00
$id = $this -> container -> getAlias ( $id );
}
2010-01-21 20:59:59 +00:00
2010-05-07 15:09:11 +01:00
if ( $this -> container -> hasDefinition ( $id )) {
2010-05-06 12:25:53 +01:00
return sprintf ( '$this->get%sService()' , Container :: camelize ( $id ));
}
2010-01-21 20:59:59 +00:00
2010-06-27 17:28:29 +01:00
return sprintf ( '$this->get(\'%s\')' , $id );
2010-05-06 12:25:53 +01:00
}
2010-01-04 14:26:20 +00:00
}
}