3633767 — Store view mode selections in a revisionable base field on the host entity

ERVMS previously kept per-item view mode selections in the key/value store, keyed by entity ID. Selections were therefore not revisioned (drafts, moderation, and reverts lost them), shared by every place a referenced entity was used (e.g. one Paragraphs Library item could not be "Media left" on one page and "Media right" on another), and persisted via static "pending data" caches applied in insert/update hooks. This moves storage to a revisionable, untranslatable ervms_view_modes base field on the entity that owns the reference field, so selections travel with the revision being saved, viewed, or reverted, and adds an upgrade path from key/value data plus a clean uninstall.

Change log:

  • Added ViewModeSelectionStorage base field support: ervms_view_modes map field (buildFieldDefinition(), ensureFieldStorage()), reads from the revision being rendered, setAllData() now sets the value on the entity object (caller saves), new mergeData(), prune(), pruneStoredData() and isSelectorField(), with a legacy key/value read/write fallback until updates have run
  • Added EntityBaseFieldHooks implementing hook_entity_base_field_info() keyed off the last-installed schema, so core still removes the storage when the module is uninstalled; registered it and the new services in entity_reference_view_mode_selector.services.yml
  • Updated EntityReferenceViewModeSelectorHooks: entity_presave now prunes stale selections (removed deltas, deleted fields, selector disabled) instead of applying pending data; added field_config_insert/update hooks to install the base field on demand when the selector is enabled on a field (wired via LegacyHook in the .module)
  • Rewrote ViewModeFormHandler: removed the pending-data caches and presave step; the form submit now runs first and copies selections straight onto the host entity and onto the paragraph objects in the Paragraphs widget state; added resolveWidgetEntity() and public extractFieldViewModes()
  • Added hook_update_10101() in entity_reference_view_mode_selector.install to install the field on all entity types using ERVMS (and ones holding only legacy data), and post_update_migrate_legacy_selections in .post_update.php, a batched migration using the new LegacySelectionMigrator service, which writes directly to the field tables (no entity saves, so no new revisions, moderation transitions or notifications) into the default and latest revisions, drops orphaned records, and keeps any skipped records and the read fallback
  • Added FormatterReverter service and hook_uninstall() implementations in the main module and ervms_paragraphs that swap the ERVMS formatters back to entity_reference_entity_view / entity_reference_revisions_entity_view (keeping settings, including Layout Builder field blocks) and clear legacy key/value data
  • EntityViewModeFormatter and ParagraphViewModeFormatter: fall back to the formatter's view mode when a selected view mode no longer exists
  • ervms_paragraphs_entity_embed: added .install that installs the field on the embedded_paragraphs entity type; removed the entity_insert/entity_update hooks and the pending-data logic in EmbeddedParagraphsFormHandler, which now reuses the main form handler to set selections on the wrapper and (nested) paragraphs before save, with the submit handler prepended to run before the form's own save handlers
  • Added kernel tests: ErvmsKernelTestBase, ViewModeSelectionStorageTest, LegacyMigrationTest and UninstallTest
  • README: documented the new storage model, the update/migration behavior, the revised data flow, the need to save after set_all_data(), and uninstall steps

Closes #3633767

Merge request reports

Loading
Loading