diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 10bf925..2195eb7 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -296,6 +296,19 @@ class Config { return $this; } + /* + * Renames the configuration object. + * + * @param $new_name + * The new name of the configuration object being constructed. + */ + public function rename($new_name) { + if ($this->storage->rename($this->name, $new_name)) { + $this->name = $new_name; + } + return $this; + } + /** * Sorts all keys in configuration data. * diff --git a/core/lib/Drupal/Core/Config/DatabaseStorage.php b/core/lib/Drupal/Core/Config/DatabaseStorage.php index 92aea45..ad8c155 100644 --- a/core/lib/Drupal/Core/Config/DatabaseStorage.php +++ b/core/lib/Drupal/Core/Config/DatabaseStorage.php @@ -99,6 +99,20 @@ class DatabaseStorage implements StorageInterface { ->execute(); } + + /** + * Implements Drupal\Core\Config\StorageInterface::rename(). + * + * @throws PDOException + */ + public function rename($name, $new_name) { + $options = array('return' => Database::RETURN_AFFECTED) + $this->options; + return (bool) $this->getConnection()->update('config', $options) + ->fields(array('name' => $new_name)) + ->condition('name', $name) + ->execute(); + } + /** * Implements Drupal\Core\Config\StorageInterface::encode(). */ diff --git a/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php index 033555d..0a41506 100644 --- a/core/lib/Drupal/Core/Config/FileStorage.php +++ b/core/lib/Drupal/Core/Config/FileStorage.php @@ -108,6 +108,17 @@ class FileStorage implements StorageInterface { } /** + * Implements Drupal\Core\Config\StorageInterface::delete(). + */ + public function rename($name, $new_name) { + $status = @rename($this->getFilePath($name), $this->getFilePath($new_name)); + if ($status === FALSE) { + throw new StorageException('Failed to rename configuration file from: ' . $this->getFilePath($name) . ' to: ' . $this->getFilePath($new_name)); + } + return TRUE; + } + + /** * Implements Drupal\Core\Config\StorageInterface::encode(). * * @throws Symfony\Component\Yaml\Exception\DumpException diff --git a/core/lib/Drupal/Core/Config/NullStorage.php b/core/lib/Drupal/Core/Config/NullStorage.php index fede4f0..ea21be1 100644 --- a/core/lib/Drupal/Core/Config/NullStorage.php +++ b/core/lib/Drupal/Core/Config/NullStorage.php @@ -50,6 +50,13 @@ class NullStorage implements StorageInterface { } /** + * Implements Drupal\Core\Config\StorageInterface::rename(). + */ + public function rename($name, $new_name) { + return FALSE; + } + + /** * Implements Drupal\Core\Config\StorageInterface::encode(). */ public static function encode($data) { diff --git a/core/lib/Drupal/Core/Config/StorageInterface.php b/core/lib/Drupal/Core/Config/StorageInterface.php index 806ee87..a466538 100644 --- a/core/lib/Drupal/Core/Config/StorageInterface.php +++ b/core/lib/Drupal/Core/Config/StorageInterface.php @@ -61,6 +61,19 @@ interface StorageInterface { public function delete($name); /** + * Renames a configuration object in the storage. + * + * @param string $name + * The name of a configuration object to rename. + * @param string $new_name + * The new name of a configuration object. + * + * @return bool + * TRUE on success, FALSE otherwise. + */ + public function rename($name, $new_name); + + /** * Encodes configuration data into the storage-specific format. * * @param array $data diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php index 37aa854..a5d36a9 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php @@ -84,6 +84,13 @@ class ConfigCRUDTest extends WebTestBase { $new_config = config($name); $this->assertIdentical($new_config->get(), $config->get()); $this->assertIdentical($config->isNew(), FALSE); + + // Rename the configuration object. + $new_name = 'config_test.crud_rename'; + $config->rename($new_name); + $renamed_config = config($new_name); + $this->assertIdentical($renamed_config->get(), $config->get()); + $this->assertIdentical($renamed_config->isNew(), FALSE); } /** diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php index 2dbc627..d07b0b7 100644 --- a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php +++ b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php @@ -68,6 +68,14 @@ abstract class ConfigStorageTestBase extends WebTestBase { $this->assertFalse(in_array('system.performance', $names)); $this->assertTrue(in_array($name, $names)); + // Rename the configuration storage object. + $new_name = 'config_test.storage_rename'; + $this->storage->rename($name, $new_name); + $raw_data = $this->read($new_name); + $this->assertIdentical($raw_data, $data); + // Rename it back so further tests work. + $this->storage->rename($new_name, $name); + // Deleting an existing name returns TRUE. $result = $this->storage->delete($name); $this->assertIdentical($result, TRUE); @@ -109,6 +117,25 @@ abstract class ConfigStorageTestBase extends WebTestBase { $class = get_class($e); $this->pass($class . ' thrown upon listing from a non-existing storage bin.'); } + + // Test renaming an object that does not exist throws an exception. + try { + $this->storage->rename('config_test.storage_does_not_exist', 'config_test.storage_does_not_exist_rename'); + } + catch (\Exception $e) { + $class = get_class($e); + $this->pass($class . ' thrown upon renaming a nonexistent storage bin.'); + } + + // Test renaming to an object that already exists throws an exception. + try { + $this->storage->rename('system.cron', 'system.performance'); + } + catch (\Exception $e) { + $class = get_class($e); + $this->pass($class . ' thrown upon renaming a nonexistent storage bin.'); + } + } abstract protected function read($name);