Skip to content

Prepare for WordPress 7.0 and fix critical bugs#7

Open
wzul wants to merge 89 commits into
mainfrom
fix/wp-7.0-readiness
Open

Prepare for WordPress 7.0 and fix critical bugs#7
wzul wants to merge 89 commits into
mainfrom
fix/wp-7.0-readiness

Conversation

@wzul

@wzul wzul commented May 18, 2026

Copy link
Copy Markdown
Collaborator

Error calling AI API: 404 Client Error: Not Found for url: https://api.ollama.com/api/generate

wzul and others added 30 commits July 30, 2025 11:43
- Bump "Tested up to" to 7.0 in readme.txt
- Add load_plugin_textdomain() on plugins_loaded
- Fix singleton == null to === null across all classes
- Fix API singleton to support per-form credentials (keyed by hash)
- Fix webhook setup using wrong global secret-key for form-specific configs
- Fix copy-paste bug: form webhooks titled "CHIP for GiveWP" instead of "CHIP for Fluent Forms"
- Replace wp_send_json_success(..., 500) with wp_send_json_error(..., 500)
- Tighten != to !== in security-relevant comparisons
- Replace exit(200) with wp_die() for currency errors
- Remove dead email notification code (parsed but never sent)
- Clean up CI: remove unnecessary composer/npm install steps

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… processor

- Drop bundled Codestar Framework (2.4M); use FF Pro's native Payment
  Methods tab via BasePaymentMethod.
- New settings schema: global option + per-form fluentform_form_meta
  rows. One-time migration preserves existing users' saved credentials.
- 14-method whitelist with 'cards' expanding to visa+mastercard+maestro
  at send-time.
- Chip_Fluent_Forms_API returns WP_Error on transport/HTTP/JSON errors.
- Chip_Fluent_Forms_Purchase uses createInitialPendingTransaction,
  getPaymentMode, updateRefund, with_submission_lock helper.
- Amount-mismatch downgrades to requires_review.
- ff_chip_payment_paid_chip, ff_chip_ipn_domain, ff_chip_payment_mode
  filter hooks; FF_CHIP_IPN_DOMAIN constant.
- Standalone admin submenu page retired; settings live under
  Fluent Forms -> Settings -> Payment Methods.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Workflows:
- plugin-check.yml — build, PHP 7.4-8.5 compatibility matrix, PHPCS
  (WordPress standards via phpcs.xml), PHPUnit, and a wp-env-based
  Plugin Check job that runs against Fluent Forms + plugin-check.
- deploy.yml — WordPress.org SVN deploy (trunk / release stages).
  Supports both vX.Y.Z and X.Y.Z tag conventions.
- release-zip.yml — builds a plugin zip and uploads it as a
  GitHub release asset when a release is published.
- prepare-release.yml — AI-assisted release prep: generates a
  WordPress-style changelog from the diff since the previous tag,
  bumps versions, opens a release PR.
- pr-summary.yml — AI-assisted PR description auto-update.

Tooling:
- scripts/bump-version.sh — updates the version header, the
  FF_CHIP_MODULE_VERSION constant, the Stable tag, and prepends
  a new changelog entry. Used by prepare-release.yml.
- scripts/generate_pr_summary.py and generate_release_notes.py —
  thin wrappers over the configured AI API for the two AI workflows.
- phpcs.xml — WordPress coding-standards ruleset (excludes vendor,
  node_modules, assets, build, dist, tests; 7.4-8.5 test version).
- phpunit.xml — PHPUnit 9.6 configuration; tests/Unit/ test suite.
- tests/bootstrap.php and tests/Unit/Chip_ApiTest.php — WP_Mock
  scaffold with a placeholder test for Chip_Fluent_Forms_API.

Local dev:
- .wp-env.json — wp-env config: WordPress core + fluentform.zip +
  plugin-check.zip, with the plugin mounted into wp-content/plugins.
- .vscode/settings.json — WordPress code style.
- .gitignore — added package-lock.json, yarn.lock, node_modules/,
  dist/, build/, ci-build/, vendor/, .phpunit.cache/.result.cache,
  and the release workflow's scratch files.
