\WP_REST_Server::CREATABLE, 'callback' => __NAMESPACE__ . '\harvify_cookie_rest_consent', // PUBLIC on purpose: the person consenting is an anonymous visitor, // and the page carrying the banner may be served from a page cache, // where a nonce would be stale. Nothing is read back and the input is // reduced to known category keys, a UUID and a version string. 'permission_callback' => '__return_true', ) ); // Geo-targeting: must THIS visitor be asked? Read-only. register_rest_route( 'harvify-cookie/v1', '/geo', array( 'methods' => \WP_REST_Server::READABLE, 'callback' => __NAMESPACE__ . '\harvify_cookie_rest_geo', 'permission_callback' => '__return_true', ) ); } /** * Record a consent choice. * * Until 1.0.22 the banner never reached this route (it was never told the * URL), and when called the route minted a NEW id each time, so a visitor who * changed their mind became a second record instead of an updated one. It now * keeps the visitor's own consent id when it is a valid UUID. * * @param \WP_REST_Request $request Request. * @return \WP_REST_Response */ function harvify_cookie_rest_consent( $request ) { $params = (array) $request->get_json_params(); $categories = isset( $params['categories'] ) ? array_map( 'sanitize_key', (array) $params['categories'] ) : array(); $client_id = isset( $params['consentId'] ) ? sanitize_text_field( (string) $params['consentId'] ) : ''; $consent_id = wp_is_uuid( $client_id ) ? $client_id : wp_generate_uuid4(); $data = array( 'consent_id' => $consent_id, 'categories' => array_values( array_intersect( $categories, array_keys( Banner::CATEGORIES ) ) ), 'timestamp' => time(), ); if ( function_exists( 'harvify_cookie_pro_log_consent' ) ) { harvify_cookie_pro_log_consent( $data, $request ); } return rest_ensure_response( array( 'success' => true, 'consent_id' => $consent_id, 'cookie_name' => Banner::cookie_name(), 'data' => $data, ) ); } /** * Must this visitor be asked for consent? * * Answered per request and never cached: a page cache must not hand one * visitor's answer to the next. * * @return \WP_REST_Response */ function harvify_cookie_rest_geo() { $required = function_exists( 'harvify_cookie_consent_required' ) ? harvify_cookie_consent_required() : true; $response = rest_ensure_response( array( 'required' => (bool) $required ) ); $response->header( 'Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0' ); return $response; }