Skip to content

Commit 9849a3d

Browse files
[DI] Add "PHP fluent format" for configuring the container
1 parent fea348c commit 9849a3d

14 files changed

+966
-2
lines changed

src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php

+25-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Loader;
1313

14-
use Symfony\Component\Config\Resource\FileResource;
14+
require_once __DIR__.'/PhpFileLoader/functions.php';
15+
16+
use Symfony\Component\DependencyInjection\Definition;
1517

1618
/**
1719
* PhpFileLoader loads service definitions from a PHP file.
@@ -23,6 +25,8 @@
2325
*/
2426
class PhpFileLoader extends FileLoader
2527
{
28+
private $defaults;
29+
2630
/**
2731
* {@inheritdoc}
2832
*/
@@ -35,8 +39,13 @@ public function load($resource, $type = null)
3539
$path = $this->locator->locate($resource);
3640
$this->setCurrentDir(dirname($path));
3741
$this->container->fileExists($path);
42+
$this->defaults = new Definition();
3843

39-
include $path;
44+
try {
45+
include $path;
46+
} finally {
47+
$this->instanceof = array();
48+
}
4049
}
4150

4251
/**
@@ -54,4 +63,18 @@ public function supports($resource, $type = null)
5463

5564
return 'php' === $type;
5665
}
66+
67+
/**
68+
* @internal
69+
*/
70+
public static function call(\Closure $callback)
71+
{
72+
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 4);
73+
if (!isset($trace[3]['object']) || !$trace[3]['object'] instanceof self) {
74+
throw new \ErrorException(sprintf('Function "%s()" must be called in a "%s" context.', $trace[1]['function'], __CLASS__), 0, E_ERROR, $trace[1]['file'], $trace[1]['line']);
75+
}
76+
$callback = $callback->bindTo($trace[3]['object'], __CLASS__);
77+
78+
return $callback($trace[1]['file'], $trace[3]['object']->defaults);
79+
}
5780
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
13+
14+
use Symfony\Component\DependencyInjection\Alias;
15+
16+
/**
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*
19+
* @method $this public()
20+
* @method $this private()
21+
*/
22+
class AliasConfigurator
23+
{
24+
private $alias;
25+
26+
public function __construct(Alias $alias)
27+
{
28+
$this->alias = $alias;
29+
}
30+
31+
/**
32+
* @return $this
33+
*/
34+
public function __call($method, $args)
35+
{
36+
if ('public' === strtolower($method)) {
37+
$this->alias->setPublic(true);
38+
} elseif ('private' === strtolower($method)) {
39+
$this->alias->setPublic(false);
40+
} else {
41+
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
42+
}
43+
44+
return $this;
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
13+
14+
/**
15+
* @author Nicolas Grekas <p@tchwork.com>
16+
*
17+
* @method $this class()
18+
*/
19+
class ChildDefinitionConfigurator extends Internal\AbstractPrototypeConfigurator
20+
{
21+
/**
22+
* Sets the service that this service is decorating.
23+
*
24+
* @param null|string $id The decorated service id, use null to remove decoration
25+
* @param null|string $renamedId The new decorated service id
26+
* @param int $priority The priority of decoration
27+
*
28+
* @return $this
29+
*
30+
* @throws InvalidArgumentException In case the decorated service id and the new decorated service id are equals.
31+
*/
32+
public function decorate($id, $renamedId = null, $priority = 0)
33+
{
34+
$this->definition->setDecoratedService($id, $renamedId, $priority);
35+
36+
return $this;
37+
}
38+
39+
/**
40+
* @return $this
41+
*/
42+
public function __call($method, $args)
43+
{
44+
if ('class' !== strtolower($method)) {
45+
return parent::__call($method, $args);
46+
}
47+
if (!array_key_exists(0, $args)) {
48+
throw new \BadMethodCallException(sprintf('Missing argument 1 when calling method %s::%s()', get_class($this), $method));
49+
}
50+
$this->definition->setClass($args[0]);
51+
52+
return $this;
53+
}
54+
55+
/**
56+
* Sets a file to require before creating the service.
57+
*
58+
* @param string $file A full pathname to include
59+
*
60+
* @return $this
61+
*/
62+
public function file($file)
63+
{
64+
$this->definition->setFile($file);
65+
66+
return $this;
67+
}
68+
69+
/**
70+
* Sets whether this definition is synthetic, that is not constructed by the
71+
* container, but dynamically injected.
72+
*
73+
* @param bool $synthetic
74+
*
75+
* @return $this
76+
*/
77+
public function synthetic($synthetic = true)
78+
{
79+
$this->definition->setSynthetic($synthetic);
80+
81+
return $this;
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
13+
14+
/**
15+
* @author Nicolas Grekas <p@tchwork.com>
16+
*/
17+
class DefaultsConfigurator extends Internal\AbstractDefaultsConfigurator
18+
{
19+
/**
20+
* Sets whether or not instanceof conditionals should be prepended with a global set.
21+
*
22+
* @return $this
23+
*/
24+
public function autoconfigure($autoconfigured = true)
25+
{
26+
$this->definition->setAutoconfigured($autoconfigured);
27+
28+
return $this;
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
13+
14+
/**
15+
* @author Nicolas Grekas <p@tchwork.com>
16+
*/
17+
class DefinitionConfigurator extends ChildDefinitionConfigurator
18+
{
19+
/**
20+
* Sets whether or not instanceof conditionals should be prepended with a global set.
21+
*
22+
* @return $this
23+
*/
24+
public function autoconfigure($autoconfigured = true)
25+
{
26+
$this->definition->setAutoconfigured($autoconfigured);
27+
28+
return $this;
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
13+
14+
/**
15+
* @author Nicolas Grekas <p@tchwork.com>
16+
*/
17+
class InstanceofConfigurator extends Internal\AbstractInstanceofConfigurator
18+
{
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\PhpFileLoader\Internal;
13+
14+
use Symfony\Component\DependencyInjection\Definition;
15+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
16+
17+
/**
18+
* @author Nicolas Grekas <p@tchwork.com>
19+
*
20+
* @method $this public()
21+
* @method $this private()
22+
*
23+
* @internal
24+
*/
25+
abstract class AbstractDefaultsConfigurator
26+
{
27+
protected $file;
28+
protected $definition;
29+
30+
public function __construct($file, Definition $definition)
31+
{
32+
$this->file = $file;
33+
$this->definition = $definition;
34+
}
35+
36+
/**
37+
* Adds a tag for this definition.
38+
*
39+
* @param string $name The tag name
40+
* @param array $attributes An array of attributes
41+
*
42+
* @return $this
43+
*/
44+
public function tag($name, array $attributes = array())
45+
{
46+
if (!is_string($name) || '' === $name) {
47+
throw new InvalidArgumentException(sprintf('The tag name in "_defaults" must be a non-empty string "%s".', $this->file));
48+
}
49+
50+
foreach ($attributes as $attribute => $value) {
51+
if (!is_scalar($value) && null !== $value) {
52+
throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type in %s.', $name, $attribute, $this->file));
53+
}
54+
}
55+
56+
$this->definition->addTag($name, $attributes);
57+
58+
return $this;
59+
}
60+
61+
/**
62+
* @return $this
63+
*/
64+
public function __call($method, $args)
65+
{
66+
if ('public' === strtolower($method)) {
67+
$this->definition->setPublic(true);
68+
} elseif ('private' === strtolower($method)) {
69+
$this->definition->setPublic(false);
70+
} else {
71+
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
72+
}
73+
74+
return $this;
75+
}
76+
77+
/**
78+
* Enables/disables autowiring.
79+
*
80+
* @param bool $autowired
81+
*
82+
* @return $this
83+
*/
84+
public function autowire($autowired = true)
85+
{
86+
$this->definition->setAutowired($autowired);
87+
88+
return $this;
89+
}
90+
}

0 commit comments

Comments
 (0)