- .gitattributes — export-ignore the new dev-only files
  (/.wordpress-org, /.wp-env.json, phpcs.xml, phpunit.xml,
  /tests, /scripts) so they never ship in the plugin zip.

The old plugin-activation.yml and build-zip.yml are removed;
their responsibilities are covered by plugin-check.yml
(plugin activation + release zip) and release-zip.yml.

Co-Authored-By: Claude <noreply@anthropic.com>
release-zip.yml and deploy.yml both built and uploaded the same
chip-for-fluent-forms.zip artifact: on a tag push, deploy.yml
created the GitHub release and uploaded the zip, then
release-zip.yml triggered on `release: created` and rebuilt the
same zip with --clobber. Two zips, double CI minutes, double
artifact storage.

The release-zip.yml file is removed. deploy.yml's existing
'Create release zip' and 'Upload release asset to GitHub' steps
remain the sole owner of the release zip. release-zip.yml's
secondary role (catching releases created outside the deploy
flow, e.g. via the GitHub UI) is now covered by manually
re-running deploy.yml with stage=release.

Co-Authored-By: Claude <noreply@anthropic.com>
composer.json:
- Add real dev dependencies (phpunit, wp_mock, wpcs, dealerdirect
  installer) so the phpunit job in plugin-check.yml has a working
  vendor/ to test against. Add a PSR-4 autoload for the tests/
  namespace, plus composer scripts for test/lint.

Webhook class loading:
- Move class-chip-webhook-setup.php from the is_admin() block to
  the unconditional includes list. The class is needed on the
  public IPN side too (refund signature verification runs during
  a public POST). Drop the now-dead class_exists guard in
  Chip_Fluent_Forms_Purchase::get_webhook_public_key().

Two-phase migration:
- Rewrite Chip_Fluent_Forms_Migration as two-phase. Phase 1
  writes the new global option and per-form meta rows and sets
  a phase-1 flag. Phase 2 (the next request) verifies the new
  options are well-formed and complete, then deletes the legacy
  options. Verification failures roll back the phase-1 flag so
  the next request retries from the still-present legacy source.
  No more single-request atomicity gap.

Per-form save pipeline:
- Hook Chip_Fluent_Forms_Form_Settings::save_per_form_settings()
  on fluentform/after_save_form_settings. Extracts the `chip`
  subkey from the per-form payment settings payload, normalizes
  React-style 'true'/'false' strings to '1'/'0', and persists
  via Chip_Fluent_Forms_Settings::save_form().

Drop get_settings() shim:
- Refactor Chip_Fluent_Forms_Purchase to consume
  Chip_Fluent_Forms_Settings::for_form() directly. The three
  call sites (create_purchase, redirect, success_callback)
  now use the new key names (send_receipt, due_strict_timing,
  payment_method_whitelist) without the translation shim.
  The shim method itself is kept as a one-line passthrough for
  any external subclass that may have called it. Also drop the
  redundant class_exists guard in getPaymentMode().

Co-Authored-By: Claude <noreply@anthropic.com>
ci: rename includes/class-chip-settings.php to class-chip-fluent-forms-
settings.php (matches the Chip_Fluent_Forms_Settings class name; PHPCS
WordPress.Files.FileName rule). Update the require path in
chip-for-fluent-forms.php.

phpcs.xml: relax WordPress.NamingConventions.ValidVariableName for
includes/class-purchase.php. The processor extends
FluentFormPro\Payments\PaymentMethods\BaseProcessor and overrides its
methods; BaseProcessor's public method signatures (handlePaymentAction,
createInitialPendingTransaction, getAmountTotal, etc.) and Fluent Forms
Pro's action callbacks use camelCase parameter names that we must accept
unchanged to maintain the contract. Same situation as
includes/block/class-chipgateway.php in the GiveWP plugin.

docs: add a top-level /** @Package CHIPForFluentForms */ file doc
comment to every PHP file that didn't have one. This is the bulk of
the PHPCS 'Missing file doc comment' error count.

