Skip to content

Commit 80cc544

Browse files
committed
4.1.0 Release
* Add some defense to ensure end users are running the correct version of PHP before loading the system. (#76) * Eliminate a race condition where another plugin or the theme created the session first. (#75) * Schedule a cron to auto-delete expired sessions. (#77) Closes #75, closes #76, closes #77, resolves #78.
1 parent ebba699 commit 80cc544

File tree

6 files changed

+201
-42
lines changed

6 files changed

+201
-42
lines changed

README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@ Absolutely! As of version 2.0, this plugin will create a new table for WordPress
4848
define( 'WP_SESSION_USE_OPTIONS', true );
4949
```
5050

51+
**I get an error saying my PHP version is out of date. Why?**
52+
53+
PHP 5.6 was designated end-of-life and stopped receiving security patches in December 2018. PHP 7.0 was _also_ marked end-of-life in December 2018. The minimum version of PHP supported by WP Session Manager is now PHP 7.1.
54+
55+
If your server is running an older version of PHP, the session system _will not work!_ To avoid triggering a PHP error, the plugin will instead output this notice to upgrade and disable itself silently. You won't see a PHP error, but you also won't get session support.
56+
57+
Reach out to your hosting provider or system administrator to upgrade your server.
58+
59+
**I get an error saying another plugin is setting up a session. What can I do?**
60+
61+
WP Session Manager overrides PHP's default session implementation with its own custom handler. Unfortunately, we can't swap in a new handler if a session is already active. This plugin hooks into the `plugins_loaded` hook to set things up as early as possible, but if you have code in _another_ plugin (or your theme) that attempts to invoke `session_start()` before WP Session Manager loads, then the custom handler won't work at all.
62+
63+
Inspect your other plugins and try to find the one that's interfering. Then, reach out to the developer to explain the conflict and see if they have a fix.
64+
5165
Screenshots
5266
-----------
5367

@@ -56,6 +70,11 @@ None
5670
Changelog
5771
---------
5872

73+
**4.1.0**
74+
- Fix: Add some defense to ensure end users are running the correct version of PHP before loading the system.
75+
- Fix: Eliminate a race condition where another plugin or the theme created the session first.
76+
- Fix: Schedule a cron to auto-delete expired sessions.
77+
5978
**4.0.0**
6079
- New: Add an object cache based handler to leverage Redis or Memcached if available for faster queries.
6180
- New: Adopt the Contributor Covenant (v1.4) as the project's official code of conduct.
@@ -161,7 +180,7 @@ Additional Information
161180
**Requires at least:** 4.7
162181
**Tested up to:** 5.0.2
163182
**Requires PHP:** 7.1
164-
**Stable tag:** 4.0.0
183+
**Stable tag:** 4.1.0
165184
**License:** GPLv2 or later
166185
**License URI:** http://www.gnu.org/licenses/gpl-2.0.html
167186

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name" : "ericmann/wp-session-manager",
33
"description" : "Prototype session management for WordPress.",
4-
"version" : "4.0.0",
4+
"version" : "4.1.0",
55
"type" : "wordpress-plugin",
66
"keywords" : ["session"],
77
"homepage" : "https://github.com/ericmann/wp-session-manager",

includes/DatabaseHandler.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,21 @@ protected function directDelete(string $key)
252252
* @param int $maxlifetime (Unused).
253253
* @param callable $next Next clean operation in the stack.
254254
*
255-
* @global \wpdb $wpdb
256-
*
257255
* @return mixed
258256
*/
259257
public function clean($maxlifetime, $next)
258+
{
259+
self::directClean();
260+
261+
return $next($maxlifetime);
262+
}
263+
264+
/**
265+
* Update the database by removing any sessions that are no longer valid
266+
*
267+
* @global \wpdb $wpdb
268+
*/
269+
public static function directClean()
260270
{
261271
global $wpdb;
262272

@@ -269,7 +279,5 @@ public function clean($maxlifetime, $next)
269279
)
270280
);
271281
}
272-
273-
return $next($maxlifetime);
274282
}
275283
}

readme.txt

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Tags: session
55
Requires at least: 4.7
66
Tested up to: 5.0.2
77
Requires PHP: 7.1
8-
Stable tag: 4.0.0
8+
Stable tag: 4.1.0
99
License: GPLv2 or later
1010
License URI: http://www.gnu.org/licenses/gpl-2.0.html
1111

@@ -54,12 +54,31 @@ Absolutely! As of version 2.0, this plugin will create a new table for WordPress
5454
define( 'WP_SESSION_USE_OPTIONS', true );
5555
`
5656

57+
= I get an error saying my PHP version is out of date. Why? =
58+
59+
PHP 5.6 was designated end-of-life and stopped receiving security patches in December 2018. PHP 7.0 was _also_ marked end-of-life in December 2018. The minimum version of PHP supported by WP Session Manager is now PHP 7.1.
60+
61+
If your server is running an older version of PHP, the session system _will not work!_ To avoid triggering a PHP error, the plugin will instead output this notice to upgrade and disable itself silently. You won't see a PHP error, but you also won't get session support.
62+
63+
Reach out to your hosting provider or system administrator to upgrade your server.
64+
65+
= I get an error saying another plugin is setting up a session. What can I do? =
66+
67+
WP Session Manager overrides PHP's default session implementation with its own custom handler. Unfortunately, we can't swap in a new handler if a session is already active. This plugin hooks into the `plugins_loaded` hook to set things up as early as possible, but if you have code in _another_ plugin (or your theme) that attempts to invoke `session_start()` before WP Session Manager loads, then the custom handler won't work at all.
68+
69+
Inspect your other plugins and try to find the one that's interfering. Then, reach out to the developer to explain the conflict and see if they have a fix.
70+
5771
== Screenshots ==
5872

5973
None
6074

6175
== Changelog ==
6276

77+
= 4.1.0 =
78+
* Fix: Add some defense to ensure end users are running the correct version of PHP before loading the system.
79+
* Fix: Eliminate a race condition where another plugin or the theme created the session first.
80+
* Fix: Schedule a cron to auto-delete expired sessions.
81+
6382
= 4.0.0 =
6483
* New: Add an object cache based handler to leverage Redis or Memcached if available for faster queries.
6584
* New: Adopt the Contributor Covenant (v1.4) as the project's official code of conduct.

tests/DatabaseHandlerTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace EAMann\WPSession;
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
class DatabaseHandlerTest extends TestCase
8+
{
9+
10+
public function test_create()
11+
{
12+
$handler = new DatabaseHandler();
13+
14+
$called = false;
15+
$callback = function($path, $name) use (&$called) {
16+
$this->assertEquals('path', $path);
17+
$this->assertEquals('name', $name);
18+
19+
$called = true;
20+
};
21+
22+
$handler->create('path', 'name', $callback);
23+
24+
$this->assertTrue($called);
25+
}
26+
27+
}

wp-session-manager.php

Lines changed: 121 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,65 +3,151 @@
33
* Plugin Name: WP Session Manager
44
* Plugin URI: https://paypal.me/eam
55
* Description: Session management for WordPress.
6-
* Version: 4.0.0
6+
* Version: 4.1.0
77
* Author: Eric Mann
88
* Author URI: https://eamann.com
99
* License: GPLv2+
1010
*
1111
* @package WP Session Manager
1212
*/
1313

14-
$wp_session_autoload = __DIR__ . '/vendor/autoload.php';
15-
if (file_exists($wp_session_autoload)) {
16-
require_once $wp_session_autoload;
14+
if (!defined('WP_SESSION_MINIMUM_PHP_VERSION')) {
15+
define('WP_SESSION_MINIMUM_PHP_VERSION', '7.1.0');
1716
}
1817

19-
if (!class_exists('EAMann\Sessionz\Manager')) {
20-
exit('WP Session Manager requires Composer autoloading, which is not configured');
21-
}
18+
$wp_session_messages = [
19+
'bad_php_version' => sprintf(
20+
__(
21+
'WP Session Manager requires PHP %s or newer. Please contact your system administrator to upgrade!',
22+
'wp-session-manager'
23+
),
24+
WP_SESSION_MINIMUM_PHP_VERSION,
25+
PHP_VERSION
26+
),
27+
'multiple_sessions' => __(
28+
'Another plugin is attempting to start a session with WordPress. WP Session Manager will not work!',
29+
'wp-session-manager'
30+
)
31+
];
2232

23-
// Queue up the session stack.
24-
$wp_session_handler = EAMann\Sessionz\Manager::initialize();
33+
/**
34+
* Initialize the plugin, bootstrap autoloading, and register default hooks
35+
*/
36+
function wp_session_manager_initialize()
37+
{
38+
$wp_session_autoload = __DIR__ . '/vendor/autoload.php';
39+
if (file_exists($wp_session_autoload)) {
40+
require_once $wp_session_autoload;
41+
}
2542

26-
// Fall back to database storage where needed.
27-
if (defined('WP_SESSION_USE_OPTIONS') && WP_SESSION_USE_OPTIONS) {
28-
$wp_session_handler->addHandler(new \EAMann\WPSession\OptionsHandler());
29-
} else {
30-
$wp_session_handler->addHandler(new \EAMann\WPSession\DatabaseHandler());
31-
}
43+
if (!class_exists('EAMann\Sessionz\Manager')) {
44+
exit('WP Session Manager requires Composer autoloading, which is not configured');
45+
}
3246

33-
// If we have an external object cache, let's use it!
34-
if (wp_using_ext_object_cache()) {
35-
$wp_session_handler->addHandler(new EAMann\WPSession\CacheHandler());
36-
}
47+
if (!isset($_SESSION)) {
48+
// Queue up the session stack.
49+
$wp_session_handler = EAMann\Sessionz\Manager::initialize();
50+
51+
// Fall back to database storage where needed.
52+
if (defined('WP_SESSION_USE_OPTIONS') && WP_SESSION_USE_OPTIONS) {
53+
$wp_session_handler->addHandler(new \EAMann\WPSession\OptionsHandler());
54+
} else {
55+
$wp_session_handler->addHandler(new \EAMann\WPSession\DatabaseHandler());
56+
57+
/**
58+
* The database handler can automatically clean up sessions as it goes. By default,
59+
* we'll run the cleanup routine every hour to catch any stale sessions that PHP's
60+
* garbage collector happens to miss. This timeout can be filtered to increase or
61+
* decrease the frequency of the manual purge.
62+
*
63+
* @param string $timeout Interval with which to purge stale sessions
64+
*/
65+
$timeout = apply_filters('wp_session_gc_interval', 'hourly');
66+
67+
if (!wp_next_scheduled('wp_session_database_gc')) {
68+
wp_schedule_event(time(), $timeout, 'wp_session_database_gc');
69+
}
70+
71+
add_action('wp_session_database_gc', ['EAMann\WPSession\DatabaseHandler', 'directClean']);
72+
}
73+
74+
// If we have an external object cache, let's use it!
75+
if (wp_using_ext_object_cache()) {
76+
$wp_session_handler->addHandler(new EAMann\WPSession\CacheHandler());
77+
}
78+
79+
// Decrypt the data surfacing from external storage.
80+
if (defined('WP_SESSION_ENC_KEY') && WP_SESSION_ENC_KEY) {
81+
$wp_session_handler->addHandler(new \EAMann\Sessionz\Handlers\EncryptionHandler(WP_SESSION_ENC_KEY));
82+
}
83+
84+
// Use an in-memory cache for the instance if we can. This will only help in rare cases.
85+
$wp_session_handler->addHandler(new \EAMann\Sessionz\Handlers\MemoryHandler());
86+
87+
$_SESSION['wp_session_manager'] = 'active';
88+
}
3789

38-
// Decrypt the data surfacing from external storage.
39-
if (defined('WP_SESSION_ENC_KEY') && WP_SESSION_ENC_KEY) {
40-
$wp_session_handler->addHandler(new \EAMann\Sessionz\Handlers\EncryptionHandler(WP_SESSION_ENC_KEY));
90+
if (! isset($_SESSION['wp_session_manager']) || $_SESSION['wp_session_manager'] !== 'active') {
91+
add_action('admin_notices', 'wp_session_manager_multiple_sessions_notice');
92+
return;
93+
}
94+
95+
// Create the required table.
96+
\EAMann\WPSession\DatabaseHandler::createTable();
97+
98+
register_deactivation_hook(__FILE__, function () {
99+
wp_clear_scheduled_hook('wp_session_database_gc');
100+
});
41101
}
42102

43-
// Use an in-memory cache for the instance if we can. This will only help in rare cases.
44-
$wp_session_handler->addHandler(new \EAMann\Sessionz\Handlers\MemoryHandler());
103+
/**
104+
* Print an admin notice if too many plugins are manipulating sessions.
105+
*
106+
* @global array $wp_session_messages
107+
*/
108+
function wp_session_manager_multiple_sessions_notice()
109+
{
110+
global $wp_session_messages;
111+
?>
112+
<div class="notice notice-error">
113+
<p><?php echo esc_html($wp_session_messages['multiple_sessions']); ?></p>
114+
</div>
115+
<?php
116+
}
45117

46-
// Create the required table.
47-
add_action('admin_init', ['EAMann\WPSession\DatabaseHandler', 'createTable']);
48-
add_action('wp_session_init', ['EAMann\WPSession\DatabaseHandler', 'createTable']);
49-
add_action('wp_install', ['EAMann\WPSession\DatabaseHandler', 'createTable']);
50-
register_activation_hook(__FILE__, ['EAMann\WPSession\DatabaseHandler', 'createTable']);
118+
/**
119+
* Print an admin notice if we're on a bad version of PHP.
120+
*
121+
* @global array $wp_session_messages
122+
*/
123+
function wp_session_manager_deactivated_notice()
124+
{
125+
global $wp_session_messages;
126+
?>
127+
<div class="notice notice-error">
128+
<p><?php echo esc_html($wp_session_messages['bad_php_version']); ?></p>
129+
</div>
130+
<?php
131+
}
51132

52133
/**
53134
* If a session hasn't already been started by some external system, start one!
54135
*/
55136
function wp_session_manager_start_session()
56137
{
57-
$bootstrap = \EAMann\WPSession\DatabaseHandler::createTable();
58-
59-
if (! is_wp_error($bootstrap) && session_status() !== PHP_SESSION_ACTIVE) {
138+
if (session_status() !== PHP_SESSION_ACTIVE) {
60139
session_start();
61140
}
62141
}
63142

64-
// Start up session management, if we're not in the CLI.
65-
if (!defined('WP_CLI') || false === WP_CLI) {
66-
add_action('plugins_loaded', 'wp_session_manager_start_session', 10, 0);
143+
// WordPress won't enforce the minimum version of PHP for us, so we need to check.
144+
if (version_compare(PHP_VERSION, WP_SESSION_MINIMUM_PHP_VERSION, '<')) {
145+
add_action('admin_notices', 'wp_session_manager_deactivated_notice');
146+
} else {
147+
add_action('plugins_loaded', 'wp_session_manager_initialize', 1, 0);
148+
149+
// Start up session management, if we're not in the CLI.
150+
if (!defined('WP_CLI') || false === WP_CLI) {
151+
add_action('plugins_loaded', 'wp_session_manager_start_session', 10, 0);
152+
}
67153
}

0 commit comments

Comments
 (0)