Problem/Motivation
The post-update views_data_export_post_update_remap_display_filesystem introduced in #3200974 renames the legacy store_in_public_file_directory option to export_filesystem, but it filters by exact plugin id:
if (($display['display_plugin'] ?? NULL) !== 'data_export') { continue; }
Subclass display plugins that inherit the same option are skipped. The most common case is data_export_excel from the views_data_export_excel module (its ExcelExport display extends this module's DataExport). Any view with such a display still carries the legacy store_in_public_file_directory key after the post-update has run, and Configuration Inspector reports it as "missing schema".
Steps to reproduce
- Have a site with
views_data_exportandviews_data_export_excel, that ranviews_data_export_post_update_remap_display_filesystemwhen it shipped. - Open any view with a
data_export_exceldisplay in Configuration Inspector (admin/config/development/configuration/inspect). - Observe a "missing schema" entry on
display.{id}.display_options.store_in_public_file_directory.
Proposed resolution
Add a follow-up post-update views_data_export_post_update_remap_subclass_display_filesystem that re-runs the same remap logic but matches on the presence of the legacy store_in_public_file_directory key rather than on a specific plugin id, so it covers data_export_excel and any other in-tree or out-of-tree subclass.
The original post-update is left alone. Sites that haven't yet run it get the standard behaviour; sites that already ran it pick up the missed subclass displays from the new follow-up.
Remaining tasks
- Review the MR.
- Ship.
Test coverage
No new test added. The change is a follow-up post-update only and is verified by Configuration Inspector returning no errors against affected views after running drush updb.
Issue fork views_data_export-3589219
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
mably commentedComment #4
mably commentedIf you don't want to wait for this to land in a release, three options for fixing existing sites manually.
Option A: one-shot script via devel/php
Replicates exactly what the proposed follow-up post-update does, scanning every view:
After running, export the active config (
drush cex -y) so the cleaned-up yml lands in version control. Otherwise the nextdrush cimre-introduces the legacy key from the on-disk file.Option B: edit the on-disk config yml directly
In each affected
views.view.{id}.ymlunderconfig/sync/, find the offending display'sdisplay_optionsblock and either:store_in_public_file_directory: falseline, orexport_filesystem: private(orpublic) to match what the original post-update would have written.Then run
drush cim -y. Reproducible across environments and shows up cleanly in git history.Option C: re-save the affected views in the UI
For each view, edit any display, click Save. The save round-trip drops keys not declared in the plugin's current option set, so the legacy key disappears. Quick fix for one or two views, painful at scale.
Comment #5
steven jones commentedSorry about this one!
Let's get it sorted and roll a new release...
Comment #6
mably commentedGreat news, thanks!
Comment #7
steven jones commentedI was going to tighten up the post update hook to check to see if the display plugin is actually a sub-class of the base VDE one. Is that worth it do you think?
Comment #8
mably commentedClaude suggests to keep the key-presence check:
Worth noting upfront: VDE doesn't currently expose a marker interface — the base class
Drupal\views_data_export\Plugin\views\display\DataExportextends core'sRestExportdirectly, and the only known subclass (views_data_export_excel'sExcelExport) just extends that concrete class. So a "subclass check" would have to beis_subclass_of($plugin, DataExport::class), which:drush updbmeans its orphaned config (which is exactly what we're cleaning up) gets skipped;If at some point you introduce a
DataExportDisplayInterface, aninstanceofagainst it would be the right gate going forward — but for this one-shot cleanup, those points all argue for the data-driven approach already in MR !99.The other thing:
store_in_public_file_directoryis a VDE-specific name, so the odds of an unrelated display plugin happening to have that exact key are basically zero — the practical false-positive risk is theoretical. The migration logic is already idempotent and same-semantics as the original post-update, so even in an unlikely collision the worst case is one extra config write that maps NULL to public, which matches core's default for that config anyway.If you want a belt-and-braces compromise, a
str_starts_with($display['display_plugin'], 'data_export')guard is cheap and string-only — no plugin manager calls, no class autoload — but I don't think even that's needed.Comment #9
mably commentedBut we are probably the only ones subclassing the VDE class for now with our Excel module.
So it should also probably be ok to use an instanceof here 😉
Comment #10
steven jones commentedThanks for the thoughts, I've re-worked the update hook, do you think that looks okay to you? It worked on my machine :D
Comment #11
mably commentedLooks ok to me.
Comment #13
steven jones commented