foldershare-8.x-1.2/src/Utilities/ConfigurationUtilities.php
src/Utilities/ConfigurationUtilities.php
<?php
namespace Drupal\foldershare\Utilities;
use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\ExtensionInstallStorage;
/**
* Defines static utility functions for working with configurations.
*
* The functions in this class support loading and reverting core and
* entity configurations.
*
* <B>Warning:</B> This class is strictly internal to the FolderShare
* module. The class's existance, name, and content may change from
* release to release without any promise of backwards compatability.
*
* @ingroup foldershare
*/
final class ConfigurationUtilities {
/*--------------------------------------------------------------------
*
* Functions.
*
*-------------------------------------------------------------------*/
/**
* Loads a configuration for an entity type and configuration name.
*
* The named configuration for the indicated entity type is found on
* disk (in any module), loaded, and returned as a raw nested array
* of values.
*
* Returning the array, rather than a created entity, avoids unnecessarily
* creating new entities when the caller only needs to see particular
* values within a configuration, or compare it with another configuration.
*
* @param string $entityTypeId
* The ID (name) of the entity type.
* @param string $configName
* The name of the desired configuration for the entity type.
*
* @return array
* Returns a nested associative array containing the keys and values
* of the configuration. The structure of the array varies with the
* type of configuration. A NULL is returned if the configuration
* could not be found. An empty array is returned if the configuration
* is found, but it is empty.
*
* @see ::revertConfiguration()
*/
public static function loadConfiguration(
string $entityTypeId,
string $configName) {
// Validate
// --------
// The entity type ID and configuration name both must be non-empty.
if (empty($entityTypeId) === TRUE || empty($configName) === TRUE) {
// Empty entity type ID or configuration name.
return NULL;
}
// Setup
// -----
// Get some values we need.
$entityTypeManager = \Drupal::entityTypeManager();
try {
$entityDefinition = $entityTypeManager->getDefinition($entityTypeId);
}
catch (\Exception $e) {
// Unrecognized entity type.
return NULL;
}
// Create the fully-qualified configuration name formed by adding a
// configuration prefix for the entity type.
$fullName = $entityDefinition->getConfigPrefix() . '.' . $configName;
// Load file
// ---------
// Read the configuration from a file. Start by checking the install
// configuration. If not found there, check the optional configuration.
$configStorage = \Drupal::service('config.storage');
$installStorage = new ExtensionInstallStorage(
$configStorage,
InstallStorage::CONFIG_INSTALL_DIRECTORY);
$config = $installStorage->read($fullName);
if (empty($config) === TRUE) {
$optionalStorage = new ExtensionInstallStorage(
$configStorage,
InstallStorage::CONFIG_OPTIONAL_DIRECTORY);
$config = $optionalStorage->read($fullName);
if (empty($config) === TRUE) {
// Cannot find the configuration file.
return NULL;
}
}
return $config;
}
/**
* Reverts an entity or core configuration by reloading it from a module.
*
* This method supports core and entity configurations. Core configurations
* have a single site-wide instance, while entity configurations are
* entity instances with an ID and values for entity fields. For instance,
* core configurations are used to describe an entity type's forms and
* and displays, while entity configurations are used to describe each
* of the views configurations that might have been created by a site.
*
* This method looks at the $baseName. If it is 'core', the method loads
* a core configuration. Otherwise it assumes the name is for an entity
* type and the method loads a configuration and saves it as either a new
* entity type instance, or to replace an existing instance.
*
* This method looks for either type of configuration in the 'install' or
* 'optional' folders across all installed modules. If not found,
* FALSE is returned. If found, the configuration is loaded as above.
*
* For entity configurations, this method looks for the entity type
* definition. If not found, FALSE is returned.
*
* @param string $baseName
* The base name of the configuration. For entity type's, this is the
* entity type ID. For core configurations, this is 'core'.
* @param string $configName
* The name of the desired configuration.
*
* @return bool
* Returns TRUE if the configuration was reverted. FALSE is returned
* if the configuration file could not be found. For entity configurations,
* FALSE is returned if the entity type could not be found.
*
* @see ::loadConfiguration()
*/
public static function revertConfiguration(
string $baseName,
string $configName) {
// The base name and configuration name both must be non-empty.
if (empty($baseName) === TRUE || empty($configName) === TRUE) {
return FALSE;
}
// Revert a core or entity configuration.
if ($baseName === 'core') {
// Core configurations SOMETIMES prefix with 'core'. Try that first.
if (self::revertCoreConfiguration('core.' . $configName) === TRUE) {
return TRUE;
}
// Other core configurations do not prefix with 'core'. Try that.
return self::revertCoreConfiguration($configName);
}
return self::revertEntityConfiguration($baseName, $configName);
}
/**
* Reverts a core configuration by reloading it from a module.
*
* Core configurations have a single site-wide instance. The form and
* display configurations for an entity type's fields, for instance,
* are core configurations.
*
* This method looks for a core configuration in the 'install' or
* 'optional' folders across all installed modules. If not found,
* FALSE is returned. If found, the configuration is loaded and used
* to replace the current core configuration.
*
* @param string $configName
* The name of the desired core configuration.
*
* @return bool
* Returns TRUE if the configuration was reverted. FALSE is returned
* if the configuration file could not be found.
*
* @see ::revertConfiguration()
*/
private static function revertCoreConfiguration(string $configName) {
//
// Load file
// ---------
// The configuration file exists in several locations:
// - The current cached configuration used each time Drupal boots.
// - The original configuration loaded when the module was installed.
// - The original optional configuration that might load on module install.
//
// We specifically want to replace the current cached configuration,
// so that isn't the one to load here.
//
// We'd prefer to get the installed configuration, but it will not exist
// if the configuration we're asked to load is for an optional feature
// that was only added if other non-required modules were installed.
// In that case, we need to switch from the non-existant installed
// configuration to the optional configuration and load that.
//
// Get the configuration storage service.
$configStorage = \Drupal::service('config.storage');
// Try to load the install configuration, if any.
$installStorage = new ExtensionInstallStorage(
$configStorage,
InstallStorage::CONFIG_INSTALL_DIRECTORY);
$config = $installStorage->read($configName);
if (empty($config) === TRUE) {
// The install configuration did not exist. Try to load the optional
// configuration, if any.
$optionalStorage = new ExtensionInstallStorage(
$configStorage,
InstallStorage::CONFIG_OPTIONAL_DIRECTORY);
$config = $optionalStorage->read($configName);
if (empty($config) === TRUE) {
// Neither the install or optional configuration directories found
// the configuration we're after. Nothing more we can do.
return FALSE;
}
}
//
// Revert
// ------
// To revert to the newly loaded configuration, we need to get the
// current cached ('sync') configuration and replace it.
$configStorage->write($configName, $config);
return TRUE;
}
/**
* Reverts an entity configuration by reloading it from a module.
*
* Entity configurations are entity instances with an ID and values for
* entity fields. For instance, since a "view" is an entity instance,
* the configuration of a specific view is an entity configuration.
* These are individually stored in cache and in a module's configuration
* folder.
*
* This method looks for an entity configuration in the 'install' or
* 'optional' folders across all installed modules. If not found,
* FALSE is returned. If found, the configuration is loaded and used
* to create a new entity or replace an existing entity with the same
* ID as that found in the configuration file. If the entity type cannot
* be found, FALSE is returned.
*
* @param string $entityTypeId
* The ID (name) of the entity type.
* @param string $configName
* The name of the desired entity configuration.
*
* @return bool
* Returns TRUE if the configuration was reverted. FALSE is returned
* if the entity type cannot be found, or if the configuration file
* cannot be found.
*
* @see ::revertConfiguration()
*/
private static function revertEntityConfiguration(
string $entityTypeId,
string $configName) {
// Get entity info
// ---------------
// The incoming $entityTypeId names an entity type that has its
// own storage manager and an entity type definition that we need
// in order to build the full name of a configuration.
try {
// Get the entity's storage and definition.
$entityTypeManager = \Drupal::entityTypeManager();
$entityStorage = $entityTypeManager->getStorage($entityTypeId);
$entityDefinition = $entityTypeManager->getDefinition($entityTypeId);
}
catch (\Exception $e) {
// Unrecognized entity type!
return FALSE;
}
//
// Create name
// -----------
// The full name of the configuration uses the given $configName,
// prefixed with an entity type-specific prefix obtained from
// the entity type definition.
$fullName = $entityDefinition->getConfigPrefix() . '.' . $configName;
//
// Load file
// ---------
// The configuration file exists in several locations:
// - The current cached configuration used each time Drupal boots.
// - The original configuration loaded when the module was installed.
// - The original optional configuration that might load on module install.
//
// We specifically want to replace the current cached configuration,
// so that isn't the one to load here.
//
// We'd prefer to get the installed configuration, but it will not exist
// if the configuration we're asked to load is for an optional feature
// that was only added if other non-required modules were installed.
// In that case, we need to switch from the non-existant installed
// configuration to the optional configuration and load that.
//
// Get the configuration storage service.
$configStorage = \Drupal::service('config.storage');
// Try to load the install configuration, if any.
$installStorage = new ExtensionInstallStorage(
$configStorage,
InstallStorage::CONFIG_INSTALL_DIRECTORY);
$config = $installStorage->read($fullName);
if (empty($config) === TRUE) {
// The install configuration did not exist. Try to load the optional
// configuration, if any.
$optionalStorage = new ExtensionInstallStorage(
$configStorage,
InstallStorage::CONFIG_OPTIONAL_DIRECTORY);
$config = $optionalStorage->read($fullName);
if (empty($config) === TRUE) {
// Neither the install or optional configuration directories found
// the configuration we're after. Nothing more we can do.
return FALSE;
}
}
//
// Load entity
// -----------
// Entity configurations handled by this method are associated with
// an entity, unsurprisingly. We need to load that entity as it is now
// so that we can replace its fields with those loaded from the
// configuration above.
//
// The entity might not exist if someone deleted it. This could happen
// if a site administrator deleted a 'view' that this method is now
// being called to restore.
$idKey = $entityDefinition->getKey('id');
$id = $config[$idKey];
$currentEntity = $entityStorage->load($id);
//
// Revert
// ------
// If there is already an entity, update it with the loaded configuration.
// And if there is not an entity, create a new one using the loaded
// configuration.
if ($currentEntity === NULL) {
// Create a new entity.
$newEntity = $entityStorage->createFromStorageRecord($config);
}
else {
// Update the existing entity.
$newEntity = $entityStorage->updateFromStorageRecord(
$currentEntity,
$config);
}
// Save the new or updated entity.
$newEntity->trustData();
$newEntity->save();
return TRUE;
}
}
