Skip to content
Snippets Groups Projects
Commit 6092145b authored by Krystian Brzoza's avatar Krystian Brzoza Committed by Alex Pott
Browse files

Issue #3479093 by krystianbrzoza, rcodina, alexpott, ghost of drupal past,...

Issue #3479093 by krystianbrzoza, rcodina, alexpott, ghost of drupal past, nicodh: Saving nodes without loading metatags form loses metatags customization
parent 43862a34
No related branches found
No related tags found
1 merge request!7fix: Keep customized metatags configuration based on the current entity field stored values
Pipeline #468225 passed
parameters: parameters:
ignoreErrors: ignoreErrors:
- -
message: "#^Call to an undefined method Drupal\\\\Tests\\\\WebAssert\\:\\:assertWaitOnAjaxRequest\\(\\)\\.$#" message: '#^Unsafe usage of new static\(\)\.$#'
identifier: new.static
count: 1
path: src/Plugin/Field/FieldWidget/AsyncMetatagFirehose.php
-
message: '#^Call to an undefined method Drupal\\Tests\\WebAssert\:\:assertWaitOnAjaxRequest\(\)\.$#'
identifier: method.notFound
count: 1 count: 1
path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php
- -
message: "#^Call to an undefined method Drupal\\\\Tests\\\\WebAssert\\:\\:waitForButton\\(\\)\\.$#" message: '#^Call to an undefined method Drupal\\Tests\\WebAssert\:\:waitForButton\(\)\.$#'
count: 2 identifier: method.notFound
count: 3
path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php
- -
message: "#^Call to an undefined method Drupal\\\\Tests\\\\WebAssert\\:\\:waitForElement\\(\\)\\.$#" message: '#^Call to an undefined method Drupal\\Tests\\WebAssert\:\:waitForElement\(\)\.$#'
count: 2 identifier: method.notFound
count: 4
path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php
- -
message: "#^Call to an undefined method Drupal\\\\Tests\\\\WebAssert\\:\\:waitForField\\(\\)\\.$#" message: '#^Call to an undefined method Drupal\\Tests\\WebAssert\:\:waitForField\(\)\.$#'
identifier: method.notFound
count: 2 count: 2
path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php
- -
message: "#^Call to an undefined method Drupal\\\\Tests\\\\WebAssert\\:\\:waitForLink\\(\\)\\.$#" message: '#^Call to an undefined method Drupal\\Tests\\WebAssert\:\:waitForLink\(\)\.$#'
count: 1 identifier: method.notFound
count: 2
path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php
- -
message: "#^Call to an undefined method Drupal\\\\Tests\\\\WebAssert\\:\\:waitForText\\(\\)\\.$#" message: '#^Call to an undefined method Drupal\\Tests\\WebAssert\:\:waitForText\(\)\.$#'
count: 3 identifier: method.notFound
count: 4
path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php path: tests/src/FunctionalJavascript/MetatagAsyncWidgetTest.php
...@@ -4,10 +4,18 @@ namespace Drupal\metatag_async_widget\Plugin\Field\FieldWidget; ...@@ -4,10 +4,18 @@ namespace Drupal\metatag_async_widget\Plugin\Field\FieldWidget;
use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\RevisionableInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element; use Drupal\Core\Render\Element;
use Drupal\metatag\MetatagManagerInterface;
use Drupal\metatag\MetatagTagPluginManager;
use Drupal\metatag\Plugin\Field\FieldWidget\MetatagFirehose; use Drupal\metatag\Plugin\Field\FieldWidget\MetatagFirehose;
use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* Asynchronous widget for the Metatag field. * Asynchronous widget for the Metatag field.
...@@ -23,6 +31,46 @@ use Drupal\metatag\Plugin\Field\FieldWidget\MetatagFirehose; ...@@ -23,6 +31,46 @@ use Drupal\metatag\Plugin\Field\FieldWidget\MetatagFirehose;
*/ */
class AsyncMetatagFirehose extends MetatagFirehose { class AsyncMetatagFirehose extends MetatagFirehose {
/**
* Instance of Entity Type Manager service.
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['third_party_settings'],
$container->get('metatag.manager'),
$container->get('plugin.manager.metatag.tag'),
$container->get('config.factory'),
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function __construct(
$plugin_id,
$plugin_definition,
FieldDefinitionInterface $field_definition,
array $settings,
array $third_party_settings,
MetatagManagerInterface $manager,
MetatagTagPluginManager $plugin_manager,
ConfigFactoryInterface $config_factory,
EntityTypeManagerInterface $entity_type_manager,
) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings, $manager, $plugin_manager, $config_factory);
$this->entityTypeManager = $entity_type_manager;
}
/** /**
* Ajax callback for the "Customize meta tags" button. * Ajax callback for the "Customize meta tags" button.
*/ */
...@@ -65,7 +113,13 @@ class AsyncMetatagFirehose extends MetatagFirehose { ...@@ -65,7 +113,13 @@ class AsyncMetatagFirehose extends MetatagFirehose {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state): array { public function formElement(
FieldItemListInterface $items,
$delta,
array $element,
array &$form,
FormStateInterface $form_state,
): array {
if ($form_state->get('metatag_async_widget_customize_meta_tags')) { if ($form_state->get('metatag_async_widget_customize_meta_tags')) {
$element += parent::formElement($items, $delta, $element, $form, $form_state); $element += parent::formElement($items, $delta, $element, $form, $form_state);
// Open the meta tags group upon selection. // Open the meta tags group upon selection.
...@@ -109,7 +163,104 @@ class AsyncMetatagFirehose extends MetatagFirehose { ...@@ -109,7 +163,104 @@ class AsyncMetatagFirehose extends MetatagFirehose {
} }
} }
// Add current entity node as hidden field for saving purposes.
$entity = $items->getEntity();
$element['metatag-async-widget-entity-new'] = [
'#type' => 'hidden',
'#name' => 'metatag-async-widget-entity-new',
'#value' => $entity->isNew() ? 1 : 0,
];
$element['metatag-async-widget-entity-id'] = [
'#type' => 'hidden',
'#name' => 'metatag-async-widget-entity-id',
'#value' => !$entity->isNew() ? $entity->id() : NULL,
];
$element['metatag-async-widget-entity-revision-id'] = [
'#type' => 'hidden',
'#name' => 'metatag-async-widget-entity-revision',
'#value' => !$entity->isNew() && $entity->getEntityType()->isRevisionable() && $entity instanceof RevisionableInterface ? $entity->getRevisionId() : NULL,
];
$element['metatag-async-widget-entity-language'] = [
'#type' => 'hidden',
'#name' => 'metatag-async-widget-entity-language',
'#value' => $entity->language()->getId(),
];
$element['metatag-async-widget-entity-type'] = [
'#type' => 'hidden',
'#name' => 'metatag-async-widget-entity-type',
'#value' => $entity->getEntityTypeId(),
];
return $element; return $element;
} }
/**
* Apply default entity values to the metatag field if no async edit was requested.
*/
public function massageFormValues(array $values, array $form, FormStateInterface $form_state): array {
$unchangedValues = array_filter($values, function ($value) {
return isset($value['metatag_async_widget_customize_meta_tags']) || !isset($value['basic']) || empty($value);
});
foreach ($unchangedValues as $key => &$value) {
$isNew = (bool) $value['metatag-async-widget-entity-new'];
$entityType = $value['metatag-async-widget-entity-type'];
$entityID = $value['metatag-async-widget-entity-id'];
$entityRevisionID = $value['metatag-async-widget-entity-revision-id'];
$entityLanguage = $value['metatag-async-widget-entity-language'];
unset(
$value['metatag-async-widget-entity-new'],
$value['metatag-async-widget-entity-id'],
$value['metatag-async-widget-entity-revision-id'],
$value['metatag-async-widget-entity-type'],
$value['metatag-async-widget-entity-language']
);
if ($isNew) {
continue;
}
try {
$storage = $this->entityTypeManager->getStorage($entityType);
}
catch (\Exception) {
continue;
}
if ($this->entityTypeManager->getDefinition($entityType)->isRevisionable()) {
/** @var \Drupal\Core\Entity\RevisionableStorageInterface $storage */
$entity = $storage->loadRevision($entityRevisionID);
}
else {
$entity = $storage->load($entityID);
}
if (!$entity instanceof ContentEntityInterface) {
continue;
}
// Check if currently handled entity is in a different language than the
// original entity.
if ($entity->language()->getId() !== $entityLanguage && $entity->hasTranslation($entityLanguage)) {
$entity = $entity->getTranslation($entityLanguage);
}
// Get current field value from the entity.
if ($originalValues = $entity->get($this->fieldDefinition->getName())->getValue()) {
$value = $originalValues[$key]['value'];
}
}
// The rest of the values that don't have the
// metatag_async_widget_customize_meta_tags value needs to be parsed by
// parent::messageFormValues.
$customizedValues = array_diff_key($values, $unchangedValues);
$customizedValues = parent::massageFormValues($customizedValues, $form, $form_state);
return array_merge($unchangedValues, $customizedValues);
}
} }
...@@ -175,6 +175,21 @@ class MetatagAsyncWidgetTest extends WebDriverTestBase { ...@@ -175,6 +175,21 @@ class MetatagAsyncWidgetTest extends WebDriverTestBase {
$assert->waitForButton('Customize meta tags')->click(); $assert->waitForButton('Customize meta tags')->click();
$assert->waitForText('Configure the meta tags below.'); $assert->waitForText('Configure the meta tags below.');
$assert->fieldValueEquals('field_meta_tags[0][basic][abstract]', $abstract); $assert->fieldValueEquals('field_meta_tags[0][basic][abstract]', $abstract);
// Test that saving the node without changing metatags does not lose the
// information.
$this->drupalGet('node/1/edit');
$assert->fieldNotExists('field_meta_tags[0][basic][abstract]');
$assert->waitForElement('xpath', $metatag_details_xpath)->click();
$page->pressButton('Save');
sleep(1);
$assert->waitForLink('Edit')->click();
$assert->fieldNotExists('field_meta_tags[0][basic][abstract]');
$assert->waitForElement('xpath', $metatag_details_xpath)->click();
$assert->waitForButton('Customize meta tags')->click();
$assert->waitForText('Configure the meta tags below.');
$assert->fieldValueEquals('field_meta_tags[0][basic][abstract]', $abstract);
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment