diff --git a/core/modules/config/config.local_tasks.yml b/core/modules/config/config.local_tasks.yml index 98ee75b..b24f53b 100644 --- a/core/modules/config/config.local_tasks.yml +++ b/core/modules/config/config.local_tasks.yml @@ -2,14 +2,37 @@ config.sync: route_name: config.sync tab_root_id: config.sync title: 'Synchronize' - weight: 0 -config.export: - route_name: config.export + +config.full: + route_name: config.import_full + title: 'Full Import/Export' tab_root_id: config.sync + +config.single: + route_name: config.import_single + title: 'Single Import/Export' + tab_root_id: config.sync + +config.export_full: + route_name: config.export_full + title: Export + tab_root_id: config.sync + tab_parent_id: config.full + +config.import_full: + route_name: config.import_full + title: Import + tab_root_id: config.sync + tab_parent_id: config.full + +config.export_single: + route_name: config.export_single title: Export - weight: 1 -config.import: - route_name: config.import + tab_root_id: config.sync + tab_parent_id: config.single + +config.import_single: + route_name: config.import_single title: Import tab_root_id: config.sync - weight: 2 + tab_parent_id: config.single diff --git a/core/modules/config/config.routing.yml b/core/modules/config/config.routing.yml index 23b2411..bd0d5c5 100644 --- a/core/modules/config/config.routing.yml +++ b/core/modules/config/config.routing.yml @@ -13,25 +13,43 @@ config.diff: requirements: _permission: 'synchronize configuration' -config_export_download: - path: '/admin/config/development/configuration/export-download' +config.export_download: + path: '/admin/config/development/configuration/full/export-download' defaults: _controller: '\Drupal\config\Controller\ConfigController::downloadExport' requirements: _permission: 'export configuration' -config.export: - path: '/admin/config/development/configuration/export' +config.export_full: + path: '/admin/config/development/configuration/full/export' defaults: _form: '\Drupal\config\Form\ConfigExportForm' _title: 'Export' requirements: _permission: 'export configuration' -config.import: - path: '/admin/config/development/configuration/import' +config.import_full: + path: '/admin/config/development/configuration/full/import' defaults: _form: '\Drupal\config\Form\ConfigImportForm' _title: 'Import' requirements: _permission: 'import configuration' + +config.import_single: + path: '/admin/config/development/configuration/single/import' + defaults: + _title: 'Single import' + _form: '\Drupal\config\Form\ConfigSingleImportForm' + requirements: + _permission: 'import configuration' + +config.export_single: + path: '/admin/config/development/configuration/single/export/{config_type}/{config_name}' + defaults: + _title: 'Single export' + _form: '\Drupal\config\Form\ConfigSingleExportForm' + config_type: NULL + config_name: NULL + requirements: + _permission: 'export configuration' diff --git a/core/modules/config/lib/Drupal/config/Form/ConfigExportForm.php b/core/modules/config/lib/Drupal/config/Form/ConfigExportForm.php index f5f42e8..7f41e50 100644 --- a/core/modules/config/lib/Drupal/config/Form/ConfigExportForm.php +++ b/core/modules/config/lib/Drupal/config/Form/ConfigExportForm.php @@ -39,7 +39,7 @@ public function buildForm(array $form, array &$form_state) { * {@inheritdoc} */ public function submitForm(array &$form, array &$form_state) { - $form_state['redirect'] = 'admin/config/development/configuration/export-download'; + $form_state['redirect'] = 'admin/config/development/configuration/full/export-download'; } } diff --git a/core/modules/config/lib/Drupal/config/Form/ConfigSingleExportForm.php b/core/modules/config/lib/Drupal/config/Form/ConfigSingleExportForm.php new file mode 100644 index 0000000..e70bd40 --- /dev/null +++ b/core/modules/config/lib/Drupal/config/Form/ConfigSingleExportForm.php @@ -0,0 +1,203 @@ +entityManager = $entity_manager; + $this->configStorage = $config_storage; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager'), + $container->get('config.storage') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'config_single_export_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state, $config_type = NULL, $config_name = NULL) { + foreach ($this->entityManager->getDefinitions() as $entity_type => $definition) { + if (isset($definition['config_prefix']) && isset($definition['entity_keys']['uuid'])) { + $this->definitions[$entity_type] = $definition; + } + } + $entity_types = array_map(function ($definition) { + return $definition['label']; + }, $this->definitions); + // Sort the entity types by label, then add the simple config to the top. + uasort($entity_types, 'strnatcasecmp'); + $config_types = array( + 'system.simple' => $this->t('Simple configuration'), + ) + $entity_types; + $form['config_type'] = array( + '#title' => $this->t('Configuration type'), + '#type' => 'select', + '#options' => $config_types, + '#default_value' => $config_type, + '#ajax' => array( + 'callback' => array($this, 'updateConfigurationType'), + 'wrapper' => 'edit-config-type-wrapper', + ), + ); + $default_type = isset($form_state['values']['config_type']) ? $form_state['values']['config_type'] : $config_type; + $form['config_name'] = array( + '#title' => $this->t('Configuration name'), + '#type' => 'select', + '#options' => $this->findConfiguration($default_type), + '#default_value' => $config_name, + '#required' => TRUE, + '#prefix' => '
', + '#suffix' => '
', + '#ajax' => array( + 'callback' => array($this, 'updateExport'), + 'wrapper' => 'edit-export-wrapper', + ), + ); + + $form['export'] = array( + '#title' => $this->t('Here is your configuration:'), + '#type' => 'textarea', + '#rows' => 24, + '#required' => TRUE, + '#prefix' => '
', + '#suffix' => '
', + ); + if ($config_type && $config_name) { + $fake_form_state = array('values' => array( + 'config_type' => $config_type, + 'config_name' => $config_name, + )); + $form['export'] = $this->updateExport($form, $fake_form_state); + } + return $form; + } + + /** + * Handles switching the configuration type selector. + */ + public function updateConfigurationType($form, &$form_state) { + $form['config_name']['#options'] = $this->findConfiguration($form_state['values']['config_type']); + return $form['config_name']; + } + + /** + * Handles switching the export textarea. + */ + public function updateExport($form, &$form_state) { + // Determine the full config name for the selected config entity. + if ($form_state['values']['config_type'] !== 'system.simple') { + $definition = $this->entityManager->getDefinition($form_state['values']['config_type']); + $name = $definition['config_prefix'] . '.' . $form_state['values']['config_name']; + } + // The config name is used directly for simple configuration. + else { + $name = $form_state['values']['config_name']; + } + // Read the raw data for this config name, encode it, and display it. + $data = $this->configStorage->read($name); + $form['export']['#value'] = $this->configStorage->encode($data); + $form['export']['#description'] = $this->t('The filename is %name.', array('%name' => $name . '.yml')); + return $form['export']; + } + + /** + * Handles switching the configuration type selector. + */ + protected function findConfiguration($config_type) { + $names = array( + '' => $this->t('- Select -'), + ); + // For a given entity type, load all entities. + if ($config_type && $config_type !== 'system.simple') { + $entity_storage = $this->entityManager->getStorageController($config_type); + foreach ($entity_storage->loadMultiple() as $entity) { + $entity_id = $entity->id(); + $label = $entity->label() ?: $entity_id; + $names[$entity_id] = $label; + } + } + // Handle simple configuration. + else { + // Gather the config entity prefixes. + $config_prefixes = array_map(function ($definition) { + return $definition['config_prefix'] . '.'; + }, $this->definitions); + + // Find all config, and then filter our anything matching a config prefix. + $names = MapArray::copyValuesToKeys($this->configStorage->listAll()); + foreach ($names as $config_name) { + foreach ($config_prefixes as $config_prefix) { + if (strpos($config_name, $config_prefix) === 0) { + unset($names[$config_name]); + } + } + } + } + return $names; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + // Nothing to submit. + } + +} diff --git a/core/modules/config/lib/Drupal/config/Form/ConfigSingleImportForm.php b/core/modules/config/lib/Drupal/config/Form/ConfigSingleImportForm.php new file mode 100644 index 0000000..5334765 --- /dev/null +++ b/core/modules/config/lib/Drupal/config/Form/ConfigSingleImportForm.php @@ -0,0 +1,247 @@ +entityManager = $entity_manager; + $this->configStorage = $config_storage; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager'), + $container->get('config.storage') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'config_single_import_form'; + } + + /** + * {@inheritdoc} + */ + public function getCancelRoute() { + return array( + 'route_name' => 'config.import_single', + ); + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + if ($this->data['config_type'] === 'system.simple') { + $name = $this->data['config_name']; + $type = $this->t('Simple configuration'); + } + else { + $definition = $this->entityManager->getDefinition($this->data['config_type']); + $name = $this->data['import'][$definition['entity_keys']['id']]; + $type = $definition['label']; + } + + $args = array( + '%name' => $name, + '@type' => strtolower($type), + ); + if ($this->configExists) { + $question = $this->t('Are you sure you want to update the %name @type?', $args); + } + else { + $question = $this->t('Are you sure you want to create new %name @type?', $args); + } + return $question; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state) { + // When this is the confirmation step fall through to the confirmation form. + if ($this->data) { + return parent::buildForm($form, $form_state); + } + + $entity_types = array(); + foreach ($this->entityManager->getDefinitions() as $entity_type => $definition) { + if (isset($definition['config_prefix']) && isset($definition['entity_keys']['uuid'])) { + $entity_types[$entity_type] = $definition['label']; + } + } + // Sort the entity types by label, then add the simple config to the top. + uasort($entity_types, 'strnatcasecmp'); + $config_types = array( + 'system.simple' => $this->t('Simple configuration'), + ) + $entity_types; + $form['config_type'] = array( + '#title' => $this->t('Configuration type'), + '#type' => 'select', + '#options' => $config_types, + '#required' => TRUE, + ); + $form['config_name'] = array( + '#title' => $this->t('Configuration name'), + '#type' => 'textfield', + '#states' => array( + 'required' => array( + ':input[name="config_type"]' => array('value' => 'system.simple'), + ), + 'visible' => array( + ':input[name="config_type"]' => array('value' => 'system.simple'), + ), + ), + ); + $form['import'] = array( + '#title' => $this->t('Paste your configuration here'), + '#type' => 'textarea', + '#rows' => 24, + '#required' => TRUE, + ); + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => $this->t('Import'), + '#button_type' => 'primary', + ); + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + // The confirmation step needs no additional validation. + if ($this->data) { + return; + } + + // Decode the submitted import. + $data = $this->configStorage->decode($form_state['values']['import']); + + // Validate for config entities. + if ($form_state['values']['config_type'] !== 'system.simple') { + $definition = $this->entityManager->getDefinition($form_state['values']['config_type']); + $id_key = $definition['entity_keys']['id']; + $entity_storage = $this->entityManager->getStorageController($form_state['values']['config_type']); + // If an entity ID was not specified, set an error. + if (!isset($data[$id_key])) { + form_set_error('import', $this->t('Missing ID key "@id_key" for this @entity_type import.', array('@id_key' => $id_key, '@entity_type' => $definition['label']))); + return; + } + $uuid_key = $definition['entity_keys']['uuid']; + // If there is an existing entity, ensure matching ID and UUID. + if ($entity = $entity_storage->load($data[$id_key])) { + $this->configExists = $entity; + if (!isset($data[$uuid_key])) { + form_set_error('import', $this->t('An entity with this machine name already exists but the import did not specify a UUID.')); + return; + } + if ($data[$uuid_key] !== $entity->uuid()) { + form_set_error('import', $this->t('An entity with this machine name already exists but the UUID does not match.')); + return; + } + } + // If there is no entity with a matching ID, check for a UUID match. + elseif (isset($data[$uuid_key]) && $entity_storage->loadByProperties(array($uuid_key => $data[$uuid_key]))) { + form_set_error('import', $this->t('An entity with this UUID already exists but the machine name does not match.')); + } + } + else { + $config = $this->config($form_state['values']['config_name']); + $this->configExists = $config->isNew() ? $config : FALSE; + } + + // Store the decoded version of the submitted import. + form_set_value($form['import'], $data, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + // If this form has not yet been confirmed, store the values and rebuild. + if (!$this->data) { + $form_state['rebuild'] = TRUE; + $this->data = $form_state['values']; + return; + } + + // If a simple configuration file was added, set the data and save. + if ($this->data['config_type'] === 'system.simple') { + $this->config($this->data['config_name'])->setData($this->data['import'])->save(); + drupal_set_message($this->t('The %name configuration was imported.', array('%name' => $this->data['config_name']))); + } + // For a config entity, create a new entity and save it. + else { + try { + $entity = $this->entityManager + ->getStorageController($this->data['config_type']) + ->create($this->data['import']); + $entity->save(); + drupal_set_message($this->t('The @entity_type %label was imported.', array('@entity_type' => $entity->entityType(), '%label' => $entity->label()))); + } + catch (\Exception $e) { + drupal_set_message($e->getMessage(), 'error'); + } + } + } + +} diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigExportImportUITest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigExportImportUITest.php index 1be3528..539879a 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigExportImportUITest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigExportImportUITest.php @@ -75,7 +75,7 @@ function testExport() { \Drupal::config('system.site') ->set('slogan', $this->slogan) ->save(); - $this->drupalPostForm('admin/config/development/configuration/export', array(), 'Export'); + $this->drupalPostForm('admin/config/development/configuration/full/export', array(), 'Export'); $this->tarball = $this->drupalGetContent(); } @@ -105,7 +105,7 @@ function testImport() { */ protected function doImport($filename) { $this->assertNotEqual($this->slogan, \Drupal::config('system.site')->get('slogan')); - $this->drupalPostForm('admin/config/development/configuration/import', array('files[import_tarball]' => $filename), 'Upload'); + $this->drupalPostForm('admin/config/development/configuration/full/import', array('files[import_tarball]' => $filename), 'Upload'); $this->drupalPostForm(NULL, array(), 'Import all'); $this->assertEqual($this->slogan, \Drupal::config('system.site')->get('slogan')); } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigExportUITest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigExportUITest.php index 71c6762..45776e5 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigExportUITest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigExportUITest.php @@ -44,11 +44,11 @@ protected function setUp() { */ function testExport() { // Verify the export page with export submit button is available. - $this->drupalGet('admin/config/development/configuration/export'); + $this->drupalGet('admin/config/development/configuration/full/export'); $this->assertFieldById('edit-submit', t('Export')); // Submit the export form and verify response. - $this->drupalPostForm('admin/config/development/configuration/export', array(), t('Export')); + $this->drupalPostForm('admin/config/development/configuration/full/export', array(), t('Export')); $this->assertResponse(200, 'User can access the download callback.'); // Get the archived binary file provided to user for download. diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportUploadTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportUploadTest.php index b78639b..025c2f4 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportUploadTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportUploadTest.php @@ -36,13 +36,13 @@ function setUp() { */ function testImport() { // Verify access to the config upload form. - $this->drupalGet('admin/config/development/configuration/import'); + $this->drupalGet('admin/config/development/configuration/full/import'); $this->assertResponse(200); // Attempt to upload a non-tar file. $text_file = current($this->drupalGetTestFiles('text')); $edit = array('files[import_tarball]' => drupal_realpath($text_file->uri)); - $this->drupalPostForm('admin/config/development/configuration/import', $edit, t('Upload')); + $this->drupalPostForm('admin/config/development/configuration/full/import', $edit, t('Upload')); $this->assertText(t('Could not extract the contents of the tar file')); } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigSingleImportExportTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigSingleImportExportTest.php new file mode 100644 index 0000000..6d610a0 --- /dev/null +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigSingleImportExportTest.php @@ -0,0 +1,131 @@ + 'Configuration Single Import/Export UI', + 'description' => 'Tests the user interface for importing/exporting a single configuration.', + 'group' => 'Configuration', + ); + } + + /** + * Tests importing a single configuration file. + */ + public function testImport() { + $storage = \Drupal::entityManager()->getStorageController('config_test'); + $uuid = \Drupal::service('uuid'); + + $this->drupalLogin($this->drupalCreateUser(array('import configuration'))); + $import = << 'config_test', + 'import' => $import, + ); + // Attempt an import with a missing ID. + $this->drupalPostForm('admin/config/development/configuration/single/import', $edit, t('Import')); + $this->assertText(t('Missing ID key "@id_key" for this @entity_type import.', array('@id_key' => 'id', '@entity_type' => 'Test configuration'))); + + // Perform an import with no specified UUID and a unique ID. + $this->assertNull($storage->load('first')); + $edit['import'] = "id: first\n" . $edit['import']; + $this->drupalPostForm('admin/config/development/configuration/single/import', $edit, t('Import')); + $this->assertRaw(t('Are you sure you want to create new %name @type?', array('%name' => 'first', '@type' => 'test configuration'))); + $this->drupalPostForm(NULL, array(), t('Confirm')); + $entity = $storage->load('first'); + $this->assertIdentical($entity->label(), 'First'); + $this->assertIdentical($entity->id(), 'first'); + $this->assertTrue($entity->status()); + $this->assertRaw(t('The @entity_type %label was imported.', array('@entity_type' => 'config_test', '%label' => $entity->label()))); + + // Attempt an import with an existing ID but missing UUID. + $this->drupalPostForm('admin/config/development/configuration/single/import', $edit, t('Import')); + $this->assertText(t('An entity with this machine name already exists but the import did not specify a UUID.')); + + // Attempt an import with a mismatched UUID and existing ID. + $edit['import'] .= "\nuuid: " . $uuid->generate(); + $this->drupalPostForm('admin/config/development/configuration/single/import', $edit, t('Import')); + $this->assertText(t('An entity with this machine name already exists but the UUID does not match.')); + + // Perform an import with a unique ID and UUID. + $import = << 'config_test', + 'import' => $import, + ); + $second_uuid = $uuid->generate(); + $edit['import'] .= "\nuuid: " . $second_uuid; + $this->drupalPostForm('admin/config/development/configuration/single/import', $edit, t('Import')); + $this->assertRaw(t('Are you sure you want to create new %name @type?', array('%name' => 'second', '@type' => 'test configuration'))); + $this->drupalPostForm(NULL, array(), t('Confirm')); + $entity = $storage->load('second'); + $this->assertRaw(t('The @entity_type %label was imported.', array('@entity_type' => 'config_test', '%label' => $entity->label()))); + $this->assertIdentical($entity->label(), 'Second'); + $this->assertIdentical($entity->id(), 'second'); + $this->assertFalse($entity->status()); + $this->assertIdentical($entity->uuid(), $second_uuid); + } + + /** + * Tests exporting a single configuration file. + */ + public function testExport() { + $this->drupalLogin($this->drupalCreateUser(array('export configuration'))); + + $this->drupalGet('admin/config/development/configuration/single/export/system.simple'); + $this->assertFieldByXPath('//select[@name="config_type"]//option', t('Date format'), 'The date format entity type is selected when specified in the URL.'); + // Spot check several known simple configuration files. + $element = $this->xpath('//select[@name="config_name"]'); + $options = $this->getAllOptions($element[0]); + $expected_options = array('filter.settings', 'system.site', 'user.settings'); + foreach ($options as &$option) { + $option = (string) $option; + } + $this->assertIdentical($expected_options, array_intersect($expected_options, $options), 'The expected configuration files are listed.'); + + $this->drupalGet('admin/config/development/configuration/single/export/system.simple/system.image'); + $this->assertFieldByXPath('//textarea[@name="export"]', "toolkit: gd\n", 'The expected system configuration is displayed.'); + + $this->drupalGet('admin/config/development/configuration/single/export/date_format'); + $this->assertFieldByXPath('//select[@name="config_type"]//option', t('Date format'), 'The date format entity type is selected when specified in the URL.'); + + $this->drupalGet('admin/config/development/configuration/single/export/date_format/fallback'); + $this->assertFieldByXPath('//select[@name="config_name"]//option', t('Fallback date format'), 'The fallback date format config entity is selected when specified in the URL.'); + + $fallback_date = \Drupal::entityManager()->getStorageController('date_format')->load('fallback'); + $data = \Drupal::service('config.storage')->encode($fallback_date->getExportProperties()); + $this->assertFieldByXPath('//textarea[@name="export"]', $data, 'The fallback date format config entity export code is displayed.'); + } + +} diff --git a/core/modules/config/tests/Drupal/config/Tests/Menu/ConfigLocalTasksTest.php b/core/modules/config/tests/Drupal/config/Tests/Menu/ConfigLocalTasksTest.php index 43640c5..7d1bcd1 100644 --- a/core/modules/config/tests/Drupal/config/Tests/Menu/ConfigLocalTasksTest.php +++ b/core/modules/config/tests/Drupal/config/Tests/Menu/ConfigLocalTasksTest.php @@ -44,9 +44,11 @@ public function testConfigAdminLocalTasks($route, $expected) { */ public function getConfigAdminRoutes() { return array( - array('config.sync', array(array('config.sync', 'config.export', 'config.import'))), - array('config.export', array(array('config.sync', 'config.export', 'config.import'))), - array('config.import', array(array('config.sync', 'config.export', 'config.import'))), + array('config.sync', array(array('config.sync', 'config.full', 'config.single'))), + array('config.export_full', array(array('config.sync', 'config.full', 'config.single'), array('config.export_full', 'config.import_full'))), + array('config.import_full', array(array('config.sync', 'config.full', 'config.single'), array('config.export_full', 'config.import_full'))), + array('config.export_single', array(array('config.sync', 'config.full', 'config.single'), array('config.export_single', 'config.import_single'))), + array('config.import_single', array(array('config.sync', 'config.full', 'config.single'), array('config.export_single', 'config.import_single'))), ); } diff --git a/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php b/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php index 2b4ef46..d74db76 100644 --- a/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php +++ b/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php @@ -114,10 +114,10 @@ public function importDelete($name, Config $new_config, Config $old_config) { public function loadByProperties(array $conditions = array()) { // Include instances of inactive fields if specified in the // $conditions parameters. - $include_inactive = $conditions['include_inactive']; + $include_inactive = isset($conditions['include_inactive']) ? $conditions['include_inactive'] : FALSE; unset($conditions['include_inactive']); // Include deleted instances if specified in the $conditions parameters. - $include_deleted = $conditions['include_deleted']; + $include_deleted = isset($conditions['include_deleted']) ? $conditions['include_deleted'] : FALSE; unset($conditions['include_deleted']); // Get instances stored in configuration. diff --git a/core/modules/field/lib/Drupal/field/FieldStorageController.php b/core/modules/field/lib/Drupal/field/FieldStorageController.php index fff0df7..b18ffe3 100644 --- a/core/modules/field/lib/Drupal/field/FieldStorageController.php +++ b/core/modules/field/lib/Drupal/field/FieldStorageController.php @@ -96,10 +96,10 @@ public static function createInstance(ContainerInterface $container, $entity_typ public function loadByProperties(array $conditions = array()) { // Include instances of inactive fields if specified in the // $conditions parameters. - $include_inactive = $conditions['include_inactive']; + $include_inactive = isset($conditions['include_inactive']) ? $conditions['include_inactive'] : FALSE; unset($conditions['include_inactive']); // Include deleted instances if specified in the $conditions parameters. - $include_deleted = $conditions['include_deleted']; + $include_deleted = isset($conditions['include_deleted']) ? $conditions['include_deleted'] : FALSE; unset($conditions['include_deleted']); // Get fields stored in configuration.