public function testRecreateEntity() { $type_name = Unicode::strtolower($this->randomMachineName(16)); $content_type = entity_create('node_type', array('type' => $type_name, 'name' => 'Node type one')); $content_type->save(); node_add_body_field($content_type); /** @var \Drupal\Core\Config\StorageInterface $active */ $active = $this->container->get('config.storage'); /** @var \Drupal\Core\Config\StorageInterface $sync */ $sync = $this->container->get('config.storage.sync'); $config_name = $content_type->getEntityType()->getConfigPrefix() . '.' . $content_type->id(); $this->copyConfig($active, $sync); // Delete the content type. This will also delete a field storage, a field, // an entity view display and an entity form display. $content_type->delete(); $this->assertFalse($active->exists($config_name), 'Content type\'s old name does not exist active store.'); // Recreate with the same type - this will have a different UUID. $content_type = entity_create('node_type', array('type' => $type_name, 'name' => 'Node type two')); $content_type->save(); node_add_body_field($content_type); $this->configImporter->reset(); // A node type, a field, an entity view display and an entity form display // will be recreated. $creates = $this->configImporter->getUnprocessedConfiguration('create'); $deletes = $this->configImporter->getUnprocessedConfiguration('delete'); $this->assertEqual(5, count($creates), 'There are 5 configuration items to create.'); $this->assertEqual(5, count($deletes), 'There are 5 configuration items to delete.'); $this->assertEqual(0, count($this->configImporter->getUnprocessedConfiguration('update')), 'There are no configuration items to update.'); $this->assertIdentical($creates, array_reverse($deletes), 'Deletes and creates contain the same configuration names in opposite orders due to dependencies.'); $this->configImporter->import(); // Verify that there is nothing more to import. $this->assertFalse($this->configImporter->reset()->hasUnprocessedConfigurationChanges()); $content_type = NodeType::load($type_name); $this->assertEqual('Node type one', $content_type->label()); }
/** * Tests configuration renaming validation for simple configuration. */ public function testRenameSimpleConfigValidation() { $uuid = new Php(); // Create a simple configuration with a UUID. $config = $this->config('config_test.new'); $uuid_value = $uuid->generate(); $config->set('uuid', $uuid_value)->save(); $active = $this->container->get('config.storage'); $sync = $this->container->get('config.storage.sync'); $this->copyConfig($active, $sync); $config->delete(); // Create another simple configuration with the same UUID. $config = $this->config('config_test.old'); $config->set('uuid', $uuid_value)->save(); // Confirm that the staged configuration is detected as a rename since the // UUIDs match. $this->configImporter->reset(); $expected = array('config_test.old::config_test.new'); $renames = $this->configImporter->getUnprocessedConfiguration('rename'); $this->assertIdentical($expected, $renames); // Try to import the configuration. We expect an exception to be thrown // because the rename is for simple configuration. try { $this->configImporter->import(); $this->fail('Expected ConfigImporterException thrown when simple configuration is renamed.'); } catch (ConfigImporterException $e) { $this->pass('Expected ConfigImporterException thrown when simple configuration is renamed.'); $expected = array(SafeMarkup::format('Rename operation for simple configuration. Existing configuration @old_name and staged configuration @new_name.', array('@old_name' => 'config_test.old', '@new_name' => 'config_test.new'))); $this->assertEqual($expected, $this->configImporter->getErrors()); } }
/** * 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; }
/** * Alter the configuration synchronization steps. * * @param array $sync_steps * A one-dimensional array of \Drupal\Core\Config\ConfigImporter method names * or callables that are invoked to complete the import, in the order that * they will be processed. Each callable item defined in $sync_steps should * either be a global function or a public static method. The callable should * accept a $context array by reference. For example: * <code> * function _additional_configuration_step(&$context) { * // Do stuff. * // If finished set $context['finished'] = 1. * } * </code> * For more information on creating batches, see the * @link batch Batch operations @endlink documentation. * * @see callback_batch_operation() * @see \Drupal\Core\Config\ConfigImporter::initialize() */ function hook_config_import_steps_alter(&$sync_steps, \Drupal\Core\Config\ConfigImporter $config_importer) { $deletes = $config_importer->getUnprocessedConfiguration('delete'); if (isset($deletes['field.storage.node.body'])) { $sync_steps[] = '_additional_configuration_step'; } }
/** * Processes all pending index tasks inside a batch run. * * @param array $context * The current batch context. * @param \Drupal\Core\Config\ConfigImporter $config_importer * The config importer. */ public static function processIndexTasks(array &$context, ConfigImporter $config_importer) { $index_task_manager = \Drupal::getContainer()->get('search_api.index_task_manager'); if (!isset($context['sandbox']['indexes'])) { $context['sandbox']['indexes'] = array(); $indexes = \Drupal::entityTypeManager()->getStorage('search_api_index')->loadByProperties(array('status' => TRUE)); $deleted = $config_importer->getUnprocessedConfiguration('delete'); /** @var \Drupal\search_api\IndexInterface $index */ foreach ($indexes as $index_id => $index) { if (!$index_task_manager->isTrackingComplete($index) && !in_array($index->getConfigDependencyName(), $deleted)) { $context['sandbox']['indexes'][] = $index_id; } } $context['sandbox']['total'] = count($context['sandbox']['indexes']); if (!$context['sandbox']['total']) { $context['finished'] = 1; return; } } $index_id = array_shift($context['sandbox']['indexes']); $index = Index::load($index_id); $added = $index_task_manager->addItemsOnce($index); if ($added !== NULL) { array_unshift($context['sandbox']['indexes'], $index_id); } if (empty($context['sandbox']['indexes'])) { $context['finished'] = 1; } else { $finished = $context['sandbox']['total'] - count($context['sandbox']['indexes']); $context['finished'] = $finished / $context['sandbox']['total']; $args = array('%index' => $index->label(), '@num' => $finished + 1, '@total' => $context['sandbox']['total']); $context['message'] = \Drupal::translation()->translate('Tracking items for search index %index (@num of @total)', $args); } }