diff --git a/core/lib/Drupal/Core/Template/Attribute.php b/core/lib/Drupal/Core/Template/Attribute.php index 3967cf8..698ce85 100644 --- a/core/lib/Drupal/Core/Template/Attribute.php +++ b/core/lib/Drupal/Core/Template/Attribute.php @@ -100,7 +100,7 @@ protected function createAttributeValue($name, $value) { $value = new AttributeString($name, $value); } // Provide a better exception message when invalid object is passed as value. - elseif (is_object($value) && !method_exists($value, '__toString')) { + elseif (is_object($value)) { throw new \Exception(t('"@attribute_name" attribute value of type "@class" can not be converted to string', array( '@attribute_name' => $name, '@class' => get_class($value) diff --git a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php index bcd04a2..0a83173 100644 --- a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php +++ b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Template\Attribute; use Drupal\Core\Template\AttributeArray; +use Drupal\Core\Template\AttributeBoolean; use Drupal\Core\Template\AttributeString; use Drupal\Tests\UnitTestCase; @@ -227,4 +228,111 @@ public function testStorage() { $this->assertEquals(array('class' => new AttributeArray('class', array('example-class'))), $attribute->storage()); } + /** + * PHPUnit's data provider callback. + * + * @see $this->testCreateAttributeValue() + * @return array + */ + public function createAttributeValuesProvider() { + $testCases = array(); + + // Test pure strings. + $name = $this->randomMachineName(); + $value = $this->randomMachineName(); + $result = new AttributeString($name, $value); + $testCases[] = array($name, $value, $result); + + // Test AttributeValue instance passed as value. + $value = $this->getMock('Drupal\Core\Template\AttributeValueBase'); + $result = $value; + $testCases[] = array($name, $value, $result); + + // Test array passed as value. + $value = array($this->getRandomGenerator()->string(), $this->getRandomGenerator()->string() => $this->getRandomGenerator()->string()); + $result = new AttributeArray($name, $value); + $testCases[] = array($name, $value, $result); + + // Test random value passed with 'class' name. + $value = $this->getRandomGenerator()->object(); + $name = 'class'; + $result = new AttributeArray($name, (array) $value); + $testCases[] = array($name, $value, $result); + + // Test boolean value. + $value = FALSE; + $name = $this->randomMachineName(); + $result = new AttributeBoolean($name, $value); + $testCases[] = array($name, $value, $result); + + // Lets test TRUE as well because php type casting brings surprises sometimes. + $value = TRUE; + $result = new AttributeBoolean($name, $value); + $testCases[] = array($name, $value, $result); + + // Test NULL as value. + $value = NULL; + $result = new AttributeString($name, $value); + $testCases[] = array($name, $value, $result); + + return $testCases; + } + + /** + * @covers ::createAttributeValue() + * @dataProvider createAttributeValuesProvider + */ + public function testCreateAttributeValue($name, $value, $result) { + $attribute = new Attribute(); + $createAttributeValueMethod = $this->getCreateAttributeValueMethod(); + + $this->assertEquals($result, $createAttributeValueMethod->invokeArgs($attribute, array($name, $value))); + } + + /** + * PHPUnit's data provider callback to test exceptions. + * + * @see $this->testCreateAttributeValueException() + * @return array + */ + public function createAttributeValueExceptionProvider() { + $testCases = array(); + + // Test passed object without 'class' as name. + $name = $this->getRandomGenerator()->string(); + $value = $this->getRandomGenerator()->object(); + $testCases[] = array($name, $value); + + // Test object with render and __toString methods present + // but it is not instance of AttributeValueBase. + $value = $this->getMock('Drupal\Core\StringTranslation\TranslationWrapper'); + $testCases[] = array($name, $value); + + return $testCases; + } + + /** + * @covers ::createAttributeValue() + * @dataProvider createAttributeValueExceptionProvider + * @expectedException \Exception + */ + public function testCreateAttributeValueException($name, $value) { + $attribute = new Attribute(); + $createAttributeValueMethod = $this->getCreateAttributeValueMethod(); + $createAttributeValueMethod->invokeArgs($attribute, array($name, $value)); + } + + /** + * Helper method to get protected createAttributeValue method. + * + * @return \ReflectionMethod + */ + protected function getCreateAttributeValueMethod() { + $attributeClass = new \ReflectionClass('Drupal\Core\Template\Attribute'); + $method = $attributeClass->getMethod('createAttributeValue'); + $method->setAccessible(TRUE); + return $method; + } + } +