diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index f69a52b..619bd51 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -80,6 +80,21 @@ protected $dependencies = array(); /** + * The maximum length of a configuration object ID. + * + * Many filesystems (including HFS, NTFS, and ext4) have a maximum file name + * length of 255 characters. To ensure that no configuration objects + * incompatible with this limitation are created, we enforce a maximum name + * length of 250 characters (leaving 5 characters for the file extension). + * + * @see http://en.wikipedia.org/wiki/Comparison_of_file_systems + * + * 50 characters of the 250 is reserved for the module name, + * 32 characters for the config prefix, that leaves 166 characters for the ID length. + */ + const MAX_ID_LENGTH = 166; + + /** * The language code of the entity's default language. * * @var string @@ -259,6 +274,13 @@ public function toArray() { public function preSave(EntityStorageControllerInterface $storage_controller) { parent::preSave($storage_controller); + if (strlen($this->id()) > self::MAX_ID_LENGTH) { + throw new \Drupal\Core\Config\ConfigNameException(String::format('Config entity machine name (id) @name exceeds maximum allowed length of @length characters.', array( + '@name' => $this->id(), + '@length' => self::MAX_ID_LENGTH, + ))); + } + // @todo When \Drupal\Core\Config\Entity\EntityWithPluginBagInterface moves // to a trait, switch to class_uses() instead. if ($this instanceof EntityWithPluginBagInterface) { diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php index 9deeaa6..1b5ab4d 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php @@ -171,6 +171,36 @@ public function testPreSaveDuringSync() { } /** + * @covers ::preSave + */ + public function testPreSaveWithLongId() { + $query = $this->getMock('\Drupal\Core\Entity\Query\QueryInterface'); + $storage = $this->getMock('\Drupal\Core\Config\Entity\ConfigStorageControllerInterface'); + + $query->expects($this->any()) + ->method('execute') + ->will($this->returnValue(array())); + $query->expects($this->any()) + ->method('condition') + ->will($this->returnValue($query)); + $storage->expects($this->any()) + ->method('getQuery') + ->will($this->returnValue($query)); + $storage->expects($this->any()) + ->method('loadUnchanged') + ->will($this->returnValue($this->entity)); + + // Entity ID must not be longer than 166 characters + $this->entity->set('dependencies', array('module' => array('node'))); + $this->entity->id = $this->randomName(\Drupal\Core\Config\Entity\ConfigEntityBase::MAX_ID_LENGTH); + $this->entity->preSave($storage); + + $this->entity->id = $this->randomName(\Drupal\Core\Config\Entity\ConfigEntityBase::MAX_ID_LENGTH + 1); + $this->setExpectedException('\Drupal\Core\Config\ConfigNameException'); + $this->entity->preSave($storage); + } + + /** * @covers ::addDependency */ public function testAddDependency() {