Passed
Push — master ( ad7989...648c0b )
by Paul
09:21 queued 04:46
created

Session::deleteSession()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules;
4
5
use GeminiLabs\SiteReviews\Database\SqlQueries;
6
use PasswordHash;
7
8
/**
9
 * @see WP Session Manager (1.2.0)
10
 */
11
class Session
12
{
13
	const DELIMITER = '__';
14
15
	const SESSION_COOKIE = '_glsr_session';
16
17
	/**
18
	 * @var int
19
	 */
20
	protected $expiryTimestamp;
21
22
	/**
23
	 * @var int
24
	 */
25
	protected $expiryTimestampReset;
26
27
	/**
28
	 * @var array
29
	 */
30
	protected $sessionData;
31
32
	/**
33
	 * @var string
34
	 */
35
	protected $sessionId;
36
37
	public function __construct()
38
	{
39
		$cookieId = filter_input( INPUT_COOKIE, static::SESSION_COOKIE );
40
		if( strpos( $cookieId, static::DELIMITER ) !== false ) {
41
			$cookie = explode( static::DELIMITER, stripslashes( $cookieId ));
42
			$this->sessionId = preg_replace( '/[^A-Za-z0-9_]/', '', $cookie[0] );
43
			$this->expiryTimestamp = absint( $cookie[1] );
44
			$this->expiryTimestampReset = absint( $cookie[2] );
45
			if( time() > $this->expiryTimestampReset ) {
46
				$this->setCookieExpiration();
47
			}
48
		}
49
		else {
50
			$this->sessionId = $this->generateSessionId();
51
			$this->setCookieExpiration();
52
		}
53
		$this->getSessionData();
54
		$this->setCookie();
55
	}
56
57
	/**
58
	 * @return void
59
	 */
60 1
	public function clear()
61
	{
62 1
		$this->setCookieExpiration();
63 1
		$this->regenerateSessionId( 'and delete session!' );
64 1
	}
65
66
	/**
67
	 * @return int|false
68
	 */
69
	public function deleteAllSessions()
70
	{
71
		return glsr( SqlQueries::class )->deleteAllSessions( static::SESSION_COOKIE );
72
	}
73
74
	/**
75
	 * @param int $limit
76
	 * @return void
77
	 */
78
	public function deleteExpiredSessions( $limit = 1000 )
79
	{
80
		if( $expiredSessions = implode( "','", $this->getExpiredSessions( $limit ))) {
81
			glsr( SqlQueries::class )->deleteExpiredSessions( $expiredSessions );
82
		}
83
	}
84
85
	/**
86
	 * @param string $key
87
	 * @param string|array $fallback
88
	 * @param bool|string $unset
89
	 * @return string|array
90
	 */
91 1
	public function get( $key, $fallback = '', $unset = false )
92
	{
93 1
		$key = sanitize_key( $key );
94 1
		$value = isset( $this->sessionData[$key] )
95 1
			? maybe_unserialize( $this->sessionData[$key] )
96 1
			: $fallback;
97 1
		if( isset( $this->sessionData[$key] ) && $unset ) {
98 1
			unset( $this->sessionData[$key] );
99 1
			$this->updateSession();
100
		}
101 1
		return $value;
102
	}
103
104
	/**
105
	 * @param string $key
106
	 * @param mixed $value
107
	 * @return mixed
108
	 */
109 1
	public function set( $key, $value )
110
	{
111 1
		$key = sanitize_key( $key );
112 1
		$this->sessionData[$key] = maybe_serialize( $value );
113 1
		$this->updateSession();
114 1
		return $this->sessionData[$key];
115
	}
116
117
	/**
118
	 * @return void
119
	 */
120 1
	protected function createSession()
121
	{
122 1
		add_option( $this->getSessionId(), $this->sessionData, '', false );
123 1
		add_option( $this->getSessionId( 'expires' ), $this->expiryTimestamp, '', false );
124 1
	}
125
126
	/**
127
	 * @return void
128
	 */
129 1
	protected function deleteSession()
130
	{
131 1
		delete_option( $this->getSessionId() );
132 1
		delete_option( $this->getSessionId( 'expires' ));
133 1
	}
134
135
	/**
136
	 * @return string
137
	 */
138 1
	protected function generateSessionId()
139
	{
140 1
		return md5(( new PasswordHash( 8, false ))->get_random_bytes( 32 ));
141
	}
142
143
	/**
144
	 * @param int $limit
145
	 * @return array
146
	 */
147
	protected function getExpiredSessions( $limit )
148
	{
149
		$expiredSessions = [];
150
		$sessions = glsr( SqlQueries::class )->getExpiredSessions( static::SESSION_COOKIE, absint( $limit ));
151
		if( !empty( $sessions )) {
152
			$now = time();
153
			foreach( $sessions as $session ) {
154
				if( $now <= $session->expiration )continue;
155
				$expiredSessions[] = $session->name;
156
				$expiredSessions[] = str_replace( '_expires_', '_', $session->name );
157
			}
158
		}
159
		return $expiredSessions;
160
	}
161
162
	/**
163
	 * @param string $separator
164
	 * @return string
165
	 */
166 1
	protected function getSessionId( $separator = '' )
167
	{
168 1
		return implode( '_', array_filter( [static::SESSION_COOKIE, $separator, $this->sessionId] ));
169
	}
170
171
	/**
172
	 * @return array
173
	 */
174
	protected function getSessionData()
175
	{
176
		return $this->sessionData = (array)get_option( $this->getSessionId(), [] );
177
	}
178
179
	/**
180
	 * @param bool|string $deleteOld
181
	 * @return void
182
	 */
183 1
	protected function regenerateSessionId( $deleteOld = false )
184
	{
185 1
		if( $deleteOld ) {
186 1
			$this->deleteSession();
187
		}
188 1
		$this->sessionId = $this->generateSessionId();
189 1
		$this->setCookie();
190 1
	}
191
192
	/**
193
	 * @return void
194
	 */
195 1
	protected function setCookie()
196
	{
197 1
		if( headers_sent() )return;
198
		$cookie = $this->sessionId.static::DELIMITER.$this->expiryTimestamp.static::DELIMITER.$this->expiryTimestampReset;
199
		$cookiePath = preg_replace( '|https?://[^/]+|i', '', trailingslashit( (string)get_option( 'home' )));
200
		setcookie( static::SESSION_COOKIE, $cookie, $this->expiryTimestamp, $cookiePath );
201
	}
202
203
	/**
204
	 * @return void
205
	 */
206 1
	protected function setCookieExpiration()
207
	{
208 1
		$this->expiryTimestampReset = time() + (24 * 60); // 24 minutes
209 1
		$this->expiryTimestamp = time() + (30 * 60); // 30 minutes
210 1
	}
211
212
	/**
213
	 * @return void
214
	 */
215 1
	protected function updateSession()
216
	{
217 1
		if( false === get_option( $this->getSessionId() )) {
218 1
			return $this->createSession();
219
		}
220 1
		update_option( $this->getSessionId(), $this->sessionData, false );
221 1
	}
222
}
223