diff --git a/core/includes/config.inc b/core/includes/config.inc index 00115335d1986c733e9ae505fe63bd4fa3cd803a..1453adeb8a005ddca63c4b56bc9a06e856aa642a 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -253,12 +253,10 @@ function config_import_invoke_owner(array $config_changes, StorageInterface $sou // handle dependencies correctly. foreach (array('delete', 'create', 'change') as $op) { foreach ($config_changes[$op] as $key => $name) { - // Extract owner from configuration object name. - $module = strtok($name, '.'); - // Check whether the module implements hook_config_import() and ask it to - // handle the configuration change. + // Call to the configuration entity's storage controller to handle the + // configuration change. $handled_by_module = FALSE; - if (module_exists($module) && module_hook($module, 'config_import_' . $op)) { + if ($entity_type = config_get_entity_type_by_name($name)) { $old_config = new Config($name, $target_storage); $old_config->load(); @@ -268,7 +266,8 @@ function config_import_invoke_owner(array $config_changes, StorageInterface $sou $new_config->setData($data); } - $handled_by_module = module_invoke($module, 'config_import_' . $op, $name, $new_config, $old_config); + $method = 'import' . ucfirst($op); + $handled_by_module = entity_get_controller($entity_type)->$method($name, $new_config, $old_config); } if (!empty($handled_by_module)) { unset($config_changes[$op][$key]); @@ -297,3 +296,19 @@ function config_get_module_config_entities($module) { return ($entity_info['module'] == $module) && is_subclass_of($entity_info['class'], 'Drupal\Core\Config\Entity\ConfigEntityInterface'); }); } + +/** + * Returns the entity type of a configuration object. + * + * @param string $name + * The configuration object name. + * + * @return string|null + * Either the entity type name, or NULL if none match. + */ +function config_get_entity_type_by_name($name) { + $entities = array_filter(entity_get_info(), function($entity_info) use ($name) { + return (isset($entity_info['config_prefix']) && strpos($name, $entity_info['config_prefix'] . '.') === 0); + }); + return key($entities); +} diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php index 7f60f9d6d6b899d7e912aafcb2de06c2b849c561..b472b8f525efa886ffaf8f6996b81286d3ec9b9e 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php @@ -11,6 +11,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityMalformedException; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Config\Config; /** * Defines the storage controller class for configuration entities. @@ -425,4 +426,76 @@ protected function invokeHook($hook, EntityInterface $entity) { public function getQueryServicename() { throw new \LogicException('Querying configuration entities is not supported.'); } + + /** + * Create configuration upon synchronizing configuration changes. + * + * This callback is invoked when configuration is synchronized between storages + * and allows a module to take over the synchronization of configuration data. + * + * @param string $name + * The name of the configuration object. + * @param \Drupal\Core\Config\Config $new_config + * A configuration object containing the new configuration data. + * @param \Drupal\Core\Config\Config $old_config + * A configuration object containing the old configuration data. + */ + public function importCreate($name, Config $new_config, Config $old_config) { + $entity = $this->create($new_config->get()); + $entity->save(); + return TRUE; + } + + /** + * Update configuration upon synchronizing configuration changes. + * + * This callback is invoked when configuration is synchronized between storages + * and allows a module to take over the synchronization of configuration data. + * + * @param string $name + * The name of the configuration object. + * @param \Drupal\Core\Config\Config $new_config + * A configuration object containing the new configuration data. + * @param \Drupal\Core\Config\Config $old_config + * A configuration object containing the old configuration data. + */ + public function importChange($name, Config $new_config, Config $old_config) { + list(, , $id) = explode('.', $name); + $entities = $this->load(array($id)); + $entity = $entities[$id]; + $entity->original = clone $entity; + + foreach ($old_config->get() as $property => $value) { + $entity->original->$property = $value; + } + + foreach ($new_config->get() as $property => $value) { + $entity->$property = $value; + } + + $entity->save(); + return TRUE; + } + + /** + * Delete configuration upon synchronizing configuration changes. + * + * This callback is invoked when configuration is synchronized between storages + * and allows a module to take over the synchronization of configuration data. + * + * @param string $name + * The name of the configuration object. + * @param \Drupal\Core\Config\Config $new_config + * A configuration object containing the new configuration data. + * @param \Drupal\Core\Config\Config $old_config + * A configuration object containing the old configuration data. + */ + public function importDelete($name, Config $new_config, Config $old_config) { + list(, , $id) = explode('.', $name); + $entities = $this->load(array($id)); + $entity = $entities[$id]; + $entity->delete(); + return TRUE; + } + } diff --git a/core/modules/config/config.api.php b/core/modules/config/config.api.php index d84566712a9600531960e166de672e8884b8c96f..7b06336bf3923220fdff6e7c85a97de647930247 100644 --- a/core/modules/config/config.api.php +++ b/core/modules/config/config.api.php @@ -11,116 +11,3 @@ * @todo Overall description of the configuration system. * @} */ - -/** - * Create configuration upon synchronizing configuration changes. - * - * This callback is invoked when configuration is synchronized between storages - * and allows a module to take over the synchronization of configuration data. - * - * Modules should implement this callback if they manage configuration data - * (such as image styles, node types, or fields) which needs to be - * prepared and passed through module API functions to properly handle a - * configuration change. - * - * @param string $name - * The name of the configuration object. - * @param Drupal\Core\Config\Config $new_config - * A configuration object containing the new configuration data. - * @param Drupal\Core\Config\Config $old_config - * A configuration object containing the old configuration data. - */ -function hook_config_import_create($name, $new_config, $old_config) { - // Only configuration entities require custom handling. Any other module - // settings can be synchronized directly. - if (strpos($name, 'config_test.dynamic.') !== 0) { - return FALSE; - } - $config_test = entity_create('config_test', $new_config->get()); - $config_test->save(); - return TRUE; -} - -/** - * Update configuration upon synchronizing configuration changes. - * - * This callback is invoked when configuration is synchronized between storages - * and allows a module to take over the synchronization of configuration data. - * - * Modules should implement this callback if they manage configuration data - * (such as image styles, node types, or fields) which needs to be - * prepared and passed through module API functions to properly handle a - * configuration change. - * - * @param string $name - * The name of the configuration object. - * @param Drupal\Core\Config\Config $new_config - * A configuration object containing the new configuration data. - * @param Drupal\Core\Config\Config $old_config - * A configuration object containing the old configuration data. - */ -function hook_config_import_change($name, $new_config, $old_config) { - // Only configuration entities require custom handling. Any other module - // settings can be synchronized directly. - if (strpos($name, 'config_test.dynamic.') !== 0) { - return FALSE; - } - - // @todo Make this less ugly. - list($entity_type) = explode('.', $name); - $entity_info = entity_get_info($entity_type); - $id = substr($name, strlen($entity_info['config_prefix']) + 1); - $config_test = entity_load('config_test', $id); - - // Store the original config, and iterate through each property to store it. - $config_test->original = clone $config_test; - foreach ($old_config->get() as $property => $value) { - $config_test->original->$property = $value; - } - - // Iterate through each property of the new config, copying it to the test - // object. - foreach ($new_config->get() as $property => $value) { - $config_test->$property = $value; - } - - $config_test->save(); - return TRUE; -} - -/** - * Delete configuration upon synchronizing configuration changes. - * - * This callback is invoked when configuration is synchronized between storages - * and allows a module to take over the synchronization of configuration data. - * - * Modules should implement this callback if they manage configuration data - * (such as image styles, node types, or fields) which needs to be - * prepared and passed through module API functions to properly handle a - * configuration change. - * - * @param string $name - * The name of the configuration object. - * @param Drupal\Core\Config\Config $new_config - * A configuration object containing the new configuration data. - * @param Drupal\Core\Config\Config $old_config - * A configuration object containing the old configuration data. - */ -function hook_config_import_delete($name, $new_config, $old_config) { - // Only configuration entities require custom handling. Any other module - // settings can be synchronized directly. - if (strpos($name, 'config_test.dynamic.') !== 0) { - return FALSE; - } - // @todo image_style_delete() supports the notion of a "replacement style" - // to be used by other modules instead of the deleted style. Essential! - // But that is impossible currently, since the config system only knows - // about deleted and added changes. Introduce an 'old_ID' key within - // config objects as a standard? - list($entity_type) = explode('.', $name); - $entity_info = entity_get_info($entity_type); - $id = substr($name, strlen($entity_info['config_prefix']) + 1); - config_test_delete($id); - return TRUE; -} - diff --git a/core/modules/config/tests/config_test/config_test.module b/core/modules/config/tests/config_test/config_test.module index 96d4aa0288ae203f37a8e63430c849fc18e02894..5dbcb92a3f0ef4d4abc991df630f4d4f21cbfeb9 100644 --- a/core/modules/config/tests/config_test/config_test.module +++ b/core/modules/config/tests/config_test/config_test.module @@ -9,68 +9,6 @@ require_once dirname(__FILE__) . '/config_test.hooks.inc'; -/** - * Implements hook_config_import_create(). - */ -function config_test_config_import_create($name, $new_config, $old_config) { - if (strpos($name, 'config_test.dynamic.') !== 0) { - return FALSE; - } - // Set a global value we can check in test code. - $GLOBALS['hook_config_import'] = __FUNCTION__; - - $config_test = entity_create('config_test', $new_config->get()); - $config_test->save(); - return TRUE; -} - -/** - * Implements hook_config_import_change(). - */ -function config_test_config_import_change($name, $new_config, $old_config) { - if (strpos($name, 'config_test.dynamic.') !== 0) { - return FALSE; - } - // Set a global value we can check in test code. - $GLOBALS['hook_config_import'] = __FUNCTION__; - - // @todo Make this less ugly. - list(, , $id) = explode('.', $name); - $config_test = entity_load('config_test', $id); - - // Store the original config, and iterate through each property to store it. - $config_test->original = clone $config_test; - foreach ($old_config->get() as $property => $value) { - $config_test->original->$property = $value; - } - - // Iterate through each property of the new config, copying it to the test - // object. - foreach ($new_config->get() as $property => $value) { - $config_test->$property = $value; - } - - $config_test->save(); - return TRUE; -} - -/** - * Implements hook_config_import_delete(). - */ -function config_test_config_import_delete($name, $new_config, $old_config) { - if (strpos($name, 'config_test.dynamic.') !== 0) { - return FALSE; - } - // Set a global value we can check in test code. - $GLOBALS['hook_config_import'] = __FUNCTION__; - - // @todo Make this less ugly. - list(, , $id) = explode('.', $name); - $config_test = entity_load('config_test', $id); - $config_test->delete(); - return TRUE; -} - /** * Entity URI callback. * @@ -197,4 +135,4 @@ function config_test_cache_flush() { $GLOBALS['hook_cache_flush'] = __FUNCTION__; return array(); -} \ No newline at end of file +} diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestStorageController.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestStorageController.php new file mode 100644 index 0000000000000000000000000000000000000000..e1fe4fe025e00ed0aeb24d74c8b5a0c56cfeb768 --- /dev/null +++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestStorageController.php @@ -0,0 +1,48 @@ +<?php + +/** + * @file + * Contains \Drupal\config_test\ConfigTestStorageController. + */ + +namespace Drupal\config_test; + +use Drupal\Core\Config\Entity\ConfigStorageController; +use Drupal\Core\Config\Config; + +/** + * @todo. + */ +class ConfigTestStorageController extends ConfigStorageController { + + /** + * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::importCreate(). + */ + public function importCreate($name, Config $new_config, Config $old_config) { + // Set a global value we can check in test code. + $GLOBALS['hook_config_import'] = __METHOD__; + + return parent::importCreate($name, $new_config, $old_config); + } + + /** + * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::importChange(). + */ + public function importChange($name, Config $new_config, Config $old_config) { + // Set a global value we can check in test code. + $GLOBALS['hook_config_import'] = __METHOD__; + + return parent::importChange($name, $new_config, $old_config); + } + + /** + * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::importDelete(). + */ + public function importDelete($name, Config $new_config, Config $old_config) { + // Set a global value we can check in test code. + $GLOBALS['hook_config_import'] = __METHOD__; + + return parent::importDelete($name, $new_config, $old_config); + } + +} diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Core/Entity/ConfigTest.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Core/Entity/ConfigTest.php index 8690b2aba55d143fe51e391d12eb043ecb2f98cc..52da7775529163ce183fa5a0847a398a79679c98 100644 --- a/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Core/Entity/ConfigTest.php +++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/Plugin/Core/Entity/ConfigTest.php @@ -18,7 +18,7 @@ * id = "config_test", * label = @Translation("Test configuration"), * module = "config_test", - * controller_class = "Drupal\Core\Config\Entity\ConfigStorageController", + * controller_class = "Drupal\config_test\ConfigTestStorageController", * list_controller_class = "Drupal\Core\Config\Entity\ConfigEntityListController", * form_controller_class = { * "default" = "Drupal\config_test\ConfigTestFormController" diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module index 00345e12372207f49a447c42fac68f7cfa468050..44a6f5af1abbbf6f2e3b710f2e1c4c0455569d29 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -173,56 +173,6 @@ function _contact_personal_tab_access($account) { return user_access('access user contact forms'); } -/** - * Implements MODULE_config_import_create(). - */ -function contact_config_import_create($name, $new_config, $old_config) { - if (strpos($name, 'contact.category.') !== 0) { - return FALSE; - } - - $category = entity_create('contact_category', $new_config->get()); - $category->save(); - return TRUE; -} - -/** - * Implements MODULE_config_import_change(). - */ -function contact_config_import_change($name, $new_config, $old_config) { - if (strpos($name, 'contact.category.') !== 0) { - return FALSE; - } - - list(, , $id) = explode('.', $name); - $category = entity_load('contact_category', $id); - - $category->original = clone $category; - foreach ($old_config->get() as $property => $value) { - $category->original->$property = $value; - } - - foreach ($new_config->get() as $property => $value) { - $category->$property = $value; - } - - $category->save(); - return TRUE; -} - -/** - * Implements MODULE_config_import_delete(). - */ -function contact_config_import_delete($name, $new_config, $old_config) { - if (strpos($name, 'contact.category.') !== 0) { - return FALSE; - } - - list(, , $id) = explode('.', $name); - entity_delete_multiple('contact_category', array($id)); - return TRUE; -} - /** * Implements hook_entity_info(). */ diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 83124204f1290dfb804cc8962c682bafce0198ff..556467bf55c49e755c0347f01d54a9e20dca4ac8 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -502,65 +502,6 @@ function image_path_flush($path) { } } -/** - * Implements hook_config_import_create(). - */ -function image_config_import_create($name, $new_config, $old_config) { - // Only image styles require custom handling. Any other module settings can be - // synchronized directly. - if (strpos($name, 'image.style.') !== 0) { - return FALSE; - } - $style = entity_create('image_style', $new_config->get()); - $style->save(); - return TRUE; -} - -/** - * Implements hook_config_import_change(). - */ -function image_config_import_change($name, $new_config, $old_config) { - // Only image styles require custom handling. Any other module settings can be - // synchronized directly. - if (strpos($name, 'image.style.') !== 0) { - return FALSE; - } - - list(, , $id) = explode('.', $name); - $style = entity_load('image_style', $id); - - $style->original = clone $style; - foreach ($old_config->get() as $property => $value) { - $style->original->$property = $value; - } - - foreach ($new_config->get() as $property => $value) { - $style->$property = $value; - } - - $style->save(); - return TRUE; -} - -/** - * Implements MODULE_config_import_delete(). - */ -function image_config_import_delete($name, $new_config, $old_config) { - // Only image styles require custom handling. Any other module settings can be - // synchronized directly. - if (strpos($name, 'image.style.') !== 0) { - return FALSE; - } - // @todo image_style_delete() supports the notion of a "replacement style" - // to be used by other modules instead of the deleted style. Essential! - // But that is impossible currently, since the config system only knows - // about deleted and added changes. Introduce an 'old_ID' key within - // config objects as a standard? - list(, , $id) = explode('.', $name); - $style = entity_load('image_style', $id); - return image_style_delete($style); -} - /** * Loads an ImageStyle object. * diff --git a/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php b/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php new file mode 100644 index 0000000000000000000000000000000000000000..ddeaac2f45eb4330cb75779acafd45fd3db98135 --- /dev/null +++ b/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php @@ -0,0 +1,34 @@ +<?php + +/** + * @file + * Contains \Drupal\image\ImageStyleStorageController. + */ + +namespace Drupal\image; + +use Drupal\Core\Config\Entity\ConfigStorageController; +use Drupal\Core\Config\Config; + +/** + * Defines a controller class for image styles. + */ +class ImageStyleStorageController extends ConfigStorageController { + + /** + * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::importDelete(). + */ + public function importDelete($name, Config $new_config, Config $old_config) { + list(, , $id) = explode('.', $name); + $entities = $this->load(array($id)); + $entity = $entities[$id]; + + // @todo image_style_delete() supports the notion of a "replacement style" + // to be used by other modules instead of the deleted style. Essential! + // But that is impossible currently, since the config system only knows + // about deleted and added changes. Introduce an 'old_ID' key within + // config objects as a standard? + return image_style_delete($entity); + } + +} diff --git a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php index 363fbd87d93e3156ba4db12abeda59eac45629a0..8110b77677389ca05f55d1cc4ea05c373768eee6 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php +++ b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php @@ -18,7 +18,7 @@ * id = "image_style", * label = @Translation("Image style"), * module = "image", - * controller_class = "Drupal\Core\Config\Entity\ConfigStorageController", + * controller_class = "Drupal\image\ImageStyleStorageController", * uri_callback = "image_style_uri", * config_prefix = "image.style", * entity_keys = { diff --git a/core/modules/views/views.module b/core/modules/views/views.module index ac4952bb1604f3550894745814989548395f9670..c3b450a659d6024cffe51e5f105d48f6b01799fd 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -78,19 +78,6 @@ function views_pre_render_view_element($element) { return $element; } -/** - * Implements hook_config_import_create(). - */ -function views_config_import_create($name, $new_config, $old_config) { - if (strpos($name, 'views.view.') !== 0) { - return FALSE; - } - - $view = entity_create('view', $new_config->get()); - $view->save(); - return TRUE; -} - /** * Implement hook_theme(). Register views theming functions. */ @@ -2072,22 +2059,6 @@ function views_array_key_plus($array) { return $array; } -/** - * Implements hook_config_import_delete(). - */ -function views_config_import_delete($name, $new_config, $old_config) { - // Only image styles require custom handling. Any other module settings can be - // synchronized directly. - if (strpos($name, 'views.view.') !== 0) { - return FALSE; - } - - list(, , $id) = explode('.', $name); - $view = entity_load('view', $id); - entity_delete($view); - return TRUE; -} - /** * Set a cached item in the views cache. *