Change record status: 
Project: 
Introduced in branch: 
8.x
Introduced in version: 
8.0
Description: 

The Drupal 8 configuration API had an elaborate context system with arbitrary context values and a context stack. The idea being that the configuration system could be sent into a context (eg. for a specific user or group or domain or any other type) and the context would have meta-information for any overrides to inform which values to take. However understanding the system of contexts and overrides based on contexts was hard to grasp and even harder to effectively cache and use.

Therefore we simplified the override system and removed the context stack. The new/current system works as follows:

1. Instead of a context, now the ConfigFactory knows/maintains if overrides are allowed or not. Use disableOverrides() and enableOverrides() on the ConfigFactory to turn off/on all overrides.

2. Instead of the context, the ConfigFactory now directly knows if specific language overrides are applied. Use setLanguage() to set the language to use for config retrieval. The language overrides are cached in the factory.

3. It is still possible to register any other kinds of overrides (for domains, groups, users, etc). There is no explicit context system to get meta-information for overrides though, so use other information sources (eg. the route, the user, the negotiated language, etc) to pick the proper overrides. Also cache those values yourself.

4. Since understanding of the language overrides is built-in, the initialisation of language overrides previously done by locale module is now done by language module instead and therefore the config file name pattern for language overrides is changed from locale.config.* to language.config.*.

Administration forms should still turn off overrides for the course of generating and processing the form, so only the original value is being edited. The config() method on ConfigFormBase is still disabling overrides for accessing values, so if you make sure to use that to get data for forms, there is nothing to change for you.

To use overrides with the proper values (for example sending email), do the following (note that there is no “context stack” anymore, so we remember the prior language and set it back after we are done):

  $original_language = \Drupal::configFactory()->getLanguage();

  $language = language_load($account->getPreferredLangcode());
  \Drupal::configFactory()->setLanguage($language);
  $mail_config = \Drupal::config('user.mail');

// … send the email with config in the right language …

  \Drupal::configFactory()->setLanguage($original_language);

To register overrides, subscribe to the config.module.overrides event. Set the subscriber priority to specify the priority of the override. Overrides set by subscribers with higher priority will trump those set from subscribers with lower priority (in case of the same config name).


/**
 * @file
 * Contains \Drupal\config_example\EventSubscriber\ConfigModuleOverrideSubscriber.
 */

namespace Drupal\config_example\EventSubscriber;

use Drupal\Core\Config\ConfigModuleOverridesEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Sample configuration override example.
 */
class ConfigModuleOverrideSubscriber implements EventSubscriberInterface {

  public function onConfigModuleOverride(ConfigModuleOverridesEvent $event) {
    $names = $event->getNames();
    if (in_array('system.site', $names)) {
      $event->setOverride('system.site', array('name' => 'Overridden site name'));
    }
  }

  /**
   * Registers the methods in this class that should be listeners.
   *
   * @return array
   *   An array of event listener definitions.
   */
  static function getSubscribedEvents() {
    $events['config.module.overrides'][] = array('onConfigModuleOverride', 40);
    return $events;
  }
}

Configuration overrides themselves operate at three distinct layers: language, modules and settings.php, with the last of these taking precedence. Overrides in settings.php take precedence over values provided by modules. Overrides provided by modules take precedence over language. The event subscriber priority for module overrides only sets priority versus the other module overrides, it cannot be used to set higher priority in relation to language or settings.php overrides.

Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

bradjones1’s picture