if ( $this->method_exists_in_current_class( $method_args ) ) { $config['args'] = $this->{$method_args}(); } return $config; } /** * maybe_add_response_to_swagger * * If the function method /(rest-method)_response_callback/ exists, adds the filter * /swagger_api_response_(namespace with slashes replaced with underscores)_(endpoint with slashes replaced with underscores)/ * with the aforementioned function method. * This filter is used with the WP API Swagger UI plugin to create documentation for the API. * The value being passed is an array: [ '200' => ['description' => 'OK'], '404' => ['description' => 'Not Found'], '400' => ['description' => 'Bad Request'] ] * @param string $method REST method name */ public function maybe_add_response_to_swagger( string $method ): void { $method_name = strtolower( $method ); $method_response_callback = $method_name . '_response_callback'; if ( $this->method_exists_in_current_class( $method_response_callback ) ) { $response_filter = $method_name . '_' . str_replace( '/', '_', $this->namespace . '/' . $this->get_endpoint() ); add_filter( 'swagger_api_responses_' . $response_filter, [ $this, $method_response_callback ] ); } } /** * build_endpoint_method_config * * Builds a configuration array for the endpoint based on the presence of the callback, permission, additional parameters, * and response to Swagger member functions. * @param string $method The REST method for the endpoint * * @return array The endpoint configuration for the method specified by the parameter */ private function build_endpoint_method_config( string $method ): array { $config = [ 'methods' => $method, 'callback' => $this->get_callback_method( $method ), 'permission_callback' => $this->get_permission_callback_method( $method ), ]; $config = $this->maybe_add_args_to_config( $method, $config ); return $config; } /** * method_exists_in_current_class * * Uses reflection to check if this class has the /method/ method. * @param string $method The name of the method being checked. * * @return bool TRUE if the class has the /method/ method, FALSE otherwise. */ private function method_exists_in_current_class( string $method ): bool { $class_name = get_class( $this ); try { $reflection = new ReflectionClass( $class_name ); } catch ( \ReflectionException $e ) { return false; } if ( ! $reflection->hasMethod( $method ) ) { return false; } $method_ref = $reflection->getMethod( $method ); return ( $method_ref && $class_name === $method_ref->class ); } /** * permission_callback * Permissions callback fallback for the endpoint * Gets the current user ID and sets the /current_user_id/ property. * If the /auth/ property is set to /true/ will make sure that the user is logged in (has an id greater than 0) * * @param WP_REST_Request $request unused * * @return bool TRUE, if permission granted, FALSE otherwise */ public function permission_callback( WP_REST_Request $request ): bool { // try to get current user $this->current_user_id = get_current_user_id(); if ( $this->auth ) { return $this->current_user_id > 0; } return true; } /** * callback * Fallback callback function, returns a response consisting of the string /ok/. * * @param WP_REST_Request $request unused * * @return WP_REST_Response Default Response of the string 'ok'. */ public function callback( WP_REST_Request $request ): WP_REST_Response { return rest_ensure_response( [ 'OK' ] ); } /** * respond_wrong_method * * Creates a WordPress error object with the /rest_no_route/ code and the message and code supplied or the defaults. * @param null $message The error message for the wrong method. * Optional. * Defaults to null, which makes sets the message to /No route was found matching the URL and request method/ * @param int $code The HTTP status code. * Optional. * Defaults to 404 (Not found). * * @return WP_Error The WordPress error object with the error message and status code supplied */ public function respond_wrong_method( $message = null, int $code = 404 ): WP_Error { if ( null === $message ) { $message = 'No route was found matching the URL and request method'; } return new WP_Error( 'rest_no_route', $message, [ 'status' => $code ] ); } /** * respond_with_code * Create a new /WP_REST_Response/ object with the specified data and HTTP response code. * * @param array|null $data The data to return in this response * @param int $code The HTTP response code. * Optional. * Defaults to 200 (OK). * * @return WP_REST_Response The WordPress response object loaded with the data and the response code. */ public function respond_with_code( ?array $data = null, int $code = 200 ): WP_REST_Response { return new WP_REST_Response( $data, $code ); } /** * get_user_from_request * * Returns the current user object. * Depends on the property /current_user_id/ to be set. * @return WP_User|false The user object or false if not found or on error. */ public function get_user_from_request() { return get_user_by( 'id', $this->current_user_id ); } /** * get_arguments * Rest Endpoint extra arguments * @return array Additional arguments for the route configuration */ public function get_arguments(): array { return []; } /** * get_endpoint * Rest route Endpoint * @return string Endpoint uri component (comes after the route namespace) */ abstract public function get_endpoint(): string; /** * get_name * @return string The name of the route */ abstract public function get_name(): string; public function get_self_url( $endpoint = '' ): string { return rest_url( $this->namespace . '/' . $endpoint ); } public function respond_success_json( $data = [] ): WP_REST_Response { return new WP_REST_Response([ 'success' => true, 'data' => $data, ]); } /** * @param array{message: string, code: string} $data * * @return WP_Error */ public function respond_error_json( array $data ): WP_Error { if ( ! isset( $data['message'] ) || ! isset( $data['code'] ) ) { _doing_it_wrong( __FUNCTION__, esc_html__( 'Both `message` and `code` keys must be provided', 'image-optimization' ), '1.0.0' ); // @codeCoverageIgnore } return new WP_Error( $data['code'] ?? 'internal_server_error', $data['message'] ?? esc_html__( 'Internal server error', 'image-optimization' ), ); } public function verify_nonce( $nonce = '', $name = '' ) { if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $nonce ) ), $name ) ) { return $this->respond_error_json([ 'message' => esc_html__( 'Invalid nonce', 'image-optimization' ), 'code' => 'bad_request', ]); } } public function verify_nonce_and_capability( $nonce = '', $name = '', $capability = 'manage_options' ) { $this->verify_nonce( $nonce, $name ); if ( ! current_user_can( $capability ) ) { return $this->respond_error_json([ 'message' => esc_html__( 'You do not have sufficient permissions to access this data.', 'image-optimization' ), 'code' => 'bad_request', ]); } } }
Fatal error: Uncaught Error: Class "ImageOptimization\Classes\Route" not found in /htdocs/wp-content/plugins/image-optimization/modules/stats/classes/route-base.php:12 Stack trace: #0 /htdocs/wp-content/plugins/image-optimization/plugin.php(79): include() #1 /htdocs/wp-content/plugins/image-optimization/modules/stats/rest/get-stats.php(15): ImageOptimization\Plugin->autoload('ImageOptimizati...') #2 /htdocs/wp-content/plugins/image-optimization/plugin.php(79): include('/htdocs/wp-cont...') #3 /htdocs/wp-content/plugins/image-optimization/classes/module-base.php(331): ImageOptimization\Plugin->autoload('ImageOptimizati...') #4 /htdocs/wp-content/plugins/image-optimization/modules/stats/module.php(31): ImageOptimization\Classes\Module_Base->register_routes() #5 /htdocs/wp-content/plugins/image-optimization/classes/module-base.php(83): ImageOptimization\Modules\Stats\Module->__construct() #6 /htdocs/wp-content/plugins/image-optimization/includes/modules-manager.php(46): ImageOptimization\Classes\Module_Base::instance() #7 /htdocs/wp-content/plugins/image-optimization/plugin.php(90): ImageOptimization\Manager->__construct() #8 /htdocs/wp-content/plugins/image-optimization/plugin.php(105): ImageOptimization\Plugin->includes() #9 /htdocs/wp-content/plugins/image-optimization/plugin.php(47): ImageOptimization\Plugin->__construct() #10 /htdocs/wp-content/plugins/image-optimization/plugin.php(109): ImageOptimization\Plugin::instance() #11 /htdocs/wp-content/plugins/image-optimization/image-optimization.php(210): require_once('/htdocs/wp-cont...') #12 /htdocs/wp-includes/class-wp-hook.php(341): ImageOptimization->init('') #13 /htdocs/wp-includes/class-wp-hook.php(365): WP_Hook->apply_filters('', Array) #14 /htdocs/wp-includes/plugin.php(522): WP_Hook->do_action(Array) #15 /htdocs/wp-settings.php(593): do_action('plugins_loaded') #16 /htdocs/wp-config.php(102): require_once('/htdocs/wp-sett...') #17 /htdocs/wp-load.php(50): require_once('/htdocs/wp-conf...') #18 /htdocs/wp-blog-header.php(13): require_once('/htdocs/wp-load...') #19 /htdocs/index.php(17): require('/htdocs/wp-blog...') #20 {main} thrown in /htdocs/wp-content/plugins/image-optimization/modules/stats/classes/route-base.php on line 12