WP-Members Membership Plugin - Version 3.4.3

Version Description

  • Simplified check_validated() and check_activated() functions, included check for null $user.
  • Added wpmem_check_validated and wpmem_check_activated filter hooks.
  • Added display="url" attribute to the [wpmem_field] shortcode for file and image field types.
  • Fix undefined variable in password reset.
  • Improve onboarding process for both new installs and updates.
Download this release

Release Info

Developer cbutlerjr
Plugin Icon 128x128 WP-Members Membership Plugin
Version 3.4.3
Comparing to
See all releases

Code changes from version 3.4.2 to 3.4.3

includes/admin/class-wp-members-admin-api.php CHANGED
@@ -66,7 +66,7 @@ class WP_Members_Admin_API {
66
  $this->load_dependencies();
67
 
68
  // Load admin hooks.
69
- $this->load_hooks( $install_state );
70
 
71
  // The following is only needed if we are on the WP-Members settings screen.
72
  $is_wpmem_admin = wpmem_get( 'page', false, 'get' );
@@ -124,7 +124,7 @@ class WP_Members_Admin_API {
124
  *
125
  * @global object $wpmem
126
  */
127
- function load_hooks( $install_state ) {
128
 
129
  global $wpmem;
130
 
@@ -197,14 +197,6 @@ class WP_Members_Admin_API {
197
  if ( current_user_can( 'manage_options' ) ) {
198
  add_action( 'admin_notices', array( $this, 'do_admin_notices' ) );
199
  }
200
-
201
- if ( 'new_install' == $install_state && 'wp-members-onboarding' != wpmem_get( 'page', false, 'get' ) ) {
202
- add_action( 'admin_notices', array( $this, 'new_install_notice' ) );
203
- }
204
-
205
- if ( 'update_pending' == $install_state && 'wp-members-onboarding' != wpmem_get( 'page', false, 'get' ) ) {
206
- add_action( 'admin_notices', array( $this, 'upgrade_notice' ) );
207
- }
208
  } // End of load_hooks()
209
 
210
  /**
@@ -659,42 +651,6 @@ class WP_Members_Admin_API {
659
  return get_post_types( array( 'public' => true, '_builtin' => false ), 'names', 'and' );
660
  }
661
 
662
- function new_install_notice() {
663
- echo '<div class="notice notice-info">
664
- <form action="index.php?page=wp-members-onboarding" method="post">
665
- <p style="font-weight:bold;">' . __( 'Thank you for installing WP-Members, the original WordPress membership plugin.', 'wp-members' ) . '</p>
666
- <h3>' . __( 'Never miss an important update!', 'wp-members' ) . '</h3>
667
- <p><input type="checkbox" name="optin" value="1" checked />' . __( 'Opt-in to our security and feature updates notifications and non-sensitive diagnostic tracking.', 'wp-members' ) . '</p>
668
- <p class="description">
669
- ' . __( 'This is only so we know how the plugin is being used so we can make it better and more secure.', 'wp-members' ) . '<br />
670
- ' . __( 'We do not track any personal information, and no data is ever shared with third parties!', 'wp-members' ) . '
671
- </p>
672
- <input type="hidden" name="page" value="wp-members-onboarding" />
673
- <input type="hidden" name="step" value="finalize">
674
- <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="' . __( 'Complete plugin setup', 'wp-members' ) . ' &raquo;"></p>
675
- </form>
676
- </div>';
677
- }
678
-
679
- function upgrade_notice() {
680
- $onboarding_release_notes = "https://rocketgeek.com/release-notes/wp-members-3-4-2/";
681
- echo '<div class="notice notice-info">
682
- <form action="index.php?page=wp-members-onboarding" method="post">
683
- <h3>' . __( 'Thank you for updating WP-Members, the original WordPress membership plugin.', 'wp-members' ) . '</h3>
684
- <p class="description"><a href="' . $onboarding_release_notes . '" target="_blank">' . __( 'Read the release notes', 'wp-members' ) . '</a></p>
685
- <h3>' . __( 'Never miss an important update!', 'wp-members' ) . '</h3>
686
- <p><input type="checkbox" name="optin" value="1" checked />' . __( 'Opt-in to our security and feature updates notifications and non-sensitive diagnostics.', 'wp-members' ) . '</p>
687
- <p class="description">
688
- ' . __( 'This is only so we know how the plugin is being used so we can make it better and more secure.', 'wp-members' ) . '<br />
689
- ' . __( 'We do not track any personal information, and no data is ever shared with third parties!', 'wp-members' ) . '
690
- </p>
691
- <input type="hidden" name="page" value="wp-members-onboarding" />
692
- <input type="hidden" name="step" value="finalize">
693
- <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="' . __( 'Complete the update', 'wp-members' ) . ' &raquo;"></p>
694
- </form>
695
- </div>';
696
- }
697
-
698
  } // End of WP_Members_Admin_API class.
699
 
700
  // End of file.
66
  $this->load_dependencies();
67
 
68
  // Load admin hooks.
69
+ $this->load_hooks();
70
 
71
  // The following is only needed if we are on the WP-Members settings screen.
72
  $is_wpmem_admin = wpmem_get( 'page', false, 'get' );
124
  *
125
  * @global object $wpmem
126
  */
127
+ function load_hooks() {
128
 
129
  global $wpmem;
130
 
197
  if ( current_user_can( 'manage_options' ) ) {
198
  add_action( 'admin_notices', array( $this, 'do_admin_notices' ) );
199
  }
 
 
 
 
 
 
 
 
200
  } // End of load_hooks()
201
 
202
  /**
651
  return get_post_types( array( 'public' => true, '_builtin' => false ), 'names', 'and' );
652
  }
653
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
654
  } // End of WP_Members_Admin_API class.
655
 
656
  // End of file.
includes/admin/class-wp-members-user-export.php CHANGED
@@ -12,6 +12,8 @@ if ( ! defined( 'ABSPATH' ) ) {
12
  exit();
13
  }
14
 
 
 
15
  class WP_Members_User_Export {
16
 
17
  /**
12
  exit();
13
  }
14
 
15
+ // error_log( 'Plugin file wp-members/admin/class-wp-members-user-export.php should not be loaded directly. Use wpmem_export_users() instead.' );
16
+
17
  class WP_Members_User_Export {
18
 
19
  /**
includes/admin/partials/onboarding_notice.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php $which = ( 'update_pending' == $install_state ) ? 'update_pending_notice_args' : 'new_install_notice_args'; ?>
2
+ <div class="notice notice-info">
3
+ <form action="index.php?page=<?php echo $this->menu_slug; ?>" method="post">
4
+ <p style="font-weight:bold;"><?php echo $this->{$which}['notice_heading']; ?></p>
5
+
6
+ <?php if ( $this->{$which}['show_release_notes'] ) { ?>
7
+ <p class="description"><a href="<?php echo $this->{$which}['release_notes_link']; ?>" target="_blank"><?php _e( 'Read the release notes', 'wp-members' ); ?></a></p>
8
+ <?php } ?>
9
+ <?php if ( false == $this->has_user_opted_in() ) { ?>
10
+ <h3><?php _e( 'Never miss an important update!', 'wp-members' ); ?></h3>
11
+ <p><input type="checkbox" name="optin" value="1" checked />
12
+ <?php _e( 'Opt-in to our security and feature updates notifications and non-sensitive diagnostic tracking.', 'wp-members' );?>
13
+ </p>
14
+ <p class="description">
15
+ <?php _e( 'This is only so we know how the plugin is being used so we can make it better and more secure.', 'wp-members' ); ?><br />
16
+ <?php _e( 'We do not track any personal information, and no data is ever shared with third parties!', 'wp-members' ); ?>
17
+ </p>
18
+ <?php } ?>
19
+ <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php echo $this->{$which}['notice_button']; ?> &raquo;"></p>
20
+ <input type="hidden" name="page" value="wp-members-onboarding" />
21
+ <input type="hidden" name="step" value="finalize">
22
+ </form>
23
+ </div>
includes/api/api-users.php CHANGED
@@ -949,7 +949,7 @@ function wpmem_get_user_ip() {
949
  */
950
  function wpmem_export_users( $args = array(), $users = array() ) {
951
  global $wpmem;
952
- include_once( $wpmem->path . 'includes/admin/class-wp-members-user-export.php' );
953
  WP_Members_User_Export::export_users( $args, $users );
954
  }
955
 
949
  */
950
  function wpmem_export_users( $args = array(), $users = array() ) {
951
  global $wpmem;
952
+ include_once( $wpmem->path . 'includes/class-wp-members-user-export.php' );
953
  WP_Members_User_Export::export_users( $args, $users );
954
  }
955
 
includes/api/api.php CHANGED
@@ -184,40 +184,6 @@ function wpmem_current_post_id() {
184
  return url_to_postid( wpmem_current_url() );
185
  }
186
 
187
- /**
188
- * Wrapper to return a string from the get_text function.
189
- *
190
- * @since 3.4.0
191
- *
192
- * @global object $wpmem The WP_Members object.
193
- * @param string $str The string to retrieve.
194
- * @param bool $echo Print the string (default: false).
195
- * @return string $str The localized string.
196
- */
197
- function wpmem_get_text( $str, $echo = false ) {
198
- global $wpmem;
199
- if ( $echo ) {
200
- echo $wpmem->dialogs->get_text( $str );
201
- } else {
202
- return $wpmem->dialogs->get_text( $str );
203
- }
204
- }
205
-
206
- /**
207
- * Wrapper to use custom dialog.
208
- *
209
- * @since 3.1.1
210
- *
211
- * @param array $defaults Dialog message defaults from the wpmem_msg_dialog_arr filter.
212
- * @param string $tag The dialog tag/name.
213
- * @param array $dialogs The dialog settings array (passed through filter).
214
- * @return array $dialogs The dialog settings array (filtered).
215
- */
216
- function wpmem_use_custom_dialog( $defaults, $tag, $dialogs ) {
217
- $defaults['msg'] = __( $dialogs[ $tag ], 'wp-members' );
218
- return $defaults;
219
- }
220
-
221
  /**
222
  * Returns or displays the user's login status.
223
  *
@@ -362,6 +328,25 @@ function wpmem_logout_link() {
362
  return apply_filters( 'wpmem_logout_link', add_query_arg( 'a', 'logout' ) );
363
  }
364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
  /**
366
  * Gets requested dialog.
367
  *
@@ -402,6 +387,21 @@ function wpmem_display_message( $tag, $custom = false ) {
402
  echo wpmem_get_display_message( $tag, $custom );
403
  }
404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  /**
406
  * Wrapper function for adding custom dialogs.
407
  *
184
  return url_to_postid( wpmem_current_url() );
185
  }
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  /**
188
  * Returns or displays the user's login status.
189
  *
328
  return apply_filters( 'wpmem_logout_link', add_query_arg( 'a', 'logout' ) );
329
  }
330
 
331
+ /**
332
+ * Wrapper to return a string from the get_text function.
333
+ *
334
+ * @since 3.4.0
335
+ *
336
+ * @global object $wpmem The WP_Members object.
337
+ * @param string $str The string to retrieve.
338
+ * @param bool $echo Print the string (default: false).
339
+ * @return string $str The localized string.
340
+ */
341
+ function wpmem_get_text( $str, $echo = false ) {
342
+ global $wpmem;
343
+ if ( $echo ) {
344
+ echo $wpmem->dialogs->get_text( $str );
345
+ } else {
346
+ return $wpmem->dialogs->get_text( $str );
347
+ }
348
+ }
349
+
350
  /**
351
  * Gets requested dialog.
352
  *
387
  echo wpmem_get_display_message( $tag, $custom );
388
  }
389
 
390
+ /**
391
+ * Wrapper to use custom dialog.
392
+ *
393
+ * @since 3.1.1
394
+ *
395
+ * @param array $defaults Dialog message defaults from the wpmem_msg_dialog_arr filter.
396
+ * @param string $tag The dialog tag/name.
397
+ * @param array $dialogs The dialog settings array (passed through filter).
398
+ * @return array $dialogs The dialog settings array (filtered).
399
+ */
400
+ function wpmem_use_custom_dialog( $defaults, $tag, $dialogs ) {
401
+ $defaults['msg'] = __( $dialogs[ $tag ], 'wp-members' );
402
+ return $defaults;
403
+ }
404
+
405
  /**
406
  * Wrapper function for adding custom dialogs.
407
  *
includes/class-wp-members-email.php CHANGED
@@ -503,6 +503,7 @@ class WP_Members_Email {
503
  *
504
  * @param array $shortcodes
505
  * @param string $toggle
 
506
  */
507
  $shortcodes = apply_filters( 'wpmem_email_shortcodes', $shortcodes, 'notify', $this->settings['user_id'] );
508
 
503
  *
504
  * @param array $shortcodes
505
  * @param string $toggle
506
+ * @param string $user_id
507
  */
508
  $shortcodes = apply_filters( 'wpmem_email_shortcodes', $shortcodes, 'notify', $this->settings['user_id'] );
509
 
includes/class-wp-members-forms.php CHANGED
@@ -750,7 +750,7 @@ class WP_Members_Forms {
750
  }
751
 
752
  // Build hidden fields, filter, and add to the form.
753
- if ( 'set_password_from_key' == wpmem_get( 'a', false, 'request' ) && false == wpmem_get( 'formsubmit', false ) ) {
754
  $hidden['action'] = wpmem_form_field( array( 'name' => 'a', 'type' => 'hidden', 'value' => 'set_password_from_key' ) );
755
  $hidden['key'] = wpmem_form_field( array( 'name' => 'key', 'type' => 'hidden', 'value' => sanitize_text_field( wpmem_get( 'key', null, 'request' ) ) ) );
756
  $hidden['login'] = wpmem_form_field( array( 'name' => 'login', 'type' => 'hidden', 'value' => sanitize_user( wpmem_get( 'login', null, 'request' ) ) ) );
750
  }
751
 
752
  // Build hidden fields, filter, and add to the form.
753
+ if ( 'set_password_from_key' == wpmem_get( 'a', false, 'request' ) && 'login' != $action ) {
754
  $hidden['action'] = wpmem_form_field( array( 'name' => 'a', 'type' => 'hidden', 'value' => 'set_password_from_key' ) );
755
  $hidden['key'] = wpmem_form_field( array( 'name' => 'key', 'type' => 'hidden', 'value' => sanitize_text_field( wpmem_get( 'key', null, 'request' ) ) ) );
756
  $hidden['login'] = wpmem_form_field( array( 'name' => 'login', 'type' => 'hidden', 'value' => sanitize_user( wpmem_get( 'login', null, 'request' ) ) ) );
includes/class-wp-members-products.php CHANGED
@@ -97,6 +97,7 @@ class WP_Members_Products {
97
  add_filter( 'wpmem_securify', array( $this, 'product_access' ) );
98
  add_filter( 'wpmem_product_restricted_msg', array( $this, 'apply_custom_access_message' ), 10, 2 );
99
  add_filter( 'wpmem_restricted_msg', array( $this, 'apply_custom_access_message' ), 10, 4 );
 
100
  }
101
 
102
  /**
@@ -544,4 +545,30 @@ class WP_Members_Products {
544
 
545
  return $new_value;
546
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  }
97
  add_filter( 'wpmem_securify', array( $this, 'product_access' ) );
98
  add_filter( 'wpmem_product_restricted_msg', array( $this, 'apply_custom_access_message' ), 10, 2 );
99
  add_filter( 'wpmem_restricted_msg', array( $this, 'apply_custom_access_message' ), 10, 4 );
100
+ add_filter( 'wpmem_email_shortcodes', array( $this, 'email_shortcodes' ), 10, 3 );
101
  }
102
 
103
  /**
545
 
546
  return $new_value;
547
  }
548
+
549
+ /**
550
+ * Adds [user_memberships] shortcode for use in the admin email
551
+ *
552
+ * @since 3.4.4
553
+ *
554
+ * @param array $shortcodes
555
+ * @param string $tag
556
+ * @param int $user_id
557
+ * @return array $shortcodes
558
+ */
559
+ function email_shortcodes( $shortcodes, $tag, $user_id ) {
560
+ global $wpmem;
561
+ if ( 'notify' == $tag ) {
562
+ $user_memberships = wpmem_get_user_memberships( $user_id );
563
+ $site_memberships = wpmem_get_memberships();
564
+ $email_memberships = ( $wpmem->email->html ) ? '<p><ul>' : "";
565
+ foreach ( $user_memberships as $meta_key => $membership ) {
566
+ $email_memberships .= ( $wpmem->email->html ) ? "<li>" . $site_memberships[ $meta_key ]['title'] . '</li>' : $site_memberships[ $meta_key ]['title'] . "\r\n";
567
+ }
568
+ $email_memberships .= ( $wpmem->email->html ) ? '</ul>' : "";
569
+
570
+ $shortcodes['memberships'] = $email_memberships;
571
+ }
572
+ return $shortcodes;
573
+ }
574
  }
includes/class-wp-members-pwd-reset.php CHANGED
@@ -12,10 +12,11 @@ class WP_Members_Pwd_Reset {
12
  *
13
  * @since 3.3.5
14
  */
15
- public $form_submitted_key_not_found;
16
- public $form_load_key_not_found;
17
  public $key_is_expired;
18
  private $reset_key;
 
19
 
20
  /**
21
  * Meta containers
@@ -33,10 +34,10 @@ class WP_Members_Pwd_Reset {
33
  function __construct() {
34
 
35
  $defaults = array(
36
- 'form_submitted_key_not_found' => __( "Sorry, no password reset key was found. Please check your email and try again.", 'wp-members' ),
37
- 'form_load_key_not_found' => __( "Sorry, no password reset key was found. Please check your email and try again.", 'wp-members' ),
38
- 'key_is_expired' => __( "Sorry, the password reset key is expired.", 'wp-members' ),
39
- 'request_new_key' => __( "Request a new reset key.", 'wp-members' ),
40
  );
41
 
42
  /**
@@ -45,7 +46,7 @@ class WP_Members_Pwd_Reset {
45
  * @since 3.3.8
46
  *
47
  * @param array $defaults {
48
- *
49
  * }
50
  */
51
  $defaults = apply_filters( 'wpmem_pwd_reset_default_dialogs', $defaults );
@@ -55,79 +56,35 @@ class WP_Members_Pwd_Reset {
55
  }
56
 
57
  add_filter( 'wpmem_email_filter', array( $this, 'add_reset_key_to_email' ), 10, 3 );
 
58
  add_filter( 'the_content', array( $this, 'display_content' ), 100 );
59
  }
60
 
61
- /**
62
- * Add reset key to the email.
63
- *
64
- * @since 3.3.5
65
- *
66
- * @param array $arr
67
- * @param array $wpmem_fields
68
- * @param array $field_data
69
- * @return array $arr
70
- */
71
- function add_reset_key_to_email( $arr, $wpmem_fields, $field_data ) {
72
-
73
- if ( $arr['toggle'] == 'repass' ) {
74
-
75
- $user = get_user_by( 'ID', $arr['user_id'] );
76
-
77
- // Get the stored key.
78
- $key = get_password_reset_key( $user );
79
- $query_args = array(
80
- 'a' => $this->form_action,
81
- 'key' => $key,
82
- 'login' => $user->user_login,
83
- );
84
-
85
- // urlencode, primarily for user_login with a space.
86
- $query_args = array_map( 'rawurlencode', $query_args );
87
-
88
- // Generate reset link.
89
- $link = add_query_arg( $query_args, trailingslashit( wpmem_profile_url() ) );
90
-
91
- // Does email body have the [reset_link] shortcode?
92
- if ( strpos( $arr['body'], '[reset_link]' ) ) {
93
- $arr['body'] = str_replace( '[reset_link]', $link, $arr['body'] );
94
- } else {
95
- // Add text and link to the email body.
96
- $arr['body'] = $arr['body'] . "\r\n"
97
- . $link;
98
- }
99
- }
100
- return $arr;
101
- }
102
-
103
- /**
104
- * Display page content to user.
105
- *
106
- * @since 3.3.5
107
- *
108
- * @param string $content
109
- * @return string $content
110
- */
111
- function display_content( $content ) {
112
-
113
  global $wpmem;
114
 
115
  if ( ! is_user_logged_in() && $this->form_action == wpmem_get( 'a', false, 'request' ) && ! is_admin() ) {
116
  // Define variables
117
- $result = '';
118
  $user_id = false;
119
  $msg = '';
120
  $form = '';
121
 
122
  // Check for key.
123
- $key = sanitize_text_field( wpmem_get( 'key', false, 'request' ) );
124
- $user_login = sanitize_text_field( wpmem_get( 'login', false, 'request' ) );
125
- $pass1 = wpmem_get( 'pass1', false );
126
- $pass2 = wpmem_get( 'pass2', false );
127
-
 
 
 
 
 
 
128
  // Set an error container.
129
  $errors = new WP_Error();
130
-
131
  /**
132
  * Validate the key.
133
  *
@@ -144,12 +101,12 @@ class WP_Members_Pwd_Reset {
144
  * @param string The user login.
145
  * @return WP_User|WP_Error WP_User object on success, WP_Error object for invalid or expired keys (invalid_key|expired_key).
146
  */
147
- $user = check_password_reset_key( $key, $user_login );
148
-
149
  if ( $user->has_errors() ) {
150
- $errors->add( 'user_not_found', $this->form_load_key_not_found );
151
  }
152
-
153
  // Validate
154
  if ( 1 == wpmem_get( 'formsubmit' ) && false !== wpmem_get( 'a', false, $this->form_action ) ) {
155
 
@@ -181,18 +138,83 @@ class WP_Members_Pwd_Reset {
181
 
182
  if ( 'invalid_key' == $user->get_error_code() ) {
183
  // If somehow the form was submitted but the key not found.
184
- $pwd_reset_link = wpmem_profile_url( 'pwdreset' );
185
- $msg = wpmem_get_display_message( 'invalid_key', $this->form_submitted_key_not_found . '<br /><a href="' . $pwd_reset_link . '">' . $this->request_new_key . '</a>' );
186
- $form = '';
187
  } else {
188
  $form = wpmem_change_password_form();
189
  }
190
 
191
  }
192
 
193
- $content = $msg . $form;
194
  }
195
-
196
- return $content;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  }
198
  }
12
  *
13
  * @since 3.3.5
14
  */
15
+ public $invalid_key;
16
+ public $invalid_user;
17
  public $key_is_expired;
18
  private $reset_key;
19
+ private $content = false;
20
 
21
  /**
22
  * Meta containers
34
  function __construct() {
35
 
36
  $defaults = array(
37
+ 'invalid_key' => __( "Invalid key." ),
38
+ 'invalid_user' => __( "Invalid user.", 'wp-members' ),
39
+ 'key_is_expired' => __( "Sorry, the password reset key is expired.", 'wp-members' ),
40
+ 'request_new_key' => __( "Request a new reset key.", 'wp-members' ),
41
  );
42
 
43
  /**
46
  * @since 3.3.8
47
  *
48
  * @param array $defaults {
49
+ *
50
  * }
51
  */
52
  $defaults = apply_filters( 'wpmem_pwd_reset_default_dialogs', $defaults );
56
  }
57
 
58
  add_filter( 'wpmem_email_filter', array( $this, 'add_reset_key_to_email' ), 10, 3 );
59
+ add_action( 'template_redirect', array( $this, 'handle_reset' ), 20 );
60
  add_filter( 'the_content', array( $this, 'display_content' ), 100 );
61
  }
62
 
63
+ function handle_reset() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  global $wpmem;
65
 
66
  if ( ! is_user_logged_in() && $this->form_action == wpmem_get( 'a', false, 'request' ) && ! is_admin() ) {
67
  // Define variables
68
+ $result = false;
69
  $user_id = false;
70
  $msg = '';
71
  $form = '';
72
 
73
  // Check for key.
74
+ $key = sanitize_text_field( wpmem_get( 'key', false, 'request' ) );
75
+ $login = sanitize_text_field( wpmem_get( 'login', false, 'request' ) );
76
+ $pass1 = wpmem_get( 'pass1', false );
77
+ $pass2 = wpmem_get( 'pass2', false );
78
+
79
+ // Check the user. get_user_by() will return false if user_login does not exist.
80
+ $is_user = get_user_by( 'login', $login );
81
+ if ( false == $is_user ) {
82
+ $this->content = $this->error_msg( 'invalid_user', $this->invalid_user );
83
+ }
84
+
85
  // Set an error container.
86
  $errors = new WP_Error();
87
+
88
  /**
89
  * Validate the key.
90
  *
101
  * @param string The user login.
102
  * @return WP_User|WP_Error WP_User object on success, WP_Error object for invalid or expired keys (invalid_key|expired_key).
103
  */
104
+ $user = check_password_reset_key( $key, $login );
105
+
106
  if ( $user->has_errors() ) {
107
+ $this->content = $this->error_msg( 'invalid_key', $this->invalid_key );
108
  }
109
+
110
  // Validate
111
  if ( 1 == wpmem_get( 'formsubmit' ) && false !== wpmem_get( 'a', false, $this->form_action ) ) {
112
 
138
 
139
  if ( 'invalid_key' == $user->get_error_code() ) {
140
  // If somehow the form was submitted but the key not found.
141
+ $this->content = $this->error_msg( 'invalid_key', $this->invalid_key );
 
 
142
  } else {
143
  $form = wpmem_change_password_form();
144
  }
145
 
146
  }
147
 
148
+ $this->content = $msg . $form;
149
  }
150
+ }
151
+
152
+ /**
153
+ * Add reset key to the email.
154
+ *
155
+ * @since 3.3.5
156
+ *
157
+ * @param array $arr
158
+ * @param array $wpmem_fields
159
+ * @param array $field_data
160
+ * @return array $arr
161
+ */
162
+ function add_reset_key_to_email( $arr, $wpmem_fields, $field_data ) {
163
+
164
+ if ( $arr['toggle'] == 'repass' ) {
165
+
166
+ $user = get_user_by( 'ID', $arr['user_id'] );
167
+
168
+ // Get the stored key.
169
+ $key = get_password_reset_key( $user );
170
+ $query_args = array(
171
+ 'a' => $this->form_action,
172
+ 'key' => $key,
173
+ 'login' => $user->user_login,
174
+ );
175
+
176
+ // urlencode, primarily for user_login with a space.
177
+ $query_args = array_map( 'rawurlencode', $query_args );
178
+
179
+ // Generate reset link.
180
+ $link = add_query_arg( $query_args, trailingslashit( wpmem_profile_url() ) );
181
+
182
+ // Does email body have the [reset_link] shortcode?
183
+ if ( strpos( $arr['body'], '[reset_link]' ) ) {
184
+ $arr['body'] = str_replace( '[reset_link]', $link, $arr['body'] );
185
+ } else {
186
+ // Add text and link to the email body.
187
+ $arr['body'] = $arr['body'] . "\r\n"
188
+ . $link;
189
+ }
190
+ }
191
+ return $arr;
192
+ }
193
+
194
+ /**
195
+ * Display page content to user.
196
+ *
197
+ * @since 3.3.5
198
+ *
199
+ * @param string $content
200
+ * @return string $content
201
+ */
202
+ function display_content( $content ) {
203
+ return ( false != $this->content ) ? $this->content : $content;
204
+ }
205
+
206
+
207
+ function error_msg( $code, $message ) {
208
+ $error = wpmem_get_display_message( $code, $message . '<br /><a href="' . wpmem_profile_url( 'pwdreset' ) . '">' . $this->request_new_key . '</a>' );
209
+ /**
210
+ * Filters the password reset error message.
211
+ *
212
+ * @since 3.4.4
213
+ *
214
+ * @param string $error The generated HTML error message.
215
+ * @param string $code The error code generated.
216
+ * @param string $message The plain text error message.
217
+ */
218
+ return apply_filters( 'wpmem_pwd_reset_error_msg', $error, $code, $message );
219
  }
220
  }
includes/class-wp-members-shortcodes.php CHANGED
@@ -604,7 +604,7 @@ class WP_Members_Shortcodes {
604
  global $wpmem;
605
  $fields = wpmem_fields();
606
 
607
- $field_type = ( 'user_login' == $field ) ? 'text' : $fields[ $field ]['type'];
608
  $user_info_field = ( isset( $field ) && is_object( $user_info ) ) ? $user_info->{$field} : '';
609
  $result = false;
610
 
@@ -635,8 +635,17 @@ class WP_Members_Shortcodes {
635
 
636
  case 'file':
637
  case 'image':
638
- if ( isset( $atts['display'] ) && 'raw' == $atts['display'] ) {
639
- $result = $user_info_field;
 
 
 
 
 
 
 
 
 
640
  } else {
641
  if ( 'file' == $field_type ) {
642
  $attachment_url = wp_get_attachment_url( $user_info_field );
604
  global $wpmem;
605
  $fields = wpmem_fields();
606
 
607
+ $field_type = ( 'user_login' == $field || ! isset( $fields[ $field ] ) ) ? 'text' : $fields[ $field ]['type'];
608
  $user_info_field = ( isset( $field ) && is_object( $user_info ) ) ? $user_info->{$field} : '';
609
  $result = false;
610
 
635
 
636
  case 'file':
637
  case 'image':
638
+ if ( isset( $atts['display'] ) ) {
639
+ switch ( $atts['display'] ) {
640
+ case "url":
641
+ $result = wp_get_attachment_url( $user_info_field );
642
+ break;
643
+ case "raw":
644
+ default:
645
+ $result = $user_info_field;
646
+ break;
647
+ }
648
+
649
  } else {
650
  if ( 'file' == $field_type ) {
651
  $attachment_url = wp_get_attachment_url( $user_info_field );
includes/class-wp-members-user-export.php ADDED
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The WP_Members Export Class.
4
+ *
5
+ * @package WP-Members
6
+ * @subpackage WP_Members Export Object Class
7
+ * @since 3.3.0
8
+ */
9
+
10
+ // Exit if accessed directly.
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit();
13
+ }
14
+
15
+ class WP_Members_User_Export {
16
+
17
+ /**
18
+ * Used instead of getting global.
19
+ *
20
+ * @since 3.4.1
21
+ * @todo May change how this is used. (Currently just replaces minor use of $wpmem global object for this one thing.)
22
+ */
23
+ public static $membership_product_stem = "_wpmem_products_";
24
+
25
+ /**
26
+ * New export function to export all or selected users
27
+ *
28
+ * @since 2.9.7
29
+ * @since 3.2.0 Updated to use fputcsv.
30
+ * @since 3.2.1 Added user data filters.
31
+ * @since 3.3.0 Moved to new object class as static method.
32
+ * @since 3.4.0 Added $tag to identify what export process is being run.
33
+ *
34
+ * @param array $args array {
35
+ * Array of defaults for export.
36
+ *
37
+ * @type string $export The type of export (all|selected)
38
+ * @type string $filename
39
+ * @type array $fields {
40
+ * The array of export fields is keyed as 'meta_key' => 'heading value'.
41
+ * The array can include fields in the Fields tab, plus the following:
42
+ *
43
+ * @type int $ID ID from wp_users
44
+ * @type string $username user_login from wp_users
45
+ * @type string $user_nicename user_nicename
46
+ * @type string $user_url user_url
47
+ * @type string $display_name display_name
48
+ * @type int $active Whether the user is active/deactivated.
49
+ * @type string $exp_type If the PayPal extension is installed pending|subscrption (optional)
50
+ * @type string $expires If the PayPal extension is installed MM/DD/YYYY (optional)
51
+ * @type string $user_registered user_registered
52
+ * @type string $user_ip The IP of the user when they registered.
53
+ * @type string $role The user's role (or roles, if multiple).
54
+ * }
55
+ * @type array $exclude_fields @deprecated 3.4.0
56
+ * @type boolean $entity_decode Whether HTML entities should be decoded (default: false)
57
+ * @type string $date_format A PHP readable date format (default: Y-m-d which results in YYYY-MM-DD)
58
+ * }
59
+ * @param array $users Array of user IDs to export.
60
+ * @param string $tag
61
+ */
62
+ public static function export_users( $args = array(), $users = array(), $tag = 'default' ) {
63
+
64
+ $export_fields = ( ! isset( $args['fields'] ) ) ? self::get_export_fields() : $args['fields'];
65
+
66
+ /**
67
+ * Filter the export fields.
68
+ *
69
+ * @since 3.2.5
70
+ * @since 3.4.0 Added $tag.
71
+ *
72
+ * @param array $export_fields {
73
+ * The array of export fields is keyed as 'meta_key' => 'heading value'.
74
+ * The array will include all fields in the Fields tab, plus the following:
75
+ *
76
+ * @type int $ID ID from wp_users
77
+ * @type string $username user_login from wp_users
78
+ * @type string $user_nicename user_nicename
79
+ * @type string $user_url user_url
80
+ * @type string $display_name display_name
81
+ * @type int $active Whether the user is active/deactivated.
82
+ * @type string $exp_type If the PayPal extension is installed pending|subscrption (optional)
83
+ * @type string $expires If the PayPal extension is installed MM/DD/YYYY (optional)
84
+ * @type string $user_registered user_registered
85
+ * @type string $user_ip The IP of the user when they registered.
86
+ * @type string $role The user's role (or roles, if multiple).
87
+ * }
88
+ * @param string $tag
89
+ */
90
+ $export_fields = apply_filters( 'wpmem_export_fields', $export_fields, $tag );
91
+
92
+ $today = date( "Y-m-d" );
93
+
94
+ // Setup defaults.
95
+ $defaults = array(
96
+ 'export' => 'all',
97
+ 'filename' => 'wp-members-user-export-' . $today . '.csv',
98
+ 'fields' => $export_fields,
99
+ 'entity_decode' => false,
100
+ 'date_format' => 'Y-m-d',
101
+ 'required_caps' => 'list_users',
102
+ );
103
+ // Merge args with default (in case any were missing).
104
+ $args = wp_parse_args( $args, $defaults );
105
+
106
+ /**
107
+ * Filter the default export arguments.
108
+ *
109
+ * @since 2.9.7
110
+ * @since 3.4.0 Filter all defaults (like other _args changes), then wp_parse_args() in case any are missing.
111
+ * @since 3.4.0 Added $tag.
112
+ * @since 3.4.0 Deprecated 'exclude_fields' (unset using wpmem_export_fields instead).
113
+ * @since 3.4.0 Deprecated 'export_fields' use "fields" instead.
114
+ *
115
+ * @param array $args {
116
+ * Array of defaults for export.
117
+ *
118
+ * @type string $export
119
+ * @type string $filename
120
+ * @type array $fields
121
+ * @type array $exclude_fields @deprecated 3.4.0
122
+ * @type boolean $entity_decode
123
+ * @type string $date_format
124
+ * }
125
+ * @param string $tag
126
+ */
127
+ $args = apply_filters( 'wpmem_export_args', $args, $tag );
128
+
129
+ // Merge args with default (in case any were missing).
130
+ $args = wp_parse_args( $args, $defaults );
131
+
132
+ if ( current_user_can( $args['required_caps'] ) ) {
133
+ // Output needs to be buffered, start the buffer.
134
+ ob_start();
135
+
136
+ // If exporting all, get all of the users.
137
+ $export_users = ( 'all' == $args['export'] ) ? get_users( array( 'fields' => 'ID' ) ) : $users;
138
+
139
+ // Generate headers and a filename based on date of export.
140
+ header( "Content-Description: File Transfer" );
141
+ header( "Content-type: application/octet-stream" );
142
+ header( "Content-Disposition: attachment; filename=" . $args['filename'] );
143
+ header( "Content-Type: text/csv; charset=" . get_option( 'blog_charset' ), true );
144
+
145
+ $handle = fopen( 'php://output', 'w' );
146
+ fputs( $handle, "\xEF\xBB\xBF" ); // UTF-8 BOM
147
+
148
+ // Remove excluded fields from $export_fields while setting up $header array.
149
+ $header = array();
150
+ foreach ( $args['fields'] as $meta => $field ) {
151
+ $header[ $meta ] = $field;
152
+ }
153
+
154
+ /**
155
+ * Filters user export header row before assembly.
156
+ *
157
+ * As of 3.4.0, this really isn't a necessary filter. You can specify the header
158
+ * value in wpmem_export_fields instead and just use one filter.
159
+ *
160
+ * @since 3.2.1
161
+ * @since 3.4.0 Added $tag.
162
+ *
163
+ * @param array $header The header column values
164
+ * @param string $tag
165
+ */
166
+ $header = apply_filters( 'wpmem_user_export_header', $header, $tag );
167
+
168
+ fputcsv( $handle, $header );
169
+
170
+ // Loop through the array of users, assemble csv.
171
+ // $fields only includes fields to be exported at this point.
172
+ foreach ( $export_users as $user ) {
173
+
174
+ $user_info = get_userdata( $user );
175
+
176
+ $wp_user_fields = array( 'ID', 'user_login', 'user_pass', 'user_nicename', 'user_email', 'user_url', 'user_registered', 'user_activation_key', 'user_status', 'display_name' );
177
+ foreach ( $args['fields'] as $meta => $field ) {
178
+
179
+ switch ( $meta ) {
180
+ case 'ID':
181
+ case 'user_login':
182
+ case 'user_pass':
183
+ case 'user_nicename':
184
+ case 'user_email':
185
+ case 'user_url':
186
+ case 'user_registered':
187
+ case 'user_activation_key':
188
+ case 'user_status':
189
+ case 'display_name':
190
+ $row[ $meta ] = $user_info->{$meta};
191
+ break;
192
+ case 'username':
193
+ $row['username'] = $user_info->user_login;
194
+ break;
195
+ case 'password':
196
+ $row['password'] = $user_info->user_pass;
197
+ break;
198
+ case 'active':
199
+ $row['active'] = wpmem_get_user_meta( $user, 'active' ) ? __( 'Yes' ) : __( 'No' );
200
+ break;
201
+ case 'exp_type':
202
+ $exp_type = wpmem_get_user_meta( $user, 'exp_type' );
203
+ $row['exp_type'] = ( false !== $exp_type ) ? $exp_type : '';
204
+ break;
205
+ case 'expires':
206
+ $expires = wpmem_get_user_meta( $user, 'expires' );
207
+ $row['expires'] = ( false !== $expires ) ? $expires : '';
208
+ break;
209
+ case 'wpmem_reg_ip':
210
+ $reg_ip = wpmem_get_user_meta( $user, 'wpmem_reg_ip' );
211
+ $row['wpmem_reg_ip'] = ( false !== $reg_ip ) ? $reg_ip : '';
212
+ break;
213
+ case 'role':
214
+ $role = wpmem_get_user_role( $user, true ); // As of 3.4, wpmem_get_user_role() can get all roles.
215
+ $row['role'] = ( is_array( $role ) ) ? implode( ",", $role ) : $role;
216
+ break;
217
+ case ( self::$membership_product_stem === substr( $meta, 0, strlen( self::$membership_product_stem ) ) ):
218
+ $product = str_replace( self::$membership_product_stem, '', $meta );
219
+ $row[ $meta ] = wpmem_get_user_meta( $user, $meta );
220
+ // If value is a date and false is not the format_date option...
221
+ if ( false !== $args['date_format'] && '' != $row[ $meta ] && $row[ $meta ] > 2 ) {
222
+ $date_format = ( 'wp' == $args['date_format'] ) ? get_option('date_format') : $args['date_format'];
223
+ $row[ $meta ] = date( $date_format, $row[ $meta ] );
224
+ }
225
+ break;
226
+ default:
227
+ if ( in_array( $meta, $wp_user_fields ) ) {
228
+ $row[ $meta ] = ( 'username' == $meta ) ? $user_info->user_login : $user_info->{$meta};
229
+ } else {
230
+ $raw_data = wpmem_get_user_meta( $user, $meta );
231
+ $raw_data = ( $raw_data ) ? $raw_data : '';
232
+ $row[ $meta ] = ( $args['entity_decode'] ) ? html_entity_decode( $raw_data ) : $raw_data;
233
+ }
234
+ break;
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Filter the user data before assembly.
240
+ *
241
+ * @since 3.2.1
242
+ * @since 3.4.0 Added user ID (it may not be included in the $row array if the field were filtered out).
243
+ * @since 3.4.0 Added $tag.
244
+ *
245
+ * @param array $row The user data row.
246
+ * @param int $user_id The user ID.
247
+ * @param string $tag
248
+ */
249
+ $row = apply_filters( 'wpmem_user_export_row', $row, $user_info->ID, $tag );
250
+
251
+ fputcsv( $handle, $row );
252
+
253
+ // Update the user record as being exported.
254
+ if ( 'all' != $args['export'] ) {
255
+ update_user_meta( $user, 'exported', 1 );
256
+ }
257
+ }
258
+
259
+ fclose( $handle );
260
+ print( ob_get_clean() );
261
+
262
+ exit();
263
+ } else {
264
+ wp_die( __( 'You do not have the required user capabilities to export users.', 'wp-members' ) );
265
+ }
266
+ }
267
+
268
+ private static function get_export_fields() {
269
+
270
+ $wpmem_fields = wpmem_fields();
271
+
272
+ // Fields to exclude.
273
+ $exclude_fields = array( 'user_pass', 'password', 'confirm_password', 'confirm_email' );
274
+
275
+ // Prepare fields, add additional "special" fields.
276
+ $export_fields = array(
277
+ 'ID' => __( 'User ID', 'wp-members' ),
278
+ );
279
+ foreach( $wpmem_fields as $meta_key => $value ) {
280
+ if ( ! in_array( $meta_key, $exclude_fields ) ) {
281
+ $export_fields[ $meta_key ] = $value['label'];
282
+ }
283
+ }
284
+ $export_fields['username'] = __( 'Username', 'wp-members' );
285
+ if ( wpmem_is_enabled( 'mod_reg' ) ) {
286
+ $export_fields['active'] = __( 'Activated?', 'wp-members' );
287
+ }
288
+ if ( wpmem_is_enabled( 'act_link' ) ) {
289
+ $export_fields['_wpmem_user_confirmed'] = __( 'Confirmed?', 'wp-members' );
290
+ }
291
+ if ( defined( 'WPMEM_EXP_MODULE' ) && wpmem_is_enabled( 'use_exp' ) ) {
292
+ $export_fields['exp_type'] = __( 'Subscription', 'wp-members' );
293
+ $export_fields['expires'] = __( 'Expires', 'wp-members' );
294
+ }
295
+ $export_fields['user_registered'] = __( 'Registered', 'wp-members' );
296
+ $export_fields['wpmem_reg_ip'] = __( 'IP', 'wp-members' );
297
+ $export_fields['role'] = __( 'Role', 'wp-members' );
298
+ if ( wpmem_is_enabled( 'enable_products' ) ) {
299
+ $membership_products = wpmem_get_memberships();
300
+ foreach( $membership_products as $product_key => $product ) {
301
+ $export_fields[ self::$membership_product_stem . $product_key ] = $membership_products[ $product_key ]['title'];
302
+ }
303
+ }
304
+
305
+ return $export_fields;
306
+ }
307
+ }
includes/class-wp-members-user-profile.php CHANGED
@@ -295,6 +295,11 @@ class WP_Members_User_Profile {
295
  * @return
296
  */
297
  static function update( $user_id ) {
 
 
 
 
 
298
 
299
  global $current_screen, $user_id, $wpmem;
300
  $display = ( 'profile' == $current_screen->base ) ? 'user' : 'admin';
295
  * @return
296
  */
297
  static function update( $user_id ) {
298
+
299
+ // Prevent from firing on front end use (i.e. password reset).
300
+ if ( ! is_admin() ) {
301
+ return;
302
+ }
303
 
304
  global $current_screen, $user_id, $wpmem;
305
  $display = ( 'profile' == $current_screen->base ) ? 'user' : 'admin';
includes/class-wp-members-user.php CHANGED
@@ -753,7 +753,7 @@ class WP_Members_User {
753
  return "reg_generic";
754
  }
755
 
756
- $user_to_check = ( strpos( $user_to_check, '@' ) ) ? sanitize_email( $arr['user'] ) : sanitize_user( $arr['user'] );
757
 
758
  if ( username_exists( $user_to_check ) ) {
759
  $user = get_user_by( 'login', $user_to_check );
@@ -1223,20 +1223,19 @@ class WP_Members_User {
1223
  * @return object $user The WordPress User object.
1224
  */
1225
  function check_activated( $user, $username, $password ) {
1226
- // Password must be validated.
1227
- $pass = ( ! is_wp_error( $user ) && ! is_null( $user ) && $password ) ? wp_check_password( $password, $user->user_pass, $user->ID ) : false;
1228
-
1229
- if ( ! $pass ) {
1230
- return $user;
1231
- }
1232
-
1233
- // Activation flag must be validated.
1234
- if ( ! $this->is_user_activated( $user->ID ) ) {
1235
- return new WP_Error( 'authentication_failed', __( '<strong>ERROR</strong>: User has not been activated.', 'wp-members' ) );
1236
  }
1237
-
1238
- // If the user is validated, return the $user object.
1239
- return $user;
 
 
 
 
 
 
 
1240
  }
1241
 
1242
  /**
753
  return "reg_generic";
754
  }
755
 
756
+ $user_to_check = ( strpos( $arr['user'], '@' ) ) ? sanitize_email( $arr['user'] ) : sanitize_user( $arr['user'] );
757
 
758
  if ( username_exists( $user_to_check ) ) {
759
  $user = get_user_by( 'login', $user_to_check );
1223
  * @return object $user The WordPress User object.
1224
  */
1225
  function check_activated( $user, $username, $password ) {
1226
+ if ( ! is_wp_error( $user ) && ! is_null( $user ) && false == $this->is_user_activated( $user->ID ) ) {
1227
+ $user = new WP_Error( 'authentication_failed', __( '<strong>ERROR</strong>: User has not been activated.', 'wp-members' ) );
 
 
 
 
 
 
 
 
1228
  }
1229
+ /**
1230
+ * Filters the check_validated result.
1231
+ *
1232
+ * @since 3.4.2
1233
+ *
1234
+ * @param mixed $user
1235
+ * @param string $username
1236
+ * @param string $password
1237
+ */
1238
+ return apply_filters( 'wpmem_check_activated', $user, $username, $password );
1239
  }
1240
 
1241
  /**
includes/class-wp-members-validation-link.php CHANGED
@@ -272,20 +272,19 @@ class WP_Members_Validation_Link {
272
  * @return object $user The WordPress User object.
273
  */
274
  function check_validated( $user, $username, $password ) {
275
- // Password must be validated.
276
- $pass = ( ( ! is_wp_error( $user ) ) && $password ) ? wp_check_password( $password, $user->user_pass, $user->ID ) : false;
277
-
278
- if ( ! $pass ) {
279
- return $user;
280
- }
281
-
282
- // Validation flag must be confirmed.
283
- if ( false == wpmem_is_user_confirmed( $user->ID ) ) {
284
- return new WP_Error( 'authentication_failed', __( '<strong>ERROR</strong>: User has not confirmed their account.', 'wp-members' ) );
285
  }
286
-
287
- // If the user is validated, return the $user object.
288
- return $user;
 
 
 
 
 
 
 
289
  }
290
 
291
  /**
272
  * @return object $user The WordPress User object.
273
  */
274
  function check_validated( $user, $username, $password ) {
275
+ if ( ! is_wp_error( $user ) && ! is_null( $user ) && false == wpmem_is_user_confirmed( $user->ID ) ) {
276
+ $user = new WP_Error( 'authentication_failed', __( '<strong>ERROR</strong>: User has not confirmed their account.', 'wp-members' ) );
 
 
 
 
 
 
 
 
277
  }
278
+ /**
279
+ * Filters the check_validated result.
280
+ *
281
+ * @since 3.4.2
282
+ *
283
+ * @param mixed $user
284
+ * @param string $username
285
+ * @param string $password
286
+ */
287
+ return apply_filters( 'wpmem_check_validated', $user, $username, $password );
288
  }
289
 
290
  /**
includes/class-wp-members.php CHANGED
@@ -72,7 +72,6 @@ class WP_Members {
72
  */
73
  public $url;
74
 
75
-
76
  /**
77
  * Content block settings.
78
  *
@@ -468,10 +467,8 @@ class WP_Members {
468
 
469
  add_action( 'init', array( $this, 'load_textdomain' ) );
470
  add_action( 'init', array( $this->membership, 'add_cpt' ), 0 ); // Adds membership plans custom post type.
471
- add_action( 'init', array( $this, 'load_admin' ) ); // @todo Check user role to load correct dashboard
472
  add_action( 'widgets_init', array( $this, 'widget_init' ) ); // initializes the widget
473
  add_action( 'rest_api_init', array( $this, 'rest_init' ) );
474
- add_action( 'admin_menu', 'wpmem_admin_options' ); // Adds admin menu
475
  add_action( 'pre_get_posts', array( $this, 'do_hide_posts' ), 20 );
476
  add_action( 'template_redirect', array( $this, 'get_action' ) );
477
  add_action( 'login_enqueue_scripts', array( $this, 'enqueue_style_wp_login' ) ); // styles the native registration
@@ -479,6 +476,11 @@ class WP_Members {
479
  add_action( 'wp_enqueue_scripts', array( $this, 'loginout_script' ) );
480
  add_action( 'customize_register', array( $this, 'customizer_settings' ) );
481
  add_action( 'wp_footer', array( $this, 'invisible_captcha' ) );
 
 
 
 
 
482
 
483
  if ( is_user_logged_in() ) {
484
  add_action( 'wpmem_pwd_change', array( $this->user, 'set_password' ), 9, 2 );
@@ -523,9 +525,9 @@ class WP_Members {
523
  add_filter( 'get_previous_post_where', array( $this, 'filter_get_adjacent_post_where' ) );
524
  add_filter( 'get_next_post_where', array( $this, 'filter_get_adjacent_post_where' ) );
525
  add_filter( 'allow_password_reset', array( $this->user, 'no_reset' ) ); // no password reset for non-activated users
526
-
527
  // If registration is moderated, check for activation (blocks backend login by non-activated users).
528
- if ( $this->mod_reg == 1 ) {
529
  add_filter( 'authenticate', array( $this->user, 'check_activated' ), 99, 3 );
530
  }
531
 
72
  */
73
  public $url;
74
 
 
75
  /**
76
  * Content block settings.
77
  *
467
 
468
  add_action( 'init', array( $this, 'load_textdomain' ) );
469
  add_action( 'init', array( $this->membership, 'add_cpt' ), 0 ); // Adds membership plans custom post type.
 
470
  add_action( 'widgets_init', array( $this, 'widget_init' ) ); // initializes the widget
471
  add_action( 'rest_api_init', array( $this, 'rest_init' ) );
 
472
  add_action( 'pre_get_posts', array( $this, 'do_hide_posts' ), 20 );
473
  add_action( 'template_redirect', array( $this, 'get_action' ) );
474
  add_action( 'login_enqueue_scripts', array( $this, 'enqueue_style_wp_login' ) ); // styles the native registration
476
  add_action( 'wp_enqueue_scripts', array( $this, 'loginout_script' ) );
477
  add_action( 'customize_register', array( $this, 'customizer_settings' ) );
478
  add_action( 'wp_footer', array( $this, 'invisible_captcha' ) );
479
+
480
+ if ( is_admin() ) {
481
+ add_action( 'init', array( $this, 'load_admin' ) ); // @todo Check user role to load correct dashboard
482
+ add_action( 'admin_menu', 'wpmem_admin_options' ); // Adds admin menu
483
+ }
484
 
485
  if ( is_user_logged_in() ) {
486
  add_action( 'wpmem_pwd_change', array( $this->user, 'set_password' ), 9, 2 );
525
  add_filter( 'get_previous_post_where', array( $this, 'filter_get_adjacent_post_where' ) );
526
  add_filter( 'get_next_post_where', array( $this, 'filter_get_adjacent_post_where' ) );
527
  add_filter( 'allow_password_reset', array( $this->user, 'no_reset' ) ); // no password reset for non-activated users
528
+
529
  // If registration is moderated, check for activation (blocks backend login by non-activated users).
530
+ if ( 1 == $this->mod_reg ) {
531
  add_filter( 'authenticate', array( $this->user, 'check_activated' ), 99, 3 );
532
  }
533
 
includes/cli/class-wp-members-cli-user.php CHANGED
@@ -192,7 +192,7 @@ if ( defined( 'WP_CLI' ) && WP_CLI ) {
192
  if ( empty( $user ) || ! $user ) {
193
  WP_CLI::error( 'User does not exist. Try wp user list' );
194
  }
195
- $all = ( $assoc_args['all'] ) ? true : false;
196
  $this->display_user_detail( $user, $all );
197
  }
198
 
@@ -207,7 +207,7 @@ if ( defined( 'WP_CLI' ) && WP_CLI ) {
207
  private function display_user_detail( $user, $all ) {
208
  WP_CLI::line( sprintf( __( 'User: %s', 'wp-members' ), $user->user_login ) );
209
 
210
- $values = wpmem_user_data( $user_id, $all );
211
  foreach ( $values as $key => $meta ) {
212
  $list[] = array(
213
  'meta' => $key,
192
  if ( empty( $user ) || ! $user ) {
193
  WP_CLI::error( 'User does not exist. Try wp user list' );
194
  }
195
+ $all = ( isset( $assoc_args['all'] ) ) ? true : false;
196
  $this->display_user_detail( $user, $all );
197
  }
198
 
207
  private function display_user_detail( $user, $all ) {
208
  WP_CLI::line( sprintf( __( 'User: %s', 'wp-members' ), $user->user_login ) );
209
 
210
+ $values = wpmem_user_data( $user->ID, $all );
211
  foreach ( $values as $key => $meta ) {
212
  $list[] = array(
213
  'meta' => $key,
includes/install.php CHANGED
@@ -789,6 +789,23 @@ function wpmem_onboarding_init( $action ) {
789
  'product_type' => 'plugin',
790
  'opt_in_callback' => 'wpmem_onboarding_opt_in',
791
  'opt_in_callback_args' => array(),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
792
  );
793
  $wpmem_onboarding = new RocketGeek_Onboarding_Beta( $settings );
794
  }
789
  'product_type' => 'plugin',
790
  'opt_in_callback' => 'wpmem_onboarding_opt_in',
791
  'opt_in_callback_args' => array(),
792
+
793
+ 'install_state_option' => 'wpmembers_install_state',
794
+ 'finalize_template' => $wpmem->path . 'includes/admin/partials/onboarding_finalize.php',
795
+ 'notice_template' => $wpmem->path . 'includes/admin/partials/onboarding_notice.php',
796
+
797
+ 'new_install_notice_args' => array(
798
+ 'notice_heading' => __( 'Thank you for installing WP-Members, the original WordPress membership plugin.', 'wp-members' ),
799
+ 'notice_button' => __( 'Complete plugin setup', 'wp-members' ),
800
+ 'show_release_notes' => false,
801
+ 'release_notes_link' => "",
802
+ ),
803
+ 'update_pending_notice_args' => array(
804
+ 'notice_heading' => __( 'Thank you for updating WP-Members, the original WordPress membership plugin.', 'wp-members' ),
805
+ 'notice_button' => __( 'Complete the update', 'wp-members' ),
806
+ 'show_release_notes' => true,
807
+ 'release_notes_link' => "https://rocketgeek.com/release-announcements/wp-members-3-4-2/",
808
+ ),
809
  );
810
  $wpmem_onboarding = new RocketGeek_Onboarding_Beta( $settings );
811
  }
includes/vendor/rocketgeek-tools/class-rocketgeek-onboarding.php CHANGED
@@ -1,11 +1,21 @@
1
  <?php
2
 
 
3
  class RocketGeek_Onboarding_Beta {
4
 
5
  public function __construct( $settings ) {
6
  $this->settings = $settings;
 
 
 
 
 
7
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
8
  add_action( 'admin_menu', array( $this, 'admin_menu' ) );
 
 
 
 
9
  }
10
 
11
  public function enqueue_scripts() {
@@ -29,11 +39,34 @@ class RocketGeek_Onboarding_Beta {
29
  }
30
 
31
  public function admin_menu () {
32
- add_submenu_page( null, $this->settings['page_title'], $this->settings['menu_title'], $this->settings['capability'], $this->settings['menu_slug'], array( $this, 'do_options_page' ) );
33
  }
34
 
35
  public function do_options_page() {
36
  // @todo Get install record to check if this is a new install or update.
37
- call_user_func_array( $this->settings['opt_in_callback'], $this->settings['opt_in_callback_args'] );
38
  }
39
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
 
3
+ if ( ! class_exists( 'RocketGeek_Onboarding_Beta' ) ) :
4
  class RocketGeek_Onboarding_Beta {
5
 
6
  public function __construct( $settings ) {
7
  $this->settings = $settings;
8
+
9
+ foreach ( $settings as $key => $value ) {
10
+ $this->{$key} = $value;
11
+ }
12
+
13
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
14
  add_action( 'admin_menu', array( $this, 'admin_menu' ) );
15
+
16
+ if ( $this->menu_slug != rktgk_get( 'page', false, 'get' ) ) {
17
+ add_action( 'admin_notices', array( $this, 'onboarding_notice' ) );
18
+ }
19
  }
20
 
21
  public function enqueue_scripts() {
39
  }
40
 
41
  public function admin_menu () {
42
+ add_submenu_page( null, $this->page_title, $this->menu_title, $this->capability, $this->menu_slug, array( $this, 'do_options_page' ) );
43
  }
44
 
45
  public function do_options_page() {
46
  // @todo Get install record to check if this is a new install or update.
47
+ call_user_func_array( $this->opt_in_callback, $this->opt_in_callback_args );
48
  }
49
+
50
+ public function onboarding_notice() {
51
+ $install_state = get_option( $this->install_state_option );
52
+ if ( 'new_install' == $install_state ) {
53
+ $args = $this->new_install_notice_args;
54
+ }
55
+
56
+ if ( 'update_pending' == $install_state ) {
57
+ $args = $this->update_pending_notice_args;
58
+ }
59
+
60
+ include_once( $this->notice_template );
61
+ }
62
+
63
+ private function has_user_opted_in() {
64
+ global $wpmem;
65
+ if ( 1 == $wpmem->optin ) {
66
+ return true;
67
+ }
68
+
69
+ return false;
70
+ }
71
+ }
72
+ endif;
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: cbutlerjr
3
  Tags: access, authentication, content, login, member, membership, password, protect, register, registration, restriction, subscriber
4
  Requires at least: 4.0
5
  Tested up to: 6.0
6
- Stable tag: 3.4.2
7
 
8
  License: GPLv3
9
 
@@ -108,7 +108,7 @@ The FAQs are maintained at https://rocketgeek.com/plugins/wp-members/docs/faqs/
108
 
109
  == Upgrade Notice ==
110
 
111
- WP-Members 3.4.2 is a minor update. WP-Members 3.4.2.1 is a bug fix release. Backup prior to upgrading is recommended, but rollback is possible. See changelog for a list of updates. Minimum WP version is 4.0.
112
 
113
 
114
  == Screenshots ==
@@ -136,9 +136,24 @@ WP-Members 3.4.2 is a minor update. WP-Members 3.4.2.1 is a bug fix release. Bac
136
 
137
  * @todo WP-Members pluggable deprecated for use in theme functions.php (wpmem will be initialized when plugins are loaded). If you have any WP-Members pluggable functions that load in the theme functions.php, you'll need to move these to another location, such as a custom plugin file. Keep in mind, pluggable functions are no longer the preferred way of customizing (and have not been for many years) as most customizations, if not all, can be handled by using the plugin's filter and action hooks.
138
 
139
- = 3.4.2.1 =
140
 
141
- * Bug fix in the onboarding notification that causes form conflicts if the install/upgrade process is not finalized.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  = 3.4.2 =
144
 
3
  Tags: access, authentication, content, login, member, membership, password, protect, register, registration, restriction, subscriber
4
  Requires at least: 4.0
5
  Tested up to: 6.0
6
+ Stable tag: 3.4.3.2
7
 
8
  License: GPLv3
9
 
108
 
109
  == Upgrade Notice ==
110
 
111
+ WP-Members 3.4.3 is a minor update. WP-Members 3.4.2.1 is a bug fix release. Backup prior to upgrading is recommended, but rollback is possible. See changelog for a list of updates. Minimum WP version is 4.0.
112
 
113
 
114
  == Screenshots ==
136
 
137
  * @todo WP-Members pluggable deprecated for use in theme functions.php (wpmem will be initialized when plugins are loaded). If you have any WP-Members pluggable functions that load in the theme functions.php, you'll need to move these to another location, such as a custom plugin file. Keep in mind, pluggable functions are no longer the preferred way of customizing (and have not been for many years) as most customizations, if not all, can be handled by using the plugin's filter and action hooks.
138
 
139
+ = 3.4.3.2 =
140
 
141
+ * Add [memberships] shortcode for admin notification email; this will include a list of memberships for the user in admin notification.
142
+ * Move password reset link actions to template_redirect action. This should resolve issues that occur when multiple instances of the_content are run (i.e. the appearance of an invalid key message upon completing the password reset).
143
+
144
+ = 3.4.3.1 =
145
+
146
+ * Moves export class to main user object (previously loaded from admin files). @todo Export class file also remains in admin for backward compatibility if file is called directly.
147
+ * Moves admin object load (back) to "init" action (from "admin_init") as later load can cause problems with extensions loading on the "wpmem_after_admin_init" action.
148
+ * Fixes potential issue with [wpmem_field] shortcode if field does not have a defined type.
149
+
150
+ = 3.4.3 =
151
+
152
+ * Simplified check_validated() and check_activated() functions, included check for null $user.
153
+ * Added wpmem_check_validated and wpmem_check_activated filter hooks.
154
+ * Added display="url" attribute to the [wpmem_field] shortcode for file and image field types.
155
+ * Fix undefined variable in password reset.
156
+ * Improve onboarding process for both new installs and updates.
157
 
158
  = 3.4.2 =
159
 
uninstall.php CHANGED
@@ -85,8 +85,6 @@ function wpmem_uninstall_options() {
85
  delete_option( 'wpmembers_autoex' );
86
  delete_option( 'wpmembers_attrib' );
87
 
88
- delete_option( 'wpmembers_install_state' );
89
-
90
  delete_transient( 'wpmem_user_counts' );
91
 
92
  // Drop user meta key search table.
@@ -99,6 +97,7 @@ function wpmem_uninstall_options() {
99
  $uninstall = new RocketGeek_Satellite_Beta( 'wp-members', plugin_dir_path( __FILE__ ) . 'wp-members.php', 'delete', 'plugin' );
100
  }
101
  delete_option( 'wpmembers_optin' );
 
102
  }
103
 
104
  // End of file.
85
  delete_option( 'wpmembers_autoex' );
86
  delete_option( 'wpmembers_attrib' );
87
 
 
 
88
  delete_transient( 'wpmem_user_counts' );
89
 
90
  // Drop user meta key search table.
97
  $uninstall = new RocketGeek_Satellite_Beta( 'wp-members', plugin_dir_path( __FILE__ ) . 'wp-members.php', 'delete', 'plugin' );
98
  }
99
  delete_option( 'wpmembers_optin' );
100
+ delete_option( 'wpmembers_install_state' );
101
  }
102
 
103
  // End of file.
wp-members.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: WP-Members
4
  Plugin URI: https://rocketgeek.com
5
  Description: WP access restriction and user registration. For more information on plugin features, refer to <a href="https://rocketgeek.com/plugins/wp-members/docs/">the online Users Guide</a>. A <a href="https://rocketgeek.com/plugins/wp-members/quick-start-guide/">Quick Start Guide</a> is also available. WP-Members(tm) is a trademark of butlerblog.com.
6
- Version: 3.4.2.1
7
  Author: Chad Butler
8
  Author URI: https://butlerblog.com/
9
  Text Domain: wp-members
@@ -58,7 +58,7 @@ if ( ! defined( 'ABSPATH' ) ) {
58
  }
59
 
60
  // Initialize constants.
61
- define( 'WPMEM_VERSION', '3.4.2.1' );
62
  define( 'WPMEM_DB_VERSION', '2.3.0' );
63
  define( 'WPMEM_PATH', plugin_dir_path( __FILE__ ) );
64
 
3
  Plugin Name: WP-Members
4
  Plugin URI: https://rocketgeek.com
5
  Description: WP access restriction and user registration. For more information on plugin features, refer to <a href="https://rocketgeek.com/plugins/wp-members/docs/">the online Users Guide</a>. A <a href="https://rocketgeek.com/plugins/wp-members/quick-start-guide/">Quick Start Guide</a> is also available. WP-Members(tm) is a trademark of butlerblog.com.
6
+ Version: 3.4.3.2
7
  Author: Chad Butler
8
  Author URI: https://butlerblog.com/
9
  Text Domain: wp-members
58
  }
59
 
60
  // Initialize constants.
61
+ define( 'WPMEM_VERSION', '3.4.3.2' );
62
  define( 'WPMEM_DB_VERSION', '2.3.0' );
63
  define( 'WPMEM_PATH', plugin_dir_path( __FILE__ ) );
64