Skip to content
Snippets Groups Projects

Draft: #3502902 Create auto-save hash from entity to confirm changes present

Compare and
15 files
+ 511
158
Compare changes
  • Side-by-side
  • Inline
Files
15
@@ -4,21 +4,34 @@ namespace Drupal\experience_builder\AutoSave;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\TranslatableInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
use Drupal\experience_builder\AutoSaveData;
use Drupal\experience_builder\Entity\PageRegion;
use Drupal\experience_builder\Entity\XbHttpApiEligibleConfigEntityInterface;
use Drupal\experience_builder\InternalXbFieldNameResolver;
use Drupal\experience_builder\Plugin\Field\FieldType\ComponentTreeItem;
use Drupal\experience_builder\ServerClientConversionTrait;
/**
* Defines a class for storing and retrieving auto-save data.
*/
class AutoSaveManager {
use ServerClientConversionTrait;
public const CACHE_TAG = 'experience_builder__autosave';
public function __construct(
private readonly AutoSaveTempStoreFactory $tempStoreFactory,
private readonly CacheTagsInvalidatorInterface $cacheTagsInvalidator,
) {
}
private readonly EntityTypeManagerInterface $entityTypeManager,
private readonly ThemeManagerInterface $themeManager,
private readonly FormBuilderInterface $formBuilder,
) {}
protected function getTempStore(): AutoSaveTempStore {
// Store for 30 days.
@@ -28,8 +41,53 @@ class AutoSaveManager {
return $this->tempStoreFactory->get('experience_builder.auto_save', expire: $expire);
}
public function hash(EntityInterface $entity, ?array $data): string {
$this->setRegions();
// Generate a hash for the saved entity.
if ($data === NULL) {
if ($entity instanceof PageRegion) {
$tree = $entity->getComponentTree();
$model = [];
$full_layout = [$this->buildRegion($entity->id(), $tree, $model)];
assert(is_array($full_layout[0]['components']));
$data = [
'layout' => $full_layout[0]['components'],
'model' => $model,
];
}
elseif ($entity instanceof XbHttpApiEligibleConfigEntityInterface) {
$data = $entity->normalizeForClientSide()->values;
}
elseif ($entity instanceof FieldableEntityInterface) {
$field_name = InternalXbFieldNameResolver::getXbFieldName($entity);
$tree = $entity->get($field_name)->first();
assert(is_null($tree) || $tree instanceof ComponentTreeItem);
$model = [];
$data = [
'layout' => [$this->buildRegion('content', $tree, $model)],
'model' => $model,
'entity_form_fields' => $this->getEntityData($entity),
];
}
else {
throw new \InvalidArgumentException('Unsupported entity type: ' . $entity->getEntityTypeId());
}
}
return \hash('xxh64', \serialize($data));
}
public function save(EntityInterface $entity, array $data): void {
$key = $this->getAutoSaveKey($entity);
$data_hash = $this->hash($entity, $data);
if ($data_hash === $this->hash($entity, NULL)) {
// The data has not changed, so we don't need to save it.
if ($this->getTempStore()->get($key)) {
$this->getTempStore()->delete($key);
$this->cacheTagsInvalidator->invalidateTags([self::CACHE_TAG]);
}
return;
}
$auto_save_data = [
'entity_type' => $entity->getEntityTypeId(),
'entity_id' => $entity->id(),
@@ -96,4 +154,16 @@ class AutoSaveManager {
$this->getTempStore()->deleteAll();
}
protected function getFormBuilder(): FormBuilderInterface {
return $this->formBuilder;
}
protected function getThemeManager(): ThemeManagerInterface {
return $this->themeManager;
}
protected function getEntityTypeManager(): EntityTypeManagerInterface {
return $this->entityTypeManager;
}
}
Loading