Paid Memberships Pro - Version 1.9.5

Version Description

  • 2018-05-24 =
  • BUG FIX: Added 'error' to the list of default order statuses.
  • BUG FIX: Fixed issue where PayPal recurring_payment messages with status "Pending" were treated as "Failed" by our IPN handler. (Thanks, Matt Julian)
  • BUG FIX: The redirect away from the billing page needed to be in the preheader instead of the page shortcode.
  • BUG FIX/ENHANCEMENT: Using the pmpro_getOrderStatuses() function in adminpages/orders.php instead of redundant code there.
  • BUG FIX/ENHANCEMENT: Passing the $order as a second parameter to pmpro_after_checkout when called from the PayPal IPN handler. (The $order was being passed already for "regular" checkouts.)
  • ENHANCEMENT: You can now sort by the Membership Level column added to the users list in the dashboard. (Thanks, Matt Julian)
  • FEATURE: Added support for the privacy features added in WP 4.9.6. Details below.
  • FEATURE: Added suggest privacy page text.
  • FEATURE: Added PMPro-related user meta fields, membership history, and order history to the personal data export. You can filter which user meta fields are included in the export using the new pmpro_get_personal_user_meta_fields filter.
  • FEATURE: Deleting PMPro-related personal data fields when personal data is erased. The ereaser deletes a number of user meta fields (filterable through the new pmpro_get_personal_user_meta_fields_to_erase filter). A user's membership history and order history are retained unless the user is deleted.
  • FEATURE: Now saving a log of when the TOS page is agreed to at checkout. The ID and date modified of the TOS post is saved along with a timestamp of when the TOS was agreed to. This information is shown on the single order page in the admin, the orders CSV export, and on the edit user profile page in the admin. Note that this feature does not yet backport any data for existing users or ask users to re-agree to the TOS if the TOS has gone out of date.
Download this release

Release Info

Developer strangerstudios
Plugin Icon 128x128 Paid Memberships Pro
Version 1.9.5
Comparing to
See all releases

Code changes from version 1.9.4.4 to 1.9.5

