Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8b6272e

Browse filesBrowse files
[DI] Add "PHP fluent format" for configuring the container
1 parent fea348c commit 8b6272e
Copy full SHA for 8b6272e

16 files changed

+1123
-1
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php
+60-1Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,15 @@
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;
17+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
18+
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader\AliasConfigurator;
19+
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader\Internal\AbstractDefaultsConfigurator;
20+
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader\ParamConfigurator;
21+
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader\ReferenceConfigurator;
22+
use Symfony\Component\DependencyInjection\Reference;
1523

1624
/**
1725
* PhpFileLoader loads service definitions from a PHP file.
@@ -23,6 +31,8 @@
2331
*/
2432
class PhpFileLoader extends FileLoader
2533
{
34+
private $defaults;
35+
2636
/**
2737
* {@inheritdoc}
2838
*/
@@ -35,6 +45,8 @@ public function load($resource, $type = null)
3545
$path = $this->locator->locate($resource);
3646
$this->setCurrentDir(dirname($path));
3747
$this->container->fileExists($path);
48+
$this->defaults = new Definition();
49+
$this->instanceof = array();
3850

3951
include $path;
4052
}
@@ -54,4 +66,51 @@ public function supports($resource, $type = null)
5466

5567
return 'php' === $type;
5668
}
69+
70+
/**
71+
* @internal
72+
*/
73+
public static function call(\Closure $callback)
74+
{
75+
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 4);
76+
if (!isset($trace[3]['object']) || !$trace[3]['object'] instanceof self) {
77+
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']);
78+
}
79+
$callback = $callback->bindTo($trace[3]['object'], __CLASS__);
80+
81+
return $callback($trace[3]['object']->defaults, $trace[1]['file']);
82+
}
83+
84+
/**
85+
* @internal
86+
*/
87+
public static function processValue($value)
88+
{
89+
if (is_array($value)) {
90+
foreach ($value as $k => $v) {
91+
$value[$k] = self::processValue($v);
92+
}
93+
94+
return $value;
95+
}
96+
97+
if ($value instanceof PhpFileLoader\ReferenceConfigurator) {
98+
static $refCast;
99+
100+
if (!$refCast) {
101+
$refCast = \Closure::bind(function ($ref) {
102+
return new Reference($ref->id, $ref->invalidBehavior);
103+
}, $value, $value);
104+
}
105+
106+
// cast ReferenceConfigurator to Reference
107+
return $refCast($value);
108+
}
109+
110+
if ($value instanceof AbstractDefaultsConfigurator || $value instanceof AliasConfigurator || $value instanceof ParamConfigurator) {
111+
throw new InvalidArgumentException(sprintf('"%s()" can be used only at the root of service configuration files.', $value::FACTORY));
112+
}
113+
114+
return $value;
115+
}
57116
}
+48Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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+
const FACTORY = 'alias';
25+
26+
private $alias;
27+
28+
public function __construct(Alias $alias)
29+
{
30+
$this->alias = $alias;
31+
}
32+
33+
/**
34+
* @return $this
35+
*/
36+
public function __call($method, $args)
37+
{
38+
if ('public' === strtolower($method)) {
39+
$this->alias->setPublic(true);
40+
} elseif ('private' === strtolower($method)) {
41+
$this->alias->setPublic(false);
42+
} else {
43+
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
44+
}
45+
46+
return $this;
47+
}
48+
}
+85Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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+
const FACTORY = 'child';
22+
23+
/**
24+
* Sets the service that this service is decorating.
25+
*
26+
* @param null|string $id The decorated service id, use null to remove decoration
27+
* @param null|string $renamedId The new decorated service id
28+
* @param int $priority The priority of decoration
29+
*
30+
* @return $this
31+
*
32+
* @throws InvalidArgumentException In case the decorated service id and the new decorated service id are equals.
33+
*/
34+
public function decorate($id, $renamedId = null, $priority = 0)
35+
{
36+
$this->definition->setDecoratedService($id, $renamedId, $priority);
37+
38+
return $this;
39+
}
40+
41+
/**
42+
* @return $this
43+
*/
44+
public function __call($method, $args)
45+
{
46+
if ('class' !== strtolower($method)) {
47+
return parent::__call($method, $args);
48+
}
49+
if (!array_key_exists(0, $args)) {
50+
throw new \BadMethodCallException(sprintf('Missing argument 1 when calling method %s::%s()', get_class($this), $method));
51+
}
52+
$this->definition->setClass($args[0]);
53+
54+
return $this;
55+
}
56+
57+
/**
58+
* Sets a file to require before creating the service.
59+
*
60+
* @param string $file A full pathname to include
61+
*
62+
* @return $this
63+
*/
64+
public function file($file)
65+
{
66+
$this->definition->setFile($file);
67+
68+
return $this;
69+
}
70+
71+
/**
72+
* Sets whether this definition is synthetic, that is not constructed by the
73+
* container, but dynamically injected.
74+
*
75+
* @param bool $synthetic
76+
*
77+
* @return $this
78+
*/
79+
public function synthetic($synthetic = true)
80+
{
81+
$this->definition->setSynthetic($synthetic);
82+
83+
return $this;
84+
}
85+
}
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
const FACTORY = '_defaults';
20+
21+
/**
22+
* Sets whether or not instanceof conditionals should be prepended with a global set.
23+
*
24+
* @return $this
25+
*/
26+
public function autoconfigure($autoconfigured = true)
27+
{
28+
$this->definition->setAutoconfigured($autoconfigured);
29+
30+
return $this;
31+
}
32+
}
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
const FACTORY = 'service';
20+
21+
/**
22+
* Sets whether or not instanceof conditionals should be prepended with a global set.
23+
*
24+
* @return $this
25+
*/
26+
public function autoconfigure($autoconfigured = true)
27+
{
28+
$this->definition->setAutoconfigured($autoconfigured);
29+
30+
return $this;
31+
}
32+
}
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
const FACTORY = '_instanceof';
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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 $definition;
28+
29+
public function __construct(Definition $definition)
30+
{
31+
$this->definition = $definition;
32+
}
33+
34+
/**
35+
* Adds a tag for this definition.
36+
*
37+
* @param string $name The tag name
38+
* @param array $attributes An array of attributes
39+
*
40+
* @return $this
41+
*/
42+
public function tag($name, array $attributes = array())
43+
{
44+
if (!is_string($name) || '' === $name) {
45+
throw new InvalidArgumentException(sprintf('The tag name in "_defaults" must be a non-empty string.'));
46+
}
47+
48+
foreach ($attributes as $attribute => $value) {
49+
if (!is_scalar($value) && null !== $value) {
50+
throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type.', $name, $attribute));
51+
}
52+
}
53+
54+
$this->definition->addTag($name, $attributes);
55+
56+
return $this;
57+
}
58+
59+
/**
60+
* @return $this
61+
*/
62+
public function __call($method, $args)
63+
{
64+
if ('public' === strtolower($method)) {
65+
$this->definition->setPublic(true);
66+
} elseif ('private' === strtolower($method)) {
67+
$this->definition->setPublic(false);
68+
} else {
69+
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
70+
}
71+
72+
return $this;
73+
}
74+
75+
/**
76+
* Enables/disables autowiring.
77+
*
78+
* @param bool $autowired
79+
*
80+
* @return $this
81+
*/
82+
public function autowire($autowired = true)
83+
{
84+
$this->definition->setAutowired($autowired);
85+
86+
return $this;
87+
}
88+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.