diff --git a/core/lib/Drupal/Core/Config/ConfigPrefixLengthException.php b/core/lib/Drupal/Core/Config/ConfigPrefixLengthException.php new file mode 100644 index 0000000000000000000000000000000000000000..d91523845b359701ad104cbf3ddfea9fef6d8410 --- /dev/null +++ b/core/lib/Drupal/Core/Config/ConfigPrefixLengthException.php @@ -0,0 +1,13 @@ +<?php + +/** +* @file +* Contains \Drupal\Core\Config\ConfigPrefixLengthException. +*/ + +namespace Drupal\Core\Config; + +/** + * Exception thrown when the config prefix length is exceeded. + */ +class ConfigPrefixLengthException extends ConfigException {} diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php index 061c2e79f868ca72fe53a56b1ef1bb7d8c124a7c..f82af84299bb6441ac17a2392211ce5b4f13d239 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php @@ -8,12 +8,27 @@ namespace Drupal\Core\Config\Entity; use Drupal\Core\Entity\EntityType; +use Drupal\Core\Config\ConfigPrefixLengthException; +use Drupal\Component\Utility\String; /** - * Provides an implementation of a config entity type and its metadata. + * Provides an implementation of a configuration entity type and its metadata. */ class ConfigEntityType extends EntityType { + /** + * Length limit of the configuration entity prefix. + * + * Most file systems limit a file name's length to 255 characters. In + * order to leave sufficient characters to construct a configuration ID, + * the configuration entity prefix is limited to 83 characters which + * leaves 166 characters for the configuration ID. 5 characters are + * reserved for the file extension. + * + * @see \Drupal\Core\Config\ConfigBase::MAX_NAME_LENGTH + */ + const PREFIX_LENGTH = 83; + /** * Returns the config prefix used by the configuration entity type. * @@ -34,18 +49,25 @@ public function getControllerClasses() { * {@inheritdoc} */ public function getConfigPrefix() { + // Ensure that all configuration entities are prefixed by the name of the + // module that provides the configuration entity type. This ensures that + // default configuration will be created as expected during module + // installation and dependencies can be calculated without the modules that + // provide the entity types being installed. if (isset($this->config_prefix)) { - $config_prefix = $this->config_prefix; + $config_prefix = $this->provider . '.' . $this->config_prefix; } else { - $config_prefix = $this->id(); + $config_prefix = $this->provider . '.' . $this->id(); + } + + if (strlen($config_prefix) > static::PREFIX_LENGTH) { + throw new ConfigPrefixLengthException(String::format('The configuration file name prefix @config_prefix exceeds the maximum character limit of @max_char.', array( + '@config_prefix' => $config_prefix, + '@max_char' => static::PREFIX_LENGTH, + ))); } - // Ensure that all configuration entities are prefixed by the module that - // provides the configuration entity type. This ensures that default - // configuration will be created as expected during module install and - // dependencies can be calculated without the modules that provide the - // entity types being installed. - return $this->provider . '.' . $config_prefix; + return $config_prefix; } /** diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityTypeTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6befb00db35c591f3e6d2264edce15e937528246 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityTypeTest.php @@ -0,0 +1,133 @@ +<?php + +/** + * @file + * Contains \Drupal\Tests\Core\Config\Entity\ConfigEntityTypeTest. + */ + +namespace Drupal\Tests\Core\Config\Entity; + +use Drupal\Tests\UnitTestCase; +use Drupal\Core\Config\Entity\ConfigEntityType; +use Drupal\Component\Utility\String; + +/** + * @coversDefaultClass \Drupal\Core\Config\Entity\ConfigEntityType + * + * @group Drupal + * @group Config + */ +class ConfigEntityTypeTest extends UnitTestCase { + + /** + * {@inheritdoc} + */ + public static function getInfo() { + return array( + 'description' => '', + 'name' => '\Drupal\Core\Config\Entity\ConfigEntityType unit test', + 'group' => 'Entity', + ); + } + + + /** + * Tests that we get an exception when the length of the config prefix that is + * returned by getConfigPrefix() exceeds the maximum defined prefix length. + * + * @dataProvider providerPrefixLengthExceeds + * @covers ::getConfigPrefix() + */ + public function testConfigPrefixLengthExceeds($entity_data, $exception, $message) { + $config_entity = new ConfigEntityType($entity_data); + $this->setExpectedException($exception, $message); + $this->assertEmpty($config_entity->getConfigPrefix()); + } + + /** + * Provides arguments to instantiate a ConfigEntityType with a configuration + * entity prefix that exceeds the maximum character length. + * + * @return array + */ + public function providerPrefixLengthExceeds() { + $test_parameters = array(); + $message_text = 'The configuration file name prefix @config_prefix exceeds the maximum character limit of @max_char.'; + + // A provider length of 24 and id length of 59 (+1 for the .) results + // in a config length of 84, which is too long. + $entity_data = array( + 'provider' => $this->randomName(24), + 'id' => $this->randomName(59), + ); + $test_parameters[] = array( + $entity_data, + '\Drupal\Core\Config\ConfigPrefixLengthException', + String::format($message_text, array( + '@config_prefix' => $entity_data['provider'] . '.' . $entity_data['id'], + '@max_char' => ConfigEntityType::PREFIX_LENGTH, + )), + ); + + // A provider length of 24 and config_prefix length of 59 (+1 for the .) + // results in a config length of 84, which is too long. + $entity_data = array( + 'provider' => $this->randomName(24), + 'config_prefix' => $this->randomName(59), + ); + $test_parameters[] = array( + $entity_data, + '\Drupal\Core\Config\ConfigPrefixLengthException', + String::format($message_text, array( + '@config_prefix' => $entity_data['provider'] . '.' . $entity_data['config_prefix'], + '@max_char' => ConfigEntityType::PREFIX_LENGTH, + )), + ); + + return $test_parameters; + } + + /** + * Tests that a valid config prefix returned by getConfigPrefix() + * does not throw an exception and is formatted as expected. + * + * @dataProvider providerPrefixLengthValid + * @covers ::getConfigPrefix() + */ + public function testConfigPrefixLengthValid($entity_data) { + $config_entity = new ConfigEntityType($entity_data); + if (isset($entity_data['config_prefix'])) { + $expected_prefix = $entity_data['provider'] . '.' . $entity_data['config_prefix']; + } else { + $expected_prefix = $entity_data['provider'] . '.' . $entity_data['id']; + } + $this->assertEquals($expected_prefix, $config_entity->getConfigPrefix()); + } + + /** + * Provides arguments to instantiate a ConfigEntityType with a configuration + * entity prefix that does not exceed the maximum character length. + * + * @return array + */ + public function providerPrefixLengthValid() { + $test_parameters = array(); + + // A provider length of 24 and config_prefix length of 58 (+1 for the .) + // results in a config length of 83, which is right at the limit. + $test_parameters[] = array(array( + 'provider' => $this->randomName(24), + 'config_prefix' => $this->randomName(58), + )); + + // A provider length of 24 and id length of 58 (+1 for the .) results in a + // config length of 83, which is right at the limit. + $test_parameters[] = array(array( + 'provider' => $this->randomName(24), + 'id' => $this->randomName(58), + )); + + return $test_parameters; + } + +}