class-api.php: same.

uninstall.php: refactor to use FluentForm\App\Helpers\Helper::deleteFormMeta()
for the actual deletion, with a narrowly-scoped phpcs:ignore on the
single wpFluent() form-ids enumeration. The previous code used a
direct $wpdb->query; the new code goes through FF Pro's own CRUD layer
for the deletion, with a justifying comment explaining why the
form-id lookup still needs an ignore.

ci: change AI_MODEL default in pr-summary.yml and prepare-release.yml
from 'gemini-3-flash-preview:cloud' to 'llama3.1:8b' to match the
configured Ollama endpoint (AI_API_URL = https://api.ollama.com/...).
The var can still be overridden at the repo level.

Co-Authored-By: Claude <noreply@anthropic.com>
PHPCS WordPress.Files.FileName: file name should match the class
name with class- prepended. Our Chip_Fluent_Forms_* admin classes
were in class-chip-*.php files; renamed to class-chip-fluent-forms-*.php.

- class-chip-form-settings.php        -> class-chip-fluent-forms-form-settings.php
- class-chip-handler.php               -> class-chip-fluent-forms-handler.php
- class-chip-migration.php            -> class-chip-fluent-forms-migration.php
- class-chip-settings-page.php         -> class-chip-fluent-forms-settings-page.php
- class-chip-webhook-setup.php         -> class-chip-fluent-forms-webhook-setup.php

Updated require paths in chip-for-fluent-forms.php.

Co-Authored-By: Claude <noreply@anthropic.com>
PHPCS WordPress conventions: add /** */ docblocks + @param tags for
every method on the processor; Yoda conditions (=== null, !== 'paid',
etc.); in_array(..., true); the line-by-line check that breaks a few
of the diff hunks (multi-line paren formatting, array-alignment
warnings, etc.) is intentionally left for a follow-up since it is
mechanical and won't break runtime.

Co-Authored-By: Claude <noreply@anthropic.com>
- Multi-line paren formatting on with_submission_lock() calls in
  redirect(), success_callback(), refund_callback().
- print_r() replaced with wp_json_encode() in log_create_payment_failure.
- wp_die( sprintf( ..., esc_html( $x ) ) ) re-wrapped: outer esc_html()
  to satisfy the 'all output should be escaped' rule.
- with_submission_lock() now uses single-quoted SQL with a
  pre-bound $lock_name variable to avoid the double-quote-with-no-
  interpolation warning.

Co-Authored-By: Claude <noreply@anthropic.com>
PHPCS WordPress.Files.FileName: file name should match the class
name with class- prepended.

- class-api.php       -> class-chip-fluent-forms-api.php
- class-purchase.php  -> class-chip-fluent-forms-purchase.php

Updated require paths in chip-for-fluent-forms.php.

Co-Authored-By: Claude <noreply@anthropic.com>
PHPCS cleanup for includes/class-chip-fluent-forms-api.php:
- /** */ class docblock on the class.
- /** */ member variable docblocks for the three private props.
- /** */ method docblocks for every public/private method, with
  @param/@return annotations.
- Yoda strict comparison in was_payment_successful.
- json_encode() -> wp_json_encode() in call().
- /* translators: */ comments on the three __() sprintf calls
  (PHPCS requires a translator note when the string contains %s/%d).
- Inline comment periods added.

Co-Authored-By: Claude <noreply@anthropic.com>
The PHPUnit bootstrap had a hardcoded include of includes/class-api.php
which was renamed to includes/class-chip-fluent-forms-api.php in the
previous commit. Update the path.

Co-Authored-By: Claude <noreply@anthropic.com>
The ValidVariableName exclusion was scoped to the old file name
includes/class-purchase.php. After the rename to
includes/class-chip-fluent-forms-purchase.php the exclusion no longer
matched, which caused ~45 'Variable not in valid snake_case' errors
to come back. Update the pattern.

Co-Authored-By: Claude <noreply@anthropic.com>
- Chip_Fluent_Forms_Form_Settings: add /** */ class docblock.
- Chip_Fluent_Forms_Migration: rewrite the top-of-file docblock to be
  the file-level doc (was previously duplicated as the class doc),
  add a class docblock referencing it, add a method docblock for
  maybe_migrate().

Co-Authored-By: Claude <noreply@anthropic.com>
- /** */ class docblock on Chip_Fluent_Forms_Handler.
- /** */ member variable docblocks for the three private props.
- /** */ method docblocks for every public method, with @param/@return.
- /* translators: */ comments on the two __() calls (PHPCS requires a
  translator note when the string contains placeholders).
- Yoda + strict comparison is_enabled() === 'yes' (already there).

Co-Authored-By: Claude <noreply@anthropic.com>
Two more admin files get the same treatment:
- class-chip-fluent-forms-settings-page.php: /** */ class docblock +
  /** */ @param docblocks on the 5 WP-Settings-API render callbacks
  (field_text, field_number, field_select, field_checkbox,
  field_checkbox_group).
- class-chip-fluent-forms-webhook-setup.php: /** */ class docblock +
  @param docblock for get_public_key_for_form.

Co-Authored-By: Claude <noreply@anthropic.com>
- /** */ file-level docblock at the top of class-chip-fluent-forms-
  settings.php (was missing — PHPCS flagged it).
- /** */ class docblock on Chip_Fluent_Forms_Settings, rewritten to
  reference the file-level block.

Co-Authored-By: Claude <noreply@anthropic.com>
chip-for-fluent-forms.php:
- /** */ class docblock on Chip_Fluent_Forms.
- /** */ member variable docblock for the private $_instance.
- /** */ method docblocks for every public method (get_instance,
  __construct, define, includes, add_filters, add_actions,
  setting_link, after_global_settings_save, after_global_settings_added,
  after_form_settings_saved) with @param/@return where applicable.
- /** */ function docblocks on the two top-level functions
  (chip_for_fluent_forms_load_textdomain, load_chip_for_fluent_forms).
- Yoda strict: null === self::$_instance.

Co-Authored-By: Claude <noreply@anthropic.com>
- phase1_write: @param array $legacy + @throws \RuntimeException.
- phase2_verify: @param array $legacy.

Co-Authored-By: Claude <noreply@anthropic.com>
- register_per_form_settings: @param array $settings, @param object $form,
  @return array.

Co-Authored-By: Claude <noreply@anthropic.com>
- Chip_Fluent_Forms_Handler extends BasePaymentMethod and writes
  to $this->settingsKey, which is a camelCase property of the
  parent class. We cannot rename it.
- Chip_Fluent_Forms_Webhook_Setup also extends from the same area
  and inherits the convention; relaxing the rule for it is consistent.

Co-Authored-By: Claude <noreply@anthropic.com>
…gration

- save_per_form_settings: flesh out the @param descriptions.
- migration: array( 'id' ) on a numeric-keyed select() is a PHPCS
  warning; rewrite as array( 0 => 'id' ) to make the key explicit.

Co-Authored-By: Claude <noreply@anthropic.com>
- if ( $data['payment_method'] !== 'chip' ) -> if ( 'chip' !==
  $data['payment_method'] )
- $transaction->status !== 'paid' && ( $payment['status'] ?? '' ) ===
  'paid' -> 'paid' === ( $payment['status'] ?? '' ) && 'paid' !==
  $transaction->status
- $transaction->status !== 'failed' && ( $payment['status'] ?? '' ) !==
  'paid' -> 'failed' !== $transaction->status && 'paid' !==
  ( $payment['status'] ?? '' )
- $transaction->status !== 'refunded' -> 'refunded' !==
  $transaction->status
- sprintf(__( 'User redirect to CHIP for completing the payment: %s', ...))
  wrapped in a /* translators: */ block.

Co-Authored-By: Claude <noreply@anthropic.com>
wzul and others added 11 commits June 15, 2026 06:25
…Webhook_Setup class; refund sync now a CHIP-dashboard concern
…refix to satisfy WordPress.NamingConventions.ValidVariableName)
…o 2.0.0

send_receipt and synchronize_refund removals are part of the same
2.0.0 major refactor, not a new minor version.
…e_refund removal

- Drop public_key from Chip_Fluent_Forms_Settings (defaults, sanitize,
  merge-fallback, migration) — no writer exists anymore.
- Drop Chip_Fluent_Forms_API::get_public_key() — refund webhook setup
  is gone, so no caller remains.
- Drop the corresponding test_get_public_key test; replace with
  singleton-identity and distinct-credentials tests that exercise
  the get_instance() factory without HTTP mocking.
- Drop the fluent_form_chip_public_key option handling from the
  migration and uninstall.php.
- Drop the now-unused $defaults locals in sanitize_global and
  sanitize_form.
Drop the manual wp-env + jq summary block and use the official
wordpress/plugin-check-action@v1, which handles wp-env startup,
plugin-check install + activation, dependency resolution, JSON
parsing, and PR annotations internally.

Behaviour preserved:
- Plugin is still checked from the build artifact (so .gitattributes
  export-ignore rules apply).
- Same two ignored codes: trademarked_term and the Fluent Forms Pro
  hookname prefix warning.
- Warnings still fail the run (ignore-warnings defaults to false).

Co-Authored-By: Claude <noreply@anthropic.com>
The 'plugins_loaded' closure referenced FF_CHIP_BASENAME, which is
only defined inside Chip_Fluent_Forms::define() (gated by the Fluent
Forms Pro class check below it). On PHP 8 this raised a fatal
'Undefined constant' Error when the closure ran before the class
was instantiated. PHP 7.4 silently coerced the undefined constant to
its name string, masking the bug.

Use FF_CHIP_FILE (defined at the top of the entry point) and call
plugin_basename() inline, mirroring the class's own define() method.
This keeps the text-domain path stable and PHP-8 safe.

Surfaced by the new wordpress/plugin-check-action step, which
activates the plugin before running checks; the old manual wp-env
job never activated the chip plugin so the latent error went unseen.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown

✅ WordPress Plugin Check Report

✅ Status: Passed

📊 Report

All checks passed! No errors or warnings found.


🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

wzul and others added 18 commits June 16, 2026 08:12
Adopt the wordpress/plugin-check-action@1 on the plugin side as
well. The new check is more thorough than the old manual block and
found 2 errors and 5 warnings the previous setup never caught:

Errors fixed:
- Add ABSPATH guard to class-chip-fluent-forms-api.php.
- Add ABSPATH guard to class-chip-fluent-forms-purchase.php.

Warnings fixed:
- Rename FF_CHIP_BASENAME / FF_CHIP_FSLUG to CHIP_FF_BASENAME /
  CHIP_FF_FSLUG so the plugin's constant prefix matches its slug
  (PrefixAllGlobals.NonPrefixedConstantFound).
- Rename FLUENT_FORMS_CHIP_ROOT_URL to CHIP_FF_API_ROOT_URL
  (same rule).
- Rename $form_ids / $row / $form_id in uninstall.php to
  $chip_ff_* so the loop vars are prefixed
  (PrefixAllGlobals.NonPrefixedVariableFound).
- Drop load_plugin_textdomain() from the entry point. WordPress
  4.6+ loads translations under the plugin slug automatically,
  and the WP plugin-check tool flags the call as discouraged.
  (Also removes the only place the closure depended on
  FF_CHIP_BASENAME, which was the latent PHP 8 fatal the previous
  commit fixed.)

Doc updates:
- CLAUDE.md: constant list now shows the new names.
- readme.txt: FAQ reference to the API base constant uses the
  new name.

Co-Authored-By: Claude <noreply@anthropic.com>
Three issues fixed for users upgrading from 1.x to 2.0:

