Skip to content

Sync hot-patch-6.15 into development (Phase 1 of 2)#1655

Merged
jakejackson1 merged 123 commits into
developmentfrom
chore/sync-development-from-hot-patch
May 18, 2026
Merged

Sync hot-patch-6.15 into development (Phase 1 of 2)#1655
jakejackson1 merged 123 commits into
developmentfrom
chore/sync-development-from-hot-patch

Conversation

@jakejackson1
Copy link
Copy Markdown
Member

Summary

Phase 1 of the hot-patch ↔ development reconciliation. Brings every production fix and structural change from hot-patch-6.15 (releases 6.12.5 → 6.14.x, 101 commits) into development, which had been frozen since 2024-11-13. After this lands, hot-patch is intended to be retired and development becomes the single trunk — future hot-fixes branch off development.

  • Conflict surface: 10 content conflicts + 6 modify/deletes + 25 rename/renames + 25 double-deletes, all resolved.
  • Verification (local): composer install, yarn install --frozen-lockfile, yarn build, yarn lint:css, yarn test:js all green. yarn lint:js shows 10 pre-existing errors (verified on both source branches — actionToolbar self-shadow + JSDoc gaps in dev's new files); the 217 prettier diffs were auto-fixed in commit d2baecec.
  • Two files deferred to Phase 2 at dev's version: src/Controller/Controller_Pdf_Queue.php and its test. See Phase 2 follow-up below.

Conflict resolution (per file)

  • .github/workflows/deployment.yml — took hot-patch (drops the WP.org deploy job; dev's rename was obsolete).
  • src/Controller/Controller_Upgrade_Routines.php — kept dev's 6.12.0 cleanup_tmp_dir hook clearing alongside hot-patch's 6.13.2 fix_tmp_folder_permissions and 6.15.0 remove_legacy_update_cache routines.
  • src/Helper/Helper_Options_Fields.php — took hot-patch for every conflicted hunk (translator comments, esc_html__ escaping, refreshed doc URLs). Dev's auto-merged REST schema additions (validate/sanitize callbacks for REST Form Settings) are preserved. Removed the duplicate desc key that resulted from hot-patch inserting an escaped variant near dev's pre-existing entry on the logged_out_timeout setting.
  • src/Helper/Helper_PDF.php — kept both imports (GFPDF\Statics\Cache from dev + GFPDF\Helper\Mpdf\Request from hot-patch).
  • src/Model/Model_PDF.php — took hot-patch's three changes (refreshed middleware doc URL, two-bucket cleanup_tmp_dir with separate mPDF / template ages, more specific GP_Populate_Anything method_exists guard).
  • src/bootstrap.php — took hot-patch (adds the GF async / background-process class alias shim).
  • src/assets/js/admin/helper/spinner.js — took hot-patch's formatting.
  • src/assets/js/admin/settings/common/setupDynamicTemplateFields.js — kept dev's actionToolbar refactor (renamed module + selector .form-action-toolbar-2 + 4th true param to insertAfter), and layered hot-patch's handleMergeTags import + call after doMergetags().
  • src/assets/js/react/bootstrap/templateBootstrap.js — took hot-patch (adds chosen:updated trigger).
  • src/assets/js/react/gfpdf-main.js — kept dev's preview / unsaved-changes wiring (previewButton, actionToolbar, unsavedChangesWarning imports + calls). Normalised to hot-patch's tabs/semicolons formatting.
  • src/assets/js/react/utilities/PdfSettings/actionToolbar.js — kept dev's renamed module (was hot-patch's addEditButton.js) with the full form-action-toolbar clone behaviour.
  • src/assets/scss/Pages/_pdf-settings.scss — kept dev's // comment style and added hot-patch's .gform-settings-input__container--with-merge-tag rule.
  • src/assets/scss/gfpdf-styles.scss — kept dev's new MediaQueries/min-782 import; normalised every @use to double-quoted paths.

Test infrastructure

  • Accepted hot-patch's relocation of test data into tools/phpunit/data/{fonts,entries,forms,pdf}/. Dev's parallel move to tests/phpunit/data/{fonts,json}/ was reverted (the partial restructure was now obsolete); the legacy tests/phpunit/unit-tests/{fonts,json}/ tree was confirmed deleted on both sides.
  • Took hot-patch's versions of tools/phpunit/bootstrap.php, tools/phpunit/gravityforms-factory.php, and the tests/phpunit/unit-tests/test-*.php + Test_Controller_Custom_Fonts.php files (they reference the new tools/phpunit/data/ constants).
  • Accepted hot-patch's deletion of the legacy TestCafe-style E2E suite in tests/e2e/ (dev had modified some of those files; hot-patch replaced the whole layer with the Playwright tests under tests/playwright/ that were carried in automatically).

Phase 2 follow-up

The following hot-patch commits touched the queue stack and were deliberately not carried in this PR — they must be re-applied on top of dev's queue refactor in a separate PR:

Hash Subject
8a7914dd Update PDF Background Processing to be compatible with the updated background processing library (+ phpunit alias)
dc772da0 Update Background Processing Queue
389ae6ce Add queue cleanup when Background Processing toggled
3fe1c1e7 Ensure background queue uses correct entry when resending notifications

Known follow-ups (smaller)

  • Some i18n entries in Helper_Options_Fields.php still use plain __() where hot-patch had esc_html__() (dev's auto-merged regressions in non-conflict hunks). Not a behaviour regression vs current development, but worth normalising.
  • src/Helper/Log/MonoLoggerPsrLog2And3.php requires PHP 8 syntax to parse and is loaded conditionally via Helper/Log/Logger.php — carried over from hot-patch unchanged.

Test plan

  • CI: PHPUnit on PHP 7.4, 8.0, 8.3, 8.5 (matrix extended by hot-patch's 71bf214c)
  • CI: yarn build produces valid build/ assets
  • CI: Playwright e2e suite under tests/playwright/ runs against tools/wp-env/e2e.json
  • Manual: PDF generation across major field types (incl. Image Choice / Multi Choice carried from dev)
  • Manual: PDF Preview (the new REST-driven feature) works end-to-end
  • Manual: trigger 6.13.2 tmp-folder permission upgrade routine (hot-patch 51d85354) and verify gfpdf-*.log for surprises from the PSR Log refactor
  • Manual: Background Processing PDF send — confirm it still works under dev's queue refactor before Phase 2 lands
  • Manual: Verify hot-patch's 9137e349 left the GitHub release workflow producing a valid plugin zip

🤖 Generated with Claude Code

jakejackson1 and others added 30 commits November 13, 2024 10:13
(cherry picked from commit 996e527)
Gravity Forms 2.9.4 set their minimum requirements to PHP7.4+

(cherry picked from commit e84e591)
Make compatible with library updates included in Gravity Forms 2.9.7 and 2.9.8. Backwards compatible with < GF 2.9.7 too.

See gravityforms/gravityforms#3208
See gravityforms/gravityforms#3196

(cherry picked from commit 062f3e4)
…ound processing library

Rather than dispatch a bunch of individual queues, traditionally, Gravity PDF has treated a queue as a bunch of mini queues. In a new GF update, retry support has been added if a queue returns anything besides `false`, which caused big delays processing the mini queues in Gravity PDF.

Rewriting Gravity PDF to convert the mini queues into individual queues would be a breaking change and a lot of development time. Instead, we'll merge all the mini queues together to be processed sequentially.

Along with this adjustment, the retry logic has been reduced from 3 to 1. This allows for faster processing of a queue when an error does occur, since there will only be one extra timeout period instead of three.

The unrecoverable error has also been removed, as this would prevent any other PDFs from generating or Notification emails being sent. The benefit to this is the Notification emails will still be sent out, even if a PDF isn't attached.

The deprecation notice from GF 2.9.7 was addressed in 062f3e4

(cherry picked from commit 8a4bc03)
… doesn't already exist

(cherry picked from commit 1fdde0a)
Fixes display issues and PHP notice due to array key issues.

(cherry picked from commit eb56ad3)
1. Move Gravity PDF info to bottom of report for quick viewing in support tickets
2. Don't translate labels in exported report
3. Don't translate outdated template export value
4. Display "unlimited" WordPress Memory in export value if PHP memory set to -1

Fixes #1597

(cherry picked from commit 6606e87)
Manually create the log file before initializing, and exit early if this fails. On a read-only filesystem the log file won't be created, and Monolog will auto-drop all log messages.

Resolves #1580

(cherry picked from commit 403d572)
Strip excess classes from nodes when they contain more than 8 individual classes.

Resolves #1536

(cherry picked from commit 8d8b75d)
Wrap the compatibility check strings in functions that won't run until the `init` hook.

Fixes #1593

(cherry picked from commit 226031b)
When getting the product fields to determine if its empty, pass the filtered `use_value` and `use_admin_label` arguments to match the actual PDF output.

Fixes #1595

(cherry picked from commit d8d231a)
- Replace Cache class with version that better accounts for directory permissions of the parent folder
- Remove creation of unnecessary ttfontdata folder
- Move override files/classes to new folder for easier development
jakejackson1 and others added 15 commits May 18, 2026 06:52
Update coding-standards, deployment, javascript-tests, and phpunit
workflows to current GitHub Actions patterns; add an automated job
that tracks new WordPress core releases.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the legacy TestCafe runner and its bash-driven install
helpers with a Playwright-based test suite under tests/playwright/,
including shared fixtures and helpers in tools/playwright/. The new
GitHub Actions workflow (playwright-e2e.yml) replaces
end-to-end-tests.yml and runs Playwright sharded across multiple
wp-env instances.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Relocate PHPUnit bootstrap, fixtures, and config under tools/phpunit,
introduce dedicated wp-env profiles (development/integration/e2e)
under tools/wp-env, refresh PHP and JS test suites for the current
toolchain, and update Jest config and supporting mu-plugins so that
tests run cleanly under WordPress 7.0 and PHP 8.5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rewrite the licensing layer end-to-end: refresh the EDD plugin
updater integration, lift license state and helpers into
Helper_Abstract_Addon so add-ons can share behavior, expose the
updater on the data class for downstream code, and restructure the
license settings UI and Model_Settings/Controller_Settings handlers
to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a Redact_Processor that masks license keys, download links,
and other sensitive values before they reach the log file, and
register it in Logger::pushProcessor alongside the existing
handlers. Adjusts the Logger docblock to credit the move from
Helper_Logger.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduce Helper_Interface_Extension_Uninstaller so add-ons can opt
into a unified uninstall pipeline, expand Model_Uninstall to drive
it, clear the new license/update cron hooks on deactivation, and add
an upgrade routine that removes the legacy update cache during
6.14 → 6.15 upgrades.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y handling

Tighten the system report to surface temp directory health and
related configuration more clearly, and align View_System_Report
with the new model output.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Route custom and core font validation through the new mPDF cache,
align template management with the cleaner cache lifecycle, and
harden Helper_Misc::cleanup_dir so it only deletes paths within
resolvable, allow-listed folders.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sweep src/assets/js/react and src/assets/js/admin to current React
patterns and ES module conventions, and refresh the legacy entries
bundle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the bundled translation catalogs out of src/assets/languages
into the WordPress-standard languages/ directory (with .l10n.php
companions), regenerate the .po/.mo pairs for the shipped locales,
and add a tools/potomatic helper script plus dictionary that drives
the new translation workflow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apply a sweep of settings/field/view-layer cleanups across Helper_
classes, fields, models, views, bundled template configs, and the
matching SCSS partials: translator-comment coverage, narrow
visibility adjustments, and the remaining WordPress 7.0 / PHP 8.5
compatibility tweaks that the larger feature commits did not
absorb.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Point the plugin bootstrap at the new build/ asset paths, load
gravity-pdf-updater.php from the entry file, move the WordPress
text-domain to /languages, switch the API URL to api.gravitypdf.com,
adopt the WP 6.3+ defer script strategy, add a CLAUDE.md project
guide, and bump the version metadata in pdf.php and api.php.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 1 of the hot-patch ↔ development reconciliation. Brings every
production fix and structural change from hot-patch-6.15 (releases
6.12.5 → 6.14.x) into development, which had been frozen since
2024-11-13. After this commit, hot-patch is retired and development
becomes the single trunk; future hot-fixes branch off development.

Conflict resolution
-------------------
* `.github/workflows/deployment.yml` — took hot-patch (drops the WP.org
  deploy job entirely; dev's rename of that job was now obsolete).
* `src/Controller/Controller_Upgrade_Routines.php` — kept dev's 6.12.0
  cleanup_tmp_dir hook clearing alongside hot-patch's 6.13.2
  fix_tmp_folder_permissions and 6.15.0 remove_legacy_update_cache
  routines (non-overlapping versions).
* `src/Helper/Helper_Options_Fields.php` — took hot-patch for every
  conflicted hunk (translator comments, esc_html__ escaping, refreshed
  doc URLs). Dev's auto-merged REST schema additions (validate /
  sanitize callbacks for REST Form Settings) are preserved. Removed the
  duplicate `desc` key that resulted from hot-patch inserting an
  escaped variant near dev's pre-existing entry on the
  logged_out_timeout setting.
* `src/Helper/Helper_PDF.php` — kept both imports
  (GFPDF\Statics\Cache from dev + GFPDF\Helper\Mpdf\Request from
  hot-patch).
* `src/Model/Model_PDF.php` — took hot-patch's three changes (refreshed
  middleware doc URL, two-bucket cleanup_tmp_dir with separate mPDF /
  template ages, more specific GP_Populate_Anything method_exists guard).
* `src/bootstrap.php` — took hot-patch (adds the GF async /
  background-process class alias shim).
* `src/assets/js/admin/helper/spinner.js` — took hot-patch's formatting.
* `src/assets/js/admin/settings/common/setupDynamicTemplateFields.js`
  — kept dev's actionToolbar refactor (renamed module + selector
  `.form-action-toolbar-2` + 4th `true` param to insertAfter), and
  layered hot-patch's `handleMergeTags` import and call after
  `doMergetags()`.
* `src/assets/js/react/bootstrap/templateBootstrap.js` — took
  hot-patch (adds `chosen:updated` trigger).
* `src/assets/js/react/gfpdf-main.js` — kept dev's preview /
  unsaved-changes wiring (`previewButton`, `actionToolbar`,
  `unsavedChangesWarning` imports + calls). Normalised the rest to
  hot-patch's tabs/semicolons formatting.
* `src/assets/js/react/utilities/PdfSettings/actionToolbar.js` — kept
  dev's renamed module (was hot-patch's `addEditButton.js`) with the
  full `form-action-toolbar` clone behaviour.
* `src/assets/scss/Pages/_pdf-settings.scss` — kept dev's `//` comment
  style and added hot-patch's
  `.gform-settings-input__container--with-merge-tag` rule.
* `src/assets/scss/gfpdf-styles.scss` — kept dev's new
  `MediaQueries/min-782` import; normalised every `@use` to
  double-quoted paths.

Test infrastructure
-------------------
* Accepted hot-patch's relocation of test data into
  `tools/phpunit/data/{fonts,entries,forms,pdf}/`. Dev's parallel move
  to `tests/phpunit/data/{fonts,json}/` was reverted (the partial
  restructure was now obsolete) and the legacy
  `tests/phpunit/unit-tests/{fonts,json}/` tree was confirmed deleted on
  both sides.
* Took hot-patch's versions of `tools/phpunit/bootstrap.php`,
  `tools/phpunit/gravityforms-factory.php`, and the
  `tests/phpunit/unit-tests/test-*.php` + `Test_Controller_Custom_Fonts.php`
  files (they reference the new `tools/phpunit/data/` constants).
* Accepted hot-patch's deletion of the legacy TestCafe-style E2E suite
  in `tests/e2e/` (dev had modified some of those files; hot-patch
  replaced the whole layer with the Playwright tests under
  `tests/playwright/` that were carried in automatically).

Deferred to Phase 2
-------------------
* `src/Controller/Controller_Pdf_Queue.php` — kept dev's queue
  architecture (flattened queue + 7.0-style notification dispatch).
* `tests/phpunit/unit-tests/Controller/Test_Controller_Pdf_Queue.php`
  — kept dev's matching tests.

The following hot-patch commits touched the queue stack and must be
re-applied on top of dev's queue refactor in a Phase 2 follow-up PR:

  8a7914d  Update PDF Background Processing to be compatible with the
            updated background processing library (+ phpunit alias).
  dc772da  Update Background Processing Queue.
  389ae6c  Add queue cleanup when Background Processing toggled.
  3fe1c1e  Ensure background queue uses correct entry when resending
            notifications.

Known follow-ups
----------------
* `composer.lock` and `package-lock.json` will need a refresh against
  hot-patch's dependency manifests in a separate commit.
* Some i18n entries in `Helper_Options_Fields.php` still use plain
  `__()` where hot-patch had `esc_html__()` (dev's auto-merged
  regressions in non-conflict hunks). Not a behaviour regression vs
  development today, but worth normalising in a small follow-up.
* `src/Helper/Log/MonoLoggerPsrLog2And3.php` requires PHP 8 syntax to
  parse and is loaded conditionally via `Helper/Log/Logger.php`
  (carried over from hot-patch unchanged).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
