` * name the renderer emits via * `wp_nonce_field($action, $name)` and the handler reads * from `$_POST`. * - `FORM_FIELD_PREFIX` — the top-level `$_POST` key under * which every settings field is namespaced * (`affilun_settings[rendering][default_template]` etc.). The * parser reads `$_POST[FORM_FIELD_PREFIX]` as the root of * the form payload. * - `FORM_ACTION` — the `admin-post.php?action=...` value * that drives WordPress's `admin_post_{action}` action * dispatch. The renderer emits it as the `` value; the {@see \Affilun\Presentation\Admin\AdminServiceProvider} * subscribes the corresponding `admin_post_affilun_save_settings` * hook. * * The {@see self::validateNonce()} helper exists so the POST * handler ({@see SaveSettingsHandler}) can perform nonce * verification through an injected closure rather than calling * `wp_verify_nonce()` directly. That keeps the handler fully * testable in pure-unit mode where WordPress is not loaded; * the production wiring forwards to `wp_verify_nonce()` * verbatim. Per §6.4 the nonce value itself is never logged. * * @package Affilun\Presentation\Admin\Page */ declare(strict_types=1); namespace Affilun\Presentation\Admin\Page; /** * Static helper carrying the §13.10 save-form literals (nonce * action / nonce field / form-field prefix / admin-post action). * * See the file-level docblock for how the §13 Settings admin * page's renderer / parser / POST handler share these literals * to round-trip a save request through `admin-post.php`. */ final class SettingsFormToken { /** * Action literal passed to `wp_create_nonce()` / * `wp_verify_nonce()`. */ public const NONCE_ACTION = 'affilun_settings_save'; /** * `` name the renderer emits via * `wp_nonce_field()` and the handler reads from `$_POST`. */ public const NONCE_FIELD = '_affilun_settings_nonce'; /** * Top-level `$_POST` key under which every settings field is * namespaced. */ public const FORM_FIELD_PREFIX = 'affilun_settings'; /** * `admin-post.php?action=...` value driving WordPress's * `admin_post_{action}` dispatch. */ public const FORM_ACTION = 'affilun_save_settings'; /** * Action literal passed to `wp_create_nonce()` / `wp_verify_nonce()` * for the Amazon bulk resync button. */ public const AMAZON_RESYNC_NONCE_ACTION = 'affilun_amazon_resync'; /** * Nonce field name for the Amazon bulk resync button. */ public const AMAZON_RESYNC_NONCE_FIELD = '_affilun_amazon_resync_nonce'; /** * `admin-post.php?action=...` value for Amazon bulk resync. */ public const AMAZON_RESYNC_FORM_ACTION = 'affilun_resync_amazon_products'; /** * Return the nonce action literal. */ public static function nonceAction(): string { return self::NONCE_ACTION; } /** * Return the nonce-field name literal. */ public static function nonceField(): string { return self::NONCE_FIELD; } /** * Return the form-field prefix literal. */ public static function formFieldPrefix(): string { return self::FORM_FIELD_PREFIX; } /** * Return the `admin-post.php` action literal. */ public static function formAction(): string { return self::FORM_ACTION; } /** * Validate a nonce value against {@see self::NONCE_ACTION} * via the supplied verifier closure. * * The closure abstracts `wp_verify_nonce()` so tests can * inject fake verifiers without touching globals; production * wiring forwards the call verbatim. * * @param callable $verifier Verifier closure. Signature: * `function (string $action, string $value): bool`. * @param string $nonceValue Nonce value to verify. * * @phpstan-param callable(string, string): bool $verifier */ public static function validateNonce( callable $verifier, string $nonceValue ): bool { return (bool) $verifier( self::NONCE_ACTION, $nonceValue ); } }