Skip to content
Snippets Groups Projects
Commit 672bf6c3 authored by Sascha Grossenbacher's avatar Sascha Grossenbacher Committed by Miro Dietiker
Browse files

Issue #2826873 by yongt9412, Berdir, ModernMantra, miro_dietiker: Changes when...

Issue #2826873 by yongt9412, Berdir, ModernMantra, miro_dietiker: Changes when saving field configuration unchanged
parent a1767f0c
No related branches found
Tags 8.x-1.0-rc1
No related merge requests found
......@@ -6,9 +6,11 @@ use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Plugin type manager for field diff builders.
......@@ -117,93 +119,79 @@ class DiffBuilderManager extends DefaultPluginManager {
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The field definition.
* @param string $bundle
* (optional) The entity bundle where to check form display when selecting
* the plugin for a field.
*
* @return \Drupal\diff\FieldDiffBuilderInterface|null
* The plugin instance, NULL if none.
*/
public function createInstanceForFieldDefinition(FieldDefinitionInterface $field_definition, $bundle = NULL) {
$selected_plugin = $this->getSelectedPluginForFieldDefinition($field_definition, $bundle);
if ($selected_plugin && $selected_plugin['type'] != 'hidden') {
if (!empty($selected_plugin['settings'])) {
return $this->createInstance($selected_plugin['type'], $selected_plugin['settings']);
}
else {
return $this->createInstance($selected_plugin['type'], []);
}
public function createInstanceForFieldDefinition(FieldDefinitionInterface $field_definition) {
$selected_plugin = $this->getSelectedPluginForFieldStorageDefinition($field_definition->getFieldStorageDefinition());
if ($selected_plugin['type'] != 'hidden') {
return $this->createInstance($selected_plugin['type'], $selected_plugin['settings']);
}
return NULL;
}
/**
* Selects a default plugin for a field definition.
* Selects a default plugin for a field storage definition.
*
* Checks the display configuration of the field to define if it should be
* displayed in the diff comparison.
* Checks if a plugin has been already selected for the field, otherwise
* chooses one between the plugins that can be applied to the field.
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The field definition.
* @param string $bundle
* (optional) The entity bundle where to check the form display if no
* setting is set for a field.
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $field_definition
* The field storage definition.
*
* @return array
* The plugin instance, NULL if none.
* An array with the key type (which contains the plugin ID) and settings.
* The special type hidden indicates that the field should not be shown.
*/
public function getSelectedPluginForFieldDefinition(FieldDefinitionInterface $field_definition, $bundle = NULL) {
$selected_plugin = NULL;
$visible = TRUE;
$field_key = $field_definition->getFieldStorageDefinition()->getTargetEntityTypeId() . '.' . $field_definition->getName();
// Do not check the entity form display if there are plugins settings stored
// for the current field.
if ($this->pluginsConfig->get('fields.' . $field_key)) {
$selected_plugin = $this->getSelectedPluginForFieldStorageDefinition($field_definition->getFieldStorageDefinition());
public function getSelectedPluginForFieldStorageDefinition(FieldStorageDefinitionInterface $field_definition) {
$plugin_options = $this->getApplicablePluginOptions($field_definition);
$field_key = $field_definition->getTargetEntityTypeId() . '.' . $field_definition->getName();
// Start with the stored configuration, this returns NULL if there is none.
$selected_plugin = $this->pluginsConfig->get('fields.' . $field_key);
// If there is configuration and it is a valid type or exlplicitly set to
// hidden, then use that, otherwise try to find a suitable default plugin.
if ($selected_plugin && (in_array($selected_plugin['type'], array_keys($plugin_options)) || $selected_plugin['type'] == 'hidden')) {
return $selected_plugin + ['settings' => []];
}
elseif (!empty($plugin_options) && $this->isFieldStorageDefinitionDisplayed($field_definition)) {
return ['type' => key($plugin_options), 'settings' => []];
}
else {
// If entity is set load its form display settings.
if ($bundle) {
$storage = $this->entityTypeManager->getStorage('entity_form_display');
/** @var \Drupal\Core\Entity\Entity\EntityViewDisplay $display */
if ($display = $storage->load($field_definition->getTargetEntityTypeId() . '.' . $bundle . '.default')) {
$visible = (bool) $display->getComponent($field_definition->getName());
}
}
if ($visible) {
$selected_plugin = $this->getSelectedPluginForFieldStorageDefinition($field_definition->getFieldStorageDefinition());
}
return ['type' => 'hidden', 'settings' => []];
}
return $selected_plugin;
}
/**
* Selects a default plugin for a field storage definition.
* Determines if the field is displayed.
*
* Checks if a plugin has been already selected for the field, otherwise
* chooses one between the plugins that can be applied to the field.
* Determines if a field should be displayed when comparing revisions based on
* the entity view display if there is no plugin selected for the field.
*
* @param FieldStorageDefinitionInterface $field_definition
* The field storage definition.
* @param FieldStorageDefinitionInterface $field_storage_definition
* The field name.
*
* @return array
* The selected plugin for the field.
* @return bool
* Whether the field is displayed.
*/
public function getSelectedPluginForFieldStorageDefinition(FieldStorageDefinitionInterface $field_definition) {
$plugin_options = $this->getApplicablePluginOptions($field_definition);
$field_key = $field_definition->getTargetEntityTypeId() . '.' . $field_definition->getName();
$selected_plugin = $this->pluginsConfig->get('fields.' . $field_key);
// Check if the plugin stored to the fields is still applicable.
if (!$selected_plugin || !in_array($selected_plugin['type'], array_keys($plugin_options))) {
if (!empty($plugin_options)) {
$selected_plugin['type'] = array_keys($plugin_options)[0];
}
else {
$selected_plugin['type'] = 'hidden';
public function isFieldStorageDefinitionDisplayed(FieldStorageDefinitionInterface $field_storage_definition) {
if (($field_storage_definition instanceof BaseFieldDefinition && $field_storage_definition->isDisplayConfigurable('view')) || $field_storage_definition instanceof FieldStorageConfig) {
$field_key = 'content.' . $field_storage_definition->getName() . '.type';
$storage = $this->entityTypeManager->getStorage('entity_view_display');
$query = $storage->getQuery()->condition('targetEntityType', $field_storage_definition->getTargetEntityTypeId());
if ($field_storage_definition instanceof FieldStorageConfig) {
$bundles = $field_storage_definition->getBundles();
$query->condition('bundle', (array) $bundles, 'IN');
}
$result = $query->exists($field_key)->range(0, 1)->execute();
return !empty($result) ? TRUE : FALSE;
}
else {
$view_options = (bool) $field_storage_definition->getDisplayOptions('view');
return $view_options;
}
return $selected_plugin;
}
/**
......
......@@ -322,7 +322,7 @@ class DiffEntityComparison {
foreach ($revision as $field_items) {
$show_delta = FALSE;
// Create a plugin instance for the field definition.
$plugin = $this->diffBuilderManager->createInstanceForFieldDefinition($field_items->getFieldDefinition(), $revision->bundle());
$plugin = $this->diffBuilderManager->createInstanceForFieldDefinition($field_items->getFieldDefinition());
if ($plugin && $this->diffBuilderManager->showDiff($field_items->getFieldDefinition()->getFieldStorageDefinition())) {
// Create the array with the fields of the entity. Recursive if the
// field contains entities.
......
......@@ -78,7 +78,7 @@ class DiffEntityParser {
continue;
}
// Create a plugin instance for the field definition.
$plugin = $this->diffBuilderManager->createInstanceForFieldDefinition($field_items->getFieldDefinition(), $entity->bundle());
$plugin = $this->diffBuilderManager->createInstanceForFieldDefinition($field_items->getFieldDefinition());
if ($plugin) {
// Create the array with the fields of the entity. Recursive if the
// field contains entities.
......
......@@ -2,12 +2,10 @@
namespace Drupal\diff;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Plugin\PluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
......@@ -16,8 +14,6 @@ use Drupal\Core\Entity\EntityTypeManagerInterface;
*/
abstract class FieldDiffBuilderBase extends PluginBase implements FieldDiffBuilderInterface, ContainerFactoryPluginInterface {
use StringTranslationTrait;
/**
* Contains the configuration object factory.
*
......@@ -48,15 +44,12 @@ abstract class FieldDiffBuilderBase extends PluginBase implements FieldDiffBuild
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config
* The configuration factory object.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\diff\DiffEntityParser $entity_parser
* The entity parser.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, EntityTypeManagerInterface $entity_type_manager, DiffEntityParser $entity_parser) {
$this->configFactory = $config;
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, DiffEntityParser $entity_parser) {
$this->entityTypeManager = $entity_type_manager;
$this->entityParser = $entity_parser;
parent::__construct($configuration, $plugin_id, $plugin_definition);
......@@ -72,7 +65,6 @@ abstract class FieldDiffBuilderBase extends PluginBase implements FieldDiffBuild
$configuration,
$plugin_id,
$plugin_definition,
$container->get('config.factory'),
$container->get('entity_type.manager'),
$container->get('diff.entity_parser')
);
......@@ -116,9 +108,6 @@ abstract class FieldDiffBuilderBase extends PluginBase implements FieldDiffBuild
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['show_header'] = $form_state->getValue('show_header');
$this->configuration['markdown'] = $form_state->getValue('markdown');
$this->configuration['#fields'] = $form_state->get('fields');
$this->setConfiguration($this->configuration);
$this->getConfiguration()->save();
}
/**
......@@ -135,27 +124,14 @@ abstract class FieldDiffBuilderBase extends PluginBase implements FieldDiffBuild
* {@inheritdoc}
*/
public function getConfiguration() {
return $this->configFactory->getEditable('diff.plugins');
return $this->configuration;
}
/**
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
$config = $this->configFactory->getEditable('diff.plugins');
$field = $configuration['#fields'];
unset($configuration['#fields']);
$field_settings = [];
foreach ($configuration as $key => $value) {
$field_settings[$key] = $value;
}
$settings = array(
'type' => $this->pluginId,
'settings' => $field_settings,
);
$config->set('fields.' . $field, $settings);
$config->save();
$this->configuration = $configuration + $this->defaultConfiguration();
}
/**
......
......@@ -23,13 +23,6 @@ use Drupal\Core\Form\FormState;
*/
class FieldsSettingsForm extends ConfigFormBase {
/**
* Wrapper object for configuration from diff.plugins.yml.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected $config;
/**
* The entity type manager.
*
......@@ -75,7 +68,6 @@ class FieldsSettingsForm extends ConfigFormBase {
public function __construct(ConfigFactoryInterface $config_factory, PluginManagerInterface $plugin_manager, DiffBuilderManager $diff_builder_manager, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager) {
parent::__construct($config_factory);
$this->config = $this->config('diff.plugins');
$this->fieldTypePluginManager = $plugin_manager;
$this->diffBuilderManager = $diff_builder_manager;
$this->entityTypeManager = $entity_type_manager;
......@@ -106,10 +98,7 @@ class FieldsSettingsForm extends ConfigFormBase {
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [
'diff.plugins',
'diff.settings',
];
return ['diff.plugins'];
}
/**
......@@ -451,42 +440,52 @@ class FieldsSettingsForm extends ConfigFormBase {
$plugin_settings = $form_state->get('plugin_settings');
$fields = $form_values['fields'];
// Set the plugin type as hidden, for fields which have no plugin selected.
$config = $this->config('diff.plugins');
// Save the settings.
foreach ($fields as $field_key => $field_values) {
if ($field_values['plugin']['type'] == 'hidden') {
$this->config->set('fields.' . $field_key, ['type' => 'hidden']);
$config->set('fields.' . $field_key, ['type' => 'hidden', 'settings' => []]);
}
}
$this->config->save();
// Save the settings, for fields which have a plugin selected.
foreach ($fields as $field_key => $field_values) {
if ($field_values['plugin']['type'] != 'hidden') {
else {
// Initialize the plugin, if the type is unchanged then with the
// existing settings, otherwise let it fall back to the default
// settings.
$configuration = [];
if ($config->get('fields.' . $field_key . '.type') == $field_values['plugin']['type'] && $config->get('fields.' . $field_key . '.settings')) {
$configuration = $config->get('fields.' . $field_key . '.settings');
}
$plugin = $this->diffBuilderManager->createInstance($field_values['plugin']['type'], $configuration);
// Get plugin settings. They lie either directly in submitted form
// values (if the whole form was submitted while some plugin settings
// were being edited), or have been persisted in $form_state.
/** @var \Drupal\diff\FieldDiffBuilderInterface $plugin */
$plugin = $this->diffBuilderManager->createInstance($field_values['plugin']['type']);
$values = NULL;
// Form submitted without pressing update button on plugin settings form.
if (isset($field_values['settings_edit_form']['settings'])) {
$settings = $field_values['settings_edit_form']['settings'];
$values = $field_values['settings_edit_form']['settings'];
}
// Form submitted after settings were updated.
elseif (isset($plugin_settings[$field_key]['settings'])) {
$settings = $plugin_settings[$field_key]['settings'];
}
// If the settings are not set anywhere in the form state just save the
// default configuration for the current plugin.
else {
$settings = $plugin->defaultConfiguration();
$values = $plugin_settings[$field_key]['settings'];
}
// Build a FormState object and call the plugin submit handler.
$state = new FormState();
$state->setValues($settings);
$state->set('fields', $field_key);
if ($values) {
$state = new FormState();
$state->setValues($values);
$plugin->submitConfigurationForm($form, $state);
}
$plugin->submitConfigurationForm($form, $state);
$config->set('fields.' . $field_key, [
'type' => $field_values['plugin']['type'],
'settings' => $plugin->getConfiguration(),
]);
}
}
$config->save();
drupal_set_message($this->t('Your settings have been saved.'));
}
......
......@@ -49,8 +49,8 @@ class CoreFieldBuilder extends FieldDiffBuilderBase {
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, EntityTypeManagerInterface $entity_type_manager, DiffEntityParser $entity_parser, RendererInterface $renderer) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $config, $entity_type_manager, $entity_parser);
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, DiffEntityParser $entity_parser, RendererInterface $renderer) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $entity_parser);
$this->renderer = $renderer;
}
......@@ -62,7 +62,6 @@ class CoreFieldBuilder extends FieldDiffBuilderBase {
$configuration,
$plugin_id,
$plugin_definition,
$container->get('config.factory'),
$container->get('entity_type.manager'),
$container->get('diff.entity_parser'),
$container->get('renderer')
......
......@@ -37,7 +37,7 @@ class TextFieldBuilder extends FieldDiffBuilderBase {
// The format loaded successfully.
$label = $this->t('Format');
if ($format != NULL) {
$result[$field_key][] = $label . ": " . $format->name;
$result[$field_key][] = $label . ": " . $format->label();
}
else {
$result[$field_key][] = $label . ": " . $this->t('Missing format @format', array('@format' => $values[$field_key]));
......
......@@ -91,16 +91,60 @@ class DiffAdminFormsTest extends DiffTestBase {
*/
public function doTestConfigurableFieldsTab() {
$this->drupalGet('admin/config/content/diff/fields');
// Test changing type without changing settings.
$edit = [
'fields[node.body][plugin][type]' => 'text_summary_field_diff_builder',
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldByName('fields[node.body][plugin][type]', 'text_summary_field_diff_builder');
$edit = [
'fields[node.body][plugin][type]' => 'text_field_diff_builder',
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldByName('fields[node.body][plugin][type]', 'text_field_diff_builder');
$this->drupalPostAjaxForm(NULL, [], 'node.body_settings_edit');
$this->assertText('Plugin settings: Text');
$edit = [
'fields[node.body][settings_edit_form][settings][show_header]' => TRUE,
'fields[node.body][settings_edit_form][settings][compare_format]' => TRUE,
'fields[node.body][settings_edit_form][settings][compare_format]' => FALSE,
'fields[node.body][settings_edit_form][settings][markdown]' => 'filter_xss_all',
];
$this->drupalPostForm(NULL, $edit, t('Update'));
$this->drupalPostAjaxForm(NULL, $edit, 'node.body_plugin_settings_update');
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertText('Your settings have been saved.');
// Check the values were saved.
$this->drupalPostAjaxForm(NULL, [], 'node.body_settings_edit');
$this->assertFieldByName('fields[node.body][settings_edit_form][settings][markdown]', 'filter_xss_all');
// Edit another field.
$this->drupalPostAjaxForm(NULL, [], 'node.title_settings_edit');
$edit = [
'fields[node.title][settings_edit_form][settings][markdown]' => 'filter_xss_all',
];
$this->drupalPostAjaxForm(NULL, $edit, 'node.title_plugin_settings_update');
$this->drupalPostForm(NULL, [], t('Save'));
// Check both fields and their config values.
$this->drupalPostAjaxForm(NULL, [], 'node.body_settings_edit');
$this->assertFieldByName('fields[node.body][settings_edit_form][settings][markdown]', 'filter_xss_all');
$this->drupalPostAjaxForm(NULL, [], 'node.title_settings_edit');
$this->assertFieldByName('fields[node.title][settings_edit_form][settings][markdown]', 'filter_xss_all');
// Save field settings without changing anything and assert the config.
$this->drupalPostForm(NULL, [], t('Save'));
$this->drupalPostAjaxForm(NULL, [], 'node.body_settings_edit');
$this->assertFieldByName('fields[node.body][settings_edit_form][settings][markdown]', 'filter_xss_all');
$this->drupalPostAjaxForm(NULL, [], 'node.title_settings_edit');
$this->assertFieldByName('fields[node.title][settings_edit_form][settings][markdown]', 'filter_xss_all');
$edit = [
'fields[node.sticky][plugin][type]' => 'hidden',
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertFieldByName('fields[node.sticky][plugin][type]', 'hidden');
}
/**
......
......@@ -42,7 +42,11 @@ class DiffViewModeTest extends DiffTestBase {
$edit = [
'fields[body][region]' => 'hidden',
];
$this->drupalPostForm('admin/structure/types/manage/article/form-display', $edit, t('Save'));
$this->drupalPostForm('admin/structure/types/manage/article/display', $edit, t('Save'));
$edit = [
'fields[body][region]' => 'hidden',
];
$this->drupalPostForm('admin/structure/types/manage/article/display/teaser', $edit, t('Save'));
// Check the difference between the last two revisions.
$this->drupalGet('node/' . $node->id() . '/revisions');
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment