PATH:
home
/
thebhoeo
/
.trash
/
backwpup
/
vendor
/
wordpress
/
mcp-adapter
/
includes
/
Transport
/
Infrastructure
<?php /** * MCP Session Manager using User Meta * * * @package McpAdapter */ declare( strict_types=1 ); namespace WP\MCP\Transport\Infrastructure; use WP_Error; /** * MCP Session Manager * * Handles session creation, validation, and cleanup using user meta storage. * Sessions are tied to authenticated users to prevent anonymous session flooding. */ final class SessionManager { /** * User meta key for storing sessions * * @var string */ private const SESSION_META_KEY = 'mcp_adapter_sessions'; /** * Maximum sessions per user. * * @var int */ private const DEFAULT_MAX_SESSIONS = 32; /** * Session inactivity timeout in seconds (24 hours). * * @var int */ private const DEFAULT_INACTIVITY_TIMEOUT = DAY_IN_SECONDS; /** * Minimum interval between last_activity writes in seconds. * * @var int */ private const DEFAULT_ACTIVITY_UPDATE_INTERVAL = 60; /** * Create a new session for a user * * @param int $user_id The user ID. * @param array $params Client parameters from initialize request. * * @return string|false The session ID on success, false on failure. */ public static function create_session( int $user_id, array $params = array() ) { if ( ! $user_id || ! get_user_by( 'id', $user_id ) ) { return false; } // Cleanup inactive sessions first self::cleanup_expired_sessions( $user_id ); // Get current sessions $sessions = self::get_all_user_sessions( $user_id ); // Check session limit - remove oldest if over limit $config = self::get_config(); $max_sessions = $config['max_sessions']; if ( count( $sessions ) >= $max_sessions ) { // Remove oldest session (FIFO) - sort by created_at and remove first uasort( $sessions, static function ( $a, $b ) { return $a['created_at'] <=> $b['created_at']; } ); array_shift( $sessions ); } // Create a new session $session_id = wp_generate_uuid4(); $now = time(); $sessions[ $session_id ] = array( 'created_at' => $now, 'last_activity' => $now, 'client_params' => $params, ); // Save sessions update_user_meta( $user_id, self::SESSION_META_KEY, $sessions ); return $session_id; } /** * Cleanup inactive sessions for a user * * @param int $user_id The user ID. * * @return int Number of sessions removed. */ public static function cleanup_expired_sessions( int $user_id ): int { if ( ! $user_id ) { return 0; } $sessions = self::get_all_user_sessions( $user_id ); $now = time(); $removed = 0; $config = self::get_config(); $inactivity_timeout = $config['inactivity_timeout']; foreach ( $sessions as $session_id => $session ) { // Check if still active - skip if valid if ( $session['last_activity'] + $inactivity_timeout >= $now ) { continue; } // Session is inactive - remove it unset( $sessions[ $session_id ] ); ++$removed; } if ( $removed > 0 ) { if ( empty( $sessions ) ) { delete_user_meta( $user_id, self::SESSION_META_KEY ); } else { update_user_meta( $user_id, self::SESSION_META_KEY, $sessions ); } } return $removed; } /** * Get all sessions for a user * * @param int $user_id The user ID. * * @return array Array of sessions. */ public static function get_all_user_sessions( int $user_id ): array { if ( ! $user_id ) { return array(); } $sessions = get_user_meta( $user_id, self::SESSION_META_KEY, true ); if ( ! is_array( $sessions ) ) { return array(); } return $sessions; } /** * Get configuration values. * * @return array{max_sessions: int, inactivity_timeout: int, activity_update_interval: int} Configuration array. */ private static function get_config(): array { /** * Filters the maximum number of MCP sessions allowed per user. * * When a user exceeds this limit, the oldest inactive session is * automatically removed to make room for new sessions. * * @since 0.3.0 * * @param int $max_sessions Maximum sessions per user. Default 32. */ $max_sessions = (int) apply_filters( 'mcp_adapter_session_max_per_user', self::DEFAULT_MAX_SESSIONS ); /** * Filters the session inactivity timeout in seconds. * * Sessions that have been inactive longer than this duration are * considered expired and may be cleaned up automatically. * * @since 0.3.0 * * @param int $timeout Inactivity timeout in seconds. Default DAY_IN_SECONDS (86400 / 24 hours). */ $inactivity_timeout = (int) apply_filters( 'mcp_adapter_session_inactivity_timeout', self::DEFAULT_INACTIVITY_TIMEOUT ); /** * Filters the minimum interval between session last_activity writes. * * To reduce write amplification, the session manager only updates * `last_activity` if at least this many seconds have elapsed since * the last write. * * @since 0.5.0 * * @param int $interval Minimum seconds between writes. Default 60. */ $activity_update_interval = (int) apply_filters( 'mcp_adapter_session_activity_update_interval', self::DEFAULT_ACTIVITY_UPDATE_INTERVAL ); // Clamp: interval must be less than inactivity timeout to prevent // sessions from expiring despite active use. if ( $activity_update_interval >= $inactivity_timeout ) { $activity_update_interval = (int) ( $inactivity_timeout / 2 ); } return array( 'max_sessions' => $max_sessions, 'inactivity_timeout' => $inactivity_timeout, 'activity_update_interval' => max( 0, $activity_update_interval ), ); } /** * Get a specific session for a user * * @param int $user_id The user ID. * @param string $session_id The session ID. * * @return array|\WP_Error|false Session data on success, WP_Error on invalid input, false if not found or inactive. */ public static function get_session( int $user_id, string $session_id ) { if ( ! $user_id || ! $session_id ) { return new WP_Error( 'mcp_session_invalid_input', 'Invalid user ID or session ID.' ); } $sessions = self::get_all_user_sessions( $user_id ); if ( ! isset( $sessions[ $session_id ] ) ) { return false; } $session = $sessions[ $session_id ]; // Check inactivity timeout $config = self::get_config(); $inactivity_timeout = $config['inactivity_timeout']; if ( $session['last_activity'] + $inactivity_timeout < time() ) { self::clear_session( $user_id, $session_id ); return false; } return $session; } /** * Clear an inactive session (internal cleanup). * * @param int $user_id The user ID. * @param string $session_id The session ID to clear. * * @return void */ private static function clear_session( int $user_id, string $session_id ): void { $sessions = self::get_all_user_sessions( $user_id ); if ( ! isset( $sessions[ $session_id ] ) ) { return; } unset( $sessions[ $session_id ] ); update_user_meta( $user_id, self::SESSION_META_KEY, $sessions ); } /** * Validate a session and update last activity * * @param int $user_id The user ID. * @param string $session_id The session ID. * * @return bool True if valid, false otherwise. */ public static function validate_session( int $user_id, string $session_id ): bool { if ( ! $user_id || ! $session_id ) { return false; } $sessions = self::get_all_user_sessions( $user_id ); if ( ! isset( $sessions[ $session_id ] ) ) { return false; } $session = $sessions[ $session_id ]; // Check inactivity timeout $config = self::get_config(); $inactivity_timeout = $config['inactivity_timeout']; if ( $session['last_activity'] + $inactivity_timeout < time() ) { self::clear_session( $user_id, $session_id ); return false; } // Throttle last_activity writes to reduce write amplification $activity_update_interval = $config['activity_update_interval']; if ( time() - $session['last_activity'] >= $activity_update_interval ) { $sessions[ $session_id ]['last_activity'] = time(); update_user_meta( $user_id, self::SESSION_META_KEY, $sessions ); } return true; } /** * Delete a specific session * * @param int $user_id The user ID. * @param string $session_id The session ID. * * @return bool True on success, false on failure. */ public static function delete_session( int $user_id, string $session_id ): bool { if ( ! $user_id || ! $session_id ) { return false; } $sessions = self::get_all_user_sessions( $user_id ); if ( ! isset( $sessions[ $session_id ] ) ) { return false; } unset( $sessions[ $session_id ] ); if ( empty( $sessions ) ) { delete_user_meta( $user_id, self::SESSION_META_KEY ); } else { update_user_meta( $user_id, self::SESSION_META_KEY, $sessions ); } return true; } }
[-] HttpRequestHandler.php
[edit]
[-] RequestRouter.php
[edit]
[-] McpTransportContext.php
[edit]
[-] JsonRpcResponseBuilder.php
[edit]
[-] HttpSessionValidator.php
[edit]
[-] McpTransportHelperTrait.php
[edit]
[+]
..
[-] HttpRequestContext.php
[edit]
[-] SessionManager.php
[edit]