diff --git a/core/lib/Drupal/Core/Entity/EntityListController.php b/core/lib/Drupal/Core/Entity/EntityListController.php index 88b2207..09cc203 100644 --- a/core/lib/Drupal/Core/Entity/EntityListController.php +++ b/core/lib/Drupal/Core/Entity/EntityListController.php @@ -9,6 +9,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Component\Utility\String; /** * Provides a generic implementation of an entity list controller. @@ -144,7 +145,7 @@ public function buildHeader() { * @see Drupal\Core\Entity\EntityListController::render() */ public function buildRow(EntityInterface $entity) { - $row['label'] = $entity->label(); + $row['label'] = String::checkPlain($entity->label()); $row['id'] = $entity->id(); $operations = $this->buildOperations($entity); $row['operations']['data'] = $operations; diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListController.php index edd0b8d..87f247c 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListController.php @@ -74,7 +74,7 @@ public function buildRow(EntityInterface $entity) { unset($row['id']); $row['label'] = array( - '#markup' => check_plain($row['label']), + '#markup' => $row['label'], ); $row['#weight'] = $entity->get('weight'); // Add weight column. diff --git a/core/modules/user/lib/Drupal/user/RoleListController.php b/core/modules/user/lib/Drupal/user/RoleListController.php index a2250f5..3f92dfd 100644 --- a/core/modules/user/lib/Drupal/user/RoleListController.php +++ b/core/modules/user/lib/Drupal/user/RoleListController.php @@ -63,7 +63,7 @@ public function buildRow(EntityInterface $entity) { unset($row['id']); $row['label'] = array( - '#markup' => check_plain($row['label']), + '#markup' => $row['label'], ); $row['#weight'] = $entity->get('weight'); // Add weight column. diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityListControllerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityListControllerTest.php new file mode 100644 index 0000000..ead80b5 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Entity/EntityListControllerTest.php @@ -0,0 +1,148 @@ + 'Entity list controller test', + 'description' => 'Unit test of entity access checking system.', + 'group' => 'Entity' + ); + } + + /** + * Entity info used by the test. + * + * @var array + * + * @see entity_get_info() + */ + public static $entityInfo = array( + 'entity_keys' => array( + 'id' => 'id', + 'label' => 'label', + ), + 'config_prefix' => 'user.role', + 'class' => 'Drupal\user\Plugin\Core\Entity\Role', + ); + + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->role = $this + ->getMockBuilder('Drupal\user\Plugin\Core\Entity\Role') + ->setConstructorArgs(array('entityInfo' => static::$entityInfo, 'user_role')) + ->getMock(); + + // Creates a stub role storage controller and replace the buildOperations() + // method with an empty version, because buildOperations() relies on hooks. + $role_storage_controller = $this->getMockBuilder('Drupal\user\RoleStorageController') + ->disableOriginalConstructor() + ->getMock(); + + $module_handler = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandler') + ->disableOriginalConstructor() + ->getMock(); + + $this->entityListController = $this->getMock('Drupal\Core\Entity\EntityListController', array('buildOperations'), array('user_role', static::$entityInfo, $role_storage_controller, $module_handler)); + + $this->entityListController->expects($this->any()) + ->method('buildOperations') + ->will($this->returnValue(array())); + + } + + /** + * Tests that buildRow() returns a string which has been run through + * String::checkPlain(). + * + * @dataProvider providerTestBuildRow + * + * @param string $input + * The entity label being passed into buildRow. + * @param string $expected + * The expected output of the label from buildRow. + * @param string $message + * The message to provide as output for the test. + * @param bool $ignorewarnings + * Whether or not to ignore PHP 5.3+ invalid multibyte sequence warnings. + * + * @see \Drupal\Component\Utility\Drupal\Core\Entity\EntityListController::buildRow() + */ + public function testBuildRow($input, $expected, $message, $ignorewarnings = FALSE) { + $this->role->expects($this->any()) + ->method('label') + ->will($this->returnValue($input)); + + if ($ignorewarnings) { + $built_row = @$this->entityListController->buildRow($this->role); + } + else { + $built_row = $this->entityListController->buildRow($this->role); + } + + $this->assertEquals($built_row['label'], $expected, $message); + } + + /** + * Data provider for testBuildRow(). + * + * @see self::testBuildRow() + * @see \Drupal\Tests\Component\Utility\StringTest::providerCheckPlain() + * + * @return array + * An array containing a string, the expected return from + * String::checkPlain, a message to be output for failures, and whether the + * test should be processed as multibyte. + */ + public function providerTestBuildRow() { + $tests = array(); + // Checks that invalid multi-byte sequences are rejected. + $tests[] = array("Foo\xC0barbaz", '', 'EntityListController::buildRow() rejects invalid sequence "Foo\xC0barbaz"', TRUE); + $tests[] = array("\xc2\"", '', 'EntityListController::buildRow() rejects invalid sequence "\xc2\""', TRUE); + $tests[] = array("Fooÿñ", "Fooÿñ", 'EntityListController::buildRow() accepts valid sequence "Fooÿñ"'); + + // Checks that special characters are escaped. + $tests[] = array("