Detect and warn about deprecated v3 functionality ahead of 7.0 - #1695
Open
jakejackson1 wants to merge 1 commit into
Open
Detect and warn about deprecated v3 functionality ahead of 7.0#1695jakejackson1 wants to merge 1 commit into
jakejackson1 wants to merge 1 commit into
Conversation
|
Coverage report for commit: c0d2b87 Summary - Lines: 92.99% | Methods: 88.31% | Branches: 81.37%
🤖 Jest coverage report |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Coverage report for commit: 1452fa4 Summary - Lines: 83.30% | Methods: 89.40%
🤖 PHPUnit coverage report |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
jakejackson1
force-pushed
the
feat/system-report-detect-legacy-templates
branch
from
August 17, 2026 04:40
df77f1a to
5b42e04
Compare
jakejackson1
force-pushed
the
feat/system-report-detect-legacy-templates
branch
from
August 17, 2026 05:04
5b42e04 to
0f42c7c
Compare
jakejackson1
force-pushed
the
feat/system-report-detect-legacy-templates
branch
9 times, most recently
from
August 17, 2026 23:53
1452fa4 to
a1bfd3b
Compare
The v3 backwards compatibility layer is scheduled for removal in Gravity PDF 7.0, but there is currently no way to
know which sites still depend on it. Legacy (v3) templates render blank under Gravity Forms 3.0 with no fatal, no
warning and nothing in the debug log; the `gfpdfe_*` filters fire silently; and the deprecated methods call
`_doing_it_wrong()`, which does not trigger `deprecated_function_run` and so never reaches WordPress' deprecation
logging or Query Monitor.
This adds detection first, so the removal in 7.0 can be judged on real data rather than assumption.
New `GFPDF\Statics\Deprecation` collects three signals:
- **Legacy templates** — any template Helper_Templates classifies in the `Legacy` group (no `Group:` header), plus
the template of any PDF still set to `advanced_template => Yes`. Advanced Templating hands the template full
control of the PDF, which only a v3-era template does, so the setting identifies a legacy template even when the
file itself carries a v4 header. The PDFs are found via a single `LIKE` over `gf_form_meta`, so sites with many
forms don't load every one; forms in the trash are skipped, since they aren't in the user's form list to fix.
- **Legacy PDF URLs** — `Controller_PDF::process_legacy_pdf_endpoint()` records the hit in the
`gfpdf_legacy_endpoint_usage` option (autoload off), after `get_legacy_config()` has confirmed the form and PDF
exist so unauthenticated requests can't drive writes. Throttled to one write an hour and capped at 20 form IDs.
- **Deprecated filters** — looks the known `gfpdfe_*` hooks and v3-shaped `gfpdf_*` aliases up in `$wp_filter` by
name, checking for third-party listeners. The System Report additionally walks all of `$wp_filter` to catch
dynamic hooks like `gfpdfe_pdf_template_{form_id}`. Core's own `PDFRender::prepare_ids` registration is excluded
via a shared constant.
The template scan is cached in a day-long transient. The System Report always refreshes it.
- **System Report** gains a **Deprecated Features** section listing each detected item with an upgrade link. Any
section with no items is now dropped from the report, which is how this one stays hidden on a clean site. Legacy
templates moved here from Outdated Templates — the two conditions have different remedies.
- **Site Health** gains a test reporting the same detections, grouped by feature, with a link to the system
report. This is the surface that can't be permanently dismissed: it clears itself once the site stops using the
v3 layer and returns if it starts again, and it carries onto the Dashboard through the Site Health Status
widget. The Info tab gains a matching section, so the detections travel in the debug export users paste into a
support ticket; it's always present, reporting "None detected" on a clean site rather than leaving the reader
to guess whether the check ran. Both are gated on `gravityforms_view_settings`, so the detections (form titles,
PDF names, template paths) aren't exposed to administrators without Gravity Forms access.
- **Log warnings** on the legacy template render path, Advanced Templating processing, and any `gfpdfe_*` filter
that has a listener, so support can identify an affected site from a submitted log file. The filter warning is
written once per hook per request — otherwise `gfpdfe_pdf_template` would write a line for every PDF field.
The three display surfaces share the per-feature wording through `View_System_Report::get_deprecated_feature()`,
which returns unescaped text: the system report and the Site Health test escape it as they build their markup,
and the Info tab hands it to WordPress, which escapes it. Escaping in the builder instead would have
double-encoded anything containing an apostrophe, such as a form title.
Two `Helper_Notices` fixes came out of prototyping an admin notice for this, which was dropped in favour of the
two Site Health surfaces. Both apply to the pre-existing `view_class` route key, which any add-on can already
use: a caller-supplied `notice-*` class now replaces the default `updated` state rather than being appended to it
(`div.updated` out-specifies `.notice-warning`, so an appended warning still rendered green), and queued notices
are stored as message/class pairs rather than keyed by their class, which silently dropped a second notice
sharing the same one. `Controller_Actions::route_notices()` also returns early on the admin pages where
`Helper_Notices` discards the notice anyway, so route conditions no longer run on every admin request.
- `_doing_it_wrong()` becomes `_deprecated_function()` / `_deprecated_argument()` across the Tier B/C/E surface, so
these now fire `deprecated_function_run` and land in WordPress' deprecation log and Query Monitor. Bespoke prose
messages collapse into the `$replacement` argument.
- The ~20 silent stubs deprecated in 6.0-6.12 (`Model_Settings` font methods, `Model_Install` uninstall proxies,
`Helper_Notices`, the `pdf.php` canonical-release notices) now emit a notice instead of returning quietly.
- The v3 shim classes in `src/deprecated.php` warn from their implemented methods, not just the `__call` fallback —
including the `mPDF` shim constructor, so a v3 template calling `new mPDF()` is no longer silent. The `__call` /
`__callStatic` fallbacks now name `static::class . '::' . $name` rather than the bare method.
- The last uncovered Tier E items warn too: `View_PDF::display_page_name()`, `View_Settings::tabs()`, and the
`$args['content']` view fallback — warned once from `Helper_Abstract_View::load()`, which already knows the view
name, rather than from each of the six templates that read it. `Helper_Misc::flatten_array()` and
`Helper_Abstract_Addon::plugin_updater()` stay on `_doing_it_wrong()` — they report misuse, not deprecation.
- The `gfpdfe_*` filters route through `Deprecation::apply_filters()`, a thin wrapper over
`apply_filters_deprecated()` that shares the hook -> replacement map with the scanner. It early-returns when no
listener is attached, so the PDF render path pays nothing on sites that have already moved on.
- New `Test_Deprecation` covers the static directly: endpoint recorder throttling and form cap, the listener scan
ignoring core's own `gfpdfe_pre_load_template` registration while catching dynamic hooks, and signal caching.
- New `Test_Controller_System_Report` coverage for each of the three signals, for Advanced Templating landing in
the legacy template row rather than one of its own, and for the registration, capability gate and reported
detections of both Site Health surfaces.
- `setExpectedIncorrectUsage()` -> `setExpectedDeprecated()` wherever the primitive changed; tests that reach a
deprecated path incidentally now declare it.
- New Playwright coverage with Chromatic snapshots of all three new screens: the system report section, the Site
Health test expanded, and the Site Health dashboard widget carrying the counts. The recorded legacy URL is
pinned to a fixed date so the snapshots don't churn daily. Signals are seeded through two options and a PDF
created over REST, then cleared afterwards, so the rest of the suite runs against a site without them.
- Integration suite: 1593 tests, 0 failures, 46 skipped. PHPCS and PHP compatibility clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jakejackson1
force-pushed
the
feat/system-report-detect-legacy-templates
branch
from
August 18, 2026 01:04
a1bfd3b to
c0d2b87
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The v3 backwards compatibility layer is scheduled for removal in Gravity PDF 7.0 (see the audit in
.claude/plans/2026-08-17-7.0-deprecated-code-removal.md), but there is currently no way to know which sites still depend on it:RGFormsclass that the v3 template boilerplate guards on, so those templatesreturnbefore emitting anything. The PDF still generates, it's just empty. No fatal, no warning, nothing in the debug log.gfpdfe_*filters fire silently, so we have no idea whether anyone still listens to them._doing_it_wrong(), which does not triggerdeprecated_function_run, so they never reach WordPress' deprecation logging or Query Monitor.This PR implements the detection and early-warning work (§3 of the plan) so the 7.0 removal can be judged on real data.
Detection
New
GFPDF\Statics\Deprecationcollects four signals:Helper_Templatesclassifies in theLegacygroup (i.e. noGroup:header — core templates declareGroup: Core, so they're never flagged).Controller_PDF::process_legacy_pdf_endpoint()records the hit in thegfpdf_legacy_endpoint_usageoption (autoload off). Recorded afterget_legacy_config()confirms the form and PDF exist, so an unauthenticated?gf_pdf=…&fid=Ncan't drive option writes. Throttled to one write an hour and capped at 20 form IDs.gfpdfe_business_plusclass, plus any PDF still set toadvanced_template => Yes. Found via a singleLIKEovergf_form_metaso sites with a lot of forms don't load every one.$wp_filterfor third-party listeners on thegfpdfe_*hooks and the v3-shapedgfpdf_*aliases (gfpdf_orientation,gfpdf_privilages, …). Scanning rather than checking a fixed list picks up dynamic hooks likegfpdfe_pdf_template_{form_id}. Core's ownPDFRender::prepare_idsregistration is excluded via a shared constant.The filesystem and database scans are cached in a day-long transient and memoized per request; the free checks are always current. The System Report always refreshes.
Surfacing
System Report gains a Deprecated Features section, listing each detected item with a "Removed in Gravity PDF 7.0" warning and an upgrade link. The whole section is dropped when nothing is detected.
Legacy templates moved here out of Outdated Templates, where the first pass of this branch put them — the two conditions have entirely different remedies and reading as one run-on warning wasn't helping anyone.
Admin notice — a dismissible,
gravityforms_view_settings-gated notice via the existinggfpdf_one_time_action_routessystem, shown only when a signal fires. It names what was detected and links through to the system report. No blanket "7.0 is coming" notice: that just trains people to dismiss without reading.Log warnings on the legacy template render path and Advanced Templating processing, so support can identify an affected site from a submitted log file without a back-and-forth.
Real deprecation notices
_doing_it_wrong()→_deprecated_function()/_deprecated_argument()across the legacy-endpoint, v3-template and stale-stub surface. These now firedeprecated_function_runand land in WordPress' deprecation log and Query Monitor. The bespoke prose messages collapse into the$replacementargument.Model_Settingsfont methods,Model_Installuninstall proxies,Helper_Notices, thepdf.phpcanonical-release notices) now emit a notice instead of returning quietly. None of them are hooked, so nothing fires on a normal request.src/deprecated.phpwarn from their implemented methods, not just the__callfallback —PDF_Common::get_ids()and friends previously warned about nothing.GFPDF_Core::setup_constants()andPDFRender::prepare_ids()are deliberately excluded: core calls those itself.gfpdfe_*filters route throughDeprecation::apply_filters(), a thin wrapper overapply_filters_deprecated()that shares the hook → replacement map with the scanner. It early-returns when nothing is listening, so the PDF render path (~16 call sites) pays nothing on sites that have already moved on.Notes
gfpdfe_signature_widthalready has a v4 replacement —gfpdf_signature_widthis fired immediately after it inField_Signature.php. The plan lists creating one as an open question; it isn't needed.Testing
Test_Controller_System_Reportcoverage for each of the four signals, plus one asserting the section is absent by default.setExpectedIncorrectUsage()→setExpectedDeprecated()wherever the primitive changed; tests that reach a deprecated path incidentally (Test_Form_Data,Test_Gravity_Forms) now declare it.developmentunder GF 3.0.2 (the knownGFCommon::get_lead_field_displaydeprecation and the repeaterempty_deepissue, fixed on the hot-patch branches but not here). Multisite: 13 failures, same set. No regressions.Follow-ups (not in this PR)
https://docs.gravitypdf.com/developers/upgrade-legacy-template/exists before release.🤖 Generated with Claude Code