diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index eb9dff9..e7d4bbf 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1642,6 +1642,11 @@ function install_finished(&$install_state) { $output = '

' . st('Congratulations, you installed @drupal!', array('@drupal' => drupal_install_profile_distribution_name())) . '

'; $output .= '

' . (isset($messages['error']) ? st('Review the messages above before visiting your new site.', array('@url' => url(''))) : st('Visit your new site.', array('@url' => url('')))) . '

'; + // Populate the cron key variable. + $cron_key = drupal_hash_base64(drupal_random_bytes(55)); + config('system.cron') + ->set('cron_key', $cron_key) + ->save(); // Run cron to populate update status tables (if available) so that users // will be warned if they've installed an out of date Drupal version. // Will also trigger indexing of profile-supplied content or feeds. diff --git a/core/lib/Drupal/Core/Config/DatabaseStorage.php b/core/lib/Drupal/Core/Config/DatabaseStorage.php index c736245..def83e4 100644 --- a/core/lib/Drupal/Core/Config/DatabaseStorage.php +++ b/core/lib/Drupal/Core/Config/DatabaseStorage.php @@ -13,15 +13,17 @@ class DatabaseStorage extends StorageBase { /** * Implements StorageInterface::read(). */ - public function read() { + public function read(&$isNew = NULL) { // There are situations, like in the installer, where we may attempt a // read without actually having the database available. In this case, // catch the exception and just return an empty array so the caller can // handle it if need be. $data = array(); + $isNew = TRUE; try { $raw = db_query('SELECT data FROM {config} WHERE name = :name', array(':name' => $this->name))->fetchField(); if ($raw !== FALSE) { + $isNew = FALSE; $data = $this->decode($raw); } } diff --git a/core/lib/Drupal/Core/Config/DrupalConfig.php b/core/lib/Drupal/Core/Config/DrupalConfig.php index f5a9220..30032c9 100644 --- a/core/lib/Drupal/Core/Config/DrupalConfig.php +++ b/core/lib/Drupal/Core/Config/DrupalConfig.php @@ -25,6 +25,20 @@ class DrupalConfig { protected $data = array(); /** + * The original data of the configuration object. + * + * @var array + */ + protected $original = array(); + + /** + * TRUE when this is new configuration ie doesnt exist in the active store. + * + * @var boolan + */ + protected $isNew; + + /** * Constructs a DrupalConfig object. * * @param StorageInterface $storage @@ -41,8 +55,12 @@ class DrupalConfig { * Reads config data from the active store into our object. */ public function read() { - $data = $this->storage->read(); - $this->setData($data !== FALSE ? $data : array()); + $data = $this->storage->read($this->isNew); + if ($data === FALSE) { + $data = array(); + } + $this->original = $data; + $this->setData($data); return $this; } @@ -205,8 +223,14 @@ class DrupalConfig { /** * Saves the configuration object. + * + * This invokes hook_config_presave() and related hooks. If you really need + * to bypass those (for example saving a config without fully bootstrapping) + * call the storage write directly but note that doing so might result in a + * broken system. */ public function save() { + $this->invoke('config_presave'); $this->storage->write($this->data); } @@ -214,7 +238,26 @@ class DrupalConfig { * Deletes the configuration object. */ public function delete() { - $this->data = array(); + $this->invoke('config_delete'); $this->storage->delete(); + $this->data = array(); + $this->original = array(); + } + + /** + * Invokes hooks. + */ + protected function invoke($hook) { + if (drupal_bootstrap() < DRUPAL_BOOTSTRAP_CODE) { + file_put_contents('/tmp/log', print_r(debug_backtrace(), TRUE)); + throw new InvokeException('Can not save without modules loaded.'); + } + module_invoke_all($hook, $this->data, $this->original, $this->isNew, $this); + $part = strtok($this->storage->getName(), '.'); + do { + $hook .= '__' . $part; + file_put_contents('/tmp/log', "$hook\n", FILE_APPEND); + module_invoke_all($hook, $this->data, $this->original, $this->isNew, $this); + } while ($part = strtok('.')); } } diff --git a/core/lib/Drupal/Core/Config/InvokeException.php b/core/lib/Drupal/Core/Config/InvokeException.php new file mode 100644 index 0000000..2bf1c63 --- /dev/null +++ b/core/lib/Drupal/Core/Config/InvokeException.php @@ -0,0 +1,8 @@ + $display) { - // Check if the formatter involves an image style. - if ($display['type'] == 'image' && $display['settings']['image_style'] == $style['old_name']) { - // Update display information for any instance using the image - // style that was just deleted. - $instance['display'][$view_mode]['settings']['image_style'] = $style['name']; - $instance_changed = TRUE; - } - } - if ($instance['widget']['settings']['preview_image_style'] == $style['old_name']) { - $instance['widget']['settings']['preview_image_style'] = $style['name']; +function image_config_presave__image__style($style, $original, $is_new) { + if (!$is_new && $style != $original) { + _image_effects_changed($style, $original); + } +} + +function _image_effects_changed($style, $original) { + $instances = field_read_instances(); + // Loop through all fields searching for image fields. + foreach ($instances as $instance) { + if ($instance['widget']['module'] == 'image') { + $instance_changed = FALSE; + foreach ($instance['display'] as $view_mode => $display) { + // Check if the formatter involves an image style. + if ($display['type'] == 'image' && $display['settings']['image_style'] == $original['name']) { + // Update display information for any instance using the image + // style that was just deleted. + $instance['display'][$view_mode]['settings']['image_style'] = $style['name']; $instance_changed = TRUE; } - if ($instance_changed) { - field_update_instance($instance); - } + } + if ($instance['widget']['settings']['preview_image_style'] == $original['name']) { + $instance['widget']['settings']['preview_image_style'] = $style['name']; + $instance_changed = TRUE; + } + if ($instance_changed) { + field_update_instance($instance); } } } } /** - * Implements hook_image_style_delete(). + * Implements hook_config_delete_image__style(). */ -function image_image_style_delete($style) { - image_image_style_save($style); +function image_config_delete__image__style($style, $original) { + _image_effects_changed($style, $original); } /** @@ -586,12 +590,6 @@ function image_style_save($style) { $config->set('effects', array()); } $config->save(); - // @todo is_new must only be set when the configuration object did not exist - // yet. - $style['is_new'] = TRUE; - - // Let other modules update as necessary on save. - module_invoke_all('image_style_save', $style); // Clear all caches and flush. image_style_flush($style); @@ -614,13 +612,9 @@ function image_style_delete($style, $replacement_style_name = '') { image_style_flush($style); $config = config('image.style.' . $style['name']); + $config->set('name', $replacement_style_name); $config->delete(); - // Let other modules update as necessary on save. - $style['old_name'] = $style['name']; - $style['name'] = $replacement_style_name; - module_invoke_all('image_style_delete', $style); - return TRUE; } diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index ed5b7a0..4772d91 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -4265,5 +4265,32 @@ function hook_filetransfer_info_alter(&$filetransfer_info) { } /** + * Validate and react before a config object is saved. + * + * This is not a single hook but a family of hooks. For example, when + * image.style.large is saved + * - hook_config_presave + * - hook_config_presave__image + * - hook_config_presave__image__style + * - hook_config_presave__image__style__large + * is called. + * + * @param $data + * The configuration data being saved. + * @param $original + * The original configuration data. + * @param $is_new + * TRUE if the configuration does not exist in the active store, FALSE if + * it does. + * @param $config + * The config object itself. + */ +function hook_config_presave($data, $original, $is_new, $config) { + if (!$is_new && $data != $original) { + _image_effects_changed($data, $original); + } +} + +/** * @} End of "addtogroup hooks". */ diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 84822c7..83570dd 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -517,12 +517,6 @@ function system_install() { ->condition('type', 'theme') ->condition('name', 'stark') ->execute(); - - // Populate the cron key variable. - $cron_key = drupal_hash_base64(drupal_random_bytes(55)); - config('system.cron') - ->set('cron_key', $cron_key) - ->save(); } /**