/** * Re-save all field storage config objects to add 'custom_storage' property. */ function field_post_update_save_custom_storage_property() { foreach (FieldStorageConfig::loadMultiple() as $field_storage_config) { $field_storage_config->save(); } return t('All field storage configuration objects re-saved.'); }
/** * Builds the fields info overview page. * * @return array * Array of page elements to render. */ public function fieldInfoPage() { $fields = FieldStorageConfig::loadMultiple(); ksort($fields); $output['fields'] = array('#markup' => kprint_r($fields, TRUE, $this->t('Fields'))); $field_instances = FieldConfig::loadMultiple(); ksort($field_instances); $output['instances'] = array('#markup' => kprint_r($field_instances, TRUE, $this->t('Instances'))); $bundles = $this->entityManager()->getAllBundleInfo(); ksort($bundles); $output['bundles'] = array('#markup' => kprint_r($bundles, TRUE, $this->t('Bundles'))); $field_types = \Drupal::service('plugin.manager.field.field_type')->getUiDefinitions(); ksort($field_types); $output['field_types'] = array('#markup' => kprint_r($field_types, TRUE, $this->t('Field types'))); $formatter_types = \Drupal::service('plugin.manager.field.formatter')->getDefinitions(); ksort($formatter_types); $output['formatter_types'] = array('#markup' => kprint_r($formatter_types, TRUE, $this->t('Formatter types'))); $widget_types = \Drupal::service('plugin.manager.field.widget')->getDefinitions(); ksort($widget_types); $output['widget_types'] = array('#markup' => kprint_r($widget_types, TRUE, $this->t('Widget types'))); return $output; }
/** * 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; }
/** * Tests a simple site export import case. */ public function testExportImport() { // After installation there is no snapshot and nothing to import. $this->drupalGet('admin/config/development/configuration'); $this->assertNoText(t('Warning message')); $this->assertText(t('There are no configuration changes to import.')); $this->originalSlogan = $this->config('system.site')->get('slogan'); $this->newSlogan = $this->randomString(16); $this->assertNotEqual($this->newSlogan, $this->originalSlogan); $this->config('system.site')->set('slogan', $this->newSlogan)->save(); $this->assertEqual($this->config('system.site')->get('slogan'), $this->newSlogan); // Create a content type. $this->contentType = $this->drupalCreateContentType(); // Create a field. $this->fieldName = Unicode::strtolower($this->randomMachineName()); $this->fieldStorage = entity_create('field_storage_config', array('field_name' => $this->fieldName, 'entity_type' => 'node', 'type' => 'text')); $this->fieldStorage->save(); entity_create('field_config', array('field_storage' => $this->fieldStorage, 'bundle' => $this->contentType->id()))->save(); // Update the displays so that configuration does not change unexpectedly on // import. entity_get_form_display('node', $this->contentType->id(), 'default')->setComponent($this->fieldName, array('type' => 'text_textfield'))->save(); entity_get_display('node', $this->contentType->id(), 'full')->setComponent($this->fieldName)->save(); entity_get_display('node', $this->contentType->id(), 'default')->setComponent($this->fieldName)->save(); entity_get_display('node', $this->contentType->id(), 'teaser')->removeComponent($this->fieldName)->save(); $this->drupalGet('node/add/' . $this->contentType->id()); $this->assertFieldByName("{$this->fieldName}[0][value]", '', 'Widget is displayed'); // Export the configuration. $this->drupalPostForm('admin/config/development/configuration/full/export', array(), 'Export'); $this->tarball = $this->getRawContent(); $this->config('system.site')->set('slogan', $this->originalSlogan)->save(); $this->assertEqual($this->config('system.site')->get('slogan'), $this->originalSlogan); // Delete the custom field. $fields = FieldConfig::loadMultiple(); foreach ($fields as $field) { if ($field->getName() == $this->fieldName) { $field->delete(); } } $field_storages = FieldStorageConfig::loadMultiple(); foreach ($field_storages as $field_storage) { if ($field_storage->getName() == $this->fieldName) { $field_storage->delete(); } } $this->drupalGet('node/add/' . $this->contentType->id()); $this->assertNoFieldByName("{$this->fieldName}[0][value]", '', 'Widget is not displayed'); // Import the configuration. $filename = 'temporary://' . $this->randomMachineName(); file_put_contents($filename, $this->tarball); $this->drupalPostForm('admin/config/development/configuration/full/import', array('files[import_tarball]' => $filename), 'Upload'); // There is no snapshot yet because an import has never run. $this->assertNoText(t('Warning message')); $this->assertNoText(t('There are no configuration changes to import.')); $this->assertText($this->contentType->label()); $this->drupalPostForm(NULL, array(), 'Import all'); // After importing the snapshot has been updated an there are no warnings. $this->assertNoText(t('Warning message')); $this->assertText(t('There are no configuration changes to import.')); $this->assertEqual($this->config('system.site')->get('slogan'), $this->newSlogan); $this->drupalGet('node/add'); $this->assertFieldByName("{$this->fieldName}[0][value]", '', 'Widget is displayed'); $this->config('system.site')->set('slogan', $this->originalSlogan)->save(); $this->drupalGet('admin/config/development/configuration'); $this->assertText(t('Warning message')); $this->assertText('The following items in your active configuration have changes since the last import that may be lost on the next import.'); // Ensure the item is displayed as part of a list (to avoid false matches // on the rest of the page) and that the list markup is not escaped. $this->assertRaw('<li>system.site</li>'); // Remove everything from staging. The warning about differences between the // active and snapshot should no longer exist. \Drupal::service('config.storage.staging')->deleteAll(); $this->drupalGet('admin/config/development/configuration'); $this->assertNoText(t('Warning message')); $this->assertNoText('The following items in your active configuration have changes since the last import that may be lost on the next import.'); $this->assertText(t('There are no configuration changes to import.')); // Write a file to staging. The warning about differences between the // active and snapshot should now exist. /** @var \Drupal\Core\Config\StorageInterface $staging */ $staging = $this->container->get('config.storage.staging'); $data = $this->config('system.site')->get(); $data['slogan'] = 'in the face'; $this->copyConfig($this->container->get('config.storage'), $staging); $staging->write('system.site', $data); $this->drupalGet('admin/config/development/configuration'); $this->assertText(t('Warning message')); $this->assertText('The following items in your active configuration have changes since the last import that may be lost on the next import.'); // Ensure the item is displayed as part of a list (to avoid false matches // on the rest of the page) and that the list markup is not escaped. $this->assertRaw('<li>system.site</li>'); }
/** * Tests a simple site export import case. */ public function testExportImport() { // After installation there is no snapshot and nothing to import. $this->drupalGet('admin/config/development/configuration'); $this->assertNoText(t('Warning message')); $this->assertText(t('There are no configuration changes to import.')); $this->originalSlogan = $this->config('system.site')->get('slogan'); $this->newSlogan = $this->randomString(16); $this->assertNotEqual($this->newSlogan, $this->originalSlogan); $this->config('system.site')->set('slogan', $this->newSlogan)->save(); $this->assertEqual($this->config('system.site')->get('slogan'), $this->newSlogan); // Create a content type. $this->contentType = $this->drupalCreateContentType(); // Create a field. $this->fieldName = Unicode::strtolower($this->randomMachineName()); $this->fieldStorage = entity_create('field_storage_config', array('field_name' => $this->fieldName, 'entity_type' => 'node', 'type' => 'text')); $this->fieldStorage->save(); entity_create('field_config', array('field_storage' => $this->fieldStorage, 'bundle' => $this->contentType->id()))->save(); // Update the displays so that configuration does not change unexpectedly on // import. entity_get_form_display('node', $this->contentType->id(), 'default')->setComponent($this->fieldName, array('type' => 'text_textfield'))->save(); entity_get_display('node', $this->contentType->id(), 'full')->setComponent($this->fieldName)->save(); entity_get_display('node', $this->contentType->id(), 'default')->setComponent($this->fieldName)->save(); entity_get_display('node', $this->contentType->id(), 'teaser')->removeComponent($this->fieldName)->save(); $this->drupalGet('node/add/' . $this->contentType->id()); $this->assertFieldByName("{$this->fieldName}[0][value]", '', 'Widget is displayed'); // Export the configuration. $this->drupalPostForm('admin/config/development/configuration/full/export', array(), 'Export'); $this->tarball = $this->getRawContent(); $this->config('system.site')->set('slogan', $this->originalSlogan)->save(); $this->assertEqual($this->config('system.site')->get('slogan'), $this->originalSlogan); // Delete the custom field. $fields = FieldConfig::loadMultiple(); foreach ($fields as $field) { if ($field->field_name == $this->fieldName) { $field->delete(); } } $field_storages = FieldStorageConfig::loadMultiple(); foreach ($field_storages as $field_storage) { if ($field_storage->getName() == $this->fieldName) { $field_storage->delete(); } } $this->drupalGet('node/add/' . $this->contentType->id()); $this->assertNoFieldByName("{$this->fieldName}[0][value]", '', 'Widget is not displayed'); // Import the configuration. $filename = 'temporary://' . $this->randomMachineName(); file_put_contents($filename, $this->tarball); $this->drupalPostForm('admin/config/development/configuration/full/import', array('files[import_tarball]' => $filename), 'Upload'); // There is no snapshot yet because an import has never run. $this->assertNoText(t('Warning message')); $this->assertNoText(t('There are no configuration changes to import.')); $this->assertText($this->contentType->label()); $this->drupalPostForm(NULL, array(), 'Import all'); // After importing the snapshot has been updated an there are no warnings. $this->assertNoText(t('Warning message')); $this->assertText(t('There are no configuration changes to import.')); $this->assertEqual($this->config('system.site')->get('slogan'), $this->newSlogan); $this->drupalGet('node/add'); $this->assertFieldByName("{$this->fieldName}[0][value]", '', 'Widget is displayed'); $this->config('system.site')->set('slogan', $this->originalSlogan)->save(); $this->drupalGet('admin/config/development/configuration'); $this->assertText(t('Warning message')); $this->assertText('Your current configuration has changed. Changes to these configuration items will be lost on the next synchronization: system.site'); // Remove everything from staging. The warning about differences between the // active and snapshot should still exist. \Drupal::service('config.storage.staging')->deleteAll(); $this->drupalGet('admin/config/development/configuration'); $this->assertText(t('Warning message')); $this->assertText('Your current configuration has changed. Changes to these configuration items will be lost on the next synchronization: system.site'); $this->assertText(t('There are no configuration changes to import.')); }