Found during the 2026-07-18 v1→v2 feature-parity audit (PDF/Templates domain) as a latent bug, not a parity gap. Verified with a failing test on branch chore/verify-pdf-list-stub-and-wkhtmltopdf-bug (commit 036559c): WkhtmltopdfDriverBugTest::it_generates_pdf_output_without_fatal_error fails with:
Error: Class "Modules\Core\Support\PDF\Drivers\Pdf" not found
at Modules/Core/Support/PDF/Drivers/wkhtmltopdf.php:36
36▕ $pdf = new Pdf(config('ip.pdfBinaryPath'));
Modules/Core/Support/PDF/Drivers/wkhtmltopdf.php instantiates an unqualified Pdf class that is never imported and does not exist anywhere in the codebase. composer.lock has no knplabs/knp-snappy or mikehaertl/php-shellcommand requirement (only stray conflict-constraint entries from an unrelated package, not actual installs) — the wkhtmltopdf/Snappy wrapper this driver expects was never added as a dependency. Selecting IP_PDF_DRIVER=wkhtmltopdf (config/ip.php:43) fatals on the very first PDF generation attempt.
A related dead-code note found in the same file: PDFFactory::getDrivers() (Modules/Core/Support/PDF/PDFFactory.php) iterates a $driverFiles array that is hard-coded to [] (with a commented-out Directory::listContents(...) call) — it always returns an empty array regardless of which driver classes actually exist on disk.
Specific
Either (a) add the missing dependency (knplabs/knp-snappy + a wkhtmltopdf/wkhtmltoimage binary, matching v1's approach) and fix the Pdf instantiation to new \Knp\Snappy\Pdf(...) (or the correct FQCN for whichever wrapper is chosen), or (b) remove the wkhtmltopdf driver entirely from Modules/Core/Support/PDF/Drivers/ and from config('ip.pdfDriver')'s valid values if it is not meant to be supported, so IP_PDF_DRIVER=wkhtmltopdf cannot be configured into a fatal at all. Separately, fix or remove the dead PDFFactory::getDrivers() method.
Measurable
- With the dependency fixed: setting
IP_PDF_DRIVER=wkhtmltopdf and generating a PDF succeeds and returns valid PDF bytes.
- With the driver removed:
IP_PDF_DRIVER=wkhtmltopdf is rejected at config/boot time (or the driver directory no longer lists it), not left to fatal deep inside PDF generation.
PDFFactory::getDrivers() either returns the real list of available driver classes or is removed if unused.
Achievable
Small, self-contained fix either way — no other code depends on this driver today (default is domPDF, PR #608 adds a Browsershot driver as the modern alternative).
Relevant
A driver that silently fatals when selected is worse than not having the option at all — this should be resolved before any documentation or settings UI advertises wkhtmltopdf as a valid IP_PDF_DRIVER value.
Time-Bound
Small fix; can land independently of any other PDF/Templates parity work.
Arrange
config(['ip.pdfDriver' => 'wkhtmltopdf']).
Act
PDFFactory::create()->getOutput('<html></html>').
Assert
Found during the 2026-07-18 v1→v2 feature-parity audit (PDF/Templates domain) as a latent bug, not a parity gap. Verified with a failing test on branch
chore/verify-pdf-list-stub-and-wkhtmltopdf-bug(commit 036559c):WkhtmltopdfDriverBugTest::it_generates_pdf_output_without_fatal_errorfails with:Modules/Core/Support/PDF/Drivers/wkhtmltopdf.phpinstantiates an unqualifiedPdfclass that is never imported and does not exist anywhere in the codebase.composer.lockhas noknplabs/knp-snappyormikehaertl/php-shellcommandrequirement (only strayconflict-constraint entries from an unrelated package, not actual installs) — the wkhtmltopdf/Snappy wrapper this driver expects was never added as a dependency. SelectingIP_PDF_DRIVER=wkhtmltopdf(config/ip.php:43) fatals on the very first PDF generation attempt.A related dead-code note found in the same file:
PDFFactory::getDrivers()(Modules/Core/Support/PDF/PDFFactory.php) iterates a$driverFilesarray that is hard-coded to[](with a commented-outDirectory::listContents(...)call) — it always returns an empty array regardless of which driver classes actually exist on disk.Specific
Either (a) add the missing dependency (
knplabs/knp-snappy+ a wkhtmltopdf/wkhtmltoimage binary, matching v1's approach) and fix thePdfinstantiation tonew \Knp\Snappy\Pdf(...)(or the correct FQCN for whichever wrapper is chosen), or (b) remove thewkhtmltopdfdriver entirely fromModules/Core/Support/PDF/Drivers/and fromconfig('ip.pdfDriver')'s valid values if it is not meant to be supported, soIP_PDF_DRIVER=wkhtmltopdfcannot be configured into a fatal at all. Separately, fix or remove the deadPDFFactory::getDrivers()method.Measurable
IP_PDF_DRIVER=wkhtmltopdfand generating a PDF succeeds and returns valid PDF bytes.IP_PDF_DRIVER=wkhtmltopdfis rejected at config/boot time (or the driver directory no longer lists it), not left to fatal deep inside PDF generation.PDFFactory::getDrivers()either returns the real list of available driver classes or is removed if unused.Achievable
Small, self-contained fix either way — no other code depends on this driver today (default is
domPDF, PR #608 adds a Browsershot driver as the modern alternative).Relevant
A driver that silently fatals when selected is worse than not having the option at all — this should be resolved before any documentation or settings UI advertises
wkhtmltopdfas a validIP_PDF_DRIVERvalue.Time-Bound
Small fix; can land independently of any other PDF/Templates parity work.
Arrange
config(['ip.pdfDriver' => 'wkhtmltopdf']).Act
PDFFactory::create()->getOutput('<html></html>').Assert
%PDFmagic header) without throwing.PDFFactory::getDrivers()no longer contains a permanently-empty, dead iteration.