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 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 All 212 releases
charitable / includes / user-management / class-charitable-user-management.php

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

411 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class that manages the hook functions for the forgot password form.
4 *
5 * @package Charitable/User Management/User Management
6 * @author Rafe Colton, David Bisset
7 * @copyright Copyright (c) 2023, WP Charitable LLC
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.4.0
10 * @version 1.6.47
11 */
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 if ( ! class_exists( 'Charitable_User_Management' ) ) :
18
19 /**
20 * Charitable_User_Management class
21 *
22 * @since 1.4.0
23 */
24 class Charitable_User_Management {
25
26 /**
27 * The class instance.
28 *
29 * @var Charitable_User_Management
30 *
31 * @since 1.4.0
32 */
33 private static $instance;
34
35 /**
36 * Returns and/or create the single instance of this class.
37 *
38 * @since 1.4.0
39 *
40 * @return Charitable_User_Management
41 */
42 public static function get_instance() {
43 return self::$instance ??= new self();
44 }
45
46 /**
47 * Set up the class.
48 *
49 * @since 1.4.0
50 */
51 private function __construct() {
52 }
53
54 /**
55 * Check whether we have clicked on a password reset link.
56 *
57 * If so, redirect to the password reset page without the query string.
58 *
59 * @since 1.4.0
60 *
61 * @return false|void False if no redirect takes place.
62 */
63 public function maybe_redirect_to_password_reset() {
64 if ( ! charitable_is_page( 'reset_password_page' ) ) {
65 return false;
66 }
67
68 if ( ! isset( $_GET['key'] ) || ! isset( $_GET['login'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
69 return false;
70 }
71
72 $value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
73
74 $this->set_reset_cookie( $value );
75
76 wp_safe_redirect( esc_url_raw( charitable_get_permalink( 'reset_password_page' ) ) );
77
78 exit();
79 }
80
81 /**
82 * Check if user is attempting to access the default reset password page
83 *
84 * If so, and charitable_disable_wp_login is set, redirect them to the custom reset password page
85 *
86 * @since 1.4.0
87 *
88 * @return void
89 */
90 public function maybe_redirect_to_custom_password_reset_page() {
91 if ( ! apply_filters( 'charitable_disable_wp_login', false ) ) {
92 return;
93 }
94
95 if ( 'wp' == charitable_get_option( 'login_page', 'wp' ) ) {
96 return;
97 }
98
99 $redirect_url = charitable_get_permalink( 'reset_password_page' );
100 $redirect_url = add_query_arg( 'login', esc_attr( $_REQUEST['login'] ), $redirect_url ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotValidated,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
101 $redirect_url = add_query_arg( 'key', esc_attr( $_REQUEST['key'] ), $redirect_url ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotValidated,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
102
103 wp_safe_redirect( esc_url_raw( $redirect_url ) );
104
105 exit();
106 }
107
108 /**
109 * Check if a failed user login attempt originated from Charitable login form.
110 *
111 * If so redirect user to Charitable login page.
112 *
113 * @since 1.4.0
114 *
115 * @param WP_User|WP_Error $user_or_error
116 * @param string $username
117 * @return WP_User|void
118 */
119 public function maybe_redirect_at_authenticate( $user_or_error, $username ) {
120 if ( 'POST' != $_SERVER['REQUEST_METHOD'] ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
121 return $user_or_error;
122 }
123
124 if ( ! is_wp_error( $user_or_error ) ) {
125 return $user_or_error;
126 }
127
128 if ( ! isset( $_POST['charitable'] ) || ! $_POST['charitable'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
129 return $user_or_error;
130 }
131
132 foreach ( $user_or_error->errors as $code => $error ) {
133
134 /* Make sure the error messages link to our forgot password page, not WordPress' */
135 switch ( $code ) {
136
137 case 'invalid_email':
138 $error = __( '<strong>ERROR</strong>: Invalid email address.', 'charitable' ) .
139 ' <a href="' . esc_url( charitable_get_permalink( 'forgot_password_page' ) ) . '">' .
140 __( 'Lost your password?', 'charitable' ) .
141 '</a>';
142 break;
143
144 case 'incorrect_password':
145 $error = sprintf(
146 /* translators: %s: email address */
147 __( '<strong>ERROR</strong>: The password you entered for %s is incorrect.', 'charitable' ),
148 '<strong>' . $username . '</strong>'
149 ) .
150 ' <a href="' . esc_url( charitable_get_permalink( 'forgot_password_page' ) ) . '">' .
151 __( 'Lost your password?', 'charitable' ) .
152 '</a>';
153 break;
154
155 default:
156 $error = $error[0];
157 }
158
159 charitable_get_notices()->add_error( $error );
160 }
161
162 charitable_get_session()->add_notices();
163
164 $redirect_url = charitable_get_permalink( 'login_page' );
165
166 if ( strlen( $username ) ) {
167 $redirect_url = add_query_arg( 'username', $username, $redirect_url );
168 }
169
170 wp_safe_redirect( esc_url_raw( $redirect_url ) );
171
172 exit();
173 }
174
175 /**
176 * Check if user is attempting to access the forgot password page
177 *
178 * If so, and charitable_disable_wp_login is set, redirect them to the custom forgot password page
179 *
180 * @since 1.4.0
181 *
182 * @return void
183 */
184 public function maybe_redirect_to_custom_lostpassword() {
185 /**
186 * Set whether the WP login should be disabled.
187 *
188 * @since 1.4.0
189 *
190 * @param boolean $disable Whether to disable the WP login.
191 */
192 if ( ! apply_filters( 'charitable_disable_wp_login', false ) ) {
193 return;
194 }
195
196 if ( 'wp' == charitable_get_option( 'login_page', 'wp' ) ) {
197 return;
198 }
199
200 if ( $_SERVER['REQUEST_METHOD'] != 'GET' ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
201 return;
202 }
203
204 wp_safe_redirect( esc_url_raw( charitable_get_permalink( 'forgot_password_page' ) ) );
205
206 exit();
207 }
208
209 /**
210 * Set the password reset cookie.
211 *
212 * This is based on the WC_Shortcode_My_Account::set_reset_password_cookie()
213 * method in WooCommerce, which in turn is based on the core implementation
214 * in wp-login.php.
215 *
216 * @since 1.4.0
217 *
218 * @param string $value
219 * @return void
220 */
221 public function set_reset_cookie( $value = '' ) {
222 $rp_cookie = 'wp-resetpass-' . COOKIEHASH;
223 $rp_path = current( explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
224
225 if ( $value ) {
226 setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
227 } else {
228 setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
229 }
230 }
231
232 /**
233 * Hides WP Admin bar if the user is not allowed to see it.
234 *
235 * Uses the builtin show_admin_bar function.
236 *
237 * @see show_admin_bar()
238 *
239 * @since 1.4.0
240 */
241 public function maybe_remove_admin_bar() {
242 /**
243 * To enable the admin bar for users without admin bar access,
244 * you can use this one-liner:
245 *
246 * add_filter( 'charitable_disable_admin_bar', '__return_true' );
247 */
248 if ( ! apply_filters( 'charitable_disable_admin_bar', true ) ) {
249 return;
250 }
251
252 if ( ! $this->user_has_admin_access() ) {
253 show_admin_bar( false );
254 }
255 }
256
257 /**
258 * Redirects the user away from /wp-admin if they are not authorized to access it.
259 *
260 * @since 1.4.0
261 */
262 public function maybe_redirect_away_from_admin() {
263 /* Leave AJAX requests alone. */
264 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
265 return;
266 }
267
268 /**
269 * To enable admin access for users without admin access,
270 * you can use this one-liner:
271 *
272 * add_filter( 'charitable_disable_admin_access', '__return_true' );
273 */
274 if ( ! apply_filters( 'charitable_disable_admin_access', true ) ) {
275 return;
276 }
277
278 if ( $this->user_has_admin_access() ) {
279 return;
280 }
281
282 /**
283 * Specify a custom URL that users should be redirected to.
284 *
285 * @since 1.4.0
286 *
287 * @param false|string Return false to use the default. Otherwise this
288 * must return a URL on the same domain.
289 */
290 $redirect_url = apply_filters( 'charitable_admin_redirect_url', false );
291
292 if ( ! $redirect_url ) {
293 $redirect_url = charitable_get_permalink( 'profile_page' );
294
295 if ( ! $redirect_url ) {
296 $redirect_url = home_url();
297 }
298 }
299
300 wp_safe_redirect( esc_url_raw( $redirect_url ) );
301
302 exit();
303 }
304
305 /**
306 * Redirect the user to the Charitable login page.
307 *
308 * @since 1.4.0
309 *
310 * @return void
311 */
312 public function maybe_redirect_to_charitable_login() {
313 if ( ! apply_filters( 'charitable_disable_wp_login', false ) ) {
314 return;
315 }
316
317 if ( 'wp' == charitable_get_option( 'login_page', 'wp' ) ) {
318 return;
319 }
320
321 /* Don't prevent logging out. */
322 if ( 'GET' != $_SERVER['REQUEST_METHOD'] ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
323 return;
324 }
325
326 wp_safe_redirect( esc_url_raw( charitable_get_permalink( 'login_page' ) ) );
327
328 exit();
329 }
330
331 /**
332 * Send the user verification email.
333 *
334 * @since 1.5.0
335 * @since 1.6.32
336 *
337 * @param WP_User $user An instance of `WP_User`.
338 * @param string $redirect_url Where the user should be redirected to after verifying their email.
339 * @param boolean|null $force_send Whether the link should include an argument to force
340 * resending the email, even if it was sent recently.
341 * @return boolean True if the email is sent. False otherwise.
342 */
343 public function send_verification_email( $user = '', $redirect_url = '', $force_send = null ) {
344 if ( empty( $user ) && array_key_exists( 'user', $_GET ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
345 $user = wp_get_current_user();
346 }
347
348 if ( ! is_a( $user, 'WP_User' ) ) {
349 return false;
350 }
351
352 if ( is_null( $force_send ) ) {
353 $force_send = array_key_exists( 'force_send', $_GET ) && $_GET['force_send']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
354 }
355
356 if ( empty( $redirect_url ) && array_key_exists( 'redirect_url', $_GET ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
357 $redirect_url = $_GET['redirect_url']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
358 }
359
360 /* Prepare the email. */
361 $email = new Charitable_Email_Email_Verification( array( 'user' => $user ) );
362
363 if ( ! $force_send && $email->sent_recently() ) {
364 return false;
365 }
366
367 if ( ! empty( $redirect_url ) ) {
368 /* Ensure that the redirect URL is encoded, but not double-encoded. */
369 $redirect_url = urlencode( urldecode( $redirect_url ) );
370
371 $email->set_redirect_url( $redirect_url );
372 }
373
374 /* If the confirmation link is generated correctly and the email is sent, set a notice. */
375 if ( is_wp_error( $email->get_confirmation_url() ) ) {
376 return false;
377 }
378
379 return $email->send();
380 }
381
382 /**
383 * Check whether the user has admin access.
384 *
385 * @since 1.4.0
386 *
387 * @return boolean
388 */
389 private function user_has_admin_access() {
390 if ( ! is_user_logged_in() ) {
391 return false;
392 }
393
394 $has_access = current_user_can( 'edit_posts' )
395 || current_user_can( 'manage_charitable_settings' )
396 || current_user_can( 'edit_products' )
397 || current_user_can( 'translate' );
398
399 /**
400 * Filter whether the user should have access to the WordPress dashboard.
401 *
402 * @since 1.4.0
403 *
404 * @param boolean $has_access Whether the user has access.
405 */
406 return apply_filters( 'charitable_user_has_admin_access', $has_access );
407 }
408 }
409
410 endif;
411