diff --git a/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php b/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php index 3d103e215c..617dd5c3fa 100644 --- a/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php +++ b/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php @@ -56,15 +56,15 @@ class DbalLogger implements SQLLogger } // non utf-8 strings break json encoding - if (!preg_match('#[\p{L}\p{N} ]#u', $params[$index])) { + if (!preg_match('//u', $params[$index])) { $params[$index] = self::BINARY_DATA_VALUE; continue; } // detect if the too long string must be shorten - if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($params[$index])) { - if (self::MAX_STRING_LENGTH < mb_strlen($params[$index], $encoding)) { - $params[$index] = mb_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, $encoding).' [...]'; + if (function_exists('mb_strlen')) { + if (self::MAX_STRING_LENGTH < mb_strlen($params[$index], 'UTF-8')) { + $params[$index] = mb_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, 'UTF-8').' [...]'; continue; } } else { diff --git a/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php b/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php index 741c894e33..0c39008d49 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php @@ -43,7 +43,10 @@ class DbalLoggerTest extends \PHPUnit_Framework_TestCase return array( array('SQL', null, array()), array('SQL', array(), array()), - array('SQL', array('foo' => 'bar'), array('foo' => 'bar')) + array('SQL', array('foo' => 'bar'), array('foo' => 'bar')), + array('SQL', array('foo' => "\x7F\xFF"), array('foo' => DbalLogger::BINARY_DATA_VALUE)), + array('SQL', array('foo' => "bar\x7F\xFF"), array('foo' => DbalLogger::BINARY_DATA_VALUE)), + array('SQL', array('foo' => ''), array('foo' => '')), ); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 527dcbb71f..3755afdf14 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -513,7 +513,7 @@ class PhpDumper extends Dumper if ($definition->isSynthetic()) { $return[] = '@throws RuntimeException always since this service is expected to be injected dynamically'; } elseif ($class = $definition->getClass()) { - $return[] = sprintf("@return %s A %s instance.", 0 === strpos($class, '%') ? 'object' : $class, $class); + $return[] = sprintf("@return %s A %s instance.", 0 === strpos($class, '%') ? 'object' : "\\".$class, $class); } elseif ($definition->getFactoryClass()) { $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryClass(), $definition->getFactoryMethod()); } elseif ($definition->getFactoryService()) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index ca9695adca..37927a6e70 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -44,7 +44,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return stdClass A stdClass instance. + * @return \stdClass A stdClass instance. */ protected function getTestService() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.php index 58697423f6..0dcd83845a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.php @@ -42,7 +42,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return stdClass A stdClass instance. + * @return \stdClass A stdClass instance. */ protected function getFooService() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index 3fafcf1757..84036928bf 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -47,7 +47,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return FooClass A FooClass instance. + * @return \FooClass A FooClass instance. */ protected function getBarService() { @@ -64,7 +64,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return Baz A Baz instance. + * @return \Baz A Baz instance. */ protected function getBazService() { @@ -81,7 +81,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return stdClass A stdClass instance. + * @return \stdClass A stdClass instance. */ protected function getDependsOnRequestService() { @@ -98,7 +98,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return Bar A Bar instance. + * @return \Bar A Bar instance. */ protected function getFactoryServiceService() { @@ -111,7 +111,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return FooClass A FooClass instance. + * @return \FooClass A FooClass instance. */ protected function getFooService() { @@ -164,7 +164,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return Foo A Foo instance. + * @return \Foo A Foo instance. */ protected function getFooWithInlineService() { @@ -181,7 +181,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return FooClass A FooClass instance. + * @return \FooClass A FooClass instance. */ protected function getMethodCall1Service() { @@ -235,7 +235,7 @@ class ProjectServiceContainer extends Container * If you want to be able to request this service from the container directly, * make it public, otherwise you might end up with broken code. * - * @return Bar A Bar instance. + * @return \Bar A Bar instance. */ protected function getInlinedService() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 9ea738db71..0dd611e90c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -55,7 +55,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return FooClass A FooClass instance. + * @return \FooClass A FooClass instance. */ protected function getBarService() { @@ -72,7 +72,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return Baz A Baz instance. + * @return \Baz A Baz instance. */ protected function getBazService() { @@ -89,7 +89,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return stdClass A stdClass instance. + * @return \stdClass A stdClass instance. */ protected function getDependsOnRequestService() { @@ -106,7 +106,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return Bar A Bar instance. + * @return \Bar A Bar instance. */ protected function getFactoryServiceService() { @@ -119,7 +119,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return FooClass A FooClass instance. + * @return \FooClass A FooClass instance. */ protected function getFooService() { @@ -143,7 +143,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return BazClass A BazClass instance. + * @return \BazClass A BazClass instance. */ protected function getFoo_BazService() { @@ -157,7 +157,7 @@ class ProjectServiceContainer extends Container /** * Gets the 'foo_bar' service. * - * @return FooClass A FooClass instance. + * @return \FooClass A FooClass instance. */ protected function getFooBarService() { @@ -170,7 +170,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return Foo A Foo instance. + * @return \Foo A Foo instance. */ protected function getFooWithInlineService() { @@ -192,7 +192,7 @@ class ProjectServiceContainer extends Container * This service is shared. * This method always returns the same instance of the service. * - * @return FooClass A FooClass instance. + * @return \FooClass A FooClass instance. */ protected function getMethodCall1Service() { diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index a701eb724e..deabe57226 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -259,7 +259,9 @@ class Crawler extends \SplObjectStorage public function addNodeList(\DOMNodeList $nodes) { foreach ($nodes as $node) { - $this->addNode($node); + if ($node instanceof \DOMNode) { + $this->addNode($node); + } } } @@ -871,18 +873,22 @@ class Crawler extends \SplObjectStorage // BC for Symfony 2.4 and lower were elements were adding in a fake _root parent if (0 === strpos($expression, '/_root/')) { $expression = './'.substr($expression, 7); + } elseif (0 === strpos($expression, 'self::*/')) { + $expression = './'.substr($expression, 8); } // add prefix before absolute element selector if (empty($expression)) { $expression = $nonMatchingExpression; } elseif (0 === strpos($expression, '//')) { - $expression = 'descendant-or-self::' . substr($expression, 2); + $expression = 'descendant-or-self::'.substr($expression, 2); } elseif (0 === strpos($expression, './/')) { - $expression = 'descendant-or-self::' . substr($expression, 3); + $expression = 'descendant-or-self::'.substr($expression, 3); } elseif (0 === strpos($expression, './')) { - $expression = 'self::' . substr($expression, 2); - } elseif ('/' === $expression[0]) { + $expression = 'self::'.substr($expression, 2); + } elseif (0 === strpos($expression, 'child::')) { + $expression = 'self::'.substr($expression, 7); + } elseif ('/' === $expression[0] || 0 === strpos($expression, 'self::')) { // the only direct child in Symfony 2.4 and lower is _root, which is already handled previously // so let's drop the expression entirely $expression = $nonMatchingExpression; @@ -890,9 +896,12 @@ class Crawler extends \SplObjectStorage // '.' is the fake root element in Symfony 2.4 and lower, which is excluded from results $expression = $nonMatchingExpression; } elseif (0 === strpos($expression, 'descendant::')) { - $expression = 'descendant-or-self::' . substr($expression, strlen('descendant::')); - } elseif (!preg_match('/^(ancestor|ancestor-or-self|attribute|child|descendant-or-self|following|following-sibling|parent|preceding|preceding-sibling|self)::/', $expression)) { - $expression = 'self::' .$expression; + $expression = 'descendant-or-self::'.substr($expression, strlen('descendant::')); + } elseif (preg_match('/^(ancestor|ancestor-or-self|attribute|following|following-sibling|namespace|parent|preceding|preceding-sibling)::/', $expression)) { + // the fake root has no parent, preceding or following nodes and also no attributes (even no namespace attributes) + $expression = $nonMatchingExpression; + } elseif (0 !== strpos($expression, 'descendant-or-self::')) { + $expression = 'self::'.$expression; } $expressions[] = $parenthesis.$expression; } diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index 9895f30637..e0b9cfb062 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -11,6 +11,7 @@ namespace Symfony\Component\DomCrawler; +use Symfony\Component\DomCrawler\Field\ChoiceFormField; use Symfony\Component\DomCrawler\Field\FormField; /** @@ -460,7 +461,9 @@ class Form extends Link implements \ArrayAccess if ('select' == $nodeName || 'input' == $nodeName && 'checkbox' == strtolower($node->getAttribute('type'))) { $this->set(new Field\ChoiceFormField($node)); } elseif ('input' == $nodeName && 'radio' == strtolower($node->getAttribute('type'))) { - if ($this->has($node->getAttribute('name'))) { + // there may be other fields with the same name that are no choice + // fields already registered (see https://github.com/symfony/symfony/issues/11689) + if ($this->has($node->getAttribute('name')) && $this->get($node->getAttribute('name')) instanceof ChoiceFormField) { $this->get($node->getAttribute('name'))->addChoice($node); } else { $this->set(new Field\ChoiceFormField($node)); diff --git a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php index c228b39b2d..72e9dadae5 100644 --- a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php @@ -400,8 +400,8 @@ EOF $this->assertCount(1, $crawler->filterXPath('//body')); $this->assertCount(1, $crawler->filterXPath('descendant-or-self::body')); $this->assertCount(1, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('./div'), 'A child selection finds only the current div'); - $this->assertCount(2, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('descendant::div'), 'A descendant selector matches the current div and its child'); - $this->assertCount(2, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('//div'), 'A descendant selector matches the current div and its child'); + $this->assertCount(3, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('descendant::div'), 'A descendant selector matches the current div and its child'); + $this->assertCount(3, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('//div'), 'A descendant selector matches the current div and its child'); $this->assertCount(5, $crawler->filterXPath('(//a | //div)//img')); $this->assertCount(7, $crawler->filterXPath('((//a | //div)//img | //ul)')); $this->assertCount(7, $crawler->filterXPath('( ( //a | //div )//img | //ul )')); @@ -472,72 +472,104 @@ EOF $this->assertSame('Music', $crawler->text()); } + public function testFilterXPathWithFakeRoot() + { + $crawler = $this->createTestCrawler(); + $this->assertCount(0, $crawler->filterXPath('.'), '->filterXPath() returns an empty result if the XPath references the fake root node'); + $this->assertCount(0, $crawler->filterXPath('/_root'), '->filterXPath() returns an empty result if the XPath references the fake root node'); + $this->assertCount(0, $crawler->filterXPath('self::*'), '->filterXPath() returns an empty result if the XPath references the fake root node'); + $this->assertCount(0, $crawler->filterXPath('self::_root'), '->filterXPath() returns an empty result if the XPath references the fake root node'); + } + public function testFilterXPathWithAncestorAxis() { $crawler = $this->createTestCrawler()->filterXPath('//form'); - $this->assertCount(2, $crawler->filterXPath('ancestor::*')); + $this->assertCount(0, $crawler->filterXPath('ancestor::*'), 'The fake root node has no ancestor nodes'); } public function testFilterXPathWithAncestorOrSelfAxis() { $crawler = $this->createTestCrawler()->filterXPath('//form'); - $this->assertCount(3, $crawler->filterXPath('ancestor-or-self::*')); + $this->assertCount(0, $crawler->filterXPath('ancestor-or-self::*'), 'The fake root node has no ancestor nodes'); } public function testFilterXPathWithAttributeAxis() { $crawler = $this->createTestCrawler()->filterXPath('//form'); - $this->assertCount(2, $crawler->filterXPath('attribute::*')); + $this->assertCount(0, $crawler->filterXPath('attribute::*'), 'The fake root node has no attribute nodes'); + } + + public function testFilterXPathWithAttributeAxisAfterElementAxis() + { + $this->assertCount(3, $this->createTestCrawler()->filterXPath('//form/button/attribute::*'), '->filterXPath() handles attribute axes properly when they are preceded by an element filtering axis'); } public function testFilterXPathWithChildAxis() { - $crawler = $this->createTestCrawler()->filterXPath('//body'); + $crawler = $this->createTestCrawler()->filterXPath('//div[@id="parent"]'); - $this->assertCount(2, $crawler->filterXPath('child::input')); + $this->assertCount(1, $crawler->filterXPath('child::div'), 'A child selection finds only the current div'); } public function testFilterXPathWithFollowingAxis() { $crawler = $this->createTestCrawler()->filterXPath('//a'); - $this->assertCount(3, $crawler->filterXPath('following::div')); + $this->assertCount(0, $crawler->filterXPath('following::div'), 'The fake root node has no following nodes'); } public function testFilterXPathWithFollowingSiblingAxis() { $crawler = $this->createTestCrawler()->filterXPath('//a'); - $this->assertCount(2, $crawler->filterXPath('following-sibling::div')); + $this->assertCount(0, $crawler->filterXPath('following-sibling::div'), 'The fake root node has no following nodes'); + } + + public function testFilterXPathWithNamespaceAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//button'); + + $this->assertCount(0, $crawler->filterXPath('namespace::*'), 'The fake root node has no namespace nodes'); + } + + public function testFilterXPathWithNamespaceAxisAfterElementAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//div[@id="parent"]/namespace::*'); + + $this->assertCount(0, $crawler->filterXPath('namespace::*'), 'Namespace axes cannot be requested'); } public function testFilterXPathWithParentAxis() { $crawler = $this->createTestCrawler()->filterXPath('//button'); - $this->assertEquals('foo', $crawler->filterXPath('parent::*')->attr('action')); + $this->assertCount(0, $crawler->filterXPath('parent::*'), 'The fake root node has no parent nodes'); } public function testFilterXPathWithPrecedingAxis() { $crawler = $this->createTestCrawler()->filterXPath('//form'); - $this->assertCount(13, $crawler->filterXPath('preceding::*')); + $this->assertCount(0, $crawler->filterXPath('preceding::*'), 'The fake root node has no preceding nodes'); } public function testFilterXPathWithPrecedingSiblingAxis() { $crawler = $this->createTestCrawler()->filterXPath('//form'); - $this->assertCount(9, $crawler->filterXPath('preceding-sibling::*')); + $this->assertCount(0, $crawler->filterXPath('preceding-sibling::*'), 'The fake root node has no preceding nodes'); } public function testFilterXPathWithSelfAxes() { - $this->assertCount(1, $this->createTestCrawler()->filterXPath('self::*')); + $crawler = $this->createTestCrawler()->filterXPath('//a'); + + $this->assertCount(0, $crawler->filterXPath('self::a'), 'The fake root node has no "real" element name'); + $this->assertCount(0, $crawler->filterXPath('self::a/img'), 'The fake root node has no "real" element name'); + $this->assertCount(9, $crawler->filterXPath('self::*/a')); } /** @@ -947,6 +979,7 @@ HTML;
+
diff --git a/src/Symfony/Component/DomCrawler/Tests/FormTest.php b/src/Symfony/Component/DomCrawler/Tests/FormTest.php index 8f18f01086..4e3cad74b1 100644 --- a/src/Symfony/Component/DomCrawler/Tests/FormTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/FormTest.php @@ -802,6 +802,28 @@ class FormTest extends \PHPUnit_Framework_TestCase )); } + public function testDifferentFieldTypesWithSameName() + { + $dom = new \DOMDocument(); + $dom->loadHTML(' + + +
+ + + + + + +
+ + + '); + $form = new Form($dom->getElementsByTagName('form')->item(0), 'http://example.com'); + + $this->assertInstanceOf('Symfony\Component\DomCrawler\Field\ChoiceFormField', $form->get('option')); + } + protected function getFormFieldMock($name, $value = null) { $field = $this diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php index 618fc6b4a4..ffc9915fa4 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php @@ -64,7 +64,7 @@ class ValueToDuplicatesTransformer implements DataTransformerInterface $emptyKeys = array(); foreach ($this->keys as $key) { - if (!empty($array[$key])) { + if (isset($array[$key]) && '' !== $array[$key] && false !== $array[$key] && array() !== $array[$key]) { if ($array[$key] !== $result) { throw new TransformationFailedException( 'All values in the array should be the same' diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php index 2c5298da50..a8a088a95a 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php @@ -82,6 +82,29 @@ class ValueToDuplicatesTransformerTest extends \PHPUnit_Framework_TestCase $this->assertNull($this->transformer->reverseTransform($input)); } + public function testReverseTransformEmptyArray() + { + $input = array( + 'a' => array(), + 'b' => array(), + 'c' => array(), + ); + + $this->assertNull($this->transformer->reverseTransform($input)); + } + + + public function testReverseTransformZeroString() + { + $input = array( + 'a' => '0', + 'b' => '0', + 'c' => '0' + ); + + $this->assertSame('0', $this->transformer->reverseTransform($input)); + } + /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index 5838b8d341..8a95f51286 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -219,7 +219,7 @@ class XmlFileLoader extends FileLoader foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { switch ($n->localName) { case 'default': - if ($n->hasAttribute('xsi:nil') && 'true' == $n->getAttribute('xsi:nil')) { + if ($this->isElementValueNull($n)) { $defaults[$n->getAttribute('key')] = null; } else { $defaults[$n->getAttribute('key')] = trim($n->textContent); @@ -242,4 +242,15 @@ class XmlFileLoader extends FileLoader return array($defaults, $requirements, $options, $condition); } + + private function isElementValueNull(\DOMElement $element) + { + $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance'; + + if (!$element->hasAttributeNS($namespaceUri, 'nil')) { + return false; + } + + return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil'); + } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/null_values.xml b/src/Symfony/Component/Routing/Tests/Fixtures/null_values.xml new file mode 100644 index 0000000000..f9e2aa24df --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/null_values.xml @@ -0,0 +1,12 @@ + + + + + + + foo + bar + + diff --git a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php index f83b9ecba8..e6f0afd3ff 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php @@ -121,4 +121,18 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); $loader->load('withdoctype.xml'); } + + public function testNullValues() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $routeCollection = $loader->load('null_values.xml'); + $route = $routeCollection->get('blog_show'); + + $this->assertTrue($route->hasDefault('foo')); + $this->assertNull($route->getDefault('foo')); + $this->assertTrue($route->hasDefault('bar')); + $this->assertNull($route->getDefault('bar')); + $this->assertEquals('foo', $route->getDefault('foobar')); + $this->assertEquals('bar', $route->getDefault('baz')); + } } diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php b/src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php index abc18b438b..79fa69f8a9 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php @@ -49,7 +49,7 @@ interface VoterInterface * ACCESS_GRANTED, ACCESS_DENIED, or ACCESS_ABSTAIN. * * @param TokenInterface $token A TokenInterface instance - * @param object $object The object to secure + * @param object|null $object The object to secure * @param array $attributes An array of attributes associated with the method being invoked * * @return int either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED