get_param( 'name' )`, * which core has already parsed off the route by this point - the slug * arrives as a literal slash (`charitable/get-donor`), never a `~` or any * other encoded separator. There is no tilde anywhere in core's REST API. */ add_filter( 'rest_request_after_callbacks', array( Charitable_Abilities::get_instance(), 'intercept_gated_ability' ), 9, 3 ); add_filter( 'rest_request_after_callbacks', array( Charitable_Abilities::get_instance(), 'set_error_http_status' ), 10, 3 ); /* * Usage counting. Three seams, because core gives us three different facts and * no single hook carries all of them: * * - `wp_ability_invoked` fires for every call, and the handler above records * both the invocation and a permission denial from it. * - `wp_after_execute_ability` fires ONLY on success — a WP_Error out of * do_execute(), or a failed output validation, returns from execute() before * it. There is no "ability failed" action in core, which is why `failed` is * derived rather than counted. * - The write gate records its own refusals from inside * Charitable_Abilities_Registrar::gate_write_callback(), where it already * knows it is refusing. * * Counts accumulate in memory and land in one option write per request on * `shutdown`. */ add_action( 'wp_after_execute_ability', array( 'Charitable_Abilities_Usage', 'record_success' ), 10, 1 ); add_action( 'shutdown', array( 'Charitable_Abilities_Usage', 'flush' ) );