Paid Memberships Pro - Version 2.0.2

Version Description

  • 2019-01-10 =
  • BUG FIX: Fixed issues when using non-US currencies. Using the pmpro_round_price function in a few places it was needed. Prepared for a later update that will increase the number of decimals on certain columns in the DB to 8 to support currencies like Bitcoin, but shelving the actual DB update for version 2.1.
  • BUG FIX: Fixed issue where existing users who checked out could run into problems. Added a getMembershipLevelAtCheckout method to the MemberOrder class and using that during checkout. The getMembershipLevel method would see the user_id property of the order (added to orders at checkout in version 2.0) and lookup the level data from the pmpro_memberships_users table instead of using the pmpro_level global. Then gateways like PayPal Express (but others also) would use the wrong data when making calls to pmpro_isLevelRecurring/etc.
  • BUG FIX: Fixed bug where a notice to deactivate the Better Logins Report plugin could show up for users who couldn't deactive the plugin.
  • BUG FIX: Fixed bad translation in the membership_expired.html file of the French translation.
  • BUG FIX: Fixed some strings on updated reports that weren't wrapped for translation.
Download this release

Release Info

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

Code changes from version 2.0.1 to 2.0.2

CHANGELOG.txt CHANGED
@@ -1,5 +1,15 @@
1
== Changelog ==
2
3
= 2.0 - 2018-12-31 =
4
* SECURITY: Fixing how we escape things in the Memberships report SQL queries.
5
* BUG FIX: Fixed issue where code in the Stripe gateway was cancelling old subscriptions early if users renewed with a different gateway.
1
== Changelog ==
2
3
+ = 2.0.2 - 2019-01-10 =
4
+ * BUG FIX: Fixed issues when using non-US currencies. Using the pmpro_round_price function in a few places it was needed. Prepared for a later update that will increase the number of decimals on certain columns in the DB to 8 to support currencies like Bitcoin, but shelving the actual DB update for version 2.1.
5
+ * BUG FIX: Fixed issue where existing users who checked out could run into problems. Added a getMembershipLevelAtCheckout method to the MemberOrder class and using that during checkout. The getMembershipLevel method would see the user_id property of the order (added to orders at checkout in version 2.0) and lookup the level data from the pmpro_memberships_users table instead of using the pmpro_level global. Then gateways like PayPal Express (but others also) would use the wrong data when making calls to pmpro_isLevelRecurring/etc.
6
+ * BUG FIX: Fixed bug where a notice to deactivate the Better Logins Report plugin could show up for users who couldn't deactive the plugin.
7
+ * BUG FIX: Fixed bad translation in the membership_expired.html file of the French translation.
8
+ * BUG FIX: Fixed some strings on updated reports that weren't wrapped for translation.
9
+
10
+ = 2.0.1 - 2019-01-03 =
11
+ * BUG FIX: Fixed issue where the PMPro dashboard and reports pages would appear blank if certain other plugins were active.
12
+
13
= 2.0 - 2018-12-31 =
14
* SECURITY: Fixing how we escape things in the Memberships report SQL queries.
15
* BUG FIX: Fixed issue where code in the Stripe gateway was cancelling old subscriptions early if users renewed with a different gateway.
adminpages/dashboard.php CHANGED
@@ -9,49 +9,49 @@
9
*/
10
add_meta_box(
11
'pmpro_dashboard_welcome',
12
- __( 'Welcome to Paid Memberships Pro' ),
13
'pmpro_dashboard_welcome_callback',
14
'toplevel_page_pmpro-dashboard',
15
'normal'
16
);
17
add_meta_box(
18
'pmpro_dashboard_report_sales',
19
- __( 'Sales and Revenue' ),
20
'pmpro_report_sales_widget',
21
'toplevel_page_pmpro-dashboard',
22
'advanced'
23
);
24
add_meta_box(
25
'pmpro_dashboard_report_membership_stats',
26
- __( 'Membership Stats' ),
27
'pmpro_report_memberships_widget',
28
'toplevel_page_pmpro-dashboard',
29
'advanced'
30
);
31
add_meta_box(
32
'pmpro_dashboard_report_logins',
33
- __( 'Visits, Views, and Logins' ),
34
'pmpro_report_login_widget',
35
'toplevel_page_pmpro-dashboard',
36
'advanced'
37
);
38
add_meta_box(
39
'pmpro_dashboard_report_recent_members',
40
- __( 'Recent Members' ),
41
'pmpro_dashboard_report_recent_members_callback',
42
'toplevel_page_pmpro-dashboard',
43
'side'
44
);
45
add_meta_box(
46
'pmpro_dashboard_report_recent_orders',
47
- __( 'Recent Orders' ),
48
'pmpro_dashboard_report_recent_orders_callback',
49
'toplevel_page_pmpro-dashboard',
50
'side'
51
);
52
add_meta_box(
53
'pmpro_dashboard_news_updates',
54
- __( 'Paid Memberships Pro News and Updates' ),
55
'pmpro_dashboard_news_updates_callback',
56
'toplevel_page_pmpro-dashboard',
57
'side'
9
*/
10
add_meta_box(
11
'pmpro_dashboard_welcome',
12
+ __( 'Welcome to Paid Memberships Pro', 'paid-memberships-pro' ),
13
'pmpro_dashboard_welcome_callback',
14
'toplevel_page_pmpro-dashboard',
15
'normal'
16
);
17
add_meta_box(
18
'pmpro_dashboard_report_sales',
19
+ __( 'Sales and Revenue', 'paid-memberships-pro' ),
20
'pmpro_report_sales_widget',
21
'toplevel_page_pmpro-dashboard',
22
'advanced'
23
);
24
add_meta_box(
25
'pmpro_dashboard_report_membership_stats',
26
+ __( 'Membership Stats', 'paid-memberships-pro' ),
27
'pmpro_report_memberships_widget',
28
'toplevel_page_pmpro-dashboard',
29
'advanced'
30
);
31
add_meta_box(
32
'pmpro_dashboard_report_logins',
33
+ __( 'Visits, Views, and Logins', 'paid-memberships-pro' ),
34
'pmpro_report_login_widget',
35
'toplevel_page_pmpro-dashboard',
36
'advanced'
37
);
38
add_meta_box(
39
'pmpro_dashboard_report_recent_members',
40
+ __( 'Recent Members', 'paid-memberships-pro' ),
41
'pmpro_dashboard_report_recent_members_callback',
42
'toplevel_page_pmpro-dashboard',
43
'side'
44
);
45
add_meta_box(
46
'pmpro_dashboard_report_recent_orders',
47
+ __( 'Recent Orders', 'paid-memberships-pro' ),
48
'pmpro_dashboard_report_recent_orders_callback',
49
'toplevel_page_pmpro-dashboard',
50
'side'
51
);
52
add_meta_box(
53
'pmpro_dashboard_news_updates',
54
+ __( 'Paid Memberships Pro News and Updates', 'paid-memberships-pro' ),
55
'pmpro_dashboard_news_updates_callback',
56
'toplevel_page_pmpro-dashboard',
57
'side'
adminpages/discountcodes.php CHANGED
@@ -574,7 +574,7 @@
574
if(pmpro_getCurrencyPosition() == "left")
575
echo $pmpro_currency_symbol;
576
?>
577
- <input name="initial_payment[]" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->initial_payment))?>" />
578
<?php
579
if(pmpro_getCurrencyPosition() == "right")
580
echo $pmpro_currency_symbol;
@@ -595,7 +595,7 @@
595
if(pmpro_getCurrencyPosition() == "left")
596
echo $pmpro_currency_symbol;
597
?>
598
- <input name="billing_amount[]" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->billing_amount))?>" />
599
<?php
600
if(pmpro_getCurrencyPosition() == "right")
601
echo $pmpro_currency_symbol;
@@ -636,7 +636,7 @@
636
if(pmpro_getCurrencyPosition() == "left")
637
echo $pmpro_currency_symbol;
638
?>
639
- <input name="trial_amount[]" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->trial_amount))?>" />
640
<?php
641
if(pmpro_getCurrencyPosition() == "right")
642
echo $pmpro_currency_symbol;
574
if(pmpro_getCurrencyPosition() == "left")
575
echo $pmpro_currency_symbol;
576
?>
577
+ <input name="initial_payment[]" type="text" size="20" value="<?php echo esc_attr( pmpro_filter_price_for_text_field( $level->initial_payment ) ); ?>" />
578
<?php
579
if(pmpro_getCurrencyPosition() == "right")
580
echo $pmpro_currency_symbol;
595
if(pmpro_getCurrencyPosition() == "left")
596
echo $pmpro_currency_symbol;
597
?>
598
+ <input name="billing_amount[]" type="text" size="20" value="<?php echo esc_attr( pmpro_filter_price_for_text_field( $level->billing_amount ) );?>" />
599
<?php
600
if(pmpro_getCurrencyPosition() == "right")
601
echo $pmpro_currency_symbol;
636
if(pmpro_getCurrencyPosition() == "left")
637
echo $pmpro_currency_symbol;
638
?>
639
+ <input name="trial_amount[]" type="text" size="20" value="<?php echo esc_attr( pmpro_filter_price_for_text_field( $level->trial_amount ) );?>" />
640
<?php
641
if(pmpro_getCurrencyPosition() == "right")
642
echo $pmpro_currency_symbol;
adminpages/membershiplevels.php CHANGED
@@ -1,773 +1,773 @@
1
- <?php
2
- //only admins can get this
3
- if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_membershiplevels")))
4
- {
5
- die(__("You do not have permissions to perform this action.", 'paid-memberships-pro' ));
6
- }
7
-
8
- global $wpdb, $msg, $msgt, $pmpro_currency_symbol, $allowedposttags;
9
-
10
- //some vars
11
- $gateway = pmpro_getOption("gateway");
12
- $pmpro_level_order = pmpro_getOption('level_order');
13
-
14
- global $pmpro_stripe_error, $pmpro_braintree_error, $pmpro_payflow_error, $pmpro_twocheckout_error, $wp_version;
15
-
16
- if(isset($_REQUEST['edit']))
17
- $edit = intval($_REQUEST['edit']);
18
- else
19
- $edit = false;
20
- if(isset($_REQUEST['copy']))
21
- $copy = intval($_REQUEST['copy']);
22
- if(isset($_REQUEST['s']))
23
- $s = sanitize_text_field($_REQUEST['s']);
24
- else
25
- $s = "";
26
-
27
- if(isset($_REQUEST['action']))
28
- $action = sanitize_text_field($_REQUEST['action']);
29
- else
30
- $action = false;
31
-
32
- if(isset($_REQUEST['saveandnext']))
33
- $saveandnext = intval($_REQUEST['saveandnext']);
34
-
35
- if(isset($_REQUEST['saveid']))
36
- $saveid = intval($_REQUEST['saveid']);
37
- if(isset($_REQUEST['deleteid']))
38
- $deleteid = intval($_REQUEST['deleteid']);
39
-
40
- //check nonce
41
- if(!empty($action) && (empty($_REQUEST['pmpro_membershiplevels_nonce']) || !check_admin_referer($action, 'pmpro_membershiplevels_nonce'))) {
42
- $msg = -1;
43
- $msgt = __("Are you sure you want to do that? Try again.", 'paid-memberships-pro' );
44
- $action = false;
45
- }
46
-
47
- if($action == "save_membershiplevel") {
48
-
49
- $ml_name = wp_kses(wp_unslash($_REQUEST['name']), $allowedposttags);
50
- $ml_description = wp_kses(wp_unslash($_REQUEST['description']), $allowedposttags);
51
- $ml_confirmation = wp_kses(wp_unslash($_REQUEST['confirmation']), $allowedposttags);
52
- if(!empty($_REQUEST['confirmation_in_email']))
53
- $ml_confirmation_in_email = 1;
54
- else
55
- $ml_confirmation_in_email = 0;
56
-
57
- $ml_initial_payment = sanitize_text_field($_REQUEST['initial_payment']);
58
- if(!empty($_REQUEST['recurring']))
59
- $ml_recurring = 1;
60
- else
61
- $ml_recurring = 0;
62
- $ml_billing_amount = sanitize_text_field($_REQUEST['billing_amount']);
63
- $ml_cycle_number = intval($_REQUEST['cycle_number']);
64
- $ml_cycle_period = sanitize_text_field($_REQUEST['cycle_period']);
65
- $ml_billing_limit = intval($_REQUEST['billing_limit']);
66
- if(!empty($_REQUEST['custom_trial']))
67
- $ml_custom_trial = 1;
68
- else
69
- $ml_custom_trial = 0;
70
- $ml_trial_amount = sanitize_text_field($_REQUEST['trial_amount']);
71
- $ml_trial_limit = intval($_REQUEST['trial_limit']);
72
- if(!empty($_REQUEST['expiration']))
73
- $ml_expiration = 1;
74
- else
75
- $ml_expiration = 0;
76
- $ml_expiration_number = intval($_REQUEST['expiration_number']);
77
- $ml_expiration_period = sanitize_text_field($_REQUEST['expiration_period']);
78
- $ml_categories = array();
79
-
80
- //reversing disable to allow here
81
- if(empty($_REQUEST['disable_signups']))
82
- $ml_allow_signups = 1;
83
- else
84
- $ml_allow_signups = 0;
85
-
86
- foreach ( $_REQUEST as $key => $value ) {
87
- if ( $value == 'yes' && preg_match( '/^membershipcategory_(\d+)#x2F;i', $key, $matches ) ) {
88
- $ml_categories[] = $matches[1];
89
- }
90
- }
91
-
92
- //clearing out values if checkboxes aren't checked
93
- if(empty($ml_recurring)) {
94
- $ml_billing_amount = $ml_cycle_number = $ml_cycle_period = $ml_billing_limit = $ml_trial_amount = $ml_trial_limit = 0;
95
- } elseif(empty($ml_custom_trial)) {
96
- $ml_trial_amount = $ml_trial_limit = 0;
97
- }
98
- if(empty($ml_expiration)) {
99
- $ml_expiration_number = $ml_expiration_period = 0;
100
- }
101
-
102
- $wpdb->replace(
103
- $wpdb->pmpro_membership_levels,
104
- array(
105
- 'id'=>max($saveid, 0),
106
- 'name' => $ml_name,
107
- 'description' => $ml_description,
108
- 'confirmation' => $ml_confirmation,
109
- 'initial_payment' => $ml_initial_payment,
110
- 'billing_amount' => $ml_billing_amount,
111
- 'cycle_number' => $ml_cycle_number,
112
- 'cycle_period' => $ml_cycle_period,
113
- 'billing_limit' => $ml_billing_limit,
114
- 'trial_amount' => $ml_trial_amount,
115
- 'trial_limit' => $ml_trial_limit,
116
- 'expiration_number' => $ml_expiration_number,
117
- 'expiration_period' => $ml_expiration_period,
118
- 'allow_signups' => $ml_allow_signups
119
- ),
120
- array(
121
- '%d', //id
122
- '%s', //name
123
- '%s', //description
124
- '%s', //confirmation
125
- '%f', //initial_payment
126
- '%f', //billing_amount
127
- '%d', //cycle_number
128
- '%s', //cycle_period
129
- '%d', //billing_limit
130
- '%f', //trial_amount
131
- '%d', //trial_limit
132
- '%d', //expiration_number
133
- '%s', //expiration_period
134
- '%d', //allow_signups
135
- )
136
- );
137
-
138
- if($saveid < 1) {
139
- //added a level
140
- $saveid = $wpdb->insert_id;
141
-
142
- pmpro_updateMembershipCategories( $saveid, $ml_categories );
143
-
144
- if(empty($wpdb->last_error)) {
145
- $saveid = $wpdb->insert_id;
146
- pmpro_updateMembershipCategories( $saveid, $ml_categories );
147
-
148
- $edit = false;
149
- $msg = 1;
150
- $msgt = __("Membership level added successfully.", 'paid-memberships-pro' );
151
- } else {
152
- $msg = -1;
153
- $msgt = __("Error adding membership level.", 'paid-memberships-pro' );
154
- }
155
- } else {
156
- pmpro_updateMembershipCategories( $saveid, $ml_categories );
157
-
158
- if(empty($wpdb->last_error)) {
159
- $edit = false;
160
- $msg = 2;
161
- $msgt = __("Membership level updated successfully.", 'paid-memberships-pro' );
162
- } else {
163
- $msg = -2;
164
- $msgt = __("Error updating membership level.", 'paid-memberships-pro' );
165
- }
166
- }
167
-
168
- if( ! empty( $msgt ) && $ml_recurring && $ml_expiration ) {
169
- $msgt .= ' <strong class="red">' . sprintf( __( 'WARNING: A level was set with both a recurring billing amount and an expiration date. You only need to set one of these unless you really want this membership to expire after a specific time period. For more information, <a target="_blank" href="%s">see our post here</a>.', 'paid-memberships-pro' ), 'https://www.paidmembershipspro.com/important-notes-on-recurring-billing-and-expiration-dates-for-membership-levels/' ) . '</strong>';
170
-
171
- // turn success to errors
172
- if( $msg > 0 ) {
173
- $msg = 0 - $msg;
174
- }
175
- }
176
-
177
- // Update the Level Meta to Add Confirmation Message to Email.
178
- if ( isset( $ml_confirmation_in_email ) ) {
179
- update_pmpro_membership_level_meta( $saveid, 'confirmation_in_email', $ml_confirmation_in_email );
180
- }
181
-
182
- do_action("pmpro_save_membership_level", $saveid);
183
- }
184
- elseif($action == "delete_membership_level")
185
- {
186
- global $wpdb;
187
-
188
- $ml_id = intval($_REQUEST['deleteid']);
189
-
190
- if($ml_id > 0) {
191
- do_action("pmpro_delete_membership_level", $ml_id);
192
-
193
- //remove any categories from the ml
194
- $sqlQuery = $wpdb->prepare("
195
- DELETE FROM $wpdb->pmpro_memberships_categories
196
- WHERE membership_id = %d",
197
- $ml_id
198
- );
199
-
200
- $r1 = $wpdb->query($sqlQuery);
201
-
202
- //cancel any subscriptions to the ml
203
- $r2 = true;
204
- $user_ids = $wpdb->get_col( $wpdb->prepare( "
205
- SELECT user_id FROM $wpdb->pmpro_memberships_users
206
- WHERE membership_id = %d
207
- AND status = 'active'",
208
- $ml_id
209
- ) );
210
-
211
- foreach($user_ids as $user_id) {
212
- //change there membership level to none. that will handle the cancel
213
- if(pmpro_changeMembershipLevel(0, $user_id)) {
214
- //okay
215
- } else {
216
- //couldn't delete the subscription
217
- //we should probably notify the admin
218
- $pmproemail = new PMProEmail();
219
- $pmproemail->data = array("body"=>"<p>" . sprintf(__("There was an error canceling the subscription for user with ID=%d. You will want to check your payment gateway to see if their subscription is still active.", 'paid-memberships-pro' ), $user_id) . "</p>");
220
- $last_order = $wpdb->get_row( $wpdb->prepare( "
221
- SELECT * FROM $wpdb->pmpro_membership_orders
222
- WHERE user_id = %d
223
- ORDER BY timestamp DESC LIMIT 1",
224
- $user_id
225
- ) );
226
- if($last_order)
227
- $pmproemail->data["body"] .= "<p>" . __("Last Invoice", 'paid-memberships-pro' ) . ":<br />" . nl2br(var_export($last_order, true)) . "</p>";
228
- $pmproemail->sendEmail(get_bloginfo("admin_email"));
229
-
230
- $r2 = false;
231
- }
232
- }
233
-
234
- //delete the ml
235
- $sqlQuery = $wpdb->prepare( "
236
- DELETE FROM $wpdb->pmpro_membership_levels
237
- WHERE id = %d LIMIT 1",
238
- $ml_id
239
- );
240
- $r3 = $wpdb->query($sqlQuery);
241
-
242
- if($r1 !== FALSE && $r2 !== FALSE && $r3 !== FALSE) {
243
- $msg = 3;
244
- $msgt = __("Membership level deleted successfully.", 'paid-memberships-pro' );
245
- } else {
246
- $msg = -3;
247
- $msgt = __("Error deleting membership level.", 'paid-memberships-pro' );
248
- }
249
- }
250
- else {
251
- $msg = -3;
252
- $msgt = __("Error deleting membership level.", 'paid-memberships-pro' );
253
- }
254
- }
255
-
256
- require_once(dirname(__FILE__) . "/admin_header.php");
257
- ?>
258
-
259
- <?php
260
- if($edit) {
261
- ?>
262
-
263
- <h2>
264
- <?php
265
- if($edit > 0)
266
- echo __("Edit Membership Level", 'paid-memberships-pro' );
267
- else
268
- echo __("Add New Membership Level", 'paid-memberships-pro' );
269
- ?>
270
- </h2>
271
-
272
- <div>
273
- <?php
274
- // get the level...
275
- if(!empty($edit) && $edit > 0) {
276
- $level = $wpdb->get_row( $wpdb->prepare( "
277
- SELECT * FROM $wpdb->pmpro_membership_levels
278
- WHERE id = %d LIMIT 1",
279
- $edit
280
- ),
281
- OBJECT
282
- );
283
- $temp_id = $level->id;
284
- } elseif(!empty($copy) && $copy > 0) {
285
- $level = $wpdb->get_row( $wpdb->prepare( "
286
- SELECT * FROM $wpdb->pmpro_membership_levels
287
- WHERE id = %d LIMIT 1",
288
- $copy
289
- ),
290
- OBJECT
291
- );
292
- $temp_id = $level->id;
293
- $level->id = NULL;
294
- }
295
- else
296
-
297
- // didn't find a membership level, let's add a new one...
298
- if(empty($level)) {
299
- $level = new stdClass();
300
- $level->id = NULL;
301
- $level->name = NULL;
302
- $level->description = NULL;
303
- $level->confirmation = NULL;
304
- $level->billing_amount = NULL;
305
- $level->trial_amount = NULL;
306
- $level->initial_payment = NULL;
307
- $level->billing_limit = NULL;
308
- $level->trial_limit = NULL;
309
- $level->expiration_number = NULL;
310
- $level->expiration_period = NULL;
311
- $edit = -1;
312
- }
313
-
314
- //defaults for new levels
315
- if(empty($copy) && $edit == -1) {
316
- $level->cycle_number = 1;
317
- $level->cycle_period = "Month";
318
- }
319
-
320
- // grab the categories for the given level...
321
- if(!empty($temp_id))
322
- $level->categories = $wpdb->get_col( $wpdb->prepare( "
323
- SELECT c.category_id
324
- FROM $wpdb->pmpro_memberships_categories c
325
- WHERE c.membership_id = %d",
326
- $temp_id
327
- ) );
328
- if(empty($level->categories))
329
- $level->categories = array();
330
-
331
- // grab the meta for the given level...
332
- if ( ! empty( $temp_id ) ) {
333
- $confirmation_in_email = get_pmpro_membership_level_meta( $temp_id, 'confirmation_in_email', true );
334
- }
335
-
336
- ?>
337
- <form action="" method="post" enctype="multipart/form-data">
338
- <input name="saveid" type="hidden" value="<?php echo esc_attr($edit); ?>" />
339
- <input type="hidden" name="action" value="save_membershiplevel" />
340
- <?php wp_nonce_field('save_membershiplevel', 'pmpro_membershiplevels_nonce'); ?>
341
- <table class="form-table">
342
- <tbody>
343
- <tr>
344
- <th scope="row" valign="top"><label><?php _e('ID', 'paid-memberships-pro' );?>:</label></th>
345
- <td>
346
- <?php echo $level->id?>
347
- </td>
348
- </tr>
349
-
350
- <tr>
351
- <th scope="row" valign="top"><label for="name"><?php _e('Name', 'paid-memberships-pro' );?>:</label></th>
352
- <td><input name="name" type="text" size="50" value="<?php echo esc_attr($level->name);?>" /></td>
353
- </tr>
354
-
355
- <tr>
356
- <th scope="row" valign="top"><label for="description"><?php _e('Description', 'paid-memberships-pro' );?>:</label></th>
357
- <td>
358
- <div id="poststuff" class="pmpro_description">
359
- <?php
360
- if(version_compare($wp_version, "3.3") >= 0)
361
- wp_editor($level->description, "description", array("textarea_rows"=>5));
362
- else
363
- {
364
- ?>
365
- <textarea rows="10" cols="80" name="description" id="description"><?php echo esc_textarea($level->description);?></textarea>
366
- <?php
367
- }
368
- ?>
369
- </div>
370
- </td>
371
- </tr>
372
-
373
- <tr>
374
- <th scope="row" valign="top"><label for="confirmation"><?php _e('Confirmation Message', 'paid-memberships-pro' );?>:</label></th>
375
- <td>
376
- <div class="pmpro_confirmation">
377
- <?php
378
- if(version_compare($wp_version, "3.3") >= 0)
379
- wp_editor($level->confirmation, "confirmation", array("textarea_rows"=>5));
380
- else
381
- {
382
- ?>
383
- <textarea rows="10" cols="80" name="confirmation" id="confirmation"><?php echo esc_textarea($level->confirmation);?></textarea>
384
- <?php
385
- }
386
- ?>
387
- </div>
388
- <input id="confirmation_in_email" name="confirmation_in_email" type="checkbox" value="yes" <?php checked( $confirmation_in_email, 1); ?> /> <label for="confirmation_in_email"><?php _e('Check to include this message in the membership confiramtion email.', 'paid-memberships-pro' );?></label>
389
- </td>
390
- </tr>
391
- </tbody>
392
- </table>
393
-
394
- <h3 class="topborder"><?php _e('Billing Details', 'paid-memberships-pro' );?></h3>
395
- <table class="form-table">
396
- <tbody>
397
- <tr>
398
- <th scope="row" valign="top"><label for="initial_payment"><?php _e('Initial Payment', 'paid-memberships-pro' );?>:</label></th>
399
- <td>
400
- <?php
401
- if(pmpro_getCurrencyPosition() == "left")
402
- echo $pmpro_currency_symbol;
403
- ?>
404
- <input name="initial_payment" type="text" size="20" value="<?php echo esc_attr($level->initial_payment);?>" />
405
- <?php
406
- if(pmpro_getCurrencyPosition() == "right")
407
- echo $pmpro_currency_symbol;
408
- ?>
409
- <small><?php _e('The initial amount collected at registration.', 'paid-memberships-pro' );?></small></td>
410
- </tr>
411
-
412
- <tr>
413
- <th scope="row" valign="top"><label><?php _e('Recurring Subscription', 'paid-memberships-pro' );?>:</label></th>
414
- <td><input id="recurring" name="recurring" type="checkbox" value="yes" <?php if(pmpro_isLevelRecurring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery('#recurring').is(':checked')) { jQuery('.recurring_info').show(); if(jQuery('#custom_trial').is(':checked')) {jQuery('.trial_info').show();} else {jQuery('.trial_info').hide();} } else { jQuery('.recurring_info').hide();}" /> <label for="recurring"><?php _e('Check if this level has a recurring subscription payment.', 'paid-memberships-pro' );?></label></td>
415
- </tr>
416
-
417
- <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
418
- <th scope="row" valign="top"><label for="billing_amount"><?php _e('Billing Amount', 'paid-memberships-pro' );?>:</label></th>
419
- <td>
420
- <?php
421
- if(pmpro_getCurrencyPosition() == "left")
422
- echo $pmpro_currency_symbol;
423
- ?>
424
- <input name="billing_amount" type="text" size="20" value="<?php echo esc_attr($level->billing_amount);?>" />
425
- <?php
426
- if(pmpro_getCurrencyPosition() == "right")
427
- echo $pmpro_currency_symbol;
428
- ?>
429
- <small><?php _e('per', 'paid-memberships-pro' );?></small>
430
- <input id="cycle_number" name="cycle_number" type="text" size="10" value="<?php echo esc_attr($level->cycle_number);?>" />
431
- <select id="cycle_period" name="cycle_period">
432
- <?php
433
- $cycles = array( __('Day(s)', 'paid-memberships-pro' ) => 'Day', __('Week(s)', 'paid-memberships-pro' ) => 'Week', __('Month(s)', 'paid-memberships-pro' ) => 'Month', __('Year(s)', 'paid-memberships-pro' ) => 'Year' );
434
- foreach ( $cycles as $name => $value ) {
435
- echo "<option value='$value'";
436
- if ( $level->cycle_period == $value ) echo " selected='selected'";
437
- echo ">$name</option>";
438
- }
439
- ?>
440
- </select>
441
- <br /><small>
442
- <?php _e('The amount to be billed one cycle after the initial payment.', 'paid-memberships-pro' );?>
443
- <?php if($gateway == "braintree") { ?>
444
- <br /><strong <?php if(!empty($pmpro_braintree_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Braintree integration currently only supports billing periods of "Month" or "Year".', 'paid-memberships-pro' );?>
445
- <?php } ?>
446
- </small>
447
- <?php if($gateway == "braintree" && $edit < 0) { ?>
448
- <p class="pmpro_message"><strong><?php _e('Note', 'paid-memberships-pro' );?>:</strong> <?php _e('After saving this level, make note of the ID and create a "Plan" in your Braintree dashboard with the same settings and the "Plan ID" set to <em>pmpro_#</em>, where # is the level ID.', 'paid-memberships-pro' );?></p>
449
- <?php } elseif($gateway == "braintree") {
450
- $has_bt_plan = PMProGateway_braintree::checkLevelForPlan( $level->id );
451
- ?>
452
- <p class="pmpro_message <?php if ( ! $has_bt_plan ) {?>pmpro_error<?php } ?>">
453
- <strong><?php _e('Note', 'paid-memberships-pro' );?>:</strong> <?php printf( __('You will need to create a "Plan" in your Braintree dashboard with the same settings and the "Plan ID" set to %s.', 'paid-memberships-pro' ), 'pmpro_' . $level->id ); ?></p>
454
- <?php } ?>
455
- </td>
456
- </tr>
457
-
458
- <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
459
- <th scope="row" valign="top"><label for="billing_limit"><?php _e('Billing Cycle Limit', 'paid-memberships-pro' );?>:</label></th>
460
- <td>
461
- <input name="billing_limit" type="text" size="20" value="<?php echo $level->billing_limit?>" />
462
- <br /><small>
463
- <?php _e('The <strong>total</strong> number of recurring billing cycles for this level, including the trial period (if applicable) but not including the initial payment. Set to zero if membership is indefinite.', 'paid-memberships-pro' );?>
464
- <?php if($gateway == "stripe") { ?>
465
- <br /><strong <?php if(!empty($pmpro_stripe_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Stripe integration currently does not support billing limits. You can still set an expiration date below.', 'paid-memberships-pro' );?></strong>
466
- <?php } ?>
467
- </small>
468
- </td>
469
- </tr>
470
-
471
- <tr class="recurring_info" <?php if (!pmpro_isLevelRecurring($level)) echo "style='display:none;'";?>>
472
- <th scope="row" valign="top"><label><?php _e('Custom Trial', 'paid-memberships-pro' );?>:</label></th>
473
- <td>
474
- <input id="custom_trial" name="custom_trial" type="checkbox" value="yes" <?php if ( pmpro_isLevelTrial($level) ) { echo "checked='checked'"; } ?> onclick="jQuery('.trial_info').toggle();" /> <label for="custom_trial"><?php _e('Check to add a custom trial period.', 'paid-memberships-pro' );?></label>
475
-
476
- <?php if($gateway == "twocheckout") { ?>
477
- <br /><small><strong <?php if(!empty($pmpro_twocheckout_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('2Checkout integration does not support custom trials. You can do one period trials by setting an initial payment different from the billing amount.', 'paid-memberships-pro' );?></strong></small>
478
- <?php } ?>
479
- </td>
480
- </tr>
481
-
482
- <tr class="trial_info recurring_info" <?php if (!pmpro_isLevelTrial($level)) echo "style='display:none;'";?>>
483
- <th scope="row" valign="top"><label for="trial_amount"><?php _e('Trial Billing Amount', 'paid-memberships-pro' );?>:</label></th>
484
- <td>
485
- <?php
486
- if(pmpro_getCurrencyPosition() == "left")
487
- echo $pmpro_currency_symbol;
488
- ?>
489
- <input name="trial_amount" type="text" size="20" value="<?php echo esc_attr($level->trial_amount);?>" />
490
- <?php
491
- if(pmpro_getCurrencyPosition() == "right")
492
- echo $pmpro_currency_symbol;
493
- ?>
494
- <small><?php _e('for the first', 'paid-memberships-pro' );?></small>
495
- <input name="trial_limit" type="text" size="10" value="<?php echo esc_attr($level->trial_limit);?>" />
496
- <small><?php _e('subscription payments', 'paid-memberships-pro' );?>.</small>
497
- <?php if($gateway == "stripe") { ?>
498
- <br /><small>
499
- <strong <?php if(!empty($pmpro_stripe_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Stripe integration currently does not support trial amounts greater than $0.', 'paid-memberships-pro' );?></strong>
500
- </small>
501
- <?php } elseif($gateway == "braintree") { ?>
502
- <br /><small>
503
- <strong <?php if(!empty($pmpro_braintree_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Braintree integration currently does not support trial amounts greater than $0.', 'paid-memberships-pro' );?></strong>
504
- </small>
505
- <?php } elseif($gateway == "payflowpro") { ?>
506
- <br /><small>
507
- <strong <?php if(!empty($pmpro_payflow_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Payflow integration currently does not support trial amounts greater than $0.', 'paid-memberships-pro' );?></strong>
508
- </small>
509
- <?php } ?>
510
- </td>
511
- </tr>
512
-
513
- </tbody>
514
- </table>
515
-
516
- <h3 class="topborder"><?php _e('Other Settings', 'paid-memberships-pro' );?></h3>
517
- <table class="form-table">
518
- <tbody>
519
- <tr>
520
- <th scope="row" valign="top"><label><?php _e('Disable New Signups', 'paid-memberships-pro' );?>:</label></th>
521
- <td><input id="disable_signups" name="disable_signups" type="checkbox" value="yes" <?php if($level->id && !$level->allow_signups) { ?>checked="checked"<?php } ?> /> <label for="disable_signups"><?php _e('Check to hide this level from the membership levels page and disable registration.', 'paid-memberships-pro' );?></label></td>
522
- </tr>
523
-
524
- <tr>
525
- <th scope="row" valign="top"><label><?php _e('Membership Expiration', 'paid-memberships-pro' );?>:</label></th>
526
- <td><input id="expiration" name="expiration" type="checkbox" value="yes" <?php if(pmpro_isLevelExpiring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery('#expiration').is(':checked')) { jQuery('.expiration_info').show(); } else { jQuery('.expiration_info').hide();}" /> <label for="expiration"><?php _e('Check this to set when membership access expires.', 'paid-memberships-pro' );?></label></a></td>
527
- </tr>
528
-
529
- <tr class="expiration_info" <?php if(!pmpro_isLevelExpiring($level)) {?>style="display: none;"<?php } ?>>
530
- <th scope="row" valign="top"><label for="billing_amount"><?php _e('Expires In', 'paid-memberships-pro' );?>:</label></th>
531
- <td>
532
- <input id="expiration_number" name="expiration_number" type="text" size="10" value="<?php echo esc_attr($level->expiration_number);?>" />
533
- <select id="expiration_period" name="expiration_period">
534
- <?php
535
- $cycles = array( __('Day(s)', 'paid-memberships-pro' ) => 'Day', __('Week(s)', 'paid-memberships-pro' ) => 'Week', __('Month(s)', 'paid-memberships-pro' ) => 'Month', __('Year(s)', 'paid-memberships-pro' ) => 'Year' );
536
- foreach ( $cycles as $name => $value ) {
537
- echo "<option value='$value'";
538
- if ( $level->expiration_period == $value ) echo " selected='selected'";
539
- echo ">$name</option>";
540
- }
541
- ?>
542
- </select>
543
- <br /><small><?php _e('Set the duration of membership access. Note that the any future payments (recurring subscription, if any) will be cancelled when the membership expires.', 'paid-memberships-pro' );?></small>
544
-
545
- <div id="pmpro_expiration_warning" style="display: none;" class="notice error inline">
546
- <p><?php printf( __( 'WARNING: This level is set with both a recurring billing amount and an expiration date. You only need to set one of these unless you really want this membership to expire after a certain number of payments. For more information, <a target="_blank" href="%s">see our post here</a>.', 'paid-memberships-pro' ), 'https://www.paidmembershipspro.com/important-notes-on-recurring-billing-and-expiration-dates-for-membership-levels/' ); ?></p>
547
- </div>
548
- <script>
549
- jQuery(document).ready(function() {
550
- function pmpro_expirationWarningCheck() {
551
- if( jQuery('#recurring:checked').length && jQuery('#expiration:checked').length) {
552
- jQuery('#pmpro_expiration_warning').show();
553
- } else {
554
- jQuery('#pmpro_expiration_warning').hide();
555
- }
556
- }
557
-
558
- pmpro_expirationWarningCheck();
559
-
560
- jQuery('#recurring,#expiration').change(function() { pmpro_expirationWarningCheck(); });
561
- });
562
- </script>
563
- </td>
564
- </tr>
565
- </tbody>
566
- </table>
567
-
568
- <?php do_action("pmpro_membership_level_after_other_settings"); ?>
569
-
570
- <h3 class="topborder"><?php _e('Content Settings', 'paid-memberships-pro' );?></h3>
571
- <table class="form-table">
572
- <tbody>
573
- <tr class="membership_categories">
574
- <th scope="row" valign="top"><label><?php _e('Categories', 'paid-memberships-pro' );?>:</label></th>
575
- <td>
576
- <?php pmpro_listCategories(0, $level->categories); ?>
577
- </td>
578
- </tr>
579
- </tbody>
580
- </table>
581
- <p class="submit topborder">
582
- <input name="save" type="submit" class="button-primary" value="<?php _e('Save Level', 'paid-memberships-pro' ); ?>" />
583
- <input name="cancel" type="button" value="<?php _e('Cancel', 'paid-memberships-pro' ); ?>" onclick="location.href='<?php echo add_query_arg( 'page', 'pmpro-membershiplevels' , get_admin_url(NULL, '/admin.php') ); ?>';" />
584
- </p>
585
- </form>
586
- </div>
587
-
588
- <?php
589
- }
590
- else
591
- {
592
- $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ";
593
- if($s)
594
- $sqlQuery .= "WHERE name LIKE '%$s%' ";
595
- $sqlQuery .= "ORDER BY id ASC";
596
-
597
- $levels = $wpdb->get_results($sqlQuery, OBJECT);
598
-
599
- if(empty($_REQUEST['s']) && !empty($pmpro_level_order)) {
600
- //reorder levels
601
- $order = explode(',', $pmpro_level_order);
602
-
603
- //put level ids in their own array
604
- $level_ids = array();
605
- foreach($levels as $level)
606
- $level_ids[] = $level->id;
607
-
608
- //remove levels from order if they are gone
609
- foreach($order as $key => $level_id)
610
- if(!in_array($level_id, $level_ids))
611
- unset($order[$key]);
612
-
613
- //add levels to the end if they aren't in the order array
614
- foreach($level_ids as $level_id)
615
- if(!in_array($level_id, $order))
616
- $order[] = $level_id;
617
-
618
- //remove dupes
619
- $order = array_unique($order);
620
-
621
- //save the level order
622
- pmpro_setOption('level_order', implode(',', $order));
623
-
624
- //reorder levels here
625
- $reordered_levels = array();
626
- foreach ($order as $level_id) {
627
- foreach ($levels as $level) {
628
- if ($level_id == $level->id)
629
- $reordered_levels[] = $level;
630
- }
631
- }
632
- }
633
- else
634
- $reordered_levels = $levels;
635
-
636
- if(empty($_REQUEST['s']) && count($reordered_levels) > 1)
637
- {
638
- ?>
639
- <script>
640
- jQuery(document).ready(function($) {
641
-
642
- // Return a helper with preserved width of cells
643
- // from http://www.foliotek.com/devblog/make-table-rows-sortable-using-jquery-ui-sortable/
644
- var fixHelper = function(e, ui) {
645
- ui.children().each(function() {
646
- $(this).width($(this).width());
647
- });
648
- return ui;
649
- };
650
-
651
- $("table.membership-levels tbody").sortable({
652
- helper: fixHelper,
653
- placeholder: 'testclass',
654
- forcePlaceholderSize: true,
655
- update: update_level_order
656
- });
657
-
658
- function update_level_order(event, ui) {
659
- level_order = [];
660
- $("table.membership-levels tbody tr").each(function() {
661
- $(this).removeClass('alternate');
662
- level_order.push(parseInt( $("td:first", this).text()));
663
- });
664
-
665
- //update styles
666
- $("table.membership-levels tbody tr:odd").each(function() {
667
- $(this).addClass('alternate');
668
- });
669
-
670
- data = {
671
- action: 'pmpro_update_level_order',
672
- level_order: level_order
673
- };
674
-
675
- $.post(ajaxurl, data, function(response) {
676
- });
677
- }
678
- });
679
- </script>
680
- <?php
681
- }
682
- ?>
683
-
684
- <?php if( count( $reordered_levels ) === 0 ) { ?>
685
- <div class="pmpro-new-install">
686
- <h2><?php echo esc_attr_e( 'No Membership Levels Found', 'paid-memberships-pro' ); ?></h2>
687
- <a href="<?php echo esc_url( admin_url( 'admin.php?page=pmpro-membershiplevels&edit=-1' ) ); ?>" class="button-primary"><?php echo esc_attr_e( 'Create a Membership Level', 'paid-memberships-pro' ); ?></a>
688
- <a href="<?php echo esc_url( 'https://www.paidmembershipspro.com/documentation/initial-plugin-setup/step-1-add-new-membership-level/' ); ?>" target="_blank" class="button"><?php echo esc_attr_e( 'Video: Membership Levels', 'paid-memberships-pro' ); ?></a>
689
- </div> <!-- end pmpro-new-install -->
690
- <?php } else { ?>
691
-
692
- <form id="posts-filter" method="get" action="">
693
- <p class="search-box">
694
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search Levels', 'paid-memberships-pro' );?>:</label>
695
- <input type="hidden" name="page" value="pmpro-membershiplevels" />
696
- <input id="post-search-input" type="text" value="<?php echo esc_attr($s); ?>" name="s" size="30" />
697
- <input class="button" type="submit" value="<?php _e('Search Levels', 'paid-memberships-pro' );?>" id="search-submit" />
698
- </p>
699
- </form>
700
- <h2><?php _e('Membership Levels', 'paid-memberships-pro' );?> <a href="<?php echo add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'edit' => -1 ), get_admin_url(null, 'admin.php' ) ); ?>" class="add-new-h2"><?php _e('Add New Level', 'paid-memberships-pro' );?></a></h2>
701
-
702
- <?php if(empty($_REQUEST['s']) && count($reordered_levels) > 1) { ?>
703
- <p><?php _e('Drag and drop membership levels to reorder them on the Levels page.', 'paid-memberships-pro' ); ?></p>
704
- <?php } ?>
705
-
706
- <?php
707
- //going to capture the output of this table so we can filter it
708
- ob_start();
709
- ?>
710
- <table class="widefat membership-levels">
711
- <thead>
712
- <tr>
713
- <th><?php _e('ID', 'paid-memberships-pro' );?></th>
714
- <th><?php _e('Name', 'paid-memberships-pro' );?></th>
715
- <th><?php _e('Billing Details', 'paid-memberships-pro' );?></th>
716
- <th><?php _e('Expiration', 'paid-memberships-pro' );?></th>
717
- <th><?php _e('Allow Signups', 'paid-memberships-pro' );?></th>
718
- <th></th>
719
- </tr>
720
- </thead>
721
- <tbody>
722
- <?php
723
- $count = 0;
724
- foreach($reordered_levels as $level)
725
- {
726
- ?>
727
- <tr class="<?php if($count++ % 2 == 1) { ?>alternate<?php } ?> <?php if(!$level->allow_signups) { ?>pmpro_gray<?php } ?> <?php if(!pmpro_checkLevelForStripeCompatibility($level) || !pmpro_checkLevelForBraintreeCompatibility($level) || !pmpro_checkLevelForPayflowCompatibility($level) || !pmpro_checkLevelForTwoCheckoutCompatibility($level)) { ?>pmpro_error<?php } ?>">
728
- <td><?php echo $level->id?></td>
729
- <td class="level_name"><a href="<?php echo add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'edit' => $level->id ), admin_url( 'admin.php' ) ); ?>"><?php esc_attr_e( $level->name ); ?></a></td>
730
- <td>
731
- <?php if(pmpro_isLevelFree($level)) { ?>
732
- <?php _e('FREE', 'paid-memberships-pro' );?>
733
- <?php } else { ?>
734
- <?php echo str_replace( 'The price for membership is', '', pmpro_getLevelCost($level)); ?>
735
- <?php } ?>
736
- </td>
737
- <td>
738
- <?php if(!pmpro_isLevelExpiring($level)) { ?>
739
- --
740
- <?php } else { ?>
741
- <?php _e('After', 'paid-memberships-pro' );?> <?php echo $level->expiration_number?> <?php echo sornot($level->expiration_period,$level->expiration_number)?>
742
- <?php } ?>
743
- </td>
744
- <td><?php if($level->allow_signups) { ?><a href="<?php echo add_query_arg( 'level', $level->id, pmpro_url("checkout") );?>"><?php _e('Yes', 'paid-memberships-pro' );?></a><?php } else { ?><?php _e('No', 'paid-memberships-pro' );?><?php } ?></td>
745
-
746
- <td><a title="<?php _e('edit', 'paid-memberships-pro' ); ?>" href="<?php echo add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'edit' => $level->id ), admin_url('admin.php' ) ); ?>" class="button-primary"><?php _e('edit', 'paid-memberships-pro' ); ?></a>&nbsp;<a title="<?php _e('copy', 'paid-memberships-pro' ); ?>" href="<?php echo add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'edit' => -1, 'copy' => $level->id ), admin_url( 'admin.php' ) ); ?>" class="button-secondary"><?php _e('copy', 'paid-memberships-pro' ); ?></a>&nbsp;<a title="<?php _e('delete', 'paid-memberships-pro' ); ?>" href="javascript:askfirst('<?php echo str_replace("'", "\'", sprintf(__("Are you sure you want to delete membership level %s? All subscriptions will be cancelled.", 'paid-memberships-pro' ), $level->name));?>', '<?php echo wp_nonce_url(add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'action' => 'delete_membership_level', 'deleteid' => $level->id ), admin_url( 'admin.php' ) ), 'delete_membership_level', 'pmpro_membershiplevels_nonce'); ?>'); void(0);" class="button-secondary"><?php _e('delete', 'paid-memberships-pro' ); ?></a></td>
747
- </tr>
748
- <?php
749
- }
750
- ?>
751
- </tbody>
752
- </table>
753
-
754
- <?php
755
- $table_html = ob_get_clean();
756
-
757
- /**
758
- * Filter to change the Membership Levels table
759
- * @since 1.8.10
760
- *
761
- * @param string $table_html HTML of the membership levels table
762
- * @param array $reordered_levels Array of membership levels
763
- */
764
- $table_html = apply_filters('pmpro_membership_levels_table', $table_html, $reordered_levels);
765
-
766
- echo $table_html;
767
- }
768
- ?>
769
-
770
- <?php } ?>
771
-
772
- <?php
773
- require_once(dirname(__FILE__) . "/admin_footer.php");
1
+ <?php
2
+ //only admins can get this
3
+ if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_membershiplevels")))
4
+ {
5
+ die(__("You do not have permissions to perform this action.", 'paid-memberships-pro' ));
6
+ }
7
+
8
+ global $wpdb, $msg, $msgt, $pmpro_currency_symbol, $allowedposttags;
9
+
10
+ //some vars
11
+ $gateway = pmpro_getOption("gateway");
12
+ $pmpro_level_order = pmpro_getOption('level_order');
13
+
14
+ global $pmpro_stripe_error, $pmpro_braintree_error, $pmpro_payflow_error, $pmpro_twocheckout_error, $wp_version;
15
+
16
+ if(isset($_REQUEST['edit']))
17
+ $edit = intval($_REQUEST['edit']);
18
+ else
19
+ $edit = false;
20
+ if(isset($_REQUEST['copy']))
21
+ $copy = intval($_REQUEST['copy']);
22
+ if(isset($_REQUEST['s']))
23
+ $s = sanitize_text_field($_REQUEST['s']);
24
+ else
25
+ $s = "";
26
+
27
+ if(isset($_REQUEST['action']))
28
+ $action = sanitize_text_field($_REQUEST['action']);
29
+ else
30
+ $action = false;
31
+
32
+ if(isset($_REQUEST['saveandnext']))
33
+ $saveandnext = intval($_REQUEST['saveandnext']);
34
+
35
+ if(isset($_REQUEST['saveid']))
36
+ $saveid = intval($_REQUEST['saveid']);
37
+ if(isset($_REQUEST['deleteid']))
38
+ $deleteid = intval($_REQUEST['deleteid']);
39
+
40
+ //check nonce
41
+ if(!empty($action) && (empty($_REQUEST['pmpro_membershiplevels_nonce']) || !check_admin_referer($action, 'pmpro_membershiplevels_nonce'))) {
42
+ $msg = -1;
43
+ $msgt = __("Are you sure you want to do that? Try again.", 'paid-memberships-pro' );
44
+ $action = false;
45
+ }
46
+
47
+ if($action == "save_membershiplevel") {
48
+
49
+ $ml_name = wp_kses(wp_unslash($_REQUEST['name']), $allowedposttags);
50
+ $ml_description = wp_kses(wp_unslash($_REQUEST['description']), $allowedposttags);
51
+ $ml_confirmation = wp_kses(wp_unslash($_REQUEST['confirmation']), $allowedposttags);
52
+ if(!empty($_REQUEST['confirmation_in_email']))
53
+ $ml_confirmation_in_email = 1;
54
+ else
55
+ $ml_confirmation_in_email = 0;
56
+
57
+ $ml_initial_payment = sanitize_text_field($_REQUEST['initial_payment']);
58
+ if(!empty($_REQUEST['recurring']))
59
+ $ml_recurring = 1;
60
+ else
61
+ $ml_recurring = 0;
62
+ $ml_billing_amount = sanitize_text_field($_REQUEST['billing_amount']);
63
+ $ml_cycle_number = intval($_REQUEST['cycle_number']);
64
+ $ml_cycle_period = sanitize_text_field($_REQUEST['cycle_period']);
65
+ $ml_billing_limit = intval($_REQUEST['billing_limit']);
66
+ if(!empty($_REQUEST['custom_trial']))
67
+ $ml_custom_trial = 1;
68
+ else
69
+ $ml_custom_trial = 0;
70
+ $ml_trial_amount = sanitize_text_field($_REQUEST['trial_amount']);
71
+ $ml_trial_limit = intval($_REQUEST['trial_limit']);
72
+ if(!empty($_REQUEST['expiration']))
73
+ $ml_expiration = 1;
74
+ else
75
+ $ml_expiration = 0;
76
+ $ml_expiration_number = intval($_REQUEST['expiration_number']);
77
+ $ml_expiration_period = sanitize_text_field($_REQUEST['expiration_period']);
78
+ $ml_categories = array();
79
+
80
+ //reversing disable to allow here
81
+ if(empty($_REQUEST['disable_signups']))
82
+ $ml_allow_signups = 1;
83
+ else
84
+ $ml_allow_signups = 0;
85
+
86
+ foreach ( $_REQUEST as $key => $value ) {
87
+ if ( $value == 'yes' && preg_match( '/^membershipcategory_(\d+)#x2F;i', $key, $matches ) ) {
88
+ $ml_categories[] = $matches[1];
89
+ }
90
+ }
91
+
92
+ //clearing out values if checkboxes aren't checked
93
+ if(empty($ml_recurring)) {
94
+ $ml_billing_amount = $ml_cycle_number = $ml_cycle_period = $ml_billing_limit = $ml_trial_amount = $ml_trial_limit = 0;
95
+ } elseif(empty($ml_custom_trial)) {
96
+ $ml_trial_amount = $ml_trial_limit = 0;
97
+ }
98
+ if(empty($ml_expiration)) {
99
+ $ml_expiration_number = $ml_expiration_period = 0;
100
+ }
101
+
102
+ $wpdb->replace(
103
+ $wpdb->pmpro_membership_levels,
104
+ array(
105
+ 'id'=>max($saveid, 0),
106
+ 'name' => $ml_name,
107
+ 'description' => $ml_description,
108
+ 'confirmation' => $ml_confirmation,
109
+ 'initial_payment' => $ml_initial_payment,
110
+ 'billing_amount' => $ml_billing_amount,
111
+ 'cycle_number' => $ml_cycle_number,
112
+ 'cycle_period' => $ml_cycle_period,
113
+ 'billing_limit' => $ml_billing_limit,
114
+ 'trial_amount' => $ml_trial_amount,
115
+ 'trial_limit' => $ml_trial_limit,
116
+ 'expiration_number' => $ml_expiration_number,
117
+ 'expiration_period' => $ml_expiration_period,
118
+ 'allow_signups' => $ml_allow_signups
119
+ ),
120
+ array(
121
+ '%d', //id
122
+ '%s', //name
123
+ '%s', //description
124
+ '%s', //confirmation
125
+ '%f', //initial_payment
126
+ '%f', //billing_amount
127
+ '%d', //cycle_number
128
+ '%s', //cycle_period
129
+ '%d', //billing_limit
130
+ '%f', //trial_amount
131
+ '%d', //trial_limit
132
+ '%d', //expiration_number
133
+ '%s', //expiration_period
134
+ '%d', //allow_signups
135
+ )
136
+ );
137
+
138
+ if($saveid < 1) {
139
+ //added a level
140
+ $saveid = $wpdb->insert_id;
141
+
142
+ pmpro_updateMembershipCategories( $saveid, $ml_categories );
143
+
144
+ if(empty($wpdb->last_error)) {
145
+ $saveid = $wpdb->insert_id;
146
+ pmpro_updateMembershipCategories( $saveid, $ml_categories );
147
+
148
+ $edit = false;
149
+ $msg = 1;
150
+ $msgt = __("Membership level added successfully.", 'paid-memberships-pro' );
151
+ } else {
152
+ $msg = -1;
153
+ $msgt = __("Error adding membership level.", 'paid-memberships-pro' );
154
+ }
155
+ } else {
156
+ pmpro_updateMembershipCategories( $saveid, $ml_categories );
157
+
158
+ if(empty($wpdb->last_error)) {
159
+ $edit = false;
160
+ $msg = 2;
161
+ $msgt = __("Membership level updated successfully.", 'paid-memberships-pro' );
162
+ } else {
163
+ $msg = -2;
164
+ $msgt = __("Error updating membership level.", 'paid-memberships-pro' );
165
+ }
166
+ }
167
+
168
+ if( ! empty( $msgt ) && $ml_recurring && $ml_expiration ) {
169
+ $msgt .= ' <strong class="red">' . sprintf( __( 'WARNING: A level was set with both a recurring billing amount and an expiration date. You only need to set one of these unless you really want this membership to expire after a specific time period. For more information, <a target="_blank" href="%s">see our post here</a>.', 'paid-memberships-pro' ), 'https://www.paidmembershipspro.com/important-notes-on-recurring-billing-and-expiration-dates-for-membership-levels/' ) . '</strong>';
170
+
171
+ // turn success to errors
172
+ if( $msg > 0 ) {
173
+ $msg = 0 - $msg;
174
+ }
175
+ }
176
+
177
+ // Update the Level Meta to Add Confirmation Message to Email.
178
+ if ( isset( $ml_confirmation_in_email ) ) {
179
+ update_pmpro_membership_level_meta( $saveid, 'confirmation_in_email', $ml_confirmation_in_email );
180
+ }
181
+
182
+ do_action("pmpro_save_membership_level", $saveid);
183
+ }
184
+ elseif($action == "delete_membership_level")
185
+ {
186
+ global $wpdb;
187
+
188
+ $ml_id = intval($_REQUEST['deleteid']);
189
+
190
+ if($ml_id > 0) {
191
+ do_action("pmpro_delete_membership_level", $ml_id);
192
+
193
+ //remove any categories from the ml
194
+ $sqlQuery = $wpdb->prepare("
195
+ DELETE FROM $wpdb->pmpro_memberships_categories
196
+ WHERE membership_id = %d",
197
+ $ml_id
198
+ );
199
+
200
+ $r1 = $wpdb->query($sqlQuery);
201
+
202
+ //cancel any subscriptions to the ml
203
+ $r2 = true;
204
+ $user_ids = $wpdb->get_col( $wpdb->prepare( "
205
+ SELECT user_id FROM $wpdb->pmpro_memberships_users
206
+ WHERE membership_id = %d
207
+ AND status = 'active'",
208
+ $ml_id
209
+ ) );
210
+
211
+ foreach($user_ids as $user_id) {
212
+ //change there membership level to none. that will handle the cancel
213
+ if(pmpro_changeMembershipLevel(0, $user_id)) {
214
+ //okay
215
+ } else {
216
+ //couldn't delete the subscription
217
+ //we should probably notify the admin
218
+ $pmproemail = new PMProEmail();
219
+ $pmproemail->data = array("body"=>"<p>" . sprintf(__("There was an error canceling the subscription for user with ID=%d. You will want to check your payment gateway to see if their subscription is still active.", 'paid-memberships-pro' ), $user_id) . "</p>");
220
+ $last_order = $wpdb->get_row( $wpdb->prepare( "
221
+ SELECT * FROM $wpdb->pmpro_membership_orders
222
+ WHERE user_id = %d
223
+ ORDER BY timestamp DESC LIMIT 1",
224
+ $user_id
225
+ ) );
226
+ if($last_order)
227
+ $pmproemail->data["body"] .= "<p>" . __("Last Invoice", 'paid-memberships-pro' ) . ":<br />" . nl2br(var_export($last_order, true)) . "</p>";
228
+ $pmproemail->sendEmail(get_bloginfo("admin_email"));
229
+
230
+ $r2 = false;
231
+ }
232
+ }
233
+
234
+ //delete the ml
235
+ $sqlQuery = $wpdb->prepare( "
236
+ DELETE FROM $wpdb->pmpro_membership_levels
237
+ WHERE id = %d LIMIT 1",
238
+ $ml_id
239
+ );
240
+ $r3 = $wpdb->query($sqlQuery);
241
+
242
+ if($r1 !== FALSE && $r2 !== FALSE && $r3 !== FALSE) {
243
+ $msg = 3;
244
+ $msgt = __("Membership level deleted successfully.", 'paid-memberships-pro' );
245
+ } else {
246
+ $msg = -3;
247
+ $msgt = __("Error deleting membership level.", 'paid-memberships-pro' );
248
+ }
249
+ }
250
+ else {
251
+ $msg = -3;
252
+ $msgt = __("Error deleting membership level.", 'paid-memberships-pro' );
253
+ }
254
+ }
255
+
256
+ require_once(dirname(__FILE__) . "/admin_header.php");
257
+ ?>
258
+
259
+ <?php
260
+ if($edit) {
261
+ ?>
262
+
263
+ <h2>
264
+ <?php
265
+ if($edit > 0)
266
+ echo __("Edit Membership Level", 'paid-memberships-pro' );
267
+ else
268
+ echo __("Add New Membership Level", 'paid-memberships-pro' );
269
+ ?>
270
+ </h2>
271
+
272
+ <div>
273
+ <?php
274
+ // get the level...
275
+ if(!empty($edit) && $edit > 0) {
276
+ $level = $wpdb->get_row( $wpdb->prepare( "
277
+ SELECT * FROM $wpdb->pmpro_membership_levels
278
+ WHERE id = %d LIMIT 1",
279
+ $edit
280
+ ),
281
+ OBJECT
282
+ );
283
+ $temp_id = $level->id;
284
+ } elseif(!empty($copy) && $copy > 0) {
285
+ $level = $wpdb->get_row( $wpdb->prepare( "
286
+ SELECT * FROM $wpdb->pmpro_membership_levels
287
+ WHERE id = %d LIMIT 1",
288
+ $copy
289
+ ),
290
+ OBJECT
291
+ );
292
+ $temp_id = $level->id;
293
+ $level->id = NULL;
294
+ }
295
+ else
296
+
297
+ // didn't find a membership level, let's add a new one...
298
+ if(empty($level)) {
299
+ $level = new stdClass();
300
+ $level->id = NULL;
301
+ $level->name = NULL;
302
+ $level->description = NULL;
303
+ $level->confirmation = NULL;
304
+ $level->billing_amount = NULL;
305
+ $level->trial_amount = NULL;
306
+ $level->initial_payment = NULL;
307
+ $level->billing_limit = NULL;
308
+ $level->trial_limit = NULL;
309
+ $level->expiration_number = NULL;
310
+ $level->expiration_period = NULL;
311
+ $edit = -1;
312
+ }
313
+
314
+ //defaults for new levels
315
+ if(empty($copy) && $edit == -1) {
316
+ $level->cycle_number = 1;
317
+ $level->cycle_period = "Month";
318
+ }
319
+
320
+ // grab the categories for the given level...
321
+ if(!empty($temp_id))
322
+ $level->categories = $wpdb->get_col( $wpdb->prepare( "
323
+ SELECT c.category_id
324
+ FROM $wpdb->pmpro_memberships_categories c
325
+ WHERE c.membership_id = %d",
326
+ $temp_id
327
+ ) );
328
+ if(empty($level->categories))
329
+ $level->categories = array();
330
+
331
+ // grab the meta for the given level...
332
+ if ( ! empty( $temp_id ) ) {
333
+ $confirmation_in_email = get_pmpro_membership_level_meta( $temp_id, 'confirmation_in_email', true );
334
+ }
335
+
336
+ ?>
337
+ <form action="" method="post" enctype="multipart/form-data">
338
+ <input name="saveid" type="hidden" value="<?php echo esc_attr($edit); ?>" />
339
+ <input type="hidden" name="action" value="save_membershiplevel" />
340
+ <?php wp_nonce_field('save_membershiplevel', 'pmpro_membershiplevels_nonce'); ?>
341
+ <table class="form-table">
342
+ <tbody>
343
+ <tr>
344
+ <th scope="row" valign="top"><label><?php _e('ID', 'paid-memberships-pro' );?>:</label></th>
345
+ <td>
346
+ <?php echo $level->id?>
347
+ </td>
348
+ </tr>
349
+
350
+ <tr>
351
+ <th scope="row" valign="top"><label for="name"><?php _e('Name', 'paid-memberships-pro' );?>:</label></th>
352
+ <td><input name="name" type="text" size="50" value="<?php echo esc_attr($level->name);?>" /></td>
353
+ </tr>
354
+
355
+ <tr>
356
+ <th scope="row" valign="top"><label for="description"><?php _e('Description', 'paid-memberships-pro' );?>:</label></th>
357
+ <td>
358
+ <div id="poststuff" class="pmpro_description">
359
+ <?php
360
+ if(version_compare($wp_version, "3.3") >= 0)
361
+ wp_editor($level->description, "description", array("textarea_rows"=>5));
362
+ else
363
+ {
364
+ ?>
365
+ <textarea rows="10" cols="80" name="description" id="description"><?php echo esc_textarea($level->description);?></textarea>
366
+ <?php
367
+ }
368
+ ?>
369
+ </div>
370
+ </td>
371
+ </tr>
372
+
373
+ <tr>
374
+ <th scope="row" valign="top"><label for="confirmation"><?php _e('Confirmation Message', 'paid-memberships-pro' );?>:</label></th>
375
+ <td>
376
+ <div class="pmpro_confirmation">
377
+ <?php
378
+ if(version_compare($wp_version, "3.3") >= 0)
379
+ wp_editor($level->confirmation, "confirmation", array("textarea_rows"=>5));
380
+ else
381
+ {
382
+ ?>
383
+ <textarea rows="10" cols="80" name="confirmation" id="confirmation"><?php echo esc_textarea($level->confirmation);?></textarea>
384
+ <?php
385
+ }
386
+ ?>
387
+ </div>
388
+ <input id="confirmation_in_email" name="confirmation_in_email" type="checkbox" value="yes" <?php checked( $confirmation_in_email, 1); ?> /> <label for="confirmation_in_email"><?php _e('Check to include this message in the membership confiramtion email.', 'paid-memberships-pro' );?></label>
389
+ </td>
390
+ </tr>
391
+ </tbody>
392
+ </table>
393
+
394
+ <h3 class="topborder"><?php _e('Billing Details', 'paid-memberships-pro' );?></h3>
395
+ <table class="form-table">
396
+ <tbody>
397
+ <tr>
398
+ <th scope="row" valign="top"><label for="initial_payment"><?php _e('Initial Payment', 'paid-memberships-pro' );?>:</label></th>
399
+ <td>
400
+ <?php
401
+ if(pmpro_getCurrencyPosition() == "left")
402
+ echo $pmpro_currency_symbol;
403
+ ?>
404
+ <input name="initial_payment" type="text" size="20" value="<?php echo esc_attr( pmpro_filter_price_for_text_field( $level->initial_payment ) );?>" />
405
+ <?php
406
+ if(pmpro_getCurrencyPosition() == "right")
407
+ echo $pmpro_currency_symbol;
408
+ ?>
409
+ <small><?php _e('The initial amount collected at registration.', 'paid-memberships-pro' );?></small></td>
410
+ </tr>
411
+
412
+ <tr>
413
+ <th scope="row" valign="top"><label><?php _e('Recurring Subscription', 'paid-memberships-pro' );?>:</label></th>
414
+ <td><input id="recurring" name="recurring" type="checkbox" value="yes" <?php if(pmpro_isLevelRecurring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery('#recurring').is(':checked')) { jQuery('.recurring_info').show(); if(jQuery('#custom_trial').is(':checked')) {jQuery('.trial_info').show();} else {jQuery('.trial_info').hide();} } else { jQuery('.recurring_info').hide();}" /> <label for="recurring"><?php _e('Check if this level has a recurring subscription payment.', 'paid-memberships-pro' );?></label></td>
415
+ </tr>
416
+
417
+ <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
418
+ <th scope="row" valign="top"><label for="billing_amount"><?php _e('Billing Amount', 'paid-memberships-pro' );?>:</label></th>
419
+ <td>
420
+ <?php
421
+ if(pmpro_getCurrencyPosition() == "left")
422
+ echo $pmpro_currency_symbol;
423
+ ?>
424
+ <input name="billing_amount" type="text" size="20" value="<?php echo esc_attr( pmpro_filter_price_for_text_field( $level->billing_amount ) );?>" />
425
+ <?php
426
+ if(pmpro_getCurrencyPosition() == "right")
427
+ echo $pmpro_currency_symbol;
428
+ ?>
429
+ <small><?php _e('per', 'paid-memberships-pro' );?></small>
430
+ <input id="cycle_number" name="cycle_number" type="text" size="10" value="<?php echo esc_attr($level->cycle_number);?>" />
431
+ <select id="cycle_period" name="cycle_period">
432
+ <?php
433
+ $cycles = array( __('Day(s)', 'paid-memberships-pro' ) => 'Day', __('Week(s)', 'paid-memberships-pro' ) => 'Week', __('Month(s)', 'paid-memberships-pro' ) => 'Month', __('Year(s)', 'paid-memberships-pro' ) => 'Year' );
434
+ foreach ( $cycles as $name => $value ) {
435
+ echo "<option value='$value'";
436
+ if ( $level->cycle_period == $value ) echo " selected='selected'";
437
+ echo ">$name</option>";
438
+ }
439
+ ?>
440
+ </select>
441
+ <br /><small>
442
+ <?php _e('The amount to be billed one cycle after the initial payment.', 'paid-memberships-pro' );?>
443
+ <?php if($gateway == "braintree") { ?>
444
+ <br /><strong <?php if(!empty($pmpro_braintree_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Braintree integration currently only supports billing periods of "Month" or "Year".', 'paid-memberships-pro' );?>
445
+ <?php } ?>
446
+ </small>
447
+ <?php if($gateway == "braintree" && $edit < 0) { ?>
448
+ <p class="pmpro_message"><strong><?php _e('Note', 'paid-memberships-pro' );?>:</strong> <?php _e('After saving this level, make note of the ID and create a "Plan" in your Braintree dashboard with the same settings and the "Plan ID" set to <em>pmpro_#</em>, where # is the level ID.', 'paid-memberships-pro' );?></p>
449
+ <?php } elseif($gateway == "braintree") {
450
+ $has_bt_plan = PMProGateway_braintree::checkLevelForPlan( $level->id );
451
+ ?>
452
+ <p class="pmpro_message <?php if ( ! $has_bt_plan ) {?>pmpro_error<?php } ?>">
453
+ <strong><?php _e('Note', 'paid-memberships-pro' );?>:</strong> <?php printf( __('You will need to create a "Plan" in your Braintree dashboard with the same settings and the "Plan ID" set to %s.', 'paid-memberships-pro' ), 'pmpro_' . $level->id ); ?></p>
454
+ <?php } ?>
455
+ </td>
456
+ </tr>
457
+
458
+ <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
459
+ <th scope="row" valign="top"><label for="billing_limit"><?php _e('Billing Cycle Limit', 'paid-memberships-pro' );?>:</label></th>
460
+ <td>
461
+ <input name="billing_limit" type="text" size="20" value="<?php echo $level->billing_limit?>" />
462
+ <br /><small>
463
+ <?php _e('The <strong>total</strong> number of recurring billing cycles for this level, including the trial period (if applicable) but not including the initial payment. Set to zero if membership is indefinite.', 'paid-memberships-pro' );?>
464
+ <?php if($gateway == "stripe") { ?>
465
+ <br /><strong <?php if(!empty($pmpro_stripe_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Stripe integration currently does not support billing limits. You can still set an expiration date below.', 'paid-memberships-pro' );?></strong>
466
+ <?php } ?>
467
+ </small>
468
+ </td>
469
+ </tr>
470
+
471
+ <tr class="recurring_info" <?php if (!pmpro_isLevelRecurring($level)) echo "style='display:none;'";?>>
472
+ <th scope="row" valign="top"><label><?php _e('Custom Trial', 'paid-memberships-pro' );?>:</label></th>
473
+ <td>
474
+ <input id="custom_trial" name="custom_trial" type="checkbox" value="yes" <?php if ( pmpro_isLevelTrial($level) ) { echo "checked='checked'"; } ?> onclick="jQuery('.trial_info').toggle();" /> <label for="custom_trial"><?php _e('Check to add a custom trial period.', 'paid-memberships-pro' );?></label>
475
+
476
+ <?php if($gateway == "twocheckout") { ?>
477
+ <br /><small><strong <?php if(!empty($pmpro_twocheckout_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('2Checkout integration does not support custom trials. You can do one period trials by setting an initial payment different from the billing amount.', 'paid-memberships-pro' );?></strong></small>
478
+ <?php } ?>
479
+ </td>
480
+ </tr>
481
+
482
+ <tr class="trial_info recurring_info" <?php if (!pmpro_isLevelTrial($level)) echo "style='display:none;'";?>>
483
+ <th scope="row" valign="top"><label for="trial_amount"><?php _e('Trial Billing Amount', 'paid-memberships-pro' );?>:</label></th>
484
+ <td>
485
+ <?php
486
+ if(pmpro_getCurrencyPosition() == "left")
487
+ echo $pmpro_currency_symbol;
488
+ ?>
489
+ <input name="trial_amount" type="text" size="20" value="<?php echo esc_attr( pmpro_filter_price_for_text_field( $level->trial_amount ) );?>" />
490
+ <?php
491
+ if(pmpro_getCurrencyPosition() == "right")
492
+ echo $pmpro_currency_symbol;
493
+ ?>
494
+ <small><?php _e('for the first', 'paid-memberships-pro' );?></small>
495
+ <input name="trial_limit" type="text" size="10" value="<?php echo esc_attr($level->trial_limit);?>" />
496
+ <small><?php _e('subscription payments', 'paid-memberships-pro' );?>.</small>
497
+ <?php if($gateway == "stripe") { ?>
498
+ <br /><small>
499
+ <strong <?php if(!empty($pmpro_stripe_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Stripe integration currently does not support trial amounts greater than $0.', 'paid-memberships-pro' );?></strong>
500
+ </small>
501
+ <?php } elseif($gateway == "braintree") { ?>
502
+ <br /><small>
503
+ <strong <?php if(!empty($pmpro_braintree_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Braintree integration currently does not support trial amounts greater than $0.', 'paid-memberships-pro' );?></strong>
504
+ </small>
505
+ <?php } elseif($gateway == "payflowpro") { ?>
506
+ <br /><small>
507
+ <strong <?php if(!empty($pmpro_payflow_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Payflow integration currently does not support trial amounts greater than $0.', 'paid-memberships-pro' );?></strong>
508
+ </small>
509
+ <?php } ?>
510
+ </td>
511
+ </tr>
512
+
513
+ </tbody>
514
+ </table>
515
+
516
+ <h3 class="topborder"><?php _e('Other Settings', 'paid-memberships-pro' );?></h3>
517
+ <table class="form-table">
518
+ <tbody>
519
+ <tr>
520
+ <th scope="row" valign="top"><label><?php _e('Disable New Signups', 'paid-memberships-pro' );?>:</label></th>
521
+ <td><input id="disable_signups" name="disable_signups" type="checkbox" value="yes" <?php if($level->id && !$level->allow_signups) { ?>checked="checked"<?php } ?> /> <label for="disable_signups"><?php _e('Check to hide this level from the membership levels page and disable registration.', 'paid-memberships-pro' );?></label></td>
522
+ </tr>
523
+
524
+ <tr>
525
+ <th scope="row" valign="top"><label><?php _e('Membership Expiration', 'paid-memberships-pro' );?>:</label></th>
526
+ <td><input id="expiration" name="expiration" type="checkbox" value="yes" <?php if(pmpro_isLevelExpiring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery('#expiration').is(':checked')) { jQuery('.expiration_info').show(); } else { jQuery('.expiration_info').hide();}" /> <label for="expiration"><?php _e('Check this to set when membership access expires.', 'paid-memberships-pro' );?></label></a></td>
527
+ </tr>
528
+
529
+ <tr class="expiration_info" <?php if(!pmpro_isLevelExpiring($level)) {?>style="display: none;"<?php } ?>>
530
+ <th scope="row" valign="top"><label for="billing_amount"><?php _e('Expires In', 'paid-memberships-pro' );?>:</label></th>
531
+ <td>
532
+ <input id="expiration_number" name="expiration_number" type="text" size="10" value="<?php echo esc_attr($level->expiration_number);?>" />
533
+ <select id="expiration_period" name="expiration_period">
534
+ <?php
535
+ $cycles = array( __('Day(s)', 'paid-memberships-pro' ) => 'Day', __('Week(s)', 'paid-memberships-pro' ) => 'Week', __('Month(s)', 'paid-memberships-pro' ) => 'Month', __('Year(s)', 'paid-memberships-pro' ) => 'Year' );
536
+ foreach ( $cycles as $name => $value ) {
537
+ echo "<option value='$value'";
538
+ if ( $level->expiration_period == $value ) echo " selected='selected'";
539
+ echo ">$name</option>";
540
+ }
541
+ ?>
542
+ </select>
543
+ <br /><small><?php _e('Set the duration of membership access. Note that the any future payments (recurring subscription, if any) will be cancelled when the membership expires.', 'paid-memberships-pro' );?></small>
544
+
545
+ <div id="pmpro_expiration_warning" style="display: none;" class="notice error inline">
546
+ <p><?php printf( __( 'WARNING: This level is set with both a recurring billing amount and an expiration date. You only need to set one of these unless you really want this membership to expire after a certain number of payments. For more information, <a target="_blank" href="%s">see our post here</a>.', 'paid-memberships-pro' ), 'https://www.paidmembershipspro.com/important-notes-on-recurring-billing-and-expiration-dates-for-membership-levels/' ); ?></p>
547
+ </div>
548
+ <script>
549
+ jQuery(document).ready(function() {
550
+ function pmpro_expirationWarningCheck() {
551
+ if( jQuery('#recurring:checked').length && jQuery('#expiration:checked').length) {
552
+ jQuery('#pmpro_expiration_warning').show();
553
+ } else {
554
+ jQuery('#pmpro_expiration_warning').hide();
555
+ }
556
+ }
557
+
558
+ pmpro_expirationWarningCheck();
559
+
560
+ jQuery('#recurring,#expiration').change(function() { pmpro_expirationWarningCheck(); });
561
+ });
562
+ </script>
563
+ </td>
564
+ </tr>
565
+ </tbody>
566
+ </table>
567
+
568
+ <?php do_action("pmpro_membership_level_after_other_settings"); ?>
569
+
570
+ <h3 class="topborder"><?php _e('Content Settings', 'paid-memberships-pro' );?></h3>
571
+ <table class="form-table">
572
+ <tbody>
573
+ <tr class="membership_categories">
574
+ <th scope="row" valign="top"><label><?php _e('Categories', 'paid-memberships-pro' );?>:</label></th>
575
+ <td>
576
+ <?php pmpro_listCategories(0, $level->categories); ?>
577
+ </td>
578
+ </tr>
579
+ </tbody>
580
+ </table>
581
+ <p class="submit topborder">
582
+ <input name="save" type="submit" class="button-primary" value="<?php _e('Save Level', 'paid-memberships-pro' ); ?>" />
583
+ <input name="cancel" type="button" value="<?php _e('Cancel', 'paid-memberships-pro' ); ?>" onclick="location.href='<?php echo add_query_arg( 'page', 'pmpro-membershiplevels' , get_admin_url(NULL, '/admin.php') ); ?>';" />
584
+ </p>
585
+ </form>
586
+ </div>
587
+
588
+ <?php
589
+ }
590
+ else
591
+ {
592
+ $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ";
593
+ if($s)
594
+ $sqlQuery .= "WHERE name LIKE '%$s%' ";
595
+ $sqlQuery .= "ORDER BY id ASC";
596
+
597
+ $levels = $wpdb->get_results($sqlQuery, OBJECT);
598
+
599
+ if(empty($_REQUEST['s']) && !empty($pmpro_level_order)) {
600
+ //reorder levels
601
+ $order = explode(',', $pmpro_level_order);
602
+
603
+ //put level ids in their own array
604
+ $level_ids = array();
605
+ foreach($levels as $level)
606
+ $level_ids[] = $level->id;
607
+
608
+ //remove levels from order if they are gone
609
+ foreach($order as $key => $level_id)
610
+ if(!in_array($level_id, $level_ids))
611
+ unset($order[$key]);
612
+
613
+ //add levels to the end if they aren't in the order array
614
+ foreach($level_ids as $level_id)
615
+ if(!in_array($level_id, $order))
616
+ $order[] = $level_id;
617
+
618
+ //remove dupes
619
+ $order = array_unique($order);
620
+
621
+ //save the level order
622
+ pmpro_setOption('level_order', implode(',', $order));
623
+
624
+ //reorder levels here
625
+ $reordered_levels = array();
626
+ foreach ($order as $level_id) {
627
+ foreach ($levels as $level) {
628
+ if ($level_id == $level->id)
629
+ $reordered_levels[] = $level;
630
+ }
631
+ }
632
+ }
633
+ else
634
+ $reordered_levels = $levels;
635
+
636
+ if(empty($_REQUEST['s']) && count($reordered_levels) > 1)
637
+ {
638
+ ?>
639
+ <script>
640
+ jQuery(document).ready(function($) {
641
+
642
+ // Return a helper with preserved width of cells
643
+ // from http://www.foliotek.com/devblog/make-table-rows-sortable-using-jquery-ui-sortable/
644
+ var fixHelper = function(e, ui) {
645
+ ui.children().each(function() {
646
+ $(this).width($(this).width());
647
+ });
648
+ return ui;
649
+ };
650
+
651
+ $("table.membership-levels tbody").sortable({
652
+ helper: fixHelper,
653
+ placeholder: 'testclass',
654
+ forcePlaceholderSize: true,
655
+ update: update_level_order
656
+ });
657
+
658
+ function update_level_order(event, ui) {
659
+ level_order = [];
660
+ $("table.membership-levels tbody tr").each(function() {
661
+ $(this).removeClass('alternate');
662
+ level_order.push(parseInt( $("td:first", this).text()));
663
+ });
664
+
665
+ //update styles
666
+ $("table.membership-levels tbody tr:odd").each(function() {
667
+ $(this).addClass('alternate');
668
+ });
669
+
670
+ data = {
671
+ action: 'pmpro_update_level_order',
672
+ level_order: level_order
673
+ };
674
+
675
+ $.post(ajaxurl, data, function(response) {
676
+ });
677
+ }
678
+ });
679
+ </script>
680
+ <?php
681
+ }
682
+ ?>
683
+
684
+ <?php if( count( $reordered_levels ) === 0 ) { ?>
685
+ <div class="pmpro-new-install">
686
+ <h2><?php echo esc_attr_e( 'No Membership Levels Found', 'paid-memberships-pro' ); ?></h2>
687
+ <a href="<?php echo esc_url( admin_url( 'admin.php?page=pmpro-membershiplevels&edit=-1' ) ); ?>" class="button-primary"><?php echo esc_attr_e( 'Create a Membership Level', 'paid-memberships-pro' ); ?></a>
688
+ <a href="<?php echo esc_url( 'https://www.paidmembershipspro.com/documentation/initial-plugin-setup/step-1-add-new-membership-level/' ); ?>" target="_blank" class="button"><?php echo esc_attr_e( 'Video: Membership Levels', 'paid-memberships-pro' ); ?></a>
689
+ </div> <!-- end pmpro-new-install -->
690
+ <?php } else { ?>
691
+
692
+ <form id="posts-filter" method="get" action="">
693
+ <p class="search-box">
694
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search Levels', 'paid-memberships-pro' );?>:</label>
695
+ <input type="hidden" name="page" value="pmpro-membershiplevels" />
696
+ <input id="post-search-input" type="text" value="<?php echo esc_attr($s); ?>" name="s" size="30" />
697
+ <input class="button" type="submit" value="<?php _e('Search Levels', 'paid-memberships-pro' );?>" id="search-submit" />
698
+ </p>
699
+ </form>
700
+ <h2><?php _e('Membership Levels', 'paid-memberships-pro' );?> <a href="<?php echo add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'edit' => -1 ), get_admin_url(null, 'admin.php' ) ); ?>" class="add-new-h2"><?php _e('Add New Level', 'paid-memberships-pro' );?></a></h2>
701
+
702
+ <?php if(empty($_REQUEST['s']) && count($reordered_levels) > 1) { ?>
703
+ <p><?php _e('Drag and drop membership levels to reorder them on the Levels page.', 'paid-memberships-pro' ); ?></p>
704
+ <?php } ?>
705
+
706
+ <?php
707
+ //going to capture the output of this table so we can filter it
708
+ ob_start();
709
+ ?>
710
+ <table class="widefat membership-levels">
711
+ <thead>
712
+ <tr>
713
+ <th><?php _e('ID', 'paid-memberships-pro' );?></th>
714
+ <th><?php _e('Name', 'paid-memberships-pro' );?></th>
715
+ <th><?php _e('Billing Details', 'paid-memberships-pro' );?></th>
716
+ <th><?php _e('Expiration', 'paid-memberships-pro' );?></th>
717
+ <th><?php _e('Allow Signups', 'paid-memberships-pro' );?></th>
718
+ <th></th>
719
+ </tr>
720
+ </thead>
721
+ <tbody>
722
+ <?php
723
+ $count = 0;
724
+ foreach($reordered_levels as $level)
725
+ {
726
+ ?>
727
+ <tr class="<?php if($count++ % 2 == 1) { ?>alternate<?php } ?> <?php if(!$level->allow_signups) { ?>pmpro_gray<?php } ?> <?php if(!pmpro_checkLevelForStripeCompatibility($level) || !pmpro_checkLevelForBraintreeCompatibility($level) || !pmpro_checkLevelForPayflowCompatibility($level) || !pmpro_checkLevelForTwoCheckoutCompatibility($level)) { ?>pmpro_error<?php } ?>">
728
+ <td><?php echo $level->id?></td>
729
+ <td class="level_name"><a href="<?php echo add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'edit' => $level->id ), admin_url( 'admin.php' ) ); ?>"><?php esc_attr_e( $level->name ); ?></a></td>
730
+ <td>
731
+ <?php if(pmpro_isLevelFree($level)) { ?>
732
+ <?php _e('FREE', 'paid-memberships-pro' );?>
733
+ <?php } else { ?>
734
+ <?php echo str_replace( 'The price for membership is', '', pmpro_getLevelCost($level)); ?>
735
+ <?php } ?>
736
+ </td>
737
+ <td>
738
+ <?php if(!pmpro_isLevelExpiring($level)) { ?>
739
+ --
740
+ <?php } else { ?>
741
+ <?php _e('After', 'paid-memberships-pro' );?> <?php echo $level->expiration_number?> <?php echo sornot($level->expiration_period,$level->expiration_number)?>
742
+ <?php } ?>
743
+ </td>
744
+ <td><?php if($level->allow_signups) { ?><a href="<?php echo add_query_arg( 'level', $level->id, pmpro_url("checkout") );?>"><?php _e('Yes', 'paid-memberships-pro' );?></a><?php } else { ?><?php _e('No', 'paid-memberships-pro' );?><?php } ?></td>
745
+
746
+ <td><a title="<?php _e('edit', 'paid-memberships-pro' ); ?>" href="<?php echo add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'edit' => $level->id ), admin_url('admin.php' ) ); ?>" class="button-primary"><?php _e('edit', 'paid-memberships-pro' ); ?></a>&nbsp;<a title="<?php _e('copy', 'paid-memberships-pro' ); ?>" href="<?php echo add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'edit' => -1, 'copy' => $level->id ), admin_url( 'admin.php' ) ); ?>" class="button-secondary"><?php _e('copy', 'paid-memberships-pro' ); ?></a>&nbsp;<a title="<?php _e('delete', 'paid-memberships-pro' ); ?>" href="javascript:askfirst('<?php echo str_replace("'", "\'", sprintf(__("Are you sure you want to delete membership level %s? All subscriptions will be cancelled.", 'paid-memberships-pro' ), $level->name));?>', '<?php echo wp_nonce_url(add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'action' => 'delete_membership_level', 'deleteid' => $level->id ), admin_url( 'admin.php' ) ), 'delete_membership_level', 'pmpro_membershiplevels_nonce'); ?>'); void(0);" class="button-secondary"><?php _e('delete', 'paid-memberships-pro' ); ?></a></td>
747
+ </tr>
748
+ <?php
749
+ }
750
+ ?>
751
+ </tbody>
752
+ </table>
753
+
754
+ <?php
755
+ $table_html = ob_get_clean();
756
+
757
+ /**
758
+ * Filter to change the Membership Levels table
759
+ * @since 1.8.10
760
+ *
761
+ * @param string $table_html HTML of the membership levels table
762
+ * @param array $reordered_levels Array of membership levels
763
+ */
764
+ $table_html = apply_filters('pmpro_membership_levels_table', $table_html, $reordered_levels);
765
+
766
+ echo $table_html;
767
+ }
768
+ ?>
769
+
770
+ <?php } ?>
771
+
772
+ <?php
773
+ require_once(dirname(__FILE__) . "/admin_footer.php");
adminpages/reports/sales.php CHANGED
@@ -378,8 +378,8 @@ function pmpro_report_sales_page()
378
var data = google.visualization.arrayToDataTable([
379
[
380
{ label: '<?php echo $date_function;?>' },
381
{ label: '<?php _e( 'Average*', 'paid-memberships-pro' );?>' },
382
- { label: '<?php echo ucwords($type);?>' }
383
],
384
<?php foreach($cols as $date => $value) { ?>
385
['<?php
@@ -387,7 +387,7 @@ function pmpro_report_sales_page()
387
echo date_i18n("M", mktime(0,0,0,$date,2));
388
} else {
389
echo $date;
390
- } ?>', <?php echo $value;?>, <?php echo $average;?>],
391
<?php } ?>
392
]);
393
@@ -419,13 +419,25 @@ function pmpro_report_sales_page()
419
420
<?php
421
if($type != "sales")
422
- {
423
- if(pmpro_getCurrencyPosition() == "right")
424
$position = "suffix";
425
- else
426
$position = "prefix";
427
?>
428
- var formatter = new google.visualization.NumberFormat({<?php echo $position;?>: '<?php echo html_entity_decode($pmpro_currency_symbol);?>'});
429
formatter.format(data, 1);
430
formatter.format(data, 2);
431
<?php
378
var data = google.visualization.arrayToDataTable([
379
[
380
{ label: '<?php echo $date_function;?>' },
381
+ { label: '<?php echo ucwords($type);?>' },
382
{ label: '<?php _e( 'Average*', 'paid-memberships-pro' );?>' },
383
],
384
<?php foreach($cols as $date => $value) { ?>
385
['<?php
387
echo date_i18n("M", mktime(0,0,0,$date,2));
388
} else {
389
echo $date;
390
+ } ?>', <?php echo pmpro_round_price( $value );?>, <?php echo pmpro_round_price( $average );?>],
391
<?php } ?>
392
]);
393
419
420
<?php
421
if($type != "sales")
422
+ {
423
+ $decimals = isset( $pmpro_currencies[ $pmpro_currency ]['decimals'] ) ? (int) $pmpro_currencies[ $pmpro_currency ]['decimals'] : 2;
424
+
425
+ $decimal_separator = isset( $pmpro_currencies[ $pmpro_currency ]['decimal_separator'] ) ? $pmpro_currencies[ $pmpro_currency ]['decimal_separator'] : '.';
426
+
427
+ $thousands_separator = isset( $pmpro_currencies[ $pmpro_currency ]['thousands_separator'] ) ? $pmpro_currencies[ $pmpro_currency ]['thousands_separator'] : ',';
428
+
429
+ if ( pmpro_getCurrencyPosition() == 'right' ) {
430
$position = "suffix";
431
+ } else {
432
$position = "prefix";
433
+ }
434
?>
435
+ var formatter = new google.visualization.NumberFormat({
436
+ <?php echo $position;?>: '<?php echo html_entity_decode($pmpro_currency_symbol); ?>',
437
+ 'decimalSymbol': '<?php echo html_entity_decode( $decimal_separator ); ?>',
438
+ 'fractionDigits': <?php echo intval( $decimals ); ?>,
439
+ 'groupingSymbol': '<?php echo html_entity_decode( $thousands_separator ); ?>',
440
+ });
441
formatter.format(data, 1);
442
formatter.format(data, 2);
443
<?php
classes/class.memberorder.php CHANGED
@@ -415,7 +415,52 @@
415
{
416
$this->membership_level = $wpdb->get_row("SELECT l.* FROM $wpdb->pmpro_membership_levels l WHERE l.id = '" . $this->membership_id . "' LIMIT 1");
417
}
418
419
return $this->membership_level;
420
}
421
415
{
416
$this->membership_level = $wpdb->get_row("SELECT l.* FROM $wpdb->pmpro_membership_levels l WHERE l.id = '" . $this->membership_id . "' LIMIT 1");
417
}
418
+
419
+ // Round prices to avoid extra decimals.
420
+ if( ! empty( $this->membership_level ) ) {
421
+ $this->membership_level->initial_payment = pmpro_round_price( $this->membership_level->initial_payment );
422
+ $this->membership_level->billing_amount = pmpro_round_price( $this->membership_level->billing_amount );
423
+ $this->membership_level->trial_amount = pmpro_round_price( $this->membership_level->trial_amount );
424
+ }
425
+
426
+ return $this->membership_level;
427
+ }
428
+
429
+ /**
430
+ * Get a membership level object at checkout
431
+ * for the level associated with this order.
432
+ *
433
+ * @since 2.0.2
434
+ * @param bool $force If true, it will reset the property.
435
+ *
436
+ */
437
+ function getMembershipLevelAtCheckout($force = false) {
438
+ global $pmpro_level;
439
440
+ if( ! empty( $this->membership_level ) && empty( $force ) ) {
441
+ return $this->membership_level;
442
+ }
443
+
444
+ // If for some reason, we haven't setup pmpro_level yet, do that.
445
+ if ( empty( $pmpro_level ) ) {
446
+ $pmpro_level = pmpro_getLevelAtCheckout();
447
+ }
448
+
449
+ // Set the level to the checkout level global.
450
+ $this->membership_level = $pmpro_level;
451
+
452
+ // Fix the membership level id.
453
+ if(!empty( $this->membership_level) && !empty($this->membership_level->level_id)) {
454
+ $this->membership_level->id = $this->membership_level->level_id;
455
+ }
456
+
457
+ // Round prices to avoid extra decimals.
458
+ if( ! empty( $this->membership_level ) ) {
459
+ $this->membership_level->initial_payment = pmpro_round_price( $this->membership_level->initial_payment );
460
+ $this->membership_level->billing_amount = pmpro_round_price( $this->membership_level->billing_amount );
461
+ $this->membership_level->trial_amount = pmpro_round_price( $this->membership_level->trial_amount );
462
+ }
463
+
464
return $this->membership_level;
465
}
466
classes/gateways/class.pmprogateway_paypalexpress.php CHANGED
@@ -323,16 +323,15 @@
323
$morder->membership_id = $pmpro_level->id;
324
$morder->membership_name = $pmpro_level->name;
325
$morder->discount_code = $discount_code;
326
- $morder->InitialPayment = $pmpro_level->initial_payment;
327
- $morder->PaymentAmount = $pmpro_level->billing_amount;
328
$morder->ProfileStartDate = date_i18n("Y-m-d") . "T0:0:0";
329
$morder->BillingPeriod = $pmpro_level->cycle_period;
330
$morder->BillingFrequency = $pmpro_level->cycle_number;
331
$morder->Email = $bemail;
332
333
- //set up level var
334
- $morder->getMembershipLevel();
335
- $morder->membership_level = apply_filters("pmpro_checkout_level", $morder->membership_level);
336
337
//tax
338
$morder->subtotal = $morder->InitialPayment;
@@ -345,7 +344,7 @@
345
$morder->TrialBillingPeriod = $pmpro_level->cycle_period;
346
$morder->TrialBillingFrequency = $pmpro_level->cycle_number;
347
$morder->TrialBillingCycles = $pmpro_level->trial_limit;
348
- $morder->TrialAmount = $pmpro_level->trial_amount;
349
}
350
351
if($morder->confirm())
@@ -402,7 +401,7 @@
402
* Repurposed in v2.0. The old process() method is now confirm().
403
*/
404
function process(&$order)
405
- {
406
$order->payment_type = "PayPal Express";
407
$order->cardtype = "";
408
$order->ProfileStartDate = date_i18n("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod)) . "T0:0:0";
323
$morder->membership_id = $pmpro_level->id;
324
$morder->membership_name = $pmpro_level->name;
325
$morder->discount_code = $discount_code;
326
+ $morder->InitialPayment = pmpro_round_price( $pmpro_level->initial_payment );
327
+ $morder->PaymentAmount = pmpro_round_price( $pmpro_level->billing_amount );
328
$morder->ProfileStartDate = date_i18n("Y-m-d") . "T0:0:0";
329
$morder->BillingPeriod = $pmpro_level->cycle_period;
330
$morder->BillingFrequency = $pmpro_level->cycle_number;
331
$morder->Email = $bemail;
332
333
+ //setup level var
334
+ $morder->getMembershipLevelAtCheckout();
335
336
//tax
337
$morder->subtotal = $morder->InitialPayment;
344
$morder->TrialBillingPeriod = $pmpro_level->cycle_period;
345
$morder->TrialBillingFrequency = $pmpro_level->cycle_number;
346
$morder->TrialBillingCycles = $pmpro_level->trial_limit;
347
+ $morder->TrialAmount = pmpro_round_price( $pmpro_level->trial_amount );
348
}
349
350
if($morder->confirm())
401
* Repurposed in v2.0. The old process() method is now confirm().
402
*/
403
function process(&$order)
404
+ {
405
$order->payment_type = "PayPal Express";
406
$order->cardtype = "";
407
$order->ProfileStartDate = date_i18n("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod)) . "T0:0:0";
includes/currencies.php CHANGED
@@ -1,103 +1,93 @@
1
<?php
2
- //thanks jigoshop
3
global $pmpro_currencies, $pmpro_default_currency;
4
- $pmpro_default_currency = apply_filters("pmpro_default_currency", "USD");
5
6
- function pmpro_euro_position_from_locale($position = 'right')
7
- {
8
- $locale = get_locale();
9
- if(strpos($locale, 'en_') === 0)
10
- {
11
- $position = 'left';
12
- }
13
- return $position;
14
- }
15
16
$pmpro_currencies = array(
17
- 'USD' => __('US Dollars (&#36;)', 'paid-memberships-pro' ),
18
- 'EUR' => array(
19
- 'name' => __('Euros (&euro;)', 'paid-memberships-pro' ),
20
- 'symbol' => '&euro;',
21
- 'position' => apply_filters("pmpro_euro_position", pmpro_euro_position_from_locale())
22
- ),
23
- 'GBP' => array(
24
- 'name' => __('Pounds Sterling (&pound;)', 'paid-memberships-pro' ),
25
- 'symbol' => '&pound;',
26
- 'position' => 'left'
27
- ),
28
- 'ARS' => __('Argentine Peso (&#36;)', 'paid-memberships-pro' ),
29
- 'AUD' => __('Australian Dollars (&#36;)', 'paid-memberships-pro' ),
30
- 'BRL' => array(
31
- 'name' => __('Brazilian Real (R&#36;)', 'paid-memberships-pro' ),
32
- 'symbol' => 'R&#36;',
33
- 'position' => 'left'
34
- ),
35
- 'CAD' => __('Canadian Dollars (&#36;)', 'paid-memberships-pro' ),
36
- 'CNY' => __('Chinese Yuan', 'paid-memberships-pro' ),
37
- 'CZK' => array(
38
- 'name' => __('Czech Koruna', 'paid-memberships-pro' ),
39
- 'decimals' => '0',
40
- 'thousands_separator' => '&nbsp;',
41
- 'decimal_separator' => ',',
42
- 'symbol' => '&nbsp;Kč',
43
- 'position' => 'right',
44
- ),
45
- 'DKK' => array(
46
- 'name' =>__('Danish Krone', 'paid-memberships-pro' ),
47
- 'decimals' => '2',
48
- 'thousands_separator' => '&nbsp;',
49
- 'decimal_separator' => ',',
50
- 'symbol' => 'DKK&nbsp;',
51
- 'position' => 'left',
52
- ),
53
- 'HKD' => __('Hong Kong Dollar (&#36;)', 'paid-memberships-pro' ),
54
- 'HUF' => __('Hungarian Forint', 'paid-memberships-pro' ),
55
- 'INR' => __('Indian Rupee', 'paid-memberships-pro' ),
56
- 'IDR' => __('Indonesia Rupiah', 'paid-memberships-pro' ),
57
- 'ILS' => __('Israeli Shekel', 'paid-memberships-pro' ),
58
- 'JPY' => array(
59
- 'name' => __('Japanese Yen (&yen;)', 'paid-memberships-pro' ),
60
- 'symbol' => '&yen;',
61
- 'position' => 'right',
62
- 'decimals' => 0,
63
- ),
64
- 'KES' => __('Kenyan Shilling', 'paid-memberships-pro' ),
65
- 'MYR' => __('Malaysian Ringgits', 'paid-memberships-pro' ),
66
- 'MXN' => __('Mexican Peso (&#36;)', 'paid-memberships-pro' ),
67
- 'NGN' => __('Nigerian Naira (&#8358;)', 'paid-memberships-pro' ),
68
- 'NZD' => __('New Zealand Dollar (&#36;)', 'paid-memberships-pro' ),
69
- 'NOK' => __('Norwegian Krone', 'paid-memberships-pro' ),
70
- 'PHP' => __('Philippine Pesos', 'paid-memberships-pro' ),
71
- 'PLN' => __('Polish Zloty', 'paid-memberships-pro' ),
72
- 'RUB' => array(
73
- 'name' => __('Russian Ruble (&#8381;)', 'paid-memberships-pro'),
74
- 'symbol' => '&#8381;',
75
- 'position' => 'right'
76
),
77
- 'SGD' => array(
78
- 'name' => __('Singapore Dollar (&#36;)', 'paid-memberships-pro' ),
79
- 'symbol' => '&#36;',
80
- 'position' => 'right'
81
- ),
82
- 'ZAR' => array(
83
- 'name' => __('South African Rand (R)', 'paid-memberships-pro' ),
84
- 'symbol' => 'R ',
85
- 'position' => 'left'
86
- ),
87
- 'KRW' => array(
88
- 'name' => __('South Korean Won', 'paid-memberships-pro' ),
89
- 'decimals' => 0,
90
- ),
91
- 'SEK' => __('Swedish Krona', 'paid-memberships-pro' ),
92
- 'CHF' => __('Swiss Franc', 'paid-memberships-pro' ),
93
- 'TWD' => __('Taiwan New Dollars', 'paid-memberships-pro' ),
94
- 'THB' => __('Thai Baht', 'paid-memberships-pro' ),
95
- 'TRY' => __('Turkish Lira', 'paid-memberships-pro' ),
96
- 'VND' => array(
97
- 'name' => __('Vietnamese Dong', 'paid-memberships-pro' ),
98
- 'decimals' => 0,
99
- ),
100
- );
101
102
$pmpro_currencies = apply_filters("pmpro_currencies", $pmpro_currencies);
103
@@ -109,4 +99,43 @@
109
'GBP' => __('Pounds Sterling (&pound;)', 'paid-memberships-pro' ),
110
'EUR' => __('Euros (&euro;)', 'paid-memberships-pro' )
111
);
112
- ?>
1
<?php
2
global $pmpro_currencies, $pmpro_default_currency;
3
4
+ $pmpro_default_currency = apply_filters("pmpro_default_currency", "USD");
5
6
$pmpro_currencies = array(
7
+ 'USD' => __('US Dollars (&#36;)', 'paid-memberships-pro' ),
8
+ 'EUR' => array(
9
+ 'name' => __('Euros (&euro;)', 'paid-memberships-pro' ),
10
+ 'symbol' => '&euro;',
11
+ 'position' => apply_filters("pmpro_euro_position", pmpro_euro_position_from_locale())
12
+ ),
13
+ 'GBP' => array(
14
+ 'name' => __('Pounds Sterling (&pound;)', 'paid-memberships-pro' ),
15
+ 'symbol' => '&pound;',
16
+ 'position' => 'left'
17
+ ),
18
+ 'ARS' => __('Argentine Peso (&#36;)', 'paid-memberships-pro' ),
19
+ 'AUD' => __('Australian Dollars (&#36;)', 'paid-memberships-pro' ),
20
+ 'BRL' => array(
21
+ 'name' => __('Brazilian Real (R&#36;)', 'paid-memberships-pro' ),
22
+ 'symbol' => 'R&#36;',
23
+ 'position' => 'left'
24
+ ),
25
+ 'CAD' => __('Canadian Dollars (&#36;)', 'paid-memberships-pro' ),
26
+ 'CNY' => __('Chinese Yuan', 'paid-memberships-pro' ),
27
+ 'CZK' => array(
28
+ 'name' => __('Czech Koruna', 'paid-memberships-pro' ),
29
+ 'decimals' => '0',
30
+ 'thousands_separator' => '&nbsp;',
31
+ 'decimal_separator' => ',',
32
+ 'symbol' => '&nbsp;Kč',
33
+ 'position' => 'right',
34
+ ),
35
+ 'DKK' => array(
36
+ 'name' =>__('Danish Krone', 'paid-memberships-pro' ),
37
+ 'decimals' => '2',
38
+ 'thousands_separator' => '&nbsp;',
39
+ 'decimal_separator' => ',',
40
+ 'symbol' => 'DKK&nbsp;',
41
+ 'position' => 'left',
42
+ ),
43
+ 'HKD' => __('Hong Kong Dollar (&#36;)', 'paid-memberships-pro' ),
44
+ 'HUF' => __('Hungarian Forint', 'paid-memberships-pro' ),
45
+ 'INR' => __('Indian Rupee', 'paid-memberships-pro' ),
46
+ 'IDR' => __('Indonesia Rupiah', 'paid-memberships-pro' ),
47
+ 'ILS' => __('Israeli Shekel', 'paid-memberships-pro' ),
48
+ 'JPY' => array(
49
+ 'name' => __('Japanese Yen (&yen;)', 'paid-memberships-pro' ),
50
+ 'symbol' => '&yen;',
51
+ 'position' => 'right',
52
+ 'decimals' => 0,
53
),
54
+ 'KES' => __('Kenyan Shilling', 'paid-memberships-pro' ),
55
+ 'MYR' => __('Malaysian Ringgits', 'paid-memberships-pro' ),
56
+ 'MXN' => __('Mexican Peso (&#36;)', 'paid-memberships-pro' ),
57
+ 'NGN' => __('Nigerian Naira (&#8358;)', 'paid-memberships-pro' ),
58
+ 'NZD' => __('New Zealand Dollar (&#36;)', 'paid-memberships-pro' ),
59
+ 'NOK' => __('Norwegian Krone', 'paid-memberships-pro' ),
60
+ 'PHP' => __('Philippine Pesos', 'paid-memberships-pro' ),
61
+ 'PLN' => __('Polish Zloty', 'paid-memberships-pro' ),
62
+ 'RUB' => array(
63
+ 'name' => __('Russian Ruble (&#8381;)', 'paid-memberships-pro'),
64
+ 'symbol' => '&#8381;',
65
+ 'position' => 'right'
66
+ ),
67
+ 'SGD' => array(
68
+ 'name' => __('Singapore Dollar (&#36;)', 'paid-memberships-pro' ),
69
+ 'symbol' => '&#36;',
70
+ 'position' => 'right'
71
+ ),
72
+ 'ZAR' => array(
73
+ 'name' => __('South African Rand (R)', 'paid-memberships-pro' ),
74
+ 'symbol' => 'R ',
75
+ 'position' => 'left'
76
+ ),
77
+ 'KRW' => array(
78
+ 'name' => __('South Korean Won', 'paid-memberships-pro' ),
79
+ 'decimals' => 0,
80
+ ),
81
+ 'SEK' => __('Swedish Krona', 'paid-memberships-pro' ),
82
+ 'CHF' => __('Swiss Franc', 'paid-memberships-pro' ),
83
+ 'TWD' => __('Taiwan New Dollars', 'paid-memberships-pro' ),
84
+ 'THB' => __('Thai Baht', 'paid-memberships-pro' ),
85
+ 'TRY' => __('Turkish Lira', 'paid-memberships-pro' ),
86
+ 'VND' => array(
87
+ 'name' => __('Vietnamese Dong', 'paid-memberships-pro' ),
88
+ 'decimals' => 0,
89
+ ),
90
+ );
91
92
$pmpro_currencies = apply_filters("pmpro_currencies", $pmpro_currencies);
93
99
'GBP' => __('Pounds Sterling (&pound;)', 'paid-memberships-pro' ),
100
'EUR' => __('Euros (&euro;)', 'paid-memberships-pro' )
101
);
102
+
103
+ /**
104
+ * Get the Euro position based on locale.
105
+ * English uses left, others use right.
106
+ */
107
+ function pmpro_euro_position_from_locale($position = 'right') {
108
+ $locale = get_locale();
109
+ if(strpos($locale, 'en_') === 0) {
110
+ $position = 'left';
111
+ }
112
+ return $position;
113
+ }
114
+
115
+ /**
116
+ * Get an array of data for a specified currency.
117
+ * Defaults to the current currency set in the global.
118
+ */
119
+ function pmpro_get_currency( $currency = null ) {
120
+ global $pmpro_currency, $pmpro_currencies;
121
+
122
+ // Defaults
123
+ $currency_array = array(
124
+ 'name' =>__('US Dollars (&#36;)', 'paid-memberships-pro' ),
125
+ 'decimals' => '2',
126
+ 'thousands_separator' => ',',
127
+ 'decimal_separator' => '.',
128
+ 'symbol' => '&#36;',
129
+ 'position' => 'left',
130
+ );
131
+
132
+ if ( ! empty( $pmpro_currency ) ) {
133
+ if ( is_array( $pmpro_currencies[$pmpro_currency] ) ) {
134
+ $currency_array = array_merge( $currency_array, $pmpro_currencies[$pmpro_currency] );
135
+ } else {
136
+ $currency_array['name'] = $pmpro_currencies[$pmpro_currency];
137
+ }
138
+ }
139
+
140
+ return $currency_array;
141
+ }
includes/functions.php CHANGED
@@ -1726,6 +1726,19 @@ function pmpro_getMembershipLevelForUser( $user_id = null, $force = false ) {
1726
if ( empty( $all_membership_levels[ $user_id ] ) ) {
1727
$all_membership_levels[ $user_id ] = false;
1728
}
1729
1730
/**
1731
* pmpro_get_membership_level_for_user filter.
@@ -1791,6 +1804,16 @@ function pmpro_getMembershipLevelsForUser( $user_id = null, $include_inactive =
1791
WHERE mu.user_id = $user_id" . ( $include_inactive ? '' : " AND mu.status = 'active'
1792
GROUP BY ID" )
1793
);
1794
/**
1795
* pmpro_get_membership_levels_for_user filter.
1796
*
@@ -1863,7 +1886,6 @@ function pmpro_getLevel( $level ) {
1863
} else {
1864
global $wpdb;
1865
$pmpro_levels[ $level_id ] = $wpdb->get_row( "SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . $level_id . "' LIMIT 1" );
1866
- return $pmpro_levels[ $level_id ];
1867
}
1868
} else {
1869
global $wpdb;
@@ -1875,9 +1897,17 @@ function pmpro_getLevel( $level ) {
1875
return false;
1876
}
1877
1878
- $pmpro_levels[ $level_id ] = $level_obj;
1879
- return $pmpro_levels[ $level_id ];
1880
}
1881
}
1882
1883
/*
@@ -1904,6 +1934,9 @@ function pmpro_getAllLevels( $include_hidden = false, $force = false ) {
1904
// lets put them into an array where the key is the id of the level
1905
$pmpro_levels = array();
1906
foreach ( $raw_levels as $raw_level ) {
1907
$pmpro_levels[ $raw_level->id ] = $raw_level;
1908
}
1909
@@ -2003,12 +2036,12 @@ function pmpro_getCheckoutButton( $level_id, $button_text = null, $classes = nul
2003
'!!name!!' => $level->name,
2004
'!!description!!' => $level->description,
2005
'!!confirmation!!' => $level->confirmation,
2006
- '!!initial_payment!!' => $level->initial_payment,
2007
- '!!billing_amount!!' => $level->billing_amount,
2008
'!!cycle_number!!' => $level->cycle_number,
2009
'!!cycle_period!!' => $level->cycle_period,
2010
'!!billing_limit!!' => $level->billing_limit,
2011
- '!!trial_amount!!' => $level->trial_amount,
2012
'!!trial_limit!!' => $level->trial_limit,
2013
'!!expiration_number!!' => $level->expiration_number,
2014
'!!expiration_period!!' => $level->expiration_period,
@@ -2371,7 +2404,7 @@ function pmpro_is_ready() {
2371
function pmpro_formatPrice( $price ) {
2372
global $pmpro_currency, $pmpro_currency_symbol, $pmpro_currencies;
2373
2374
- // start with the price formatted with two decimals
2375
$formatted = pmpro_round_price( $price );
2376
2377
// settings stored in array?
@@ -2391,7 +2424,8 @@ function pmpro_formatPrice( $price ) {
2391
$formatted = $formatted . $pmpro_currency_symbol;
2392
}
2393
} else {
2394
- $formatted = $pmpro_currency_symbol . $formatted; // default to symbol on the left
2395
}
2396
2397
// filter
@@ -2428,16 +2462,64 @@ function pmpro_round_price( $price, $currency = '' ) {
2428
$currency = $pmpro_currency;
2429
}
2430
2431
- if ( ! empty( $pmpro_currencies[ $currency ] ) && is_array( $pmpro_currencies[ $pmpro_currency ] ) && ! empty( $pmpro_currencies[ $currency ]['decimals'] ) && is_int( $pmpro_currencies[ $currency ]['decimals'] ) ) {
2432
- $decimals = $pmpro_currencies[ $currency ]['decimals'];
2433
}
2434
2435
- $formatted = number_format( round( (double) $price, $decimals ), $decimals );
2436
/**
2437
* Filter for result of pmpro_round_price.
2438
*/
2439
- $formatted = apply_filters( 'pmpro_round_price', $formatted );
2440
- return $formatted;
2441
}
2442
2443
/*
1726
if ( empty( $all_membership_levels[ $user_id ] ) ) {
1727
$all_membership_levels[ $user_id ] = false;
1728
}
1729
+
1730
+ // Round off prices
1731
+ if ( ! empty( $all_membership_levels[$user_id] ) ) {
1732
+ if ( isset( $all_membership_levels[$user_id]->initial_payment ) ) {
1733
+ $all_membership_levels[$user_id]->initial_payment = pmpro_round_price( $all_membership_levels[$user_id]->initial_payment );
1734
+ }
1735
+ if ( isset( $all_membership_levels[$user_id]->billing_amount ) ) {
1736
+ $all_membership_levels[$user_id]->billing_amount = pmpro_round_price( $all_membership_levels[$user_id]->billing_amount );
1737
+ }
1738
+ if ( isset( $all_membership_levels[$user_id]->trial_amount ) ) {
1739
+ $all_membership_levels[$user_id]->trial_amount = pmpro_round_price( $all_membership_levels[$user_id]->trial_amount );
1740
+ }
1741
+ }
1742
1743
/**
1744
* pmpro_get_membership_level_for_user filter.
1804
WHERE mu.user_id = $user_id" . ( $include_inactive ? '' : " AND mu.status = 'active'
1805
GROUP BY ID" )
1806
);
1807
+
1808
+ // Round off prices
1809
+ if ( ! empty( $levels ) ) {
1810
+ foreach( $levels as $key => $level ) {
1811
+ $levels[$key]->initial_payment = pmpro_round_price( $level->initial_payment );
1812
+ $levels[$key]->billing_amount = pmpro_round_price( $level->billing_amount );
1813
+ $levels[$key]->trial_amount = pmpro_round_price( $level->trial_amount );
1814
+ }
1815
+ }
1816
+
1817
/**
1818
* pmpro_get_membership_levels_for_user filter.
1819
*
1886
} else {
1887
global $wpdb;
1888
$pmpro_levels[ $level_id ] = $wpdb->get_row( "SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . $level_id . "' LIMIT 1" );
1889
}
1890
} else {
1891
global $wpdb;
1897
return false;
1898
}
1899
1900
+ $pmpro_levels[ $level_id ] = $level_obj;
1901
+ }
1902
+
1903
+ // Round prices
1904
+ if ( ! empty( $pmpro_levels[ $level_id ] ) ) {
1905
+ $pmpro_levels[ $level_id ]->initial_payment = pmpro_round_price( $pmpro_levels[ $level_id ]->initial_payment );
1906
+ $pmpro_levels[ $level_id ]->billing_amount = pmpro_round_price( $pmpro_levels[ $level_id ]->billing_amount );
1907
+ $pmpro_levels[ $level_id ]->trial_amount = pmpro_round_price( $pmpro_levels[ $level_id ]->trial_amount );
1908
}
1909
+
1910
+ return $pmpro_levels[ $level_id ];
1911
}
1912
1913
/*
1934
// lets put them into an array where the key is the id of the level
1935
$pmpro_levels = array();
1936
foreach ( $raw_levels as $raw_level ) {
1937
+ $raw_level->initial_payment = pmpro_round_price( $raw_level->initial_payment );
1938
+ $raw_level->billing_amount = pmpro_round_price( $raw_level->billing_amount );
1939
+ $raw_level->trial_amount = pmpro_round_price( $raw_level->trial_amount );
1940
$pmpro_levels[ $raw_level->id ] = $raw_level;
1941
}
1942
2036
'!!name!!' => $level->name,
2037
'!!description!!' => $level->description,
2038
'!!confirmation!!' => $level->confirmation,
2039
+ '!!initial_payment!!' => pmpro_filter_price_for_text_field( $level->initial_payment ),
2040
+ '!!billing_amount!!' => pmpro_filter_price_for_text_field( $level->billing_amount ),
2041
'!!cycle_number!!' => $level->cycle_number,
2042
'!!cycle_period!!' => $level->cycle_period,
2043
'!!billing_limit!!' => $level->billing_limit,
2044
+ '!!trial_amount!!' => pmpro_filter_price_for_text_field( $level->trial_amount ),
2045
'!!trial_limit!!' => $level->trial_limit,
2046
'!!expiration_number!!' => $level->expiration_number,
2047
'!!expiration_period!!' => $level->expiration_period,
2404
function pmpro_formatPrice( $price ) {
2405
global $pmpro_currency, $pmpro_currency_symbol, $pmpro_currencies;
2406
2407
+ // start with the rounded price
2408
$formatted = pmpro_round_price( $price );
2409
2410
// settings stored in array?
2424
$formatted = $formatted . $pmpro_currency_symbol;
2425
}
2426
} else {
2427
+ // default to symbol on the left, 2 decimals using . and ,
2428
+ $formatted = $pmpro_currency_symbol . number_format( $formatted, 2 );
2429
}
2430
2431
// filter
2462
$currency = $pmpro_currency;
2463
}
2464
2465
+ if ( ! empty( $pmpro_currencies[ $currency ] )
2466
+ && is_array( $pmpro_currencies[ $pmpro_currency ] )
2467
+ && ! empty( $pmpro_currencies[ $currency ]['decimals'] ) ) {
2468
+ $decimals = intval( $pmpro_currencies[ $currency ]['decimals'] );
2469
}
2470
2471
+ $rounded = round( (double) $price, $decimals );
2472
+
2473
/**
2474
* Filter for result of pmpro_round_price.
2475
*/
2476
+ $rounded = apply_filters( 'pmpro_round_price', $rounded );
2477
+
2478
+ return $rounded;
2479
+ }
2480
+
2481
+ /**
2482
+ * Cast to floast and pad zeroes after the decimal
2483
+ * when editing the price on the edit level page.
2484
+ * Only do this for currency with decimals = 2
2485
+ * Only do this if using . as the decimal separator.
2486
+ * Only pad zeroes to the decimal portion if there is exactly one number
2487
+ * after the decimal.
2488
+ *
2489
+ * @since 2.0.2
2490
+ */
2491
+ function pmpro_filter_price_for_text_field( $price, $currency = null ) {
2492
+ global $pmpro_currency, $pmpro_currencies;
2493
+
2494
+ // We always want to cast to float
2495
+ $price = floatval( $price );
2496
+
2497
+ // Only do this currencies with 2 decimals
2498
+ if ( ! empty( $pmpro_currency )
2499
+ && is_array( $pmpro_currencies[$pmpro_currency] )
2500
+ && isset( $pmpro_currencies[$pmpro_currency]['decimals'] )
2501
+ && $pmpro_currencies[$pmpro_currency]['decimals'] != 2 ) {
2502
+ return $price;
2503
+ }
2504
+
2505
+ // Only do this if using . as the decimal separator.
2506
+ if ( strpos( $price, '.' ) === false ) {
2507
+ return $price;
2508
+ }
2509
+
2510
+ $parts = explode( '.', (string)$price );
2511
+
2512
+ // If no significant decimals, return the whole number.
2513
+ if ( empty( $parts[1] ) ) {
2514
+ return $price;
2515
+ }
2516
+
2517
+ // Do we need an extra 0?
2518
+ if ( strlen( $parts[1] ) == 1 ) {
2519
+ $price = (string)$price . '0';
2520
+ }
2521
+
2522
+ return $price;
2523
}
2524
2525
/*
includes/init.php CHANGED
@@ -117,9 +117,13 @@ function pmpro_init() {
117
}
118
119
//figure out what symbol to show for currency
120
- if(!empty($pmpro_currencies[$pmpro_currency]) && is_array($pmpro_currencies[$pmpro_currency]))
121
- $pmpro_currency_symbol = $pmpro_currencies[$pmpro_currency]['symbol'];
122
- elseif(!empty($pmpro_currencies[$pmpro_currency]) && strpos($pmpro_currencies[$pmpro_currency], "(") !== false)
123
$pmpro_currency_symbol = pmpro_getMatches("/\((.*)\)/", $pmpro_currencies[$pmpro_currency], true);
124
else
125
$pmpro_currency_symbol = $pmpro_currency . " "; //just use the code
117
}
118
119
//figure out what symbol to show for currency
120
+ if(!empty($pmpro_currencies[$pmpro_currency]) && is_array($pmpro_currencies[$pmpro_currency])) {
121
+ if ( isset( $pmpro_currencies[$pmpro_currency]['symbol'] ) ) {
122
+ $pmpro_currency_symbol = $pmpro_currencies[$pmpro_currency]['symbol'];
123
+ } else {
124
+ $pmpro_currency_symbol = '';
125
+ }
126
+ } elseif(!empty($pmpro_currencies[$pmpro_currency]) && strpos($pmpro_currencies[$pmpro_currency], "(") !== false)
127
$pmpro_currency_symbol = pmpro_getMatches("/\((.*)\)/", $pmpro_currencies[$pmpro_currency], true);
128
else
129
$pmpro_currency_symbol = $pmpro_currency . " "; //just use the code
includes/setup.sql CHANGED
@@ -37,12 +37,12 @@ CREATE TABLE `wp_pmpro_discount_codes` (
37
CREATE TABLE `wp_pmpro_discount_codes_levels` (
38
`code_id` int(11) unsigned NOT NULL,
39
`level_id` int(11) unsigned NOT NULL,
40
- `initial_payment` decimal(10,2) NOT NULL DEFAULT '0.00',
41
- `billing_amount` decimal(10,2) NOT NULL DEFAULT '0.00',
42
`cycle_number` int(11) NOT NULL DEFAULT '0',
43
`cycle_period` enum('Day','Week','Month','Year') DEFAULT 'Month',
44
`billing_limit` int(11) NOT NULL COMMENT 'After how many cycles should billing stop?',
45
- `trial_amount` decimal(10,2) NOT NULL DEFAULT '0.00',
46
`trial_limit` int(11) NOT NULL DEFAULT '0',
47
`expiration_number` int(10) unsigned NOT NULL,
48
`expiration_period` enum('Day','Week','Month','Year') NOT NULL,
@@ -78,12 +78,12 @@ CREATE TABLE `wp_pmpro_membership_levels` (
78
`name` varchar(255) NOT NULL,
79
`description` longtext NOT NULL,
80
`confirmation` longtext NOT NULL,
81
- `initial_payment` decimal(10,2) NOT NULL DEFAULT '0.00',
82
- `billing_amount` decimal(10,2) NOT NULL DEFAULT '0.00',
83
`cycle_number` int(11) NOT NULL DEFAULT '0',
84
`cycle_period` enum('Day','Week','Month','Year') DEFAULT 'Month',
85
`billing_limit` int(11) NOT NULL COMMENT 'After how many cycles should billing stop?',
86
- `trial_amount` decimal(10,2) NOT NULL DEFAULT '0.00',
87
`trial_limit` int(11) NOT NULL DEFAULT '0',
88
`allow_signups` tinyint(4) NOT NULL DEFAULT '1',
89
`expiration_number` int(10) unsigned NOT NULL,
@@ -206,12 +206,12 @@ CREATE TABLE `wp_pmpro_memberships_users` (
206
`user_id` int(11) unsigned NOT NULL,
207
`membership_id` int(11) unsigned NOT NULL,
208
`code_id` int(11) unsigned NOT NULL,
209
- `initial_payment` decimal(10,2) NOT NULL,
210
- `billing_amount` decimal(10,2) NOT NULL,
211
`cycle_number` int(11) NOT NULL,
212
`cycle_period` enum('Day','Week','Month','Year') NOT NULL DEFAULT 'Month',
213
`billing_limit` int(11) NOT NULL,
214
- `trial_amount` decimal(10,2) NOT NULL,
215
`trial_limit` int(11) NOT NULL,
216
`status` varchar(20) NOT NULL DEFAULT 'active',
217
`startdate` datetime NOT NULL,
37
CREATE TABLE `wp_pmpro_discount_codes_levels` (
38
`code_id` int(11) unsigned NOT NULL,
39
`level_id` int(11) unsigned NOT NULL,
40
+ `initial_payment` decimal(18,8) NOT NULL DEFAULT '0.00',
41
+ `billing_amount` decimal(18,8) NOT NULL DEFAULT '0.00',
42
`cycle_number` int(11) NOT NULL DEFAULT '0',
43
`cycle_period` enum('Day','Week','Month','Year') DEFAULT 'Month',
44
`billing_limit` int(11) NOT NULL COMMENT 'After how many cycles should billing stop?',
45
+ `trial_amount` decimal(18,8) NOT NULL DEFAULT '0.00',
46
`trial_limit` int(11) NOT NULL DEFAULT '0',
47
`expiration_number` int(10) unsigned NOT NULL,
48
`expiration_period` enum('Day','Week','Month','Year') NOT NULL,
78
`name` varchar(255) NOT NULL,
79
`description` longtext NOT NULL,
80
`confirmation` longtext NOT NULL,
81
+ `initial_payment` decimal(18,8) NOT NULL DEFAULT '0.00',
82
+ `billing_amount` decimal(18,8) NOT NULL DEFAULT '0.00',
83
`cycle_number` int(11) NOT NULL DEFAULT '0',
84
`cycle_period` enum('Day','Week','Month','Year') DEFAULT 'Month',
85
`billing_limit` int(11) NOT NULL COMMENT 'After how many cycles should billing stop?',
86
+ `trial_amount` decimal(18,8) NOT NULL DEFAULT '0.00',
87
`trial_limit` int(11) NOT NULL DEFAULT '0',
88
`allow_signups` tinyint(4) NOT NULL DEFAULT '1',
89
`expiration_number` int(10) unsigned NOT NULL,
206
`user_id` int(11) unsigned NOT NULL,
207
`membership_id` int(11) unsigned NOT NULL,
208
`code_id` int(11) unsigned NOT NULL,
209
+ `initial_payment` decimal(18,8) NOT NULL,
210
+ `billing_amount` decimal(18,8) NOT NULL,
211
`cycle_number` int(11) NOT NULL,
212
`cycle_period` enum('Day','Week','Month','Year') NOT NULL DEFAULT 'Month',
213
`billing_limit` int(11) NOT NULL,
214
+ `trial_amount` decimal(18,8) NOT NULL,
215
`trial_limit` int(11) NOT NULL,
216
`status` varchar(20) NOT NULL DEFAULT 'active',
217
`startdate` datetime NOT NULL,
includes/updates.php CHANGED
@@ -37,7 +37,7 @@ function pmpro_removeUpdate($update) {
37
}
38
39
$updates = array_values($updates);
40
-
41
update_option('pmpro_updates', $updates, 'no');
42
}
43
@@ -59,7 +59,7 @@ function pmpro_wp_ajax_pmpro_updates() {
59
$updates = array_values(get_option('pmpro_updates', array()));
60
61
//run update or let them know we're done
62
- if(!empty($updates)) {
63
//get the latest one and run it
64
if(function_exists($updates[0]))
65
call_user_func($updates[0]);
@@ -69,10 +69,10 @@ function pmpro_wp_ajax_pmpro_updates() {
69
} else {
70
echo "[done]";
71
}
72
-
73
//reset this transient so we know AJAX is running
74
set_transient('pmpro_updates_first_load', false, 60*60*24);
75
-
76
//show progress
77
global $pmpro_updates_progress;
78
if(!empty($pmpro_updates_progress))
@@ -98,7 +98,7 @@ add_action('init', 'pmpro_admin_init_updates_redirect');
98
*/
99
if(pmpro_isUpdateRequired() && (empty($_REQUEST['page']) || $_REQUEST['page'] != 'pmpro-updates'))
100
add_action('admin_notices', 'pmpro_updates_notice');
101
-
102
/*
103
Function to show an admin notice linking to the updates page.
104
*/
@@ -106,7 +106,7 @@ function pmpro_updates_notice() {
106
?>
107
<div class="update-nag">
108
<p>
109
- <?php
110
echo __( 'Paid Memberships Pro Data Update Required', 'paid-memberships-pro' ) . '. ';
111
echo sprintf(__( '(1) <a target="_blank" href="%s">Backup your WordPress database</a></strong> and then (2) <a href="%s">click here to start the update</a>.', 'paid-memberships-pro' ), 'https://codex.wordpress.org/WordPress_Backups#Database_Backup_Instructions', admin_url('admin.php?page=pmpro-updates'));
112
?>
@@ -120,7 +120,7 @@ function pmpro_updates_notice() {
120
*/
121
if(is_admin() && !empty($_REQUEST['updatescomplete']))
122
add_action('admin_notices', 'pmpro_updates_notice_complete');
123
-
124
/*
125
Function to show an admin notice linking to the updates page.
126
*/
@@ -128,10 +128,10 @@ function pmpro_updates_notice_complete() {
128
?>
129
<div class="updated notice notice-success is-dismissible">
130
<p>
131
- <?php
132
echo __('All Paid Memberships Pro updates have finished.', 'paid-memberships-pro' );
133
?>
134
- </p>
135
</div>
136
<?php
137
}
@@ -141,9 +141,9 @@ function pmpro_updates_notice_complete() {
141
* This Add On has been merged into PMPro Core from 2.0
142
* @since 2.0
143
*/
144
- function pmpro_show_notice_for_reports(){
145
-
146
- if( !function_exists( 'pmproblr_fixOptions' ) ) {
147
return;
148
}
149
@@ -153,8 +153,6 @@ function pmpro_show_notice_for_reports(){
153
</div>
154
<?php
155
}
156
- if ( isset($_REQUEST['page']) == 'pmpro-reports') {
157
add_action( 'admin_notices', 'pmpro_show_notice_for_reports', 20 );
158
-
159
}
160
-
37
}
38
39
$updates = array_values($updates);
40
+
41
update_option('pmpro_updates', $updates, 'no');
42
}
43
59
$updates = array_values(get_option('pmpro_updates', array()));
60
61
//run update or let them know we're done
62
+ if(!empty($updates)) {
63
//get the latest one and run it
64
if(function_exists($updates[0]))
65
call_user_func($updates[0]);
69
} else {
70
echo "[done]";
71
}
72
+
73
//reset this transient so we know AJAX is running
74
set_transient('pmpro_updates_first_load', false, 60*60*24);
75
+
76
//show progress
77
global $pmpro_updates_progress;
78
if(!empty($pmpro_updates_progress))
98
*/
99
if(pmpro_isUpdateRequired() && (empty($_REQUEST['page']) || $_REQUEST['page'] != 'pmpro-updates'))
100
add_action('admin_notices', 'pmpro_updates_notice');
101
+
102
/*
103
Function to show an admin notice linking to the updates page.
104
*/
106
?>
107
<div class="update-nag">
108
<p>
109
+ <?php
110
echo __( 'Paid Memberships Pro Data Update Required', 'paid-memberships-pro' ) . '. ';
111
echo sprintf(__( '(1) <a target="_blank" href="%s">Backup your WordPress database</a></strong> and then (2) <a href="%s">click here to start the update</a>.', 'paid-memberships-pro' ), 'https://codex.wordpress.org/WordPress_Backups#Database_Backup_Instructions', admin_url('admin.php?page=pmpro-updates'));
112
?>
120
*/
121
if(is_admin() && !empty($_REQUEST['updatescomplete']))
122
add_action('admin_notices', 'pmpro_updates_notice_complete');
123
+
124
/*
125
Function to show an admin notice linking to the updates page.
126
*/
128
?>
129
<div class="updated notice notice-success is-dismissible">
130
<p>
131
+ <?php
132
echo __('All Paid Memberships Pro updates have finished.', 'paid-memberships-pro' );
133
?>
134
+ </p>
135
</div>
136
<?php
137
}
141
* This Add On has been merged into PMPro Core from 2.0
142
* @since 2.0
143
*/
144
+ function pmpro_show_notice_for_reports() {
145
+
146
+ if( ! function_exists( 'pmproblr_fixOptions' ) || ! current_user_can( 'activate_plugins' ) ) {
147
return;
148
}
149
153
</div>
154
<?php
155
}
156
+ if ( isset( $_REQUEST['page'] ) && $_REQUEST['page'] == 'pmpro-reports' ) {
157
add_action( 'admin_notices', 'pmpro_show_notice_for_reports', 20 );
158
}
languages/email/fr_FR/membership_expired.html CHANGED
@@ -1,6 +1,6 @@
1
<p>Votre adhésion à !!sitename!! a expiré.</p>
2
3
- <p>L'IFAC compte sur vous !</p>
4
5
<p>Voir les niveaux d'adhésion : !!levels_link!!</p>
6
1
<p>Votre adhésion à !!sitename!! a expiré.</p>
2
3
+ <p>Merci pour votre soutien</p>
4
5
<p>Voir les niveaux d'adhésion : !!levels_link!!</p>
6
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: info@paidmembershipspro.com\n"
9
- "POT-Creation-Date: 2018-12-31 10:55-0500\n"
10
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
11
"Last-Translator: \n"
12
"Language-Team: Stranger Studios <info@paidmembershipspro.com>\n"
@@ -36,75 +36,80 @@ msgstr ""
36
#: adminpages/addons.php:81 adminpages/admin_header.php:208
37
#: includes/adminpages.php:55 includes/adminpages.php:192
38
#: adminpages/addons.php:64 adminpages/addons.php:67 adminpages/addons.php:80
39
- #: adminpages/admin_header.php:133 adminpages/admin_header.php:154
40
- #: adminpages/admin_header.php:170 adminpages/admin_header.php:179
41
- #: adminpages/admin_header.php:191 adminpages/admin_header.php:204
42
#: includes/adminpages.php:14 includes/adminpages.php:52
43
- #: includes/adminpages.php:53 includes/adminpages.php:69
44
- #: includes/adminpages.php:135 includes/adminpages.php:142
45
- #: includes/adminpages.php:146 includes/adminpages.php:151
46
msgid "Add Ons"
47
msgstr ""
48
49
#: adminpages/addons.php:88 adminpages/addons.php:71 adminpages/addons.php:74
50
- #: adminpages/addons.php:87
51
#, php-format
52
msgid "Last checked on %s at %s."
53
msgstr ""
54
55
#: adminpages/addons.php:89 adminpages/addons.php:72 adminpages/addons.php:75
56
- #: adminpages/addons.php:88
57
msgid "Check Again"
58
msgstr ""
59
60
#: adminpages/addons.php:93 adminpages/orders.php:1039 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
64
- #: adminpages/orders.php:892 adminpages/orders.php:983
65
msgid "All"
66
msgstr ""
67
68
#: adminpages/addons.php:94 adminpages/addons.php:77 adminpages/addons.php:80
69
- #: adminpages/addons.php:93
70
msgid "Active"
71
msgstr ""
72
73
#: adminpages/addons.php:95 adminpages/addons.php:78 adminpages/addons.php:81
74
- #: adminpages/addons.php:94
75
msgid "Inactive"
76
msgstr ""
77
78
#: adminpages/addons.php:96 adminpages/addons.php:79 adminpages/addons.php:82
79
- #: adminpages/addons.php:95
80
msgid "Update Available"
81
msgstr ""
82
83
#: adminpages/addons.php:97 adminpages/addons.php:80 adminpages/addons.php:83
84
- #: adminpages/addons.php:96
85
msgid "Not Installed"
86
msgstr ""
87
88
#: adminpages/addons.php:110 adminpages/addons.php:93 adminpages/addons.php:96
89