Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions inc/class-cli-command.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ public function delete( $args, $assoc_args ) {
}
}

/**
* Run session garbage collection.
*
* @subcommand gc
*/
public function gc( $args, $assoc_args ) {
if ( ! PANTHEON_SESSIONS_ENABLED ) {
WP_CLI::error( 'Pantheon Sessions is currently disabled.' );
}

$pantheon_session = \Pantheon_Sessions::get_instance();
$pantheon_session->garbage_collection();
WP_CLI::success( 'Session garbage collection complete.' );
}

/**
* Set id as primary key in the Native PHP Sessions plugin table.
*
Expand Down
1 change: 1 addition & 0 deletions inc/class-session.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public static function create_for_sid( $sid ) {
$insert_data = [
'session_id' => $sid,
'user_id' => (int) get_current_user_id(),
'datetime' => gmdate( 'Y-m-d H:i:s' ),
];
if ( function_exists( 'is_ssl' ) && is_ssl() ) {
$insert_data['secure_session_id'] = $sid;
Expand Down
24 changes: 19 additions & 5 deletions pantheon-sessions.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ private function load() {
return;
}

if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
return;
}

$this->define_constants();
$this->require_files();

Expand All @@ -74,12 +70,30 @@ private function load() {
$this->set_ini_values();
add_action( 'set_logged_in_cookie', [ __CLASS__, 'action_set_logged_in_cookie' ], 10, 4 );
add_action( 'clear_auth_cookie', [ __CLASS__, 'action_clear_auth_cookie' ] );

if ( ! wp_next_scheduled( 'pantheon_sessions_gc' ) ) {
wp_schedule_event( time(), 'hourly', 'pantheon_sessions_gc' );
}
add_action( 'pantheon_sessions_gc', [ $this, 'garbage_collection' ] );
}

add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
add_action( 'wp_ajax_dismiss_notice', [ $this, 'dismiss_notice' ] );
}

/**
* Runs the garbage collection process.
*
* @param int $maxlifetime Maximum lifetime in seconds.
*/
public function garbage_collection( $maxlifetime = null ) {
if ( null === $maxlifetime ) {
$maxlifetime = (int) ini_get( 'session.gc_maxlifetime' );
}
$handler = new \Pantheon_Sessions\Session_Handler();
$handler->gc( $maxlifetime );
}

/**
* Enqueue scripts
*/
Expand Down Expand Up @@ -240,7 +254,7 @@ private function setup_database() {
`session_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'A session ID. The value is generated by plugin''s session handlers.',
`secure_session_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Secure session ID. The value is generated by plugin''s session handlers.',
`ip_address` varchar(128) NOT NULL DEFAULT '' COMMENT 'The IP address that last used this session ID.',
`datetime` datetime DEFAULT NULL COMMENT 'The datetime value when this session last requested a page. Old records are purged by PHP automatically.',
`datetime` datetime DEFAULT NULL COMMENT 'The datetime value when this session was last written to.',
`data` mediumblob COMMENT 'The serialized contents of \$_SESSION, an array of name/value pairs that persists across page requests by this session ID. Plugin loads \$_SESSION from here at the start of each request and saves it at the end.',
KEY `session_id` (`session_id`),
KEY `secure_session_id` (`secure_session_id`)
Expand Down
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ Adds a WP-CLI command to add an index to the sessions table if one does not exis
== Changelog ==

= 1.4.6-dev =
* Run session garbage collection hourly through WordPress scheduled task. Create WP-CLI command to run GC manually

= 1.4.5 (December 2025) =
* Compatibility: Supports Wordpress 6.9
Expand Down
17 changes: 8 additions & 9 deletions tests/phpunit/test-sessions.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public function setUp(): void {
if ( ! Session::get_by_sid( session_id() ) ) {
Session::create_for_sid( session_id() );
}

parent::setUp();
}

Expand Down Expand Up @@ -126,23 +127,21 @@ public function test_session_sync_user_id_login_logout() {
}

/**
* Ensures the garbage collection function wroks as expected.
* Ensures the garbage collection function works as expected.
*/
public function test_session_garbage_collection() {
$this->markTestSkipped( 'ini_set() never works once headers have been set' );

global $wpdb;
$_SESSION['foo'] = 'bar';
session_commit();
$this->assertEquals( 1, $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->pantheon_sessions" ) );
$current_val = ini_get( 'session.gc_maxlifetime' );
ini_set( 'session.gc_maxlifetime', 100000000 );
_pantheon_session_garbage_collection( ini_get( 'session.gc_maxlifetime' ) );

// Should NOT delete the session with a very long lifetime.
Pantheon_Sessions()->garbage_collection( 100000000 );
$this->assertEquals( 1, $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->pantheon_sessions" ) );
ini_set( 'session.gc_maxlifetime', 0 );
_pantheon_session_garbage_collection( ini_get( 'session.gc_maxlifetime' ) );

// Should delete the session with a lifetime of 0.
Pantheon_Sessions()->garbage_collection( 0 );
$this->assertEquals( 0, $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->pantheon_sessions" ) );
ini_set( 'session.gc_maxlifetime', $current_val );
}

/**
Expand Down