Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176
This commit is contained in:
commit
9921556621
13277 changed files with 1459781 additions and 0 deletions
151
core/modules/field/src/ConfigImporterFieldPurger.php
Normal file
151
core/modules/field/src/ConfigImporterFieldPurger.php
Normal file
|
@ -0,0 +1,151 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\field\ConfigImporterFieldPurger.
|
||||
*/
|
||||
|
||||
namespace Drupal\field;
|
||||
|
||||
use Drupal\Core\Config\ConfigImporter;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityStorage;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
||||
/**
|
||||
* Processes field purges before a configuration synchronization.
|
||||
*/
|
||||
class ConfigImporterFieldPurger {
|
||||
|
||||
/**
|
||||
* Processes fields targeted for purge as part of a configuration sync.
|
||||
*
|
||||
* This takes care of deleting the field if necessary, and purging the data on
|
||||
* the fly.
|
||||
*
|
||||
* @param array $context
|
||||
* The batch context.
|
||||
* @param \Drupal\Core\Config\ConfigImporter $config_importer
|
||||
* The config importer.
|
||||
*/
|
||||
public static function process(array &$context, ConfigImporter $config_importer) {
|
||||
if (!isset($context['sandbox']['field'])) {
|
||||
static::initializeSandbox($context, $config_importer);
|
||||
}
|
||||
|
||||
// Get the list of field storages to purge.
|
||||
$field_storages = static::getFieldStoragesToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete'));
|
||||
// Get the first field storage to process.
|
||||
$field_storage = reset($field_storages);
|
||||
if (!isset($context['sandbox']['field']['current_storage_id']) || $context['sandbox']['field']['current_storage_id'] != $field_storage->id()) {
|
||||
$context['sandbox']['field']['current_storage_id'] = $field_storage->id();
|
||||
// If the storage has not been deleted yet we need to do that. This is the
|
||||
// case when the storage deletion is staged.
|
||||
if (!$field_storage->isDeleted()) {
|
||||
$field_storage->delete();
|
||||
}
|
||||
}
|
||||
field_purge_batch($context['sandbox']['field']['purge_batch_size'], $field_storage->uuid());
|
||||
$context['sandbox']['field']['current_progress']++;
|
||||
$fields_to_delete_count = count(static::getFieldStoragesToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete')));
|
||||
if ($fields_to_delete_count == 0) {
|
||||
$context['finished'] = 1;
|
||||
}
|
||||
else {
|
||||
$context['finished'] = $context['sandbox']['field']['current_progress'] / $context['sandbox']['field']['steps_to_delete'];
|
||||
$context['message'] = \Drupal::translation()->translate('Purging field @field_label', array('@field_label' => $field_storage->label()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the batch context sandbox for processing field deletions.
|
||||
*
|
||||
* This calculates the number of steps necessary to purge all the field data
|
||||
* and saves data for later use.
|
||||
*
|
||||
* @param array $context
|
||||
* The batch context.
|
||||
* @param \Drupal\Core\Config\ConfigImporter $config_importer
|
||||
* The config importer.
|
||||
*/
|
||||
protected static function initializeSandbox(array &$context, ConfigImporter $config_importer) {
|
||||
$context['sandbox']['field']['purge_batch_size'] = \Drupal::config('field.settings')->get('purge_batch_size');
|
||||
// Save the future list of installed extensions to limit the amount of times
|
||||
// the configuration is read from disk.
|
||||
$context['sandbox']['field']['extensions'] = $config_importer->getStorageComparer()->getSourceStorage()->read('core.extension');
|
||||
|
||||
$context['sandbox']['field']['steps_to_delete'] = 0;
|
||||
$fields = static::getFieldStoragesToPurge($context['sandbox']['field']['extensions'], $config_importer->getUnprocessedConfiguration('delete'));
|
||||
foreach ($fields as $field) {
|
||||
$row_count = \Drupal::entityManager()->getStorage($field->getTargetEntityTypeId())
|
||||
->countFieldData($field);
|
||||
if ($row_count > 0) {
|
||||
// The number of steps to delete each field is determined by the
|
||||
// purge_batch_size setting. For example if the field has 9 rows and the
|
||||
// batch size is 10 then this will add 1 step to $number_of_steps.
|
||||
$how_many_steps = ceil($row_count / $context['sandbox']['field']['purge_batch_size']);
|
||||
$context['sandbox']['field']['steps_to_delete'] += $how_many_steps;
|
||||
}
|
||||
}
|
||||
// Each field possibly needs one last field_purge_batch() call to remove the
|
||||
// last field and the field storage itself.
|
||||
$context['sandbox']['field']['steps_to_delete'] += count($fields);
|
||||
|
||||
$context['sandbox']['field']['current_progress'] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of fields to purge before configuration synchronization.
|
||||
*
|
||||
* If, during a configuration synchronization, a field is being deleted and
|
||||
* the module that provides the field type is being uninstalled then the field
|
||||
* data must be purged before the module is uninstalled. Also, if deleted
|
||||
* fields exist whose field types are provided by modules that are being
|
||||
* uninstalled their data need to be purged too.
|
||||
*
|
||||
* @param array $extensions
|
||||
* The list of extensions that will be enabled after the configuration
|
||||
* synchronization has finished.
|
||||
* @param array $deletes
|
||||
* The configuration that will be deleted by the configuration
|
||||
* synchronization.
|
||||
*
|
||||
* @return \Drupal\field\Entity\FieldStorageConfig[]
|
||||
* An array of field storages that need purging before configuration can be
|
||||
* synchronized.
|
||||
*/
|
||||
public static function getFieldStoragesToPurge(array $extensions, array $deletes) {
|
||||
$providers = array_keys($extensions['module']);
|
||||
$providers[] = 'core';
|
||||
$storages_to_delete = array();
|
||||
|
||||
// Gather fields that will be deleted during configuration synchronization
|
||||
// where the module that provides the field type is also being uninstalled.
|
||||
$field_storage_ids = array();
|
||||
foreach ($deletes as $config_name) {
|
||||
$field_storage_config_prefix = \Drupal::entityManager()->getDefinition('field_storage_config')->getConfigPrefix();
|
||||
if (strpos($config_name, $field_storage_config_prefix . '.') === 0) {
|
||||
$field_storage_ids[] = ConfigEntityStorage::getIDFromConfigName($config_name, $field_storage_config_prefix);
|
||||
}
|
||||
}
|
||||
if (!empty($field_storage_ids)) {
|
||||
$field_storages = \Drupal::entityQuery('field_storage_config')
|
||||
->condition('id', $field_storage_ids, 'IN')
|
||||
->condition('module', $providers, 'NOT IN')
|
||||
->execute();
|
||||
if (!empty($field_storages)) {
|
||||
$storages_to_delete = FieldStorageConfig::loadMultiple($field_storages);
|
||||
}
|
||||
}
|
||||
|
||||
// Gather deleted fields from modules that are being uninstalled.
|
||||
/** @var \Drupal\field\FieldStorageConfigInterface[] $field_storages */
|
||||
$field_storages = entity_load_multiple_by_properties('field_storage_config', array('deleted' => TRUE, 'include_deleted' => TRUE));
|
||||
foreach ($field_storages as $field_storage) {
|
||||
if (!in_array($field_storage->getTypeProvider(), $providers)) {
|
||||
$storages_to_delete[$field_storage->id()] = $field_storage;
|
||||
}
|
||||
}
|
||||
return $storages_to_delete;
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue