woocommerce-paypal-payments/tests/PHPUnit/Settings/Data
David Stone f69ff9b96a fix(settings): coerce stored values in typed-bool getters and vault_enabled migration
SettingsModel exposes ten typed-bool getters (get_save_paypal_and_venmo,
get_authorize_only, get_capture_virtual_orders, get_instant_payments_only,
get_enable_contact_module, get_save_card_details, get_enable_pay_now,
get_enable_logging, get_stay_updated, get_payment_level_processing) that
return $this->data[$key] directly. On PHP 8.x this throws

    Return value must be of type bool, string returned

whenever the stored option holds a non-bool value -- the shape produced by
the legacy classic-WooCommerce 'yes'/'no' settings format, by direct DB
writes, and by some third-party import/export tools that re-serialise
options without preserving scalar types.

Reported in production for get_save_paypal_and_venmo, which fatals during
WcSubscriptionsModule boot and prevents the PPCP REST routes (including
the webhook endpoint at /wp-json/paypal/v1/incoming) from registering.

Two-part defence:

1. Wrap each typed-bool getter with the existing DataSanitizer::sanitize_bool()
   (filter_var FILTER_VALIDATE_BOOLEAN). Pure pass-through for real bools;
   correctly handles 'yes'/'no'/'1'/'0'/'true'/'false'/'on'/'off' strings
   that were observed in production. Each getter also gets a per-field
   default via ?? so a missing key falls back to the value declared in
   get_defaults() instead of producing a PHP warning.

2. Add an explicit 'vault_enabled' case to SettingsTabMigration so the
   legacy 'yes'/'no' string is coerced to bool before from_array() hands
   it to set_save_paypal_and_venmo(bool $save). Without this the
   migration either TypeErrors on the typed setter (strict mode) or
   persists 'no' as true (weak mode, where every non-empty non-'0'
   string casts to true).

Tests:
- New tests/PHPUnit/Settings/Data/SettingsModelTest covers every bool
  getter against 14 input shapes (real bools, legacy yes/no strings,
  '1'/'0', 'true'/'false', 'on'/'off', empty/unrecognised strings,
  integers), plus a per-field 'getter returns declared default when
  option is empty' matrix.
- Extends SettingsTabMigrationTest with vault_enabled coverage for the
  same 14 shapes, asserting both the resulting type and value.

Full PPCP Settings + PpcpSettings suites pass (240 tests, 304 assertions).
2026-05-21 15:32:24 -06:00
..
SettingsModelTest.php fix(settings): coerce stored values in typed-bool getters and vault_enabled migration 2026-05-21 15:32:24 -06:00
SettingsProviderTest.php Add test suite for the new settings migration 2026-03-12 17:56:26 +01:00