Problem/Motivation
I have a site where if I upload a fillable PDF to my site, the PDF's fields are no longer fillable. If I uninstall this module, the fillable-ness of the PDF is maintained.
Steps to reproduce
- Add a PDF file via Content -> Media -> Add Media -> Document
- Attach a PDF that has fillable fields
- After the PDF file is attached to the Document, but before saving, click the PDF to view it
- The fillable fields are highlighted in light blue and can be typed into
- Save the document
- Reopen the document
- Click the PDF link to open it - the file is now flat and no fields can be typed into any more
- Uninstall PDF Metadata module
- Run all of the above steps again
- PDF is now still fillable after saving the Document
There are no errors showing in the system log.
I'll uninstall the module in the short term, but we would prefer to be able to use it.
Proposed resolution
I don't know enough about what's going on under the hood to propose a resolution. Thanks in advance to any who can offer a solution!
Issue fork pdf_metadata-3480679
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 #2
j-barnes commented@asigrist - Thanks for the breakdown. We are facing the same issues on some of our forms that leverage "Acrobat's Extended" version. Ghostscript actually regenerates the PDF file, but also flattens it -- which results fillable forms being in a printed state.
Originally, we leveraged ExifTool with a PHP wrapper. This allowed us to not have to regenerate the entire PDF, but rather only modify the metadata. At the time, the library was not being maintained (so we switched over to Ghostscript) -- but it looks like it is now so it might be a good opportunity make this module a bit more generic and allow multiple providers.
I think we can solve this but implementing the below:
Comment #3
asigrist commentedThanks for the very speedy reply and willingness to fix!
Comment #4
j-barnes commentedComment #5
j-barnes commentedUnassigning myself for now due to higher priority tickets, will revisit soon.
Comment #6
j-barnes commentedComment #9
johan den hollander commentedI worked on a MR that implements a selectable provider.
The GhostScript provider will be set as the default provider.
Exiftool can be choosen as well. It needs to be available on your server though, just like Ghostscript.
Claude Code was used to create the code. I tested the workings on my DDEV environment.
By the way I added ExifTool to DDEV via:
webimage_extra_packages: [libimage-exiftool-perl]
In the composer.json of my project I added:
"phpexiftool/exiftool": "dev-master",
This is only necessary for the moment I believe. When the code gets merged the dependency will be managed by the composer.json of the module.
This is the description of the change as summarized by Claude:
We've successfully implemented a pluggable provider architecture for PDF metadata
handling that solves the issue of preserving interactive form fields in PDF documents.
What Changed
The patch introduces a provider abstraction system that allows switching between
different PDF metadata writers:
Two Built-in Providers:
1. GhostscriptProvider (default, backward compatible)
- Traditional approach: regenerates entire PDF
- High compatibility with various PDF types
- Note: May flatten interactive form fields
2. ExiftoolProvider (NEW, recommended for forms)
- Modern approach: modifies metadata in-place
- Preserves interactive form fields and other PDF features
- Uses PHPExiftool wrapper for safe, OOP-based implementation
- Cleaner alternative to GhostScript for fillable PDFs
Implementation Details
New Components:
- PdfMetadataProviderInterface - Contract for metadata providers
- PdfMetadataProviderManager - Registers and manages providers
- GhostscriptProvider - Existing functionality, now pluggable
- ExiftoolProvider - New, wrapper-based implementation
Enhanced Features:
- Admin settings form with provider selection UI
- Availability indicators showing which tools are installed
- Detailed descriptions per provider (installation, behavior, use cases)
- Backward compatible: defaults to GhostScript
- Database update hook (8001) for seamless migration
Key Benefits
✅ Solves form preservation issue - Users can now choose ExifTool to keep interactive
forms intact
✅ Backward compatible - Existing sites continue using GhostScript by default
✅ Easy to extend - New providers can be added by implementing the interface
✅ Safe implementation - Uses PHPExiftool wrapper instead of direct exec() calls
✅ User control - Admin can select preferred provider based on their needs
Comment #10
johan den hollander commentedComment #11
j-barnes commented@johan_den_hollander - Awesome work! The provider architecture looks great and solves the fillable PDF issue.
One thing I noticed:
phpexiftool/exiftoolprovides the binary (usually atvendor/phpexiftool/exiftool/exiftool), but we need a way to make it reliably accessible for pdf_metadata.Thinking about a few approaches:
The challenge is that vendor folders might not be executable or could be read-only in production environments (like Acquia). Not sure what the best approach is - what do you think?
Really appreciate your work on this - our team will test once we nail down the approach!
Comment #12
j-barnes commentedComment #13
johan den hollander commentedI put some more effort into this today:
Adjusted binary detection priority to give developers more control:
The ExifTool binary detection now follows this priority order:
1. New custom configured path (admin override)
2. Composer vendor directory (project-specific version)
3. System PATH (system-wide installation)
4. Common system paths (fallback)
Rationale: Composer vendor path has higher priority than System PATH, allowing
developers to control the ExifTool version via composer.json. This is especially useful
during development and testing when a specific version is needed.
I tried using a bin dir in my project with a symbolic link to the exiftool binary in the vendor dirs but that doesn't work because the binary is looking for dependencies in the place it is called.
As a bonus I added a link from the drupal modules page to the pdf-metadata admin screen.
I tested with Exiftool via DDEV install, and exiftool via the php binary and both work well.
Comment #14
johan den hollander commentedComment #15
j-barnes commented@johan_den_hollander - This is excellent work! I tested the latest changes locally and everything is working great.
We're going to run this through our internal QA team on our staging environments to make sure everything holds up. Once they give the green light, I'll get this merged in.
Really appreciate all the work you put into this!
Comment #16
sunny-lee commentedThanks! This is great! It works as expected. Tested with a media entity and the form is still fillable. Also tried with a node that has a media attachment which still works. Turned on the pdf metadata module for one of the media entities it was not working for previously and that's working as well.
Comment #18
j-barnes commentedMerged! Thanks again for the contribution.
Comment #19
j-barnes commented