summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2014-10-15 10:06:55 (GMT)
committerNathaniel Catchpole2014-10-15 10:06:55 (GMT)
commitd3f8b78c008bc115b8cd0a035f60ab7c6f47c3a4 (patch)
tree927371159d7e0ddeda39f414fbdf8e51d6657428
parent9d5d3b3b5cac64654a8ec6249cf831f281c9d48f (diff)
Issue #1003788 by stefan.r, Alan D., JimmyAx, Josh Waihi, john_brown, bellHead, twistor, wiifm, bzrudi71, pwolanin, gngn, Gisle, robhardwick: Fixed PostgreSQL: PDOException:Invalid text representation when attempting to load an entity with a string or non-scalar ID.
-rw-r--r--core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php30
-rw-r--r--core/modules/system/src/Tests/Entity/EntityViewControllerTest.php5
-rw-r--r--core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php69
3 files changed, 104 insertions, 0 deletions
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 23b8cb0..be561a6 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -427,6 +427,12 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
protected function getFromStorage(array $ids = NULL) {
$entities = array();
+ if (!empty($ids)) {
+ // Sanitize IDs. Before feeding ID array into buildQuery, check whether
+ // it is empty as this would load all entities.
+ $ids = $this->cleanIds($ids);
+ }
+
if ($ids === NULL || $ids) {
// Build and execute the query.
$query_result = $this->buildQuery($ids)->execute();
@@ -453,6 +459,30 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
}
/**
+ * Ensures integer entity IDs are valid.
+ *
+ * The identifier sanitization provided by this method has been introduced
+ * as Drupal used to rely on the database to facilitate this, which worked
+ * correctly with MySQL but led to errors with other DBMS such as PostgreSQL.
+ *
+ * @param array $ids
+ * The entity IDs to verify.
+ * @return array
+ * The sanitized list of entity IDs.
+ */
+ protected function cleanIds(array $ids) {
+ $definitions = $this->entityManager->getBaseFieldDefinitions($this->entityTypeId);
+ $id_definition = $definitions[$this->entityType->getKey('id')];
+ if ($id_definition->getType() == 'integer') {
+ $ids = array_filter($ids, function ($id) {
+ return is_numeric($id) && $id == (int) $id;
+ });
+ $ids = array_map('intval', $ids);
+ }
+ return $ids;
+ }
+
+ /**
* Gets entities from the persistent cache backend.
*
* @param array|null &$ids
diff --git a/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php b/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php
index 656d8c9..1b4dc6b 100644
--- a/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php
@@ -70,6 +70,11 @@ class EntityViewControllerTest extends WebTestBase {
$this->assertRaw($entity->label());
$this->assertRaw('full');
}
+
+ // As entity_test IDs must be integers, make sure requests for non-integer
+ // IDs return a page not found error.
+ $this->drupalGet('entity_test/invalid');
+ $this->assertResponse(404);
}
/**
diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
index 420afba..d86fe33 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
@@ -1181,6 +1181,75 @@ class SqlContentEntityStorageTest extends UnitTestCase {
}
/**
+ * Tests entity ID sanitization.
+ */
+ public function testCleanIds() {
+ $valid_ids = array(
+ -1,
+ 0,
+ 1,
+ '-1',
+ '0',
+ '1',
+ 0123,
+ -0x1A,
+ 0x1AFC,
+ -0b111,
+ 0b101,
+ '0123',
+ '00123',
+ '000123',
+ '-0123',
+ '-00123',
+ '-000123',
+ -10.0,
+ -1.0,
+ 0.0,
+ 1.0,
+ 10.0,
+ -10.00,
+ -1.00,
+ 0.00,
+ 1.00,
+ 10.00,
+ );
+
+ $this->fieldDefinitions = $this->mockFieldDefinitions(array('id'));
+ $this->fieldDefinitions['id']->expects($this->any())
+ ->method('getType')
+ ->will($this->returnValue('integer'));
+
+ $this->setUpEntityStorage();
+
+ $this->entityType->expects($this->any())
+ ->method('getKey')
+ ->will($this->returnValueMap(array(
+ array('id', 'id'),
+ )));
+
+ $method = new \ReflectionMethod($this->entityStorage, 'cleanIds');
+ $method->setAccessible(TRUE);
+ $this->assertEquals($valid_ids, $method->invoke($this->entityStorage, $valid_ids));
+
+ $invalid_ids = array(
+ '--1',
+ '-0x1A',
+ '0x1AFC',
+ '-0b111',
+ '0b101',
+ 'a',
+ FALSE,
+ TRUE,
+ NULL,
+ '32acb',
+ 123.123,
+ 123.678,
+ );
+ $this->assertEquals(array(), $method->invoke($this->entityStorage, $invalid_ids));
+
+ }
+
+ /**
* Sets up the module handler with no implementations.
*/
protected function setUpModuleHandlerNoImplementations() {