Completed
Push — master ( bcec5b...3c5936 )
by Devin
28:11 queued 09:32
created

Give_Session::should_start_session()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 30
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 30
ccs 0
cts 5
cp 0
rs 8.439
cc 5
eloc 20
nc 9
nop 0
crap 30
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 24 and the first side effect is on line 16.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Give Session
4
 *
5
 * This is a wrapper class for WP_Session / PHP $_SESSION and handles the storage of Give sessions
6
 *
7
 * @package     Give
8
 * @subpackage  Classes/Session
9
 * @copyright   Copyright (c) 2016, WordImpress
10
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
 * @since       1.0
12
 */
13
14
// Exit if accessed directly
15
if ( ! defined( 'ABSPATH' ) ) {
16
	exit;
17
}
18
19
/**
20
 * Give_Session Class
21
 *
22
 * @since 1.0
23
 */
24
class Give_Session {
25
26
	/**
27
	 * Holds our session data
28
	 *
29
	 * @var array
30
	 * @access private
31
	 * @since  1.0
32
	 */
33
	private $session;
34
35
36
	/**
37
	 * Whether to use PHP $_SESSION or WP_Session
38
	 *
39
	 * @var bool
40
	 * @access private
41
	 * @since  1.0
42
	 */
43
	private $use_php_sessions = false;
44
45
	/**
46
	 * Expiration Time
47
	 *
48
	 * @var int
49
	 * @access private
50
	 * @since  1.0
51
	 */
52
	private $exp_option = false;
53
54
	/**
55
	 * Session index prefix
56
	 *
57
	 * @var string
58
	 * @access private
59
	 * @since  1.0
60
	 */
61
	private $prefix = '';
62
63
	/**
64
	 * Get things started
65
	 *
66
	 * @description: Defines our session constants, includes the necessary libraries and retrieves the session instance
67
	 *
68
	 * @since 1.0
69
	 */
70
	public function __construct() {
71 2
72
		$this->use_php_sessions = $this->use_php_sessions();
73 2
		$this->exp_option       = give_get_option( 'session_lifetime' );
74 2
75
		//PHP Sessions
76
		if ( $this->use_php_sessions ) {
77
78
			if ( is_multisite() ) {
79
80
				$this->prefix = '_' . get_current_blog_id();
81
82
			}
83
84
			add_action( 'init', array( $this, 'maybe_start_session' ), - 2 );
85
86
		} else {
87
88
			if ( ! $this->should_start_session() ) {
89
				return;
90
			}
91
92
			// Use WP_Session
93
			if ( ! defined( 'WP_SESSION_COOKIE' ) ) {
94
				define( 'WP_SESSION_COOKIE', 'give_wp_session' );
95
			}
96
97
			if ( ! class_exists( 'Recursive_ArrayAccess' ) ) {
98
				require_once GIVE_PLUGIN_DIR . 'includes/libraries/sessions/class-recursive-arrayaccess.php';
99
			}
100
101
			if ( ! class_exists( 'WP_Session' ) ) {
102
				require_once GIVE_PLUGIN_DIR . 'includes/libraries/sessions/class-wp-session.php';
103
				require_once GIVE_PLUGIN_DIR . 'includes/libraries/sessions/wp-session.php';
104
			}
105
106
			add_filter( 'wp_session_expiration_variant', array( $this, 'set_expiration_variant_time' ), 99999 );
107
			add_filter( 'wp_session_expiration', array( $this, 'set_expiration_time' ), 99999 );
108
109
		}
110
111
		//Init Session
112
		if ( empty( $this->session ) && ! $this->use_php_sessions ) {
113
			add_action( 'plugins_loaded', array( $this, 'init' ), - 1 );
114
		} else {
115
			add_action( 'init', array( $this, 'init' ), - 1 );
116
		}
117
118
		//Set cookie on Donation Completion page
119
		add_action( 'give_pre_process_purchase', array( $this, 'set_session_cookies' ) );
120
121
	}
122
123
	/**
124
	 * Setup the Session instance
125
	 *
126
	 * @access public
127
	 * @since  1.0
128
	 * @return array $this->session
129
	 */
130
	public function init() {
131
132
		if ( $this->use_php_sessions ) {
133
			$this->session = isset( $_SESSION[ 'give' . $this->prefix ] ) && is_array( $_SESSION[ 'give' . $this->prefix ] ) ? $_SESSION[ 'give' . $this->prefix ] : array();
134
		} else {
135
			$this->session = WP_Session::get_instance();
136
		}
137
138
		return $this->session;
139
140
	}
141
142
143
	/**
144
	 * Retrieve session ID
145
	 *
146
	 * @access public
147
	 * @since  1.0
148
	 * @return string Session ID
149
	 */
150
	public function get_id() {
151
		return $this->session->session_id;
152
	}
153
154
155
	/**
156
	 * Retrieve a session variable
157
	 *
158
	 * @access public
159
	 * @since  1.0
160
	 *
161 12
	 * @param string $key Session key
162 12
	 *
163
	 * @return string Session variable
164 12
	 */
165
	public function get( $key ) {
166
		$key = sanitize_key( $key );
167
168
		return isset( $this->session[ $key ] ) ? maybe_unserialize( $this->session[ $key ] ) : false;
169
170
	}
171
172
	/**
173
	 * Set a session variable
174
	 *
175
	 * @since 1.0
176
	 *
177
	 * @param $key $_SESSION key
0 ignored issues
show
Documentation introduced by
The doc-type $key could not be parsed: Unknown type name "$key" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
Bug introduced by
There is no parameter named $_SESSION. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
178 11
	 * @param $value $_SESSION variable
0 ignored issues
show
Documentation introduced by
The doc-type $value could not be parsed: Unknown type name "$value" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
Bug introduced by
There is no parameter named $_SESSION. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
179
	 *
180 11
	 * @return mixed Session variable
181
	 */
182 11
	public function set( $key, $value ) {
183 9
184 9
		$key = sanitize_key( $key );
185 9
186
		if ( is_array( $value ) ) {
187
			$this->session[ $key ] = serialize( $value );
188 11
		} else {
189 11
			$this->session[ $key ] = $value;
190 11
		}
191
192 11
		if ( $this->use_php_sessions ) {
193
			$_SESSION[ 'give' . $this->prefix ] = $this->session;
194
		}
195
196
		return $this->session[ $key ];
197
	}
198
199
	/**
200
	 * Set Session Cookies
201
	 *
202
	 * @description: Cookies are used to increase the session lifetime using the give setting; this is helpful for when a user closes their browser after making a donation and comes back to the site.
203
	 *
204
	 * @access public
205
	 * @hook
206
	 * @since 1.4
207
	 */
208
	public function set_session_cookies() {
209
		if( ! headers_sent() ) {
210
			$lifetime = current_time( 'timestamp' ) + $this->set_expiration_time();
211
			@setcookie( session_name(), session_id(), $lifetime, COOKIEPATH, COOKIE_DOMAIN, false  );
212
			@setcookie( session_name() . '_expiration', $lifetime, $lifetime,  COOKIEPATH, COOKIE_DOMAIN, false  );
213
		}
214
	}
215
216
	/**
217
	 * Set Cookie Variant Time
218
	 *
219
	 * @description Force the cookie expiration variant time to custom expiration option, less and hour; defaults to 23 hours (set_expiration_variant_time used in WP_Session)
220
	 *
221
	 * @access      public
222
	 * @since       1.0
223
	 *
224
	 * @return int
225
	 */
226
	public function set_expiration_variant_time() {
227
228
		return ( ! empty( $this->exp_option ) ? ( intval( $this->exp_option ) - 3600 ) : 30 * 60 * 23 );
229
	}
230
231
	/**
232
	 * Set the Cookie Expiration
233
	 *
234
	 * @description Force the cookie expiration time if set, default to 24 hours
235 2
	 *
236
	 * @access      public
237 2
	 * @since       1.0
238
	 *
239
	 * @return int
240 2
	 */
241
	public function set_expiration_time() {
242 2
243
		return ( ! empty( $this->exp_option ) ? intval( $this->exp_option ) : 30 * 60 * 24 );
244
	}
245
246
	/**
247
	 * Starts a new session if one has not started yet.
248
	 *
249
	 * @return null
250
	 * Checks to see if the server supports PHP sessions or if the GIVE_USE_PHP_SESSIONS constant is defined
251
	 *
252
	 * @access public
253
	 * @since  1.0
254
	 * @return bool $ret True if we are using PHP sessions, false otherwise
255
	 */
256
	public function use_php_sessions() {
257
258
		$ret = false;
259
260
		// If the database variable is already set, no need to run autodetection
261
		$give_use_php_sessions = (bool) get_option( 'give_use_php_sessions' );
262 2
263
		if ( ! $give_use_php_sessions ) {
264
265
			// Attempt to detect if the server supports PHP sessions
266 2
			if ( function_exists( 'session_start' ) && ! ini_get( 'safe_mode' ) ) {
267
268 2
				$this->set( 'give_use_php_sessions', 1 );
269 2
270 2
				if ( $this->get( 'give_use_php_sessions' ) ) {
271
272 2
					$ret = true;
273
274
					// Set the database option
275
					update_option( 'give_use_php_sessions', true );
276
277
				}
278
279
			}
280
281
		} else {
282
283
			$ret = $give_use_php_sessions;
284
		}
285
286
		// Enable or disable PHP Sessions based on the GIVE_USE_PHP_SESSIONS constant
287
		if ( defined( 'GIVE_USE_PHP_SESSIONS' ) && GIVE_USE_PHP_SESSIONS ) {
288
			$ret = true;
289
		} else if ( defined( 'GIVE_USE_PHP_SESSIONS' ) && ! GIVE_USE_PHP_SESSIONS ) {
290
			$ret = false;
291
		}
292
293
		return (bool) apply_filters( 'give_use_php_sessions', $ret );
294
	}
295
296
	/**
297
	 * Determines if we should start sessions
298
	 *
299
	 * @since  1.4
300
	 * @return bool
301
	 */
302
	public function should_start_session() {
303
304
		$start_session = true;
305
306
		if ( ! empty( $_SERVER['REQUEST_URI'] ) ) {
307
308
			$blacklist = apply_filters( 'give_session_start_uri_blacklist', array(
309
				'feed',
310
				'feed',
311
				'feed/rss',
312
				'feed/rss2',
313
				'feed/rdf',
314
				'feed/atom',
315
				'comments/feed/'
316
			) );
317
			$uri       = ltrim( $_SERVER['REQUEST_URI'], '/' );
318
			$uri       = untrailingslashit( $uri );
319
			if ( in_array( $uri, $blacklist ) ) {
320
				$start_session = false;
321
			}
322
			if ( false !== strpos( $uri, 'feed=' ) ) {
323
				$start_session = false;
324
			}
325
			if ( is_admin() ) {
326
				$start_session = false;
327
			}
328
		}
329
330
		return apply_filters( 'give_start_session', $start_session );
331
	}
332
333
	/**
334
	 * Maybe Start Session
335
	 *
336
	 * @description Starts a new session if one hasn't started yet.
337
	 * @see         http://php.net/manual/en/function.session-set-cookie-params.php
338
	 */
339
	public function maybe_start_session() {
340
341
		if ( ! $this->should_start_session() ) {
342
			return;
343
		}
344
345
		if ( ! session_id() && ! headers_sent() ) {
346
			session_start();
347
		}
348
349
	}
350
351
352
	/**
353
	 * Get Session Expiration
354
	 *
355
	 * @description  Looks at the session cookies and returns the expiration date for this session if applicable
356
	 */
357
	public function get_session_expiration() {
358
359
		$expiration = false;
360
361
		if ( session_id() && isset( $_COOKIE[ session_name() . '_expiration' ] ) ) {
362
363
			$expiration = date( 'D, d M Y h:i:s', intval( $_COOKIE[ session_name() . '_expiration' ] ) );
364
365
		}
366
367
		return $expiration;
368
369
	}
370
371
}
372
373