PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.6.22
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.6.22
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 1.8.0 All 210 releases
charitable / includes / forms / class-charitable-profile-form.php

class-charitable-profile-form.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.6.22, at includes/forms/class-charitable-profile-form.php

633 lines 16.1 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 display and processing of the profile form.
4 *
5 * @package Charitable/Classes/Charitable_Profile_Form
6 * @author Eric Daams
7 * @copyright Copyright (c) 2019, Studio 164a
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.0.0
10 * @version 1.5.1
11 */
12
13 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 if ( ! class_exists( 'Charitable_Profile_Form' ) ) :
19
20 /**
21 * Charitable_Profile_Form
22 *
23 * @since 1.0.0
24 */
25 class Charitable_Profile_Form extends Charitable_Form {
26
27 /**
28 * Shortcode parameters.
29 *
30 * @var array
31 */
32 protected $shortcode_args;
33
34 /**
35 * @var string
36 */
37 protected $nonce_action = 'charitable_user_profile';
38
39 /**
40 * @var string
41 */
42 protected $nonce_name = '_charitable_user_profile_nonce';
43
44 /**
45 * Action to be executed upon form submission.
46 *
47 * @var string
48 */
49 protected $form_action = 'update_profile';
50
51 /**
52 * The current user.
53 *
54 * @var Charitable_User
55 */
56 protected $user;
57
58 /**
59 * Create class object.
60 *
61 * @since 1.0.0
62 *
63 * @param array $args User-defined shortcode attributes.
64 */
65 public function __construct( $args = array() ) {
66 $this->id = uniqid();
67 $this->shortcode_args = $args;
68
69 /* For backwards-compatibility */
70 add_action( 'charitable_form_field', array( $this, 'render_field' ), 10, 6 );
71 }
72
73 /**
74 * Return the current user's Charitable_User object.
75 *
76 * @since 1.0.0
77 *
78 * @return Charitable_User
79 */
80 public function get_user() {
81 if ( ! isset( $this->user ) ) {
82 $this->user = new Charitable_User( wp_get_current_user() );
83 }
84
85 return $this->user;
86 }
87
88 /**
89 * Returns the value of a particular key.
90 *
91 * @since 1.0.0
92 *
93 * @param string $key The key of the data we are searching for.
94 * @param string $default Optional. The value that will be used if none is set.
95 * @return mixed
96 */
97 public function get_user_value( $key, $default = '' ) {
98 if ( isset( $_POST[ $key ] ) ) {
99 return $_POST[ $key ];
100 }
101
102 $value = $this->get_user_prop_or_default( $key, $default );
103
104 /**
105 * Deprecated filter. Use the filter below instead.
106 *
107 * @deprecated 1.8.0
108 *
109 * @since 1.0.0
110 * @since 1.5.7 Deprecated.
111 *
112 * @param string $value The value.
113 * @param string $key The key of the value.
114 * @param Charitable_User $user Instance of `Charitable_User`.
115 */
116 $value = apply_filters( 'charitable_campaign_submission_user_value', $value, $key, $this->get_user() );
117
118 /**
119 * Filter the set value for a particular key.
120 *
121 * @since 1.5.7
122 *
123 * @param string $value The value.
124 * @param string $key The key of the value.
125 * @param Charitable_User $user Instance of `Charitable_User`.
126 */
127 return apply_filters( 'charitable_profile_value', $value, $key, $this->get_user() );
128 }
129
130 /**
131 * Return the core user fields.
132 *
133 * @since 1.0.0
134 *
135 * @return array
136 */
137 public function get_user_fields() {
138 $user_fields = apply_filters( 'charitable_user_fields', array(
139 'username' => array(
140 'type' => 'paragraph',
141 'priority' => '',
142 'content' => sprintf(
143 /* translators: %s: username */
144 __( 'Username: %s.', 'charitable' ),
145 $this->get_user()->user_login
146 ),
147 ),
148 'first_name' => array(
149 'label' => __( 'First name', 'charitable' ),
150 'type' => 'text',
151 'priority' => 4,
152 'required' => true,
153 'value' => $this->get_user_value( 'first_name' ),
154 ),
155 'last_name' => array(
156 'label' => __( 'Last name', 'charitable' ),
157 'type' => 'text',
158 'priority' => 6,
159 'required' => true,
160 'value' => $this->get_user_value( 'last_name' ),
161 ),
162 'user_email' => array(
163 'label' => __( 'Email', 'charitable' ),
164 'type' => 'email',
165 'required' => true,
166 'priority' => 8,
167 'value' => $this->get_user_value( 'user_email' ),
168 ),
169 'organisation' => array(
170 'label' => __( 'Organization', 'charitable' ),
171 'type' => 'text',
172 'priority' => 10,
173 'required' => false,
174 'value' => $this->get_user_value( 'organisation' ),
175 ),
176 'description' => array(
177 'label' => __( 'Bio', 'charitable' ),
178 'type' => 'textarea',
179 'required' => false,
180 'priority' => 12,
181 'value' => $this->get_user_value( 'description' ),
182 ),
183 ), $this );
184
185 uasort( $user_fields, 'charitable_priority_sort' );
186
187 return $user_fields;
188 }
189
190 /**
191 * Return the user's address fields.
192 *
193 * @since 1.0.0
194 *
195 * @return array
196 */
197 public function get_address_fields() {
198 $address_fields = apply_filters( 'charitable_user_address_fields', array(
199 'address' => array(
200 'label' => __( 'Address', 'charitable' ),
201 'type' => 'text',
202 'priority' => 22,
203 'required' => false,
204 'value' => $this->get_user_value( 'donor_address' ),
205 ),
206 'address_2' => array(
207 'label' => __( 'Address 2', 'charitable' ),
208 'type' => 'text',
209 'priority' => 24,
210 'required' => false,
211 'value' => $this->get_user_value( 'donor_address_2' ),
212 ),
213 'city' => array(
214 'label' => __( 'City', 'charitable' ),
215 'type' => 'text',
216 'priority' => 26,
217 'required' => false,
218 'value' => $this->get_user_value( 'donor_city' ),
219 ),
220 'state' => array(
221 'label' => __( 'State', 'charitable' ),
222 'type' => 'text',
223 'priority' => 28,
224 'required' => false,
225 'value' => $this->get_user_value( 'donor_state' ),
226 ),
227 'postcode' => array(
228 'label' => __( 'Postcode / ZIP code', 'charitable' ),
229 'type' => 'text',
230 'priority' => 30,
231 'required' => false,
232 'value' => $this->get_user_value( 'donor_postcode' ),
233 ),
234 'country' => array(
235 'label' => __( 'Country', 'charitable' ),
236 'type' => 'select',
237 'options' => charitable_get_location_helper()->get_countries(),
238 'priority' => 32,
239 'required' => false,
240 'value' => $this->get_user_value( 'donor_country', charitable_get_option( 'country' ) ),
241 ),
242 'phone' => array(
243 'label' => __( 'Phone', 'charitable' ),
244 'type' => 'text',
245 'priority' => 34,
246 'required' => false,
247 'value' => $this->get_user_value( 'donor_phone' ),
248 ),
249 ), $this );
250
251 uasort( $address_fields, 'charitable_priority_sort' );
252
253 return $address_fields;
254 }
255
256 /**
257 * Return the social fields.
258 *
259 * @since 1.0.0
260 *
261 * @return array
262 */
263 public function get_social_fields() {
264 $social_fields = apply_filters( 'charitable_user_social_fields', array(
265 'user_url' => array(
266 'label' => __( 'Your Website', 'charitable' ),
267 'type' => 'url',
268 'priority' => 42,
269 'required' => false,
270 'value' => $this->get_user_value( 'user_url' ),
271 ),
272 'twitter' => array(
273 'label' => __( 'Twitter', 'charitable' ),
274 'type' => 'text',
275 'priority' => 44,
276 'required' => false,
277 'value' => $this->get_user_value( 'twitter' ),
278 ),
279 'facebook' => array(
280 'label' => __( 'Facebook', 'charitable' ),
281 'type' => 'text',
282 'priority' => 46,
283 'required' => false,
284 'value' => $this->get_user_value( 'facebook' ),
285 ),
286 ), $this );
287
288 uasort( $social_fields, 'charitable_priority_sort' );
289
290 return $social_fields;
291 }
292
293 /**
294 * Maybe add communication preferences fields.
295 *
296 * @since 1.6.2
297 *
298 * @param array $fields The existing profile form fields.
299 * @return array
300 */
301 public function maybe_get_communication_preferences_fields( $fields ) {
302 if ( ! charitable_is_contact_consent_activated() ) {
303 return $fields;
304 }
305
306 $donor = $this->get_user()->get_donor();
307
308 if ( array_key_exists( 'contact_consent', $_POST ) ) {
309 $consent = $_POST['contact_consent'];
310 } elseif ( is_null( $donor ) ) {
311 $consent = false;
312 } else {
313 $consent = $donor->contact_consent;
314 }
315
316 /**
317 * Filter the communication preferences fields.
318 *
319 * @since 1.6.2
320 *
321 * @param array $communication_fields List of fields.
322 * @param Charitable_Profile_Form $form Instance of `Charitable_Profile_Form`.
323 */
324 $communication_fields = apply_filters( 'charitable_user_communication_preferences_fields', array(
325 'contact_consent' => array(
326 'type' => 'checkbox',
327 'label' => charitable_get_option( 'contact_consent_label', __( 'Yes, I am happy for you to contact me via email or phone.', 'charitable' ) ),
328 'priority' => 8,
329 'required' => false,
330 'checked' => $consent,
331 ),
332 ), $this );
333
334 if ( empty( $communication_fields ) ) {
335 return $fields;
336 }
337
338 uasort( $fields, 'charitable_priority_sort' );
339
340 return array_merge( $fields, array(
341 'communication_fields' => array(
342 'legend' => __( 'Communication Preferences', 'charitable' ),
343 'type' => 'fieldset',
344 'fields' => $communication_fields,
345 'priority' => 60,
346 ),
347 ) );
348 }
349
350 /**
351 * Profile fields to be displayed.
352 *
353 * @since 1.0.0
354 *
355 * @return array[]
356 */
357 public function get_fields() {
358 $fields = apply_filters( 'charitable_user_profile_fields', array(
359 'user_fields' => array(
360 'legend' => __( 'Your Details', 'charitable' ),
361 'type' => 'fieldset',
362 'fields' => $this->get_user_fields(),
363 'priority' => 0,
364 ),
365 'password_fields' => array(
366 'legend' => __( 'Change Your Password', 'charitable' ),
367 'type' => 'fieldset',
368 'fields' => $this->get_password_fields(),
369 'priority' => 10,
370 ),
371 'address_fields' => array(
372 'legend' => __( 'Your Address', 'charitable' ),
373 'type' => 'fieldset',
374 'fields' => $this->get_address_fields(),
375 'priority' => 20,
376 ),
377 'social_fields' => array(
378 'legend' => __( 'Your Social Profiles', 'charitable' ),
379 'type' => 'fieldset',
380 'fields' => $this->get_social_fields(),
381 'priority' => 40,
382 ),
383 ), $this );
384
385 $fields = $this->maybe_get_communication_preferences_fields( $fields );
386
387 uasort( $fields, 'charitable_priority_sort' );
388
389 return $fields;
390 }
391
392 /**
393 * Retrieve hidden fields.
394 *
395 * @since 1.6.2
396 *
397 * @return array
398 */
399 public function get_hidden_fields() {
400 return array_merge( parent::get_hidden_fields(), array(
401 'current_email' => $this->get_user()->get_email(),
402 ) );
403 }
404
405 /**
406 * The fields displayed on the password form.
407 *
408 * @since 1.4.0
409 *
410 * @return array[]
411 */
412 public function get_password_fields() {
413 $password_fields = apply_filters( 'charitable_user_profile_password_fields', array(
414 'current_pass' => array(
415 'priority' => 2,
416 'type' => 'password',
417 'label' => __( 'Current Password (leave blank to leave unchanged)', 'charitable' ),
418 'value' => '',
419 'required' => false,
420 ),
421 'user_pass' => array(
422 'priority' => 4,
423 'type' => 'password',
424 'label' => __( 'New Password (leave blank to leave unchanged)', 'charitable' ),
425 'required' => false,
426 ),
427 'user_pass_repeat' => array(
428 'priority' => 6,
429 'type' => 'password',
430 'label' => __( 'New Password (again)', 'charitable' ),
431 'required' => false,
432 ),
433 ), $this );
434
435 uasort( $password_fields, 'charitable_priority_sort' );
436
437 return $password_fields;
438 }
439
440 /**
441 * Returns all fields as a merged array.
442 *
443 * @since 1.0.0
444 *
445 * @return array[]
446 */
447 public function get_merged_fields() {
448 $fields = array();
449
450 foreach ( $this->get_fields() as $key => $section ) {
451
452 if ( isset( $section['fields'] ) ) {
453 $fields = array_merge( $fields, $section['fields'] );
454 } else {
455 $fields[ $key ] = $section;
456 }
457 }
458
459 return $fields;
460 }
461
462 /**
463 * Update profile after form submission.
464 *
465 * @since 1.0.0
466 *
467 * @return void
468 */
469 public static function update_profile() {
470 $form = new Charitable_Profile_Form();
471
472 if ( ! $form->validate_nonce() || ! $form->validate_honeypot() ) {
473 charitable_get_notices()->add_error( __( 'There was an error with processing your form submission. Please reload the page and try again.', 'charitable' ) );
474 return;
475 }
476
477 $user = $form->get_user();
478
479 /* Verify that the user is logged in. */
480 if ( 0 == $user->ID ) {
481 return;
482 }
483
484 $fields = $form->get_merged_fields();
485
486 $submitted = apply_filters( 'charitable_profile_update_values', $_POST, $fields, $form );
487
488 /* Remove the current_pass and user_pass_repeat fields, if set. */
489 unset(
490 $submitted['current_pass'],
491 $submitted['user_pass_repeat']
492 );
493
494 $valid = $form->check_required_fields( $fields );
495
496 if ( $valid && $form->is_changing_password() ) {
497 $valid = $form->validate_password_change();
498 }
499
500 if ( $valid && $form->is_changing_email() ) {
501 $valid = $form->validate_email_change();
502 }
503
504 if ( $valid ) {
505 $user->update_profile( $submitted, array_keys( $fields ) );
506
507 charitable_get_notices()->add_success( __( 'Your profile has been updated.', 'charitable' ) );
508
509 do_action( 'charitable_profile_updated', $submitted, $fields, $form );
510 }
511 }
512
513 /**
514 * Check whether the password is being changed.
515 *
516 * @since 1.4.0
517 *
518 * @return boolean
519 */
520 public function is_changing_password() {
521 if ( ! isset( $_POST['user_pass'] ) || empty( $_POST['user_pass'] ) ) {
522 return false;
523 }
524
525 if ( ! isset( $_POST['current_pass'] ) || empty( $_POST['current_pass'] ) ) {
526 return false;
527 }
528
529 return true;
530 }
531
532 /**
533 * Changes a password if the current password is correct and the repeat matches the new password.
534 *
535 * @since 1.4.0
536 *
537 * @return boolean
538 */
539 public function validate_password_change() {
540 /* The current password must be correct. */
541 if ( false == wp_check_password( $_POST['current_pass'], $this->get_user()->user_pass ) ) {
542 charitable_get_notices()->add_error( __( 'Current password is incorrect.', 'charitable' ) );
543 return false;
544 }
545
546 /* The new password must match the repeat (if set). */
547 if ( isset( $_POST['user_pass_repeat'] ) && $_POST['user_pass_repeat'] != $_POST['user_pass'] ) {
548 charitable_get_notices()->add_error( __( 'New passwords did not match.', 'charitable' ) );
549 return false;
550 }
551
552 return true;
553 }
554
555 /**
556 * Check whether the email address is being changed.
557 *
558 * @since 1.6.2
559 *
560 * @return boolean
561 */
562 public function is_changing_email() {
563 if ( ! isset( $_POST['user_email'] ) || empty( $_POST['user_email'] ) ) {
564 return false;
565 }
566
567 if ( ! isset( $_POST['current_email'] ) ) {
568 return $_POST['user_email'] != $this->get_user()->get_email();
569 }
570
571 return $_POST['user_email'] != $_POST['current_email'];
572 }
573
574 /**
575 * Validate the email change.
576 *
577 * @since 1.6.2
578 *
579 * @return boolean
580 */
581 public function validate_email_change() {
582 if ( 0 != charitable_get_donor_id_by_email( $_POST['user_email'] ) ) {
583 charitable_get_notices()->add_error(
584 __( 'This email address is already in use.', 'charitable' )
585 );
586 return false;
587 }
588
589 return true;
590 }
591
592 /**
593 * Return a user's set value for a particular value, or return the default value.
594 *
595 * @since 1.5.7
596 *
597 * @param string $key The property we're getting the value for.
598 * @param string $default The fallback value.
599 * @return string
600 */
601 protected function get_user_prop_or_default( $key, $default ) {
602 $user = $this->get_user();
603
604 return $user && $user->has_prop( $key ) ? $user->get( $key ) : $default;
605 }
606
607 /**
608 * Add the charitable_user_profile_after_fields hook but fire off a deprecated notice.
609 *
610 * @deprecated 1.4.0
611 * @since 1.4.0
612 *
613 * @return void
614 */
615 public static function add_deprecated_charitable_user_profile_after_fields_hook( $form ) {
616 if ( ! has_action( 'charitable_user_profile_after_fields' ) ) {
617 return;
618 }
619
620 charitable_get_deprecated()->doing_it_wrong(
621 __METHOD__,
622 __( 'charitable_user_profile_after_fields hook has been removed. Use charitable_form_after_fields instead.', 'charitable' ),
623 '1.4.0'
624 );
625
626 if ( 'Charitable_Profile_Form' == get_class( $form ) ) {
627 do_action( 'charitable_user_profile_after_fields', $form );
628 }
629 }
630 }
631
632 endif;
633