PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.11.3
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.11.3
1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 All 211 releases
charitable / includes / public / class-charitable-session.php

class-charitable-session.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.11.3, at includes/public/class-charitable-session.php

497 lines 11.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Responsible for managing user sessions.
4 *
5 * @package Charitable/Classes/Charitable Session
6 * @copyright Copyright (c) 2023, WP Charitable LLC
7 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
8 * @since 1.0.0
9 * @version 1.8.9.1
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 if ( ! class_exists( 'Charitable_Session' ) ) :
18
19 /**
20 * Charitable_Session
21 *
22 * @since 1.0.0
23 */
24 class Charitable_Session {
25
26 /**
27 * Holds our session data
28 *
29 * @since 1.0.0
30 *
31 * @var WP_Session
32 */
33 private $session;
34
35 /**
36 * Whether to disable the cookie.
37 *
38 * @since 1.6.27
39 *
40 * @var boolean
41 */
42 private $disable_cookie;
43
44 /**
45 * Instantiate session object.
46 *
47 * @since 1.0.0
48 * @since 1.5.4 Access changed to public.
49 */
50 public function __construct() {
51 /**
52 * Filter to disable the cookie.
53 *
54 * @since 1.6.27
55 *
56 * @param boolean $disable Whether to disable the cookie.
57 */
58 $this->disable_cookie = apply_filters( 'charitable_disable_cookie', false );
59
60 if ( ! $this->should_start_session() ) {
61 return;
62 }
63
64 if ( ! defined( 'WP_SESSION_COOKIE' ) ) {
65 define( 'WP_SESSION_COOKIE', 'charitable_session' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound -- This is a bundled library constant. Changing it would break existing functionality.
66 }
67
68 if ( ! class_exists( 'Recursive_ArrayAccess' ) ) {
69 require_once( charitable()->get_path( 'includes' ) . 'libraries/wp-session/class-recursive-arrayaccess.php' );
70 }
71
72 if ( ! class_exists( 'WP_Session_Utils' ) ) {
73 require_once( charitable()->get_path( 'includes' ) . 'libraries/wp-session/class-wp-session-utils.php' );
74 }
75
76 if ( defined( 'WP_CLI' ) && WP_CLI ) {
77 require_once( charitable()->get_path( 'includes' ) . 'libraries/wp-session/wp-cli.php' );
78 }
79
80 if ( ! class_exists( 'WP_Session' ) ) {
81 require_once( charitable()->get_path( 'includes' ) . 'libraries/wp-session/class-wp-session.php' );
82 require_once( charitable()->get_path( 'includes' ) . 'libraries/wp-session/wp-session.php' );
83 }
84
85 /* Set the expiration length & variant of the session */
86 add_filter( 'wp_session_expiration', array( $this, 'set_session_length' ), 99999 );
87 add_filter( 'wp_session_expiration_variant', array( $this, 'set_session_expiration_variant_length' ), 99999 );
88
89 $this->init();
90 }
91
92 /**
93 * Create the session.
94 *
95 * @since 1.4.17
96 *
97 * @return WP_Session
98 */
99 public function init() {
100 $this->session = WP_Session::get_instance();
101
102 /* We're missing a Session ID, so we'll need to queue up our session scripts. */
103 if ( ! $this->has_session_id() || $this->disable_cookie ) {
104 add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ), 1 );
105 }
106
107 return $this->session;
108 }
109
110 /**
111 * Set up scripts to create & manage cookies client-side.
112 *
113 * @since 1.5.0
114 *
115 * @return void
116 */
117 public function enqueue_scripts() {
118
119 $min = charitable_get_min_suffix();
120 $version = charitable()->get_version();
121
122 $assets_dir = charitable()->get_path( 'assets', false );
123
124 wp_register_script(
125 'js-cookie',
126 $assets_dir . 'js/libraries/js-cookie' . $min . '.js',
127 array(),
128 '2.1.4',
129 false
130 );
131
132 wp_enqueue_script(
133 'charitable-sessions',
134 $assets_dir . 'js/charitable-session' . $min . '.js',
135 array( 'js-cookie' ),
136 $version,
137 false
138 );
139
140 wp_localize_script(
141 'charitable-sessions',
142 'CHARITABLE_SESSION',
143 array(
144 'ajaxurl' => admin_url( 'admin-ajax.php' ),
145 'id' => $this->get_session_id(),
146 'cookie_name' => WP_SESSION_COOKIE,
147 'expiration' => $this->set_session_length(),
148 'expiration_variant' => $this->set_session_expiration_variant_length(),
149 'secure' => (bool) apply_filters( 'wp_session_cookie_secure', false ), // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- This is a bundled library hook. Changing it would break existing functionality.
150 'cookie_path' => COOKIEPATH,
151 'cookie_domain' => COOKIE_DOMAIN,
152 'generated_id' => WP_Session_Utils::generate_id(),
153 'disable_cookie' => $this->disable_cookie,
154 )
155 );
156 }
157
158 /**
159 * Returns and/or create the single instance of this class.
160 *
161 * @since 1.2.0
162 *
163 * @return Charitable_Session
164 */
165 public static function get_instance() {
166 return charitable()->registry()->get( 'session' );
167 }
168
169 /**
170 * Checks whether the current request has a session ID.
171 *
172 * @since 1.5.0
173 *
174 * @return boolean
175 */
176 public function has_session_id() {
177 return ! empty( $this->session->session_id );
178 }
179
180 /**
181 * Return a session variable.
182 *
183 * @since 1.0.0
184 *
185 * @param string $key Session variable key.
186 * @return mixed Session variable
187 */
188 public function get( $key ) {
189 $key = sanitize_key( $key );
190 return isset( $this->session[ $key ] ) ? maybe_unserialize( $this->session[ $key ] ) : false;
191 }
192
193 /**
194 * Set a session variable.
195 *
196 * @since 1.0.0
197 *
198 * @param string $key Session variable key.
199 * @param mixed $value The value of the session variable.
200 * @return mixed The session variable value.
201 */
202 public function set( $key, $value ) {
203 $key = sanitize_key( $key );
204
205 if ( is_array( $value ) ) {
206 $this->session[ $key ] = serialize( $value );
207 } else {
208 $this->session[ $key ] = $value;
209 }
210
211 return $this->session[ $key ];
212 }
213
214 /**
215 * Remove a session variable.
216 *
217 * @since 1.5.0
218 *
219 * @param string $key Session variable key.
220 * @return mixed The session variable value.
221 */
222 public function remove( $key ) {
223 unset( $this->session[ $key ] );
224 }
225
226 /**
227 * Set the length of the cookie session to 24 hours.
228 *
229 * @since 1.0.0
230 *
231 * @return int
232 */
233 public function set_session_length() {
234 if ( ! defined( 'DAY_IN_SECONDS' ) ) {
235 define( 'DAY_IN_SECONDS', 86400 );
236 }
237
238 /**
239 * Filter the length of the session.
240 *
241 * @since 1.0.0
242 *
243 * @param int $seconds Defaults to 86400 — one day.
244 */
245 return apply_filters( 'charitable_session_length', DAY_IN_SECONDS );
246 }
247
248 /**
249 * Set the cookie expiration variant time to 23 hours.
250 *
251 * @since 1.0.0
252 *
253 * @return int
254 */
255 public function set_session_expiration_variant_length() {
256 if ( ! defined( 'HOUR_IN_SECONDS' ) ) {
257 define( 'HOUR_IN_SECONDS', 3600 );
258 }
259
260 /**
261 * Filter the variation length of the session.
262 *
263 * @since 1.0.0
264 *
265 * @param int $seconds Defaults to 82800 — 23 hours.
266 */
267 return apply_filters( 'charitable_session_expiration_variant_length', HOUR_IN_SECONDS * 23 );
268 }
269
270 /**
271 * Add a donation to a campaign to the session.
272 *
273 * @since 1.0.0
274 * @since 1.6.25 Added $period parameter.
275 *
276 * @param int $campaign_id Campaign ID.
277 * @param int $amount Donation amount.
278 * @param string $period Set the donation period. Defaults to once.
279 * @return void
280 */
281 public function add_donation( $campaign_id, $amount, $period = 'once' ) {
282 $donations = $this->get( 'donations' );
283
284 $campaign_donation = isset( $donations[ $campaign_id ] ) ? $donations[ $campaign_id ] : array();
285 $campaign_donation['amount'] = floatval( charitable_get_currency_helper()->cast_to_decimal_format( $amount ) );
286 $campaign_donation['donation_period'] = $period;
287
288 $donations[ $campaign_id ] = $campaign_donation;
289
290 $this->set( 'donations', $donations );
291 }
292
293 /**
294 * Remove a donation from the session.
295 *
296 * @since 1.0.0
297 *
298 * @param int $campaign_id Campaign ID.
299 * @return void
300 */
301 public function remove_donation( $campaign_id ) {
302 $donations = $this->get( 'donations' );
303
304 if ( isset( $donations[ $campaign_id ] ) ) {
305 unset( $donations[ $campaign_id ] );
306 }
307
308 $this->set( 'donations', $donations );
309 }
310
311 /**
312 * Return the donation in session for a campaign.
313 *
314 * @since 1.0.0
315 *
316 * @param int $campaign_id The campaign ID.
317 * @return false|array
318 */
319 public function get_donation_by_campaign( $campaign_id ) {
320 $donations = $this->get( 'donations' );
321 return isset( $donations[ $campaign_id ] ) ? $donations[ $campaign_id ] : false;
322 }
323
324 /**
325 * Store the donation key in the session, to ensure the user can access their receipt.
326 *
327 * @since 1.1.2
328 *
329 * @param string $donation_key The transaction key for the donation.
330 * @return void
331 */
332 public function add_donation_key( $donation_key ) {
333 $keys = $this->get( 'donation-keys' );
334
335 if ( ! $keys ) {
336 $keys = array();
337 }
338
339 $keys[] = $donation_key;
340
341 $this->set( 'donation-keys', $keys );
342 }
343
344 /**
345 * Checks whether the donation key is stored in the session.
346 *
347 * @since 1.0.0
348 *
349 * @param string $donation_key The transaction key for the donation.
350 * @return boolean
351 */
352 public function has_donation_key( $donation_key ) {
353 $keys = $this->get( 'donation-keys' );
354
355 if ( ! $keys ) {
356 return false;
357 }
358
359 return in_array( $donation_key, $keys );
360 }
361
362 /**
363 * Add the all notices to the session.
364 *
365 * @since 1.0.0
366 *
367 * @return void
368 */
369 public function add_notices() {
370 $this->set( 'notices', charitable_get_notices()->get_notices() );
371 }
372
373 /**
374 * Return any notices set in the session.
375 *
376 * @since 1.4.0
377 *
378 * @return array Session variable
379 */
380 public function get_notices() {
381 $notices = $this->get( 'notices' );
382
383 if ( $notices ) {
384 return $notices;
385 }
386
387 return array(
388 'error' => array(),
389 'warning' => array(),
390 'success' => array(),
391 'info' => array(),
392 );
393 }
394
395 /**
396 * Returns the session ID.
397 *
398 * @since 1.3.5
399 *
400 * @return string Session ID
401 */
402 public function get_session_id() {
403 if ( isset( $this->session->session_id ) ) {
404 return $this->session->session_id;
405 } else {
406 return false;
407 }
408 }
409
410 /**
411 * Determines if we should start sessions
412 *
413 * @since 1.4.17
414 *
415 * @return boolean
416 */
417 public function should_start_session() {
418 $start_session = true;
419
420 if ( ! empty( $_SERVER['REQUEST_URI'] ) ) {
421 $blocklist = $this->get_blocklist();
422 $uri = ltrim( $_SERVER['REQUEST_URI'], '/' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
423 $uri = untrailingslashit( $uri );
424
425 if ( in_array( $uri, $blocklist ) ) {
426 $start_session = false;
427 }
428
429 if ( false !== strpos( $uri, 'feed=' ) ) {
430 $start_session = false;
431 }
432 }
433
434 /**
435 * Filter whether the session should be started for the current request.
436 *
437 * @since 1.4.17
438 *
439 * @param boolean $start_session Whether to start the session.
440 */
441 return apply_filters( 'charitable_start_session', $start_session );
442 }
443
444 /**
445 * Retrieve the URI blocklist.
446 *
447 * These are the URIs where we never start sessions.
448 *
449 * @since 1.4.17
450 *
451 * @return array
452 */
453 public function get_blocklist() {
454 /**
455 * Filter the blocklist of URIs where sessions should not be started.
456 *
457 * @since 1.4.17
458 *
459 * @param string[] $blocklist Array of URIs.
460 */
461 $blocklist = apply_filters(
462 'charitable_session_start_uri_blocklist',
463 array(
464 'feed',
465 'feed/rss',
466 'feed/rss2',
467 'feed/rdf',
468 'feed/atom',
469 'comments/feed',
470 )
471 );
472
473 /**
474 * Deprecated filter retained for backwards compatibility.
475 *
476 * @since 1.4.17
477 * @since 1.6.42 Deprecated in favour of charitable_session_start_uri_blocklist
478 *
479 * @param string[] $blocklist Array of URIs.
480 */
481 $blocklist = apply_filters( 'charitable_session_start_uri_blacklist', $blocklist );
482
483 /* Look to see if WordPress is in a sub folder or this is a network site that uses sub folders */
484 $folder = str_replace( network_home_url(), '', get_site_url() );
485
486 if ( ! empty( $folder ) ) {
487 foreach ( $blocklist as $path ) {
488 $blocklist[] = $folder . '/' . $path;
489 }
490 }
491
492 return $blocklist;
493 }
494 }
495
496 endif;
497