8000 Merge branch '2.7' · symfony/symfony@1aaa382 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1aaa382

Browse files
committed
Merge branch '2.7'
* 2.7: Marked the ResolveParameterPlaceHoldersPassTest as legacy [ExpressionLanguage] fixed issues when parsing postfix expressions remove unused code do not inline service factories resolve class parameters in service factories [Serializer] Fix object normalization exceptions
2 parents 3ea8943 + 59ca5b3 commit 1aaa382

File tree

12 files changed

+185
-21
lines changed

12 files changed

+185
-21
lines changed

src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ public function process(ContainerBuilder $container)
6565

6666
$configurator = $this->inlineArguments($container, array($definition->getConfigurator()));
6767
$definition->setConfigurator($configurator[0]);
68-
69-
$factory = $this->inlineArguments($container, array($definition->getFactory()));
70-
$definition->setFactory($factory[0]);
7168
}
7269
}
7370

src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ public function process(ContainerBuilder $container)
4141
$definition->setFactoryClass($parameterBag->resolveValue($definition->getFactoryClass()));
4242
}
4343

44+
$factory = $definition->getFactory();
45+
46+
if (is_array($factory) && isset($factory[0])) {
47+
$factory[0] = $parameterBag->resolveValue($factory[0]);
48+
$definition->setFactory($factory);
49+
}
50+
4451
$calls = array();
4552
foreach ($definition->getMethodCalls() as $name => $arguments) {
4653
$calls[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($arguments);

src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,23 @@ public function testProcessDoesNotInlineWhenServiceReferencesItself()
237237
$this->assertSame($ref, $calls[0][1][0]);
238238
}
239239

240+
public function testProcessDoesNotInlineFactories()
241+
{
242+
$container = new ContainerBuilder();
243+
$container
244+
->register('foo.factory')
245+
->setPublic(false)
246+
;
247+
$container
248+
->register('foo')
249+
->setFactory(array(new Reference('foo.factory'), 'getFoo'))
250+
;
251+
$this->process($container);
252+
253+
$factory = $container->getDefinition('foo')->getFactory();
254+
$this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $factory[0]);
255+
}
256+
240257
protected function process(ContainerBuilder $container)
241258
{
242259
$repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass()));
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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\Tests\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
17+
/**
18+
* @group legacy
19+
*/
20+
class LegacyResolveParameterPlaceHoldersPassTest extends \PHPUnit_Framework_TestCase
21+
{
22+
public function testFactoryClassParametersShouldBeResolved()
23+
{
24+
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
25+
26+
$compilerPass = new ResolveParameterPlaceHoldersPass();
27+
28+
$container = new ContainerBuilder();
29+
$container->setParameter('foo.factory.class', 'FooFactory');
30+
$fooDefinition = $container->register('foo', '%foo.factory.class%');
31+
$fooDefinition->setFactoryClass('%foo.factory.class%');
32+
$compilerPass->process($container);
33+
$fooDefinition = $container->getDefinition('foo');
34+
35+
$this->assertSame('FooFactory', $fooDefinition->getFactoryClass());
36+
}
37+
}

src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ public function testClassParametersShouldBeResolved()
3333
$this->assertSame('Foo', $this->fooDefinition->getClass());
3434
}
3535

36-
public function testFactoryClassParametersShouldBeResolved()
36+
public function testFactoryParametersShouldBeResolved()
3737
{
38-
$this->assertSame('FooFactory', $this->fooDefinition->getFactoryClass());
38+
$this->assertSame(array('FooFactory', 'getFoo'), $this->fooDefinition->getFactory());
3939
}
4040

4141
public function testArgumentParametersShouldBeResolved()
@@ -78,7 +78,7 @@ private function createContainerBuilder()
7878
$containerBuilder->setParameter('alias.id', 'bar');
7979

8080
$fooDefinition = $containerBuilder->register('foo', '%foo.class%');
81-
$fooDefinition->setFactoryClass('%foo.factory.class%');
81+
$fooDefinition->setFactory(array('%foo.factory.class%', 'getFoo'));
8282
$fooDefinition->setArguments(array('%foo.arg1%', '%foo.arg2%'));
8383
$fooDefinition->addMethodCall('%foo.method%', array('%foo.arg1%', '%foo.arg2%'));
8484
$fooDefinition->setProperty('%foo.property.name%', '%foo.property.value%');

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,9 @@ public static function setUpBeforeClass()
2525

2626
public function testDump()
2727
{
28-
$dumper = new XmlDumper($container = new ContainerBuilder());
28+
$dumper = new XmlDumper(new ContainerBuilder());
2929

3030
$this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services1.xml', $dumper->dump(), '->dump() dumps an empty container as an empty XML file');
31-
32-
$container = new ContainerBuilder();
33-
$dumper = new XmlDumper($container);
3431
}
3532

3633
public function testExportParameters()
@@ -155,4 +152,26 @@ public function provideDecoratedServicesData()
155152
", include $fixturesPath.'/containers/container16.php'),
156153
);
157154
}
155+
156+
/**
157+
* @dataProvider provideCompiledContainerData
158+
*/
159+
public function testCompiledContainerCanBeDumped($containerFile)
160+
{
161+
$fixturesPath = __DIR__.'/../Fixtures';
162+
$container = require $fixturesPath.'/containers/'.$containerFile.'.php';
163+
$container->compile();
164+
$dumper = new XmlDumper($container);
165+
$dumper->dump();
166+
}
167+
168+
public function provideCompiledContainerData()
169+
{
170+
return array(
171+
array('container8'),
172+
array('container11'),
173+
array('container12'),
174+
array('container14'),
175+
);
176+
}
158177
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container14.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@
44

55
use Symfony\Component\DependencyInjection\ContainerBuilder;
66

7-
class ProjectServiceContainer extends ContainerBuilder
8-
{
7+
/**
8+
* This file is included in Tests\Dumper\GraphvizDumperTest::testDumpWithFrozenCustomClassContainer
9+
* and Tests\Dumper\XmlDumperTest::testCompiledContainerCanBeDumped.
10+
*/
11+
if (!class_exists('Container14\ProjectServiceContainer')) {
12+
class ProjectServiceContainer extends ContainerBuilder
13+
{
14+
}
915
}
1016

1117
return new ProjectServiceContainer();

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public function __construct()
4646
'foo_bar' => 'getFooBarService',
4747
'foo_with_inline' => 'getFooWithInlineService',
4848
'method_call1' => 'getMethodCall1Service',
49+
'new_factory' => 'getNewFactoryService',
4950
'new_factory_service' => 'getNewFactoryServiceService',
5051
'request' => 'getRequestService',
5152
'service_from_static_method' => 'getServiceFromStaticMethodService',
@@ -264,10 +265,7 @@ protected function getMethodCall1Service()
264265
*/
265266
protected function getNewFactoryServiceService()
266267
{
267-
$a = new \FactoryClass();
268-
$a->foo = 'bar';
269-
270-
$this->services['new_factory_service'] = $instance = $a->getInstance();
268+
$this->services['new_factory_service'] = $instance = $this->get('new_factory')->getInstance();
271269

272270
$instance->foo = 'bar';
273271

@@ -300,6 +298,27 @@ protected function getServiceFromStaticMethodService()
300298
return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance();
301299
}
302300

301+
/**
302+
* Gets the 'new_factory' service.
303+
*
304+
* This service is shared.
305+
* This method always returns the same instance of the service.
306+
*
307+
* This service is private.
308+
* If you want to be able to request this service from the container directly,
309+
* make it public, otherwise you might end up with broken code.
310+
*
311+
* @return \FactoryClass A FactoryClass instance.
312+
*/
313+
protected function getNewFactoryService()
314+
{
315+
$this->services['new_factory'] = $instance = new \FactoryClass();
316+
317+
$instance->foo = 'bar';
318+
319+
return $instance;
320+
}
321+
303322
/**
304323
* {@inheritdoc}
305324
*/

src/Symfony/Component/ExpressionLanguage/Parser.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,20 @@ public function parsePostfixExpression($node)
314314
if (
315315
$token->type !== Token::NAME_TYPE
316316
&&
317-
$token->type !== Token::NUMBER_TYPE
318-
&&
319-
// operators line "not" are valid method or property names
320-
($token->type !== Token::OPERATOR_TYPE && preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value))
317+
// Operators like "not" and "matches" are valid method or property names,
318+
//
319+
// In other words, besides NAME_TYPE, OPERATOR_TYPE could also be parsed as a property or method.
320+
// This is because operators are processed by the lexer prior to names. So "not" in "foo.not()" or "matches" in "foo.matches" will be recognized as an operator first.
321+
// But in fact, "not" and "matches" in such expressions shall be parsed as method or property names.
322+
//
323+
// And this ONLY works if the operator consists of valid characters for a property or method name.
324+
//
325+
// Other types, such as STRING_TYPE and NUMBER_TYPE, can't be parsed as property nor method names.
326+
//
327+
// As a result, if $token is NOT an operator OR $token->value is NOT a valid property or method name, an exception shall be thrown.
328+
($token->type !== Token::OPERATOR_TYPE || !preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value))
321329
) {
322-
throw new SyntaxError('Expected name or number', $token->cursor);
330+
throw new SyntaxError('Expected name', $token->cursor);
323331
}
324332

