'GET', 'callback' => 'a1tools_rest_get_variables', 'permission_callback' => '__return_true', ) ); // Clear cache (requires admin). register_rest_route( 'a1-tools/v1', '/site-variables/clear-cache', array( 'methods' => 'POST', 'callback' => 'a1tools_rest_clear_cache', 'permission_callback' => function () { return current_user_can( 'manage_options' ); }, ) ); // Yoast meta endpoints. register_rest_route( 'a1-tools/v1', '/yoast-meta/(?P\d+)', array( 'methods' => 'POST', 'callback' => 'a1tools_update_yoast_meta', 'permission_callback' => function () { return current_user_can( 'edit_posts' ); }, 'args' => array( 'id' => array( 'description' => 'Post ID', 'type' => 'integer', 'required' => true, 'validate_callback' => function ( $param ) { return is_numeric( $param ) && $param > 0; }, ), ), ) ); register_rest_route( 'a1-tools/v1', '/yoast-meta/(?P\d+)', array( 'methods' => 'GET', 'callback' => 'a1tools_get_yoast_meta', 'permission_callback' => function () { return current_user_can( 'edit_posts' ); }, 'args' => array( 'id' => array( 'description' => 'Post ID', 'type' => 'integer', 'required' => true, 'validate_callback' => function ( $param ) { return is_numeric( $param ) && $param > 0; }, ), ), ) ); // Cache invalidation webhook (authenticated via shared secret). register_rest_route( 'a1-tools/v1', '/invalidate-cache', array( 'methods' => 'POST', 'callback' => 'a1tools_rest_invalidate_cache', 'permission_callback' => function ( WP_REST_Request $request ) { // Validate via shared secret in header. $secret = $request->get_header( 'X-Cache-Secret' ); if ( empty( $secret ) ) { $secret = ''; } $expected = get_option( 'a1tools_form_secret', '' ); if ( empty( $expected ) || empty( $secret ) ) { return false; } return hash_equals( $expected, $secret ); }, ) ); } add_action( 'rest_api_init', 'a1tools_register_rest_routes' ); /** * REST: Get site variables. * * @since 1.0.0 * @return WP_REST_Response|WP_Error Response object. */ function a1tools_rest_get_variables() { $variables = a1tools_get_site_variables(); if ( null === $variables ) { return new WP_Error( 'fetch_error', __( 'Could not fetch site variables', 'a1-tools' ), array( 'status' => 500 ) ); } return new WP_REST_Response( array( 'success' => true, 'variables' => $variables, 'cached' => false !== get_transient( A1TOOLS_CACHE_KEY ), ), 200 ); } /** * REST: Clear variables cache. * * @since 1.0.0 * @return WP_REST_Response Response object. */ function a1tools_rest_clear_cache() { a1tools_clear_cache(); return new WP_REST_Response( array( 'success' => true, 'message' => __( 'Cache cleared', 'a1-tools' ), ), 200 ); } /** * REST: Invalidate cache via webhook. * * Called externally by the A1 Tools platform when site variables or * business data changes, so WordPress sites can bust their caches * without waiting for the transient to expire. * * @since 2.1.0 * @param WP_REST_Request $request The request object. * @return WP_REST_Response Response object. */ function a1tools_rest_invalidate_cache( $request ) { a1tools_clear_cache(); return new WP_REST_Response( array( 'success' => true, 'message' => 'Cache cleared', 'cleared_at' => current_time( 'mysql' ), ), 200 ); }