diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index f1adc832ef..657777f020 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -14,7 +14,7 @@ CHANGELOG * Added 'host' option to firewall configuration * Added 'csrf_token_generator' and 'csrf_token_id' options to firewall logout - listener configuration to supercede/alias 'csrf_provider' and 'intention' + listener configuration to supersede/alias 'csrf_provider' and 'intention' respectively * Moved 'security.secure_random' service configuration to FrameworkBundle diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 93dfba9a39..660e18a26e 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -312,7 +312,15 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N $allowed = $allowedAttributes === false || in_array($paramName, $allowedAttributes); $ignored = in_array($paramName, $this->ignoredAttributes); - if ($allowed && !$ignored && array_key_exists($key, $data)) { + if (method_exists($constructorParameter, 'isVariadic') && $constructorParameter->isVariadic()) { + if ($allowed && !$ignored && (isset($data[$key]) || array_key_exists($key, $data))) { + if (!is_array($data[$paramName])) { + throw new RuntimeException(sprintf('Cannot create an instance of %s from serialized data because the variadic parameter %s can only accept an array.', $class, $constructorParameter->name)); + } + + $params = array_merge($params, $data[$paramName]); + } + } elseif ($allowed && !$ignored && (isset($data[$key]) || array_key_exists($key, $data))) { $params[] = $data[$key]; // don't run set for a parameter passed to the constructor unset($data[$key]); diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/VariadicConstructorArgsDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/VariadicConstructorArgsDummy.php new file mode 100644 index 0000000000..c04aeba0c4 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/VariadicConstructorArgsDummy.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +class VariadicConstructorArgsDummy +{ + private $foo; + + public function __construct(...$foo) + { + $this->foo = $foo; + } + + public function getFoo() + { + return $this->foo; + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php index 32d729a211..24036292ca 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php @@ -216,6 +216,28 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase $this->assertEquals('test', $obj->getBar()); } + /** + * @requires PHP 5.6 + */ + public function testConstructorDenormalizeWithVariadicArgument() + { + $obj = $this->normalizer->denormalize( + array('foo' => array(1, 2, 3)), + 'Symfony\Component\Serializer\Tests\Fixtures\VariadicConstructorArgsDummy', 'any'); + $this->assertEquals(array(1, 2, 3), $obj->getFoo()); + } + + /** + * @requires PHP 5.6 + */ + public function testConstructorDenormalizeWithMissingVariadicArgument() + { + $obj = $this->normalizer->denormalize( + array(), + 'Symfony\Component\Serializer\Tests\Fixtures\VariadicConstructorArgsDummy', 'any'); + $this->assertEquals(array(), $obj->getFoo()); + } + public function testConstructorWithObjectDenormalize() { $data = new \stdClass(); diff --git a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php index 8634ac5ed6..a238b1754a 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php @@ -162,7 +162,7 @@ class ClassMetadataTest extends \PHPUnit_Framework_TestCase $this->metadata->addPropertyConstraint('firstName', new ConstraintA()); $this->assertTrue($this->metadata->hasPropertyMetadata('firstName')); - $this->assertFalse($this->metadata->hasPropertyMetadata('non_existant_field')); + $this->assertFalse($this->metadata->hasPropertyMetadata('non_existent_field')); } public function testMergeConstraintsKeepsPrivateMembersSeparate() diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 2de62e58bd..ad7ae498ff 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -115,6 +115,9 @@ class Parser $data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap); } } + if ($isRef) { + $this->refs[$isRef] = end($data); + } } elseif (preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P.+?))?\s*$#u', $this->currentLine, $values) && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'")))) { if ($context && 'sequence' == $context) { throw new ParseException('You cannot define a mapping item when in a sequence'); @@ -227,6 +230,9 @@ class Parser $data[$key] = $value; } } + if ($isRef) { + $this->refs[$isRef] = $data[$key]; + } } else { // multiple documents are not supported if ('---' === $this->currentLine) { @@ -284,10 +290,6 @@ class Parser throw new ParseException($error, $this->getRealCurrentLineNb() + 1, $this->currentLine); } - - if ($isRef) { - $this->refs[$isRef] = end($data); - } } if (isset($mbEncoding)) { diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.yml index f8501ddc29..d98810256e 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.yml @@ -21,7 +21,7 @@ ruby: | test: Leading Document Separator todo: true brief: > - You can explicity give an opening + You can explicitly give an opening document separator to your YAML stream. yaml: | --- diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml index fd9910174d..4b67d34100 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.yml @@ -33,6 +33,17 @@ yaml: | isit: tested head: <<: [ *foo , *dong , *foo2 ] + taz: &taz + a: Steve + w: + p: 1234 + nested: + <<: *taz + d: Doug + w: &nestedref + p: 12345 + z: + <<: *nestedref php: | array( 'foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian'), @@ -41,5 +52,7 @@ php: | 'foo2' => array('a' => 'Ballmer'), 'ding' => array('fi', 'fei', 'fo', 'fam'), 'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'), - 'head' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam') + 'head' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam'), + 'taz' => array('a' => 'Steve', 'w' => array('p' => 1234)), + 'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345)) )