JezK
Edit File: api-base.php
<?php /** * API base. * * @package SureRank; * @since 1.0.0 */ namespace SureRank\Inc\API; use SureRank\Inc\Functions\Helper; use SureRank\Inc\Functions\Sanitize; use SureRank\Inc\Meta_Variables\Site; use WP_Error; use WP_REST_Controller; use WP_REST_Request; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } /** * Api_Base * * @since 1.0.0 */ abstract class Api_Base extends WP_REST_Controller { /** * Endpoint namespace. * * @var string */ protected $namespace = 'surerank/v1'; /** * Constructor * * @since 1.0.0 */ public function __construct() { } /** * Get API namespace. * * @since 1.0.0 * @return string */ public function get_api_namespace() { return $this->namespace; } /** * Validate the nonce for REST API requests, then apply the * capability + Pro filter chain via check_permission_for_action(). * * The `wp_rest` nonce protects cookie-authenticated (browser) requests * against CSRF and is required for them. Requests authenticated with an * Application Password are not cookie-based and cannot be CSRF'd, so the * nonce does not apply to them; WordPress core itself exempts them in * rest_cookie_check_errors(). We detect that case via core's * rest_get_authenticated_app_password() (set during authentication, before * this callback runs) and skip the nonce only then, so a server-to-server * request with an Application Password can write while browser sessions * still require a valid nonce. The capability check always runs. * * @param WP_REST_Request<array<string, mixed>> $request The REST request object. * @return bool|WP_Error True if valid, WP_Error if invalid. * @since 1.9.0 */ public function validate_permission( $request ) { // Whether this request was authenticated with an Application Password. $app_password_uuid = function_exists( 'rest_get_authenticated_app_password' ) ? rest_get_authenticated_app_password() : null; // Only enforce the nonce for non-Application-Password (e.g. browser/cookie) auth. if ( empty( $app_password_uuid ) ) { // Retrieve the nonce from the request header. $nonce = $request->get_header( 'X-WP-Nonce' ); // Check if nonce is null or empty. if ( empty( $nonce ) || ! is_string( $nonce ) ) { return new WP_Error( 'surerank_nonce_verification_failed', __( 'Nonce is missing.', 'surerank' ), [ 'status' => rest_authorization_required_code() ] ); } // Verify the nonce. if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) { return new WP_Error( 'surerank_nonce_verification_failed', __( 'Nonce is invalid.', 'surerank' ), [ 'status' => rest_authorization_required_code() ] ); } } return self::check_permission_for_action( $request ); } /** * Apply SureRank's capability + Pro-filter permission chain for * the given request. * * Extracted from validate_permission() so the AJAX fallback in * inc/ajax/save-endpoints.php can enforce the exact same policy * that Pro plugins layer on top of the REST endpoints via the * `surerank_rest_api_permission` and * `surerank_rest_api_permission_check` filters. AJAX must not be * a back door around a Pro licensing or role policy that blocks * the REST endpoint. * * Callers are responsible for verifying request authenticity * (X-WP-Nonce for REST, `_wpnonce` via check_ajax_referer() for * AJAX) before invoking this helper. * * @param WP_REST_Request<array<string, mixed>> $request The REST request object (or a synthetic request built by the AJAX handler mirroring the equivalent REST route). * @return bool|WP_Error True on pass, WP_Error on denial. * @since 1.7.2 */ public static function check_permission_for_action( $request ) { /** * Filter to allow Pro plugin or extensions to override permission checks. * * @since 1.6.4 * @param bool|WP_Error $has_permission True to allow access, WP_Error to deny with custom message, false to use default check. * @param WP_REST_Request $request The REST request object. */ $has_permission = apply_filters( 'surerank_rest_api_permission', false, $request ); if ( is_wp_error( $has_permission ) ) { return $has_permission; } // If filter didn't handle permission (Pro not active), fall back to admin capability check. if ( true !== $has_permission ) { if ( ! current_user_can( 'manage_options' ) ) { return new WP_Error( 'surerank_rest_cannot_access', __( 'You do not have permission to perform this action.', 'surerank' ), [ 'status' => rest_authorization_required_code() ] ); } } /** * Filter to allow additional permission checks (e.g., license validation). * * This runs AFTER the user capability check has passed. * * @since 1.6.4 * @param bool|WP_Error $permission_status True if permission granted, WP_Error to deny. * @param WP_REST_Request $request The REST request object. */ $permission_status = apply_filters( 'surerank_rest_api_permission_check', true, $request ); if ( is_wp_error( $permission_status ) ) { return $permission_status; } return true; } /** * Get favicon image URL. * * @since 1.0.0 * @return string */ public function get_favicon() { return esc_url( get_site_icon_url( 16 ) ); } /** * Get site variables * * @since 1.0.0 * @return array<string, mixed> */ public function get_site_variables() { $site = Site::get_instance(); $site_variables = $site->get_all_values(); $variables = []; // Add favicon icon if variable is available and should be a array. if ( ! empty( $site_variables ) && is_array( $site_variables ) ) { // Keep in key and array format. foreach ( $site_variables as $key => $value ) { // Verify that value should be an array. if ( ! isset( $value['value'] ) ) { continue; } $variables[ $key ] = $value['value']; } $variables['favicon'] = $this->get_favicon(); $variables['title'] = __( 'Sample Post', 'surerank' ); $variables['current_year'] = gmdate( 'Y' ); $variables['current_month'] = gmdate( 'F' ); } else { $variables = []; } $variables['page'] = Helper::format_paged_info( 2, 5 ); return $variables; } /** * Sanitize object data * * @since 1.0.0 * @param array<string, mixed>|array<int, string> $data Data to sanitize. * @return array<string, mixed>|array<int, string> */ public function sanitize_array_data( $data ) { return Sanitize::sanitize_request_data( $data ); } }
https://personalfinance365.com/post-type-page-sitemap-1.xml
2026-09-27T18:16:25+05:30
https://personalfinance365.com/post-type-post-sitemap-1.xml
2026-09-27T18:16:25+05:30
https://personalfinance365.com/post-type-post-sitemap-2.xml
2026-09-27T18:16:25+05:30
https://personalfinance365.com/taxonomy-type-category-sitemap-1.xml
2026-09-27T18:16:25+05:30
https://personalfinance365.com/taxonomy-type-post_tag-sitemap-1.xml
2026-09-27T18:16:25+05:30
https://personalfinance365.com/taxonomy-type-post_tag-sitemap-2.xml
2026-09-27T18:16:25+05:30