CHANGELOG.txt CHANGED
@@ -1,5 +1,27 @@
1
== Changelog ==
2
3
= 1.9.4.3 - 2018-01-04 =
4
* BUG FIX: Fixed issue where PMPro would attempt to cancel gateway subscriptions more than once in some cases.
5
1
== Changelog ==
2
3
+ = 1.9.5 - 2018-05-24 =
4
+ * BUG FIX: Added 'error' to the list of default order statuses.
5
+ * BUG FIX: Fixed issue where PayPal recurring_payment messages with status "Pending" were treated as "Failed" by our IPN handler. (Thanks, Matt Julian)
6
+ * BUG FIX: The redirect away from the billing page needed to be in the preheader instead of the page shortcode.
7
+ * BUG FIX/ENHANCEMENT: Using the pmpro_getOrderStatuses() function in adminpages/orders.php instead of redundant code there.
8
+ * BUG FIX/ENHANCEMENT: Passing the $order as a second parameter to pmpro_after_checkout when called from the PayPal IPN handler. (The $order was being passed already for "regular" checkouts.)
9
+ * ENHANCEMENT: You can now sort by the Membership Level column added to the users list in the dashboard. (Thanks, Matt Julian)
10
+ * FEATURE: Added support for the privacy features added in WP 4.9.6. Details below.
11
+ * FEATURE: Added suggest privacy page text.
12
+ * FEATURE: Added PMPro-related user meta fields, membership history, and order history to the personal data export. You can filter which user meta fields are included in the export using the new pmpro_get_personal_user_meta_fields filter.
13
+ * FEATURE: Deleting PMPro-related personal data fields when personal data is erased. The ereaser deletes a number of user meta fields (filterable through the new pmpro_get_personal_user_meta_fields_to_erase filter). A user's membership history and order history are retained unless the user is deleted.
14
+ * FEATURE: Now saving a log of when the TOS page is agreed to at checkout. The ID and date modified of the TOS post is saved along with a timestamp of when the TOS was agreed to. This information is shown on the single order page in the admin, the orders CSV export, and on the edit user profile page in the admin. Note that this feature does not yet backport any data for existing users or ask users to re-agree to the TOS if the TOS has gone out of date.
15
+
16
+ = 1.9.4.4 - 2018-03-14 =
17
+ * BUG FIX: Updated the filters to extend membership levels to use the new pmpro_getSpecificMembershipLevelForUser() function to avoid bugs when MMPU is enabled.
18
+ * BUG FIX: Fixed cases where certain email templates were resulting in the body of the email being duplicated.
19
+ * BUG FIX: Fixed conflict with pmpro-email-templates when emails were disabled (the pmpro_email filter returns false). (Thanks, Mathieu Hays)
20
+ * BUG FIX: Now updating status on related subscription orders BEFORE canceling at gateway to avoid cases where the webhook sent by the gateway after canceling the subscription triggers further cancellation attempts.
21
+ * BUG FIX: No longer showing the "Stripe Publishable Key appears incorrect" error message if the key field is blank.
22
+ * ENHANCEMENT: Added the pmpro_getSpecificMembershipLevelForUser( $user_id, $level_id ) function for cases where MMPU is enabled and you want data about a specific membership level a user might have.
23
+ * ENHANCEMENT: Changed labels on the reCAPTCHA settings to match their current terminology: Site Key and Secret Key.
24
+
25
= 1.9.4.3 - 2018-01-04 =
26
* BUG FIX: Fixed issue where PMPro would attempt to cancel gateway subscriptions more than once in some cases.
27
CONTRIBUTE.md CHANGED
@@ -19,16 +19,20 @@ __Please Note:__ GitHub is for bug reports and contributions only. If you have a
19
* Fork the repository on GitHub
20
* For bug fixes, checkout the DEV branch of the PMPro repository.
21
* For new features and enhancements, checkout the branch for the version the feature is milestoned for.
22
- * Make the changes to your forked repository
23
- * Make sure to pull in any "upstream" changes first.
24
- * Use `git remote add upstream https://github.com/strangerstudios/paid-memberships-pro.git` to set the upstream repo
25
* Use `git checkout upstream/dev` then `git pull` to pull in the latest updates on dev.
26
* Use `git checkout dev` then `git merge upstream/dev` to merge those updates into your dev.
27
- * Ensure you stick to the [WordPress Coding Standards](https://codex.wordpress.org/WordPress_Coding_Standards) (even though much of the PMPro code does not currently)
28
- * When committing, reference your issue (if present) and include a note about the fix
29
- * Push the changes to your fork
30
- * For bug fixes, submit a pull request to the latest versioned branch of the PMPro repository (e.g. 1.9).
31
- * For new features and enhancements, submit a pull request to the DEV branch of the PMPro repository.
32
* We will process all pull requests and make suggestions or changes as soon as possible. Feel free to ping us politely via email or social networks to take a look at your pulls.
33
34
## Code Documentation
19
* Fork the repository on GitHub
20
* For bug fixes, checkout the DEV branch of the PMPro repository.
21
* For new features and enhancements, checkout the branch for the version the feature is milestoned for.
22
+ * Make sure to pull in any "upstream" changes first.
23
+ * Use `git remote add upstream https://github.com/strangerstudios/paid-memberships-pro.git` to set the upstream repo
24
* Use `git checkout upstream/dev` then `git pull` to pull in the latest updates on dev.
25
* Use `git checkout dev` then `git merge upstream/dev` to merge those updates into your dev.
26
+ * Create a new local branch for each separate bug fix or feature. This will ensure that each pull request is for one issue only and easier to process.
27
+ * Use `git checkout -b nameofmybugfixorfeature` to create the new branch
28
+ * Make the changes to your local repository.
29
+ * Ensure you stick to the [WordPress Coding Standards](https://codex.wordpress.org/WordPress_Coding_Standards) (even though much of the PMPro code does not currently)
30
+ * If you have an automatic beautifier in your IDE or dev environment, turn it off. Unrelated style changes in your pull requests will make them harder to process. Feel free to message the core development team to ask them to clean up a file you are working on if the inconsitent coding styles is bothering you.
31
+ * You can update the readme.txt to include a comment about your fix or feature in the changelog, but if you do not the core team will do it for you.
32
+ * When committing, reference your issue (if present) and include a note about the fix in the commit message.
33
+ * Push the changes to your fork.
34
+ * For bug fixes, submit a pull request to the DEV branch of the PMPro repository.
35
+ * For new features and enhancements, submit a pull request to the version the feature is milestoned for. This will usually be the version number following the current release unless the core dev team has milestoned the feature for a later release.
36
* We will process all pull requests and make suggestions or changes as soon as possible. Feel free to ping us politely via email or social networks to take a look at your pulls.
37
38
## Code Documentation
adminpages/orders-csv.php CHANGED
@@ -271,6 +271,8 @@ $csv_file_header_array = array(
271
"subscription_transaction_id",
272
"discount_code_id",
273
"discount_code",
274
"timestamp"
275
);
276
@@ -467,6 +469,16 @@ for ( $ic = 1; $ic <= $iterations; $ic ++ ) {
467
}
468
}
469
470
//timestamp
471
$ts = date_i18n( $dateformat, $order->timestamp );
472
array_push( $csvoutput, pmpro_enclose( $ts ) );
271
"subscription_transaction_id",
272
"discount_code_id",
273
"discount_code",
274
+ "tos_consent_post_id",
275
+ "tos_consent_post_modified",
276
"timestamp"
277
);
278
469
}
470
}
471
472
+ //tos_consent
473
+ $consent_entry = $order->get_tos_consent_log_entry();
474
+ if( !empty( $consent_entry ) ) {
475
+ array_push( $csvoutput, pmpro_enclose( $consent_entry['post_id'] ) );
476
+ array_push( $csvoutput, pmpro_enclose( $consent_entry['post_modified'] ) );
477
+ } else {
478
+ array_push( $csvoutput, '' );
479
+ array_push( $csvoutput, '' );
480
+ }
481
+
482
//timestamp
483
$ts = date_i18n( $dateformat, $order->timestamp );
484
array_push( $csvoutput, pmpro_enclose( $ts ) );
adminpages/orders.php CHANGED
@@ -669,32 +669,19 @@ require_once( dirname( __FILE__ ) . '/admin_header.php' );
669
<?php
670
if ( in_array( 'status', $read_only_fields ) && $order_id > 0 ) {
671
echo $order->status;
672
- } else {
673
- ?>
674
- <?php
675
- $statuses = array();
676
- $default_statuses = array(
677
- '',
678
- 'success',
679
- 'cancelled',
680
- 'review',
681
- 'token',
682
- 'refunded',
683
- 'pending',
684
- 'error',
685
- );
686
- $used_statuses = $wpdb->get_col( "SELECT DISTINCT(status) FROM $wpdb->pmpro_membership_orders" );
687
- $statuses = array_unique( array_merge( $default_statuses, $used_statuses ) );
688
- asort( $statuses );
689
- $statuses = apply_filters( 'pmpro_order_statuses', $statuses );
690
?>
691
<select id="status" name="status">
692
- <?php foreach ( $statuses as $status ) { ?>
693
<option
694
value="<?php echo esc_attr( $status ); ?>" <?php selected( $order->status, $status ); ?>><?php echo $status; ?></option>
695
<?php } ?>
696
</select>
697
- <?php } ?>
698
</td>
699
</tr>
700
@@ -851,6 +838,29 @@ selected="selected"<?php } ?>><?php echo date_i18n( 'M', strtotime( $i . '/1/' .
851
</tr>
852
<?php } ?>
853
854
<tr>
855
<th scope="row" valign="top"><label for="notes"><?php _e( 'Notes', 'paid-memberships-pro' ); ?>:</label></th>
856
<td>
669
<?php
670
if ( in_array( 'status', $read_only_fields ) && $order_id > 0 ) {
671
echo $order->status;
672
+ } else { ?>
673
+ <?php
674
+ $statuses = pmpro_getOrderStatuses();
675
?>
676
<select id="status" name="status">
677
+ <?php foreach ( $statuses as $status ) { ?>
678
<option
679
value="<?php echo esc_attr( $status ); ?>" <?php selected( $order->status, $status ); ?>><?php echo $status; ?></option>
680
<?php } ?>
681
</select>
682
+ <?php
683
+ }
684
+ ?>
685
</td>
686
</tr>
687
838
</tr>
839
<?php } ?>
840
841
+ <?php
842
+ $tospage_id = pmpro_getOption( 'tospage' );
843
+ $consent_entry = $order->get_tos_consent_log_entry();
844
+
845
+ if( !empty( $tospage_id ) || !empty( $consent_entry ) ) {
846
+ ?>
847
+ <tr>
848
+ <th scope="row" valign="top"><label for="tos_consent"><?php _e( 'TOS Consent', 'paid-memberships-pro' ); ?>:</label></th>
849
+ <td id="tos_consent">
850
+ <?php
851
+
852
+ if( !empty( $consent_entry ) ) {
853
+ echo pmpro_consent_to_text( $consent_entry );
854
+ } else {
855
+ echo __( 'N/A' );
856
+ }
857
+ ?>
858
+ </td>
859
+ </tr>
860
+ <?php
861
+ }
862
+ ?>
863
+
864
<tr>
865
<th scope="row" valign="top"><label for="notes"><?php _e( 'Notes', 'paid-memberships-pro' ); ?>:</label></th>
866
<td>
classes/class.memberorder.php CHANGED
@@ -808,6 +808,21 @@
808
}
809
}
810
811
/**
812
* Delete an order and associated data.
813
*/
808
}
809
}
810
811
+ /**
812
+ * Get TOS consent information.
813
+ * @since 1.9.5
814
+ */
815
+ function get_tos_consent_log_entry() {
816
+ $consent_log = pmpro_get_consent_log( $this->user_id );
817
+ foreach( $consent_log as $entry ) {
818
+ if( $entry['order_id'] == $this->id ) {
819
+ return $entry;
820
+ }
821
+ }
822
+
823
+ return false;
824
+ }
825
+
826
/**
827
* Delete an order and associated data.
828
*/
classes/class.pmproemail.php CHANGED
@@ -862,16 +862,24 @@
862
//make sure we have the current membership level data
863
$user->membership_level = pmpro_getMembershipLevelForUser($user->ID, true);
864
865
$this->email = get_bloginfo("admin_email");
866
$this->subject = sprintf(__("Membership for %s at %s has been changed", "paid-memberships-pro"), $user->user_login, get_option("blogname"));
867
868
- $this->data = array("subject" => $this->subject, "name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "membership_level_name" => $user->membership_level->name, "siteemail" => get_bloginfo("admin_email"), "login_link" => wp_login_url());
869
- if($user->membership_level->ID)
870
$this->data["membership_change"] = sprintf(__("The new level is %s", 'paid-memberships-pro' ), $user->membership_level->name);
871
- else
872
- $this->data["membership_change"] = __("Membership has been cancelled", 'paid-memberships-pro' );
873
874
- if(!empty($user->membership_level->enddate))
875
{
876
$this->data["membership_change"] .= ". " . sprintf(__("This membership will expire on %s", 'paid-memberships-pro' ), date_i18n(get_option('date_format'), $user->membership_level->enddate));
877
}
862
//make sure we have the current membership level data
863
$user->membership_level = pmpro_getMembershipLevelForUser($user->ID, true);
864
865
+ if(!empty($user->membership_level) && !empty($user->membership_level->name)) {
866
+ $membership_level_name = $user->membership_level->name;
867
+ } else {
868
+ $membership_level_name = __('None', 'paid-memberships-pro');
869
+ }
870
+
871
$this->email = get_bloginfo("admin_email");
872
$this->subject = sprintf(__("Membership for %s at %s has been changed", "paid-memberships-pro"), $user->user_login, get_option("blogname"));
873
874
+ $this->data = array("subject" => $this->subject, "name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "membership_level_name" => $membership_level_name, "siteemail" => get_bloginfo("admin_email"), "login_link" => wp_login_url());
875
+
876
+ if(!empty($user->membership_level) && !empty($user->membership_level->ID)) {
877
$this->data["membership_change"] = sprintf(__("The new level is %s", 'paid-memberships-pro' ), $user->membership_level->name);
878
+ } else {
879
+ $this->data["membership_change"] = __("Membership has been cancelled", 'paid-memberships-pro' );
880
+ }
881
882
+ if(!empty($user->membership_level) && !empty($user->membership_level->enddate))
883
{
884
$this->data["membership_change"] .= ". " . sprintf(__("This membership will expire on %s", 'paid-memberships-pro' ), date_i18n(get_option('date_format'), $user->membership_level->enddate));
885
}
classes/gateways/class.pmprogateway_paypalexpress.php CHANGED
@@ -229,13 +229,11 @@
229
*
230
* @since 1.8
231
*/
232
- static function pmpro_checkout_before_processing()
233
- {
234
global $current_user, $gateway;
235
236
//save user fields for PayPal Express
237
- if(!$current_user->ID)
238
- {
239
//get values from post
240
if(isset($_REQUEST['username']))
241
$username = trim(sanitize_text_field($_REQUEST['username']));
@@ -256,6 +254,14 @@
256
$_SESSION['pmpro_signup_email'] = $bemail;
257
}
258
259
//can use this hook to save some other variables to the session
260
do_action("pmpro_paypalexpress_session_vars");
261
}
229
*
230
* @since 1.8
231
*/
232
+ static function pmpro_checkout_before_processing() {
233
global $current_user, $gateway;
234
235
//save user fields for PayPal Express
236
+ if(!$current_user->ID) {
237
//get values from post
238
if(isset($_REQUEST['username']))
239
$username = trim(sanitize_text_field($_REQUEST['username']));
254
$_SESSION['pmpro_signup_email'] = $bemail;
255
}
256
257
+ if( !empty( $_REQUEST['tos'] ) ) {
258
+ $tospost = get_post( pmpro_getOption( 'tospage' ) );
259
+ $_SESSION['tos'] = array(
260
+ 'post_id' => $tospost->ID,
261
+ 'post_modified' => $tospost->post_modified,
262
+ );
263
+ }
264
+
265
//can use this hook to save some other variables to the session
266
do_action("pmpro_paypalexpress_session_vars");
267
}
includes/addons.php CHANGED
@@ -1,70 +1,66 @@
1
<?php
2
- /*
3
- Some of the code in this library was borrowed from the TGM Updater class by Thomas Griffin. (https://github.com/thomasgriffin/TGM-Updater)
4
- */
5
6
/**
7
* Setup plugins api filters
8
*
9
* @since 1.8.5
10
- */
11
- function pmpro_setupAddonUpdateInfo()
12
- {
13
- add_filter('plugins_api', 'pmpro_plugins_api', 10, 3);
14
- add_filter('pre_set_site_transient_update_plugins', 'pmpro_update_plugins_filter');
15
- add_filter('http_request_args', 'pmpro_http_request_args_for_addons', 10, 2);
16
- add_action('update_option_pmpro_license_key', 'pmpro_reset_update_plugins_cache', 10, 2);
17
}
18
- add_action('init', 'pmpro_setupAddonUpdateInfo');
19
20
/**
21
* Get addon information from PMPro server.
22
*
23
* @since 1.8.5
24
*/
25
- function pmpro_getAddons()
26
- {
27
- //check if forcing a pull from the server
28
- $addons = get_option("pmpro_addons", array());
29
- $addons_timestamp = get_option("pmpro_addons_timestamp", 0);
30
-
31
- //if no addons locally, we need to hit the server
32
- if(empty($addons) || !empty($_REQUEST['force-check']) || current_time('timestamp') > $addons_timestamp+86400)
33
- {
34
- /**
35
- * Filter to change the timeout for this wp_remote_get() request.
36
- *
37
- * @since 1.8.5.1
38
- *
39
- * @param int $timeout The number of seconds before the request times out
40
- */
41
- $timeout = apply_filters("pmpro_get_addons_timeout", 5);
42
-
43
- //get em
44
- $remote_addons = wp_remote_get(PMPRO_LICENSE_SERVER . "addons/", $timeout);
45
-
46
- //make sure we have at least an array to pass back
47
- if(empty($addons))
48
- $addons = array();
49
-
50
- //test response
51
- if(is_wp_error($remote_addons)) {
52
- //error
53
- pmpro_setMessage("Could not connect to the PMPro License Server to update addon information. Try again later.", "error");
54
- }
55
- elseif(!empty($remote_addons) && $remote_addons['response']['code'] == 200)
56
- {
57
- //update addons in cache
58
- $addons = json_decode(wp_remote_retrieve_body($remote_addons), true);
59
- delete_option('pmpro_addons');
60
- add_option("pmpro_addons", $addons, NULL, 'no');
61
- }
62
-
63
- //save timestamp of last update
64
- delete_option('pmpro_addons_timestamp');
65
- add_option("pmpro_addons_timestamp", current_time('timestamp'), NULL, 'no');
66
- }
67
-
68
return $addons;
69
}
70
@@ -75,31 +71,33 @@ function pmpro_getAddons()
75
*
76
* @param object $slug The identifying slug for the addon (typically the directory name)
77
* @return object $addon containing plugin information or false if not found
78
- */
79
- function pmpro_getAddonBySlug($slug)
80
- {
81
$addons = pmpro_getAddons();
82
-
83
- if(empty($addons))
84
return false;
85
-
86
- foreach($addons as $addon)
87
- if($addon['Slug'] == $slug)
88
return $addon;
89
-
90
return false;
91
}
92
93
/**
94
- * Infuse plugin update details when WordPress runs its update checker.
95
- *
96
- * @since 1.8.5
97
- *
98
- * @param object $value The WordPress update object.
99
- * @return object $value Amended WordPress update object on success, default if object is empty.
100
- */
101
function pmpro_update_plugins_filter( $value ) {
102
-
103
// If no update object exists, return early.
104
if ( empty( $value ) ) {
105
return $value;
@@ -107,36 +105,37 @@ function pmpro_update_plugins_filter( $value ) {
107
108
// get addon information
109
$addons = pmpro_getAddons();
110
-
111
// no addons?
112
- if(empty($addons))
113
return $value;
114
-
115
- //check addons
116
- foreach($addons as $addon)
117
- {
118
- //skip wordpress.org plugins
119
- if(empty($addon['License']) || $addon['License'] == 'wordpress')
120
continue;
121
-
122
- //get data for plugin
123
$plugin_file = $addon['Slug'] . '/' . $addon['Slug'] . '.php';
124
- $plugin_file_abs = WP_PLUGIN_DIR . "/" . $plugin_file;
125
-
126
- //couldn't find plugin, skip
127
- if(!file_exists($plugin_file_abs))
128
continue;
129
- else
130
- $plugin_data = get_plugin_data( $plugin_file_abs, false, true);
131
-
132
- //compare versions
133
- if(!empty($addon['License']) && version_compare($plugin_data['Version'], $addon['Version'], '<'))
134
- {
135
- $value->response[$plugin_file] = pmpro_getPluginAPIObjectFromAddon($addon);
136
- $value->response[$plugin_file]->new_version = $addon['Version'];
137
}
138
}
139
-
140
// Return the update object.
141
return $value;
142
}
@@ -146,16 +145,16 @@ function pmpro_update_plugins_filter( $value ) {
146
*
147
* @since 1.8.5
148
*
149
- * @param array $args Array of request args.
150
* @param string $url The URL to be pinged.
151
* @return array $args Amended array of request args.
152
*/
153
- function pmpro_http_request_args_for_addons($args, $url)
154
- {
155
// If this is an SSL request and we are performing an upgrade routine, disable SSL verification.
156
- if(strpos($url, 'https://') !== false && strpos($url, PMPRO_LICENSE_SERVER) !== false && strpos($url, "download") !== false)
157
$args['sslverify'] = false;
158
-
159
return $args;
160
}
161
@@ -164,25 +163,27 @@ function pmpro_http_request_args_for_addons($args, $url)
164
*
165
* @since 1.8.5
166
*/
167
- function pmpro_plugins_api($api, $action = '', $args = null)
168
- {
169
- //Not even looking for plugin information? Or not given slug?
170
- if('plugin_information' != $action || empty($args->slug))
171
return $api;
172
-
173
- //get addon information
174
- $addon = pmpro_getAddonBySlug($args->slug);
175
-
176
- //no addons?
177
- if(empty($addon))
178
return $api;
179
-
180
- //handled by wordpress.org?
181
- if(empty($addon['License']) || $addon['License'] == 'wordpress')
182
return $api;
183
-
184
// Create a new stdClass object and populate it with our plugin information.
185
- $api = pmpro_getPluginAPIObjectFromAddon($addon);
186
return $api;
187
}
188
@@ -191,36 +192,39 @@ function pmpro_plugins_api($api, $action = '', $args = null)
191
*
192
* @since 1.8.5
193
*/
194
- function pmpro_getPluginAPIObjectFromAddon($addon)
195
- {
196
- $api = new stdClass;
197
-
198
- if(empty($addon))
199
return $api;
200
-
201
- $api->name = isset( $addon['Name'] ) ? $addon['Name'] : '';
202
- $api->slug = isset( $addon['Slug'] ) ? $addon['Slug'] : '';
203
- $api->plugin = isset( $addon['plugin'] ) ? $addon['plugin'] : '';
204
- $api->version = isset( $addon['Version'] ) ? $addon['Version'] : '';
205
- $api->author = isset( $addon['Author'] ) ? $addon['Author'] : '';
206
- $api->author_profile = isset( $addon['AuthorURI'] ) ? $addon['AuthorURI'] : '';
207
- $api->requires = isset( $addon['Requires'] ) ? $addon['Requires'] : '';
208
- $api->tested = isset( $addon['Tested'] ) ? $addon['Tested'] : '';
209
- $api->last_updated = isset( $addon['LastUpdated'] ) ? $addon['LastUpdated'] : '';
210
- $api->homepage = isset( $addon['URI'] ) ? $addon['URI'] : '';
211
- $api->sections['changelog'] = isset( $addon['Changelog'] ) ? $addon['Changelog'] : '';
212
- $api->download_link = isset( $addon['Download'] ) ? $addon['Download'] : '';
213
- $api->package = isset( $addon['Download'] ) ? $addon['Download'] : '';
214
-
215
- //get license key if one is available
216
- $key = get_option("pmpro_license_key", "");
217
- if(!empty($key) && !empty($api->download_link))
218
- $api->download_link = add_query_arg("key", $key, $api->download_link);
219
- if(!empty($key) && !empty($api->package))
220
- $api->package = add_query_arg("key", $key, $api->package);
221
- if(empty($api->upgrade_notice) && !pmpro_license_isValid())
222
- $api->upgrade_notice = __('Important: This plugin requires a valid PMPro Plus license key to update.', 'paid-memberships-pro');
223
-
224
return $api;
225
}
226
@@ -229,14 +233,13 @@ function pmpro_getPluginAPIObjectFromAddon($addon)
229
*
230
* @since 1.8
231
*
232
- * @param array $args Array of request args.
233
* @param string $url The URL to be pinged.
234
* @return array $args Amended array of request args.
235
*/
236
- function pmpro_reset_update_plugins_cache($old_value, $value)
237
- {
238
- delete_option('pmpro_addons_timestamp');
239
- delete_site_transient('update_themes');
240
}
241
242
/**
@@ -244,89 +247,90 @@ function pmpro_reset_update_plugins_cache($old_value, $value)
244
*
245
* @since 1.9
246
*/
247
- function pmpro_admin_init_updating_plugins() {
248
- //if user can't edit plugins, then WP will catch this later
249
- if ( ! current_user_can('update_plugins') )
250
return;
251
-
252
- //updating one or more plugins via Dashboard -> Upgrade
253
- if(basename($_SERVER['SCRIPT_NAME']) == 'update.php' && !empty($_REQUEST['action']) && $_REQUEST['action'] == 'update-selected' && !empty($_REQUEST['plugins'])) {
254
- //figure out which plugin we are updating
255
- $plugins = explode( ',', stripslashes($_GET['plugins']) );
256
- $plugins = array_map('urldecode', $plugins);
257
-
258
- //look for addons
259
$plus_addons = array();
260
$plus_plugins = array();
261
- foreach($plugins as $plugin) {
262
- $slug = str_replace('.php', '', basename($plugin));
263
- $addon = pmpro_getAddonBySlug($slug);
264
- if(!empty($addon) && $addon['License'] == 'plus') {
265
$plus_addons[] = $addon['Name'];
266
$plus_plugins[] = $plugin;
267
- }
268
}
269
- unset($plugin);
270
-
271
- //if Plus addons found, check license key
272
- if(!empty($plus_plugins) && !pmpro_license_isValid(NULL, 'plus')) {
273
- //show error
274
- $msg = __('You must have a <a href="https://www.paidmembershipspro.com/pricing/?utm_source=wp-admin&utm_pluginlink=bulkupdate">valid PMPro Plus License Key</a> to update PMPro Plus add ons. The following plugins will not be updated:', 'paid-memberships-pro');
275
- echo '<div class="error"><p>' . $msg . ' <strong>' . implode(', ', $plus_addons) . '</strong></p></div>';
276
}
277
-
278
- //can exit out of this function now
279
return;
280
}
281
-
282
- //upgrading just one or plugin via an update.php link
283
- if(basename($_SERVER['SCRIPT_NAME']) == 'update.php' && !empty($_REQUEST['action']) && $_REQUEST['action'] == 'upgrade-plugin' && !empty($_REQUEST['plugin'])) {
284
- //figure out which plugin we are updating
285
- $plugin = urldecode(trim($_REQUEST['plugin']));
286
-
287
- $slug = str_replace('.php', '', basename($plugin));
288
- $addon = pmpro_getAddonBySlug($slug);
289
- if(!empty($addon) && !pmpro_license_isValid()) {
290
- require_once(ABSPATH . 'wp-admin/admin-header.php');
291
-
292
- echo '<div class="wrap"><h2>' . __('Update Plugin') . '</h2>';
293
-
294
- $msg = __('You must have a <a href="https://www.paidmembershipspro.com/pricing/?utm_source=wp-admin&utm_pluginlink=addon_update">valid PMPro Plus License Key</a> to update PMPro Plus add ons.', 'paid-memberships-pro');
295
echo '<div class="error"><p>' . $msg . '</p></div>';
296
-
297
- echo '<p><a href="' . admin_url('admin.php?page=pmpro-addons') . '" target="_parent">' . __('Return to the PMPro Add Ons page', 'paid-memberships-pro') . '</a></p>';
298
-
299
echo '</div>';
300
-
301
- include(ABSPATH . 'wp-admin/admin-footer.php');
302
-
303
- //can exit WP now
304
- exit;
305
- }
306
}
307
-
308
- //updating via AJAX on the plugins page
309
- if(basename($_SERVER['SCRIPT_NAME']) == 'admin-ajax.php' && !empty($_REQUEST['action']) && $_REQUEST['action'] == 'update-plugin' && !empty($_REQUEST['plugin'])) {
310
- //figure out which plugin we are updating
311
- $plugin = urldecode(trim($_REQUEST['plugin']));
312
-
313
- $slug = str_replace('.php', '', basename($plugin));
314
- $addon = pmpro_getAddonBySlug($slug);
315
- if(!empty($addon) && !pmpro_license_isValid()) {
316
- $msg = __('You must enter a valid PMPro Plus License Key under Settings > PMPro License to update this add on.', 'paid-memberships-pro');
317
- echo '<div class="error"><p>' . $msg . '</p></div>';
318
-
319
- //can exit WP now
320
exit;
321
- }
322
}
323
-
324
/*
325
- TODO:
326
* Check for PMPro Plug plugins
327
* If a plus plugin is found, check the PMPro license key
328
* If the key is missing or invalid, throw an error
329
* Show appropriate footer and exit... maybe do something else to keep plugin update from happening
330
*/
331
}
332
- add_action('admin_init', 'pmpro_admin_init_updating_plugins');
1
<?php
2
+ /**
3
+ * Some of the code in this library was borrowed from the TGM Updater class by Thomas Griffin. (https://github.com/thomasgriffin/TGM-Updater)
4
+ */
5
6
/**
7
* Setup plugins api filters
8
*
9
* @since 1.8.5
10
+ */
11
+ function pmpro_setupAddonUpdateInfo() {
12
+ add_filter( 'plugins_api', 'pmpro_plugins_api', 10, 3 );
13
+ add_filter( 'pre_set_site_transient_update_plugins', 'pmpro_update_plugins_filter' );
14
+ add_filter( 'http_request_args', 'pmpro_http_request_args_for_addons', 10, 2 );
15
+ add_action( 'update_option_pmpro_license_key', 'pmpro_reset_update_plugins_cache', 10, 2 );
16
}
17
+ add_action( 'init', 'pmpro_setupAddonUpdateInfo' );
18
19
/**
20
* Get addon information from PMPro server.
21
*
22
* @since 1.8.5
23
*/
24
+ function pmpro_getAddons() {
25
+ // check if forcing a pull from the server
26
+ $addons = get_option( 'pmpro_addons', array() );
27
+ $addons_timestamp = get_option( 'pmpro_addons_timestamp', 0 );
28
+
29
+ // if no addons locally, we need to hit the server
30
+ if ( empty( $addons ) || ! empty( $_REQUEST['force-check'] ) || current_time( 'timestamp' ) > $addons_timestamp + 86400 ) {
31
+ /**
32
+ * Filter to change the timeout for this wp_remote_get() request.
33
+ *
34
+ * @since 1.8.5.1
35
+ *
36
+ * @param int $timeout The number of seconds before the request times out
37
+ */
38
+ $timeout = apply_filters( 'pmpro_get_addons_timeout', 5 );
39
+
40
+ // get em
41
+ $remote_addons = wp_remote_get( PMPRO_LICENSE_SERVER . 'addons/', $timeout );
42
+
43
+ // make sure we have at least an array to pass back
44
+ if ( empty( $addons ) ) {
45
+ $addons = array();
46
+ }
47
+
48
+ // test response
49
+ if ( is_wp_error( $remote_addons ) ) {
50
+ // error
51
+ pmpro_setMessage( 'Could not connect to the PMPro License Server to update addon information. Try again later.', 'error' );
52
+ } elseif ( ! empty( $remote_addons ) && $remote_addons['response']['code'] == 200 ) {
53
+ // update addons in cache
54
+ $addons = json_decode( wp_remote_retrieve_body( $remote_addons ), true );
55
+ delete_option( 'pmpro_addons' );
56
+ add_option( 'pmpro_addons', $addons, null, 'no' );
57
+ }
58
+
59
+ // save timestamp of last update
60
+ delete_option( 'pmpro_addons_timestamp' );
61
+ add_option( 'pmpro_addons_timestamp', current_time( 'timestamp' ), null, 'no' );
62
+ }
63
+
64
return $addons;
65
}
66
71
*
72
* @param object $slug The identifying slug for the addon (typically the directory name)
73
* @return object $addon containing plugin information or false if not found
74
+ */
75
+ function pmpro_getAddonBySlug( $slug ) {
76
$addons = pmpro_getAddons();
77
+
78
+ if ( empty( $addons ) ) {
79
return false;
80
+ }
81
+
82
+ foreach ( $addons as $addon ) {
83
+ if ( $addon['Slug'] == $slug ) {
84
return $addon;
85
+ }
86
+ }
87
+
88
return false;
89
}
90
91
/**
92
+ * Infuse plugin update details when WordPress runs its update checker.
93
+ *
94
+ * @since 1.8.5
95
+ *
96
+ * @param object $value The WordPress update object.
97
+ * @return object $value Amended WordPress update object on success, default if object is empty.
98
+ */
99
function pmpro_update_plugins_filter( $value ) {
100
+
101
// If no update object exists, return early.
102
if ( empty( $value ) ) {
103
return $value;
105
106
// get addon information
107
$addons = pmpro_getAddons();
108
+
109
// no addons?
110
+ if ( empty( $addons ) ) {
111
return $value;
112
+ }
113
+
114
+ // check addons
115
+ foreach ( $addons as $addon ) {
116
+ // skip wordpress.org plugins
117
+ if ( empty( $addon['License'] ) || $addon['License'] == 'wordpress.org' ) {
118
continue;
119
+ }
120
+
121
+ // get data for plugin
122
$plugin_file = $addon['Slug'] . '/' . $addon['Slug'] . '.php';
123
+ $plugin_file_abs = WP_PLUGIN_DIR . '/' . $plugin_file;
124
+
125
+ // couldn't find plugin, skip
126
+ if ( ! file_exists( $plugin_file_abs ) ) {
127
continue;
128
+ } else {
129
+ $plugin_data = get_plugin_data( $plugin_file_abs, false, true );
130
+ }
131
+
132
+ // compare versions
133
+ if ( ! empty( $addon['License'] ) && version_compare( $plugin_data['Version'], $addon['Version'], '<' ) ) {
134
+ $value->response[ $plugin_file ] = pmpro_getPluginAPIObjectFromAddon( $addon );
135
+ $value->response[ $plugin_file ]->new_version = $addon['Version'];
136
}
137
}
138
+
139
// Return the update object.
140
return $value;
141
}
145
*
146
* @since 1.8.5
147
*
148
+ * @param array $args Array of request args.
149
* @param string $url The URL to be pinged.
150
* @return array $args Amended array of request args.
151
*/
152
+ function pmpro_http_request_args_for_addons( $args, $url ) {
153
// If this is an SSL request and we are performing an upgrade routine, disable SSL verification.
154
+ if ( strpos( $url, 'https://' ) !== false && strpos( $url, PMPRO_LICENSE_SERVER ) !== false && strpos( $url, 'download' ) !== false ) {
155
$args['sslverify'] = false;
156
+ }
157
+
158
return $args;
159
}
160
163
*
164
* @since 1.8.5
165
*/
166
+ function pmpro_plugins_api( $api, $action = '', $args = null ) {
167
+ // Not even looking for plugin information? Or not given slug?
168
+ if ( 'plugin_information' != $action || empty( $args->slug ) ) {
169
return $api;
170
+ }
171
+
172
+ // get addon information
173
+ $addon = pmpro_getAddonBySlug( $args->slug );
174
+
175
+ // no addons?
176
+ if ( empty( $addon ) ) {
177
return $api;
178
+ }
179
+
180
+ // handled by wordpress.org?
181
+ if ( empty( $addon['License'] ) || $addon['License'] == 'wordpress.org' ) {
182
return $api;
183
+ }
184
+
185
// Create a new stdClass object and populate it with our plugin information.
186
+ $api = pmpro_getPluginAPIObjectFromAddon( $addon );
187
return $api;
188
}
189
192
*
193
* @since 1.8.5
194
*/
195
+ function pmpro_getPluginAPIObjectFromAddon( $addon ) {
196
+ $api = new stdClass();
197
+
198
+ if ( empty( $addon ) ) {
199
return $api;
200
+ }
201
+
202
+ $api->name = isset( $addon['Name'] ) ? $addon['Name'] : '';
203
+ $api->slug = isset( $addon['Slug'] ) ? $addon['Slug'] : '';
204
+ $api->plugin = isset( $addon['plugin'] ) ? $addon['plugin'] : '';
205
+ $api->version = isset( $addon['Version'] ) ? $addon['Version'] : '';
206
+ $api->author = isset( $addon['Author'] ) ? $addon['Author'] : '';
207
+ $api->author_profile = isset( $addon['AuthorURI'] ) ? $addon['AuthorURI'] : '';
208
+ $api->requires = isset( $addon['Requires'] ) ? $addon['Requires'] : '';
209
+ $api->tested = isset( $addon['Tested'] ) ? $addon['Tested'] : '';
210
+ $api->last_updated = isset( $addon['LastUpdated'] ) ? $addon['LastUpdated'] : '';
211
+ $api->homepage = isset( $addon['URI'] ) ? $addon['URI'] : '';
212
+ $api->sections['changelog'] = isset( $addon['Changelog'] ) ? $addon['Changelog'] : '';
213
+ $api->download_link = isset( $addon['Download'] ) ? $addon['Download'] : '';
214
+ $api->package = isset( $addon['Download'] ) ? $addon['Download'] : '';
215
+
216
+ // get license key if one is available
217
+ $key = get_option( 'pmpro_license_key', '' );
218
+ if ( ! empty( $key ) && ! empty( $api->download_link ) ) {
219
+ $api->download_link = add_query_arg( 'key', $key, $api->download_link );
220
+ }
221
+ if ( ! empty( $key ) && ! empty( $api->package ) ) {
222
+ $api->package = add_query_arg( 'key', $key, $api->package );
223
+ }
224
+ if ( empty( $api->upgrade_notice ) && ! pmpro_license_isValid() ) {
225
+ $api->upgrade_notice = __( 'Important: This plugin requires a valid PMPro Plus license key to update.', 'paid-memberships-pro' );
226
+ }
227
+
228
return $api;
229
}
230
233
*
234
* @since 1.8
235
*
236
+ * @param array $args Array of request args.
237
* @param string $url The URL to be pinged.
238
* @return array $args Amended array of request args.
239
*/
240
+ function pmpro_reset_update_plugins_cache( $old_value, $value ) {
241
+ delete_option( 'pmpro_addons_timestamp' );
242
+ delete_site_transient( 'update_themes' );
243
}
244
245
/**
247
*
248
* @since 1.9
249
*/
250
+ function pmpro_admin_init_updating_plugins() {
251
+ // if user can't edit plugins, then WP will catch this later
252
+ if ( ! current_user_can( 'update_plugins' ) ) {
253
return;
254
+ }
255
+
256
+ // updating one or more plugins via Dashboard -> Upgrade
257
+ if ( basename( $_SERVER['SCRIPT_NAME'] ) == 'update.php' && ! empty( $_REQUEST['action'] ) && $_REQUEST['action'] == 'update-selected' && ! empty( $_REQUEST['plugins'] ) ) {
258
+ // figure out which plugin we are updating
259
+ $plugins = explode( ',', stripslashes( $_GET['plugins'] ) );
260
+ $plugins = array_map( 'urldecode', $plugins );
261
+
262
+ // look for addons
263
$plus_addons = array();
264
$plus_plugins = array();
265
+ foreach ( $plugins as $plugin ) {
266
+ $slug = str_replace( '.php', '', basename( $plugin ) );
267
+ $addon = pmpro_getAddonBySlug( $slug );
268
+ if ( ! empty( $addon ) && $addon['License'] == 'plus' ) {
269
$plus_addons[] = $addon['Name'];
270
$plus_plugins[] = $plugin;
271
+ }
272
}
273
+ unset( $plugin );
274
+
275
+ // if Plus addons found, check license key
276
+ if ( ! empty( $plus_plugins ) && ! pmpro_license_isValid( null, 'plus' ) ) {
277
+ // show error
278
+ $msg = __( 'You must have a <a href="https://www.paidmembershipspro.com/pricing/?utm_source=wp-admin&utm_pluginlink=bulkupdate">valid PMPro Plus License Key</a> to update PMPro Plus add ons. The following plugins will not be updated:', 'paid-memberships-pro' );
279
+ echo '<div class="error"><p>' . $msg . ' <strong>' . implode( ', ', $plus_addons ) . '</strong></p></div>';
280
}
281
+
282
+ // can exit out of this function now
283
return;
284
}
285
+
286
+ // upgrading just one or plugin via an update.php link
287
+ if ( basename( $_SERVER['SCRIPT_NAME'] ) == 'update.php' && ! empty( $_REQUEST['action'] ) && $_REQUEST['action'] == 'upgrade-plugin' && ! empty( $_REQUEST['plugin'] ) ) {
288
+ // figure out which plugin we are updating
289
+ $plugin = urldecode( trim( $_REQUEST['plugin'] ) );
290
+
291
+ $slug = str_replace( '.php', '', basename( $plugin ) );
292
+ $addon = pmpro_getAddonBySlug( $slug );
293
+ if ( ! empty( $addon ) && ! pmpro_license_isValid() ) {
294
+ require_once( ABSPATH . 'wp-admin/admin-header.php' );
295
+
296
+ echo '<div class="wrap"><h2>' . __( 'Update Plugin' ) . '</h2>';
297
+
298
+ $msg = __( 'You must have a <a href="https://www.paidmembershipspro.com/pricing/?utm_source=wp-admin&utm_pluginlink=addon_update">valid PMPro Plus License Key</a> to update PMPro Plus add ons.', 'paid-memberships-pro' );
299
echo '<div class="error"><p>' . $msg . '</p></div>';
300
+
301
+ echo '<p><a href="' . admin_url( 'admin.php?page=pmpro-addons' ) . '" target="_parent">' . __( 'Return to the PMPro Add Ons page', 'paid-memberships-pro' ) . '</a></p>';
302
+
303
echo '</div>';
304
+
305
+ include( ABSPATH . 'wp-admin/admin-footer.php' );
306
+
307
+ // can exit WP now
308
+ exit;
309
+ }
310
}
311
+
312
+ // updating via AJAX on the plugins page
313
+ if ( basename( $_SERVER['SCRIPT_NAME'] ) == 'admin-ajax.php' && ! empty( $_REQUEST['action'] ) && $_REQUEST['action'] == 'update-plugin' && ! empty( $_REQUEST['plugin'] ) ) {
314
+ // figure out which plugin we are updating
315
+ $plugin = urldecode( trim( $_REQUEST['plugin'] ) );
316
+
317
+ $slug = str_replace( '.php', '', basename( $plugin ) );
318
+ $addon = pmpro_getAddonBySlug( $slug );
319
+ if ( ! empty( $addon ) && ! pmpro_license_isValid() ) {
320
+ $msg = __( 'You must enter a valid PMPro Plus License Key under Settings > PMPro License to update this add on.', 'paid-memberships-pro' );
321
+ echo '<div class="error"><p>' . $msg . '</p></div>';
322
+
323
+ // can exit WP now
324
exit;
325
+ }
326
}
327
+
328
/*
329
+ TODO:
330
* Check for PMPro Plug plugins
331
* If a plus plugin is found, check the PMPro license key
332
* If the key is missing or invalid, throw an error
333
* Show appropriate footer and exit... maybe do something else to keep plugin update from happening
334
*/
335
}
336
+ add_action( 'admin_init', 'pmpro_admin_init_updating_plugins' );
includes/functions.php CHANGED
@@ -2574,7 +2574,7 @@ function pmpro_getOrderStatuses( $force = false ) {
2574
if ( ! isset( $pmpro_order_statuses ) || $force ) {
2575
global $wpdb;
2576
$statuses = array();
2577
- $default_statuses = array( '', 'success', 'cancelled', 'review', 'token', 'refunded' );
2578
$used_statuses = $wpdb->get_col( "SELECT DISTINCT(status) FROM $wpdb->pmpro_membership_orders" );
2579
$statuses = array_unique( array_merge( $default_statuses, $used_statuses ) );
2580
asort( $statuses );
2574
if ( ! isset( $pmpro_order_statuses ) || $force ) {
2575
global $wpdb;
2576
$statuses = array();
2577
+ $default_statuses = array( '', 'success', 'cancelled', 'review', 'token', 'refunded', 'pending', 'error' );
2578
$used_statuses = $wpdb->get_col( "SELECT DISTINCT(status) FROM $wpdb->pmpro_membership_orders" );
2579
$statuses = array_unique( array_merge( $default_statuses, $used_statuses ) );
2580
asort( $statuses );
includes/init.php CHANGED
@@ -245,6 +245,12 @@ function pmpro_manage_users_columns($columns) {
245
return $columns;
246
}
247
248
function pmpro_manage_users_custom_column($column_data, $column_name, $user_id) {
249
250
if($column_name == 'pmpro_membership_level') {
@@ -261,6 +267,19 @@ function pmpro_manage_users_custom_column($column_data, $column_name, $user_id)
261
return $column_data;
262
}
263
264
add_filter('manage_users_columns', 'pmpro_manage_users_columns');
265
add_filter('manage_users_custom_column', 'pmpro_manage_users_custom_column', 10, 3);
266
-
245
return $columns;
246
}
247
248
+ function pmpro_sortable_column($columns)
249
+ {
250
+ $columns['pmpro_membership_level'] = ['level', 'desc'];
251
+ return $columns;
252
+ }
253
+
254
function pmpro_manage_users_custom_column($column_data, $column_name, $user_id) {
255
256
if($column_name == 'pmpro_membership_level') {
267
return $column_data;
268
}
269
270
+ function pmpro_sortable_column_query($query) {
271
+ global $wpdb;
272
+
273
+ $vars = $query->query_vars;
274
+
275
+ if($vars['orderby'] == 'level'){
276
+ $query->query_from .= " LEFT JOIN {$wpdb->prefix}pmpro_memberships_users AS pmpro_mu ON {$wpdb->prefix}users.ID = pmpro_mu.user_id AND pmpro_mu.status = 'active'";
277
+ $query->query_orderby = "ORDER BY pmpro_mu.membership_id " . $vars['order'] . ", {$wpdb->prefix}users.user_registered";
278
+ }
279
+
280
+ }
281
+
282
add_filter('manage_users_columns', 'pmpro_manage_users_columns');
283
add_filter('manage_users_custom_column', 'pmpro_manage_users_custom_column', 10, 3);
284
+ add_filter( 'manage_users_sortable_columns', 'pmpro_sortable_column' );
285
+ add_action('pre_user_query','pmpro_sortable_column_query');
includes/privacy.php ADDED
@@ -0,0 +1,531 @@
1
+ <?php
2
+ /**
3
+ * Code to aid with user data privacy, e.g. GDPR compliance
4
+ *
5
+ * @since 1.9.5
6
+ */
7
+
8
+ /**
9
+ * Add suggested Privacy Policy language for PMPro
10
+ * @since 1.9.5
11
+ */
12
+ function pmpro_add_privacy_policy_content() {
13
+ // Check for support.
14
+ if ( ! function_exists( 'wp_add_privacy_policy_content') ) {
15
+ return;
16
+ }
17
+
18
+ $content = '';
19
+ $content .= '<h2>' . __( 'Data Collected to Manage Your Membership', 'paid-memberships-pro' ) . '</h2>';
20
+ $content .= '<p>' . __( "At checkout, we will collect your name, email address, username, and password. This information is used to setup your account for our site. If you are redirected to an offsite payment gateway to complete your payment, we may store this information in a temporary session variable to setup your account when you return to our site.", 'paid-memberships-pro' ) . '</p>';
21
+ $content .= '<p>' . __( "At checkout, we may also collect your billing address and phone number. This information is used to confirm your credit card. The billing address and phone number are saved by our site to prepopulate the checkout form for future purchases and so we can get in touch with you if needed to discuss your order.", 'paid-memberships-pro' ) . '</p>';
22
+ $content .= '<p>' . __( "At checkout, we may also collect your credit card number, expiration date, and security code. This information is passed to our payment gateway to process your purchase. The last 4 digits of your credit card number and the expiration date are saved by our site to use for reference and to send you an email if your credit card will expire before the next recurring payment.", 'paid-memberships-pro' ) . '</p>';
23
+ $content .= '<p>' . __( "When logged in, we use cookies to track some of your activity on our site including logins, visits, and page views.", 'paid-memberships-pro' ) . '</p>';
24
+
25
+ wp_add_privacy_policy_content( 'Paid Memberships Pro', $content );
26
+ }
27
+ add_action( 'admin_init', 'pmpro_add_privacy_policy_content' );
28
+
29
+ /**
30
+ * Register the personal data eraser for PMPro
31
+ * @param array $erasers All erasers added so far
32
+ */
33
+ function pmpro_register_personal_data_erasers( $erasers = array() ) {
34
+ $erasers[] = array(
35
+ 'eraser_friendly_name' => __( 'Paid Memberships Pro Data' ),
36
+ 'callback' => 'pmpro_personal_data_eraser',
37
+ );
38
+
39
+ return $erasers;
40
+ }
41
+ add_filter( 'wp_privacy_personal_data_erasers', 'pmpro_register_personal_data_erasers' );
42
+
43
+ /**
44
+ * Personal data eraser for PMPro data.
45
+ * @since 1.9.5
46
+ * @param string $email_address Email address of the user to be erased.
47
+ * @param int $page For batching
48
+ */
49
+ function pmpro_personal_data_eraser( $email_address, $page = 1 ) {
50
+ global $wpdb;
51
+
52
+ // What user is this?
53
+ $user = get_user_by( 'email', $email_address );
54
+
55
+ $num_items_removed = 0;
56
+ $num_items_retained = 0;
57
+ $messages = array();
58
+ $done = false;
59
+
60
+ if( !empty( $user ) ) {
61
+ // Erase any data we have about this user.
62
+ $user_meta_fields_to_erase = pmpro_get_personal_user_meta_fields_to_erase();
63
+
64
+ $sqlQuery = $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE user_id = %d AND meta_key IN( [IN_CLAUSE] )", intval( $user->ID ) );
65
+
66
+ $in_clause_data = array_map( 'esc_sql', $user_meta_fields_to_erase );
67
+ $in_clause = "'" . implode( "', '", $in_clause_data ) . "'";
68
+ $sqlQuery = preg_replace( '/\[IN_CLAUSE\]/', $in_clause, $sqlQuery );
69
+
70
+ $wpdb->query( $sqlQuery );
71
+ $num_deleted = $wpdb->rows_affected;
72
+ $num_items_removed += $num_deleted;
73
+
74
+ // We retain all orders. Get the number of them to report them as retained.
75
+ $sqlQuery = $wpdb->prepare( "SELECT COUNT(id) FROM {$wpdb->pmpro_membership_orders} WHERE user_id = %d", intval( $user->ID ) );
76
+ $num_orders = $wpdb->get_var( $sqlQuery );
77
+ if( $num_orders > 0 ) {
78
+ $num_items_retained += $num_orders;
79
+ // We could have used _n below, but that doesn't work well with our script for generating the .pot file.
80
+ if( $num_orders == 1 ) {
81
+ $messages[] = __( '1 PMPro order was retained for business records.', 'paid-memberships-pro' );
82
+ } else {
83
+ $messages[] = sprintf( __( '%d PMPro orders were retained for business records.', 'paid-memberships-pro' ), $num_orders );
84
+ }
85
+ }
86
+
87
+ // Warn the admin if this user has an active subscription
88
+ $messages[] = __( "Please note that data erasure will not cancel a user's membership level or any active subscriptions. Please edit or delete the user through the WordPress dashboard.", 'paid-memberships-pro' );
89
+ }
90
+
91
+ // Set done to false if we still have stuff to erase.
92
+ $done = true;
93
+
94
+ return array(
95
+ 'items_removed' => $num_items_removed,
96
+ 'items_retained' => $num_items_retained,
97
+ 'messages' => $messages,
98
+ 'done' => $done,
99
+ );
100
+ }
101
+
102
+ /**
103
+ * Register the personal data exporter for PMPro.
104
+ * @since 1.9.5
105
+ * @param array $exporters All exporters added so far
106
+ */
107
+ function pmpro_register_personal_data_exporters( $exporters ) {
108
+ $exporters[] = array(
109
+ 'exporter_friendly_name' => __( 'Paid Memberships Pro Data' ),
110
+ 'callback' => 'pmpro_personal_data_exporter',
111
+ );
112
+
113
+ return $exporters;
114
+ }
115
+ add_filter( 'wp_privacy_personal_data_exporters', 'pmpro_register_personal_data_exporters' );
116
+
117
+ /**
118
+ * Personal data exporter for PMPro data.
119
+ * @since 1.9.5
120
+ */
121
+ function pmpro_personal_data_exporter( $email_address, $page = 1 ) {
122
+ global $wpdb;
123
+
124
+ $data_to_export = array();
125
+
126
+ // What user is this?
127
+ $user = get_user_by( 'email', $email_address );
128
+
129
+ if( !empty( $user ) ) {
130
+ // Add data stored in user meta.
131
+ $personal_user_meta_fields = pmpro_get_personal_user_meta_fields();
132
+ $sqlQuery = $wpdb->prepare(
133
+ "SELECT meta_key, meta_value
134
+ FROM {$wpdb->usermeta}
135
+ WHERE user_id = %d
136
+ AND meta_key IN( [IN_CLAUSE] )", intval( $user->ID ) );
137
+
138
+ $in_clause_data = array_map( 'esc_sql', array_keys( $personal_user_meta_fields ) );
139
+ $in_clause = "'" . implode( "', '", $in_clause_data ) . "'";
140
+ $sqlQuery = preg_replace( '/\[IN_CLAUSE\]/', $in_clause, $sqlQuery );
141
+
142
+ $personal_user_meta_data = $wpdb->get_results( $sqlQuery, OBJECT_K );
143
+
144
+ $user_meta_data_to_export = array();
145
+ foreach( $personal_user_meta_fields as $key => $name ) {
146
+ if( !empty( $personal_user_meta_data[$key] ) ) {
147
+ $value = $personal_user_meta_data[$key]->meta_value;
148
+ } else {
149
+ $value = '';
150
+ }
151
+
152
+ $user_meta_data_to_export[] = array(
153
+ 'name' => $name,
154
+ 'value' => $value,
155
+ );
156
+ }
157
+
158
+ $data_to_export[] = array(
159
+ 'group_id' => 'pmpro_user_data',
160
+ 'group_label' => __( 'Paid Memberships Pro User Data' ),
161
+ 'item_id' => "user-{$user->ID}",
162
+ 'data' => $user_meta_data_to_export,
163
+ );
164
+
165
+
166
+ // Add membership history.
167
+ $sqlQuery = $wpdb->prepare(
168
+ "SELECT * FROM {$wpdb->pmpro_memberships_users}
169
+ WHERE user_id = %d
170
+ ORDER BY id DESC", intval( $user->ID ) );
171
+
172
+ $history = $wpdb->get_results( $sqlQuery );
173
+ foreach( $history as $item ) {
174
+ if( $item->enddate === null || $item->enddate == '0000-00-00 00:00:00' ) {
175
+ $item->enddate = __( 'Never', 'paid-memberships-pro' );
176
+ } else {
177
+ $item->enddate = date( get_option( 'date_format' ), strtotime( $item->enddate, current_time( 'timestamp' ) ) );
178
+ }
179
+
180
+ $history_data_to_export = array(
181
+ array(
182
+ 'name' => __( 'Level ID', 'paid-memberships-pro' ),
183
+ 'value' => $item->membership_id,
184
+ ),
185
+ array(
186
+ 'name' => __( 'Start Date', 'paid-memberships-pro' ),
187
+ 'value' => date( get_option( 'date_format' ), strtotime( $item->startdate, current_time( 'timestamp' ) ) ),
188
+ ),
189
+ array(
190
+ 'name' => __( 'Date Modified', 'paid-memberships-pro' ),
191
+ 'value' => date( get_option( 'date_format' ), strtotime( $item->modified, current_time( 'timestamp' ) ) ),
192
+ ),
193
+ array(
194
+ 'name' => __( 'End Date', 'paid-memberships-pro' ),
195
+ 'value' => $item->enddate,
196
+ ),
197
+ array(
198
+ 'name' => __( 'Level Cost', 'paid-memberships-pro' ),
199
+ 'value' => pmpro_getLevelCost( $item, false, true ),
200
+ ),
201
+ array(
202
+ 'name' => __( 'Status', 'paid-memberships-pro' ),
203
+ 'value' => $item->status,
204
+ ),
205
+ );
206
+
207
+ $data_to_export[] = array(
208
+ 'group_id' => 'pmpro_membership_history',
209
+ 'group_label' => __( 'Paid Memberships Pro Membership History' ),
210
+ 'item_id' => "memberships_users-{$item->id}",
211
+ 'data' => $history_data_to_export,
212
+ );
213
+ }
214
+
215
+ // Add order history.
216
+ $sqlQuery = $wpdb->prepare(
217
+ "SELECT id FROM {$wpdb->pmpro_membership_orders}
218
+ WHERE user_id = %d
219
+ ORDER BY id DESC", intval( $user->ID ) );
220
+
221
+ $order_ids = $wpdb->get_col( $sqlQuery );
222
+
223
+ foreach( $order_ids as $order_id ) {
224
+ $order = new MemberOrder( $order_id );
225
+ $order->getMembershipLevel();
226
+
227
+ $order_data_to_export = array(
228
+ array(
229
+ 'name' => __( 'Order ID', 'paid-memberships-pro' ),
230
+ 'value' => $order->id,
231
+ ),
232
+ array(
233
+ 'name' => __( 'Order Code', 'paid-memberships-pro' ),
234
+ 'value' => $order->code,
235
+ ),
236
+ array(
237
+ 'name' => __( 'Order Date', 'paid-memberships-pro' ),
238
+ 'value' => date( get_option( 'date_format' ), $order->timestamp ),
239
+ ),
240
+ array(
241
+ 'name' => __( 'Level', 'paid-memberships-pro' ),
242
+ 'value' => $order->membership_level->name,
243
+ ),
244
+ array(
245
+ 'name' => __( 'Billing Name', 'paid-memberships-pro' ),
246
+ 'value' => $order->billing->name,
247
+ ),
248
+ array(
249
+ 'name' => __( 'Billing Street', 'paid-memberships-pro' ),
250
+ 'value' => $order->billing->street,
251
+ ),
252
+ array(
253
+ 'name' => __( 'Billing City', 'paid-memberships-pro' ),
254
+ 'value' => $order->billing->city,
255
+ ),
256
+ array(
257
+ 'name' => __( 'Billing State', 'paid-memberships-pro' ),
258
+ 'value' => $order->billing->state,
259
+ ),
260
+ array(
261
+ 'name' => __( 'Billing Postal Code', 'paid-memberships-pro' ),
262
+ 'value' => $order->billing->zip,
263
+ ),
264
+ array(
265
+ 'name' => __( 'Billing Country', 'paid-memberships-pro' ),
266
+ 'value' => $order->billing->country,
267
+ ),
268
+ array(
269
+ 'name' => __( 'Billing Phone', 'paid-memberships-pro' ),
270
+ 'value' => formatPhone( $order->billing->phone ),
271
+ ),
272
+ array(
273
+ 'name' => __( 'Sub Total', 'paid-memberships-pro' ),
274
+ 'value' => $order->subtotal,
275
+ ),
276
+ array(
277
+ 'name' => __( 'Tax', 'paid-memberships-pro' ),
278
+ 'value' => $order->tax,
279
+ ),
280
+ array(
281
+ 'name' => __( 'Coupon Amount', 'paid-memberships-pro' ),
282
+ 'value' => $order->couponamount,
283
+ ),
284
+ array(
285
+ 'name' => __( 'Total', 'paid-memberships-pro' ),
286
+ 'value' => $order->total,
287
+ ),
288
+ array(
289
+ 'name' => __( 'Payment Type', 'paid-memberships-pro' ),
290
+ 'value' => $order->payment_type,
291
+ ),
292
+ array(
293
+ 'name' => __( 'Card Type', 'paid-memberships-pro' ),
294
+ 'value' => $order->cardtype,
295
+ ),
296
+ array(
297
+ 'name' => __( 'Account Number', 'paid-memberships-pro' ),
298
+ 'value' => $order->accountnumber,
299
+ ),
300
+ array(
301
+ 'name' => __( 'Expiration Month', 'paid-memberships-pro' ),
302
+ 'value' => $order->expirationmonth,
303
+ ),
304
+ array(
305
+ 'name' => __( 'Expiration Year', 'paid-memberships-pro' ),
306
+ 'value' => $order->expirationyear,
307
+ ),
308
+ array(
309
+ 'name' => __( 'Status', 'paid-memberships-pro' ),
310
+ 'value' => $order->status,
311
+ ),
312
+ array(
313
+ 'name' => __( 'Gateway', 'paid-memberships-pro' ),
314
+ 'value' => $order->gateway,
315
+ ),
316
+ array(
317
+ 'name' => __( 'Gateway Environment', 'paid-memberships-pro' ),
318
+ 'value' => $order->gateway_environment,
319
+ ),
320
+ array(
321
+ 'name' => __( 'Payment Transaction ID', 'paid-memberships-pro' ),
322
+ 'value' => $order->payment_transaction_id,
323
+ ),
324
+ array(
325
+ 'name' => __( 'Subscription Transaction ID', 'paid-memberships-pro' ),
326
+ 'value' => $order->subscription_transaction_id,
327
+ ),
328
+ // Note: Order notes, session_id, and paypal_token are excluded.
329
+ );
330
+
331
+ $data_to_export[] = array(
332
+ 'group_id' => 'pmpro_order_history',
333
+ 'group_label' => __( 'Paid Memberships Pro Order History' ),
334
+ 'item_id' => "membership_order-{$order->id}",
335
+ 'data' => $order_data_to_export,
336
+ );
337
+ }
338
+ }
339
+
340
+ $done = true;
341
+
342
+ return array(
343
+ 'data' => $data_to_export,
344
+ 'done' => $done,
345
+ );
346
+ }
347
+
348
+ /**
349
+ * Get list of user meta fields with labels to include in the PMPro data exporter
350
+ * @since 1.9.5
351
+ */
352
+ function pmpro_get_personal_user_meta_fields() {
353
+ $fields = array(
354
+ 'pmpro_bfirstname' => __( 'Billing First Name', 'paid-memberships-pro' ),
355
+ 'pmpro_blastname' => __( 'Billing Last Name', 'paid-memberships-pro' ),
356
+ 'pmpro_baddress1' => __( 'Billing Address 1', 'paid-memberships-pro' ),
357
+ 'pmpro_baddress2' => __( 'Billing Address 2', 'paid-memberships-pro' ),
358
+ 'pmpro_bcity' => __( 'Billing City', 'paid-memberships-pro' ),
359
+ 'pmpro_bstate' => __( 'Billing State/Province', 'paid-memberships-pro' ),
360
+ 'pmpro_bzipcode' => __( 'Billing Postal Code', 'paid-memberships-pro' ),
361
+ 'pmpro_bphone' => __( 'Billing Phone Number', 'paid-memberships-pro' ),
362
+ 'pmpro_bcountry' => __( 'Billing Country', 'paid-memberships-pro' ),
363
+ 'pmpro_CardType' => __( 'Credit Card Type', 'paid-memberships-pro' ),
364
+ 'pmpro_AccountNumber' => __( 'Credit Card Account Number', 'paid-memberships-pro' ),
365
+ 'pmpro_ExpirationMonth' => __( 'Credit Card Expiration Month', 'paid-memberships-pro' ),
366
+ 'pmpro_ExpirationYear' => __( 'Credit Card Expiration Year', 'paid-memberships-pro' ),
367
+ 'pmpro_logins' => __( 'Login Data', 'paid-memberships-pro' ),
368
+ 'pmpro_visits' => __( 'Visits Data', 'paid-memberships-pro' ),
369
+ 'pmpro_views' => __( 'Views Data', 'paid-memberships-pro' ),
370
+ );
371
+
372
+ $fields = apply_filters( 'pmpro_get_personal_user_meta_fields', $fields );
373
+
374
+ return $fields;
375
+ }
376
+
377
+ /**
378
+ * Get list of user meta fields to include in the PMPro data eraser
379
+ * @since 1.9.5
380
+ */
381
+ function pmpro_get_personal_user_meta_fields_to_erase() {
382
+ $fields = array(
383
+ 'pmpro_bfirstname',
384
+ 'pmpro_blastname',
385
+ 'pmpro_baddress1',
386
+ 'pmpro_baddress2',
387
+ 'pmpro_bcity',
388
+ 'pmpro_bstate',
389
+ 'pmpro_bzipcode',
390
+ 'pmpro_bphone',
391
+ 'pmpro_bcountry',
392
+ 'pmpro_CardType',
393
+ 'pmpro_AccountNumber',
394
+ 'pmpro_ExpirationMonth',
395
+ 'pmpro_ExpirationYear',
396
+ 'pmpro_logins',
397
+ 'pmpro_visits',
398
+ 'pmpro_views',
399
+ );
400
+
401
+ $fields = apply_filters( 'pmpro_get_personal_user_meta_fields_to_erase', $fields );
402
+
403
+ return $fields;
404
+ }
405
+
406
+ /**
407
+ * Save a TOS consent timestamp to user meta.
408
+ * @since 1.9.5
409
+ */
410
+ function pmpro_save_consent( $user_id = NULL, $post_id = NULL, $post_modified = NULL, $order_id = NULL ) {
411
+ // Default to current user.
412
+ if( empty( $user_id ) ) {
413
+ global $current_user;
414
+ $user_id = $user->ID;
415
+ }
416
+
417
+ if( empty( $user_id ) ) {
418
+ return false;
419
+ }
420
+
421
+ // Default to the TOS post chosen on the advanced settings page
422
+ if( empty( $post_id ) ) {
423
+ $post_id = pmpro_getOption( 'tospage' );
424
+ }
425
+
426
+ if( empty( $post_id ) ) {
427
+ return false;
428
+ }
429
+
430
+ $post = get_post( $post_id );
431
+
432
+ if( empty( $post_modified ) ) {
433
+ $post_modified = $post->post_modified;
434
+ }
435
+
436
+ $log = pmpro_get_consent_log( $user_id );
437
+ $log[] = array(
438
+ 'user_id' => $user_id,
439
+ 'post_id' => $post_id,
440
+ 'post_modified' => $post_modified,
441
+ 'order_id' => $order_id,
442
+ 'consented' => true,
443
+ 'timestamp' => current_time( 'timestamp' ),
444
+ );
445
+
446
+ update_user_meta( $user_id, 'pmpro_consent_log', $log );
447
+ return true;
448
+ }
449
+
450
+ /**
451
+ * Get the TOS consent log from user meta.
452
+ * @since 1.9.5
453
+ */
454
+ function pmpro_get_consent_log( $user_id = NULL, $reversed = true ) {
455
+ // Default to current user.
456
+ if( empty( $user_id ) ) {
457
+ global $current_user;
458
+ $user_id = $user->ID;
459
+ }
460
+
461
+ if( empty( $user_id ) ) {
462
+ return false;
463
+ }
464
+
465
+ $log = get_user_meta( $user_id, 'pmpro_consent_log', true );
466
+
467
+ // Default log.
468
+ if( empty( $log ) ) {
469
+ $log = array();
470
+ }
471
+
472
+ if( $reversed ) {
473
+ $log = array_reverse( $log );
474
+ }
475
+
476
+ return $log;
477
+ }
478
+
479
+ /**
480
+ * Update TOS consent log after checkout.
481
+ * @since 1.9.5
482
+ */
483
+ function pmpro_after_checkout_update_consent( $user_id, $order ) {
484
+ if( !empty( $_REQUEST['tos'] ) ) {
485
+ $tospage_id = pmpro_getOption( 'tospage' );
486
+ pmpro_save_consent( $user_id, $tospage_id, NULL, $order->id );
487
+ } elseif ( !empty( $_SESSION['tos'] ) ) {
488
+ // PayPal Express and others might save tos info into a session variable
489
+ $tospage_id = $_SESSION['tos']['post_id'];
490
+ $tospage_modified = $_SESSION['tos']['post_modified'];
491
+ pmpro_save_consent( $user_id, $tospage_id, $tospage_modified, $order->id );
492
+ unset( $_SESSION['tos'] );
493
+ }
494
+ }
495
+ add_action( 'pmpro_after_checkout', 'pmpro_after_checkout_update_consent', 10, 2 );
496
+ add_action( 'pmpro_before_send_to_paypal_standard', 'pmpro_after_checkout_update_consent', 10, 2);
497
+ add_action( 'pmpro_before_send_to_twocheckout', 'pmpro_after_checkout_update_consent' );
498
+
499
+ /**
500
+ * Convert a consent entry into a English sentence.
501
+ * @since 1.9.5
502
+ */
503
+ function pmpro_consent_to_text( $entry ) {
504
+ $user = get_userdata( $entry['user_id'] );
505
+ $post = get_post( $entry['post_id'] );
506
+
507
+ $s = sprintf( __('%s agreed to %s (ID #%d, last modified %s) on %s.' ),
508
+ $user->display_name,
509
+ $post->post_title,
510
+ $post->ID,
511
+ $entry['post_modified'],
512
+ date( get_option( 'date_format' ), $entry['timestamp'] ) );
513
+
514
+ if( !pmpro_is_consent_current( $entry ) ) {
515
+ $s .= ' ' . __( 'That post has since been updated.', 'paid-memberships-pro' );
516
+ }
517
+
518
+ return $s;
519
+ }
520
+
521
+ /**
522
+ * Check if a consent entry is current.
523
+ * @since 1.9.5
524
+ */
525
+ function pmpro_is_consent_current( $entry ) {
526
+ $post = get_post( $entry['post_id'] );
527
+ if( !empty( $post ) && !empty( $post->post_modified ) && $post->post_modified == $entry['post_modified'] ) {
528
+ return true;
529
+ }
530
+ return false;
531
+ }
includes/profile.php CHANGED
@@ -165,6 +165,32 @@ function pmpro_membership_level_profile_fields($user)
165
<?php
166
}
167
?>
168
</table>
169
<script>
170
jQuery(document).ready(function() {
@@ -295,7 +321,7 @@ function pmpro_membership_level_profile_fields_update()
295
add_filter('pmpro_cancel_previous_subscriptions', 'pmpro_cancel_previous_subscriptions_false');
296
297
//do the change
298
- if(pmpro_changeMembershipLevel($_REQUEST['membership_level'], $user_ID, $changed_or_cancelled))
299
{
300
//it changed. send email
301
$level_changed = true;
165
<?php
166
}
167
?>
168
+
169
+ <?php
170
+ $tospage_id = pmpro_getOption( 'tospage' );
171
+ $consent_log = pmpro_get_consent_log( $user->ID, true );
172
+
173
+ if( !empty( $tospage_id ) || !empty( $consent_log ) ) {
174
+ ?>
175
+ <tr>
176
+ <th><label for="tos_consent_history"><?php _e("TOS Consent History", 'paid-memberships-pro' ); ?></label></th>
177
+ <td id="tos_consent_history">
178
+ <?php
179
+ if( !empty( $consent_log ) ) {
180
+ echo '<ul>';
181
+ foreach( $consent_log as $entry ) {
182
+ echo '<li>' . pmpro_consent_to_text( $entry ) . '</li>';
183
+ }
184
+ echo '</ul>';
185
+ } else {
186
+ echo __( 'N/A', 'paid-memberships-pro' );
187
+ }
188
+ ?>
189
+ </td>
190
+ </tr>
191
+ <?php
192
+ }
193
+ ?>
194
</table>
195
<script>
196
jQuery(document).ready(function() {
321
add_filter('pmpro_cancel_previous_subscriptions', 'pmpro_cancel_previous_subscriptions_false');
322
323
//do the change
324
+ if(pmpro_changeMembershipLevel(intval($_REQUEST['membership_level']), $user_ID, $changed_or_cancelled))
325
{
326
//it changed. send email
327
$level_changed = true;
includes/sessions.php CHANGED
@@ -4,9 +4,14 @@
4
GPLv2 Full license details in license.txt
5
*/
6
7
function pmpro_start_session() {
8
9
- //if the session has been started yet, start it (ignore if running from command line)
10
if ( ! defined( 'PMPRO_USE_SESSIONS' ) || PMPRO_USE_SESSIONS == true ) {
11
if ( defined( 'STDIN' ) ) {
12
//command line
@@ -28,7 +33,7 @@ add_action( 'pmpro_checkout_preheader', 'pmpro_start_session', -1 );
28
29
/**
30
* Close the session object for new updates
31
- * @return MemberOrder
32
*/
33
function pmpro_close_session() {
34
@@ -49,4 +54,4 @@ function pmpro_close_session() {
49
}
50
}
51
52
- add_action( 'pmpro_after_checkout', 'pmpro_close_session', 32768 );
4
GPLv2 Full license details in license.txt
5
*/
6
7
+
8
+ /**
9
+ * A general function to start sessions for Paid Memberships Pro.
10
+ * @since 1.9.2
11
+ */
12
function pmpro_start_session() {
13
14
+ //if the session hasn't been started yet, start it (ignore if running from command line)
15
if ( ! defined( 'PMPRO_USE_SESSIONS' ) || PMPRO_USE_SESSIONS == true ) {
16
if ( defined( 'STDIN' ) ) {
17
//command line
33
34
/**
35
* Close the session object for new updates
36
+ * @since 1.9.2
37
*/
38
function pmpro_close_session() {
39
54
}
55
}
56
57
+ add_action( 'pmpro_after_checkout', 'pmpro_close_session', 32768 );
languages/paid-memberships-pro.mo CHANGED
Binary file
languages/paid-memberships-pro.po CHANGED
@@ -6,7 +6,7 @@ msgid ""
6
msgstr ""
7
"Project-Id-Version: paid-memberships-pro\n"
8
"Report-Msgid-Bugs-To: jason@strangerstudios.com\n"
9
- "POT-Creation-Date: 2018-03-14 19:33-0400\n"
10
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
11
"Last-Translator: \n"
12
"Language-Team: Stranger Studios <jason@strangerstudios.com>\n"
@@ -57,7 +57,7 @@ msgstr ""
57
msgid "Check Again"
58
msgstr ""
59
60
- #: adminpages/addons.php:79 adminpages/orders.php:892 adminpages/addons.php:76
61
#: adminpages/addons.php:79 adminpages/addons.php:92 adminpages/orders.php:605
62
#: adminpages/orders.php:712 adminpages/orders.php:741
63
#: adminpages/orders.php:850 adminpages/orders.php:881
@@ -188,7 +188,9 @@ msgstr ""
188
msgid "WordPress.org"
189
msgstr ""
190
191
- #: adminpages/addons.php:234 shortcodes/pmpro_account.php:148
192
#: adminpages/addons.php:231 adminpages/addons.php:234
193
#: adminpages/addons.php:247 shortcodes/pmpro_account.php:145
194
#: shortcodes/pmpro_account.php:146 shortcodes/pmpro_account.php:148
@@ -539,7 +541,7 @@ msgstr ""
539
#: adminpages/advancedsettings.php:167 adminpages/advancedsettings.php:226
540
#: adminpages/advancedsettings.php:238 adminpages/membershiplevels.php:694
541
#: adminpages/paymentsettings.php:236
542
- #: classes/gateways/class.pmprogateway_stripe.php:298 includes/profile.php:125
543
#: adminpages/advancedsettings.php:128 adminpages/advancedsettings.php:135
544
#: adminpages/advancedsettings.php:148 adminpages/advancedsettings.php:151
545
#: adminpages/advancedsettings.php:167 adminpages/advancedsettings.php:187
@@ -569,7 +571,8 @@ msgstr ""
569
#: classes/gateways/class.pmprogateway_stripe.php:222
570
#: classes/gateways/class.pmprogateway_stripe.php:249
571
#: classes/gateways/class.pmprogateway_stripe.php:281
572
- #: classes/gateways/class.pmprogateway_stripe.php:297 includes/profile.php:101
573
#: includes/profile.php:105 includes/profile.php:110 includes/profile.php:117
574
#: includes/profile.php:121 includes/profile.php:123 includes/profile.php:125
575
msgid "No"
@@ -619,7 +622,7 @@ msgstr ""
619
620
#: adminpages/advancedsettings.php:227 adminpages/membershiplevels.php:694
621
#: adminpages/paymentsettings.php:237
622
- #: classes/gateways/class.pmprogateway_stripe.php:299 includes/profile.php:126
623
#: adminpages/advancedsettings.php:188 adminpages/advancedsettings.php:195
624
#: adminpages/advancedsettings.php:208 adminpages/advancedsettings.php:211
625
#: adminpages/advancedsettings.php:227 adminpages/membershiplevels.php:563
@@ -645,7 +648,8 @@ msgstr ""
645
#: classes/gateways/class.pmprogateway_stripe.php:223
646
#: classes/gateways/class.pmprogateway_stripe.php:250
647
#: classes/gateways/class.pmprogateway_stripe.php:282
648
- #: classes/gateways/class.pmprogateway_stripe.php:298 includes/profile.php:102
649
#: includes/profile.php:106 includes/profile.php:111 includes/profile.php:118
650
#: includes/profile.php:122 includes/profile.php:124 includes/profile.php:126
651
msgid "Yes"
@@ -681,11 +685,11 @@ msgstr ""
681
msgid "Click here to signup for reCAPTCHA"
682
msgstr ""
683
684
- #: adminpages/advancedsettings.php:248
685
msgid "reCAPTCHA Site Key"
686
msgstr ""
687
688
- #: adminpages/advancedsettings.php:251
689
msgid "reCAPTCHA Secret Key"
690
msgstr ""
691
@@ -809,7 +813,7 @@ msgstr ""
809
810
#: adminpages/discountcodes.php:422 adminpages/discountcodes.php:719
811
#: adminpages/membershiplevels.php:322 adminpages/membershiplevels.php:663
812
- #: adminpages/memberslist.php:164 adminpages/orders.php:1140
813
#: adminpages/reports/login.php:162 adminpages/templates/orders-email.php:46
814
#: adminpages/templates/orders-print.php:75 adminpages/discountcodes.php:306
815
#: adminpages/discountcodes.php:309 adminpages/discountcodes.php:310
@@ -841,7 +845,7 @@ msgstr ""
841
msgid "ID"
842
msgstr ""
843
844
- #: adminpages/discountcodes.php:423 adminpages/orders.php:386
845
#: adminpages/discountcodes.php:307 adminpages/discountcodes.php:310
846
#: adminpages/discountcodes.php:311 adminpages/discountcodes.php:312
847
#: adminpages/discountcodes.php:317 adminpages/discountcodes.php:382
@@ -853,7 +857,7 @@ msgid "This will be generated when you save."
853
msgstr ""
854
855
#: adminpages/discountcodes.php:427 adminpages/discountcodes.php:720
856
- #: adminpages/orders.php:391 adminpages/orders.php:1141
857
#: adminpages/discountcodes.php:311 adminpages/discountcodes.php:314
858
#: adminpages/discountcodes.php:315 adminpages/discountcodes.php:316
859
#: adminpages/discountcodes.php:321 adminpages/discountcodes.php:386
@@ -872,16 +876,17 @@ msgstr ""
872
msgid "Code"
873
msgstr ""
874
875
- #: adminpages/discountcodes.php:465 adminpages/discountcodes.php:349
876
- #: adminpages/discountcodes.php:352 adminpages/discountcodes.php:353
877
- #: adminpages/discountcodes.php:354 adminpages/discountcodes.php:359
878
- #: adminpages/discountcodes.php:424 adminpages/discountcodes.php:465
879
msgid "Start Date"
880
msgstr ""
881
882
#: adminpages/discountcodes.php:483
883
#: classes/gateways/class.pmprogateway_braintree.php:459
884
- #: classes/gateways/class.pmprogateway_stripe.php:630 pages/billing.php:317
885
#: pages/checkout.php:463 adminpages/discountcodes.php:367
886
#: adminpages/discountcodes.php:370 adminpages/discountcodes.php:371
887
#: adminpages/discountcodes.php:372 adminpages/discountcodes.php:377
@@ -908,7 +913,8 @@ msgstr ""
908
#: classes/gateways/class.pmprogateway_stripe.php:570
909
#: classes/gateways/class.pmprogateway_stripe.php:597
910
#: classes/gateways/class.pmprogateway_stripe.php:613
911
- #: classes/gateways/class.pmprogateway_stripe.php:629 pages/billing.php:249
912
#: pages/billing.php:253 pages/billing.php:262 pages/billing.php:265
913
#: pages/billing.php:268 pages/billing.php:310 pages/billing.php:316
914
#: pages/billing.php:317 pages/billing.php:319 pages/billing.php:342
@@ -1007,7 +1013,7 @@ msgstr ""
1007
1008
#: adminpages/discountcodes.php:587 adminpages/discountcodes.php:641
1009
#: adminpages/membershiplevels.php:410 adminpages/membershiplevels.php:511
1010
- #: classes/gateways/class.pmprogateway_stripe.php:688
1011
#: adminpages/discountcodes.php:446 adminpages/discountcodes.php:466
1012
#: adminpages/discountcodes.php:467 adminpages/discountcodes.php:468
1013
#: adminpages/discountcodes.php:473 adminpages/discountcodes.php:492
@@ -1036,12 +1042,13 @@ msgstr ""
1036
#: classes/gateways/class.pmprogateway_stripe.php:664
1037
#: classes/gateways/class.pmprogateway_stripe.php:671
1038
#: classes/gateways/class.pmprogateway_stripe.php:687
1039
msgid "Day(s)"
1040
msgstr ""
1041
1042
#: adminpages/discountcodes.php:587 adminpages/discountcodes.php:641
1043
#: adminpages/membershiplevels.php:410 adminpages/membershiplevels.php:511
1044
- #: classes/gateways/class.pmprogateway_stripe.php:688
1045
#: adminpages/discountcodes.php:446 adminpages/discountcodes.php:466
1046
#: adminpages/discountcodes.php:467 adminpages/discountcodes.php:468
1047
#: adminpages/discountcodes.php:473 adminpages/discountcodes.php:492
@@ -1070,12 +1077,13 @@ msgstr ""
1070
#: classes/gateways/class.pmprogateway_stripe.php:664
1071
#: classes/gateways/class.pmprogateway_stripe.php:671
1072
#: classes/gateways/class.pmprogateway_stripe.php:687
1073
msgid "Month(s)"
1074
msgstr ""
1075
1076
#: adminpages/discountcodes.php:587 adminpages/discountcodes.php:641
1077
#: adminpages/membershiplevels.php:410 adminpages/membershiplevels.php:511
1078
- #: classes/gateways/class.pmprogateway_stripe.php:688
1079
#: adminpages/discountcodes.php:446 adminpages/discountcodes.php:466
1080
#: adminpages/discountcodes.php:467 adminpages/discountcodes.php:468
1081
#: adminpages/discountcodes.php:473 adminpages/discountcodes.php:492
@@ -1104,12 +1112,13 @@ msgstr ""
1104
#: classes/gateways/class.pmprogateway_stripe.php:664
1105
#: classes/gateways/class.pmprogateway_stripe.php:671
1106
#: classes/gateways/class.pmprogateway_stripe.php:687
1107
msgid "Week(s)"
1108
msgstr ""
1109
1110
#: adminpages/discountcodes.php:587 adminpages/discountcodes.php:641
1111
#: adminpages/membershiplevels.php:410 adminpages/membershiplevels.php:511
1112
- #: classes/gateways/class.pmprogateway_stripe.php:688
1113
#: adminpages/discountcodes.php:446 adminpages/discountcodes.php:466
1114
#: adminpages/discountcodes.php:467 adminpages/discountcodes.php:468
1115
#: adminpages/discountcodes.php:473 adminpages/discountcodes.php:492
@@ -1138,6 +1147,7 @@ msgstr ""
1138
#: classes/gateways/class.pmprogateway_stripe.php:664
1139
#: classes/gateways/class.pmprogateway_stripe.php:671
1140
#: classes/gateways/class.pmprogateway_stripe.php:687
1141
msgid "Year(s)"
1142
msgstr ""
1143
@@ -1375,7 +1385,7 @@ msgid ""
1375
msgstr ""
1376
1377
#: adminpages/discountcodes.php:789 adminpages/membershiplevels.php:696
1378
- #: adminpages/orders.php:1245 adminpages/discountcodes.php:614
1379
#: adminpages/discountcodes.php:619 adminpages/discountcodes.php:647
1380
#: adminpages/discountcodes.php:648 adminpages/discountcodes.php:649
1381
#: adminpages/discountcodes.php:650 adminpages/discountcodes.php:655
@@ -1408,7 +1418,7 @@ msgid ""
1408
msgstr ""
1409
1410
#: adminpages/discountcodes.php:792 adminpages/membershiplevels.php:696
1411
- #: adminpages/orders.php:1251 adminpages/discountcodes.php:617
1412
#: adminpages/discountcodes.php:622 adminpages/discountcodes.php:650
1413
#: adminpages/discountcodes.php:651 adminpages/discountcodes.php:652
1414
#: adminpages/discountcodes.php:653 adminpages/discountcodes.php:658
@@ -1657,7 +1667,7 @@ msgid "Billing Details"
1657
msgstr ""
1658
1659
#: adminpages/membershiplevels.php:406
1660
- #: classes/gateways/class.pmprogateway_stripe.php:786
1661
#: adminpages/membershiplevels.php:349 adminpages/membershiplevels.php:351
1662
#: adminpages/membershiplevels.php:370 adminpages/membershiplevels.php:372
1663
#: adminpages/membershiplevels.php:373 adminpages/membershiplevels.php:396
@@ -1676,6 +1686,7 @@ msgstr ""
1676
#: classes/gateways/class.pmprogateway_stripe.php:762
1677
#: classes/gateways/class.pmprogateway_stripe.php:769
1678
#: classes/gateways/class.pmprogateway_stripe.php:785
1679
msgid "per"
1680
msgstr ""
1681
@@ -1835,8 +1846,8 @@ msgstr ""
1835
msgid "Save Level"
1836
msgstr ""
1837
1838
- #: adminpages/membershiplevels.php:540 adminpages/orders.php:807
1839
- #: pages/billing.php:365 pages/cancel.php:84 shortcodes/pmpro_account.php:72
1840
#: adminpages/membershiplevels.php:506 adminpages/membershiplevels.php:508
1841
#: adminpages/membershiplevels.php:517 adminpages/membershiplevels.php:518
1842
#: adminpages/membershiplevels.php:530 adminpages/membershiplevels.php:540
@@ -1947,7 +1958,7 @@ msgid ""
1947
"be cancelled."
1948
msgstr ""
1949
1950
- #: adminpages/membershiplevels.php:696 adminpages/orders.php:1248
1951
#: adminpages/membershiplevels.php:565 adminpages/membershiplevels.php:571
1952
#: adminpages/membershiplevels.php:573 adminpages/membershiplevels.php:580
1953
#: adminpages/membershiplevels.php:600 adminpages/membershiplevels.php:660
@@ -1972,7 +1983,7 @@ msgstr ""
1972
msgid "Members List"
1973
msgstr ""
1974
1975
- #: adminpages/memberslist.php:26 adminpages/orders.php:875
1976
#: adminpages/memberslist.php:26 adminpages/orders.php:522
1977
#: adminpages/orders.php:591 adminpages/orders.php:698
1978
#: adminpages/orders.php:727 adminpages/orders.php:833
@@ -1980,7 +1991,7 @@ msgstr ""
1980
msgid "Export to CSV"
1981
msgstr ""
1982
1983
- #: adminpages/memberslist.php:30 adminpages/orders.php:890
1984
#: adminpages/reports/login.php:87 adminpages/reports/memberships.php:328
1985
#: adminpages/reports/sales.php:203 adminpages/memberslist.php:30
1986
#: adminpages/orders.php:603 adminpages/orders.php:710
@@ -2013,7 +2024,8 @@ msgstr ""
2013
#: adminpages/reports/sales.php:216 adminpages/reports/sales.php:217
2014
#: adminpages/reports/sales.php:225 adminpages/reports/sales.php:226
2015
#: classes/class.pmproemail.php:145 classes/class.pmproemail.php:147
2016
- #: classes/class.pmproemail.php:189 classes/class.pmproemail.php:192
2017
msgid "All Levels"
2018
msgstr ""
2019
@@ -2069,7 +2081,7 @@ msgstr ""
2069
msgid "Last&nbsp;Name"
2070
msgstr ""
2071
2072
- #: adminpages/memberslist.php:170 pages/billing.php:104 pages/checkout.php:275
2073
#: pages/confirmation.php:66 pages/invoice.php:48
2074
#: adminpages/memberslist.php:117 adminpages/memberslist.php:150
2075
#: adminpages/memberslist.php:160 adminpages/memberslist.php:170
@@ -2163,181 +2175,187 @@ msgstr ""
2163
msgid "Error deleting order."
2164
msgstr ""
2165
2166
- #: adminpages/orders.php:295 adminpages/orders.php:119
2167
#: adminpages/orders.php:169 adminpages/orders.php:270
2168
#: adminpages/orders.php:284 adminpages/orders.php:285
2169
#: adminpages/orders.php:295
2170
msgid "Order saved successfully."
2171
msgstr ""
2172
2173
- #: adminpages/orders.php:298 adminpages/orders.php:124
2174
#: adminpages/orders.php:174 adminpages/orders.php:275
2175
#: adminpages/orders.php:287 adminpages/orders.php:288
2176
#: adminpages/orders.php:298
2177
msgid "Error updating order timestamp."
2178
msgstr ""
2179
2180
- #: adminpages/orders.php:302 adminpages/orders.php:130
2181
#: adminpages/orders.php:180 adminpages/orders.php:281
2182
#: adminpages/orders.php:291 adminpages/orders.php:292
2183
#: adminpages/orders.php:302
2184
msgid "Error saving order."
2185
msgstr ""
2186
2187
- #: adminpages/orders.php:362 classes/class.memberorder.php:743
2188
#: adminpages/orders.php:195 adminpages/orders.php:245
2189
#: adminpages/orders.php:317 adminpages/orders.php:321
2190
#: adminpages/orders.php:346 adminpages/orders.php:352
2191
- #: adminpages/orders.php:362 classes/class.memberorder.php:746
2192
msgid "Order"
2193
msgstr ""
2194
2195
- #: adminpages/orders.php:364 adminpages/orders.php:197
2196
#: adminpages/orders.php:247 adminpages/orders.php:319
2197
#: adminpages/orders.php:323 adminpages/orders.php:348
2198
#: adminpages/orders.php:354 adminpages/orders.php:364
2199
msgid "New Order"
2200
msgstr ""
2201
2202
- #: adminpages/orders.php:401 adminpages/orders.php:220
2203
#: adminpages/orders.php:270 adminpages/orders.php:342
2204
#: adminpages/orders.php:359 adminpages/orders.php:371
2205
#: adminpages/orders.php:390 adminpages/orders.php:401
2206
msgid "Randomly generated for you."
2207
msgstr ""
2208
2209
- #: adminpages/orders.php:406 adminpages/orders.php:225
2210
#: adminpages/orders.php:275 adminpages/orders.php:347
2211
#: adminpages/orders.php:364 adminpages/orders.php:376
2212
#: adminpages/orders.php:395 adminpages/orders.php:406
2213
msgid "User ID"
2214
msgstr ""
2215
2216
- #: adminpages/orders.php:418 adminpages/orders.php:234
2217
#: adminpages/orders.php:284 adminpages/orders.php:356
2218
#: adminpages/orders.php:376 adminpages/orders.php:385
2219
#: adminpages/orders.php:407 adminpages/orders.php:418
2220
msgid "Membership Level ID"
2221
msgstr ""
2222
2223
- #: adminpages/orders.php:431 adminpages/orders.php:243
2224
#: adminpages/orders.php:293 adminpages/orders.php:365
2225
#: adminpages/orders.php:389 adminpages/orders.php:394
2226
#: adminpages/orders.php:420 adminpages/orders.php:431
2227
msgid "Billing Name"
2228
msgstr ""
2229
2230
- #: adminpages/orders.php:443 adminpages/orders.php:251
2231
#: adminpages/orders.php:301 adminpages/orders.php:373
2232
#: adminpages/orders.php:401 adminpages/orders.php:402
2233
#: adminpages/orders.php:432 adminpages/orders.php:443
2234
msgid "Billing Street"
2235
msgstr ""
2236
2237
- #: adminpages/orders.php:454 adminpages/orders.php:258
2238
- #: adminpages/orders.php:308 adminpages/orders.php:380
2239
- #: adminpages/orders.php:409 adminpages/orders.php:412
2240
- #: adminpages/orders.php:443 adminpages/orders.php:454
2241
msgid "Billing City"
2242
msgstr ""
2243
2244
- #: adminpages/orders.php:465 adminpages/orders.php:265
2245
#: adminpages/orders.php:315 adminpages/orders.php:387
2246
#: adminpages/orders.php:416 adminpages/orders.php:423
2247
#: adminpages/orders.php:454 adminpages/orders.php:465
2248
msgid "Billing State"
2249
msgstr ""
2250
2251
- #: adminpages/orders.php:476 adminpages/orders.php:272
2252
- #: adminpages/orders.php:322 adminpages/orders.php:394
2253
- #: adminpages/orders.php:423 adminpages/orders.php:434
2254
- #: adminpages/orders.php:465 adminpages/orders.php:476
2255
msgid "Billing Postal Code"
2256
msgstr ""
2257
2258
- #: adminpages/orders.php:487 adminpages/orders.php:279
2259
- #: adminpages/orders.php:329 adminpages/orders.php:401
2260
- #: adminpages/orders.php:430 adminpages/orders.php:445
2261
- #: adminpages/orders.php:476 adminpages/orders.php:487
2262
msgid "Billing Country"
2263
msgstr ""
2264
2265
- #: adminpages/orders.php:499 adminpages/orders.php:287
2266
#: adminpages/orders.php:337 adminpages/orders.php:409
2267
#: adminpages/orders.php:438 adminpages/orders.php:457
2268
#: adminpages/orders.php:488 adminpages/orders.php:499
2269
msgid "Billing Phone"
2270
msgstr ""
2271
2272
- #: adminpages/orders.php:512 adminpages/orders.php:296
2273
#: adminpages/orders.php:346 adminpages/orders.php:418
2274
#: adminpages/orders.php:447 adminpages/orders.php:470
2275
#: adminpages/orders.php:501 adminpages/orders.php:512
2276
msgid "Sub Total"
2277
msgstr ""
2278
2279
- #: adminpages/orders.php:523 adminpages/templates/orders-email.php:60
2280
- #: adminpages/templates/orders-print.php:89 pages/confirmation.php:92
2281
- #: pages/invoice.php:74 adminpages/orders.php:304 adminpages/orders.php:354
2282
- #: adminpages/orders.php:426 adminpages/orders.php:455
2283
- #: adminpages/orders.php:481 adminpages/orders.php:512
2284
- #: adminpages/orders.php:523 adminpages/templates/orders-email.php:60
2285
#: adminpages/templates/orders-print.php:89 pages/confirmation.php:92
2286
#: pages/invoice.php:74 pages/invoice.php:78 pages/invoice.php:80
2287
msgid "Tax"
2288
msgstr ""
2289
2290
- #: adminpages/orders.php:534 adminpages/orders.php:312
2291
#: adminpages/orders.php:362 adminpages/orders.php:434
2292
#: adminpages/orders.php:463 adminpages/orders.php:492
2293
#: adminpages/orders.php:523 adminpages/orders.php:534
2294
msgid "Coupon Amount"
2295
msgstr ""
2296
2297
- #: adminpages/orders.php:546 adminpages/orders.php:1145
2298
#: adminpages/templates/orders-email.php:64
2299
- #: adminpages/templates/orders-print.php:93 pages/confirmation.php:96
2300
- #: pages/invoice.php:78 adminpages/orders.php:320 adminpages/orders.php:370
2301
- #: adminpages/orders.php:442 adminpages/orders.php:471
2302
- #: adminpages/orders.php:504 adminpages/orders.php:535
2303
- #: adminpages/orders.php:546 adminpages/orders.php:602
2304
- #: adminpages/orders.php:905 adminpages/orders.php:915
2305
- #: adminpages/orders.php:942 adminpages/orders.php:971
2306
- #: adminpages/orders.php:1108 adminpages/orders.php:1139
2307
- #: adminpages/orders.php:1145 adminpages/templates/orders-email.php:64
2308
#: adminpages/templates/orders-print.php:93 pages/confirmation.php:96
2309
#: pages/invoice.php:78 pages/invoice.php:82 pages/invoice.php:84
2310
msgid "Total"
2311
msgstr ""
2312
2313
- #: adminpages/orders.php:555 adminpages/orders.php:325
2314
#: adminpages/orders.php:375 adminpages/orders.php:447
2315
#: adminpages/orders.php:476 adminpages/orders.php:513
2316
#: adminpages/orders.php:544 adminpages/orders.php:555
2317
msgid "Should be subtotal + tax - couponamount."
2318
msgstr ""
2319
2320
- #: adminpages/orders.php:560 adminpages/orders.php:330
2321
#: adminpages/orders.php:380 adminpages/orders.php:452
2322
#: adminpages/orders.php:481 adminpages/orders.php:518
2323
#: adminpages/orders.php:549 adminpages/orders.php:560
2324
msgid "Payment Type"
2325
msgstr ""
2326
2327
- #: adminpages/orders.php:570 adminpages/orders.php:335
2328
#: adminpages/orders.php:385 adminpages/orders.php:457
2329
#: adminpages/orders.php:486 adminpages/orders.php:528
2330
#: adminpages/orders.php:559 adminpages/orders.php:570
2331
msgid "e.g. PayPal Express, PayPal Standard, Credit Card."
2332
msgstr ""
2333
2334
- #: adminpages/orders.php:574
2335
#: classes/gateways/class.pmprogateway_braintree.php:446
2336
- #: classes/gateways/class.pmprogateway_stripe.php:590 pages/billing.php:275
2337
- #: pages/checkout.php:423 adminpages/orders.php:339 adminpages/orders.php:389
2338
- #: adminpages/orders.php:461 adminpages/orders.php:490
2339
- #: adminpages/orders.php:532 adminpages/orders.php:563
2340
- #: adminpages/orders.php:574
2341
#: classes/gateways/class.pmprogateway_braintree.php:291
2342
#: classes/gateways/class.pmprogateway_braintree.php:304
2343
#: classes/gateways/class.pmprogateway_braintree.php:306
@@ -2361,7 +2379,8 @@ msgstr ""
2361
#: classes/gateways/class.pmprogateway_stripe.php:522
2362
#: classes/gateways/class.pmprogateway_stripe.php:549
2363
#: classes/gateways/class.pmprogateway_stripe.php:573
2364
- #: classes/gateways/class.pmprogateway_stripe.php:589 pages/billing.php:234
2365
#: pages/billing.php:238 pages/billing.php:247 pages/billing.php:250
2366
#: pages/billing.php:253 pages/billing.php:262 pages/billing.php:268
2367
#: pages/billing.php:271 pages/billing.php:274 pages/billing.php:275
@@ -2372,16 +2391,16 @@ msgstr ""
2372
msgid "Card Type"
2373
msgstr ""
2374
2375
- #: adminpages/orders.php:582 adminpages/orders.php:344
2376
#: adminpages/orders.php:394 adminpages/orders.php:466
2377
#: adminpages/orders.php:495 adminpages/orders.php:540
2378
#: adminpages/orders.php:571 adminpages/orders.php:582
2379
msgid "e.g. Visa, MasterCard, AMEX, etc"
2380
msgstr ""
2381
2382
- #: adminpages/orders.php:586
2383
#: classes/gateways/class.pmprogateway_twocheckout.php:137
2384
- #: adminpages/orders.php:348 adminpages/orders.php:398
2385
#: adminpages/orders.php:470 adminpages/orders.php:499
2386
#: adminpages/orders.php:544 adminpages/orders.php:575
2387
#: adminpages/orders.php:586 adminpages/paymentsettings.php:347
@@ -2392,54 +2411,55 @@ msgstr ""
2392
msgid "Account Number"
2393
msgstr ""
2394
2395
- #: adminpages/orders.php:595 adminpages/orders.php:353
2396
#: adminpages/orders.php:403 adminpages/orders.php:475
2397
#: adminpages/orders.php:504 adminpages/orders.php:553
2398
#: adminpages/orders.php:584 adminpages/orders.php:595
2399
msgid "Obscure all but last 4 digits."
2400
msgstr ""
2401
2402
- #: adminpages/orders.php:603 adminpages/orders.php:358
2403
#: adminpages/orders.php:408 adminpages/orders.php:480
2404
#: adminpages/orders.php:509 adminpages/orders.php:561
2405
#: adminpages/orders.php:592 adminpages/orders.php:603
2406
msgid "Expiration Month"
2407
msgstr ""
2408
2409
- #: adminpages/orders.php:611 adminpages/orders.php:365
2410
#: adminpages/orders.php:415 adminpages/orders.php:487
2411
#: adminpages/orders.php:516 adminpages/orders.php:569
2412
#: adminpages/orders.php:600 adminpages/orders.php:611
2413
msgid "Expiration Year"
2414
msgstr ""
2415
2416
- #: adminpages/orders.php:621 adminpages/orders.php:1149
2417
- #: adminpages/orders.php:373 adminpages/orders.php:423
2418
- #: adminpages/orders.php:495 adminpages/orders.php:524
2419
- #: adminpages/orders.php:579 adminpages/orders.php:606
2420
- #: adminpages/orders.php:610 adminpages/orders.php:621
2421
- #: adminpages/orders.php:909 adminpages/orders.php:919
2422
- #: adminpages/orders.php:946 adminpages/orders.php:975
2423
- #: adminpages/orders.php:1112 adminpages/orders.php:1143
2424
- #: adminpages/orders.php:1149
2425
msgid "Status"
2426
msgstr ""
2427
2428
- #: adminpages/orders.php:654 adminpages/orders.php:1147
2429
- #: classes/class.memberorder.php:744 adminpages/orders.php:394
2430
- #: adminpages/orders.php:444 adminpages/orders.php:516
2431
- #: adminpages/orders.php:545 adminpages/orders.php:604
2432
- #: adminpages/orders.php:612 adminpages/orders.php:643
2433
- #: adminpages/orders.php:654 adminpages/orders.php:907
2434
- #: adminpages/orders.php:917 adminpages/orders.php:944
2435
- #: adminpages/orders.php:973 adminpages/orders.php:1110
2436
- #: adminpages/orders.php:1141 adminpages/orders.php:1147
2437
#: classes/class.memberorder.php:747
2438
msgid "Gateway"
2439
msgstr ""
2440
2441
- #: adminpages/orders.php:675 adminpages/paymentsettings.php:141
2442
- #: adminpages/orders.php:411 adminpages/orders.php:461
2443
#: adminpages/orders.php:462 adminpages/orders.php:534
2444
#: adminpages/orders.php:563 adminpages/orders.php:633
2445
#: adminpages/orders.php:664 adminpages/orders.php:675
@@ -2449,7 +2469,7 @@ msgstr ""
2449
msgid "Gateway Environment"
2450
msgstr ""
2451
2452
- #: adminpages/orders.php:682 adminpages/paymentsettings.php:145
2453
#: adminpages/orders.php:415 adminpages/orders.php:465
2454
#: adminpages/orders.php:466 adminpages/orders.php:538
2455
#: adminpages/orders.php:567 adminpages/orders.php:640
@@ -2460,7 +2480,7 @@ msgstr ""
2460
msgid "Sandbox/Testing"
2461
msgstr ""
2462
2463
- #: adminpages/orders.php:684 adminpages/paymentsettings.php:146
2464
#: adminpages/orders.php:416 adminpages/orders.php:466
2465
#: adminpages/orders.php:467 adminpages/orders.php:539
2466
#: adminpages/orders.php:568 adminpages/orders.php:642
@@ -2471,7 +2491,7 @@ msgstr ""
2471
msgid "Live/Production"
2472
msgstr ""
2473
2474
- #: adminpages/orders.php:692 adminpages/orders.php:423
2475
#: adminpages/orders.php:473 adminpages/orders.php:474
2476
#: adminpages/orders.php:546 adminpages/orders.php:575
2477
#: adminpages/orders.php:650 adminpages/orders.php:681
@@ -2479,7 +2499,7 @@ msgstr ""
2479
msgid "Payment Transaction ID"
2480
msgstr ""
2481
2482
- #: adminpages/orders.php:701 adminpages/orders.php:428
2483
#: adminpages/orders.php:478 adminpages/orders.php:479
2484
#: adminpages/orders.php:551 adminpages/orders.php:580
2485
#: adminpages/orders.php:659 adminpages/orders.php:690
@@ -2487,16 +2507,16 @@ msgstr ""
2487
msgid "Generated by the gateway. Useful to cross reference orders."
2488
msgstr ""
2489
2490
- #: adminpages/orders.php:706 classes/class.memberorder.php:745
2491
- #: adminpages/orders.php:432 adminpages/orders.php:482
2492
#: adminpages/orders.php:483 adminpages/orders.php:555
2493
#: adminpages/orders.php:584 adminpages/orders.php:664
2494
#: adminpages/orders.php:695 adminpages/orders.php:706
2495
- #: classes/class.memberorder.php:748
2496
msgid "Subscription Transaction ID"
2497
msgstr ""
2498
2499
- #: adminpages/orders.php:716 adminpages/orders.php:437
2500
#: adminpages/orders.php:487 adminpages/orders.php:488
2501
#: adminpages/orders.php:560 adminpages/orders.php:589
2502
#: adminpages/orders.php:674 adminpages/orders.php:705
@@ -2504,7 +2524,7 @@ msgstr ""
2504
msgid "Generated by the gateway. Useful to cross reference subscriptions."
2505
msgstr ""
2506
2507
- #: adminpages/orders.php:721 adminpages/orders.php:1150 pages/invoice.php:100
2508
#: shortcodes/pmpro_account.php:127 adminpages/orders.php:442
2509
#: adminpages/orders.php:492 adminpages/orders.php:493
2510
#: adminpages/orders.php:565 adminpages/orders.php:594
@@ -2520,53 +2540,57 @@ msgstr ""
2520
msgid "Date"
2521
msgstr ""
2522
2523
- #: adminpages/orders.php:758 adminpages/orders.php:477
2524
#: adminpages/orders.php:527 adminpages/orders.php:599
2525
#: adminpages/orders.php:628 adminpages/orders.php:716
2526
#: adminpages/orders.php:747 adminpages/orders.php:758
2527
msgid "Affiliate ID"
2528
msgstr ""
2529
2530
- #: adminpages/orders.php:770 adminpages/orders.php:485
2531
#: adminpages/orders.php:535 adminpages/orders.php:607
2532
#: adminpages/orders.php:636 adminpages/orders.php:728
2533
#: adminpages/orders.php:759 adminpages/orders.php:770
2534
msgid "Affiliate SubID"
2535
msgstr ""
2536
2537
- #: adminpages/orders.php:784 adminpages/orders.php:495
2538
#: adminpages/orders.php:545 adminpages/orders.php:617
2539
#: adminpages/orders.php:646 adminpages/orders.php:742
2540
#: adminpages/orders.php:773 adminpages/orders.php:784
2541
msgid "Notes"
2542
msgstr ""
2543
2544
- #: adminpages/orders.php:806 adminpages/orders.php:510
2545
#: adminpages/orders.php:560 adminpages/orders.php:632
2546
#: adminpages/orders.php:661 adminpages/orders.php:764
2547
#: adminpages/orders.php:795 adminpages/orders.php:806
2548
msgid "Save Order"
2549
msgstr ""
2550
2551
- #: adminpages/orders.php:842 adminpages/orders.php:667
2552
#: adminpages/orders.php:696 adminpages/orders.php:800
2553
#: adminpages/orders.php:831 adminpages/orders.php:842
2554
msgid "Email Invoice"
2555
msgstr ""
2556
2557
- #: adminpages/orders.php:845 adminpages/orders.php:670
2558
#: adminpages/orders.php:699 adminpages/orders.php:803
2559
#: adminpages/orders.php:834 adminpages/orders.php:845
2560
msgid "Send an invoice for this order to: "
2561
msgstr ""
2562
2563
- #: adminpages/orders.php:847 adminpages/orders.php:672
2564
#: adminpages/orders.php:701 adminpages/orders.php:805
2565
#: adminpages/orders.php:836 adminpages/orders.php:847
2566
msgid "Send Email"
2567
msgstr ""
2568
2569
- #: adminpages/orders.php:852 includes/adminpages.php:56
2570
#: includes/adminpages.php:172 adminpages/orders.php:520
2571
#: adminpages/orders.php:570 adminpages/orders.php:677
2572
#: adminpages/orders.php:706 adminpages/orders.php:810
@@ -2578,70 +2602,70 @@ msgstr ""
2578
msgid "Orders"
2579
msgstr ""
2580
2581
- #: adminpages/orders.php:854 adminpages/orders.php:521
2582
#: adminpages/orders.php:571 adminpages/orders.php:678
2583
#: adminpages/orders.php:707 adminpages/orders.php:812
2584
#: adminpages/orders.php:843 adminpages/orders.php:854
2585
msgid "Add New Order"
2586
msgstr ""
2587
2588
- #: adminpages/orders.php:894 adminpages/orders.php:606
2589
#: adminpages/orders.php:713 adminpages/orders.php:742
2590
#: adminpages/orders.php:852 adminpages/orders.php:883
2591
#: adminpages/orders.php:894
2592
msgid "Within a Date Range"
2593
msgstr ""
2594
2595
- #: adminpages/orders.php:896 adminpages/orders.php:607
2596
#: adminpages/orders.php:714 adminpages/orders.php:743
2597
#: adminpages/orders.php:854 adminpages/orders.php:885
2598
#: adminpages/orders.php:896
2599
msgid "Predefined Date Range"
2600
msgstr ""
2601
2602
- #: adminpages/orders.php:898 adminpages/orders.php:608
2603
#: adminpages/orders.php:715 adminpages/orders.php:744
2604
#: adminpages/orders.php:856 adminpages/orders.php:887
2605
#: adminpages/orders.php:898
2606
msgid "Within a Level"
2607
msgstr ""
2608
2609
- #: adminpages/orders.php:900 adminpages/orders.php:609
2610
#: adminpages/orders.php:716 adminpages/orders.php:745
2611
#: adminpages/orders.php:858 adminpages/orders.php:889
2612
#: adminpages/orders.php:900
2613
msgid "Within a Status"
2614
msgstr ""
2615
2616
- #: adminpages/orders.php:903 adminpages/orders.php:612
2617
#: adminpages/orders.php:719 adminpages/orders.php:748
2618
#: adminpages/orders.php:861 adminpages/orders.php:892
2619
#: adminpages/orders.php:903
2620
msgid "From"
2621
msgstr ""
2622
2623
- #: adminpages/orders.php:918 adminpages/orders.php:624
2624
#: adminpages/orders.php:731 adminpages/orders.php:760
2625
#: adminpages/orders.php:876 adminpages/orders.php:907
2626
#: adminpages/orders.php:918
2627
msgid "To"
2628
msgstr ""
2629
2630
- #: adminpages/orders.php:931 adminpages/orders.php:636
2631
#: adminpages/orders.php:743 adminpages/orders.php:772
2632
#: adminpages/orders.php:889 adminpages/orders.php:920
2633
#: adminpages/orders.php:931
2634
msgid "filter by "
2635
msgstr ""
2636
2637
- #: adminpages/orders.php:969 adminpages/orders.php:674
2638
#: adminpages/orders.php:780 adminpages/orders.php:809
2639
#: adminpages/orders.php:932 adminpages/orders.php:963
2640
#: adminpages/orders.php:969
2641
msgid "Filter"
2642
msgstr ""
2643
2644
- #: adminpages/orders.php:1066 adminpages/orders.php:1069
2645
#: adminpages/orders.php:535 adminpages/orders.php:538
2646
#: adminpages/orders.php:777 adminpages/orders.php:780
2647
#: adminpages/orders.php:883 adminpages/orders.php:886
@@ -2652,7 +2676,7 @@ msgstr ""
2652
msgid "Search Orders"
2653
msgstr ""
2654
2655
- #: adminpages/orders.php:1133 adminpages/orders.php:590
2656
#: adminpages/orders.php:893 adminpages/orders.php:903
2657
#: adminpages/orders.php:930 adminpages/orders.php:959
2658
#: adminpages/orders.php:1096 adminpages/orders.php:1127
@@ -2661,7 +2685,7 @@ msgstr ""
2661
msgid "%d orders found."
2662
msgstr ""
2663
2664
- #: adminpages/orders.php:1142 adminpages/reports/login.php:163
2665
#: classes/gateways/class.pmprogateway_payflowpro.php:116
2666
#: adminpages/orders.php:599 adminpages/orders.php:902
2667
#: adminpages/orders.php:912 adminpages/orders.php:939
@@ -2675,7 +2699,7 @@ msgstr ""
2675
msgid "User"
2676
msgstr ""
2677
2678
- #: adminpages/orders.php:1144 includes/init.php:244 includes/profile.php:36
2679
#: pages/checkout.php:34 pages/confirmation.php:53 pages/confirmation.php:124
2680
#: pages/invoice.php:28 adminpages/orders.php:601 adminpages/orders.php:904
2681
#: adminpages/orders.php:914 adminpages/orders.php:941
@@ -2697,7 +2721,7 @@ msgstr ""
2697
msgid "Membership Level"
2698
msgstr ""
2699
2700
- #: adminpages/orders.php:1146 adminpages/orders.php:1226
2701
#: adminpages/orders.php:603 adminpages/orders.php:651
2702
#: adminpages/orders.php:906 adminpages/orders.php:916
2703
#: adminpages/orders.php:943 adminpages/orders.php:954
@@ -2709,7 +2733,7 @@ msgstr ""
2709
msgid "Payment"
2710
msgstr ""
2711
2712
- #: adminpages/orders.php:1148 adminpages/orders.php:605
2713
#: adminpages/orders.php:908 adminpages/orders.php:918
2714
#: adminpages/orders.php:945 adminpages/orders.php:974
2715
#: adminpages/orders.php:1111 adminpages/orders.php:1142
@@ -2717,7 +2741,7 @@ msgstr ""
2717
msgid "Transaction IDs"
2718
msgstr ""
2719
2720
- #: adminpages/orders.php:1178 adminpages/orders.php:630
2721
#: adminpages/orders.php:933 adminpages/orders.php:943
2722
#: adminpages/orders.php:972 adminpages/orders.php:1001
2723
#: adminpages/orders.php:1141 adminpages/orders.php:1172
@@ -2725,7 +2749,11 @@ msgstr ""
2725
msgid "deleted"
2726
msgstr ""
2727
2728
- #: adminpages/orders.php:1232 adminpages/orders.php:653
2729
#: adminpages/orders.php:956 adminpages/orders.php:974
2730
#: adminpages/orders.php:984 adminpages/orders.php:1013
2731
#: adminpages/orders.php:1042 adminpages/orders.php:1192
@@ -2733,7 +2761,7 @@ msgstr ""
2733
msgid "Subscription"
2734
msgstr ""
2735
2736
- #: adminpages/orders.php:1251 adminpages/orders.php:664
2737
#: adminpages/orders.php:967 adminpages/orders.php:985
2738
#: adminpages/orders.php:995 adminpages/orders.php:998
2739
#: adminpages/orders.php:1027 adminpages/orders.php:1056
@@ -2745,19 +2773,19 @@ msgid ""
2745
"want to delete order %s?"
2746
msgstr ""
2747
2748
- #: adminpages/orders.php:1255 adminpages/orders.php:1030
2749
#: adminpages/orders.php:1059 adminpages/orders.php:1215
2750
#: adminpages/orders.php:1249 adminpages/orders.php:1255
2751
msgid "print"
2752
msgstr ""
2753
2754
- #: adminpages/orders.php:1259 adminpages/orders.php:1033
2755
#: adminpages/orders.php:1062 adminpages/orders.php:1219
2756
#: adminpages/orders.php:1253 adminpages/orders.php:1259
2757
msgid "email"
2758
msgstr ""
2759
2760
- #: adminpages/orders.php:1268 adminpages/orders.php:674
2761
#: adminpages/orders.php:977 adminpages/orders.php:995
2762
#: adminpages/orders.php:1005 adminpages/orders.php:1008
2763
#: adminpages/orders.php:1043 adminpages/orders.php:1072
@@ -3075,7 +3103,7 @@ msgstr ""
3075
msgid "Sales Tax"
3076
msgstr ""
3077
3078
- #: adminpages/paymentsettings.php:205 pages/billing.php:121
3079
#: adminpages/paymentsettings.php:188 adminpages/paymentsettings.php:205
3080
#: adminpages/paymentsettings.php:398 adminpages/paymentsettings.php:438
3081
#: adminpages/paymentsettings.php:443 adminpages/paymentsettings.php:445
@@ -3518,7 +3546,7 @@ msgid ""
3518
"site's plugin page."
3519
msgstr ""
3520
3521
- #: classes/class.memberorder.php:740 classes/class.memberorder.php:553
3522
#: classes/class.memberorder.php:561 classes/class.memberorder.php:564
3523
#: classes/class.memberorder.php:573 classes/class.memberorder.php:644
3524
#: classes/class.memberorder.php:697 classes/class.memberorder.php:699
@@ -3533,11 +3561,13 @@ msgid ""
3533
"active."
3534
msgstr ""
3535
3536
- #: classes/class.memberorder.php:741 classes/class.memberorder.php:744
3537
msgid "User Email"
3538
msgstr ""
3539
3540
- #: classes/class.memberorder.php:742 classes/class.memberorder.php:745
3541
msgid "User Display Name"
3542
msgstr ""
3543
@@ -3549,6 +3579,7 @@ msgstr ""
3549
#: classes/class.pmproemail.php:143 classes/class.pmproemail.php:120
3550
#: classes/class.pmproemail.php:122 classes/class.pmproemail.php:125
3551
#: classes/class.pmproemail.php:134 classes/class.pmproemail.php:136
3552
#, php-format
3553
msgid "Your membership at %s has been CANCELLED"
3554
msgstr ""
@@ -3556,7 +3587,7 @@ msgstr ""
3556
#: classes/class.pmproemail.php:176 classes/class.pmproemail.php:142
3557
#: classes/class.pmproemail.php:144 classes/class.pmproemail.php:147
3558
#: classes/class.pmproemail.php:156 classes/class.pmproemail.php:166
3559
- #: classes/class.pmproemail.php:169
3560
#, php-format
3561
msgid "Membership for %s at %s has been CANCELLED"
3562
msgstr ""
@@ -3565,6 +3596,7 @@ msgstr ""
3565
#: classes/class.pmproemail.php:173 classes/class.pmproemail.php:175
3566
#: classes/class.pmproemail.php:178 classes/class.pmproemail.php:187
3567
#: classes/class.pmproemail.php:207 classes/class.pmproemail.php:212
3568
#, php-format
3569
msgid "Your membership confirmation for %s"
3570
msgstr ""
@@ -3574,7 +3606,7 @@ msgstr ""
3574
#: classes/class.pmproemail.php:385 classes/class.pmproemail.php:703
3575
#: classes/class.pmproemail.php:705
3576
#: classes/gateways/class.pmprogateway_braintree.php:489
3577
- #: classes/gateways/class.pmprogateway_stripe.php:661 pages/checkout.php:70
3578
#: pages/checkout.php:76 pages/checkout.php:498 pages/confirmation.php:58
3579
#: pages/invoice.php:33 classes/class.pmproemail.php:216
3580
#: classes/class.pmproemail.php:218 classes/class.pmproemail.php:225
@@ -3584,18 +3616,22 @@ msgstr ""
3584
#: classes/class.pmproemail.php:240 classes/class.pmproemail.php:246
3585
#: classes/class.pmproemail.php:249 classes/class.pmproemail.php:258
3586
#: classes/class.pmproemail.php:260 classes/class.pmproemail.php:269
3587
- #: classes/class.pmproemail.php:278 classes/class.pmproemail.php:287
3588
- #: classes/class.pmproemail.php:304 classes/class.pmproemail.php:307
3589
- #: classes/class.pmproemail.php:313 classes/class.pmproemail.php:316
3590
- #: classes/class.pmproemail.php:325 classes/class.pmproemail.php:328
3591
- #: classes/class.pmproemail.php:334 classes/class.pmproemail.php:337
3592
- #: classes/class.pmproemail.php:346 classes/class.pmproemail.php:357
3593
- #: classes/class.pmproemail.php:366 classes/class.pmproemail.php:369
3594