Skip to content
Snippets Groups Projects

Only send necessary changes in request

6 files
+ 106
23
Compare changes
  • Side-by-side
  • Inline
Files
6
@@ -3,18 +3,25 @@
namespace Drupal\experience_builder\AutoSave;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\Config\Entity\ConfigEntityTypeInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\TranslatableInterface;
use Drupal\experience_builder\AutoSaveData;
use Drupal\experience_builder\Entity\XbHttpApiEligibleConfigEntityInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Defines a class for storing and retrieving auto-save data.
*/
class AutoSaveManager {
class AutoSaveManager implements EventSubscriberInterface {
public const CACHE_TAG = 'experience_builder__auto_save';
public function __construct(
private readonly EntityTypeManagerInterface $entityTypeManager,
private readonly AutoSaveTempStoreFactory $tempStoreFactory,
private readonly CacheTagsInvalidatorInterface $cacheTagsInvalidator,
) {
@@ -163,4 +170,79 @@ class AutoSaveManager {
}
}
public function onSave(ConfigCrudEvent $event): void {
// @todo SURELY there must be a better mechanism than this?!
$name_parts = explode('.', $event->getConfig()->getName(), 3);
if (count($name_parts) < 3) {
return;
}
[$module, $config_entity_type_id, $id] = $name_parts;
if ($module !== 'experience_builder') {
return;
}
$entity = $this->entityTypeManager->getStorage($config_entity_type_id)->load($id);
if (!$entity) {
return;
}
// Auto-saves can only occur for XB config entities modified by the XB UI.
if (!$entity instanceof XbHttpApiEligibleConfigEntityInterface) {
return;
}
$autoSaveData = $this->getAutoSaveData($entity);
if ($autoSaveData->isEmpty()) {
return;
}
$data = $autoSaveData->data;
assert($data !== NULL);
// Update the `label` and `status` keys of the config entity, if they've
// changed.
// @todo Consider auto-updating the auto-save entries for other config entity properties, but that will need very careful evaluation.
$auto_save_update_needed = FALSE;
assert($entity->getEntityType() instanceof ConfigEntityTypeInterface);
$properties_to_assess = $entity->getEntityType()->getPropertiesToExport();
assert(is_array($properties_to_assess));
foreach (['status', 'label'] as $entity_key) {
$key_name = $entity->getEntityType()->getKey($entity_key);
// Not every config entity type has both keys.
if ($key_name === FALSE) {
continue;
}
unset($properties_to_assess[$key_name]);
if ($event->isChanged($key_name) && array_key_exists($key_name, $data)) {
$data[$key_name] = $entity->get($key_name);
$auto_save_update_needed = TRUE;
}
}
// Ensure that no properties other than `status` and `label` were modified;
// otherwise the auto-save entry must be deleted.
$auto_save_must_be_deleted = FALSE;
foreach ($properties_to_assess as $property) {
if ($event->isChanged($property)) {
$auto_save_must_be_deleted = TRUE;
break;
}
}
if ($auto_save_must_be_deleted) {
$this->delete($entity);
return;
}
// Finally: the goal: to update rather than delete the auto-save entry when
// safe.
if ($auto_save_update_needed) {
$this->save($entity, $data);
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
$events[ConfigEvents::SAVE][] = ['onSave'];
return $events;
}
}
Loading