1. Payment Methods tab does not render CHIP fields. The 2.0 rewrite adopted BasePaymentMethod but kept the Codestar-style field schema (key/type=checkbox/template=inputYesNoCheckbox). FF Pro's React UI for the Payment Methods tab expects a different shape ({ label, fields: [{ settings_key, type, ... }] }), so the section was silently dropped. Rewrite get_fields() to use settings_key + type values (yes-no-checkbox, input-radio, input-text, input-checkboxes) per the FF Pro convention seen in AuthorizeNetHandler::getGlobalFields() and friends.

2. Save flow drops user edits. FF Pro's savePaymentMethodSettings writes to fluentform_payment_settings_chip; the runtime reads from fluent_form_chip_settings. Without a bridge, any value the merchant enters through the new UI is invisible to the processor. Register fluentform/payment_method_settings_save_chip in the handler to mirror the payload into our canonical option. FF Pro's default save still runs in parallel (harmless duplicate).

3. Form render 'No activated payment method found' on upgrade. The global is_active toggle defaulted to 'no' in global_defaults(); resolve_legacy_is_active() only flipped it to 'yes' when the legacy secret-key was set, so users with per-form credentials (no global key) had to re-check the toggle manually. And forms whose payment_method field was created in 1.x but never re-saved through the form editor in 2.0 still had chip missing or enabled='no' in their form_fields JSON. Loosen resolve_legacy_is_active so any non-empty legacy option flips is_active='yes' (1.x had no master enable toggle, the option existing was the signal). Add a new migrate_per_form_payment_methods() step to phase 1 that walks every form with a payment_method field and sets settings.payment_methods[chip].enabled='yes' (preserves explicit 'no' choices). Extend phase 2 verify with a spot-check that at least one such form has chip enabled.

CLAUDE.md: document the FF Pro field schema, the save mirror, and the per-form upgrade step.

Co-Authored-By: Claude <noreply@anthropic.com>
The WordPress coding standards check flagged:
- Empty IF statement (the old code had a no-op if/elseif where the
  first branch only contained a comment). Restructured to a single
  guard that combines the two conditions.
- Equals sign not aligned with the other assignments in the block
  (the $methods['chip'] = array() line had one space; the others
  use 13 to align at column 30).

Co-Authored-By: Claude <noreply@anthropic.com>
Fixes the off-by-one PHPCS warning (expected 13 spaces, found 12).

Co-Authored-By: Claude <noreply@anthropic.com>
Two real bugs that the WordPress Plugin Check CI didn't catch (it
only runs the activation step on a clean install, not the live
wptest site):

1. includes/class-chip-fluent-forms.php references the bootstrap
   file as 'admin/chip-for-fluent-forms-handlerbootstrap.php'
   (no hyphen before 'bootstrap'), but the file on disk is named
   'admin/chip-for-fluent-forms-handler-bootstrap.php' (with the
   hyphen). The include silently failed, so the bootstrap function
   was never defined, the push filter was never registered, and
   'available_methods' never contained 'chip' — which is why the
   Payment Methods tab never rendered the CHIP section.

   The typo was introduced in commit b69ff7e (the synchronize_refund
   removal / webhook-setup cleanup) and has been on the branch since.

   Fix: rename the include path to match the file.

2. Once the typo is fixed, the bootstrap fires, instantiates the
   handler, and the handler constructor tries to 'new
   Chip_Fluent_Forms_Settings_Page()' (line 69). That class is only
   loaded by the is_admin() branch of Chip_Fluent_Forms::includes(),
   so on a non-admin request (wp-login.php, public form render, REST
   API), the class doesn't exist and PHP 8 raises an Uncaught Error
   'Class not found' — which kills the entire request. This is why
   the site 500'd once the bootstrap started firing.

   Fix: lazy-instantiate the admin-only objects in private getters
   (get_settings_page / get_form_settings). The handler's __construct
   no longer references any admin-only class. The handlers are only
   created when getGlobalFields() runs (on the FF Pro admin UI side,
   where the class will be loaded).

Surfaced by the upgrade on the wptest.wanzul-hosting.com test site
when the user reported the Payment Methods tab not rendering. The
plugin-check CI only ran the activation step, which doesn't exercise
the bootstrap's instantiation path.