These five files (added on development for the REST API / PDF
Preview / unsaved-changes feature) used the older Prettier config —
2-space soft indents, no semicolons. Hot-patch standardised on tabs +
semicolons via wp-scripts. Auto-applied 'yarn lint:js --fix' after
the merge to normalise.

No behaviour change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.85%. Comparing base (4eec6df) to head (a88359f).
⚠️ Report is 193 commits behind head on development.

Additional details and impacted files
@@               Coverage Diff                @@
##           development    #1655       +/-   ##
================================================
+ Coverage        77.74%   92.85%   +15.10%     
================================================
  Files              255       58      -197     
  Lines            13925     1511    -12414     
  Branches           370      419       +49     
================================================
- Hits             10826     1403     -9423     
+ Misses            3091      103     -2988     
+ Partials             8        5        -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

jakejackson1 and others added 3 commits May 18, 2026 10:58
When resolving src/bootstrap.php in 607337e I took hot-patch wholesale
(--theirs), which dropped dev's wiring for the new REST API controllers
that were carried in for the 7.0 release:

  - $this->rest_api() call in Router::init() between gf_form_settings()
    and pdf()
  - rest_api() method that instantiates Rest_Form_Settings and
    Rest_Pdf_Preview, adds them to the singleton, and registers a
    rest_request_after_callbacks logger for /gravity-pdf/* routes

Without this wiring the Rest classes existed on disk but never
registered any routes, so the PDF Preview button and every Form-PDF
CRUD endpoint silently failed. Re-applied dev's additions verbatim;
all other hot-patch changes to bootstrap.php (GF async/background
process alias shim, gfpdf_settings_sanitize toggle hook, copyright
bump) are preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three more issues found by auditing files I took with --theirs in the
Phase 1 merge:

1. test-slow-pdf-processes.php — when I took hot-patch's version
   wholesale I lost two dev-added test methods that exercise the
   end-to-end PDF generation pipeline:
     * test_process_legacy_pdf_endpoint (covers Controller_PDF's
       legacy gf_pdf endpoint, including its setExpectedIncorrectUsage
       deprecation notices)
     * test_process_pdf_endpoint (covers the modern endpoint via
       $GLOBALS['wp']->query_vars['gpdf'])
   Restored dev's full file, then patched the font-glob path to use
   PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/' (hot-patch's
   relocation) and bumped the copyright to 2026.

2. tests/phpunit/unit-tests/Rest/Test_Rest_Pdf_Preview.php — this
   file was auto-merged in (dev added it new) but referenced
   __DIR__ . '/../../data/fonts/' which was dev's relocation that
   we reverted. Fixed to PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/'
   so the mPDF fontDir resolves under hot-patch's data layout.

3. tests/e2e/advanced-checks/pdf-preview.test.js — orphaned TestCafe
   test that survived the merge as an A-side add from dev. Imports
   from the now-deleted tests/e2e/utilities/page-model/helpers/pdf
   module and pulls in 'testcafe' which is no longer a dependency
   on hot-patch. Deleted the file (and its now-empty parent dirs).
   Test intent remains in git history; rewriting it as a Playwright
   spec under tests/playwright/core/ is Phase 2 work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…t debt

PHPUnit found Test_PDF::test_cleanup_tmp_dir failing because the test
ages on dev side (1.01hr) were auto-merged in alongside hot-patch's
cleanup_tmp_dir implementation (which now uses a 12hr threshold for
template tmp + 1hr for mPDF tmp). Reverted the test ages to the merge
base / hot-patch values so file age vs threshold lines up:

  test1=11.5hr (keep, <12hr)
  test2=12.01hr (delete, >12hr)
  test3=12.5hr (delete, >12hr)
  test6=5hr (keep, <12hr)

Also closed the 10 pre-existing JS lint errors in dev's new 7.0 files
that CI would otherwise flag:

  preview.js
    - jsdoc/no-undefined-types: fixed 'int' -> 'number'
    - jsdoc/require-returns-description: added one-line descriptions
    - no-console: two console.error calls suppressed with reason
      ('surface fetch errors to the browser console for diagnostics')
  formSettings.js
    - jsdoc/require-param-type: typed 'schema' and 'formId'
    - jsdoc/require-returns-description: added FormData description
    - no-unused-vars: gform.addFilter is variadic and supplies the
      schema arg even when unused; documented with disable + reason
  actionToolbar.js
    - no-shadow: renamed inner 'actionToolbar' to 'originalToolbar'
      so it doesn't shadow the exported function

PHPUnit after these changes: 1118 tests, 4080 assertions, 1 failure
(Test_Controller_Pdf_Queue::test_failed_queue_tasks - expected Phase 2
follow-up), 8 skipped, 1 risky (pre-existing output buffer warning).
yarn lint:js: clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jakejackson1 and others added 7 commits May 18, 2026 11:32
Both workflows gate themselves on the 'run-tests' label via the
check_for_string_in_pull_request_comment job, but their pull_request
trigger uses the default event types (opened, reopened, synchronize) —
so adding the label after the PR was opened does NOT re-run them.

playwright-e2e.yml already lists 'labeled' in its types; copying that
pattern to phpunit.tests.yml and coding-standards.yml so the same
label-flow works for all three test suites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three classes of PHPCS errors surfaced after CI ran with the
'run-tests' label:

1. Auto-fixable formatting (26 of 28 errors), applied via phpcbf:
   * api.php: 'static::' -> 'self::' on 18 scope-resolutions inside
     the final GPDFAPI class (Universal.CodeAnalysis.StaticInFinalClass).
   * api.php + Helper_Misc.php + Helper_Options_Fields.php: missing
     space between 'function' keyword and '(' on 7 anonymous functions
     (Squiz.Functions.MultiLineFunctionDeclaration.SpaceAfterFunction).

2. Reserved-keyword parameter names regressed in dev's edits to
   GPDFAPI methods (the merge-base + hot-patch both used non-reserved
   names; dev had quietly renamed them). Restored the non-reserved
   names so PHP 8 named-arg callers and the lint sniff are both happy:
     get_plugin_option(): $default        -> $default_value
     product_table():    $return         -> $should_return
     likert_table():     $return         -> $should_return
     Helper_Misc::flatten_array(): $array -> $items (dev's new method,
       so no API stability concern)
   (Universal.NamingConventions.NoReservedKeywordParameterNames.*)

3. Two false-positive nonce errors in GPDFAPI::add_pdf_font(). The
   helper swaps $_FILES out for a synthetic payload built from its own
   $font argument (programmatic API, not an unverified form submission),
   so a nonce check is irrelevant. Targeted // phpcs:ignore comments
   with a one-line reason on each (WordPress.Security.NonceVerification.Missing).

Note: 'composer phpcs:lint .' run from inside the worktree currently
reports 'no violations' because the ruleset excludes /.claude/* and
the worktree lives at .claude/worktrees/sync-development-from-hot-patch/.
CI checks out at /home/runner/work/gravity-pdf/gravity-pdf/ so the
exclude doesn't fire there - which is why these violations only
surfaced after the workflow ran. Re-running phpcs against a copy of
the files outside .claude/ now reports 0 errors, 1 pre-existing
readfile() warning in Model_PDF.php that hot-patch CI already
tolerates.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ry budget

Helper_Pdf_Queue::task() retries a failing callback exactly once, so
on a callback that always throws the mock is invoked twice (initial
attempt + 1 retry). Hot-patch had already corrected this expectation
in its branch; dev still had 'exactly(3)' which doesn't match the
helper's behaviour on either branch.

I deliberately deferred the *Controller_Pdf_Queue* file and its test
to Phase 2 (architectural reconciliation of dev's flattened queue vs
hot-patch's queue-update changes), but test_failed_queue_tasks
exercises Helper_Pdf_Queue::task() — which is byte-identical on both
branches — so it's not actually queue-architecture work; it's a
straight test correction.

PHPUnit was reporting:
  Tests: 1118, Assertions: 4080, Failures: 1, Skipped: 8, Risky: 1
across PHP 7.4 / 8.3 / 8.5. The 1 failure was this test; the 8 skips
(EDD_SL_Plugin_Updater x6 + multisite x2) and 1 risky (output-buffer
warning on Test_Slow_PDF_Processes::test_generate_pdf) are
pre-existing on hot-patch and tolerated.

Updated the @SInCE docblock to describe the actual behaviour.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ow_PDF_Processes risky

PHPCS (11 errors auto-fixed by phpcbf in dev's surviving 7.0 files —
all Squiz.Functions.MultiLineFunctionDeclaration.SpaceAfterFunction
on anonymous `function( ... )` declarations):

  src/Rest/Rest_Form_Settings.php   - 4 errors (lines 176, 972, 1019, 1084)
  src/Statics/Cache.php             - 1 error  (line 94)
  src/Statics/Debug.php             - 1 error  (line 52)
  src/Controller/Controller_PDF.php - 5 errors (lines 121, 148, 200, 217, 224)

These were missed by my earlier phpcbf sweep because I only piped the
files that CI's *first* failed run named; CI then picked the next
batch of files once those cleared. The fixes are byte-identical to
what phpcbf produces, so style-equivalent to hot-patch's existing JS
files.

Test_Slow_PDF_Processes::test_generate_pdf risky:

beStrictAboutOutputDuringTests=true in tools/phpunit/config.xml fails
any test that leaves the output-buffer stack different from where it
started. Helper_PDF::pre_stream_actions() (run before mPDF streams)
drains *every* active output buffer:

    while ( ob_get_level() > 0 ) {
        ob_end_clean();
    }

So by the time generate_pdf() trips the wp_die() error path and the
WPDieException bubbles up to the test, PHPUnit's own buffers have
already been torn down. The risky warning then fires on test teardown.

Snapshot the buffer depth before the call and re-establish it
afterwards in both directions: close any extras above the snapshot,
then open empties below it. Local PHPUnit run is now clean:
'OK (1 test, 2 assertions)' with no risky note. Hot-patch did not
need this guard because it lacked the dev-side setExpectedIncorrectUsage
call that interacted with the buffer state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI was exiting with code 1 on two warnings:

1) src/Model/Model_PDF.php:2694 - readfile()
   The line already had a phpcs:ignore comment but it referenced the
   *old* WPCS sniff slug (file_system_read_readfile). The sniff was
   renamed to file_system_operations_readfile when WordPressCS was
   refactored, so the existing ignore was a no-op. Updated the slug
   and added a reason: we're streaming the generated PDF straight
   to the response and WP_Filesystem has no streaming equivalent.

2) src/Rest/Rest_Form_Settings.php:972 - unused $item param
   This is a closure bound to the 'gfpdf_template_for_current_page'
   filter. The filter passes its current value as the first arg, but
   we intentionally ignore it and force-return the captured $template
   so the REST schema can be regenerated for an arbitrary template.
   Added a phpcs:ignore for Generic.CodeAnalysis.UnusedFunctionParameter.Found
   with a one-line reason rather than renaming the param (the filter
   signature is fixed).

PHPCS exit code is now 0 against a copy of these files outside .claude/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…op dead ob_end_clean loop

* tools/phpcs/config.xml: add Generic.CodeAnalysis.UnusedFunctionParameter.Found
  to the WordPress-Extra <exclude> list (alongside its existing
  ...FoundAfterLastUsed sibling). PHP closures bound to WP filters /
  REST callbacks routinely have to accept args dictated by the caller
  signature, and the per-line phpcs:ignore noise wasn't paying for
  itself. Reverted the targeted ignore on
  src/Rest/Rest_Form_Settings.php::get_template_schema() now that the
  sniff is off.

* tests/phpunit/unit-tests/test-slow-pdf-processes.php: drop the
  'while ob_get_level() > $initial_ob_level' guard. The only thing
  generate_pdf() does to the buffer stack via pre_stream_actions() is
  drain it, so the buffer depth can only land at or below the initial
  snapshot - the open-up loop is sufficient on its own. Kept the
  ob_start() loop and reworded the comment.

PHPCS exit 0; phpunit --filter test_generate_pdf:
  'OK (1 test, 2 assertions)' - no risky warning.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ommits

Review pass — trimmed AI-slip in the post-merge fix-up commits:

* tests/phpunit/unit-tests/test-slow-pdf-processes.php — collapsed
  the 5-line block comment above the ob_get_level() snapshot to one
  line. The body says how; the comment now just says why.
* tests/phpunit/unit-tests/Controller/Test_Controller_Pdf_Queue.php
  — collapsed parenthetical-narration docblock back to one line.
* src/assets/js/react/api/preview.js — trimmed JSDoc @return text
  and dropped paragraph-length 'surface … to the browser console'
  justifications from two eslint-disable-next-line no-console
  comments.
* src/assets/js/react/utilities/PdfSettings/formSettings.js — trimmed
  JSDoc descriptions and shortened the two eslint-disable-next-line
  no-unused-vars reasons.
* api.php — shortened the two phpcs:ignore reasons on the
   swap inside add_pdf_font().
* src/Model/Model_PDF.php — shortened the readfile() phpcs:ignore
  reason.

PHPCS exit 0; yarn lint:js clean; phpunit --filter
'test_generate_pdf|test_failed_queue_tasks' passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jakejackson1 jakejackson1 merged commit b3b562a into development May 18, 2026
19 of 20 checks passed
@jakejackson1 jakejackson1 deleted the chore/sync-development-from-hot-patch branch May 18, 2026 02:52
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