325333
$arg = new Node\ConstantNode($token->value);

src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,37 @@ private function createGetAttrNode($node, $item, $type)
161161
{
162162
return new Node\GetAttrNode($node, new Node\ConstantNode($item), new Node\ArgumentsNode(), $type);
163163
}
164+
165+
/**
166+
* @dataProvider getInvalidPostfixData
167+
* @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError
168+
*/
169+
public function testParseWithInvalidPostfixData($expr, $names = array())
170+
{
171+
$lexer = new Lexer();
172+
$parser = new Parser(array());
173+
$parser->parse($lexer->tokenize($expr), $names);
174+
}
175+
176+
public function getInvalidPostfixData()
177+
{
178+
return array(
179+
array(
180+
'foo."#"',
181+
array('foo'),
182+
),
183+
array(
184+
'foo."bar"',
185+
array('foo'),
186+
),
187+
array(
188+
'foo.**',
189+
array('foo'),
190+
),
191+
array(
192+
'foo.123',
193+
array('foo'),
194+
),
195+
);
196+
}
164197
}

src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
n 10000 amespace Symfony\Component\Serializer\Normalizer;
1313

1414
use Symfony\Component\Serializer\Exception\CircularReferenceException;
15+
use Symfony\Component\Serializer\Exception\LogicException;
1516
use Symfony\Component\Serializer\Exception\RuntimeException;
1617

1718
/**
@@ -68,6 +69,10 @@ public function normalize($object, $format = null, array $context = array())
6869
$attributeValue = call_user_func($this->callbacks[$property->name], $attributeValue);
6970
}
7071
if (null !== $attributeValue && !is_scalar($attributeValue)) {
72+
if (!$this->serializer instanceof NormalizerInterface) {
73+
throw new LogicException(sprintf('Cannot normalize attribute "%s" because injected serializer is not a normalizer', $property->name));
74+
}
75+
7176
$attributeValue = $this->serializer->normalize($attributeValue, $format, $context);
7277
}
7378

src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,22 @@ public function testDenormalizeNonExistingAttribute()
350350
$this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\PropertyDummy')
351351
);
352352
}
353+
354+
/**
355+
* @expectedException \Symfony\Component\Serializer\Exception\LogicException
356+
* @expectedExceptionMessage Cannot normalize attribute "bar" because injected serializer is not a normalizer
357+
*/
358+
public function testUnableToNormalizeObjectAttribute()
359+
{
360+
$serializer = $this->getMock('Symfony\Component\Serializer\SerializerInterface');
361+
$this->normalizer->setSerializer($serializer);
362+
363+
$obj = new PropertyDummy();
364+
$object = new \stdClass();
365+
$obj->setBar($object);
366+
367+
$this->normalizer->normalize($obj, 'any');
368+
}
353369
}
354370

355371
class PropertyDummy

0 commit comments

Comments
 (0)
0