Co-Authored-By: Claude <noreply@anthropic.com>
Fluent Forms Pro's React form-settings UI does not currently render
per-payment-method subkeys, so the per-form 'Customize for form #N'
panel that class-chip-fluent-forms-form-settings adds to the
fluentform/form_payment_settings filter is invisible in the form
editor. The data path is wired (per-form _chip_payment_settings
rows, the runtime read in for_form(), the migration populating
is_active='yes' for upgrading 1.x users) but the merchant has no UI
to set per-form Brand ID / Secret Key through WP admin.

Add a standalone WordPress admin submenu page under the Fluent
Forms menu (slug 'chip-form-settings') that lets the merchant list
all FF forms and edit per-form credentials through a standard WP
Settings API form. Persists via Chip_Fluent_Forms_Settings::save_form()
and fires the 'ff_chip_form_settings_saved' action.

The per-form page is wired through add_admin_hooks() in the bootstrap
class, only registered when is_admin() is true. Add a discoverability
link from the standalone settings page. CLAUDE.md updated to
document the new page and the actual per-form data path.

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace short ternary '$form ?: null' with explicit '$form ? $form : null'
  (WordPress.NamingConventions.PrefixAllGlobals disallows short ternaries).
- Align const block ($MENU_SLUG / $SAVE_ACTION / $NONCE_ACTION / $SETTINGS_GROUP)
  so the = signs are at the same column.
- Align $form_id / $is_customized / $edit_url in the list view to a
  single = column.
- Replace aligned-but-WP-non-conformant 'key     => value' style with
  the WordPress.Array.MultipleStatementAlignment-aligned style (single
  space, arrows in a single column).

Co-Authored-By: Claude <noreply@anthropic.com>
The previous fix only added spaces to $form_id and $edit_url, but
$is_customized was still at col 15 with 1 space. PHPCS wants all
three aligned to the longest key + 1.

Co-Authored-By: Claude <noreply@anthropic.com>
PHPPCS computes alignment within a block based on the longest key
($is_customized, 13 chars), so target = col 15. That means
$form_id (8) and $edit_url (8) each need 6 spaces of padding.

Co-Authored-By: Claude <noreply@anthropic.com>
…1/6)

The WordPress-Extra EqualsAlign rule gives the first assignment in a
block 1 extra space. So for a 3-line block with keys form_id (8),
is_customized (13), edit_url (8), the target is:

  form_id       = ...    (8 + 7 spaces + = = col 16)
  is_customized = ...    (13 + 1 space + = = col 15)
  edit_url      = ...    (8 + 6 spaces + = = col 15)

Co-Authored-By: Claude <noreply@anthropic.com>
FF Pro's React form-settings UI does not surface per-payment-method
subkeys, so the merchant has no in-editor way to find the new
per-form admin page. Add a dismissible admin notice that appears
on the Fluent Forms settings page (page=fluent_forms_settings)
when the URL hash contains '#/payment' (the Payment Methods tab),
pointing the merchant to admin.php?page=chip-form-settings.

Co-Authored-By: Claude <noreply@anthropic.com>
…ent_forms

The FF Pro parent menu gates access on the
fluentform_dashboard_access cap, which the administrator role
does not automatically have. So a submenu under fluent_forms
returned 'Sorry, you are not allowed to access this page' for
stock admin users.

Register as a top-level menu (add_menu_page) with the
manage_options cap. The URL is the same
wp-admin/admin.php?page=chip-form-settings the merchant has been
trying, and the menu shows up in the WP admin sidebar as a new
top-level 'CHIP Per-Form' entry.

Co-Authored-By: Claude <noreply@anthropic.com>
WordPress.Security.ValidatedSanitizedInput.InputNotSanitized requires
wp_unslash() + a sanitization function on superglobal reads. Use
esc_url_raw() which both unslashes and sanitizes the URL.

Co-Authored-By: Claude <noreply@anthropic.com>
…a dedicated admin page

The user pointed out that Method Label and Notes are already
editable on the per-form payment_method field in FF Pro's form
editor, and that per-form Brand ID / Secret Key should live in
the same place. Move the per-form credentials from the dedicated
admin page (admin.php?page=chip-form-settings, which the user
disliked) onto the payment_method field's per-method settings,
rendered by FF Pro's own React UI.

Changes:

* push_payment_method() in class-chip-fluent-forms-handler.php
  now declares the full set of per-form credential fields
  (is_active, brand_id, secret_key, payment_mode, due_strict,
  due_strict_timing, payment_method_whitelist) alongside the
  existing option_label and notes. Field shape uses the FF Pro
  schema (settings_key / type / label / options / info_help) so
  the React form-settings UI renders them in the per-method
  sub-panel.

* create_purchase() in class-chip-fluent-forms-purchase.php
  computes the effective config from three layers in priority
  order: per-form method field settings (highest), the migration
  row in _chip_payment_settings (fallback), and the global
  fluent_form_chip_settings (lowest). When the per-form method
  field's is_active toggle is off or unset, the credential keys
  fall through to the lower layers.

* class-chip-fluent-forms-form-settings.php: drop the
  fluentform/after_save_form_settings hook and the
  save_per_form_settings() handler. The per-form method field
  saves into form_fields directly. The render filter
  (fluentform/form_payment_settings) stays for downstream
  integrations and as a future extension point.

* Delete the dedicated per-form admin page
  (class-chip-fluent-forms-per-form-page.php) and all its
  wiring in class-chip-fluent-forms.php (the add_admin_hooks()
  method, the admin_notices discoverability hook, the
  wp-admin/admin.php?page=chip-form-settings top-level menu).
  Net -323 lines.

* Drop the discoverability link from the standalone settings
  page (it pointed at the deleted per-form admin page).

* CLAUDE.md updated: Settings resolution section now
  documents the three-layer precedence; admin section no
  longer lists the deleted per-form page; the per-form
  customize bullet points at the form editor's
  payment_method field.

Backward compat: 1.x → 2.0 upgraded users with _chip_payment_settings
rows continue to work — the runtime falls through to layer 2
when the per-form method field has no override. New 2.x merchants
can edit credentials directly in the form editor.

Co-Authored-By: Claude <noreply@anthropic.com>
* Replace '$default' parameter name with '$fallback' in the
  $pfm_value closure (WordPress.NamingConventions.PrefixAllGlobals
  warns about using reserved keyword 'default' as a param name).
* Realign the inner '=>' arrows in the new push_payment_method
  sub-arrays. Each sub-array's longest key determines the column;
  previous commit had inconsistent alignment because the long
  'checkbox_label' key in the 'customize' sub-array forced the
  other sub-arrays to over-pad 'settings_key' / 'type' / 'value'
  while sub-arrays without 'checkbox_label' were under-padded.

Co-Authored-By: Claude <noreply@anthropic.com>
PHPCS WordPress.Arrays.ArrayDeclaration wants the longest
expected key (payment_method_whitelist, 23 chars) + 2 spaces
before '=>'. So all keys in the block need 1 more space than
they had.

Co-Authored-By: Claude <noreply@anthropic.com>
The credential block's outer keys (option_label, notes, customize,
brand_id, secret_key, payment_mode, due_strict, due_strict_timing,
payment_method_whitelist) are a single alignment group per
WordPress.Arrays.ArrayDeclaration. The longest key is
payment_method_whitelist (24 chars), so target = col 27 (key +
2 spaces + =). Each shorter key gets (24 - len + 2) spaces.

Also fix the inner arrow alignment in option_label and notes
sub-arrays (longest inner key is help_text, 9 chars).

Co-Authored-By: Claude <noreply@anthropic.com>
PHPCS wants the longest outer key (payment_method_whitelist, 24
chars) + 1 space. So target col 26. Each shorter key gets
(24 - len + 1) spaces. Previous commit had + 2 spaces. Subtract 1
from each.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant