Linux webm002.cluster126.gra.hosting.ovh.net 6.18.39-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Tue Jul 21 12:03:15 CEST 2026 x86_64
/
home
/
ariannadhf
/
www
/
wp-content
/
plugins
/
simple-history
/
inc
/
/home/ariannadhf/www/wp-content/plugins/simple-history/inc/class-wp-rest-stats-controller.php
<?php namespace Simple_History; use WP_Error; use WP_REST_Controller; use WP_REST_Server; use Simple_History\Date_Helper; /** * REST API controller for stats. */ class WP_REST_Stats_Controller extends WP_REST_Controller { /** * Simple History instance. * * @var Simple_History */ protected Simple_History $simple_history; /** * Constructor. */ public function __construct() { $this->namespace = 'simple-history/v1'; $this->rest_base = 'stats'; $this->simple_history = Simple_History::get_instance(); } /** * Register the routes for the objects of the controller. */ public function register_routes() { // GET /wp-json/simple-history/v1/stats/summary. register_rest_route( $this->namespace, '/' . $this->rest_base . '/summary', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_summary' ], 'permission_callback' => [ $this, 'get_items_permissions_check' ], 'args' => $this->get_collection_params(), ], 'schema' => [ $this, 'get_public_item_schema' ], ] ); // GET /wp-json/simple-history/v1/stats/users. register_rest_route( $this->namespace, '/' . $this->rest_base . '/users', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_users_stats' ], 'permission_callback' => [ $this, 'get_items_permissions_check' ], 'args' => $this->get_collection_params(), ], 'schema' => [ $this, 'get_public_item_schema' ], ] ); // GET /wp-json/simple-history/v1/stats/content. register_rest_route( $this->namespace, '/' . $this->rest_base . '/content', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_content_stats' ], 'permission_callback' => [ $this, 'get_items_permissions_check' ], 'args' => $this->get_collection_params(), ], 'schema' => [ $this, 'get_public_item_schema' ], ] ); // GET /wp-json/simple-history/v1/stats/media. register_rest_route( $this->namespace, '/' . $this->rest_base . '/media', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_media_stats' ], 'permission_callback' => [ $this, 'get_items_permissions_check' ], 'args' => $this->get_collection_params(), ], 'schema' => [ $this, 'get_public_item_schema' ], ] ); // GET /wp-json/simple-history/v1/stats/plugins. register_rest_route( $this->namespace, '/' . $this->rest_base . '/plugins', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_plugins_stats' ], 'permission_callback' => [ $this, 'get_items_permissions_check' ], 'args' => $this->get_collection_params(), ], 'schema' => [ $this, 'get_public_item_schema' ], ] ); // GET /wp-json/simple-history/v1/stats/core. register_rest_route( $this->namespace, '/' . $this->rest_base . '/core', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_core_stats' ], 'permission_callback' => [ $this, 'get_items_permissions_check' ], 'args' => $this->get_collection_params(), ], 'schema' => [ $this, 'get_public_item_schema' ], ] ); // GET /wp-json/simple-history/v1/stats/peak-days. register_rest_route( $this->namespace, '/' . $this->rest_base . '/peak-days', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_peak_days' ], 'permission_callback' => [ $this, 'get_items_permissions_check' ], 'args' => $this->get_collection_params(), ], 'schema' => [ $this, 'get_public_item_schema' ], ] ); // GET /wp-json/simple-history/v1/stats/peak-times. register_rest_route( $this->namespace, '/' . $this->rest_base . '/peak-times', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_peak_times' ], 'permission_callback' => [ $this, 'get_items_permissions_check' ], 'args' => $this->get_collection_params(), ], 'schema' => [ $this, 'get_public_item_schema' ], ] ); // GET /wp-json/simple-history/v1/stats/activity-overview. register_rest_route( $this->namespace, '/' . $this->rest_base . '/activity-overview', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_activity_overview' ], 'permission_callback' => [ $this, 'get_items_permissions_check' ], 'args' => $this->get_collection_params(), ], 'schema' => [ $this, 'get_public_item_schema' ], ] ); // GET /wp-json/simple-history/v1/stats/notes. register_rest_route( $this->namespace, '/' . $this->rest_base . '/notes', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_notes_stats' ], 'permission_callback' => [ $this, 'get_items_permissions_check' ], 'args' => $this->get_collection_params(), ], 'schema' => [ $this, 'get_public_item_schema' ], ] ); } /** * Checks if a given request has access to read stats. * * @param \WP_REST_Request $request Full details about the request. * @return true|\WP_Error True if the request has read access, WP_Error object otherwise. */ public function get_items_permissions_check( $request ) { // User must be logged in and have manage_options capability. if ( ! current_user_can( 'manage_options' ) ) { return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to view stats.', 'simple-history' ), array( 'status' => rest_authorization_required_code() ) ); } return true; } /** * Retrieves the query params for the collection. * * @return array Collection parameters. */ public function get_collection_params() { $params = parent::get_collection_params(); $params['date_from'] = array( // translators: %d is the number of days. 'description' => sprintf( __( 'Start date as Unix timestamp. If not provided, defaults to %d days ago.', 'simple-history' ), Date_Helper::DAYS_PER_MONTH ), 'type' => 'integer', 'required' => false, ); $params['date_to'] = array( 'description' => __( 'End date as Unix timestamp. If not provided, defaults to end of today.', 'simple-history' ), 'type' => 'integer', 'required' => false, ); $params['limit'] = array( 'description' => __( 'Maximum number of items to be returned in result set.', 'simple-history' ), 'type' => 'integer', 'default' => 50, 'minimum' => 1, 'maximum' => 100, ); $params['include_details'] = array( 'description' => __( 'Whether to include detailed stats.', 'simple-history' ), 'type' => 'boolean', 'default' => false, ); return $params; } /** * Get default date range for last month. * * Uses WordPress timezone from Settings > General. * * @return array Array with 'from' and 'to' timestamps for last month. */ private function get_default_date_range() { return Date_Helper::get_default_date_range(); } /** * Get date range from request or default to today. * * @param \WP_REST_Request $request Full details about the request. * @return array Array with 'from' and 'to' timestamps. */ private function get_date_range_from_request( $request ) { $date_from = $request->get_param( 'date_from' ); $date_to = $request->get_param( 'date_to' ); if ( ! $date_from || ! $date_to ) { $default_range = $this->get_default_date_range(); if ( ! $date_from ) { $date_from = $default_range['from']; } if ( ! $date_to ) { $date_to = $default_range['to']; } } return array( 'from' => $date_from, 'to' => $date_to, ); } /** * Format date range with human-readable dates. * * @param int $from Unix timestamp for start date. * @param int $to Unix timestamp for end date. * @return array Array with timestamps, formatted dates, and duration. */ private function format_date_range( $from, $to ) { $date_format = get_option( 'date_format' ); $time_format = get_option( 'time_format' ); $datetime_format = $date_format . ' ' . $time_format; return array( 'from' => $from, 'to' => $to, 'from_formatted' => date_i18n( $datetime_format, $from ), 'to_formatted' => date_i18n( $datetime_format, $to ), 'duration_days' => ceil( ( $to - $from ) / DAY_IN_SECONDS ), ); } /** * Get summary stats. * * @param \WP_REST_Request $request Full details about the request. * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. */ public function get_summary( $request ) { $date_range = $this->get_date_range_from_request( $request ); $date_from = $date_range['from']; $date_to = $date_range['to']; $events_stats = new Events_Stats(); $summary = array( 'date_range' => $this->format_date_range( $date_from, $date_to ), 'total_events' => $events_stats->get_total_events( $date_from, $date_to ), 'total_events_since_install' => Helpers::get_total_logged_events_count(), 'totals' => array( 'users' => array( 'logins' => $events_stats->get_successful_logins_count( $date_from, $date_to ), 'failed_logins' => $events_stats->get_failed_logins_count( $date_from, $date_to ), 'profile_updates' => $events_stats->get_user_updated_count( $date_from, $date_to ), 'total' => $events_stats->get_user_total_count( $date_from, $date_to ), ), 'content' => array( 'created' => $events_stats->get_posts_pages_created( $date_from, $date_to ), 'updated' => $events_stats->get_posts_pages_updated( $date_from, $date_to ), 'deleted' => $events_stats->get_posts_pages_deleted( $date_from, $date_to ), 'total' => $events_stats->get_content_total_count( $date_from, $date_to ), ), 'media' => array( 'uploads' => $events_stats->get_media_uploads_count( $date_from, $date_to ), 'edits' => $events_stats->get_media_edits_count( $date_from, $date_to ), 'deletions' => $events_stats->get_media_deletions_count( $date_from, $date_to ), 'total' => $events_stats->get_media_total_count( $date_from, $date_to ), ), 'plugins' => array( 'updates' => $events_stats->get_plugin_updates_count( $date_from, $date_to ), 'installations' => $events_stats->get_plugin_installs_count( $date_from, $date_to ), 'activations' => $events_stats->get_plugin_activations_count( $date_from, $date_to ), 'total' => $events_stats->get_plugin_total_count( $date_from, $date_to ), ), 'core' => array( 'updates' => $events_stats->get_wordpress_core_updates_count( $date_from, $date_to ), 'available_updates' => $events_stats->get_wordpress_core_updates_found_count( $date_from, $date_to ), 'total' => $events_stats->get_core_total_count( $date_from, $date_to ), ), 'notes' => array( 'added' => $events_stats->get_notes_added_count( $date_from, $date_to ), 'resolved' => $events_stats->get_notes_resolved_count( $date_from, $date_to ), 'total' => $events_stats->get_notes_total_count( $date_from, $date_to ), ), ), ); return rest_ensure_response( $summary ); } /** * Get user stats. * * @param \WP_REST_Request $request Full details about the request. * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. */ public function get_users_stats( $request ) { $date_range = $this->get_date_range_from_request( $request ); $date_from = $date_range['from']; $date_to = $date_range['to']; $limit = $request->get_param( 'limit' ); $include_details = $request->get_param( 'include_details' ); $events_stats = new Events_Stats(); $stats = array( 'date_range' => $this->format_date_range( $date_from, $date_to ), 'summary' => array( 'logins' => $events_stats->get_successful_logins_count( $date_from, $date_to ), 'failed_logins' => $events_stats->get_failed_logins_count( $date_from, $date_to ), 'profile_updates' => $events_stats->get_user_updated_count( $date_from, $date_to ), 'total' => $events_stats->get_user_total_count( $date_from, $date_to ), ), ); if ( $include_details ) { $stats['details'] = $events_stats->get_detailed_user_stats( $date_from, $date_to, $limit ); } return rest_ensure_response( $stats ); } /** * Get content stats. * * @param \WP_REST_Request $request Full details about the request. * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. */ public function get_content_stats( $request ) { $date_range = $this->get_date_range_from_request( $request ); $date_from = $date_range['from']; $date_to = $date_range['to']; $limit = $request->get_param( 'limit' ); $include_details = $request->get_param( 'include_details' ); $events_stats = new Events_Stats(); $stats = array( 'date_range' => $this->format_date_range( $date_from, $date_to ), 'summary' => array( 'created' => $events_stats->get_posts_pages_created( $date_from, $date_to ), 'updated' => $events_stats->get_posts_pages_updated( $date_from, $date_to ), 'deleted' => $events_stats->get_posts_pages_deleted( $date_from, $date_to ), 'total' => $events_stats->get_content_total_count( $date_from, $date_to ), ), ); if ( $include_details ) { $stats['details'] = $events_stats->get_detailed_content_stats( $date_from, $date_to, $limit ); } return rest_ensure_response( $stats ); } /** * Get media stats. * * @param \WP_REST_Request $request Full details about the request. * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. */ public function get_media_stats( $request ) { $date_range = $this->get_date_range_from_request( $request ); $date_from = $date_range['from']; $date_to = $date_range['to']; $include_details = $request->get_param( 'include_details' ); $events_stats = new Events_Stats(); $stats = array( 'date_range' => $this->format_date_range( $date_from, $date_to ), 'summary' => array( 'uploads' => $events_stats->get_media_uploads_count( $date_from, $date_to ), 'edits' => $events_stats->get_media_edits_count( $date_from, $date_to ), 'deletions' => $events_stats->get_media_deletions_count( $date_from, $date_to ), 'total' => $events_stats->get_media_total_count( $date_from, $date_to ), ), ); if ( $include_details ) { $stats['details'] = array( 'uploads' => $events_stats->get_media_uploaded_details( $date_from, $date_to ), 'edits' => $events_stats->get_media_edited_details( $date_from, $date_to ), 'deletions' => $events_stats->get_media_deleted_details( $date_from, $date_to ), ); } return rest_ensure_response( $stats ); } /** * Get plugins stats. * * @param \WP_REST_Request $request Full details about the request. * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. */ public function get_plugins_stats( $request ) { $date_range = $this->get_date_range_from_request( $request ); $date_from = $date_range['from']; $date_to = $date_range['to']; $limit = $request->get_param( 'limit' ); $include_details = $request->get_param( 'include_details' ); $events_stats = new Events_Stats(); $stats = array( 'date_range' => $this->format_date_range( $date_from, $date_to ), 'summary' => array( 'updates' => $events_stats->get_plugin_updates_count( $date_from, $date_to ), 'installations' => $events_stats->get_plugin_installs_count( $date_from, $date_to ), 'activations' => $events_stats->get_plugin_activations_count( $date_from, $date_to ), 'available_updates' => $events_stats->get_available_plugin_updates(), 'total' => $events_stats->get_plugin_total_count( $date_from, $date_to ), ), ); if ( $include_details ) { $stats['details'] = array( 'updates' => $events_stats->get_plugin_details( 'updated', $date_from, $date_to, $limit ), 'installations' => $events_stats->get_plugin_details( 'installed', $date_from, $date_to, $limit ), 'activations' => $events_stats->get_plugin_details( 'activated', $date_from, $date_to, $limit ), 'available_updates' => $events_stats->get_plugins_with_updates(), ); } return rest_ensure_response( $stats ); } /** * Get core stats. * * @param \WP_REST_Request $request Full details about the request. * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. */ public function get_core_stats( $request ) { $date_range = $this->get_date_range_from_request( $request ); $date_from = $date_range['from']; $date_to = $date_range['to']; $events_stats = new Events_Stats(); $stats = array( 'date_range' => $this->format_date_range( $date_from, $date_to ), 'summary' => array( 'updates' => $events_stats->get_wordpress_core_updates_count( $date_from, $date_to ), 'available_updates' => $events_stats->get_wordpress_core_updates_found_count( $date_from, $date_to ), 'total' => $events_stats->get_core_total_count( $date_from, $date_to ), ), ); return rest_ensure_response( $stats ); } /** * Get peak days stats. * * @param \WP_REST_Request $request Full details about the request. * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. */ public function get_peak_days( $request ) { $date_range = $this->get_date_range_from_request( $request ); $date_from = $date_range['from']; $date_to = $date_range['to']; $events_stats = new Events_Stats(); $stats = array( 'date_range' => $this->format_date_range( $date_from, $date_to ), 'peak_days' => $events_stats->get_peak_days( $date_from, $date_to ), ); return rest_ensure_response( $stats ); } /** * Get peak activity times stats. * * @param \WP_REST_Request $request Full details about the request. * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. */ public function get_peak_times( $request ) { $date_range = $this->get_date_range_from_request( $request ); $date_from = $date_range['from']; $date_to = $date_range['to']; $events_stats = new Events_Stats(); $stats = array( 'date_range' => $this->format_date_range( $date_from, $date_to ), 'peak_times' => $events_stats->get_peak_activity_times( $date_from, $date_to ), ); return rest_ensure_response( $stats ); } /** * Get activity overview by date. * * @param \WP_REST_Request $request Full details about the request. * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. */ public function get_activity_overview( $request ) { $date_range = $this->get_date_range_from_request( $request ); $date_from = $date_range['from']; $date_to = $date_range['to']; $events_stats = new Events_Stats(); $stats = array( 'date_range' => $this->format_date_range( $date_from, $date_to ), 'activity_by_date' => $events_stats->get_activity_overview_by_date( $date_from, $date_to ), ); return rest_ensure_response( $stats ); } /** * Get notes stats (WordPress 6.9+). * * @param \WP_REST_Request $request Full details about the request. * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure. */ public function get_notes_stats( $request ) { $date_range = $this->get_date_range_from_request( $request ); $date_from = $date_range['from']; $date_to = $date_range['to']; $events_stats = new Events_Stats(); $stats = array( 'date_range' => $this->format_date_range( $date_from, $date_to ), 'summary' => array( 'added' => $events_stats->get_notes_added_count( $date_from, $date_to ), 'resolved' => $events_stats->get_notes_resolved_count( $date_from, $date_to ), 'total' => $events_stats->get_notes_total_count( $date_from, $date_to ), ), ); return rest_ensure_response( $stats ); } /** * Retrieves the post's schema, conforming to JSON Schema. * * @return array Item schema data. */ public function get_item_schema() { if ( $this->schema ) { return $this->add_additional_fields_schema( $this->schema ); } $schema = array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'simple-history-stats', 'type' => 'object', 'properties' => array( 'date_range' => array( 'description' => __( 'Date range for the stats.', 'simple-history' ), 'type' => 'object', 'properties' => array( 'from' => array( 'description' => __( 'Start date as Unix timestamp.', 'simple-history' ), 'type' => 'integer', ), 'to' => array( 'description' => __( 'End date as Unix timestamp.', 'simple-history' ), 'type' => 'integer', ), ), ), 'summary' => array( 'description' => __( 'Summary of stats.', 'simple-history' ), 'type' => 'object', ), 'details' => array( 'description' => __( 'Detailed stats.', 'simple-history' ), 'type' => 'object', ), ), ); $this->schema = $schema; return $this->add_additional_fields_schema( $this->schema ); } }