8000 [Yaml] Add custom tags support · symfony/symfony@3bb73c3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3bb73c3

Browse files
committed
[Yaml] Add custom tags support
1 parent 554b1a7 commit 3bb73c3

File tree

10 files changed

+335
-88
lines changed

10 files changed

+335
-88
lines changed

src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\DependencyInjection\Dumper;
1313

1414
use Symfony\Component\Yaml\Dumper as YmlDumper;
15+
use Symfony\Component\Yaml\Tag\TaggedValue;
1516
use Symfony\Component\DependencyInjection\Alias;
1617
use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
1718
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
@@ -251,10 +252,10 @@ private function dumpCallable($callable)
251252
*/
252253
private function dumpValue($value)
253254
{
254-
if ($value instanceof IteratorArgument) {
255-
$value = array('=iterator' => $value->getValues());
256-
} elseif ($value instanceof ClosureProxyArgument) {
257-
$value = array('=closure_proxy' => $value->getValues());
255+
if ($value instanceof IteratorArgument || $value instanceof ClosureProxyArgument) {
256+
$tag = $value instanceof IteratorArgument ? 'iterator' : 'closure_proxy';
257+
258+
return new TaggedValue($this->dumpValue($value->getValues()), $tag);
258259
}
259260

260261
if (is_array($value)) {

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

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Symfony\Component\Config\Resource\FileResource;
2424
use Symfony\Component\Yaml\Exception\ParseException;
2525
use Symfony\Component\Yaml\Parser as YamlParser;
26+
use Symfony\Component\Yaml\Tag\TaggedValue;
2627
use Symfony\Component\Yaml\Yaml;
2728
use Symfony\Component\ExpressionLanguage\Expression;
2829

@@ -506,7 +507,7 @@ protected function loadFile($file)
506507
}
507508

508509
try {
509-
$configuration = $this->yamlParser->parse(file_get_contents($file), Yaml::PARSE_CONSTANT);
510+
$configuration = $this->yamlParser->parse(file_get_contents($file), Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS);
510511
} catch (ParseException $e) {
511512
throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $file), 0, $e);
512513
}
@@ -557,42 +558,42 @@ private function validate($content, $file)
557558
/**
558559
* Resolves services.
559560
*
560-
* @param string|array $value
561+
* @param mixed $value
561562
*
562-
* @return array|string|Reference
563+
* @return array|string|Reference|ArgumentInterface
563564
*/
564565
private function resolveServices($value)
565566
{
566-
if (is_array($value)) {
567-
if (array_key_exists('=iterator', $value)) {
568-
if (1 !== count($value)) {
569-
throw new InvalidArgumentException('Arguments typed "=iterator" must have no sibling keys.');
570-
}
571-
if (!is_array($value = $value['=iterator'])) {
572-
throw new InvalidArgumentException('Arguments typed "=iterator" must be arrays.');
573-
}
574-
$value = new IteratorArgument(array_map(array($this, 'resolveServices'), $value));
575-
} elseif (array_key_exists('=closure_proxy', $value)) {
576-
if (1 !== count($value)) {
577-
throw new InvalidArgumentException('Arguments typed "=closure_proxy" must have no sibling keys.');
578-
}
579-
if (!is_array($value = $value['=closure_proxy']) || array(0, 1) !== array_keys($value)) {
580-
throw new InvalidArgumentException('Arguments typed "=closure_proxy" must be arrays of [@service, method].');
567+
if ($value instanceof TaggedValue) {
568+
$argument = $value->getValue();
569+
if ('iterator' === $value->getTag()) {
570+
if (!is_array($argument)) {
571+
throw new InvalidArgumentException('"!iterator" tag only accepts sequences.');
581572
}
582-
if (!is_string($value[0]) || !is_string($value[1]) || 0 !== strpos($value[0], '@') || 0 === strpos($value[0], '@@')) {
583-
throw new InvalidArgumentException('Arguments typed "=closure_proxy" must be arrays of [@service, method].');
573+
574+
return new IteratorArgument(array_map(array($this, 'resolveServices'), $argument));
575+
}
576+
if ('closure_proxy' === $value->getTag()) {
577+
if (!is_array($argument) || array(0, 1) !== array_keys($argument) || !is_string($argument[0]) || !is_string($argument[1]) || 0 !== strpos($argument[0], '@') || 0 === strpos($argument[0], '@@')) {
578+
throw new InvalidArgumentException('"!closure_proxy" tagged values must be arrays of [@service, method].');
584579
}
585-
if (0 === strpos($value[0], '@?')) {
586-
$value[0] = substr($value[0], 2);
580+
581+
if (0 === strpos($argument[0], '@?')) {
582+
$argument[0] = substr($argument[0], 2);
587583
$invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
588584
} else {
589-
$value[0] = substr($value[0], 1);
585+
$argument[0] = substr($argument[0], 1);
590586
$invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
591587
}
592-
$value = new ClosureProxyArgument($value[0], $value[1], $invalidBehavior);
593-
} else {
594-
$value = array_map(array($this, 'resolveServices'), $value);
588+
589+
return new ClosureProxyArgument($argument[0], $argument[1], $invalidBehavior);
595590
}
591+
592+
throw new InvalidArgumentException(sprintf('Unsupported tag "!%s".', $value->getTag()));
593+
}
594+
595+
if (is_array($value)) {
596+
$value = array_map(array($this, 'resolveServices'), $value);
596597
} elseif (is_string($value) && 0 === strpos($value, '@=')) {
597598
return new Expression(substr($value, 2));
598599
} elseif (is_string($value) && 0 === strpos($value, '@')) {

src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\DependencyInjection\ContainerBuilder;
1515
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
1616
use Symfony\Component\Yaml\Yaml;
17+
use Symfony\Component\Yaml\Parser;
1718

1819
class YamlDumperTest extends \PHPUnit_Framework_TestCase
1920
{
@@ -62,8 +63,10 @@ public function testDumpAutowireData()
6263
$this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services24.yml', $dumper->dump());
6364
}
6465

65-
private function assertEqualYamlStructure($yaml, $expected, $message = '')
66+
private function assertEqualYamlStructure($expected, $yaml, $message = '')
6667
{
67-
$this->assertEquals(Yaml::parse($expected), Yaml::parse($yaml), $message);
68+
$parser = new Parser();
69+
70+
$this->assertEquals($parser->parse($expected, Yaml::PARSE_CUSTOM_TAGS), $parser->parse($yaml, Yaml::PARSE_CUSTOM_TAGS), $message);
6871
}
6972
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@ services:
109109
factory: ['@factory_simple', getInstance]
110110
lazy_context:
111111
class: LazyContext
112-
arguments: [{ '=iterator': [foo, '@foo.baz', { '%foo%': 'foo is %foo%', foobar: '%foo%' }, true, '@service_container'] }]
112+
arguments: [!iterator [foo, '@foo.baz', { '%foo%': 'foo is %foo%', foobar: '%foo%' }, true, '@service_container']]
113113
lazy_context_ignore_invalid_ref:
114114
class: LazyContext
115-
arguments: [{ '=iterator': ['@foo.baz', '@?invalid'] }]
115+
arguments: [!iterator ['@foo.baz', '@?invalid']]
116116
closure_proxy:
117117
class: BarClass
118-
arguments: [{ '=closure_proxy': ['@closure_proxy', getBaz] }]
118+
arguments: [!closure_proxy ['@closure_proxy', getBaz]]
119119
alias_for_foo: '@foo'
120120
alias_for_alias: '@foo'

src/Symfony/Component/DependencyInjection/composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"php": ">=5.5.9"
2020
},
2121
"require-dev": {
22-
"symfony/yaml": "~3.2",
22+
"symfony/yaml": "~3.3",
2323
"symfony/config": "~3.3",
2424
"symfony/expression-language": "~2.8|~3.0"
2525
},
@@ -30,8 +30,8 @@
3030
"symfony/proxy-manager-bridge": "Generate service proxies to lazy load them"
3131
},
3232
"conflict": {
33-
"symfony/config": "<3.3",
34-
"symfony/yaml": "<3.2"
33+
"symfony/yaml": "<3.3",
34+
"symfony/config": "<3.3"
3535
},
3636
"autoload": {
3737
"psr-4": { "Symfony\\Component\\DependencyInjection\\": "" },

0 commit comments

Comments
 (0)
0