/** * 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 changes that will be imported. * * @param string $op * (optional) A change operation. Either delete, create or update. If * supplied the returned list will be limited to this operation. * @param string $collection * (optional) The collection to get the changelist for. Defaults to the * default collection. * * @return array * An array of config changes that are yet to be imported. * * @see \Drupal\Core\Config\StorageComparerInterface::getChangelist() */ public function getChangelist($op = NULL, $collection = StorageInterface::DEFAULT_COLLECTION) { return $this->configImporter->getStorageComparer()->getChangelist($op, $collection); }
/** * Validates configuration being imported does not have unmet dependencies. * * @param \Drupal\Core\Config\ConfigImporter $config_importer * The configuration importer. */ protected function validateDependencies(ConfigImporter $config_importer) { $core_extension = $config_importer->getStorageComparer()->getSourceStorage()->read('core.extension'); $existing_dependencies = ['config' => $config_importer->getStorageComparer()->getSourceStorage()->listAll(), 'module' => array_keys($core_extension['module']), 'theme' => array_keys($core_extension['theme'])]; $theme_data = $this->getThemeData(); $module_data = $this->getModuleData(); // Validate the dependencies of all the configuration. We have to validate // the entire tree because existing configuration might depend on // configuration that is being deleted. foreach ($config_importer->getStorageComparer()->getSourceStorage()->listAll() as $name) { // Ensure that the config owner is installed. This checks all // configuration including configuration entities. list($owner, ) = explode('.', $name, 2); if ($owner !== 'core') { $message = FALSE; if (!isset($core_extension['module'][$owner]) && isset($module_data[$owner])) { $message = $this->t('Configuration %name depends on the %owner module that will not be installed after import.', array('%name' => $name, '%owner' => $module_data[$owner]->info['name'])); } elseif (!isset($core_extension['theme'][$owner]) && isset($theme_data[$owner])) { $message = $this->t('Configuration %name depends on the %owner theme that will not be installed after import.', array('%name' => $name, '%owner' => $theme_data[$owner]->info['name'])); } elseif (!isset($core_extension['module'][$owner]) && !isset($core_extension['theme'][$owner])) { $message = $this->t('Configuration %name depends on the %owner extension that will not be installed after import.', array('%name' => $name, '%owner' => $owner)); } if ($message) { $config_importer->logError($message); continue; } } $data = $config_importer->getStorageComparer()->getSourceStorage()->read($name); // Configuration entities have dependencies on modules, themes, and other // configuration entities that we can validate. Their content dependencies // are not validated since we assume that they are soft dependencies. // Configuration entities can be identified by having 'dependencies' and // 'uuid' keys. if (isset($data['dependencies']) && isset($data['uuid'])) { $dependencies_to_check = array_intersect_key($data['dependencies'], array_flip(['module', 'theme', 'config'])); foreach ($dependencies_to_check as $type => $dependencies) { $diffs = array_diff($dependencies, $existing_dependencies[$type]); if (!empty($diffs)) { $message = FALSE; switch ($type) { case 'module': $message = $this->formatPlural(count($diffs), 'Configuration %name depends on the %module module that will not be installed after import.', 'Configuration %name depends on modules (%module) that will not be installed after import.', array('%name' => $name, '%module' => implode(', ', $this->getNames($diffs, $module_data)))); break; case 'theme': $message = $this->formatPlural(count($diffs), 'Configuration %name depends on the %theme theme that will not be installed after import.', 'Configuration %name depends on themes (%theme) that will not be installed after import.', array('%name' => $name, '%theme' => implode(', ', $this->getNames($diffs, $theme_data)))); break; case 'config': $message = $this->formatPlural(count($diffs), 'Configuration %name depends on the %config configuration that will not exist after import.', 'Configuration %name depends on configuration (%config) that will not exist after import.', array('%name' => $name, '%config' => implode(', ', $diffs))); break; } if ($message) { $config_importer->logError($message); } } } } } }