The pdv_file element has two storage modes: a vault reference (link mode), and an uploaded local copy (the default, including vault picks materialized to a local file). Both were served through the custom pdv_webform.download controller, which streamed the bytes and gated them by the submission-view permission.
For the upload mode that is unnecessary: the file is an ordinary managed file in private://pdv-uploads with webform / webform_submission file usage, so webform's standard private-file download path already gates it (system.files route -> hook_file_download -> WebformManagedFileBase::accessFile, which checks view access to the owning submission). The only reason the standard path was not used is that PdvFile is a composite and so never advertised file-download access, leaving its files unservable by the standard route -> the custom controller streamed them instead.
Change
- PdvFile implements WebformElementFileDownloadAccessInterface, scoped to its own private://pdv-uploads directory, delegating to WebformManagedFileBase::accessFileDownload(). Upload-mode files are now gated and served exactly like any other webform submission upload.
- formatHtmlItem links upload-mode values to the standard managed-file download URL; only vault references keep using the pdv_webform.download route (their bytes are decrypted per viewer and have no local file).
- The controller and PdvFileValue::resolveFile() are now vault-only; the dead resolveBytes() and the unreachable upload branch are removed. The private://pdv-uploads literal is consolidated into PdvFile::UPLOAD_DIRECTORY.
Tests: upload-mode links to the standard file URL, the controller 404s an upload-source value, accessFileDownload defers for foreign URIs. Full pdv_webform suite green; phpcs and phpstan clean.
Issue fork pdv-3596253
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 #4
mably commented