Skip to content

Detect and warn about deprecated v3 functionality ahead of 7.0 - #1695

Open
jakejackson1 wants to merge 1 commit into
developmentfrom
feat/system-report-detect-legacy-templates
Open

Detect and warn about deprecated v3 functionality ahead of 7.0#1695
jakejackson1 wants to merge 1 commit into
developmentfrom
feat/system-report-detect-legacy-templates

Conversation

@jakejackson1

@jakejackson1 jakejackson1 commented Aug 14, 2026

Copy link
Copy Markdown
Member

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:

  • Legacy (v3) templates render blank under Gravity Forms 3.0 — GF 3.0 removed the RGForms class that the v3 template boilerplate guards on, so those templates return before emitting anything. The PDF still generates, it's just empty. No fatal, no warning, nothing in the debug log.
  • The gfpdfe_* filters fire silently, so we have no idea whether anyone still listens to them.
  • The deprecated methods call _doing_it_wrong(), which does not trigger deprecated_function_run, so they never reach WordPress' deprecation logging or Query Monitor.
  • ~20 methods deprecated between 6.0 and 6.12 are empty stubs or thin proxies that emit nothing at all.

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\Deprecation collects four signals:

Signal How
Legacy templates Any template Helper_Templates classifies in the Legacy group (i.e. no Group: header — core templates declare Group: Core, so they're never flagged).
Legacy PDF URLs Controller_PDF::process_legacy_pdf_endpoint() records the hit in the gfpdf_legacy_endpoint_usage option (autoload off). Recorded after get_legacy_config() confirms the form and PDF exist, so an unauthenticated ?gf_pdf=…&fid=N can't drive option writes. Throttled to one write an hour and capped at 20 form IDs.
Advanced Templating The gfpdfe_business_plus class, plus any PDF still set to advanced_template => Yes. Found via a single LIKE over gf_form_meta so sites with a lot of forms don't load every one.
Deprecated filters Scans $wp_filter for third-party listeners on the gfpdfe_* hooks and the v3-shaped gfpdf_* aliases (gfpdf_orientation, gfpdf_privilages, …). Scanning rather than checking a fixed list picks up dynamic hooks like gfpdfe_pdf_template_{form_id}. Core's own PDFRender::prepare_ids registration 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
/wp-content/uploads/PDF_EXTENDED_TEMPLATES/cms.php is a legacy template and is no longer supported ✘
⚠ Removed in Gravity PDF 7.0. Learn how to upgrade legacy templates

Legacy PDF URLs
Legacy PDF URLs were last requested on 12 August 2026 for form(s) 1, 5 ✘
⚠ Removed in Gravity PDF 7.0. Replace these links with the [gravitypdf] shortcode or PDF merge tags

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 existing gfpdf_one_time_action_routes system, 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 fire deprecated_function_run and land in WordPress' deprecation log and Query Monitor. The bespoke prose messages collapse into the $replacement argument.
  • The ~20 silent stubs (Model_Settings font methods, Model_Install uninstall proxies, Helper_Notices, the pdf.php canonical-release notices) now emit a notice instead of returning quietly. None of them are hooked, so nothing fires on a normal request.
  • The v3 shim classes in src/deprecated.php warn from their implemented methods, not just the __call fallback — PDF_Common::get_ids() and friends previously warned about nothing. GFPDF_Core::setup_constants() and PDFRender::prepare_ids() are deliberately excluded: core calls those itself.
  • 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 nothing is listening, so the PDF render path (~16 call sites) pays nothing on sites that have already moved on.

Notes

  • gfpdfe_signature_width already has a v4 replacementgfpdf_signature_width is fired immediately after it in Field_Signature.php. The plan lists creating one as an open question; it isn't needed.
  • The notice's dismissal is permanent (inherited from the existing route system), so a site that dismisses it and later adds a legacy template won't be warned again. The system report still reports it.

Testing

  • New Test_Controller_System_Report coverage 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.
  • Integration suite: 1563 tests, 14 failures — a strict subset of the pre-existing failures on development under GF 3.0.2 (the known GFCommon::get_lead_field_display deprecation and the repeater empty_deep issue, fixed on the hot-patch branches but not here). Multisite: 13 failures, same set. No regressions.
  • PHPCS and PHP compatibility clean.

Follow-ups (not in this PR)

  • Confirm https://docs.gravitypdf.com/developers/upgrade-legacy-template/ exists before release.
  • Changelog entry — there's no 6.17.0 section yet, and this repo writes those at release time.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown

Coverage report for commit: c0d2b87
File: ./tmp/jest-coverage/clover.xml

Cover ┌─────────────────────────┐ Freq.
   0% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  10% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  20% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  30% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  40% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  50% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  60% │ ░░░░░░░░░░░░░░░░░░░░░░░ │  0.0%
  70% │ █░░░░░░░░░░░░░░░░░░░░░░ │  1.6%
  80% │ ███░░░░░░░░░░░░░░░░░░░░ │  8.1%
  90% │ ███████░░░░░░░░░░░░░░░░ │ 21.0%
 100% │ ███████████████████████ │ 69.4%
      └─────────────────────────┘
 *Legend:* █ = Current Distribution 
Summary - Lines: 92.99% | Methods: 88.31% | Branches: 81.37%
FilesLinesMethodsBranches
src/assets/js/react/actions
   coreFonts.js100.00%100.00%100.00%
   fontManager.js100.00%100.00%100.00%
   templates.js100.00%100.00%100.00%
src/assets/js/react/components/Alert
   Alert.js100.00%100.00%100.00%
src/assets/js/react/components/CoreFonts
   CoreFontContainer.js100.00%100.00%91.43%
   CoreFontCounter.js100.00%100.00%100.00%
   CoreFontListResults.js100.00%100.00%85.71%
   CoreFontListSpacer.js100.00%100.00%100.00%
src/assets/js/react/components
   CustomHashRouter.js100.00%100.00%100.00%
   Empty.js100.00%100.00%100.00%
   ShowMessage.js79.31%80.00%64.29%
   Spinner.js100.00%100.00%100.00%
src/assets/js/react/components/FontManager
   AddFont.js100.00%100.00%100.00%
   AddUpdateFontFooter.js85.37%50.00%88.89%
   AdvancedButton.js100.00%100.00%100.00%
   FontList.js100.00%50.00%65.22%
   FontListAlertMessage.js100.00%100.00%100.00%
   FontListHeader.js100.00%100.00%100.00%
   FontListIcon.js100.00%100.00%100.00%
   FontListItems.js85.39%64.00%68.66%
   FontListSkeleton.js100.00%100.00%100.00%
   FontManager.js77.78%57.14%50.00%
   FontManagerBody.js94.20%96.43%90.29%
   FontManagerHeader.js100.00%100.00%100.00%
   FontVariant.js90.00%60.00%70.00%
   FontVariantLabel.js100.00%100.00%100.00%
   InitialAddUpdateState.js100.00%100.00%100.00%
   SearchBox.js90.00%66.67%69.23%
   TemplateTooltip.js100.00%75.00%100.00%
   UpdateFont.js75.00%50.00%75.00%
src/assets/js/react/components/Modal
   CloseDialog.js93.33%66.67%70.59%
src/assets/js/react/components/Template
   TemplateActivateButton.js100.00%100.00%100.00%
   TemplateButton.js85.71%66.67%100.00%
   TemplateContainer.js71.43%66.67%25.00%
   TemplateDeleteButton.js100.00%100.00%70.00%
   TemplateFooterActions.js100.00%100.00%100.00%
   TemplateHeaderNavigation.js82.35%85.71%70.00%
   TemplateHeaderTitle.js100.00%100.00%100.00%
   TemplateList.js100.00%100.00%60.00%
   TemplateListItem.js100.00%100.00%92.86%
   TemplateListItemComponents.js100.00%100.00%100.00%
   TemplateScreenshot.js100.00%100.00%100.00%
   TemplateScreenshots.js100.00%100.00%50.00%
   TemplateSearch.js93.75%88.89%50.00%
   TemplateSingle.js100.00%100.00%100.00%
   TemplateSingleComponents.js100.00%100.00%75.00%
   TemplateUploader.js98.04%100.00%86.67%
src/assets/js/react/reducers
   coreFontReducer.js95.65%100.00%88.00%
   fontManagerReducer.js87.21%75.00%75.00%
   index.js100.00%100.00%100.00%
   templateReducer.js100.00%100.00%100.00%
src/assets/js/react/sagas
   coreFonts.js91.67%100.00%75.00%
   fontManager.js86.96%90.00%83.33%
   index.js100.00%100.00%100.00%
   templates.js83.33%100.00%100.00%
src/assets/js/react/selectors
   getTemplates.js91.11%100.00%83.33%
src/assets/js/react/utilities/FontManager
   adjustFontListHeight.js100.00%100.00%100.00%
   associatedFontManagerSelectBox.js94.44%100.00%66.67%
   fontManagerReducer.js100.00%100.00%100.00%
   getTabLocation.js100.00%100.00%100.00%
   toggleUpdateFont.js100.00%100.00%100.00%
src/assets/js/react/utilities
   withRouterHooks.js100.00%100.00%100.00%

🤖 Jest coverage report

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown

Coverage report for commit: 1452fa4
File: tmp/coverage/report-xml/merged.xml

Cover ┌─────────────────────────┐ Freq.
   0% │ ████████░░░░░░░░░░░░░░░ │ 11.0%
  10% │ █░░░░░░░░░░░░░░░░░░░░░░ │  1.0%
  20% │ █░░░░░░░░░░░░░░░░░░░░░░ │  0.5%
  30% │ █░░░░░░░░░░░░░░░░░░░░░░ │  1.0%
  40% │ █░░░░░░░░░░░░░░░░░░░░░░ │  0.5%
  50% │ ███████░░░░░░░░░░░░░░░░ │  8.6%
  60% │ ██░░░░░░░░░░░░░░░░░░░░░ │  1.4%
  70% │ █████░░░░░░░░░░░░░░░░░░ │  6.2%
  80% │ ███████████████░░░░░░░░ │ 19.6%
  90% │ ███████████████████████ │ 32.1%
 100% │ ██████████████░░░░░░░░░ │ 18.2%
      └─────────────────────────┘
 *Legend:* █ = Current Distribution 
Summary - Lines: 83.30% | Methods: 89.40%
FilesLinesMethodsBranches
/var/www/html/wp-content/plugins/gravity-pdf
   api.php96.55%100.00%100.00%
   gravity-pdf-updater.php53.97%100.00%100.00%
   pdf.php58.77%72.22%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Controller
   Controller_Actions.php100.00%100.00%100.00%
   Controller_Activation.php95.45%100.00%100.00%
   Controller_Custom_Fonts.php88.52%100.00%100.00%
   Controller_Debug.php100.00%100.00%100.00%
   Controller_Export_Entries.php96.67%100.00%100.00%
   Controller_Form_Settings.php86.05%90.00%100.00%
   Controller_Install.php100.00%100.00%100.00%
   Controller_Mergetags.php100.00%100.00%100.00%
   Controller_PDF.php82.14%100.00%100.00%
   Controller_Pdf_Queue.php83.72%77.78%100.00%
   Controller_Save_Core_Fonts.php66.67%100.00%100.00%
   Controller_Settings.php86.05%100.00%100.00%
   Controller_Shortcodes.php100.00%100.00%100.00%
   Controller_System_Report.php100.00%100.00%100.00%
   Controller_Templates.php100.00%100.00%100.00%
   Controller_Uninstaller.php83.33%77.78%100.00%
   Controller_Upgrade_Routines.php93.65%100.00%100.00%
   Controller_Webhooks.php100.00%100.00%100.00%
   Controller_Zapier.php100.00%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Exceptions
   GravityPdfDatabaseUpdateException.php50.00%100.00%100.00%
   GravityPdfDomainException.php50.00%100.00%100.00%
   GravityPdfException.php50.00%100.00%100.00%
   GravityPdfFontNotFoundException.php50.00%100.00%100.00%
   GravityPdfIdException.php50.00%100.00%100.00%
   GravityPdfModelNotUpdatedException.php50.00%100.00%100.00%
   GravityPdfRuntimeException.php50.00%100.00%100.00%
   GravityPdfShortcodeEntryIdException.php50.00%100.00%100.00%
   GravityPdfShortcodePdfConditionalLogicFailedException.php50.00%100.00%100.00%
   GravityPdfShortcodePdfConfigNotFoundException.php50.00%100.00%100.00%
   GravityPdfShortcodePdfInactiveException.php50.00%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Helper/Fields
   Field_Address.php92.16%100.00%100.00%
   Field_Chainedselect.php66.67%75.00%100.00%
   Field_Checkbox.php94.34%100.00%100.00%
   Field_Consent.php89.47%100.00%100.00%
   Field_Coupon.php--100.00%
   Field_Creditcard.php83.33%100.00%100.00%
   Field_Date.php83.33%100.00%100.00%
   Field_Default.php83.33%100.00%100.00%
   Field_Discount.php44.00%75.00%100.00%
   Field_Email.php83.33%100.00%100.00%
   Field_Fg_Ls_Consent.php92.86%100.00%100.00%
   Field_Fg_Ls_Signature.php73.08%66.67%100.00%
   Field_Fileupload.php94.23%100.00%100.00%
   Field_Form.php89.09%100.00%100.00%
   Field_Hidden.php81.82%100.00%100.00%
   Field_Html.php89.47%100.00%100.00%
   Field_Image_Choice.php86.67%100.00%100.00%
   Field_Likert.php97.22%100.00%100.00%
   Field_List.php92.41%100.00%100.00%
   Field_Multi_Choice.php50.00%100.00%100.00%
   Field_Multiselect.php92.59%100.00%100.00%
   Field_Name.php84.62%100.00%100.00%
   Field_Number.php83.33%100.00%100.00%
   Field_Option.php57.69%50.00%100.00%
   Field_Page.php83.33%100.00%100.00%
   Field_Phone.php94.55%100.00%100.00%
   Field_Poll.php93.75%100.00%100.00%
   Field_Post_Category.php85.00%100.00%100.00%
   Field_Post_Content.php82.35%100.00%100.00%
   Field_Post_Custom_Field.php50.00%100.00%100.00%
   Field_Post_Excerpt.php81.82%100.00%100.00%
   Field_Post_Image.php94.00%100.00%100.00%
   Field_Post_Tags.php90.91%100.00%100.00%
   Field_Post_Title.php81.82%100.00%100.00%
   Field_Product.php88.46%100.00%100.00%
   Field_Products.php85.41%100.00%100.00%
   Field_Quantity.php84.62%100.00%100.00%
   Field_Quiz.php89.74%100.00%100.00%
   Field_Radio.php95.35%100.00%100.00%
   Field_Rank.php95.24%100.00%100.00%
   Field_Rating.php95.24%100.00%100.00%
   Field_Repeater.php97.37%100.00%100.00%
   Field_Section.php90.74%100.00%100.00%
   Field_Select.php94.12%100.00%100.00%
   Field_Shipping.php75.00%66.67%100.00%
   Field_Signature.php67.39%100.00%100.00%
   Field_Slim.php82.35%100.00%100.00%
   Field_Slim_Post.php91.30%100.00%100.00%
   Field_Subtotal.php65.38%75.00%100.00%
   Field_Survey.php95.00%100.00%100.00%
   Field_Tax.php32.00%50.00%100.00%
   Field_Text.php81.82%100.00%100.00%
   Field_Textarea.php90.63%100.00%100.00%
   Field_Time.php81.82%100.00%100.00%
   Field_Tos.php92.59%100.00%100.00%
   Field_Total.php68.00%66.67%100.00%
   Field_V3_List.php92.86%100.00%100.00%
   Field_V3_Products.php73.68%100.00%100.00%
   Field_V3_Section.php77.78%100.00%100.00%
   Field_Website.php85.71%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Helper/Fonts
   FlushCache.php80.00%100.00%100.00%
   LocalFile.php90.00%100.00%100.00%
   LocalFilesystem.php66.67%100.00%100.00%
   SupportsOtl.php88.89%100.00%100.00%
   TtfFontValidation.php72.73%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Helper
   Helper_Abstract_Addon.php93.33%100.00%100.00%
   Helper_Abstract_Config_Settings.php75.00%100.00%100.00%
   Helper_Abstract_Controller.php-100.00%100.00%
   Helper_Abstract_Field_Products.php89.47%66.67%100.00%
   Helper_Abstract_Fields.php93.59%93.75%100.00%
   Helper_Abstract_Fields_Input_Type.php84.00%100.00%100.00%
   Helper_Abstract_Form.php--100.00%
   Helper_Abstract_Model.php100.00%100.00%100.00%
   Helper_Abstract_Options.php75.51%78.57%100.00%
   Helper_Abstract_Pdf_Shortcode.php89.52%91.67%100.00%
   Helper_Abstract_View.php92.31%100.00%100.00%
   Helper_Data.php96.57%100.00%100.00%
   Helper_Field_Container.php92.31%100.00%100.00%
   Helper_Field_Container_Gf25.php82.22%100.00%100.00%
   Helper_Field_Container_Void.php16.67%-100.00%
   Helper_Form.php70.97%64.29%100.00%
   Helper_Interface_Actions.php-100.00%100.00%
   Helper_Interface_Config.php50.00%100.00%100.00%
   Helper_Interface_Config_Settings.php50.00%100.00%100.00%
   Helper_Interface_Extension_Settings.php-100.00%100.00%
   Helper_Interface_Extension_Uninstaller.php-100.00%100.00%
   Helper_Interface_Field_Pdf_Config.php50.00%100.00%100.00%
   Helper_Interface_Filters.php-100.00%100.00%
   Helper_Interface_Setup_TearDown.php-100.00%100.00%
   Helper_Interface_Url_Signer.php-100.00%100.00%
   Helper_Logger.php-100.00%100.00%
   Helper_Misc.php73.56%93.94%100.00%
   Helper_Mpdf.php50.00%100.00%100.00%
   Helper_Notices.php79.69%73.33%100.00%
   Helper_Options_Fields.php96.87%100.00%100.00%
   Helper_PDF.php89.69%94.29%100.00%
   Helper_PDF_List_Table.php84.50%92.31%100.00%
   Helper_Pdf_Queue.php84.31%100.00%100.00%
   Helper_QueryPath.php80.00%100.00%100.00%
   Helper_Sha256_Url_Signer.php87.50%100.00%100.00%
   Helper_Singleton.php90.00%100.00%100.00%
   Helper_Templates.php96.44%100.00%100.00%
   Helper_Trait_Logger.php--100.00%
   Helper_Url_Signer.php82.86%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Helper/Licensing
   EDD_SL_Plugin_Updater.php94.74%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Helper/Log
   Logger.php86.89%100.00%100.00%
   Redact_Processor.php96.15%100.00%100.00%
/var/www/html/wp-content/plugins/gravity-pdf/src/Helper/Mpdf
   Cache.php66.67%100.00%100.00%
   Mpdf.php92.31%100.00%100.00%
Table truncated to fit comment

🤖 PHPUnit coverage report

@jakejackson1
jakejackson1 force-pushed the feat/system-report-detect-legacy-templates branch from df77f1a to 5b42e04 Compare August 17, 2026 04:40
@jakejackson1 jakejackson1 changed the title Detect legacy templates in the Outdated Templates system status section Detect and warn about deprecated v3 functionality ahead of 7.0 Aug 17, 2026
@jakejackson1
jakejackson1 force-pushed the feat/system-report-detect-legacy-templates branch from 5b42e04 to 0f42c7c Compare August 17, 2026 05:04
@jakejackson1
jakejackson1 force-pushed the feat/system-report-detect-legacy-templates branch 9 times, most recently from 1452fa4 to a1bfd3b Compare August 17, 2026 23:53
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
jakejackson1 force-pushed the feat/system-report-detect-legacy-templates branch from a1bfd3b to c0d2b87 Compare August 18, 2026 01:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant