Paid Memberships Pro - Version 1.8.4

Version Description

  • BUG: Fixed the Stripe webhook to work on new orders that are storing the subscription id instead of the customer id in the subscription_transaction_id field. (Thanks, nickd32 on GitHub)
  • BUG: Fixed issue where the name and email address of customers was not being sent to Stripe if existing members checked out while the "show billing address" option was set to false.
  • BUG: Fixed bug where users who checked out with the Braintree Payments gateway could checkout again using their on file credit card if an invalid credit card was entered at checkout the second time. (Thanks, patternsinthecloud)
  • BUG: Updated the 2Checkout PHP API library and fixed some issues with 2Checkout integration.
  • BUG: Fixed issue where custom roles had to have pmpro_membershiplevels capability to view other PMPro-related dashboard pages. (Thanks, squarelines)
  • ENHANCEMENT: Added the ability to order levels on the Levels page by drag and drop in the WordPress admin.
  • ENHANCEMENT: Now hiding tabs in the PMPro settings if a user doesn't have access to that tab (but does have access to other tabs).
  • ENHANCEMENT: Converted all files to unix format and removed trailing whitespace. This has no functional change on the plugin, but helps developers who are contributing. (Thanks, meths on GitHub)
  • ENHANCEMENT: New Danish translation. (Thanks, Morten Stenbk and Frederik Hermund)
Download this release

Release Info

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

Code changes from version 1.8.3.1 to 1.8.4

Files changed (79) hide show
  1. adminpages/addons.php +142 -142
  2. adminpages/addons/hide-admin-bar-from-non-admins.php +31 -31
  3. adminpages/addons/pmpro-addon-packages.php +30 -30
  4. adminpages/addons/pmpro-affiliates.php +30 -30
  5. adminpages/addons/pmpro-aweber.php +31 -31
  6. adminpages/addons/pmpro-bbpress.php +31 -31
  7. adminpages/addons/pmpro-constant-contact.php +31 -31
  8. adminpages/addons/pmpro-disable-emails.php +28 -28
  9. adminpages/addons/pmpro-email-templates.php +31 -31
  10. adminpages/addons/pmpro-expiration.php +30 -30
  11. adminpages/addons/pmpro-freeaddress.php +30 -30
  12. adminpages/addons/pmpro-infusionsoft.php +31 -31
  13. adminpages/addons/pmpro-level-cost-text.php +30 -30
  14. adminpages/addons/pmpro-mailchimp.php +31 -31
  15. adminpages/addons/pmpro-network-subsite.php +31 -31
  16. adminpages/addons/pmpro-network.php +31 -31
  17. adminpages/addons/pmpro-post-affiliate-pro.php +31 -31
  18. adminpages/addons/pmpro-register-helper.php +31 -31
  19. adminpages/addons/pmpro-require-code-to-register.php +28 -28
  20. adminpages/addons/pmpro-series.php +30 -30
  21. adminpages/addons/pmpro-shipping.php +31 -31
  22. adminpages/addons/pmpro-user-pages.php +30 -30
  23. adminpages/addons/pmpro-woocommerce.php +31 -31
  24. adminpages/addons/pmpro-wp-affiliate.php +31 -31
  25. adminpages/addons/tml.php +32 -32
  26. adminpages/addons/wp-bouncer.php +31 -31
  27. adminpages/admin_footer.php +1 -1
  28. adminpages/admin_header.php +173 -156
  29. adminpages/advancedsettings.php +79 -79
  30. adminpages/dashboard.php +27 -27
  31. adminpages/discountcodes.php +665 -665
  32. adminpages/emailsettings.php +181 -181
  33. adminpages/functions.php +255 -255
  34. adminpages/membershiplevels.php +673 -594
  35. adminpages/memberslist-csv.php +41 -41
  36. adminpages/memberslist.php +58 -58
  37. adminpages/orders-csv.php +75 -75
  38. adminpages/orders.php +2 -2
  39. adminpages/pagesettings.php +260 -257
  40. adminpages/paymentsettings.php +244 -244
  41. adminpages/reports.php +61 -61
  42. adminpages/reports/login.php +419 -419
  43. adminpages/reports/memberships.php +660 -660
  44. adminpages/reports/sales.php +406 -406
  45. classes/class.memberorder.php +3 -3
  46. classes/class.mimetype.php +238 -238
  47. classes/class.pmproemail.php +815 -815
  48. classes/gateways/class.pmprogateway.php +220 -220
  49. classes/gateways/class.pmprogateway_authorizenet.php +224 -224
  50. classes/gateways/class.pmprogateway_braintree.php +824 -824
  51. classes/gateways/class.pmprogateway_check.php +340 -340
  52. classes/gateways/class.pmprogateway_cybersource.php +884 -884
  53. classes/gateways/class.pmprogateway_payflowpro.php +175 -175
  54. classes/gateways/class.pmprogateway_paypal.php +178 -178
  55. classes/gateways/class.pmprogateway_paypalexpress.php +243 -243
  56. classes/gateways/class.pmprogateway_paypalstandard.php +537 -537
  57. classes/gateways/class.pmprogateway_stripe.php +1616 -1616
  58. classes/gateways/class.pmprogateway_twocheckout.php +83 -30
  59. css/admin.css +117 -113
  60. css/frontend.css +177 -177
  61. css/print.css +3 -3
  62. email/billing.html +3 -3
  63. email/billing_admin.html +4 -4
  64. email/billing_failure.html +2 -2
  65. email/billing_failure_admin.html +10 -10
  66. email/cancel_admin.html +1 -1
  67. email/checkout_freetrial.html +2 -2
  68. email/checkout_freetrial_admin.html +2 -2
  69. email/checkout_paid.html +2 -2
  70. email/checkout_paid_admin.html +2 -2
  71. email/checkout_trial.html +2 -2
  72. email/checkout_trial_admin.html +2 -2
  73. email/credit_card_expiring.html +12 -12
  74. email/invoice.html +2 -2
  75. email/membership_expired.html +6 -6
  76. email/membership_expiring.html +5 -5
  77. includes/adminpages.php +272 -268
  78. includes/cleanup.php +39 -39
  79. includes/content.php +357 -458
adminpages/addons.php CHANGED
@@ -1,142 +1,142 @@
1
- <?php
2
- //only admins can get this
3
- if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_addons")))
4
- {
5
- die(__("You do not have permissions to perform this action.", "pmpro"));
6
- }
7
-
8
- global $wpdb, $msg, $msgt, $pmpro_addons;
9
-
10
- /*
11
- Addon lists
12
- */
13
- $pmpro_addon_lists = array(
14
- 'repo' => array('Plugins in the WordPress Repository', 'These official PMPro plugins are available in the WordPress repository and can be installed through Plugins --> Add New.'),
15
- 'thirdparty' => array('Third-party Integration', 'These official PMPro plugins integrate with specific third-party tools and software.'),
16
- 'recommended' => array('Recommended Plugins', 'These plugins are not developed by the PMPro team, but are recommended for sites running PMPro.'),
17
- 'github' => array('Plugins on GitHub', 'These official PMPro plugins must be downloaded from GitHub and installed through Plugins --> Add New --> Upload, then activated. These plugins cannot be automatically updated and may require more developer input.'),
18
- 'gists' => array('Code Gists', 'These are bits of code that generally must be added to your active theme\'s functions.php file or included in a custom plugin. Most gists require customization and are recommended for developers only.')
19
- );
20
-
21
- /*
22
- Function to add an addon
23
- */
24
- function pmpro_add_addon($list, $addon)
25
- {
26
- global $pmpro_addons;
27
-
28
- //make sure we have the base array
29
- if(empty($pmpro_addons))
30
- $pmpro_addons = array();
31
-
32
- //make sure we have an array for the list
33
- if(empty($pmpro_addons[$list]))
34
- $pmpro_addons[$list] = array();
35
-
36
- //add addon to list
37
- $pmpro_addons[$list][] = $addon;
38
- }
39
-
40
- /*
41
- Load All Addons
42
- */
43
- $pmpro_addons_dir = dirname(__FILE__) . "/../adminpages/addons/";
44
- $cwd = getcwd();
45
- chdir($pmpro_addons_dir);
46
- $count = 0;
47
- foreach (glob("*.php") as $filename)
48
- {
49
- $count++;
50
- require_once($filename);
51
- }
52
- chdir($cwd);
53
-
54
- require_once(dirname(__FILE__) . "/admin_header.php");
55
- ?>
56
-
57
- <h2>Add Ons</h2>
58
- <ul id="addon-filters" class="subsubsub">
59
- <li id="addon-filters-all"><a href="javascript:void(0);" class="current all tab">All</a> <span>(<?php echo $count;?>)</span></li>
60
- <?php foreach($pmpro_addon_lists as $list => $list_info) { ?>
61
- <li id="addon-filters-<?php echo $list;?>"> | <a href="javascript:void(0);>" class="tab"><?php echo $list_info[0];?></a> <span>(<?php echo count($pmpro_addons[$list]);?>)</span></li>
62
- <?php } ?>
63
- </ul>
64
-
65
- <?php foreach($pmpro_addon_lists as $list => $list_info) { ?>
66
- <div id="pmpro-<?php echo $list;?>" class="pmpro-addon-list widgets-holder-wrap">
67
-
68
- <h3 class="section-title"><?php echo $list_info[0];?></h3>
69
- <p class="description"><?php echo $list_info[1];?></p>
70
- <br class="clear" />
71
-
72
- <div id="addons-list-<?php echo $list;?>" class="addon-list">
73
-
74
- <?php foreach($pmpro_addons[$list] as $slug => $addon) { ?>
75
- <div id="addon-<?php echo $slug;?>" class="widget <?php if($addon['enabled']) echo "enabled"; else echo "disabled";?>">
76
- <div class="widget-top">
77
- <div class="widget-title">
78
- <h4>
79
- <span class="status-label"><?php if($addon['enabled']) echo __("Enabled", "pmpro"); else echo __("Disabled", "pmpro");?></span>
80
- <span class="title"><?php echo $addon['title'];?></span>
81
- <span class="version pmpro_tag-grey"><?php echo $addon['version'];?></span>
82
- <span class="in-widget-title"></span>
83
- </h4>
84
- </div> <!-- end widget-title -->
85
- </div> <!-- end widget-top -->
86
- <div class="widget-inside">
87
- <?php call_user_func($addon['widget'], $addon);?>
88
- </div> <!-- end addon-inside -->
89
- </div> <!-- end widget -->
90
- <?php } ?>
91
-
92
- <br class="clear" />
93
- </div> <!-- end addon-list -->
94
-
95
- </div> <!-- end pmpro-<?php echo $list;?> -->
96
- <?php } ?>
97
-
98
- <script>
99
- //tabs
100
- jQuery(document).ready(function() {
101
- jQuery('#addon-filters a.tab').click(function() {
102
- //which tab?
103
- var tab = jQuery(this).parent().attr('id').replace('addon-filters-', '');
104
-
105
- //un select tabs
106
- jQuery('#addon-filters a.tab').removeClass('current');
107
-
108
- //select this tab
109
- jQuery('#addon-filters-'+tab+' a').addClass('current');
110
-
111
- //show all?
112
- if(tab == 'all')
113
- jQuery('div.pmpro-addon-list').show();
114
- else
115
- {
116
- //hide all
117
- jQuery('div.pmpro-addon-list').hide();
118
-
119
- //show this one
120
- jQuery('#pmpro-'+tab).show();
121
- }
122
- });
123
- });
124
-
125
- //resize addon boxes
126
- jQuery(document).ready(function() {
127
- jQuery('.addon-list').each(function() {
128
- //what's the tallest p in the list?
129
- var tallest = 32;
130
- jQuery(this).find('div.info p').each(function() {
131
- tallest = Math.max(tallest, jQuery(this).height());
132
- });
133
-
134
- //set all p's to match
135
- jQuery(this).find('div.info p').css('height', tallest);
136
- });
137
- });
138
- </script>
139
-
140
- <?php
141
- require_once(dirname(__FILE__) . "/admin_footer.php");
142
- ?>
1
+ <?php
2
+ //only admins can get this
3
+ if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_addons")))
4
+ {
5
+ die(__("You do not have permissions to perform this action.", "pmpro"));
6
+ }
7
+
8
+ global $wpdb, $msg, $msgt, $pmpro_addons;
9
+
10
+ /*
11
+ Addon lists
12
+ */
13
+ $pmpro_addon_lists = array(
14
+ 'repo' => array('Plugins in the WordPress Repository', 'These official PMPro plugins are available in the WordPress repository and can be installed through Plugins --> Add New.'),
15
+ 'thirdparty' => array('Third-party Integration', 'These official PMPro plugins integrate with specific third-party tools and software.'),
16
+ 'recommended' => array('Recommended Plugins', 'These plugins are not developed by the PMPro team, but are recommended for sites running PMPro.'),
17
+ 'github' => array('Plugins on GitHub', 'These official PMPro plugins must be downloaded from GitHub and installed through Plugins --> Add New --> Upload, then activated. These plugins cannot be automatically updated and may require more developer input.'),
18
+ 'gists' => array('Code Gists', 'These are bits of code that generally must be added to your active theme\'s functions.php file or included in a custom plugin. Most gists require customization and are recommended for developers only.')
19
+ );
20
+
21
+ /*
22
+ Function to add an addon
23
+ */
24
+ function pmpro_add_addon($list, $addon)
25
+ {
26
+ global $pmpro_addons;
27
+
28
+ //make sure we have the base array
29
+ if(empty($pmpro_addons))
30
+ $pmpro_addons = array();
31
+
32
+ //make sure we have an array for the list
33
+ if(empty($pmpro_addons[$list]))
34
+ $pmpro_addons[$list] = array();
35
+
36
+ //add addon to list
37
+ $pmpro_addons[$list][] = $addon;
38
+ }
39
+
40
+ /*
41
+ Load All Addons
42
+ */
43
+ $pmpro_addons_dir = dirname(__FILE__) . "/../adminpages/addons/";
44
+ $cwd = getcwd();
45
+ chdir($pmpro_addons_dir);
46
+ $count = 0;
47
+ foreach (glob("*.php") as $filename)
48
+ {
49
+ $count++;
50
+ require_once($filename);
51
+ }
52
+ chdir($cwd);
53
+
54
+ require_once(dirname(__FILE__) . "/admin_header.php");
55
+ ?>
56
+
57
+ <h2>Add Ons</h2>
58
+ <ul id="addon-filters" class="subsubsub">
59
+ <li id="addon-filters-all"><a href="javascript:void(0);" class="current all tab">All</a> <span>(<?php echo $count;?>)</span></li>
60
+ <?php foreach($pmpro_addon_lists as $list => $list_info) { ?>
61
+ <li id="addon-filters-<?php echo $list;?>"> | <a href="javascript:void(0);>" class="tab"><?php echo $list_info[0];?></a> <span>(<?php echo count($pmpro_addons[$list]);?>)</span></li>
62
+ <?php } ?>
63
+ </ul>
64
+
65
+ <?php foreach($pmpro_addon_lists as $list => $list_info) { ?>
66
+ <div id="pmpro-<?php echo $list;?>" class="pmpro-addon-list widgets-holder-wrap">
67
+
68
+ <h3 class="section-title"><?php echo $list_info[0];?></h3>
69
+ <p class="description"><?php echo $list_info[1];?></p>
70
+ <br class="clear" />
71
+
72
+ <div id="addons-list-<?php echo $list;?>" class="addon-list">
73
+
74
+ <?php foreach($pmpro_addons[$list] as $slug => $addon) { ?>
75
+ <div id="addon-<?php echo $slug;?>" class="widget <?php if($addon['enabled']) echo "enabled"; else echo "disabled";?>">
76
+ <div class="widget-top">
77
+ <div class="widget-title">
78
+ <h4>
79
+ <span class="status-label"><?php if($addon['enabled']) echo __("Enabled", "pmpro"); else echo __("Disabled", "pmpro");?></span>
80
+ <span class="title"><?php echo $addon['title'];?></span>
81
+ <span class="version pmpro_tag-grey"><?php echo $addon['version'];?></span>
82
+ <span class="in-widget-title"></span>
83
+ </h4>
84
+ </div> <!-- end widget-title -->
85
+ </div> <!-- end widget-top -->
86
+ <div class="widget-inside">
87
+ <?php call_user_func($addon['widget'], $addon);?>
88
+ </div> <!-- end addon-inside -->
89
+ </div> <!-- end widget -->
90
+ <?php } ?>
91
+
92
+ <br class="clear" />
93
+ </div> <!-- end addon-list -->
94
+
95
+ </div> <!-- end pmpro-<?php echo $list;?> -->
96
+ <?php } ?>
97
+
98
+ <script>
99
+ //tabs
100
+ jQuery(document).ready(function() {
101
+ jQuery('#addon-filters a.tab').click(function() {
102
+ //which tab?
103
+ var tab = jQuery(this).parent().attr('id').replace('addon-filters-', '');
104
+
105
+ //un select tabs
106
+ jQuery('#addon-filters a.tab').removeClass('current');
107
+
108
+ //select this tab
109
+ jQuery('#addon-filters-'+tab+' a').addClass('current');
110
+
111
+ //show all?
112
+ if(tab == 'all')
113
+ jQuery('div.pmpro-addon-list').show();
114
+ else
115
+ {
116
+ //hide all
117
+ jQuery('div.pmpro-addon-list').hide();
118
+
119
+ //show this one
120
+ jQuery('#pmpro-'+tab).show();
121
+ }
122
+ });
123
+ });
124
+
125
+ //resize addon boxes
126
+ jQuery(document).ready(function() {
127
+ jQuery('.addon-list').each(function() {
128
+ //what's the tallest p in the list?
129
+ var tallest = 32;
130
+ jQuery(this).find('div.info p').each(function() {
131
+ tallest = Math.max(tallest, jQuery(this).height());
132
+ });
133
+
134
+ //set all p's to match
135
+ jQuery(this).find('div.info p').css('height', tallest);
136
+ });
137
+ });
138
+ </script>
139
+
140
+ <?php
141
+ require_once(dirname(__FILE__) . "/admin_footer.php");
142
+ ?>
adminpages/addons/hide-admin-bar-from-non-admins.php CHANGED
@@ -1,32 +1,32 @@
1
- <?php
2
- /*
3
- Addon: Hide Admin Bar From Non-Admins
4
- Slug: hide-admin-bar-from-non-admins
5
- */
6
- pmpro_add_addon('repo', array(
7
- 'title' => 'Hide Admin Bar From Non-Admins',
8
- 'version' => '1.0',
9
- 'widget' => 'pmpro_addon_hide_admin_bar_from_non_admins_widget',
10
- 'enabled' => function_exists('habfna_disable_admin_bar')
11
- )
12
- );
13
-
14
- function pmpro_addon_hide_admin_bar_from_non_admins_widget($addon)
15
- {
16
- ?>
17
- <div class="info">
18
- <p>Perfect for sites where there is only one admin who needs access to the dashboard and the admin bar. When activated only administrators will see the admin bar.</p>
19
- <div class="actions">
20
- <form method="post" name="component-actions" action="">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../hide-admin-bar-from-non-admins/hide-admin-bar-from-non-admins.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=hide-admin-bar-from-non-admins/hide-admin-bar-from-non-admins.php'), 'activate-plugin_hide-admin-bar-from-non-admins/hide-admin-bar-from-non-admins.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=hide-admin-bar-from-non-admins'), 'install-plugin_hide-admin-bar-from-non-admins'); ?>" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </form>
29
- </div>
30
- </div> <!-- end info -->
31
- <?php
32
  }
1
+ <?php
2
+ /*
3
+ Addon: Hide Admin Bar From Non-Admins
4
+ Slug: hide-admin-bar-from-non-admins
5
+ */
6
+ pmpro_add_addon('repo', array(
7
+ 'title' => 'Hide Admin Bar From Non-Admins',
8
+ 'version' => '1.0',
9
+ 'widget' => 'pmpro_addon_hide_admin_bar_from_non_admins_widget',
10
+ 'enabled' => function_exists('habfna_disable_admin_bar')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_hide_admin_bar_from_non_admins_widget($addon)
15
+ {
16
+ ?>
17
+ <div class="info">
18
+ <p>Perfect for sites where there is only one admin who needs access to the dashboard and the admin bar. When activated only administrators will see the admin bar.</p>
19
+ <div class="actions">
20
+ <form method="post" name="component-actions" action="">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../hide-admin-bar-from-non-admins/hide-admin-bar-from-non-admins.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=hide-admin-bar-from-non-admins/hide-admin-bar-from-non-admins.php'), 'activate-plugin_hide-admin-bar-from-non-admins/hide-admin-bar-from-non-admins.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=hide-admin-bar-from-non-admins'), 'install-plugin_hide-admin-bar-from-non-admins'); ?>" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </form>
29
+ </div>
30
+ </div> <!-- end info -->
31
+ <?php
32
  }
adminpages/addons/pmpro-addon-packages.php CHANGED
@@ -1,30 +1,30 @@
1
- <?php
2
- /*
3
- Addon: PMPro Addon Packages
4
- Slug: pmpro-addon-packages
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro Addon Packages',
8
- 'version' => '.4.3',
9
- 'widget' => 'pmpro_addon_pmpro_addon_packages_widget',
10
- 'enabled' => function_exists('pmproap_post_meta')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_addon_packages_widget($addon)
15
- {
16
- ?>
17
- <div class="info">
18
- <p>Sell access to individual pages or posts for a flat fee. This is a workaround if you would like to allow multiple membership levels per user.</p>
19
- <div class="actions">
20
- <?php if($addon['enabled']) { ?>
21
- <a href="https://github.com/strangerstudios/pmpro-addon-packages/blob/master/readme.txt" class="button">Enabled</a>
22
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-addon-packages/pmpro-addon-packages.php")) { ?>
23
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-addon-packages/pmpro-addon-packages.php'), 'activate-plugin_pmpro-addon-packages/pmpro-addon-packages.php')?>" class="button button-primary">Activate</a>
24
- <?php } else { ?>
25
- <a href="https://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-addon-packages.zip" class="button button-primary">Download</a>
26
- <?php } ?>
27
- </div>
28
- </div> <!-- end info -->
29
- <?php
30
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Addon Packages
4
+ Slug: pmpro-addon-packages
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro Addon Packages',
8
+ 'version' => '.4.3',
9
+ 'widget' => 'pmpro_addon_pmpro_addon_packages_widget',
10
+ 'enabled' => function_exists('pmproap_post_meta')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_addon_packages_widget($addon)
15
+ {
16
+ ?>
17
+ <div class="info">
18
+ <p>Sell access to individual pages or posts for a flat fee. This is a workaround if you would like to allow multiple membership levels per user.</p>
19
+ <div class="actions">
20
+ <?php if($addon['enabled']) { ?>
21
+ <a href="https://github.com/strangerstudios/pmpro-addon-packages/blob/master/readme.txt" class="button">Enabled</a>
22
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-addon-packages/pmpro-addon-packages.php")) { ?>
23
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-addon-packages/pmpro-addon-packages.php'), 'activate-plugin_pmpro-addon-packages/pmpro-addon-packages.php')?>" class="button button-primary">Activate</a>
24
+ <?php } else { ?>
25
+ <a href="https://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-addon-packages.zip" class="button button-primary">Download</a>
26
+ <?php } ?>
27
+ </div>
28
+ </div> <!-- end info -->
29
+ <?php
30
+ }
adminpages/addons/pmpro-affiliates.php CHANGED
@@ -1,30 +1,30 @@
1
- <?php
2
- /*
3
- Addon: PMPro Affiliates
4
- Slug: pmpro-affiliates
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro Affiliates',
8
- 'version' => '.2.4',
9
- 'widget' => 'pmpro_addon_pmpro_affiliates_widget',
10
- 'enabled' => function_exists('pmpro_affiliates_dependencies')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_affiliates_widget($addon)
15
- {
16
- ?>
17
- <div class="info">
18
- <p>Lightweight Affiliate system. Create affiliate accounts and codes; tracks checkouts by affiliate account.</p>
19
- <div class="actions">
20
- <?php if($addon['enabled']) { ?>
21
- <a href="https://github.com/strangerstudios/pmpro-affiliates/blob/master/readme.txt" class="button">Enabled</a>
22
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-affiliates/pmpro-affiliates.php")) { ?>
23
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-affiliates/pmpro-affiliates.php'), 'activate-plugin_pmpro-affiliates/pmpro-affiliates.php')?>" class="button button-primary">Activate</a>
24
- <?php } else { ?>
25
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-affiliates.zip" class="button button-primary">Download</a>
26
- <?php } ?>
27
- </div>
28
- </div> <!-- end info -->
29
- <?php
30
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Affiliates
4
+ Slug: pmpro-affiliates
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro Affiliates',
8
+ 'version' => '.2.4',
9
+ 'widget' => 'pmpro_addon_pmpro_affiliates_widget',
10
+ 'enabled' => function_exists('pmpro_affiliates_dependencies')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_affiliates_widget($addon)
15
+ {
16
+ ?>
17
+ <div class="info">
18
+ <p>Lightweight Affiliate system. Create affiliate accounts and codes; tracks checkouts by affiliate account.</p>
19
+ <div class="actions">
20
+ <?php if($addon['enabled']) { ?>
21
+ <a href="https://github.com/strangerstudios/pmpro-affiliates/blob/master/readme.txt" class="button">Enabled</a>
22
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-affiliates/pmpro-affiliates.php")) { ?>
23
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-affiliates/pmpro-affiliates.php'), 'activate-plugin_pmpro-affiliates/pmpro-affiliates.php')?>" class="button button-primary">Activate</a>
24
+ <?php } else { ?>
25
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-affiliates.zip" class="button button-primary">Download</a>
26
+ <?php } ?>
27
+ </div>
28
+ </div> <!-- end info -->
29
+ <?php
30
+ }
adminpages/addons/pmpro-aweber.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro AWeber Integration
4
- Slug: pmpro-aweber
5
- */
6
- pmpro_add_addon('thirdparty', array(
7
- 'title' => 'PMPro AWeber Integration',
8
- 'version' => '1.0',
9
- 'widget' => 'pmpro_addon_pmpro_aweber_widget',
10
- 'enabled' => function_exists('pmproaw_init')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_aweber_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-aweber.gif" />
18
- <div class="info">
19
- <p>Integrate User Registrations with AWeber. Adds members to lists based on their membership level. (Note: works without PMPro as well.)</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-aweber/pmpro-aweber.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-aweber/pmpro-aweber.php'), 'activate-plugin_pmpro-aweber/pmpro-aweber.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-aweber'), 'install-plugin_pmpro-aweber'); ?>" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro AWeber Integration
4
+ Slug: pmpro-aweber
5
+ */
6
+ pmpro_add_addon('thirdparty', array(
7
+ 'title' => 'PMPro AWeber Integration',
8
+ 'version' => '1.0',
9
+ 'widget' => 'pmpro_addon_pmpro_aweber_widget',
10
+ 'enabled' => function_exists('pmproaw_init')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_aweber_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-aweber.gif" />
18
+ <div class="info">
19
+ <p>Integrate User Registrations with AWeber. Adds members to lists based on their membership level. (Note: works without PMPro as well.)</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-aweber/pmpro-aweber.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-aweber/pmpro-aweber.php'), 'activate-plugin_pmpro-aweber/pmpro-aweber.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-aweber'), 'install-plugin_pmpro-aweber'); ?>" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-bbpress.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro bbPress
4
- Slug: pmpro-bbpress
5
- */
6
- pmpro_add_addon('repo', array(
7
- 'title' => 'PMPro bbPress',
8
- 'version' => '1.0.1',
9
- 'widget' => 'pmpro_addon_pmpro_bbpress_widget',
10
- 'enabled' => function_exists('pmprobbp_add_meta_box')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_bbpress_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-bbpress.jpg" />
18
- <div class="info">
19
- <p>Locking down bbPress Forums by Membership Level and Forum ID.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-bbpress/pmpro-bbpress.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-bbpress/pmpro-bbpress.php'), 'activate-plugin_pmpro-bbpress/pmpro-bbpress.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-bbpress'), 'install-plugin_pmpro-bbpress'); ?>" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro bbPress
4
+ Slug: pmpro-bbpress
5
+ */
6
+ pmpro_add_addon('repo', array(
7
+ 'title' => 'PMPro bbPress',
8
+ 'version' => '1.0.1',
9
+ 'widget' => 'pmpro_addon_pmpro_bbpress_widget',
10
+ 'enabled' => function_exists('pmprobbp_add_meta_box')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_bbpress_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-bbpress.jpg" />
18
+ <div class="info">
19
+ <p>Locking down bbPress Forums by Membership Level and Forum ID.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-bbpress/pmpro-bbpress.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-bbpress/pmpro-bbpress.php'), 'activate-plugin_pmpro-bbpress/pmpro-bbpress.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-bbpress'), 'install-plugin_pmpro-bbpress'); ?>" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-constant-contact.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro Constant Contact Integration
4
- Slug: pmpro-constant-contact
5
- */
6
- pmpro_add_addon('thirdparty', array(
7
- 'title' => 'PMPro Constant Contact Integration',
8
- 'version' => '1.0',
9
- 'widget' => 'pmpro_addon_pmpro_constant_contact_widget',
10
- 'enabled' => function_exists('pmprocc_init')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_constant_contact_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-constant-contact.gif" />
18
- <div class="info">
19
- <p>Integrate User Registrations with Constant Contact . Adds members to lists based on their membership level. (Note: works without PMPro as well.)</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-constant-contact/pmpro-constant-contact.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-constant-contact/pmpro-constant-contact.php'), 'activate-plugin_pmpro-constant-contact/pmpro-constant-contact.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-constant-contact'), 'install-plugin_pmpro-constant-contact'); ?>" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Constant Contact Integration
4
+ Slug: pmpro-constant-contact
5
+ */
6
+ pmpro_add_addon('thirdparty', array(
7
+ 'title' => 'PMPro Constant Contact Integration',
8
+ 'version' => '1.0',
9
+ 'widget' => 'pmpro_addon_pmpro_constant_contact_widget',
10
+ 'enabled' => function_exists('pmprocc_init')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_constant_contact_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-constant-contact.gif" />
18
+ <div class="info">
19
+ <p>Integrate User Registrations with Constant Contact . Adds members to lists based on their membership level. (Note: works without PMPro as well.)</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-constant-contact/pmpro-constant-contact.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-constant-contact/pmpro-constant-contact.php'), 'activate-plugin_pmpro-constant-contact/pmpro-constant-contact.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-constant-contact'), 'install-plugin_pmpro-constant-contact'); ?>" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-disable-emails.php CHANGED
@@ -1,28 +1,28 @@
1
- <?php
2
- /*
3
- Addon: PMPro Disable PMPro Emails
4
- Slug: pmpro-disable-emails
5
- */
6
- pmpro_add_addon('gists', array(
7
- 'title' => 'PMPro Disable Emails',
8
- 'version' => '.1',
9
- 'widget' => 'pmpro_addon_pmpro_disable_emails_widget',
10
- 'enabled' => function_exists('dae_pmpro_email_recipient')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_disable_emails_widget($addon)
15
- {
16
- ?>
17
- <div class="info">
18
- <p>Disable all or specific emails sent by the PMPro plugin.</p>
19
- <div class="actions">
20
- <?php if($addon['enabled']) { ?>
21
- <a target="_blank" href="https://gist.github.com/strangerstudios/3667545" class="button">Enabled</a>
22
- <?php } else { ?>
23
- <a target="_blank" href="https://gist.github.com/strangerstudios/3667545" class="button button-primary">View Gist</a>
24
- <?php } ?>
25
- </div>
26
- </div> <!-- end info -->
27
- <?php
28
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Disable PMPro Emails
4
+ Slug: pmpro-disable-emails
5
+ */
6
+ pmpro_add_addon('gists', array(
7
+ 'title' => 'PMPro Disable Emails',
8
+ 'version' => '.1',
9
+ 'widget' => 'pmpro_addon_pmpro_disable_emails_widget',
10
+ 'enabled' => function_exists('dae_pmpro_email_recipient')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_disable_emails_widget($addon)
15
+ {
16
+ ?>
17
+ <div class="info">
18
+ <p>Disable all or specific emails sent by the PMPro plugin.</p>
19
+ <div class="actions">
20
+ <?php if($addon['enabled']) { ?>
21
+ <a target="_blank" href="https://gist.github.com/strangerstudios/3667545" class="button">Enabled</a>
22
+ <?php } else { ?>
23
+ <a target="_blank" href="https://gist.github.com/strangerstudios/3667545" class="button button-primary">View Gist</a>
24
+ <?php } ?>
25
+ </div>
26
+ </div> <!-- end info -->
27
+ <?php
28
+ }
adminpages/addons/pmpro-email-templates.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro Email Templates Editor
4
- Slug: pmpro-email-templates-addon
5
- */
6
- pmpro_add_addon('repo', array(
7
- 'title' => 'PMPro Email Templates',
8
- 'version' => '.5.2',
9
- 'widget' => 'pmpro_addon_email_templates_widget',
10
- 'enabled' => function_exists('pmproet_scripts')
11
- )
12
- );
13
-
14
- function pmpro_addon_email_templates_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-email-templates.gif" />
18
- <div class="info">
19
- <p>Easily edit system-generated Email Templates from the WordPress admin.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="http://wordpress.org/plugins/pmpro-email-templates-addon/" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-email-templates-addon/pmpro-email-templates.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-email-templates-addon/pmpro-email-templates.php'), 'activate-plugin_pmpro-email-templates-addon/pmpro-email-templates.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-email-templates-addon'), 'install-plugin_pmpro-email-templates-addon'); ?>" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Email Templates Editor
4
+ Slug: pmpro-email-templates-addon
5
+ */
6
+ pmpro_add_addon('repo', array(
7
+ 'title' => 'PMPro Email Templates',
8
+ 'version' => '.5.2',
9
+ 'widget' => 'pmpro_addon_email_templates_widget',
10
+ 'enabled' => function_exists('pmproet_scripts')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_email_templates_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-email-templates.gif" />
18
+ <div class="info">
19
+ <p>Easily edit system-generated Email Templates from the WordPress admin.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="http://wordpress.org/plugins/pmpro-email-templates-addon/" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-email-templates-addon/pmpro-email-templates.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-email-templates-addon/pmpro-email-templates.php'), 'activate-plugin_pmpro-email-templates-addon/pmpro-email-templates.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-email-templates-addon'), 'install-plugin_pmpro-email-templates-addon'); ?>" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-expiration.php CHANGED
@@ -1,30 +1,30 @@
1
- <?php
2
- /*
3
- Addon: PMPro Expiration Date
4
- Slug: pmpro-expiration
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro Set Expiration Dates',
8
- 'version' => '.1.1',
9
- 'widget' => 'pmpro_addon_pmpro_expiration_widget',
10
- 'enabled' => function_exists('pmprosed_pmpro_checkout_level')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_expiration_widget($addon)
15
- {
16
- ?>
17
- <div class="info">
18
- <p>Set a specific expiration date (e.g. 2013-12-31) for a PMPro membership level or discount code.</p>
19
- <div class="actions">
20
- <?php if($addon['enabled']) { ?>
21
- <a href="https://github.com/strangerstudios/pmpro-set-expiration-dates/blob/master/readme.txt" class="button">Enabled</a>
22
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-set-expiration-dates/pmpro-set-expiration-dates.php")) { ?>
23
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-set-expiration-dates/pmpro-set-expiration-dates.php'), 'activate-plugin_pmpro-set-expiration-dates/pmpro-set-expiration-dates.php')?>" class="button button-primary">Activate</a>
24
- <?php } else { ?>
25
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-set-expiration-dates.zip" class="button button-primary">Download</a>
26
- <?php } ?>
27
- </div>
28
- </div> <!-- end info -->
29
- <?php
30
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Expiration Date
4
+ Slug: pmpro-expiration
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro Set Expiration Dates',
8
+ 'version' => '.1.1',
9
+ 'widget' => 'pmpro_addon_pmpro_expiration_widget',
10
+ 'enabled' => function_exists('pmprosed_pmpro_checkout_level')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_expiration_widget($addon)
15
+ {
16
+ ?>
17
+ <div class="info">
18
+ <p>Set a specific expiration date (e.g. 2013-12-31) for a PMPro membership level or discount code.</p>
19
+ <div class="actions">
20
+ <?php if($addon['enabled']) { ?>
21
+ <a href="https://github.com/strangerstudios/pmpro-set-expiration-dates/blob/master/readme.txt" class="button">Enabled</a>
22
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-set-expiration-dates/pmpro-set-expiration-dates.php")) { ?>
23
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-set-expiration-dates/pmpro-set-expiration-dates.php'), 'activate-plugin_pmpro-set-expiration-dates/pmpro-set-expiration-dates.php')?>" class="button button-primary">Activate</a>
24
+ <?php } else { ?>
25
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-set-expiration-dates.zip" class="button button-primary">Download</a>
26
+ <?php } ?>
27
+ </div>
28
+ </div> <!-- end info -->
29
+ <?php
30
+ }
adminpages/addons/pmpro-freeaddress.php CHANGED
@@ -1,30 +1,30 @@
1
- <?php
2
- /*
3
- Addon: PMPro Require Name and Address for Free Level
4
- Slug: pmpro-freerequire
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro Require Name/Address for Free Level',
8
- 'version' => '.2',
9
- 'widget' => 'pmpro_addon_pmpro_freerequire_widget',
10
- 'enabled' => function_exists('my_pmpro_checkout_boxes_require_address')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_freerequire_widget($addon)
15
- {
16
- ?>
17
- <div class="info">
18
- <p>Require name/address for free Membership Level checkout.</p>
19
- <div class="actions">
20
- <?php if($addon['enabled']) { ?>
21
- <a href="https://github.com/strangerstudios/pmpro-address-for-free-levels" class="button">Enabled</a>
22
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-address-for-free-levels/pmpro-address-for-free-levels.php")) { ?>
23
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-address-for-free-levels/pmpro-address-for-free-levels.php'), 'activate-plugin_pmpro-address-for-free-levels/pmpro-address-for-free-levels.php')?>" class="button button-primary">Activate</a>
24
- <?php } else { ?>
25
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-address-for-free-levels.zip" class="button button-primary">Download</a>
26
- <?php } ?>
27
- </div>
28
- </div> <!-- end info -->
29
- <?php
30
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Require Name and Address for Free Level
4
+ Slug: pmpro-freerequire
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro Require Name/Address for Free Level',
8
+ 'version' => '.2',
9
+ 'widget' => 'pmpro_addon_pmpro_freerequire_widget',
10
+ 'enabled' => function_exists('my_pmpro_checkout_boxes_require_address')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_freerequire_widget($addon)
15
+ {
16
+ ?>
17
+ <div class="info">
18
+ <p>Require name/address for free Membership Level checkout.</p>
19
+ <div class="actions">
20
+ <?php if($addon['enabled']) { ?>
21
+ <a href="https://github.com/strangerstudios/pmpro-address-for-free-levels" class="button">Enabled</a>
22
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-address-for-free-levels/pmpro-address-for-free-levels.php")) { ?>
23
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-address-for-free-levels/pmpro-address-for-free-levels.php'), 'activate-plugin_pmpro-address-for-free-levels/pmpro-address-for-free-levels.php')?>" class="button button-primary">Activate</a>
24
+ <?php } else { ?>
25
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-address-for-free-levels.zip" class="button button-primary">Download</a>
26
+ <?php } ?>
27
+ </div>
28
+ </div> <!-- end info -->
29
+ <?php
30
+ }
adminpages/addons/pmpro-infusionsoft.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro Infusionsoft Integration
4
- Slug: pmpro-infusionsoft
5
- */
6
- pmpro_add_addon('thirdparty', array(
7
- 'title' => 'PMPro Infusionsoft Integration',
8
- 'version' => '1.2',
9
- 'widget' => 'pmpro_addon_pmpro_infusionsoft_widget',
10
- 'enabled' => function_exists('pmprois_init')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_infusionsoft_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-infusionsoft.jpg" />
18
- <div class="info">
19
- <p>Integrate with Infusionsoft. Add members to email lists (groups, tags) based on their membership level. (Note: works without PMPro as well.)</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-infusionsoft/pmpro-infusionsoft.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-infusionsoft/pmpro-infusionsoft.php'), 'activate-plugin_pmpro-infusionsoft/pmpro-infusionsoft.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-infusionsoft'), 'install-plugin_pmpro-infusionsoft'); ?>" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Infusionsoft Integration
4
+ Slug: pmpro-infusionsoft
5
+ */
6
+ pmpro_add_addon('thirdparty', array(
7
+ 'title' => 'PMPro Infusionsoft Integration',
8
+ 'version' => '1.2',
9
+ 'widget' => 'pmpro_addon_pmpro_infusionsoft_widget',
10
+ 'enabled' => function_exists('pmprois_init')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_infusionsoft_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-infusionsoft.jpg" />
18
+ <div class="info">
19
+ <p>Integrate with Infusionsoft. Add members to email lists (groups, tags) based on their membership level. (Note: works without PMPro as well.)</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-infusionsoft/pmpro-infusionsoft.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-infusionsoft/pmpro-infusionsoft.php'), 'activate-plugin_pmpro-infusionsoft/pmpro-infusionsoft.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-infusionsoft'), 'install-plugin_pmpro-infusionsoft'); ?>" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-level-cost-text.php CHANGED
@@ -1,30 +1,30 @@
1
- <?php
2
- /*
3
- Addon: PMPro Custom Level Cost Text
4
- Slug: pmpro-level-cost-text
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro Level Cost Text',
8
- 'version' => '.2',
9
- 'widget' => 'pmpro_addon_pmpro_level_cost_text_widget',
10
- 'enabled' => function_exists('pclct_pmpro_discount_code_after_level_settings')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_level_cost_text_widget($addon)
15
- {
16
- ?>
17
- <div class="info">
18
- <p>Adds a "level cost text" field to PMPro Membership Levels and Discount Codes to allow you to override the automatically generated level cost text PMPro provides.</p>
19
- <div class="actions">
20
- <?php if($addon['enabled']) { ?>
21
- <a href="https://github.com/strangerstudios/pmpro-level-cost-text/blob/master/readme.txt" class="button">Enabled</a>
22
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-level-cost-text/pmpro-level-cost-text.php")) { ?>
23
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-level-cost-text/pmpro-level-cost-text.php'), 'activate-plugin_pmpro-level-cost-text/pmpro-level-cost-text.php')?>" class="button button-primary">Activate</a>
24
- <?php } else { ?>
25
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-level-cost-text.zip" class="button button-primary">Download</a>
26
- <?php } ?>
27
- </div>
28
- </div> <!-- end info -->
29
- <?php
30
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Custom Level Cost Text
4
+ Slug: pmpro-level-cost-text
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro Level Cost Text',
8
+ 'version' => '.2',
9
+ 'widget' => 'pmpro_addon_pmpro_level_cost_text_widget',
10
+ 'enabled' => function_exists('pclct_pmpro_discount_code_after_level_settings')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_level_cost_text_widget($addon)
15
+ {
16
+ ?>
17
+ <div class="info">
18
+ <p>Adds a "level cost text" field to PMPro Membership Levels and Discount Codes to allow you to override the automatically generated level cost text PMPro provides.</p>
19
+ <div class="actions">
20
+ <?php if($addon['enabled']) { ?>
21
+ <a href="https://github.com/strangerstudios/pmpro-level-cost-text/blob/master/readme.txt" class="button">Enabled</a>
22
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-level-cost-text/pmpro-level-cost-text.php")) { ?>
23
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-level-cost-text/pmpro-level-cost-text.php'), 'activate-plugin_pmpro-level-cost-text/pmpro-level-cost-text.php')?>" class="button button-primary">Activate</a>
24
+ <?php } else { ?>
25
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-level-cost-text.zip" class="button button-primary">Download</a>
26
+ <?php } ?>
27
+ </div>
28
+ </div> <!-- end info -->
29
+ <?php
30
+ }
adminpages/addons/pmpro-mailchimp.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro MailChimp Integration
4
- Slug: pmpro-mailchimp
5
- */
6
- pmpro_add_addon('thirdparty', array(
7
- 'title' => 'PMPro MailChimp Integration',
8
- 'version' => '1.0',
9
- 'widget' => 'pmpro_addon_pmpro_mailchimp_widget',
10
- 'enabled' => function_exists('pmpromc_init')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_mailchimp_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-mailchimp.jpg" />
18
- <div class="info">
19
- <p>Integrate User Registrations with Mailchimp. Adds members to lists based on their membership level. (Note: works without PMPro as well.)</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-mailchimp/pmpro-mailchimp.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-mailchimp/pmpro-mailchimp.php'), 'activate-plugin_pmpro-mailchimp/pmpro-mailchimp.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-mailchimp'), 'install-plugin_pmpro-mailchimp'); ?>" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro MailChimp Integration
4
+ Slug: pmpro-mailchimp
5
+ */
6
+ pmpro_add_addon('thirdparty', array(
7
+ 'title' => 'PMPro MailChimp Integration',
8
+ 'version' => '1.0',
9
+ 'widget' => 'pmpro_addon_pmpro_mailchimp_widget',
10
+ 'enabled' => function_exists('pmpromc_init')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_mailchimp_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-mailchimp.jpg" />
18
+ <div class="info">
19
+ <p>Integrate User Registrations with Mailchimp. Adds members to lists based on their membership level. (Note: works without PMPro as well.)</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-mailchimp/pmpro-mailchimp.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-mailchimp/pmpro-mailchimp.php'), 'activate-plugin_pmpro-mailchimp/pmpro-mailchimp.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-mailchimp'), 'install-plugin_pmpro-mailchimp'); ?>" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-network-subsite.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro Network
4
- Slug: pmpro-network-subsite
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro Network Subsite Helper',
8
- 'version' => '.2',
9
- 'widget' => 'pmpro_addon_pmpro_network_subsite_widget',
10
- 'enabled' => function_exists('pmpron_subsite_activated_plugin')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_network_subsite_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-network.gif" />
18
- <div class="info">
19
- <p>Have network subsites use membership data from a "main" site to handle access restrictions.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="https://github.com/strangerstudios/pmpro-network-subsite" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-network-subsite/pmpro-network-subsite.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-network-subsite/pmpro-network-subsite.php'), 'activate-plugin_pmpro-network-subsite/pmpro-network-subsite.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-network-subsite.zip" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Network
4
+ Slug: pmpro-network-subsite
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro Network Subsite Helper',
8
+ 'version' => '.2',
9
+ 'widget' => 'pmpro_addon_pmpro_network_subsite_widget',
10
+ 'enabled' => function_exists('pmpron_subsite_activated_plugin')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_network_subsite_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-network.gif" />
18
+ <div class="info">
19
+ <p>Have network subsites use membership data from a "main" site to handle access restrictions.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="https://github.com/strangerstudios/pmpro-network-subsite" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-network-subsite/pmpro-network-subsite.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-network-subsite/pmpro-network-subsite.php'), 'activate-plugin_pmpro-network-subsite/pmpro-network-subsite.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-network-subsite.zip" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-network.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro Network
4
- Slug: pmpro-network
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro Network',
8
- 'version' => '.3.1',
9
- 'widget' => 'pmpro_addon_pmpro_network_widget',
10
- 'enabled' => function_exists('pmpron_new_blogs_settings')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_network_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-network.gif" />
18
- <div class="info">
19
- <p>Allow users to checkout for a membership to create a site on your WordPress multisite network.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="https://github.com/strangerstudios/pmpro-network/blob/master/readme.txt" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-network/pmpro-network.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-network/pmpro-network.php'), 'activate-plugin_pmpro-network/pmpro-network.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-network.zip" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Network
4
+ Slug: pmpro-network
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro Network',
8
+ 'version' => '.3.1',
9
+ 'widget' => 'pmpro_addon_pmpro_network_widget',
10
+ 'enabled' => function_exists('pmpron_new_blogs_settings')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_network_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-network.gif" />
18
+ <div class="info">
19
+ <p>Allow users to checkout for a membership to create a site on your WordPress multisite network.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="https://github.com/strangerstudios/pmpro-network/blob/master/readme.txt" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-network/pmpro-network.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-network/pmpro-network.php'), 'activate-plugin_pmpro-network/pmpro-network.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-network.zip" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-post-affiliate-pro.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro Post Affiliate Pro Integration
4
- Slug: pmpro-post-affiliate-pro
5
- */
6
- pmpro_add_addon('thirdparty', array(
7
- 'title' => 'PMPro Post Affiliate Pro Integration',
8
- 'version' => '.2.1.1',
9
- 'widget' => 'pmpro_addon_pmpro_post_affiliate_pro_widget',
10
- 'enabled' => function_exists('pap_pmpro_track_sale')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_post_affiliate_pro_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-post-affiliate-pro.jpg" />
18
- <div class="info">
19
- <p>Integrate Paid Memberships Pro with the Post Affiliate Pro platform.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="https://github.com/strangerstudios/pmpro-post-affiliate-pro/blob/master/readme.txt" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-post-affiliate-pro/pmpro-post-affiliate-pro.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-post-affiliate-pro/pmpro-post-affiliate-pro.php'), 'activate-plugin_pmpro-post-affiliate-pro/pmpro-post-affiliate-pro.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-post-affiliate-pro.zip" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Post Affiliate Pro Integration
4
+ Slug: pmpro-post-affiliate-pro
5
+ */
6
+ pmpro_add_addon('thirdparty', array(
7
+ 'title' => 'PMPro Post Affiliate Pro Integration',
8
+ 'version' => '.2.1.1',
9
+ 'widget' => 'pmpro_addon_pmpro_post_affiliate_pro_widget',
10
+ 'enabled' => function_exists('pap_pmpro_track_sale')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_post_affiliate_pro_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-post-affiliate-pro.jpg" />
18
+ <div class="info">
19
+ <p>Integrate Paid Memberships Pro with the Post Affiliate Pro platform.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="https://github.com/strangerstudios/pmpro-post-affiliate-pro/blob/master/readme.txt" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-post-affiliate-pro/pmpro-post-affiliate-pro.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-post-affiliate-pro/pmpro-post-affiliate-pro.php'), 'activate-plugin_pmpro-post-affiliate-pro/pmpro-post-affiliate-pro.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-post-affiliate-pro.zip" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-register-helper.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro Register Helper
4
- Slug: pmpro-register-helper
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro Register Helper',
8
- 'version' => '.5.16.1',
9
- 'widget' => 'pmpro_addon_pmpro_register_helper_widget',
10
- 'enabled' => class_exists('PMProRH_Field')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_register_helper_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-register-helper.gif" />
18
- <div class="info">
19
- <p>Add additional meta fields to your PMPro checkout page and/or "Your Profile" pages. Support for text, select, multi-select, textarea, hidden, and custom HTML. Loop into existing checkout/profile field sections or add new ones.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="https://github.com/strangerstudios/pmpro-register-helper/blob/master/readme.txt" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-register-helper/pmpro-register-helper.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-register-helper/pmpro-register-helper.php'), 'activate-plugin_pmpro-register-helper/pmpro-register-helper.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-register-helper.zip" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Register Helper
4
+ Slug: pmpro-register-helper
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro Register Helper',
8
+ 'version' => '.5.16.1',
9
+ 'widget' => 'pmpro_addon_pmpro_register_helper_widget',
10
+ 'enabled' => class_exists('PMProRH_Field')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_register_helper_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-register-helper.gif" />
18
+ <div class="info">
19
+ <p>Add additional meta fields to your PMPro checkout page and/or "Your Profile" pages. Support for text, select, multi-select, textarea, hidden, and custom HTML. Loop into existing checkout/profile field sections or add new ones.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="https://github.com/strangerstudios/pmpro-register-helper/blob/master/readme.txt" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-register-helper/pmpro-register-helper.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-register-helper/pmpro-register-helper.php'), 'activate-plugin_pmpro-register-helper/pmpro-register-helper.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-register-helper.zip" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-require-code-to-register.php CHANGED
@@ -1,28 +1,28 @@
1
- <?php
2
- /*
3
- Addon: PMPro Require Code to Register
4
- Slug: pmpro-require-code-to-register
5
- */
6
- pmpro_add_addon('gists', array(
7
- 'title' => 'PMPro Require a Code to Register',
8
- 'version' => '.1',
9
- 'widget' => 'pmpro_addon_pmpro_require_code_to_register_widget',
10
- 'enabled' => function_exists('my_pmpro_registration_checks_require_code_to_register')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_require_code_to_register_widget($addon)
15
- {
16
- ?>
17
- <div class="info">
18
- <p>Require a discount code to checkout for a specific level.</p>
19
- <div class="actions">
20
- <?php if($addon['enabled']) { ?>
21
- <a target="_blank" href="https://gist.github.com/strangerstudios/5573829" class="button">Enabled</a>
22
- <?php } else { ?>
23
- <a target="_blank" href="https://gist.github.com/strangerstudios/5573829" class="button button-primary">View Gist</a>
24
- <?php } ?>
25
- </div>
26
- </div> <!-- end info -->
27
- <?php
28
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Require Code to Register
4
+ Slug: pmpro-require-code-to-register
5
+ */
6
+ pmpro_add_addon('gists', array(
7
+ 'title' => 'PMPro Require a Code to Register',
8
+ 'version' => '.1',
9
+ 'widget' => 'pmpro_addon_pmpro_require_code_to_register_widget',
10
+ 'enabled' => function_exists('my_pmpro_registration_checks_require_code_to_register')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_require_code_to_register_widget($addon)
15
+ {
16
+ ?>
17
+ <div class="info">
18
+ <p>Require a discount code to checkout for a specific level.</p>
19
+ <div class="actions">
20
+ <?php if($addon['enabled']) { ?>
21
+ <a target="_blank" href="https://gist.github.com/strangerstudios/5573829" class="button">Enabled</a>
22
+ <?php } else { ?>
23
+ <a target="_blank" href="https://gist.github.com/strangerstudios/5573829" class="button button-primary">View Gist</a>
24
+ <?php } ?>
25
+ </div>
26
+ </div> <!-- end info -->
27
+ <?php
28
+ }
adminpages/addons/pmpro-series.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro Series
4
- Slug: pmpro-series
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro Series',
8
- 'version' => '.3',
9
- 'widget' => 'pmpro_addon_pmpro_series_widget',
10
- 'enabled' => class_exists("PMProSeries")
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_series_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-series.gif" />
18
- <div class="info">
19
- <p>"Drip feed" content to your members over the course of their membership. Serializes content by # of days post-registration.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="<?php echo admin_url("edit.php?post_type=pmpro_series");?>" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-series/pmpro-series.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-series/pmpro-series.php'), 'activate-plugin_pmpro-series/pmpro-series.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-series.zip" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
  }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Series
4
+ Slug: pmpro-series
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro Series',
8
+ 'version' => '.3',
9
+ 'widget' => 'pmpro_addon_pmpro_series_widget',
10
+ 'enabled' => class_exists("PMProSeries")
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_series_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-series.gif" />
18
+ <div class="info">
19
+ <p>"Drip feed" content to your members over the course of their membership. Serializes content by # of days post-registration.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="<?php echo admin_url("edit.php?post_type=pmpro_series");?>" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-series/pmpro-series.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-series/pmpro-series.php'), 'activate-plugin_pmpro-series/pmpro-series.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-series.zip" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
  }
adminpages/addons/pmpro-shipping.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro Shipping Add On
4
- Slug: pmpro-shipping
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro Shipping Add On',
8
- 'version' => '.2.6',
9
- 'widget' => 'pmpro_addon_pmpro_shipping_widget',
10
- 'enabled' => function_exists('pmproship_pmpro_checkout_boxes')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_shipping_widget($addon)
15
- {
16
- ?>
17
- <?php /* <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-shipping.jpg" /> */ ?>
18
- <div class="info">
19
- <p>Adds shipping fields to the checkout page, confirmation page, confirmation emails, member's list and edit user profile pages.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="https://github.com/strangerstudios/pmpro-shipping/" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-shipping/pmpro-shipping.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-shipping/pmpro-shipping.php'), 'activate-plugin_pmpro-shipping/pmpro-shipping.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-shipping.zip" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro Shipping Add On
4
+ Slug: pmpro-shipping
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro Shipping Add On',
8
+ 'version' => '.2.6',
9
+ 'widget' => 'pmpro_addon_pmpro_shipping_widget',
10
+ 'enabled' => function_exists('pmproship_pmpro_checkout_boxes')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_shipping_widget($addon)
15
+ {
16
+ ?>
17
+ <?php /* <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-shipping.jpg" /> */ ?>
18
+ <div class="info">
19
+ <p>Adds shipping fields to the checkout page, confirmation page, confirmation emails, member's list and edit user profile pages.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="https://github.com/strangerstudios/pmpro-shipping/" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-shipping/pmpro-shipping.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-shipping/pmpro-shipping.php'), 'activate-plugin_pmpro-shipping/pmpro-shipping.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-shipping.zip" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-user-pages.php CHANGED
@@ -1,30 +1,30 @@
1
- <?php
2
- /*
3
- Addon: PMPro User Pages
4
- Slug: pmpro-user-pages
5
- */
6
- pmpro_add_addon('github', array(
7
- 'title' => 'PMPro User Pages',
8
- 'version' => '.3',
9
- 'widget' => 'pmpro_addon_pmpro_user_pages_widget',
10
- 'enabled' => function_exists('pmproup_pmpro_after_checkout')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_user_pages_widget($addon)
15
- {
16
- ?>
17
- <div class="info">
18
- <p>Creates a unique page for each Member after checkout, giving the Admin access to write customized content for each specific member.</p>
19
- <div class="actions">
20
- <?php if($addon['enabled']) { ?>
21
- <a href="https://github.com/strangerstudios/pmpro-user-pages/blob/master/readme.txt" class="button">Enabled</a>
22
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-user-pages/pmpro-user-pages.php")) { ?>
23
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-user-pages/pmpro-user-pages.php'), 'activate-plugin_pmpro-user-pages/pmpro-user-pages.php')?>" class="button button-primary">Activate</a>
24
- <?php } else { ?>
25
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-user-pages.zip" class="button button-primary">Download</a>
26
- <?php } ?>
27
- </div>
28
- </div> <!-- end info -->
29
- <?php
30
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro User Pages
4
+ Slug: pmpro-user-pages
5
+ */
6
+ pmpro_add_addon('github', array(
7
+ 'title' => 'PMPro User Pages',
8
+ 'version' => '.3',
9
+ 'widget' => 'pmpro_addon_pmpro_user_pages_widget',
10
+ 'enabled' => function_exists('pmproup_pmpro_after_checkout')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_user_pages_widget($addon)
15
+ {
16
+ ?>
17
+ <div class="info">
18
+ <p>Creates a unique page for each Member after checkout, giving the Admin access to write customized content for each specific member.</p>
19
+ <div class="actions">
20
+ <?php if($addon['enabled']) { ?>
21
+ <a href="https://github.com/strangerstudios/pmpro-user-pages/blob/master/readme.txt" class="button">Enabled</a>
22
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-user-pages/pmpro-user-pages.php")) { ?>
23
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-user-pages/pmpro-user-pages.php'), 'activate-plugin_pmpro-user-pages/pmpro-user-pages.php')?>" class="button button-primary">Activate</a>
24
+ <?php } else { ?>
25
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-user-pages.zip" class="button button-primary">Download</a>
26
+ <?php } ?>
27
+ </div>
28
+ </div> <!-- end info -->
29
+ <?php
30
+ }
adminpages/addons/pmpro-woocommerce.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro WooCommerce
4
- Slug: pmpro-woocommerce
5
- */
6
- pmpro_add_addon('thirdparty', array(
7
- 'title' => 'PMPro WooCommerce',
8
- 'version' => '1.2.2',
9
- 'widget' => 'pmpro_addon_pmpro_woocommerce_widget',
10
- 'enabled' => function_exists('pmprowoo_add_membership_from_order')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_woocommerce_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-woocommerce.gif" />
18
- <div class="info">
19
- <p>Use <a href="http://www.woothemes.com/woocommerce/">WooCommerce</a> to purchase membership levels or set members-only product pricing.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-woocommerce/pmpro-woocommerce.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-woocommerce/pmpro-woocommerce.php'), 'activate-plugin_pmpro-woocommerce/pmpro-woocommerce.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-woocommerce'), 'install-plugin_pmpro-woocommerce'); ?>" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro WooCommerce
4
+ Slug: pmpro-woocommerce
5
+ */
6
+ pmpro_add_addon('thirdparty', array(
7
+ 'title' => 'PMPro WooCommerce',
8
+ 'version' => '1.2.2',
9
+ 'widget' => 'pmpro_addon_pmpro_woocommerce_widget',
10
+ 'enabled' => function_exists('pmprowoo_add_membership_from_order')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_woocommerce_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-woocommerce.gif" />
18
+ <div class="info">
19
+ <p>Use <a href="http://www.woothemes.com/woocommerce/">WooCommerce</a> to purchase membership levels or set members-only product pricing.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-woocommerce/pmpro-woocommerce.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-woocommerce/pmpro-woocommerce.php'), 'activate-plugin_pmpro-woocommerce/pmpro-woocommerce.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-woocommerce'), 'install-plugin_pmpro-woocommerce'); ?>" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/pmpro-wp-affiliate.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: PMPro WP Affiliate Platform Integration
4
- Slug: pmpro-wp-affiliate
5
- */
6
- pmpro_add_addon('thirdparty', array(
7
- 'title' => 'PMPro WP Affiliate Platform Integration',
8
- 'version' => '.3',
9
- 'widget' => 'pmpro_addon_pmpro_wp_affiliate_widget',
10
- 'enabled' => function_exists('wpa_pmpro_after_checkout')
11
- )
12
- );
13
-
14
- function pmpro_addon_pmpro_wp_affiliate_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-wp-affiliate-platform.jpg" />
18
- <div class="info">
19
- <p>Process an affiliate via WP Affiliate Platform after a PMPro checkout.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="https://github.com/strangerstudios/pmpro-wp-affiliate-platform/" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-wp-affiliate-platform/pmpro-wp-affiliate-platform.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-wp-affiliate-platform/pmpro-wp-affiliate-platform.php'), 'activate-plugin_pmpro-wp-affiliate-platform/pmpro-wp-affiliate-platform.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-wp-affiliate-platform.zip" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: PMPro WP Affiliate Platform Integration
4
+ Slug: pmpro-wp-affiliate
5
+ */
6
+ pmpro_add_addon('thirdparty', array(
7
+ 'title' => 'PMPro WP Affiliate Platform Integration',
8
+ 'version' => '.3',
9
+ 'widget' => 'pmpro_addon_pmpro_wp_affiliate_widget',
10
+ 'enabled' => function_exists('wpa_pmpro_after_checkout')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_pmpro_wp_affiliate_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/pmpro-wp-affiliate-platform.jpg" />
18
+ <div class="info">
19
+ <p>Process an affiliate via WP Affiliate Platform after a PMPro checkout.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="https://github.com/strangerstudios/pmpro-wp-affiliate-platform/" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../pmpro-wp-affiliate-platform/pmpro-wp-affiliate-platform.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=pmpro-wp-affiliate-platform/pmpro-wp-affiliate-platform.php'), 'activate-plugin_pmpro-wp-affiliate-platform/pmpro-wp-affiliate-platform.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="http://www.paidmembershipspro.com/wp-content/uploads/plugins/pmpro-wp-affiliate-platform.zip" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/addons/tml.php CHANGED
@@ -1,32 +1,32 @@
1
- <?php
2
- /*
3
- Addon: Theme My Login
4
- Slug: pmpro-tml
5
- */
6
- pmpro_add_addon('recommended', array(
7
- 'title' => 'Theme My Login',
8
- 'widget' => 'pmpro_addon_tml_widget',
9
- 'enabled' => class_exists('Theme_My_Login'),
10
- 'version' => '6.3.10'
11
- )
12
- );
13
-
14
- function pmpro_addon_tml_widget($addon)
15
- {
16
- ?>
17
- <div class="info">
18
- <p>This plugin themes the WordPress login, registration and forgot password pages according to your current theme. By <a href="http://www.jfarthing.com/" target="_blank">Jeff Farthing</a></p>
19
- <div class="actions">
20
- <form method="post" name="component-actions" action="">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../theme-my-login/theme-my-login.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=theme-my-login/theme-my-login.php'), 'activate-plugin_theme-my-login/theme-my-login.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=theme-my-login'), 'install-plugin_theme-my-login'); ?>" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </form>
29
- </div>
30
- </div> <!-- end info -->
31
- <?php
32
- }
1
+ <?php
2
+ /*
3
+ Addon: Theme My Login
4
+ Slug: pmpro-tml
5
+ */
6
+ pmpro_add_addon('recommended', array(
7
+ 'title' => 'Theme My Login',
8
+ 'widget' => 'pmpro_addon_tml_widget',
9
+ 'enabled' => class_exists('Theme_My_Login'),
10
+ 'version' => '6.3.10'
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_tml_widget($addon)
15
+ {
16
+ ?>
17
+ <div class="info">
18
+ <p>This plugin themes the WordPress login, registration and forgot password pages according to your current theme. By <a href="http://www.jfarthing.com/" target="_blank">Jeff Farthing</a></p>
19
+ <div class="actions">
20
+ <form method="post" name="component-actions" action="">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="<?php echo admin_url("plugins.php");?>" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../theme-my-login/theme-my-login.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=theme-my-login/theme-my-login.php'), 'activate-plugin_theme-my-login/theme-my-login.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=theme-my-login'), 'install-plugin_theme-my-login'); ?>" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </form>
29
+ </div>
30
+ </div> <!-- end info -->
31
+ <?php
32
+ }
adminpages/addons/wp-bouncer.php CHANGED
@@ -1,31 +1,31 @@
1
- <?php
2
- /*
3
- Addon: WP Bouncer
4
- Slug: wp-bouncer
5
- */
6
- pmpro_add_addon('repo', array(
7
- 'title' => 'WP Bouncer',
8
- 'version' => '1.1',
9
- 'widget' => 'pmpro_addon_wp_bouncer_widget',
10
- 'enabled' => class_exists('WP_Bouncer')
11
- )
12
- );
13
-
14
- function pmpro_addon_wp_bouncer_widget($addon)
15
- {
16
- ?>
17
- <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/wp-bouncer.gif" />
18
- <div class="info">
19
- <p>Make sure users are only logged in from one computer or device at a time.</p>
20
- <div class="actions">
21
- <?php if($addon['enabled']) { ?>
22
- <a href="http://wordpress.org/plugins/wp-bouncer/" class="button">Enabled</a>
23
- <?php } elseif(file_exists(dirname(__FILE__) . "/../../../wp-bouncer/wp-bouncer.php")) { ?>
24
- <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=wp-bouncer/wp-bouncer.php'), 'activate-plugin_wp-bouncer/wp-bouncer.php')?>" class="button button-primary">Activate</a>
25
- <?php } else { ?>
26
- <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=wp-bouncer'), 'install-plugin_wp-bouncer'); ?>" class="button button-primary">Download</a>
27
- <?php } ?>
28
- </div>
29
- </div> <!-- end info -->
30
- <?php
31
- }
1
+ <?php
2
+ /*
3
+ Addon: WP Bouncer
4
+ Slug: wp-bouncer
5
+ */
6
+ pmpro_add_addon('repo', array(
7
+ 'title' => 'WP Bouncer',
8
+ 'version' => '1.1',
9
+ 'widget' => 'pmpro_addon_wp_bouncer_widget',
10
+ 'enabled' => class_exists('WP_Bouncer')
11
+ )
12
+ );
13
+
14
+ function pmpro_addon_wp_bouncer_widget($addon)
15
+ {
16
+ ?>
17
+ <img class="addon-thumb" src="<?php echo PMPRO_URL?>/adminpages/addons/images/wp-bouncer.gif" />
18
+ <div class="info">
19
+ <p>Make sure users are only logged in from one computer or device at a time.</p>
20
+ <div class="actions">
21
+ <?php if($addon['enabled']) { ?>
22
+ <a href="http://wordpress.org/plugins/wp-bouncer/" class="button">Enabled</a>
23
+ <?php } elseif(file_exists(dirname(__FILE__) . "/../../../wp-bouncer/wp-bouncer.php")) { ?>
24
+ <a href="<?php echo wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin=wp-bouncer/wp-bouncer.php'), 'activate-plugin_wp-bouncer/wp-bouncer.php')?>" class="button button-primary">Activate</a>
25
+ <?php } else { ?>
26
+ <a href="<?php echo wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=wp-bouncer'), 'install-plugin_wp-bouncer'); ?>" class="button button-primary">Download</a>
27
+ <?php } ?>
28
+ </div>
29
+ </div> <!-- end info -->
30
+ <?php
31
+ }
adminpages/admin_footer.php CHANGED
@@ -1,2 +1,2 @@
1
- <div class="clear"></div>
2
  </div>
1
+ <div class="clear"></div>
2
  </div>
adminpages/admin_header.php CHANGED
@@ -1,156 +1,173 @@
1
- <?php
2
- require_once(dirname(__FILE__) . "/functions.php");
3
-
4
- if(isset($_REQUEST['page']))
5
- $view = $_REQUEST['page'];
6
- else
7
- $view = "";
8
-
9
- global $pmpro_ready, $msg, $msgt;
10
- $pmpro_ready = pmpro_is_ready();
11
- if(!$pmpro_ready)
12
- {
13
- global $pmpro_level_ready, $pmpro_gateway_ready, $pmpro_pages_ready;
14
- if(!isset($edit))
15
- {
16
- if(isset($_REQUEST['edit']))
17
- $edit = $_REQUEST['edit'];
18
- else
19
- $edit = false;
20
- }
21
-
22
- if(empty($msg))
23
- $msg = -1;
24
- if(empty($pmpro_level_ready) && empty($edit))
25
- $msgt .= " <a href=\"?page=pmpro-membershiplevels&edit=-1\">" . __("Add a membership level to get started.", "pmpro") . "</a>";
26
- elseif($pmpro_level_ready && !$pmpro_pages_ready && $view != "pmpro-pagesettings")
27
- $msgt .= " <a href=\"?page=pmpro-pagesettings\">" . __("Setup the membership pages", "pmpro") . "</a>.";
28
- elseif($pmpro_level_ready && $pmpro_pages_ready && !$pmpro_gateway_ready && $view != "pmpro-paymentsettings")
29
- $msgt .= " <a href=\"?page=pmpro-paymentsettings\">" . __("Setup your SSL certificate and payment gateway", "pmpro") . "</a>.";
30
-
31
- if(empty($msgt))
32
- $msg = false;
33
- }
34
-
35
- if(!pmpro_checkLevelForStripeCompatibility())
36
- {
37
- $msg = -1;
38
- $msgt = __("The billing details for some of your membership levels is not supported by Stripe.", "pmpro");
39
- if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
40
- {
41
- if(!pmpro_checkLevelForStripeCompatibility($_REQUEST['edit']))
42
- {
43
- global $pmpro_stripe_error;
44
- $pmpro_stripe_error = true;
45
- $msg = -1;
46
- $msgt = __("The billing details for this level are not supported by Stripe. Please review the notes in the Billing Details section below.", "pmpro");
47
- }
48
- }
49
- elseif($view == "pmpro-membershiplevels")
50
- $msgt .= " " . __("The levels with issues are highlighted below.", "pmpro");
51
- else
52
- $msgt .= " <a href=\"?page=pmpro-membershiplevels\">" . __("Please edit your levels", "pmpro") . "</a>.";
53
- }
54
-
55
- if(!pmpro_checkLevelForPayflowCompatibility())
56
- {
57
- $msg = -1;
58
- $msgt = __("The billing details for some of your membership levels is not supported by Payflow.", "pmpro");
59
- if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
60
- {
61
- if(!pmpro_checkLevelForPayflowCompatibility($_REQUEST['edit']))
62
- {
63
- global $pmpro_payflow_error;
64
- $pmpro_payflow_error = true;
65
- $msg = -1;
66
- $msgt = __("The billing details for this level are not supported by Payflow. Please review the notes in the Billing Details section below.", "pmpro");
67
- }
68
- }
69
- elseif($view == "pmpro-membershiplevels")
70
- $msgt .= " " . __("The levels with issues are highlighted below.", "pmpro");
71
- else
72
- $msgt .= " <a href=\"?page=pmpro-membershiplevels\">" . __("Please edit your levels", "pmpro") . "</a>.";
73
- }
74
-
75
- if(!pmpro_checkLevelForBraintreeCompatibility())
76
- {
77
- $msg = -1;
78
- $msgt = __("The billing details for some of your membership levels is not supported by Braintree.", "pmpro");
79
- if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
80
- {
81
- if(!pmpro_checkLevelForBraintreeCompatibility($_REQUEST['edit']))
82
- {
83
- global $pmpro_braintree_error;
84
- $pmpro_braintree_error = true;
85
- $msg = -1;
86
- $msgt = __("The billing details for this level are not supported by Braintree. Please review the notes in the Billing Details section below.", "pmpro");
87
- }
88
- }
89
- elseif($view == "pmpro-membershiplevels")
90
- $msgt .= " " . __("The levels with issues are highlighted below.", "pmpro");
91
- else
92
- $msgt .= " <a href=\"?page=pmpro-membershiplevels\">" . __("Please edit your levels", "pmpro") . "</a>.";
93
- }
94
-
95
- if(!pmpro_checkLevelForTwoCheckoutCompatibility())
96
- {
97
- $msg = -1;
98
- $msgt = __("The billing details for some of your membership levels is not supported by TwoCheckout.", "pmpro");
99
- if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
100
- {
101
- if(!pmpro_checkLevelForTwoCheckoutCompatibility($_REQUEST['edit']))
102
- {
103
- global $pmpro_twocheckout_error;
104
- $pmpro_twocheckout_error = true;
105
-
106
- $msg = -1;
107
- $msgt = __("The billing details for this level are not supported by 2Checkout. Please review the notes in the Billing Details section below.", "pmpro");
108
- }
109
- }
110
- elseif($view == "pmpro-membershiplevels")
111
- $msgt .= " " . __("The levels with issues are highlighted below.", "pmpro");
112
- else
113
- $msgt .= " <a href=\"?page=pmpro-membershiplevels\">" . __("Please edit your levels", "pmpro") . "</a>.";
114
- }
115
-
116
- if(!empty($msg))
117
- {
118
- ?>
119
- <div id="message" class="<?php if($msg > 0) echo "updated fade"; else echo "error"; ?>"><p><?php echo $msgt?></p></div>
120
- <?php
121
- }
122
-
123
- ?>
124
- <div class="wrap pmpro_admin">
125
- <div class="pmpro_banner">
126
- <a class="pmpro_logo" title="Paid Memberships Pro - Membership Plugin for WordPress" target="_blank" href="<?php echo pmpro_https_filter("http://www.paidmembershipspro.com")?>"><img src="<?php echo PMPRO_URL?>/images/Paid-Memberships-Pro.png" width="350" height="75" border="0" alt="Paid Memberships Pro(c) - All Rights Reserved" /></a>
127
- <div class="pmpro_meta"><span class="pmpro_tag-grey">v<?php echo PMPRO_VERSION?></span><a target="_blank" class="pmpro_tag-blue" href="<?php echo pmpro_https_filter("http://www.paidmembershipspro.com")?>"><?php _e('Plugin Support', 'pmpro');?></a><a target="_blank" class="pmpro_tag-blue" href="http://www.paidmembershipspro.com/forums/"><?php _e('User Forum', 'pmpro');?></a></div>
128
-
129
- <br style="clear:both;" />
130
- </div>
131
-
132
- <div id="pmpro_notifications">
133
- </div>
134
- <script>
135
- jQuery(document).ready(function() {
136
- jQuery.get('<?php echo get_admin_url(NULL, "/admin-ajax.php?action=pmpro_notifications"); ?>', function(data) {
137
- if(data && data != 'NULL')
138
- jQuery('#pmpro_notifications').html(data);
139
- });
140
- });
141
- </script>
142
-
143
- <?php
144
- $settings_tabs = array("pmpro-membershiplevels", "pmpro-pagesettings", "pmpro-paymentsettings", "pmpro-emailsettings", "pmpro-advancedsettings", "pmpro-addons");
145
- if(in_array($view, $settings_tabs))
146
- {
147
- ?>
148
- <h2 class="nav-tab-wrapper">
149
- <a href="admin.php?page=pmpro-membershiplevels" class="nav-tab<?php if($view == 'pmpro-membershiplevels') { ?> nav-tab-active<?php } ?>"><?php _e('Membership Levels', 'pmpro');?></a>
150
- <a href="admin.php?page=pmpro-pagesettings" class="nav-tab<?php if($view == 'pmpro-pagesettings') { ?> nav-tab-active<?php } ?>"><?php _e('Pages', 'pmpro');?></a>
151
- <a href="admin.php?page=pmpro-paymentsettings" class="nav-tab<?php if($view == 'pmpro-paymentsettings') { ?> nav-tab-active<?php } ?>"><?php _e('Payment Gateway &amp; SSL', 'pmpro');?></a>
152
- <a href="admin.php?page=pmpro-emailsettings" class="nav-tab<?php if($view == 'pmpro-emailsettings') { ?> nav-tab-active<?php } ?>"><?php _e('Email', 'pmpro');?></a>
153
- <a href="admin.php?page=pmpro-advancedsettings" class="nav-tab<?php if($view == 'pmpro-advancedsettings') { ?> nav-tab-active<?php } ?>"><?php _e('Advanced', 'pmpro');?></a>
154
- <a href="admin.php?page=pmpro-addons" class="nav-tab<?php if($view == 'pmpro-addons') { ?> nav-tab-active<?php } ?>"><?php _e('Add Ons', 'pmpro');?></a>
155
- </h2>
156
- <?php } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once(dirname(__FILE__) . "/functions.php");
3
+
4
+ if(isset($_REQUEST['page']))
5
+ $view = $_REQUEST['page'];
6
+ else
7
+ $view = "";
8
+
9
+ global $pmpro_ready, $msg, $msgt;
10
+ $pmpro_ready = pmpro_is_ready();
11
+ if(!$pmpro_ready)
12
+ {
13
+ global $pmpro_level_ready, $pmpro_gateway_ready, $pmpro_pages_ready;
14
+ if(!isset($edit))
15
+ {
16
+ if(isset($_REQUEST['edit']))
17
+ $edit = $_REQUEST['edit'];
18
+ else
19
+ $edit = false;
20
+ }
21
+
22
+ if(empty($msg))
23
+ $msg = -1;
24
+ if(empty($pmpro_level_ready) && empty($edit))
25
+ $msgt .= " <a href=\"?page=pmpro-membershiplevels&edit=-1\">" . __("Add a membership level to get started.", "pmpro") . "</a>";
26
+ elseif($pmpro_level_ready && !$pmpro_pages_ready && $view != "pmpro-pagesettings")
27
+ $msgt .= " <a href=\"?page=pmpro-pagesettings\">" . __("Setup the membership pages", "pmpro") . "</a>.";
28
+ elseif($pmpro_level_ready && $pmpro_pages_ready && !$pmpro_gateway_ready && $view != "pmpro-paymentsettings")
29
+ $msgt .= " <a href=\"?page=pmpro-paymentsettings\">" . __("Setup your SSL certificate and payment gateway", "pmpro") . "</a>.";
30
+
31
+ if(empty($msgt))
32
+ $msg = false;
33
+ }
34
+
35
+ if(!pmpro_checkLevelForStripeCompatibility())
36
+ {
37
+ $msg = -1;
38
+ $msgt = __("The billing details for some of your membership levels is not supported by Stripe.", "pmpro");
39
+ if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
40
+ {
41
+ if(!pmpro_checkLevelForStripeCompatibility($_REQUEST['edit']))
42
+ {
43
+ global $pmpro_stripe_error;
44
+ $pmpro_stripe_error = true;
45
+ $msg = -1;
46
+ $msgt = __("The billing details for this level are not supported by Stripe. Please review the notes in the Billing Details section below.", "pmpro");
47
+ }
48
+ }
49
+ elseif($view == "pmpro-membershiplevels")
50
+ $msgt .= " " . __("The levels with issues are highlighted below.", "pmpro");
51
+ else
52
+ $msgt .= " <a href=\"?page=pmpro-membershiplevels\">" . __("Please edit your levels", "pmpro") . "</a>.";
53
+ }
54
+
55
+ if(!pmpro_checkLevelForPayflowCompatibility())
56
+ {
57
+ $msg = -1;
58
+ $msgt = __("The billing details for some of your membership levels is not supported by Payflow.", "pmpro");
59
+ if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
60
+ {
61
+ if(!pmpro_checkLevelForPayflowCompatibility($_REQUEST['edit']))
62
+ {
63
+ global $pmpro_payflow_error;
64
+ $pmpro_payflow_error = true;
65
+ $msg = -1;
66
+ $msgt = __("The billing details for this level are not supported by Payflow. Please review the notes in the Billing Details section below.", "pmpro");
67
+ }
68
+ }
69
+ elseif($view == "pmpro-membershiplevels")
70
+ $msgt .= " " . __("The levels with issues are highlighted below.", "pmpro");
71
+ else
72
+ $msgt .= " <a href=\"?page=pmpro-membershiplevels\">" . __("Please edit your levels", "pmpro") . "</a>.";
73
+ }
74
+
75
+ if(!pmpro_checkLevelForBraintreeCompatibility())
76
+ {
77
+ $msg = -1;
78
+ $msgt = __("The billing details for some of your membership levels is not supported by Braintree.", "pmpro");
79
+ if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
80
+ {
81
+ if(!pmpro_checkLevelForBraintreeCompatibility($_REQUEST['edit']))
82
+ {
83
+ global $pmpro_braintree_error;
84
+ $pmpro_braintree_error = true;
85
+ $msg = -1;
86
+ $msgt = __("The billing details for this level are not supported by Braintree. Please review the notes in the Billing Details section below.", "pmpro");
87
+ }
88
+ }
89
+ elseif($view == "pmpro-membershiplevels")
90
+ $msgt .= " " . __("The levels with issues are highlighted below.", "pmpro");
91
+ else
92
+ $msgt .= " <a href=\"?page=pmpro-membershiplevels\">" . __("Please edit your levels", "pmpro") . "</a>.";
93
+ }
94
+
95
+ if(!pmpro_checkLevelForTwoCheckoutCompatibility())
96
+ {
97
+ $msg = -1;
98
+ $msgt = __("The billing details for some of your membership levels is not supported by TwoCheckout.", "pmpro");
99
+ if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
100
+ {
101
+ if(!pmpro_checkLevelForTwoCheckoutCompatibility($_REQUEST['edit']))
102
+ {
103
+ global $pmpro_twocheckout_error;
104
+ $pmpro_twocheckout_error = true;
105
+
106
+ $msg = -1;
107
+ $msgt = __("The billing details for this level are not supported by 2Checkout. Please review the notes in the Billing Details section below.", "pmpro");
108
+ }
109
+ }
110
+ elseif($view == "pmpro-membershiplevels")
111
+ $msgt .= " " . __("The levels with issues are highlighted below.", "pmpro");
112
+ else
113
+ $msgt .= " <a href=\"?page=pmpro-membershiplevels\">" . __("Please edit your levels", "pmpro") . "</a>.";
114
+ }
115
+
116
+ if(!empty($msg))
117
+ {
118
+ ?>
119
+ <div id="message" class="<?php if($msg > 0) echo "updated fade"; else echo "error"; ?>"><p><?php echo $msgt?></p></div>
120
+ <?php
121
+ }
122
+
123
+ ?>
124
+ <div class="wrap pmpro_admin">
125
+ <div class="pmpro_banner">
126
+ <a class="pmpro_logo" title="Paid Memberships Pro - Membership Plugin for WordPress" target="_blank" href="<?php echo pmpro_https_filter("http://www.paidmembershipspro.com")?>"><img src="<?php echo PMPRO_URL?>/images/Paid-Memberships-Pro.png" width="350" height="75" border="0" alt="Paid Memberships Pro(c) - All Rights Reserved" /></a>
127
+ <div class="pmpro_meta"><span class="pmpro_tag-grey">v<?php echo PMPRO_VERSION?></span><a target="_blank" class="pmpro_tag-blue" href="<?php echo pmpro_https_filter("http://www.paidmembershipspro.com")?>"><?php _e('Plugin Support', 'pmpro');?></a><a target="_blank" class="pmpro_tag-blue" href="http://www.paidmembershipspro.com/forums/"><?php _e('User Forum', 'pmpro');?></a></div>
128
+
129
+ <br style="clear:both;" />
130
+ </div>
131
+
132
+ <div id="pmpro_notifications">
133
+ </div>
134
+ <script>
135
+ jQuery(document).ready(function() {
136
+ jQuery.get('<?php echo get_admin_url(NULL, "/admin-ajax.php?action=pmpro_notifications"); ?>', function(data) {
137
+ if(data && data != 'NULL')
138
+ jQuery('#pmpro_notifications').html(data);
139
+ });
140
+ });
141
+ </script>
142
+
143
+ <?php
144
+ $settings_tabs = array("pmpro-membershiplevels", "pmpro-pagesettings", "pmpro-paymentsettings", "pmpro-emailsettings", "pmpro-advancedsettings", "pmpro-addons");
145
+ if(in_array($view, $settings_tabs))
146
+ {
147
+ ?>
148
+ <h2 class="nav-tab-wrapper">
149
+ <?php if(current_user_can('pmpro_membershiplevels')) { ?>
150
+ <a href="admin.php?page=pmpro-membershiplevels" class="nav-tab<?php if($view == 'pmpro-membershiplevels') { ?> nav-tab-active<?php } ?>"><?php _e('Membership Levels', 'pmpro');?></a>
151
+ <?php } ?>
152
+
153
+ <?php if(current_user_can('pmpro_pagesettings')) { ?>
154
+ <a href="admin.php?page=pmpro-pagesettings" class="nav-tab<?php if($view == 'pmpro-pagesettings') { ?> nav-tab-active<?php } ?>"><?php _e('Pages', 'pmpro');?></a>
155
+ <?php } ?>
156
+
157
+ <?php if(current_user_can('pmpro_paymentsettings')) { ?>
158
+ <a href="admin.php?page=pmpro-paymentsettings" class="nav-tab<?php if($view == 'pmpro-paymentsettings') { ?> nav-tab-active<?php } ?>"><?php _e('Payment Gateway &amp; SSL', 'pmpro');?></a>
159
+ <?php } ?>
160
+
161
+ <?php if(current_user_can('pmpro_emailsettings')) { ?>
162
+ <a href="admin.php?page=pmpro-emailsettings" class="nav-tab<?php if($view == 'pmpro-emailsettings') { ?> nav-tab-active<?php } ?>"><?php _e('Email', 'pmpro');?></a>
163
+ <?php } ?>
164
+
165
+ <?php if(current_user_can('pmpro_advancedsettings')) { ?>
166
+ <a href="admin.php?page=pmpro-advancedsettings" class="nav-tab<?php if($view == 'pmpro-advancedsettings') { ?> nav-tab-active<?php } ?>"><?php _e('Advanced', 'pmpro');?></a>
167
+ <?php } ?>
168
+
169
+ <?php if(current_user_can('pmpro_addons')) { ?>
170
+ <a href="admin.php?page=pmpro-addons" class="nav-tab<?php if($view == 'pmpro-addons') { ?> nav-tab-active<?php } ?>"><?php _e('Add Ons', 'pmpro');?></a>
171
+ <?php } ?>
172
+ </h2>
173
+ <?php } ?>
adminpages/advancedsettings.php CHANGED
@@ -3,31 +3,31 @@
3
  if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_advancedsettings")))
4
  {
5
  die(__("You do not have permissions to perform this action.", "pmpro"));
6
- }
7
-
8
  global $wpdb, $msg, $msgt;
9
-
10
- //get/set settings
11
  if(!empty($_REQUEST['savesettings']))
12
- {
13
  //other settings
14
  pmpro_setOption("nonmembertext");
15
  pmpro_setOption("notloggedintext");
16
- pmpro_setOption("rsstext");
17
  pmpro_setOption("filterqueries");
18
  pmpro_setOption("showexcerpts");
19
  pmpro_setOption("hideads");
20
  pmpro_setOption("hideadslevels");
21
- pmpro_setOption("redirecttosubscription");
22
-
23
  //captcha
24
  pmpro_setOption("recaptcha");
25
  pmpro_setOption("recaptcha_publickey");
26
- pmpro_setOption("recaptcha_privatekey");
27
-
28
  //tos
29
- pmpro_setOption("tospage");
30
-
31
  //footer link
32
  pmpro_setOption("hide_footer_link");
33
 
@@ -37,58 +37,58 @@
37
  pmpro_setOption($key);
38
  }
39
  }
40
-
41
  //assume success
42
  $msg = true;
43
- $msgt = __("Your advanced settings have been updated.", "pmpro");
44
  }
45
 
46
  $nonmembertext = pmpro_getOption("nonmembertext");
47
  $notloggedintext = pmpro_getOption("notloggedintext");
48
- $rsstext = pmpro_getOption("rsstext");
49
  $hideads = pmpro_getOption("hideads");
50
  $filterqueries = pmpro_getOption('filterqueries');
51
  $showexcerpts = pmpro_getOption("showexcerpts");
52
  $hideadslevels = pmpro_getOption("hideadslevels");
53
-
54
  if(is_multisite())
55
  $redirecttosubscription = pmpro_getOption("redirecttosubscription");
56
-
57
  $recaptcha = pmpro_getOption("recaptcha");
58
  $recaptcha_publickey = pmpro_getOption("recaptcha_publickey");
59
  $recaptcha_privatekey = pmpro_getOption("recaptcha_privatekey");
60
-
61
  $tospage = pmpro_getOption("tospage");
62
-
63
  $hide_footer_link = pmpro_getOption("hide_footer_link");
64
-
65
  //default settings
66
  if(!$nonmembertext)
67
  {
68
  $nonmembertext = sprintf( __( 'This content is for !!levels!! members only. <a href="%s">Register here</a>.', 'pmpro' ), wp_login_url() . "?action=register" );
69
  pmpro_setOption("nonmembertext", $nonmembertext);
70
- }
71
  if(!$notloggedintext)
72
  {
73
  $notloggedintext = sprintf( __( 'Please <a href="%s">login</a> to view this content. (<a href="%s">Register here</a>.)', 'pmpro' ), wp_login_url( get_permalink() ), wp_login_url() . "?action=register" );
74
  pmpro_setOption("notloggedintext", $notloggedintext);
75
- }
76
  if(!$rsstext)
77
  {
78
  $rsstext = __( 'This content is for members only. Visit the site and log in/register to read.', 'pmpro' );
79
  pmpro_setOption("rsstext", $rsstext);
80
- }
81
-
82
  $levels = $wpdb->get_results( "SELECT * FROM {$wpdb->pmpro_membership_levels}", OBJECT );
83
-
84
- require_once(dirname(__FILE__) . "/admin_header.php");
85
  ?>
86
 
87
- <form action="" method="post" enctype="multipart/form-data">
88
  <h2><?php _e('Advanced Settings', 'pmpro');?></h2>
89
-
90
  <table class="form-table">
91
- <tbody>
92
  <tr>
93
  <th scope="row" valign="top">
94
  <label for="nonmembertext"><?php _e('Message for Logged-in Non-members', 'pmpro');?>:</label>
@@ -97,7 +97,7 @@
97
  <textarea name="nonmembertext" rows="3" cols="80"><?php echo stripslashes($nonmembertext)?></textarea><br />
98
  <small class="litegray"><?php _e('This message replaces the post content for non-members. Available variables', 'pmpro');?>: !!levels!!, !!referrer!!</small>
99
  </td>
100
- </tr>
101
  <tr>
102
  <th scope="row" valign="top">
103
  <label for="notloggedintext"><?php _e('Message for Logged-out Users', 'pmpro');?>:</label>
@@ -106,7 +106,7 @@
106
  <textarea name="notloggedintext" rows="3" cols="80"><?php echo stripslashes($notloggedintext)?></textarea><br />
107
  <small class="litegray"><?php _e('This message replaces the post content for logged-out visitors.', 'pmpro');?></small>
108
  </td>
109
- </tr>
110
  <tr>
111
  <th scope="row" valign="top">
112
  <label for="rsstext"><?php _e('Message for RSS Feed', 'pmpro');?>:</label>
@@ -115,8 +115,8 @@
115
  <textarea name="rsstext" rows="3" cols="80"><?php echo stripslashes($rsstext)?></textarea><br />
116
  <small class="litegray"><?php _e('This message replaces the post content in RSS feeds.', 'pmpro');?></small>
117
  </td>
118
- </tr>
119
-
120
  <tr>
121
  <th scope="row" valign="top">
122
  <label for="filterqueries"><?php _e("Filter searches and archives?", 'pmpro');?></label>
@@ -124,10 +124,10 @@
124
  <td>
125
  <select id="filterqueries" name="filterqueries">
126
  <option value="0" <?php if(!$filterqueries) { ?>selected="selected"<?php } ?>><?php _e('No - Non-members will see restricted posts/pages in searches and archives.', 'pmpro');?></option>
127
- <option value="1" <?php if($filterqueries == 1) { ?>selected="selected"<?php } ?>><?php _e('Yes - Only members will see restricted posts/pages in searches and archives.', 'pmpro');?></option>
128
- </select>
129
  </td>
130
- </tr>
131
  <tr>
132
  <th scope="row" valign="top">
133
  <label for="showexcerpts"><?php _e('Show Excerpts to Non-Members?', 'pmpro');?></label>
@@ -141,16 +141,16 @@
141
  </tr>
142
  <tr>
143
  <th scope="row" valign="top">
144
- <label for="hideads">Hide Ads From Members?</label>
145
  </th>
146
  <td>
147
  <select id="hideads" name="hideads" onchange="pmpro_updateHideAdsTRs();">
148
  <option value="0" <?php if(!$hideads) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
149
  <option value="1" <?php if($hideads == 1) { ?>selected="selected"<?php } ?>><?php _e('Hide Ads From All Members', 'pmpro');?></option>
150
  <option value="2" <?php if($hideads == 2) { ?>selected="selected"<?php } ?>><?php _e('Hide Ads From Certain Members', 'pmpro');?></option>
151
- </select>
152
  </td>
153
- </tr>
154
  <tr id="hideads_explanation" <?php if($hideads < 2) { ?>style="display: none;"<?php } ?>>
155
  <th scope="row" valign="top">&nbsp;</th>
156
  <td>
@@ -161,42 +161,42 @@ if(pmpro_displayAds())
161
  {
162
  //insert ad code here
163
  }
164
- </pre>
165
  </td>
166
- </tr>
167
  <tr id="hideadslevels_tr" <?php if($hideads != 2) { ?>style="display: none;"<?php } ?>>
168
  <th scope="row" valign="top">
169
  <label for="hideadslevels"><?php _e('Choose Levels to Hide Ads From', 'pmpro');?>:</label>
170
  </th>
171
  <td>
172
  <div class="checkbox_box" <?php if(count($levels) > 5) { ?>style="height: 100px; overflow: auto;"<?php } ?>>
173
- <?php
174
  $hideadslevels = pmpro_getOption("hideadslevels");
175
  if(!is_array($hideadslevels))
176
  $hideadslevels = explode(",", $hideadslevels);
177
-
178
- $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ";
179
- $levels = $wpdb->get_results($sqlQuery, OBJECT);
180
- foreach($levels as $level)
181
- {
182
  ?>
183
  <div class="clickable"><input type="checkbox" id="hideadslevels_<?php echo $level->id?>" name="hideadslevels[]" value="<?php echo $level->id?>" <?php if(in_array($level->id, $hideadslevels)) { ?>checked="checked"<?php } ?>> <?php echo $level->name?></div>
184
- <?php
185
- }
186
  ?>
187
- </div>
188
  <script>
189
  jQuery('.checkbox_box input').click(function(event) {
190
  event.stopPropagation()
191
  });
192
 
193
- jQuery('.checkbox_box div.clickable').click(function() {
194
  var checkbox = jQuery(this).find(':checkbox');
195
  checkbox.attr('checked', !checkbox.attr('checked'));
196
  });
197
  </script>
198
  </td>
199
- </tr>
200
  <?php if(is_multisite()) { ?>
201
  <tr>
202
  <th scope="row" valign="top">
@@ -205,11 +205,11 @@ if(pmpro_displayAds())
205
  <td>
206
  <select id="redirecttosubscription" name="redirecttosubscription">
207
  <option value="0" <?php if(!$redirecttosubscription) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
208
- <option value="1" <?php if($redirecttosubscription == 1) { ?>selected="selected"<?php } ?>><?php _e('Yes', 'pmpro');?></option>
209
- </select>
210
  </td>
211
- </tr>
212
- <?php } ?>
213
  <tr>
214
  <th scope="row" valign="top">
215
  <label for="recaptcha"><?php _e('Use reCAPTCHA?', 'pmpro');?>:</label>
@@ -217,20 +217,20 @@ if(pmpro_displayAds())
217
  <td>
218
  <select id="recaptcha" name="recaptcha" onchange="pmpro_updateRecaptchaTRs();">
219
  <option value="0" <?php if(!$recaptcha) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
220
- <option value="1" <?php if($recaptcha == 1) { ?>selected="selected"<?php } ?>><?php _e('Yes - Free memberships only.', 'pmpro');?></option>
221
  <option value="2" <?php if($recaptcha == 2) { ?>selected="selected"<?php } ?>><?php _e('Yes - All memberships.', 'pmpro');?></option>
222
  </select><br />
223
- <small><?php _e('A free reCAPTCHA key is required.', 'pmpro');?> <a href="https://www.google.com/recaptcha/admin/create"><?php _e('Click here to signup for reCAPTCHA', 'pmpro');?></a>.</small>
224
  </td>
225
- </tr>
226
  <tr id="recaptcha_tr" <?php if(!$recaptcha) { ?>style="display: none;"<?php } ?>>
227
  <th scope="row" valign="top">&nbsp;</th>
228
- <td>
229
  <label for="recaptcha_publickey"><?php _e('reCAPTCHA Public Key', 'pmpro');?>:</label>
230
  <input type="text" name="recaptcha_publickey" size="60" value="<?php echo $recaptcha_publickey?>" />
231
  <br /><br />
232
  <label for="recaptcha_privatekey"><?php _e('reCAPTCHA Private Key', 'pmpro');?>:</label>
233
- <input type="text" name="recaptcha_privatekey" size="60" value="<?php echo $recaptcha_privatekey?>" />
234
  </td>
235
  </tr>
236
  <tr>
@@ -244,8 +244,8 @@ if(pmpro_displayAds())
244
  <br />
245
  <small><?php _e('If yes, create a WordPress page containing your TOS agreement and assign it using the dropdown above.', 'pmpro');?></small>
246
  </td>
247
- </tr>
248
-
249
  <?php /*
250
  <tr>
251
  <th scope="row" valign="top">
@@ -254,8 +254,8 @@ if(pmpro_displayAds())
254
  <td>
255
  <select id="hide_footer_link" name="hide_footer_link">
256
  <option value="0" <?php if(!$hide_footer_link) { ?>selected="selected"<?php } ?>>No - Leave the link. (Thanks!)</option>
257
- <option value="1" <?php if($hide_footer_link == 1) { ?>selected="selected"<?php } ?>>Yes - Hide the link.</option>
258
- </select>
259
  </td>
260
  </tr>
261
  */
@@ -329,46 +329,46 @@ if(pmpro_displayAds())
329
  function pmpro_updateHideAdsTRs()
330
  {
331
  var hideads = jQuery('#hideads').val();
332
- if(hideads == 2)
333
  {
334
  jQuery('#hideadslevels_tr').show();
335
- }
336
  else
337
  {
338
  jQuery('#hideadslevels_tr').hide();
339
  }
340
-
341
- if(hideads > 0)
342
  {
343
  jQuery('#hideads_explanation').show();
344
- }
345
  else
346
  {
347
  jQuery('#hideads_explanation').hide();
348
  }
349
  }
350
  pmpro_updateHideAdsTRs();
351
-
352
  function pmpro_updateRecaptchaTRs()
353
  {
354
  var recaptcha = jQuery('#recaptcha').val();
355
- if(recaptcha > 0)
356
  {
357
  jQuery('#recaptcha_tr').show();
358
- }
359
  else
360
  {
361
  jQuery('#recaptcha_tr').hide();
362
- }
363
  }
364
  pmpro_updateRecaptchaTRs();
365
  </script>
366
-
367
- <p class="submit">
368
- <input name="savesettings" type="submit" class="button button-primary" value="<?php _e('Save Settings', 'pmpro');?>" />
369
- </p>
370
  </form>
371
 
372
  <?php
373
- require_once(dirname(__FILE__) . "/admin_footer.php");
374
  ?>
3
  if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_advancedsettings")))
4
  {
5
  die(__("You do not have permissions to perform this action.", "pmpro"));
6
+ }
7
+
8
  global $wpdb, $msg, $msgt;
9
+
10
+ //get/set settings
11
  if(!empty($_REQUEST['savesettings']))
12
+ {
13
  //other settings
14
  pmpro_setOption("nonmembertext");
15
  pmpro_setOption("notloggedintext");
16
+ pmpro_setOption("rsstext");
17
  pmpro_setOption("filterqueries");
18
  pmpro_setOption("showexcerpts");
19
  pmpro_setOption("hideads");
20
  pmpro_setOption("hideadslevels");
21
+ pmpro_setOption("redirecttosubscription");
22
+
23
  //captcha
24
  pmpro_setOption("recaptcha");
25
  pmpro_setOption("recaptcha_publickey");
26
+ pmpro_setOption("recaptcha_privatekey");
27
+
28
  //tos
29
+ pmpro_setOption("tospage");
30
+
31
  //footer link
32
  pmpro_setOption("hide_footer_link");
33
 
37
  pmpro_setOption($key);
38
  }
39
  }
40
+
41
  //assume success
42
  $msg = true;
43
+ $msgt = __("Your advanced settings have been updated.", "pmpro");
44
  }
45
 
46
  $nonmembertext = pmpro_getOption("nonmembertext");
47
  $notloggedintext = pmpro_getOption("notloggedintext");
48
+ $rsstext = pmpro_getOption("rsstext");
49
  $hideads = pmpro_getOption("hideads");
50
  $filterqueries = pmpro_getOption('filterqueries');
51
  $showexcerpts = pmpro_getOption("showexcerpts");
52
  $hideadslevels = pmpro_getOption("hideadslevels");
53
+
54
  if(is_multisite())
55
  $redirecttosubscription = pmpro_getOption("redirecttosubscription");
56
+
57
  $recaptcha = pmpro_getOption("recaptcha");
58
  $recaptcha_publickey = pmpro_getOption("recaptcha_publickey");
59
  $recaptcha_privatekey = pmpro_getOption("recaptcha_privatekey");
60
+
61
  $tospage = pmpro_getOption("tospage");
62
+
63
  $hide_footer_link = pmpro_getOption("hide_footer_link");
64
+
65
  //default settings
66
  if(!$nonmembertext)
67
  {
68
  $nonmembertext = sprintf( __( 'This content is for !!levels!! members only. <a href="%s">Register here</a>.', 'pmpro' ), wp_login_url() . "?action=register" );
69
  pmpro_setOption("nonmembertext", $nonmembertext);
70
+ }
71
  if(!$notloggedintext)
72
  {
73
  $notloggedintext = sprintf( __( 'Please <a href="%s">login</a> to view this content. (<a href="%s">Register here</a>.)', 'pmpro' ), wp_login_url( get_permalink() ), wp_login_url() . "?action=register" );
74
  pmpro_setOption("notloggedintext", $notloggedintext);
75
+ }
76
  if(!$rsstext)
77
  {
78
  $rsstext = __( 'This content is for members only. Visit the site and log in/register to read.', 'pmpro' );
79
  pmpro_setOption("rsstext", $rsstext);
80
+ }
81
+
82
  $levels = $wpdb->get_results( "SELECT * FROM {$wpdb->pmpro_membership_levels}", OBJECT );
83
+
84
+ require_once(dirname(__FILE__) . "/admin_header.php");
85
  ?>
86
 
87
+ <form action="" method="post" enctype="multipart/form-data">
88
  <h2><?php _e('Advanced Settings', 'pmpro');?></h2>
89
+
90
  <table class="form-table">
91
+ <tbody>
92
  <tr>
93
  <th scope="row" valign="top">
94
  <label for="nonmembertext"><?php _e('Message for Logged-in Non-members', 'pmpro');?>:</label>
97
  <textarea name="nonmembertext" rows="3" cols="80"><?php echo stripslashes($nonmembertext)?></textarea><br />
98
  <small class="litegray"><?php _e('This message replaces the post content for non-members. Available variables', 'pmpro');?>: !!levels!!, !!referrer!!</small>
99
  </td>
100
+ </tr>
101
  <tr>
102
  <th scope="row" valign="top">
103
  <label for="notloggedintext"><?php _e('Message for Logged-out Users', 'pmpro');?>:</label>
106
  <textarea name="notloggedintext" rows="3" cols="80"><?php echo stripslashes($notloggedintext)?></textarea><br />
107
  <small class="litegray"><?php _e('This message replaces the post content for logged-out visitors.', 'pmpro');?></small>
108
  </td>
109
+ </tr>
110
  <tr>
111
  <th scope="row" valign="top">
112
  <label for="rsstext"><?php _e('Message for RSS Feed', 'pmpro');?>:</label>
115
  <textarea name="rsstext" rows="3" cols="80"><?php echo stripslashes($rsstext)?></textarea><br />
116
  <small class="litegray"><?php _e('This message replaces the post content in RSS feeds.', 'pmpro');?></small>
117
  </td>
118
+ </tr>
119
+
120
  <tr>
121
  <th scope="row" valign="top">
122
  <label for="filterqueries"><?php _e("Filter searches and archives?", 'pmpro');?></label>
124
  <td>
125
  <select id="filterqueries" name="filterqueries">
126
  <option value="0" <?php if(!$filterqueries) { ?>selected="selected"<?php } ?>><?php _e('No - Non-members will see restricted posts/pages in searches and archives.', 'pmpro');?></option>
127
+ <option value="1" <?php if($filterqueries == 1) { ?>selected="selected"<?php } ?>><?php _e('Yes - Only members will see restricted posts/pages in searches and archives.', 'pmpro');?></option>
128
+ </select>
129
  </td>
130
+ </tr>
131
  <tr>
132
  <th scope="row" valign="top">
133
  <label for="showexcerpts"><?php _e('Show Excerpts to Non-Members?', 'pmpro');?></label>
141
  </tr>
142
  <tr>
143
  <th scope="row" valign="top">
144
+ <label for="hideads"><?php _e("Hide Ads From Members?", 'pmpro');?></label>
145
  </th>
146
  <td>
147
  <select id="hideads" name="hideads" onchange="pmpro_updateHideAdsTRs();">
148
  <option value="0" <?php if(!$hideads) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
149
  <option value="1" <?php if($hideads == 1) { ?>selected="selected"<?php } ?>><?php _e('Hide Ads From All Members', 'pmpro');?></option>
150
  <option value="2" <?php if($hideads == 2) { ?>selected="selected"<?php } ?>><?php _e('Hide Ads From Certain Members', 'pmpro');?></option>
151
+ </select>
152
  </td>
153
+ </tr>
154
  <tr id="hideads_explanation" <?php if($hideads < 2) { ?>style="display: none;"<?php } ?>>
155
  <th scope="row" valign="top">&nbsp;</th>
156
  <td>
161
  {
162
  //insert ad code here
163
  }
164
+ </pre>
165
  </td>
166
+ </tr>
167
  <tr id="hideadslevels_tr" <?php if($hideads != 2) { ?>style="display: none;"<?php } ?>>
168
  <th scope="row" valign="top">
169
  <label for="hideadslevels"><?php _e('Choose Levels to Hide Ads From', 'pmpro');?>:</label>
170
  </th>
171
  <td>
172
  <div class="checkbox_box" <?php if(count($levels) > 5) { ?>style="height: 100px; overflow: auto;"<?php } ?>>
173
+ <?php
174
  $hideadslevels = pmpro_getOption("hideadslevels");
175
  if(!is_array($hideadslevels))
176
  $hideadslevels = explode(",", $hideadslevels);
177
+
178
+ $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ";
179
+ $levels = $wpdb->get_results($sqlQuery, OBJECT);
180
+ foreach($levels as $level)
181
+ {
182
  ?>
183
  <div class="clickable"><input type="checkbox" id="hideadslevels_<?php echo $level->id?>" name="hideadslevels[]" value="<?php echo $level->id?>" <?php if(in_array($level->id, $hideadslevels)) { ?>checked="checked"<?php } ?>> <?php echo $level->name?></div>
184
+ <?php
185
+ }
186
  ?>
187
+ </div>
188
  <script>
189
  jQuery('.checkbox_box input').click(function(event) {
190
  event.stopPropagation()
191
  });
192
 
193
+ jQuery('.checkbox_box div.clickable').click(function() {
194
  var checkbox = jQuery(this).find(':checkbox');
195
  checkbox.attr('checked', !checkbox.attr('checked'));
196
  });
197
  </script>
198
  </td>
199
+ </tr>
200
  <?php if(is_multisite()) { ?>
201
  <tr>
202
  <th scope="row" valign="top">
205
  <td>
206
  <select id="redirecttosubscription" name="redirecttosubscription">
207
  <option value="0" <?php if(!$redirecttosubscription) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
208
+ <option value="1" <?php if($redirecttosubscription == 1) { ?>selected="selected"<?php } ?>><?php _e('Yes', 'pmpro');?></option>
209
+ </select>
210
  </td>
211
+ </tr>
212
+ <?php } ?>
213
  <tr>
214
  <th scope="row" valign="top">
215
  <label for="recaptcha"><?php _e('Use reCAPTCHA?', 'pmpro');?>:</label>
217
  <td>
218
  <select id="recaptcha" name="recaptcha" onchange="pmpro_updateRecaptchaTRs();">
219
  <option value="0" <?php if(!$recaptcha) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
220
+ <option value="1" <?php if($recaptcha == 1) { ?>selected="selected"<?php } ?>><?php _e('Yes - Free memberships only.', 'pmpro');?></option>
221
  <option value="2" <?php if($recaptcha == 2) { ?>selected="selected"<?php } ?>><?php _e('Yes - All memberships.', 'pmpro');?></option>
222
  </select><br />
223
+ <small><?php _e('A free reCAPTCHA key is required.', 'pmpro');?> <a href="https://www.google.com/recaptcha/admin/create"><?php _e('Click here to signup for reCAPTCHA', 'pmpro');?></a>.</small>
224
  </td>
225
+ </tr>
226
  <tr id="recaptcha_tr" <?php if(!$recaptcha) { ?>style="display: none;"<?php } ?>>
227
  <th scope="row" valign="top">&nbsp;</th>
228
+ <td>
229
  <label for="recaptcha_publickey"><?php _e('reCAPTCHA Public Key', 'pmpro');?>:</label>
230
  <input type="text" name="recaptcha_publickey" size="60" value="<?php echo $recaptcha_publickey?>" />
231
  <br /><br />
232
  <label for="recaptcha_privatekey"><?php _e('reCAPTCHA Private Key', 'pmpro');?>:</label>
233
+ <input type="text" name="recaptcha_privatekey" size="60" value="<?php echo $recaptcha_privatekey?>" />
234
  </td>
235
  </tr>
236
  <tr>
244
  <br />
245
  <small><?php _e('If yes, create a WordPress page containing your TOS agreement and assign it using the dropdown above.', 'pmpro');?></small>
246
  </td>
247
+ </tr>
248
+
249
  <?php /*
250
  <tr>
251
  <th scope="row" valign="top">
254
  <td>
255
  <select id="hide_footer_link" name="hide_footer_link">
256
  <option value="0" <?php if(!$hide_footer_link) { ?>selected="selected"<?php } ?>>No - Leave the link. (Thanks!)</option>
257
+ <option value="1" <?php if($hide_footer_link == 1) { ?>selected="selected"<?php } ?>>Yes - Hide the link.</option>
258
+ </select>
259
  </td>
260
  </tr>
261
  */
329
  function pmpro_updateHideAdsTRs()
330
  {
331
  var hideads = jQuery('#hideads').val();
332
+ if(hideads == 2)
333
  {
334
  jQuery('#hideadslevels_tr').show();
335
+ }
336
  else
337
  {
338
  jQuery('#hideadslevels_tr').hide();
339
  }
340
+
341
+ if(hideads > 0)
342
  {
343
  jQuery('#hideads_explanation').show();
344
+ }
345
  else
346
  {
347
  jQuery('#hideads_explanation').hide();
348
  }
349
  }
350
  pmpro_updateHideAdsTRs();
351
+
352
  function pmpro_updateRecaptchaTRs()
353
  {
354
  var recaptcha = jQuery('#recaptcha').val();
355
+ if(recaptcha > 0)
356
  {
357
  jQuery('#recaptcha_tr').show();
358
+ }
359
  else
360
  {
361
  jQuery('#recaptcha_tr').hide();
362
+ }
363
  }
364
  pmpro_updateRecaptchaTRs();
365
  </script>
366
+
367
+ <p class="submit">
368
+ <input name="savesettings" type="submit" class="button button-primary" value="<?php _e('Save Settings', 'pmpro');?>" />
369
+ </p>
370
  </form>
371
 
372
  <?php
373
+ require_once(dirname(__FILE__) . "/admin_footer.php");
374
  ?>
adminpages/dashboard.php CHANGED
@@ -1,12 +1,12 @@
1
  <?php
2
  /*
3
- Much of this code is borroed from yst_plugin_tools.php in the Yoast WordPress SEO plugin. Thanks, Yoast!
4
  */
5
-
6
  global $pmpro_feed;
7
  $pmpro_feed = "http://feeds.feedburner.com/PaidMembershipsPro";
8
-
9
- function pmpro_postbox($id, $title, $content)
10
  {
11
  ?>
12
  <div id="<?php echo $id; ?>" class="postbox">
@@ -17,22 +17,22 @@
17
  </div>
18
  </div>
19
  <?php
20
- }
21
-
22
- function pmpro_fetch_rss_items( $num )
23
  {
24
  global $pmpro_feed;
25
-
26
  include_once(ABSPATH . WPINC . '/feed.php');
27
  $rss = fetch_feed( $pmpro_feed );
28
-
29
  // Bail if feed doesn't work
30
  if ( is_wp_error($rss) )
31
  return false;
32
-
33
  $rss_items = $rss->get_items( 0, $rss->get_item_quantity( $num ) );
34
-
35
- // If the feed was erroneously
36
  if ( !$rss_items ) {
37
  $md5 = md5( $pmpro_feed );
38
  delete_transient( 'feed_' . $md5 );
@@ -40,17 +40,17 @@
40
  $rss = fetch_feed( $pmpro_feed );
41
  $rss_items = $rss->get_items( 0, $rss->get_item_quantity( $num ) );
42
  }
43
-
44
  return $rss_items;
45
  }
46
-
47
  /**
48
  * Box with latest news from PaidMembershipsPro.com for sidebar
49
  */
50
- function pmpro_news()
51
  {
52
  $rss_items = pmpro_fetch_rss_items( 5 );
53
-
54
  $content = '<ul>';
55
  if ( !$rss_items ) {
56
  $content .= '<li class="pmpro_news">no news items, feed might be broken...</li>';
@@ -60,7 +60,7 @@
60
  $content .= '<a class="rsswidget" href="'.esc_url( $item->get_permalink(), $protocolls=null, 'display' ).'">'. esc_html( $item->get_title() ) .'</a> ';
61
  $content .= '</li>';
62
  }
63
- }
64
  $content .= '</ul>';
65
  $pmpro_postbox('pmprolatest', 'Recent Updates from PaidMembershipsPro.com', $content);
66
  }
@@ -68,12 +68,12 @@
68
  /**
69
  * Widget with latest news from PaidMembershipsPro.com for dashbaord
70
  */
71
- function pmpro_db_widget()
72
  {
73
  global $pmpro_feed;
74
-
75
  $options = get_option('pmpro_pmprodbwidget');
76
-
77
  $network = '';
78
  if ( function_exists('is_network_admin') && is_network_admin() )
79
  $network = '_network';
@@ -81,16 +81,16 @@
81
  if (isset($_POST['pmpro_removedbwidget'])) {
82
  $options['removedbwidget'.$network] = true;
83
  update_option('pmpro_pmprodbwidget',$options);
84
- }
85
  if ( isset($options['removedbwidget'.$network]) && $options['removedbwidget'.$network] ) {
86
  echo "If you reload, this widget will be gone and never appear again, unless you decide to delete the database option 'pmpro_pmprodbwidget'.";
87
  return;
88
  }
89
 
90
- $rss_items = pmpro_fetch_rss_items( 3 );
91
-
92
  echo "<ul>";
93
-
94
  if ( !$rss_items ) {
95
  echo '<li class="pmpro_news">no news items, feed might be broken...</li>';
96
  } else {
@@ -101,7 +101,7 @@
101
  echo '<div class="rssSummary">'. esc_html( pmpro_text_limit( strip_tags( $item->get_description() ), 150 ) ).'</div>';
102
  echo '</li>';
103
  }
104
- }
105
 
106
  echo '</ul>';
107
  echo '<br class="clear"/><div style="margin-top:10px;border-top: 1px solid #ddd; padding-top: 10px; text-align:center;">';
@@ -112,7 +112,7 @@
112
  echo '</div>';
113
  }
114
 
115
- function pmpro_widget_setup()
116
  {
117
  $network = '';
118
  if ( function_exists('is_network_admin') && is_network_admin() )
@@ -122,6 +122,6 @@
122
  if ( !isset($options['removedbwidget'.$network]) || !$options['removedbwidget'.$network] )
123
  wp_add_dashboard_widget( 'pmpro_db_widget' , 'The Latest From PaidMembershipsPro.com' , 'pmpro_db_widget');
124
  }
125
-
126
  add_action( 'wp_dashboard_setup', 'pmpro_widget_setup');
127
  ?>
1
  <?php
2
  /*
3
+ Much of this code is borroed from yst_plugin_tools.php in the Yoast WordPress SEO plugin. Thanks, Yoast!
4
  */
5
+
6
  global $pmpro_feed;
7
  $pmpro_feed = "http://feeds.feedburner.com/PaidMembershipsPro";
8
+
9
+ function pmpro_postbox($id, $title, $content)
10
  {
11
  ?>
12
  <div id="<?php echo $id; ?>" class="postbox">
17
  </div>
18
  </div>
19
  <?php
20
+ }
21
+
22
+ function pmpro_fetch_rss_items( $num )
23
  {
24
  global $pmpro_feed;
25
+
26
  include_once(ABSPATH . WPINC . '/feed.php');
27
  $rss = fetch_feed( $pmpro_feed );
28
+
29
  // Bail if feed doesn't work
30
  if ( is_wp_error($rss) )
31
  return false;
32
+
33
  $rss_items = $rss->get_items( 0, $rss->get_item_quantity( $num ) );
34
+
35
+ // If the feed was erroneously
36
  if ( !$rss_items ) {
37
  $md5 = md5( $pmpro_feed );
38
  delete_transient( 'feed_' . $md5 );
40
  $rss = fetch_feed( $pmpro_feed );
41
  $rss_items = $rss->get_items( 0, $rss->get_item_quantity( $num ) );
42
  }
43
+
44
  return $rss_items;
45
  }
46
+
47
  /**
48
  * Box with latest news from PaidMembershipsPro.com for sidebar
49
  */
50
+ function pmpro_news()
51
  {
52
  $rss_items = pmpro_fetch_rss_items( 5 );
53
+
54
  $content = '<ul>';
55
  if ( !$rss_items ) {
56
  $content .= '<li class="pmpro_news">no news items, feed might be broken...</li>';
60
  $content .= '<a class="rsswidget" href="'.esc_url( $item->get_permalink(), $protocolls=null, 'display' ).'">'. esc_html( $item->get_title() ) .'</a> ';
61
  $content .= '</li>';
62
  }
63
+ }
64
  $content .= '</ul>';
65
  $pmpro_postbox('pmprolatest', 'Recent Updates from PaidMembershipsPro.com', $content);
66
  }
68
  /**
69
  * Widget with latest news from PaidMembershipsPro.com for dashbaord
70
  */
71
+ function pmpro_db_widget()
72
  {
73
  global $pmpro_feed;
74
+
75
  $options = get_option('pmpro_pmprodbwidget');
76
+
77
  $network = '';
78
  if ( function_exists('is_network_admin') && is_network_admin() )
79
  $network = '_network';
81
  if (isset($_POST['pmpro_removedbwidget'])) {
82
  $options['removedbwidget'.$network] = true;
83
  update_option('pmpro_pmprodbwidget',$options);
84
+ }
85
  if ( isset($options['removedbwidget'.$network]) && $options['removedbwidget'.$network] ) {
86
  echo "If you reload, this widget will be gone and never appear again, unless you decide to delete the database option 'pmpro_pmprodbwidget'.";
87
  return;
88
  }
89
 
90
+ $rss_items = pmpro_fetch_rss_items( 3 );
91
+
92
  echo "<ul>";
93
+
94
  if ( !$rss_items ) {
95
  echo '<li class="pmpro_news">no news items, feed might be broken...</li>';
96
  } else {
101
  echo '<div class="rssSummary">'. esc_html( pmpro_text_limit( strip_tags( $item->get_description() ), 150 ) ).'</div>';
102
  echo '</li>';
103
  }
104
+ }
105
 
106
  echo '</ul>';
107
  echo '<br class="clear"/><div style="margin-top:10px;border-top: 1px solid #ddd; padding-top: 10px; text-align:center;">';
112
  echo '</div>';
113
  }
114
 
115
+ function pmpro_widget_setup()
116
  {
117
  $network = '';
118
  if ( function_exists('is_network_admin') && is_network_admin() )
122
  if ( !isset($options['removedbwidget'.$network]) || !$options['removedbwidget'.$network] )
123
  wp_add_dashboard_widget( 'pmpro_db_widget' , 'The Latest From PaidMembershipsPro.com' , 'pmpro_db_widget');
124
  }
125
+
126
  add_action( 'wp_dashboard_setup', 'pmpro_widget_setup');
127
  ?>
adminpages/discountcodes.php CHANGED
@@ -1,665 +1,665 @@
1
- <?php
2
- //only admins can get this
3
- if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_discountcodes")))
4
- {
5
- die(__("You do not have permissions to perform this action.", "pmpro"));
6
- }
7
-
8
- //vars
9
- global $wpdb, $pmpro_currency_symbol;
10
-
11
- if(isset($_REQUEST['edit']))
12
- $edit = $_REQUEST['edit'];
13
- else
14
- $edit = false;
15
-
16
- if(isset($_REQUEST['delete']))
17
- $delete = $_REQUEST['delete'];
18
- else
19
- $delete = false;
20
-
21
- if(isset($_REQUEST['saveid']))
22
- $saveid = $_POST['saveid'];
23
- else
24
- $saveid = false;
25
-
26
- if($saveid)
27
- {
28
- //get vars
29
- $code = $_POST['code'];
30
- $starts_month = $_POST['starts_month'];
31
- $starts_day = $_POST['starts_day'];
32
- $starts_year = $_POST['starts_year'];
33
- $expires_month = $_POST['expires_month'];
34
- $expires_day = $_POST['expires_day'];
35
- $expires_year = $_POST['expires_year'];
36
- $uses = $_POST['uses'];
37
-
38
- //fix up dates
39
- $starts = date("Y-m-d", strtotime($starts_month . "/" . $starts_day . "/" . $starts_year, current_time("timestamp")));
40
- $expires = date("Y-m-d", strtotime($expires_month . "/" . $expires_day . "/" . $expires_year, current_time("timestamp")));
41
-
42
- //updating or new?
43
- if($saveid > 0)
44
- {
45
- $sqlQuery = "UPDATE $wpdb->pmpro_discount_codes SET code = '" . esc_sql($code) . "', starts = '" . $starts . "', expires = '" . $expires . "', uses = '" . intval($uses) . "' WHERE id = '" . $saveid . "' LIMIT 1";
46
- if($wpdb->query($sqlQuery) !== false)
47
- {
48
- $pmpro_msg = __("Discount code updated successfully.", "pmpro");
49
- $pmpro_msgt = "success";
50
- $saved = true;
51
- $edit = $saveid;
52
- }
53
- else
54
- {
55
- $pmpro_msg = __("Error updating discount code. That code may already be in use.", "pmpro");
56
- $pmpro_msgt = "error";
57
- }
58
- }
59
- else
60
- {
61
- $sqlQuery = "INSERT INTO $wpdb->pmpro_discount_codes (code, starts, expires, uses) VALUES('" . esc_sql($code) . "', '" . $starts . "', '" . $expires . "', '" . intval($uses) . "')";
62
- if($wpdb->query($sqlQuery) !== false)
63
- {
64
- $pmpro_msg = __("Discount code added successfully.", "pmpro");
65
- $pmpro_msgt = "success";
66
- $saved = true;
67
- $edit = $wpdb->insert_id;
68
- //$saveid = $edit;
69
- }
70
- else
71
- {
72
- $pmpro_msg = __("Error adding discount code. That code may already be in use.", "pmpro") . $wpdb->last_error;
73
- $pmpro_msgt = "error";
74
- }
75
- }
76
-
77
- //now add the membership level rows
78
- if($saved && $edit > 0)
79
- {
80
- //get the submitted values
81
- $all_levels_a = $_REQUEST['all_levels'];
82
- if(!empty($_REQUEST['levels']))
83
- $levels_a = $_REQUEST['levels'];
84
- else
85
- $levels_a = array();
86
- $initial_payment_a = $_REQUEST['initial_payment'];
87
- if(!empty($_REQUEST['recurring']))
88
- $recurring_a = $_REQUEST['recurring'];
89
- $billing_amount_a = $_REQUEST['billing_amount'];
90
- $cycle_number_a = $_REQUEST['cycle_number'];
91
- $cycle_period_a = $_REQUEST['cycle_period'];
92
- $billing_limit_a = $_REQUEST['billing_limit'];
93
- if(!empty($_REQUEST['custom_trial']))
94
- $custom_trial_a = $_REQUEST['custom_trial'];
95
- $trial_amount_a = $_REQUEST['trial_amount'];
96
- $trial_limit_a = $_REQUEST['trial_limit'];
97
- if(!empty($_REQUEST['expiration']))
98
- $expiration_a = $_REQUEST['expiration'];
99
- $expiration_number_a = $_REQUEST['expiration_number'];
100
- $expiration_period_a = $_REQUEST['expiration_period'];
101
-
102
- //clear the old rows
103
- $sqlQuery = "DELETE FROM $wpdb->pmpro_discount_codes_levels WHERE code_id = '" . $edit . "'";
104
- $wpdb->query($sqlQuery);
105
-
106
- //add a row for each checked level
107
- if(!empty($levels_a))
108
- {
109
- foreach($levels_a as $level_id)
110
- {
111
- //get the values ready
112
- $n = array_search($level_id, $all_levels_a); //this is the key location of this level's values
113
- $initial_payment = $initial_payment_a[$n];
114
-
115
- //is this recurring?
116
- if(!empty($recurring_a))
117
- {
118
- if(in_array($level_id, $recurring_a))
119
- $recurring = 1;
120
- else
121
- $recurring = 0;
122
- }
123
- else
124
- $recurring = 0;
125
-
126
- if(!empty($recurring))
127
- {
128
- $billing_amount = $billing_amount_a[$n];
129
- $cycle_number = $cycle_number_a[$n];
130
- $cycle_period = $cycle_period_a[$n];
131
- $billing_limit = $billing_limit_a[$n];
132
-
133
- //custom trial
134
- if(!empty($custom_trial_a))
135
- {
136
- if(in_array($level_id, $custom_trial_a))
137
- $custom_trial = 1;
138
- else
139
- $custom_trial = 0;
140
- }
141
- else
142
- $custom_trial = 0;
143
-
144
- if(!empty($custom_trial))
145
- {
146
- $trial_amount = $trial_amount_a[$n];
147
- $trial_limit = $trial_limit_a[$n];
148
- }
149
- else
150
- {
151
- $trial_amount = '';
152
- $trial_limit = '';
153
- }
154
- }
155
- else
156
- {
157
- $billing_amount = '';
158
- $cycle_number = '';
159
- $cycle_period = 'Month';
160
- $billing_limit = '';
161
- $custom_trial = 0;
162
- $trial_amount = '';
163
- $trial_limit = '';
164
- }
165
-
166
- if(!empty($expiration_a))
167
- {
168
- if(in_array($level_id, $expiration_a))
169
- $expiration = 1;
170
- else
171
- $expiration = 0;
172
- }
173
- else
174
- $expiration = 0;
175
-
176
- if(!empty($expiration))
177
- {
178
- $expiration_number = $expiration_number_a[$n];
179
- $expiration_period = $expiration_period_a[$n];
180
- }
181
- else
182
- {
183
- $expiration_number = '';
184
- $expiration_period = 'Month';
185
- }
186
-
187
- //okay, do the insert
188
- $sqlQuery = "INSERT INTO $wpdb->pmpro_discount_codes_levels (code_id, level_id, initial_payment, billing_amount, cycle_number, cycle_period, billing_limit, trial_amount, trial_limit, expiration_number, expiration_period) VALUES('" . esc_sql($edit) . "', '" . esc_sql($level_id) . "', '" . (double)esc_sql($initial_payment) . "', '" . (double)esc_sql($billing_amount) . "', '" . intval(esc_sql($cycle_number)) . "', '" . esc_sql($cycle_period) . "', '" . intval(esc_sql($billing_limit)) . "', '" . (double)esc_sql($trial_amount) . "', '" . intval(esc_sql($trial_limit)) . "', '" . intval(esc_sql($expiration_number)) . "', '" . esc_sql($expiration_period) . "')";
189
-
190
- if($wpdb->query($sqlQuery) !== false)
191
- {
192
- //okay
193
- do_action("pmpro_save_discount_code_level", $edit, $level_id);
194
- }
195
- else
196
- {
197
- $level_errors[] = sprintf(__("Error saving values for the %s level.", "pmpro"), $wpdb->get_var("SELECT name FROM $wpdb->pmpro_membership_levels WHERE id = '" . $level_id . "' LIMIT 1"));
198
- }
199
- }
200
- }
201
-
202
- //errors?
203
- if(!empty($level_errors))
204
- {
205
- $pmpro_msg = __("There were errors updating the level values: ", "pmpro") . implode(" ", $level_errors);
206
- $pmpro_msgt = "error";
207
- }
208
- else
209
- {
210
- //all good. set edit = NULL so we go back to the overview page
211
- $edit = NULL;
212
-
213
- do_action("pmpro_save_discount_code", $saveid);
214
- }
215
- }
216
- }
217
-
218
- //are we deleting?
219
- if(!empty($delete))
220
- {
221
- //is this a code?
222
- $code = $wpdb->get_var("SELECT code FROM $wpdb->pmpro_discount_codes WHERE id = '" . $delete . "' LIMIT 1");
223
- if(!empty($code))
224
- {
225
- //action
226
- do_action("pmpro_delete_discount_code", $delete);
227
-
228
- //delete the code levels
229
- $r1 = $wpdb->query("DELETE FROM $wpdb->pmpro_discount_codes_levels WHERE code_id = '" . $delete . "'");
230
-
231
- if($r1 !== false)
232
- {
233
- //delete the code
234
- $r2 = $wpdb->query("DELETE FROM $wpdb->pmpro_discount_codes WHERE id = '" . $delete . "' LIMIT 1");
235
-
236
- if($r2 !== false)
237
- {
238
- $pmpro_msg = sprintf(__("Code %s deleted successfully.", "pmpro"), $code);
239
- $pmpro_msgt = "success";
240
- }
241
- else
242
- {
243
- $pmpro_msg = __("Error deleting discount code. The code was only partially deleted. Please try again.", "pmpro");
244
- $pmpro_msgt = "error";
245
- }
246
- }
247
- else
248
- {
249
- $pmpro_msg = __("Error deleting code. Please try again.", "pmpro");
250
- $pmpro_msgt = "error";
251
- }
252
- }
253
- else
254
- {
255
- $pmpro_msg = __("Code not found.", "pmpro");
256
- $pmpro_msgt = "error";
257
- }
258
- }
259
-
260
- require_once(dirname(__FILE__) . "/admin_header.php");
261
- ?>
262
-
263
- <?php if($edit) { ?>
264
-
265
- <h2>
266
- <?php
267
- if($edit > 0)
268
- echo __("Edit Discount Code", "pmpro");
269
- else
270
- echo __("Add New Discount Code", "pmpro");
271
- ?>
272
- </h2>
273
-
274
- <?php if(!empty($pmpro_msg)) { ?>
275
- <div id="message" class="<?php if($pmpro_msgt == "success") echo "updated fade"; else echo "error"; ?>"><p><?php echo $pmpro_msg?></p></div>
276
- <?php } ?>
277
-
278
- <div>
279
- <?php
280
- // get the code...
281
- if($edit > 0)
282
- {
283
- $code = $wpdb->get_row("SELECT *, UNIX_TIMESTAMP(starts) as starts, UNIX_TIMESTAMP(expires) as expires FROM $wpdb->pmpro_discount_codes WHERE id = '" . $edit . "' LIMIT 1", OBJECT);
284
- $uses = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->pmpro_discount_codes_uses WHERE code_id = '" . $code->id . "'");
285
- $levels = $wpdb->get_results("SELECT l.id, l.name, cl.initial_payment, cl.billing_amount, cl.cycle_number, cl.cycle_period, cl.billing_limit, cl.trial_amount, cl.trial_limit FROM $wpdb->pmpro_membership_levels l LEFT JOIN $wpdb->pmpro_discount_codes_levels cl ON l.id = cl.level_id WHERE cl.code_id = '" . $code->code . "'");
286
- $temp_id = $code->id;
287
- }
288
- elseif(!empty($copy) && $copy > 0)
289
- {
290
- $code = $wpdb->get_row("SELECT *, UNIX_TIMESTAMP(starts) as starts, UNIX_TIMESTAMP(expires) as expires FROM $wpdb->pmpro_discount_codes WHERE id = '" . $copy . "' LIMIT 1", OBJECT);
291
- $temp_id = $level->id;
292
- $level->id = NULL;
293
- }
294
-
295
- // didn't find a discount code, let's add a new one...
296
- if(empty($code->id)) $edit = -1;
297
-
298
- //defaults for new codes
299
- if($edit == -1)
300
- {
301
- $code = new stdClass();
302
- $code->code = pmpro_getDiscountCode();
303
- }
304
- ?>
305
- <form action="" method="post">
306
- <input name="saveid" type="hidden" value="<?php echo $edit?>" />
307
- <table class="form-table">
308
- <tbody>
309
- <tr>
310
- <th scope="row" valign="top"><label><?php _e('ID', 'pmpro');?>:</label></th>
311
- <td class="pmpro_lite"><?php if(!empty($code->id)) echo $code->id; else echo __("This will be generated when you save.", "pmpro");?></td>
312
- </tr>
313
-
314
- <tr>
315
- <th scope="row" valign="top"><label for="code"><?php _e('Code', 'pmpro');?>:</label></th>
316
- <td><input name="code" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($code->code))?>" /></td>
317
- </tr>
318
-
319
- <?php
320
- //some vars for the dates
321
- $current_day = date("j");
322
- if(!empty($code->starts))
323
- $selected_starts_day = date("j", $code->starts);
324
- else
325
- $selected_starts_day = $current_day;
326
- if(!empty($code->expires))
327
- $selected_expires_day = date("j", $code->expires);
328
- else
329
- $selected_expires_day = $current_day;
330
-
331
- $current_month = date("M");
332
- if(!empty($code->starts))
333
- $selected_starts_month = date("m", $code->starts);
334
- else
335
- $selected_starts_month = date("m");
336
- if(!empty($code->expires))
337
- $selected_expires_month = date("m", $code->expires);
338
- else
339
- $selected_expires_month = date("m");
340
-
341
- $current_year = date("Y");
342
- if(!empty($code->starts))
343
- $selected_starts_year = date("Y", $code->starts);
344
- else
345
- $selected_starts_year = $current_year;
346
- if(!empty($code->expires))
347
- $selected_expires_year = date("Y", $code->expires);
348
- else
349
- $selected_expires_year = (int)$current_year + 1;
350
- ?>
351
-
352
- <tr>
353
- <th scope="row" valign="top"><label for="starts"><?php _e('Start Date', 'pmpro');?>:</label></th>
354
- <td>
355
- <select name="starts_month">
356
- <?php
357
- for($i = 1; $i < 13; $i++)
358
- {
359
- ?>
360
- <option value="<?php echo $i?>" <?php if($i == $selected_starts_month) { ?>selected="selected"<?php } ?>><?php echo date("M", strtotime($i . "/1/" . $current_year, current_time("timestamp")))?></option>
361
- <?php
362
- }
363
- ?>
364
- </select>
365
- <input name="starts_day" type="text" size="2" value="<?php echo $selected_starts_day?>" />
366
- <input name="starts_year" type="text" size="4" value="<?php echo $selected_starts_year?>" />
367
- </td>
368
- </tr>
369
-
370
- <tr>
371
- <th scope="row" valign="top"><label for="expires"><?php _e('Expiration Date', 'pmpro');?>:</label></th>
372
- <td>
373
- <select name="expires_month">
374
- <?php
375
- for($i = 1; $i < 13; $i++)
376
- {
377
- ?>
378
- <option value="<?php echo $i?>" <?php if($i == $selected_expires_month) { ?>selected="selected"<?php } ?>><?php echo date("M", strtotime($i . "/1/" . $current_year, current_time("timestamp")))?></option>
379
- <?php
380
- }
381
- ?>
382
- </select>
383
- <input name="expires_day" type="text" size="2" value="<?php echo $selected_expires_day?>" />
384
- <input name="expires_year" type="text" size="4" value="<?php echo $selected_expires_year?>" />
385
- </td>
386
- </tr>
387
-
388
- <tr>
389
- <th scope="row" valign="top"><label for="uses"><?php _e('Uses', 'pmpro');?>:</label></th>
390
- <td>
391
- <input name="uses" type="text" size="10" value="<?php if(!empty($code->uses)) echo str_replace("\"", "&quot;", stripslashes($code->uses));?>" />
392
- <small class="pmpro_lite"><?php _e('Leave blank for unlimited uses.', 'pmpro');?></small>
393
- </td>
394
- </tr>
395
-
396
- </tbody>
397
- </table>
398
-
399
- <?php do_action("pmpro_discount_code_after_settings"); ?>
400
-
401
- <h3><?php _e('Which Levels Will This Code Apply To?', 'pmpro'); ?></h3>
402
-
403
- <div class="pmpro_discount_levels">
404
- <?php
405
- $levels = $wpdb->get_results("SELECT * FROM $wpdb->pmpro_membership_levels");
406
- foreach($levels as $level)
407
- {
408
- //if this level is already managed for this discount code, use the code values
409
- if($edit > 0)
410
- {
411
- $code_level = $wpdb->get_row("SELECT l.id, cl.*, l.name, l.description, l.allow_signups FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id WHERE cl.code_id = '" . $edit . "' AND cl.level_id = '" . $level->id . "' LIMIT 1");
412
- if($code_level)
413
- {
414
- $level = $code_level;
415
- $level->checked = true;
416
- }
417
- else
418
- $level_checked = false;
419
- }
420
- else
421
- $level_checked = false;
422
- ?>
423
- <div>
424
- <input type="hidden" name="all_levels[]" value="<?php echo $level->id?>" />
425
- <input type="checkbox" id="levels_<?php echo $level->id;?>" name="levels[]" value="<?php echo $level->id?>" <?php if(!empty($level->checked)) { ?>checked="checked"<?php } ?> onclick="if(jQuery(this).is(':checked')) jQuery(this).next().next().show(); else jQuery(this).next().next().hide();" />
426
- <label for="levels_<?php echo $level->id;?>"><?php echo $level->name?></label>
427
- <div class="pmpro_discount_levels_pricing level_<?php echo $level->id?>" <?php if(empty($level->checked)) { ?>style="display: none;"<?php } ?>>
428
- <table class="form-table">
429
- <tbody>
430
- <tr>
431
- <th scope="row" valign="top"><label for="initial_payment"><?php _e('Initial Payment', 'pmpro');?>:</label></th>
432
- <td>
433
- <?php
434
- if(pmpro_getCurrencyPosition() == "left")
435
- echo $pmpro_currency_symbol;
436
- ?>
437
- <input name="initial_payment[]" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->initial_payment))?>" />
438
- <?php
439
- if(pmpro_getCurrencyPosition() == "right")
440
- echo $pmpro_currency_symbol;
441
- ?>
442
- <small><?php _e('The initial amount collected at registration.', 'pmpro');?></small>
443
- </td>
444
- </tr>
445
-
446
- <tr>
447
- <th scope="row" valign="top"><label><?php _e('Recurring Subscription', 'pmpro');?>:</label></th>
448
- <td><input class="recurring_checkbox" id="recurring_<?php echo $level->id;?>" name="recurring[]" type="checkbox" value="<?php echo $level->id?>" <?php if(pmpro_isLevelRecurring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).attr('checked')) { jQuery(this).parent().parent().siblings('.recurring_info').show(); if(!jQuery('#custom_trial_<?php echo $level->id?>').is(':checked')) jQuery(this).parent().parent().siblings('.trial_info').hide();} else jQuery(this).parent().parent().siblings('.recurring_info').hide();" /> <label for="recurring_<?php echo $level->id;?>"><?php _e('Check if this level has a recurring subscription payment.', 'pmpro');?></label></td>
449
- </tr>
450
-
451
- <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
452
- <th scope="row" valign="top"><label for="billing_amount"><?php _e('Billing Amount', 'pmpro');?>:</label></th>
453
- <td>
454
- <?php
455
- if(pmpro_getCurrencyPosition() == "left")
456
- echo $pmpro_currency_symbol;
457
- ?>
458
- <input name="billing_amount[]" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->billing_amount))?>" />
459
- <?php
460
- if(pmpro_getCurrencyPosition() == "right")
461
- echo $pmpro_currency_symbol;
462
- ?>
463
- <small>per</small>
464
- <input name="cycle_number[]" type="text" size="10" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->cycle_number))?>" />
465
- <select name="cycle_period[]" onchange="updateCyclePeriod();">
466
- <?php
467
- $cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
468
- foreach ( $cycles as $name => $value ) {
469
- echo "<option value='$value'";
470
- if ( $level->cycle_period == $value ) echo " selected='selected'";
471
- echo ">$name</option>";
472
- }
473
- ?>
474
- </select>
475
- <br /><small><?php _e('The amount to be billed one cycle after the initial payment.', 'pmpro');?></small>
476
- </td>
477
- </tr>
478
-
479
- <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
480
- <th scope="row" valign="top"><label for="billing_limit"><?php _e('Billing Cycle Limit', 'pmpro');?>:</label></th>
481
- <td>
482
- <input name="billing_limit[]" type="text" size="20" value="<?php echo $level->billing_limit?>" />
483
- <br /><small><?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.', 'pmpro');?></small>
484
- </td>
485
- </tr>
486
-
487
- <tr class="recurring_info" <?php if (!pmpro_isLevelRecurring($level)) echo "style='display:none;'";?>>
488
- <th scope="row" valign="top"><label><?php _e('Custom Trial', 'pmpro');?>:</label></th>
489
- <td><input id="custom_trial_<?php echo $level->id?>" id="custom_trial_<?php echo $level->id;?>" name="custom_trial[]" type="checkbox" value="<?php echo $level->id?>" <?php if ( pmpro_isLevelTrial($level) ) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).attr('checked')) jQuery(this).parent().parent().siblings('.trial_info').show(); else jQuery(this).parent().parent().siblings('.trial_info').hide();" /> <label for="custom_trial_<?php echo $level->id;?>"><?php _e('Check to add a custom trial period.', 'pmpro');?></label></td>
490
- </tr>
491
-
492
- <tr class="trial_info recurring_info" <?php if (!pmpro_isLevelTrial($level)) echo "style='display:none;'";?>>
493
- <th scope="row" valign="top"><label for="trial_amount"><?php _e('Trial Billing Amount', 'pmpro');?>:</label></th>
494
- <td>
495
- <?php
496
- if(pmpro_getCurrencyPosition() == "left")
497
- echo $pmpro_currency_symbol;
498
- ?>
499
- <input name="trial_amount[]" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->trial_amount))?>" />
500
- <?php
501
- if(pmpro_getCurrencyPosition() == "right")
502
- echo $pmpro_currency_symbol;
503
- ?>
504
- <small><?php _e('for the first', 'pmpro');?></small>
505
- <input name="trial_limit[]" type="text" size="10" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->trial_limit))?>" />
506
- <small><?php _e('subscription payments', 'pmpro');?>.</small>
507
- </td>
508
- </tr>
509
-
510
- <tr>
511
- <th scope="row" valign="top"><label><?php _e('Membership Expiration', 'pmpro');?>:</label></th>
512
- <td><input id="expiration_<?php echo $level->id;?>" name="expiration[]" type="checkbox" value="<?php echo $level->id?>" <?php if(pmpro_isLevelExpiring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).is(':checked')) { jQuery(this).parent().parent().siblings('.expiration_info').show(); } else { jQuery(this).parent().parent().siblings('.expiration_info').hide();}" /> <label for="expiration_<?php echo $level->id;?>"><?php _e('Check this to set when membership access expires.', 'pmpro');?></label></td>
513
- </tr>
514
-
515
- <tr class="expiration_info" <?php if(!pmpro_isLevelExpiring($level)) {?>style="display: none;"<?php } ?>>
516
- <th scope="row" valign="top"><label for="billing_amount"><?php _e('Expires In', 'pmpro');?>:</label></th>
517
- <td>
518
- <input id="expiration_number" name="expiration_number[]" type="text" size="10" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->expiration_number))?>" />
519
- <select id="expiration_period" name="expiration_period[]">
520
- <?php
521
- $cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
522
- foreach ( $cycles as $name => $value ) {
523
- echo "<option value='$value'";
524
- if ( $level->expiration_period == $value ) echo " selected='selected'";
525
- echo ">$name</option>";
526
- }
527
- ?>
528
- </select>
529
- <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.', 'pmpro');?></small>
530
- </td>
531
- </tr>
532
- </tbody>
533
- </table>
534
-
535
- <?php do_action("pmpro_discount_code_after_level_settings", $edit, $level); ?>
536
-
537
- </div>
538
- </div>
539
- <script>
540
-
541
- </script>
542
- <?php
543
- }
544
- ?>
545
- </div>
546
-
547
- <p class="submit topborder">
548
- <input name="save" type="submit" class="button button-primary" value="Save Code" />
549
- <input name="cancel" type="button" class="button button-secondary" value="Cancel" onclick="location.href='<?php echo get_admin_url(NULL, '/admin.php?page=pmpro-discountcodes')?>';" />
550
- </p>
551
- </form>
552
- </div>
553
-
554
- <?php } else { ?>
555
-
556
- <h2>
557
- <?php _e('Memberships Discount Codes', 'pmpro');?>
558
- <a href="admin.php?page=pmpro-discountcodes&edit=-1" class="add-new-h2"><?php _e('Add New Discount Code', 'pmpro');?></a>
559
- </h2>
560
-
561
- <?php if(!empty($pmpro_msg)) { ?>
562
- <div id="message" class="<?php if($pmpro_msgt == "success") echo "updated fade"; else echo "error"; ?>"><p><?php echo $pmpro_msg?></p></div>
563
- <?php } ?>
564
-
565
- <form id="posts-filter" method="get" action="">
566
- <p class="search-box">
567
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search Discount Codes', 'pmpro');?>:</label>
568
- <input type="hidden" name="page" value="pmpro-discountcodes" />
569
- <input id="post-search-input" type="text" value="<?php if(!empty($s)) echo $s;?>" name="s" size="30" />
570
- <input class="button" type="submit" value="<?php _e('Search', 'pmpro');?>" id="search-submit "/>
571
- </p>
572
- </form>
573
-
574
- <br class="clear" />
575
- <?php
576
- $sqlQuery = "SELECT *, UNIX_TIMESTAMP(starts) as starts, UNIX_TIMESTAMP(expires) as expires FROM $wpdb->pmpro_discount_codes ";
577
- if(!empty($s))
578
- $sqlQuery .= "WHERE code LIKE '%$s%' ";
579
- $sqlQuery .= "ORDER BY id ASC";
580
-
581
- $codes = $wpdb->get_results($sqlQuery, OBJECT);
582
- ?>
583
- <table class="widefat">
584
- <thead>
585
- <tr>
586
- <th><?php _e('ID', 'pmpro');?></th>
587
- <th><?php _e('Code', 'pmpro');?></th>
588
- <th><?php _e('Starts', 'pmpro');?></th>
589
- <th><?php _e('Expires', 'pmpro');?></th>
590
- <th><?php _e('Uses', 'pmpro');?></th>
591
- <th><?php _e('Levels', 'pmpro');?></th>
592
- <?php do_action("pmpro_discountcodes_extra_cols_header", $codes);?>
593
- <th></th>
594
- <th></th>
595
- </tr>
596
- </thead>
597
- <tbody>
598
- <?php
599
- if(!$codes)
600
- {
601
- ?>
602
- <tr><td colspan="7" class="pmpro_pad20">
603
- <p><?php _e('Discount codes allow you to offer your memberships at discounted prices to select customers.', 'pmpro');?> <a href="admin.php?page=pmpro-discountcodes&edit=-1"><?php _e('Create your first discount code now', 'pmpro');?></a>.</p>
604
- </td></tr>
605
- <?php
606
- }
607
- else
608
- {
609
- foreach($codes as $code)
610
- {
611
- ?>
612
- <tr<?php if($count++ % 2 == 1) { ?> class="alternate"<?php } ?>>
613
- <td><?php echo $code->id?></td>
614
- <td>
615
- <a href="?page=pmpro-discountcodes&edit=<?php echo $code->id?>"><?php echo $code->code?></a>
616
- </td>
617
- <td>
618
- <?php echo date(get_option('date_format'), $code->starts)?>
619
- </td>
620
- <td>
621
- <?php echo date(get_option('date_format'), $code->expires)?>
622
- </td>
623
- <td>
624
- <?php
625
- $uses = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->pmpro_discount_codes_uses WHERE code_id = '" . $code->id . "'");
626
- if($code->uses > 0)
627
- echo "<strong>" . (int)$uses . "</strong>/" . $code->uses;
628
- else
629
- echo "<strong>" . (int)$uses . "</strong>/unlimited";
630
- ?>
631
- </td>
632
- <td>
633
- <?php
634
- $sqlQuery = "SELECT l.id, l.name FROM $wpdb->pmpro_membership_levels l LEFT JOIN $wpdb->pmpro_discount_codes_levels cl ON l.id = cl.level_id WHERE cl.code_id = '" . $code->id . "'";
635
- $levels = $wpdb->get_results($sqlQuery);
636
-
637
- $level_names = array();
638
- foreach($levels as $level)
639
- $level_names[] = "<a target=\"_blank\" href=\"" . pmpro_url("checkout", "?level=" . $level->id . "&discount_code=" . $code->code) . "\">" . $level->name . "</a>";
640
- if($level_names)
641
- echo implode(", ", $level_names);
642
- else
643
- echo "None";
644
- ?>
645
- </td>
646
- <?php do_action("pmpro_discountcodes_extra_cols_body", $code);?>
647
- <td>
648
- <a href="?page=pmpro-discountcodes&edit=<?php echo $code->id?>"><?php _e('edit', 'pmpro');?></a>
649
- </td>
650
- <td>
651
- <a href="javascript:askfirst('<?php printf(__('Are you sure you want to delete the %s discount code? The subscriptions for existing users will not change, but new users will not be able to use this code anymore.', 'pmpro'), $code->code);?>', '?page=pmpro-discountcodes&delete=<?php echo $code->id?>'); void(0);"><?php _e('delete', 'pmpro');?></a>
652
- </td>
653
- </tr>
654
- <?php
655
- }
656
- }
657
- ?>
658
- </tbody>
659
- </table>
660
-
661
- <?php } ?>
662
-
663
- <?php
664
- require_once(dirname(__FILE__) . "/admin_footer.php");
665
- ?>
1
+ <?php
2
+ //only admins can get this
3
+ if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_discountcodes")))
4
+ {
5
+ die(__("You do not have permissions to perform this action.", "pmpro"));
6
+ }
7
+
8
+ //vars
9
+ global $wpdb, $pmpro_currency_symbol;
10
+
11
+ if(isset($_REQUEST['edit']))
12
+ $edit = $_REQUEST['edit'];
13
+ else
14
+ $edit = false;
15
+
16
+ if(isset($_REQUEST['delete']))
17
+ $delete = $_REQUEST['delete'];
18
+ else
19
+ $delete = false;
20
+
21
+ if(isset($_REQUEST['saveid']))
22
+ $saveid = $_POST['saveid'];
23
+ else
24
+ $saveid = false;
25
+
26
+ if($saveid)
27
+ {
28
+ //get vars
29
+ $code = $_POST['code'];
30
+ $starts_month = $_POST['starts_month'];
31
+ $starts_day = $_POST['starts_day'];
32
+ $starts_year = $_POST['starts_year'];
33
+ $expires_month = $_POST['expires_month'];
34
+ $expires_day = $_POST['expires_day'];
35
+ $expires_year = $_POST['expires_year'];
36
+ $uses = $_POST['uses'];
37
+
38
+ //fix up dates
39
+ $starts = date("Y-m-d", strtotime($starts_month . "/" . $starts_day . "/" . $starts_year, current_time("timestamp")));
40
+ $expires = date("Y-m-d", strtotime($expires_month . "/" . $expires_day . "/" . $expires_year, current_time("timestamp")));
41
+
42
+ //updating or new?
43
+ if($saveid > 0)
44
+ {
45
+ $sqlQuery = "UPDATE $wpdb->pmpro_discount_codes SET code = '" . esc_sql($code) . "', starts = '" . $starts . "', expires = '" . $expires . "', uses = '" . intval($uses) . "' WHERE id = '" . $saveid . "' LIMIT 1";
46
+ if($wpdb->query($sqlQuery) !== false)
47
+ {
48
+ $pmpro_msg = __("Discount code updated successfully.", "pmpro");
49
+ $pmpro_msgt = "success";
50
+ $saved = true;
51
+ $edit = $saveid;
52
+ }
53
+ else
54
+ {
55
+ $pmpro_msg = __("Error updating discount code. That code may already be in use.", "pmpro");
56
+ $pmpro_msgt = "error";
57
+ }
58
+ }
59
+ else
60
+ {
61
+ $sqlQuery = "INSERT INTO $wpdb->pmpro_discount_codes (code, starts, expires, uses) VALUES('" . esc_sql($code) . "', '" . $starts . "', '" . $expires . "', '" . intval($uses) . "')";
62
+ if($wpdb->query($sqlQuery) !== false)
63
+ {
64
+ $pmpro_msg = __("Discount code added successfully.", "pmpro");
65
+ $pmpro_msgt = "success";
66
+ $saved = true;
67
+ $edit = $wpdb->insert_id;
68
+ //$saveid = $edit;
69
+ }
70
+ else
71
+ {
72
+ $pmpro_msg = __("Error adding discount code. That code may already be in use.", "pmpro") . $wpdb->last_error;
73
+ $pmpro_msgt = "error";
74
+ }
75
+ }
76
+
77
+ //now add the membership level rows
78
+ if($saved && $edit > 0)
79
+ {
80
+ //get the submitted values
81
+ $all_levels_a = $_REQUEST['all_levels'];
82
+ if(!empty($_REQUEST['levels']))
83
+ $levels_a = $_REQUEST['levels'];
84
+ else
85
+ $levels_a = array();
86
+ $initial_payment_a = $_REQUEST['initial_payment'];
87
+ if(!empty($_REQUEST['recurring']))
88
+ $recurring_a = $_REQUEST['recurring'];
89
+ $billing_amount_a = $_REQUEST['billing_amount'];
90
+ $cycle_number_a = $_REQUEST['cycle_number'];
91
+ $cycle_period_a = $_REQUEST['cycle_period'];
92
+ $billing_limit_a = $_REQUEST['billing_limit'];
93
+ if(!empty($_REQUEST['custom_trial']))
94
+ $custom_trial_a = $_REQUEST['custom_trial'];
95
+ $trial_amount_a = $_REQUEST['trial_amount'];
96
+ $trial_limit_a = $_REQUEST['trial_limit'];
97
+ if(!empty($_REQUEST['expiration']))
98
+ $expiration_a = $_REQUEST['expiration'];
99
+ $expiration_number_a = $_REQUEST['expiration_number'];
100
+ $expiration_period_a = $_REQUEST['expiration_period'];
101
+
102
+ //clear the old rows
103
+ $sqlQuery = "DELETE FROM $wpdb->pmpro_discount_codes_levels WHERE code_id = '" . $edit . "'";
104
+ $wpdb->query($sqlQuery);
105
+
106
+ //add a row for each checked level
107
+ if(!empty($levels_a))
108
+ {
109
+ foreach($levels_a as $level_id)
110
+ {
111
+ //get the values ready
112
+ $n = array_search($level_id, $all_levels_a); //this is the key location of this level's values
113
+ $initial_payment = $initial_payment_a[$n];
114
+
115
+ //is this recurring?
116
+ if(!empty($recurring_a))
117
+ {
118
+ if(in_array($level_id, $recurring_a))
119
+ $recurring = 1;
120
+ else
121
+ $recurring = 0;
122
+ }
123
+ else
124
+ $recurring = 0;
125
+
126
+ if(!empty($recurring))
127
+ {
128
+ $billing_amount = $billing_amount_a[$n];
129
+ $cycle_number = $cycle_number_a[$n];
130
+ $cycle_period = $cycle_period_a[$n];
131
+ $billing_limit = $billing_limit_a[$n];
132
+
133
+ //custom trial
134
+ if(!empty($custom_trial_a))
135
+ {
136
+ if(in_array($level_id, $custom_trial_a))
137
+ $custom_trial = 1;
138
+ else
139
+ $custom_trial = 0;
140
+ }
141
+ else
142
+ $custom_trial = 0;
143
+
144
+ if(!empty($custom_trial))
145
+ {
146
+ $trial_amount = $trial_amount_a[$n];
147
+ $trial_limit = $trial_limit_a[$n];
148
+ }
149
+ else
150
+ {
151
+ $trial_amount = '';
152
+ $trial_limit = '';
153
+ }
154
+ }
155
+ else
156
+ {
157
+ $billing_amount = '';
158
+ $cycle_number = '';
159
+ $cycle_period = 'Month';
160
+ $billing_limit = '';
161
+ $custom_trial = 0;
162
+ $trial_amount = '';
163
+ $trial_limit = '';
164
+ }
165
+
166
+ if(!empty($expiration_a))
167
+ {
168
+ if(in_array($level_id, $expiration_a))
169
+ $expiration = 1;
170
+ else
171
+ $expiration = 0;
172
+ }
173
+ else
174
+ $expiration = 0;
175
+
176
+ if(!empty($expiration))
177
+ {
178
+ $expiration_number = $expiration_number_a[$n];
179
+ $expiration_period = $expiration_period_a[$n];
180
+ }
181
+ else
182
+ {
183
+ $expiration_number = '';
184
+ $expiration_period = 'Month';
185
+ }
186
+
187
+ //okay, do the insert
188
+ $sqlQuery = "INSERT INTO $wpdb->pmpro_discount_codes_levels (code_id, level_id, initial_payment, billing_amount, cycle_number, cycle_period, billing_limit, trial_amount, trial_limit, expiration_number, expiration_period) VALUES('" . esc_sql($edit) . "', '" . esc_sql($level_id) . "', '" . (double)esc_sql($initial_payment) . "', '" . (double)esc_sql($billing_amount) . "', '" . intval(esc_sql($cycle_number)) . "', '" . esc_sql($cycle_period) . "', '" . intval(esc_sql($billing_limit)) . "', '" . (double)esc_sql($trial_amount) . "', '" . intval(esc_sql($trial_limit)) . "', '" . intval(esc_sql($expiration_number)) . "', '" . esc_sql($expiration_period) . "')";
189
+
190
+ if($wpdb->query($sqlQuery) !== false)
191
+ {
192
+ //okay
193
+ do_action("pmpro_save_discount_code_level", $edit, $level_id);
194
+ }
195
+ else
196
+ {
197
+ $level_errors[] = sprintf(__("Error saving values for the %s level.", "pmpro"), $wpdb->get_var("SELECT name FROM $wpdb->pmpro_membership_levels WHERE id = '" . $level_id . "' LIMIT 1"));
198
+ }
199
+ }
200
+ }
201
+
202
+ //errors?
203
+ if(!empty($level_errors))
204
+ {
205
+ $pmpro_msg = __("There were errors updating the level values: ", "pmpro") . implode(" ", $level_errors);
206
+ $pmpro_msgt = "error";
207
+ }
208
+ else
209
+ {
210
+ //all good. set edit = NULL so we go back to the overview page
211
+ $edit = NULL;
212
+
213
+ do_action("pmpro_save_discount_code", $saveid);
214
+ }
215
+ }
216
+ }
217
+
218
+ //are we deleting?
219
+ if(!empty($delete))
220
+ {
221
+ //is this a code?
222
+ $code = $wpdb->get_var("SELECT code FROM $wpdb->pmpro_discount_codes WHERE id = '" . $delete . "' LIMIT 1");
223
+ if(!empty($code))
224
+ {
225
+ //action
226
+ do_action("pmpro_delete_discount_code", $delete);
227
+
228
+ //delete the code levels
229
+ $r1 = $wpdb->query("DELETE FROM $wpdb->pmpro_discount_codes_levels WHERE code_id = '" . $delete . "'");
230
+
231
+ if($r1 !== false)
232
+ {
233
+ //delete the code
234
+ $r2 = $wpdb->query("DELETE FROM $wpdb->pmpro_discount_codes WHERE id = '" . $delete . "' LIMIT 1");
235
+
236
+ if($r2 !== false)
237
+ {
238
+ $pmpro_msg = sprintf(__("Code %s deleted successfully.", "pmpro"), $code);
239
+ $pmpro_msgt = "success";
240
+ }
241
+ else
242
+ {
243
+ $pmpro_msg = __("Error deleting discount code. The code was only partially deleted. Please try again.", "pmpro");
244
+ $pmpro_msgt = "error";
245
+ }
246
+ }
247
+ else
248
+ {
249
+ $pmpro_msg = __("Error deleting code. Please try again.", "pmpro");
250
+ $pmpro_msgt = "error";
251
+ }
252
+ }
253
+ else
254
+ {
255
+ $pmpro_msg = __("Code not found.", "pmpro");
256
+ $pmpro_msgt = "error";
257
+ }
258
+ }
259
+
260
+ require_once(dirname(__FILE__) . "/admin_header.php");
261
+ ?>
262
+
263
+ <?php if($edit) { ?>
264
+
265
+ <h2>
266
+ <?php
267
+ if($edit > 0)
268
+ echo __("Edit Discount Code", "pmpro");
269
+ else
270
+ echo __("Add New Discount Code", "pmpro");
271
+ ?>
272
+ </h2>
273
+
274
+ <?php if(!empty($pmpro_msg)) { ?>
275
+ <div id="message" class="<?php if($pmpro_msgt == "success") echo "updated fade"; else echo "error"; ?>"><p><?php echo $pmpro_msg?></p></div>
276
+ <?php } ?>
277
+
278
+ <div>
279
+ <?php
280
+ // get the code...
281
+ if($edit > 0)
282
+ {
283
+ $code = $wpdb->get_row("SELECT *, UNIX_TIMESTAMP(starts) as starts, UNIX_TIMESTAMP(expires) as expires FROM $wpdb->pmpro_discount_codes WHERE id = '" . $edit . "' LIMIT 1", OBJECT);
284
+ $uses = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->pmpro_discount_codes_uses WHERE code_id = '" . $code->id . "'");
285
+ $levels = $wpdb->get_results("SELECT l.id, l.name, cl.initial_payment, cl.billing_amount, cl.cycle_number, cl.cycle_period, cl.billing_limit, cl.trial_amount, cl.trial_limit FROM $wpdb->pmpro_membership_levels l LEFT JOIN $wpdb->pmpro_discount_codes_levels cl ON l.id = cl.level_id WHERE cl.code_id = '" . $code->code . "'");
286
+ $temp_id = $code->id;
287
+ }
288
+ elseif(!empty($copy) && $copy > 0)
289
+ {
290
+ $code = $wpdb->get_row("SELECT *, UNIX_TIMESTAMP(starts) as starts, UNIX_TIMESTAMP(expires) as expires FROM $wpdb->pmpro_discount_codes WHERE id = '" . $copy . "' LIMIT 1", OBJECT);
291
+ $temp_id = $level->id;
292
+ $level->id = NULL;
293
+ }
294
+
295
+ // didn't find a discount code, let's add a new one...
296
+ if(empty($code->id)) $edit = -1;
297
+
298
+ //defaults for new codes
299
+ if($edit == -1)
300
+ {
301
+ $code = new stdClass();
302
+ $code->code = pmpro_getDiscountCode();
303
+ }
304
+ ?>
305
+ <form action="" method="post">
306
+ <input name="saveid" type="hidden" value="<?php echo $edit?>" />
307
+ <table class="form-table">
308
+ <tbody>
309
+ <tr>
310
+ <th scope="row" valign="top"><label><?php _e('ID', 'pmpro');?>:</label></th>
311
+ <td class="pmpro_lite"><?php if(!empty($code->id)) echo $code->id; else echo __("This will be generated when you save.", "pmpro");?></td>
312
+ </tr>
313
+
314
+ <tr>
315
+ <th scope="row" valign="top"><label for="code"><?php _e('Code', 'pmpro');?>:</label></th>
316
+ <td><input name="code" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($code->code))?>" /></td>
317
+ </tr>
318
+
319
+ <?php
320
+ //some vars for the dates
321
+ $current_day = date("j");
322
+ if(!empty($code->starts))
323
+ $selected_starts_day = date("j", $code->starts);
324
+ else
325
+ $selected_starts_day = $current_day;
326
+ if(!empty($code->expires))
327
+ $selected_expires_day = date("j", $code->expires);
328
+ else
329
+ $selected_expires_day = $current_day;
330
+
331
+ $current_month = date("M");
332
+ if(!empty($code->starts))
333
+ $selected_starts_month = date("m", $code->starts);
334
+ else
335
+ $selected_starts_month = date("m");
336
+ if(!empty($code->expires))
337
+ $selected_expires_month = date("m", $code->expires);
338
+ else
339
+ $selected_expires_month = date("m");
340
+
341
+ $current_year = date("Y");
342
+ if(!empty($code->starts))
343
+ $selected_starts_year = date("Y", $code->starts);
344
+ else
345
+ $selected_starts_year = $current_year;
346
+ if(!empty($code->expires))
347
+ $selected_expires_year = date("Y", $code->expires);
348
+ else
349
+ $selected_expires_year = (int)$current_year + 1;
350
+ ?>
351
+
352
+ <tr>
353
+ <th scope="row" valign="top"><label for="starts"><?php _e('Start Date', 'pmpro');?>:</label></th>
354
+ <td>
355
+ <select name="starts_month">
356
+ <?php
357
+ for($i = 1; $i < 13; $i++)
358
+ {
359
+ ?>
360
+ <option value="<?php echo $i?>" <?php if($i == $selected_starts_month) { ?>selected="selected"<?php } ?>><?php echo date("M", strtotime($i . "/1/" . $current_year, current_time("timestamp")))?></option>
361
+ <?php
362
+ }
363
+ ?>
364
+ </select>
365
+ <input name="starts_day" type="text" size="2" value="<?php echo $selected_starts_day?>" />
366
+ <input name="starts_year" type="text" size="4" value="<?php echo $selected_starts_year?>" />
367
+ </td>
368
+ </tr>
369
+
370
+ <tr>
371
+ <th scope="row" valign="top"><label for="expires"><?php _e('Expiration Date', 'pmpro');?>:</label></th>
372
+ <td>
373
+ <select name="expires_month">
374
+ <?php
375
+ for($i = 1; $i < 13; $i++)
376
+ {
377
+ ?>
378
+ <option value="<?php echo $i?>" <?php if($i == $selected_expires_month) { ?>selected="selected"<?php } ?>><?php echo date("M", strtotime($i . "/1/" . $current_year, current_time("timestamp")))?></option>
379
+ <?php
380
+ }
381
+ ?>
382
+ </select>
383
+ <input name="expires_day" type="text" size="2" value="<?php echo $selected_expires_day?>" />
384
+ <input name="expires_year" type="text" size="4" value="<?php echo $selected_expires_year?>" />
385
+ </td>
386
+ </tr>
387
+
388
+ <tr>
389
+ <th scope="row" valign="top"><label for="uses"><?php _e('Uses', 'pmpro');?>:</label></th>
390
+ <td>
391
+ <input name="uses" type="text" size="10" value="<?php if(!empty($code->uses)) echo str_replace("\"", "&quot;", stripslashes($code->uses));?>" />
392
+ <small class="pmpro_lite"><?php _e('Leave blank for unlimited uses.', 'pmpro');?></small>
393
+ </td>
394
+ </tr>
395
+
396
+ </tbody>
397
+ </table>
398
+
399
+ <?php do_action("pmpro_discount_code_after_settings"); ?>
400
+
401
+ <h3><?php _e('Which Levels Will This Code Apply To?', 'pmpro'); ?></h3>
402
+
403
+ <div class="pmpro_discount_levels">
404
+ <?php
405
+ $levels = $wpdb->get_results("SELECT * FROM $wpdb->pmpro_membership_levels");
406
+ foreach($levels as $level)
407
+ {
408
+ //if this level is already managed for this discount code, use the code values
409
+ if($edit > 0)
410
+ {
411
+ $code_level = $wpdb->get_row("SELECT l.id, cl.*, l.name, l.description, l.allow_signups FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id WHERE cl.code_id = '" . $edit . "' AND cl.level_id = '" . $level->id . "' LIMIT 1");
412
+ if($code_level)
413
+ {
414
+ $level = $code_level;
415
+ $level->checked = true;
416
+ }
417
+ else
418
+ $level_checked = false;
419
+ }
420
+ else
421
+ $level_checked = false;
422
+ ?>
423
+ <div>
424
+ <input type="hidden" name="all_levels[]" value="<?php echo $level->id?>" />
425
+ <input type="checkbox" id="levels_<?php echo $level->id;?>" name="levels[]" value="<?php echo $level->id?>" <?php if(!empty($level->checked)) { ?>checked="checked"<?php } ?> onclick="if(jQuery(this).is(':checked')) jQuery(this).next().next().show(); else jQuery(this).next().next().hide();" />
426
+ <label for="levels_<?php echo $level->id;?>"><?php echo $level->name?></label>
427
+ <div class="pmpro_discount_levels_pricing level_<?php echo $level->id?>" <?php if(empty($level->checked)) { ?>style="display: none;"<?php } ?>>
428
+ <table class="form-table">
429
+ <tbody>
430
+ <tr>
431
+ <th scope="row" valign="top"><label for="initial_payment"><?php _e('Initial Payment', 'pmpro');?>:</label></th>
432
+ <td>
433
+ <?php
434
+ if(pmpro_getCurrencyPosition() == "left")
435
+ echo $pmpro_currency_symbol;
436
+ ?>
437
+ <input name="initial_payment[]" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->initial_payment))?>" />
438
+ <?php
439
+ if(pmpro_getCurrencyPosition() == "right")
440
+ echo $pmpro_currency_symbol;
441
+ ?>
442
+ <small><?php _e('The initial amount collected at registration.', 'pmpro');?></small>
443
+ </td>
444
+ </tr>
445
+
446
+ <tr>
447
+ <th scope="row" valign="top"><label><?php _e('Recurring Subscription', 'pmpro');?>:</label></th>
448
+ <td><input class="recurring_checkbox" id="recurring_<?php echo $level->id;?>" name="recurring[]" type="checkbox" value="<?php echo $level->id?>" <?php if(pmpro_isLevelRecurring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).attr('checked')) { jQuery(this).parent().parent().siblings('.recurring_info').show(); if(!jQuery('#custom_trial_<?php echo $level->id?>').is(':checked')) jQuery(this).parent().parent().siblings('.trial_info').hide();} else jQuery(this).parent().parent().siblings('.recurring_info').hide();" /> <label for="recurring_<?php echo $level->id;?>"><?php _e('Check if this level has a recurring subscription payment.', 'pmpro');?></label></td>
449
+ </tr>
450
+
451
+ <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
452
+ <th scope="row" valign="top"><label for="billing_amount"><?php _e('Billing Amount', 'pmpro');?>:</label></th>
453
+ <td>
454
+ <?php
455
+ if(pmpro_getCurrencyPosition() == "left")
456
+ echo $pmpro_currency_symbol;
457
+ ?>
458
+ <input name="billing_amount[]" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->billing_amount))?>" />
459
+ <?php
460
+ if(pmpro_getCurrencyPosition() == "right")
461
+ echo $pmpro_currency_symbol;
462
+ ?>
463
+ <small>per</small>
464
+ <input name="cycle_number[]" type="text" size="10" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->cycle_number))?>" />
465
+ <select name="cycle_period[]" onchange="updateCyclePeriod();">
466
+ <?php
467
+ $cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
468
+ foreach ( $cycles as $name => $value ) {
469
+ echo "<option value='$value'";
470
+ if ( $level->cycle_period == $value ) echo " selected='selected'";
471
+ echo ">$name</option>";
472
+ }
473
+ ?>
474
+ </select>
475
+ <br /><small><?php _e('The amount to be billed one cycle after the initial payment.', 'pmpro');?></small>
476
+ </td>
477
+ </tr>
478
+
479
+ <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
480
+ <th scope="row" valign="top"><label for="billing_limit"><?php _e('Billing Cycle Limit', 'pmpro');?>:</label></th>
481
+ <td>
482
+ <input name="billing_limit[]" type="text" size="20" value="<?php echo $level->billing_limit?>" />
483
+ <br /><small><?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.', 'pmpro');?></small>
484
+ </td>
485
+ </tr>
486
+
487
+ <tr class="recurring_info" <?php if (!pmpro_isLevelRecurring($level)) echo "style='display:none;'";?>>
488
+ <th scope="row" valign="top"><label><?php _e('Custom Trial', 'pmpro');?>:</label></th>
489
+ <td><input id="custom_trial_<?php echo $level->id?>" id="custom_trial_<?php echo $level->id;?>" name="custom_trial[]" type="checkbox" value="<?php echo $level->id?>" <?php if ( pmpro_isLevelTrial($level) ) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).attr('checked')) jQuery(this).parent().parent().siblings('.trial_info').show(); else jQuery(this).parent().parent().siblings('.trial_info').hide();" /> <label for="custom_trial_<?php echo $level->id;?>"><?php _e('Check to add a custom trial period.', 'pmpro');?></label></td>
490
+ </tr>
491
+
492
+ <tr class="trial_info recurring_info" <?php if (!pmpro_isLevelTrial($level)) echo "style='display:none;'";?>>
493
+ <th scope="row" valign="top"><label for="trial_amount"><?php _e('Trial Billing Amount', 'pmpro');?>:</label></th>
494
+ <td>
495
+ <?php
496
+ if(pmpro_getCurrencyPosition() == "left")
497
+ echo $pmpro_currency_symbol;
498
+ ?>
499
+ <input name="trial_amount[]" type="text" size="20" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->trial_amount))?>" />
500
+ <?php
501
+ if(pmpro_getCurrencyPosition() == "right")
502
+ echo $pmpro_currency_symbol;
503
+ ?>
504
+ <small><?php _e('for the first', 'pmpro');?></small>
505
+ <input name="trial_limit[]" type="text" size="10" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->trial_limit))?>" />
506
+ <small><?php _e('subscription payments', 'pmpro');?>.</small>
507
+ </td>
508
+ </tr>
509
+
510
+ <tr>
511
+ <th scope="row" valign="top"><label><?php _e('Membership Expiration', 'pmpro');?>:</label></th>
512
+ <td><input id="expiration_<?php echo $level->id;?>" name="expiration[]" type="checkbox" value="<?php echo $level->id?>" <?php if(pmpro_isLevelExpiring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery(this).is(':checked')) { jQuery(this).parent().parent().siblings('.expiration_info').show(); } else { jQuery(this).parent().parent().siblings('.expiration_info').hide();}" /> <label for="expiration_<?php echo $level->id;?>"><?php _e('Check this to set when membership access expires.', 'pmpro');?></label></td>
513
+ </tr>
514
+
515
+ <tr class="expiration_info" <?php if(!pmpro_isLevelExpiring($level)) {?>style="display: none;"<?php } ?>>
516
+ <th scope="row" valign="top"><label for="billing_amount"><?php _e('Expires In', 'pmpro');?>:</label></th>
517
+ <td>
518
+ <input id="expiration_number" name="expiration_number[]" type="text" size="10" value="<?php echo str_replace("\"", "&quot;", stripslashes($level->expiration_number))?>" />
519
+ <select id="expiration_period" name="expiration_period[]">
520
+ <?php
521
+ $cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
522
+ foreach ( $cycles as $name => $value ) {
523
+ echo "<option value='$value'";
524
+ if ( $level->expiration_period == $value ) echo " selected='selected'";
525
+ echo ">$name</option>";
526
+ }
527
+ ?>
528
+ </select>
529
+ <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.', 'pmpro');?></small>
530
+ </td>
531
+ </tr>
532
+ </tbody>
533
+ </table>
534
+
535
+ <?php do_action("pmpro_discount_code_after_level_settings", $edit, $level); ?>
536
+
537
+ </div>
538
+ </div>
539
+ <script>
540
+
541
+ </script>
542
+ <?php
543
+ }
544
+ ?>
545
+ </div>
546
+
547
+ <p class="submit topborder">
548
+ <input name="save" type="submit" class="button button-primary" value="Save Code" />
549
+ <input name="cancel" type="button" class="button button-secondary" value="Cancel" onclick="location.href='<?php echo get_admin_url(NULL, '/admin.php?page=pmpro-discountcodes')?>';" />
550
+ </p>
551
+ </form>
552
+ </div>
553
+
554
+ <?php } else { ?>
555
+
556
+ <h2>
557
+ <?php _e('Memberships Discount Codes', 'pmpro');?>
558
+ <a href="admin.php?page=pmpro-discountcodes&edit=-1" class="add-new-h2"><?php _e('Add New Discount Code', 'pmpro');?></a>
559
+ </h2>
560
+
561
+ <?php if(!empty($pmpro_msg)) { ?>
562
+ <div id="message" class="<?php if($pmpro_msgt == "success") echo "updated fade"; else echo "error"; ?>"><p><?php echo $pmpro_msg?></p></div>
563
+ <?php } ?>
564
+
565
+ <form id="posts-filter" method="get" action="">
566
+ <p class="search-box">
567
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search Discount Codes', 'pmpro');?>:</label>
568
+ <input type="hidden" name="page" value="pmpro-discountcodes" />
569
+ <input id="post-search-input" type="text" value="<?php if(!empty($s)) echo $s;?>" name="s" size="30" />
570
+ <input class="button" type="submit" value="<?php _e('Search', 'pmpro');?>" id="search-submit "/>
571
+ </p>
572
+ </form>
573
+
574
+ <br class="clear" />
575
+ <?php
576
+ $sqlQuery = "SELECT *, UNIX_TIMESTAMP(starts) as starts, UNIX_TIMESTAMP(expires) as expires FROM $wpdb->pmpro_discount_codes ";
577
+ if(!empty($s))
578
+ $sqlQuery .= "WHERE code LIKE '%$s%' ";
579
+ $sqlQuery .= "ORDER BY id ASC";
580
+
581
+ $codes = $wpdb->get_results($sqlQuery, OBJECT);
582
+ ?>
583
+ <table class="widefat">
584
+ <thead>
585
+ <tr>
586
+ <th><?php _e('ID', 'pmpro');?></th>
587
+ <th><?php _e('Code', 'pmpro');?></th>
588
+ <th><?php _e('Starts', 'pmpro');?></th>
589
+ <th><?php _e('Expires', 'pmpro');?></th>
590
+ <th><?php _e('Uses', 'pmpro');?></th>
591
+ <th><?php _e('Levels', 'pmpro');?></th>
592
+ <?php do_action("pmpro_discountcodes_extra_cols_header", $codes);?>
593
+ <th></th>
594
+ <th></th>
595
+ </tr>
596
+ </thead>
597
+ <tbody>
598
+ <?php
599
+ if(!$codes)
600
+ {
601
+ ?>
602
+ <tr><td colspan="7" class="pmpro_pad20">
603
+ <p><?php _e('Discount codes allow you to offer your memberships at discounted prices to select customers.', 'pmpro');?> <a href="admin.php?page=pmpro-discountcodes&edit=-1"><?php _e('Create your first discount code now', 'pmpro');?></a>.</p>
604
+ </td></tr>
605
+ <?php
606
+ }
607
+ else
608
+ {
609
+ foreach($codes as $code)
610
+ {
611
+ ?>
612
+ <tr<?php if($count++ % 2 == 1) { ?> class="alternate"<?php } ?>>
613
+ <td><?php echo $code->id?></td>
614
+ <td>
615
+ <a href="?page=pmpro-discountcodes&edit=<?php echo $code->id?>"><?php echo $code->code?></a>
616
+ </td>
617
+ <td>
618
+ <?php echo date(get_option('date_format'), $code->starts)?>
619
+ </td>
620
+ <td>
621
+ <?php echo date(get_option('date_format'), $code->expires)?>
622
+ </td>
623
+ <td>
624
+ <?php
625
+ $uses = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->pmpro_discount_codes_uses WHERE code_id = '" . $code->id . "'");
626
+ if($code->uses > 0)
627
+ echo "<strong>" . (int)$uses . "</strong>/" . $code->uses;
628
+ else
629
+ echo "<strong>" . (int)$uses . "</strong>/unlimited";
630
+ ?>
631
+ </td>
632
+ <td>
633
+ <?php
634
+ $sqlQuery = "SELECT l.id, l.name FROM $wpdb->pmpro_membership_levels l LEFT JOIN $wpdb->pmpro_discount_codes_levels cl ON l.id = cl.level_id WHERE cl.code_id = '" . $code->id . "'";
635
+ $levels = $wpdb->get_results($sqlQuery);
636
+
637
+ $level_names = array();
638
+ foreach($levels as $level)
639
+ $level_names[] = "<a target=\"_blank\" href=\"" . pmpro_url("checkout", "?level=" . $level->id . "&discount_code=" . $code->code) . "\">" . $level->name . "</a>";
640
+ if($level_names)
641
+ echo implode(", ", $level_names);
642
+ else
643
+ echo "None";
644
+ ?>
645
+ </td>
646
+ <?php do_action("pmpro_discountcodes_extra_cols_body", $code);?>
647
+ <td>
648
+ <a href="?page=pmpro-discountcodes&edit=<?php echo $code->id?>"><?php _e('edit', 'pmpro');?></a>
649
+ </td>
650
+ <td>
651
+ <a href="javascript:askfirst('<?php printf(__('Are you sure you want to delete the %s discount code? The subscriptions for existing users will not change, but new users will not be able to use this code anymore.', 'pmpro'), $code->code);?>', '?page=pmpro-discountcodes&delete=<?php echo $code->id?>'); void(0);"><?php _e('delete', 'pmpro');?></a>
652
+ </td>
653
+ </tr>
654
+ <?php
655
+ }
656
+ }
657
+ ?>
658
+ </tbody>
659
+ </table>
660
+
661
+ <?php } ?>
662
+
663
+ <?php
664
+ require_once(dirname(__FILE__) . "/admin_footer.php");
665
+ ?>
adminpages/emailsettings.php CHANGED
@@ -1,181 +1,181 @@
1
- <?php
2
- //only admins can get this
3
- if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_emailsettings")))
4
- {
5
- die(__("You do not have permissions to perform this action.", "pmpro"));
6
- }
7
-
8
- global $wpdb, $msg, $msgt;
9
-
10
- //get/set settings
11
- global $pmpro_pages;
12
- if(!empty($_REQUEST['savesettings']))
13
- {
14
- //email options
15
- pmpro_setOption("from_email");
16
- pmpro_setOption("from_name");
17
- pmpro_setOption("only_filter_pmpro_emails");
18
-
19
- pmpro_setOption("email_admin_checkout");
20
- pmpro_setOption("email_admin_changes");
21
- pmpro_setOption("email_admin_cancels");
22
- pmpro_setOption("email_admin_billing");
23
-
24
- pmpro_setOption("email_member_notification");
25
-
26
- //assume success
27
- $msg = true;
28
- $msgt = "Your email settings have been updated.";
29
- }
30
-
31
- $from_email = pmpro_getOption("from_email");
32
- $from_name = pmpro_getOption("from_name");
33
- $only_filter_pmpro_emails = pmpro_getOption("only_filter_pmpro_emails");
34
-
35
- $email_admin_checkout = pmpro_getOption("email_admin_checkout");
36
- $email_admin_changes = pmpro_getOption("email_admin_changes");
37
- $email_admin_cancels = pmpro_getOption("email_admin_cancels");
38
- $email_admin_billing = pmpro_getOption("email_admin_billing");
39
-
40
- $email_member_notification = pmpro_getOption("email_member_notification");
41
-
42
- if(empty($from_email))
43
- {
44
- $parsed = parse_url(home_url());
45
- $hostname = $parsed[host];
46
- $hostparts = split("\.", $hostname);
47
- $email_domain = $hostparts[count($hostparts) - 2] . "." . $hostparts[count($hostparts) - 1];
48
- $from_email = "wordpress@" . $email_domain;
49
- pmpro_setOption("from_email", $from_email);
50
- }
51
-
52
- if(empty($from_name))
53
- {
54
- $from_name = "WordPress";
55
- pmpro_setOption("from_name", $from_name);
56
- }
57
-
58
- // default from email wordpress@sitename
59
- $sitename = strtolower( $_SERVER['SERVER_NAME'] );
60
- if ( substr( $sitename, 0, 4 ) == 'www.' ) {
61
- $sitename = substr( $sitename, 4 );
62
- }
63
- $default_from_email = 'wordpress@' . $sitename;
64
-
65
- require_once(dirname(__FILE__) . "/admin_header.php");
66
- ?>
67
-
68
- <form action="" method="post" enctype="multipart/form-data">
69
- <h2><?php _e('Email Settings', 'pmpro');?></h2>
70
- <p><?php _e('By default, system generated emails are sent from <em><strong>wordpress@yourdomain.com</strong></em>. You can update this from address using the fields below.', 'pmpro');?></p>
71
-
72
- <p><?php _e('To modify the appearance of system generated emails, add the files <em>email_header.html</em> and <em>email_footer.html</em> to your theme\'s directory. This will modify both the WordPress default messages as well as messages generated by Paid Memberships Pro. <a title="Paid Memberships Pro - Member Communications" target="_blank" href="http://www.paidmembershipspro.com/documentation/member-communications/">Click here to learn more about Paid Memberships Pro emails</a>.', 'pmpro');?></p>
73
-
74
- <table class="form-table">
75
- <tbody>
76
- <tr>
77
- <th scope="row" valign="top">
78
- <label for="from_email"><?php _e('From Email', 'pmpro');?>:</label>
79
- </th>
80
- <td>
81
- <input type="text" name="from_email" size="60" value="<?php echo esc_attr($from_email);?>" />
82
- </td>
83
- </tr>
84
- <tr>
85
- <th scope="row" valign="top">
86
- <label for="from_name"><?php _e('From Name', 'pmpro');?>:</label>
87
- </th>
88
- <td>
89
- <input type="text" name="from_name" size="60" value="<?php echo esc_attr($from_name);?>" />
90
- </td>
91
- </tr>
92
- <tr>
93
- <th scope="row" valign="top">
94
- <label for="only_filter_pmpro_emails"><?php _e('Only Filter PMPro Emails?', 'pmpro');?>:</label>
95
- </th>
96
- <td>
97
- <input type="checkbox" id="only_filter_pmpro_emails" name="only_filter_pmpro_emails" value="1" <?php if(!empty($only_filter_pmpro_emails)) { ?>checked="checked"<?php } ?> />
98
- <label for="only_filter_pmpro_emails"><?php _e('If unchecked, all emails from "WordPress &lt;' . $default_from_email . '&gt;" will be filtered to use the above settings.', 'pmpro');?></label>
99
- </td>
100
- </tr>
101
- </tbody>
102
- </table>
103
-
104
- <?php /* going to put something like this here in next version
105
- <h3><?php _e('Modify System-generated Email Templates', 'pmpro');?>:</h3>
106
- <?php
107
- if (function_exists('pmproet_scripts'))
108
- {
109
- _e('You have installed the PMPro Email Templates add on. <a href="' . admin_url('admin.php?page=pmpro-email-templates') . '">Click here to modify email templates</a>');
110
- }
111
- ?>
112
- <p><?php _e('To modify the subject line and body content of system generated emails, <a title="Paid Memberships Pro - Email Templates Plugin" target="_blank" href="' . wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-email-templates-addon'), 'install-plugin_pmpro-email-templates-addon') . '">Install and Activate the PMPro Email Templates add on</a>.', 'pmpro'); ?></p>
113
- */ ?>
114
-
115
- <h3><?php _e('Send the site admin emails', 'pmpro');?>:</h3>
116
-
117
- <table class="form-table">
118
- <tbody>
119
- <tr>
120
- <th scope="row" valign="top">
121
- <label for="email_admin_checkout"><?php _e('Checkout', 'pmpro');?>:</label>
122
- </th>
123
- <td>
124
- <input type="checkbox" id="email_admin_checkout" name="email_admin_checkout" value="1" <?php if(!empty($email_admin_checkout)) { ?>checked="checked"<?php } ?> />
125
- <label for="email_admin_checkout"><?php _e('when a member checks out.', 'pmpro');?></label>
126
- </td>
127
- </tr>
128
- <tr>
129
- <th scope="row" valign="top">
130
- <label for="email_admin_changes"><?php _e('Admin Changes', 'pmpro');?>:</label>
131
- </th>
132
- <td>
133
- <input type="checkbox" id="email_admin_changes" name="email_admin_changes" value="1" <?php if(!empty($email_admin_changes)) { ?>checked="checked"<?php } ?> />
134
- <label for="email_admin_changes"><?php _e('when an admin changes a user\'s membership level through the dashboard.', 'pmpro');?></label>
135
- </td>
136
- </tr>
137
- <tr>
138
- <th scope="row" valign="top">
139
- <label for="email_admin_cancels"><?php _e('Cancellation', 'pmpro');?>:</label>
140
- </th>
141
- <td>
142
- <input type="checkbox" id="email_admin_cancels" name="email_admin_cancels" value="1" <?php if(!empty($email_admin_cancels)) { ?>checked="checked"<?php } ?> />
143
- <label for="email_admin_cancels"><?php _e('when a user cancels his or her account.', 'pmpro');?></label>
144
- </td>
145
- </tr>
146
- <tr>
147
- <th scope="row" valign="top">
148
- <label for="email_admin_billing"><?php _e('Bill Updates', 'pmpro');?>:</label>
149
- </th>
150
- <td>
151
- <input type="checkbox" id="email_admin_billing" name="email_admin_billing" value="1" <?php if(!empty($email_admin_billing)) { ?>checked="checked"<?php } ?> />
152
- <label for="email_admin_billing"><?php _e('when a user updates his or her billing information.', 'pmpro');?></label>
153
- </td>
154
- </tr>
155
- </tbody>
156
- </table>
157
-
158
- <h3><?php _e('Send members emails', 'pmpro');?>:</h3>
159
-
160
- <table class="form-table">
161
- <tbody>
162
- <tr>
163
- <th scope="row" valign="top">
164
- <label for="email_member_notification"><?php _e('New Users', 'pmpro');?>:</label>
165
- </th>
166
- <td>
167
- <input type="checkbox" id="email_member_notification" name="email_member_notification" value="1" <?php if(!empty($email_member_notification)) { ?>checked="checked"<?php } ?> />
168
- <label for="email_member_notification"><?php _e('Default WP notification email. (Recommended: Leave unchecked. Members will still get an email confirmation from PMPro after checkout.)', 'pmpro');?></label>
169
- </td>
170
- </tr>
171
- </tbody>
172
- </table>
173
-
174
- <p class="submit">
175
- <input name="savesettings" type="submit" class="button-primary" value="Save Settings" />
176
- </p>
177
- </form>
178
-
179
- <?php
180
- require_once(dirname(__FILE__) . "/admin_footer.php");
181
- ?>
1
+ <?php
2
+ //only admins can get this
3
+ if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_emailsettings")))
4
+ {
5
+ die(__("You do not have permissions to perform this action.", "pmpro"));
6
+ }
7
+
8
+ global $wpdb, $msg, $msgt;
9
+
10
+ //get/set settings
11
+ global $pmpro_pages;
12
+ if(!empty($_REQUEST['savesettings']))
13
+ {
14
+ //email options
15
+ pmpro_setOption("from_email");
16
+ pmpro_setOption("from_name");
17
+ pmpro_setOption("only_filter_pmpro_emails");
18
+
19
+ pmpro_setOption("email_admin_checkout");
20
+ pmpro_setOption("email_admin_changes");
21
+ pmpro_setOption("email_admin_cancels");
22
+ pmpro_setOption("email_admin_billing");
23
+
24
+ pmpro_setOption("email_member_notification");
25
+
26
+ //assume success
27
+ $msg = true;
28
+ $msgt = "Your email settings have been updated.";
29
+ }
30
+
31
+ $from_email = pmpro_getOption("from_email");
32
+ $from_name = pmpro_getOption("from_name");
33
+ $only_filter_pmpro_emails = pmpro_getOption("only_filter_pmpro_emails");
34
+
35
+ $email_admin_checkout = pmpro_getOption("email_admin_checkout");
36
+ $email_admin_changes = pmpro_getOption("email_admin_changes");
37
+ $email_admin_cancels = pmpro_getOption("email_admin_cancels");
38
+ $email_admin_billing = pmpro_getOption("email_admin_billing");
39
+
40
+ $email_member_notification = pmpro_getOption("email_member_notification");
41
+
42
+ if(empty($from_email))
43
+ {
44
+ $parsed = parse_url(home_url());
45
+ $hostname = $parsed[host];
46
+ $hostparts = split("\.", $hostname);
47
+ $email_domain = $hostparts[count($hostparts) - 2] . "." . $hostparts[count($hostparts) - 1];
48
+ $from_email = "wordpress@" . $email_domain;
49
+ pmpro_setOption("from_email", $from_email);
50
+ }
51
+
52
+ if(empty($from_name))
53
+ {
54
+ $from_name = "WordPress";
55
+ pmpro_setOption("from_name", $from_name);
56
+ }
57
+
58
+ // default from email wordpress@sitename
59
+ $sitename = strtolower( $_SERVER['SERVER_NAME'] );
60
+ if ( substr( $sitename, 0, 4 ) == 'www.' ) {
61
+ $sitename = substr( $sitename, 4 );
62
+ }
63
+ $default_from_email = 'wordpress@' . $sitename;
64
+
65
+ require_once(dirname(__FILE__) . "/admin_header.php");
66
+ ?>
67
+
68
+ <form action="" method="post" enctype="multipart/form-data">
69
+ <h2><?php _e('Email Settings', 'pmpro');?></h2>
70
+ <p><?php _e('By default, system generated emails are sent from <em><strong>wordpress@yourdomain.com</strong></em>. You can update this from address using the fields below.', 'pmpro');?></p>
71
+
72
+ <p><?php _e('To modify the appearance of system generated emails, add the files <em>email_header.html</em> and <em>email_footer.html</em> to your theme\'s directory. This will modify both the WordPress default messages as well as messages generated by Paid Memberships Pro. <a title="Paid Memberships Pro - Member Communications" target="_blank" href="http://www.paidmembershipspro.com/documentation/member-communications/">Click here to learn more about Paid Memberships Pro emails</a>.', 'pmpro');?></p>
73
+
74
+ <table class="form-table">
75
+ <tbody>
76
+ <tr>
77
+ <th scope="row" valign="top">
78
+ <label for="from_email"><?php _e('From Email', 'pmpro');?>:</label>
79
+ </th>
80
+ <td>
81
+ <input type="text" name="from_email" size="60" value="<?php echo esc_attr($from_email);?>" />
82
+ </td>
83
+ </tr>
84
+ <tr>
85
+ <th scope="row" valign="top">
86
+ <label for="from_name"><?php _e('From Name', 'pmpro');?>:</label>
87
+ </th>
88
+ <td>
89
+ <input type="text" name="from_name" size="60" value="<?php echo esc_attr($from_name);?>" />
90
+ </td>
91
+ </tr>
92
+ <tr>
93
+ <th scope="row" valign="top">
94
+ <label for="only_filter_pmpro_emails"><?php _e('Only Filter PMPro Emails?', 'pmpro');?>:</label>
95
+ </th>
96
+ <td>
97
+ <input type="checkbox" id="only_filter_pmpro_emails" name="only_filter_pmpro_emails" value="1" <?php if(!empty($only_filter_pmpro_emails)) { ?>checked="checked"<?php } ?> />
98
+ <label for="only_filter_pmpro_emails"><?php _e('If unchecked, all emails from "WordPress &lt;' . $default_from_email . '&gt;" will be filtered to use the above settings.', 'pmpro');?></label>
99
+ </td>
100
+ </tr>
101
+ </tbody>
102
+ </table>
103
+
104
+ <?php /* going to put something like this here in next version
105
+ <h3><?php _e('Modify System-generated Email Templates', 'pmpro');?>:</h3>
106
+ <?php
107
+ if (function_exists('pmproet_scripts'))
108
+ {
109
+ _e('You have installed the PMPro Email Templates add on. <a href="' . admin_url('admin.php?page=pmpro-email-templates') . '">Click here to modify email templates</a>');
110
+ }
111
+ ?>
112
+ <p><?php _e('To modify the subject line and body content of system generated emails, <a title="Paid Memberships Pro - Email Templates Plugin" target="_blank" href="' . wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=pmpro-email-templates-addon'), 'install-plugin_pmpro-email-templates-addon') . '">Install and Activate the PMPro Email Templates add on</a>.', 'pmpro'); ?></p>
113
+ */ ?>
114
+
115
+ <h3><?php _e('Send the site admin emails', 'pmpro');?>:</h3>
116
+
117
+ <table class="form-table">
118
+ <tbody>
119
+ <tr>
120
+ <th scope="row" valign="top">
121
+ <label for="email_admin_checkout"><?php _e('Checkout', 'pmpro');?>:</label>
122
+ </th>
123
+ <td>
124
+ <input type="checkbox" id="email_admin_checkout" name="email_admin_checkout" value="1" <?php if(!empty($email_admin_checkout)) { ?>checked="checked"<?php } ?> />
125
+ <label for="email_admin_checkout"><?php _e('when a member checks out.', 'pmpro');?></label>
126
+ </td>
127
+ </tr>
128
+ <tr>
129
+ <th scope="row" valign="top">
130
+ <label for="email_admin_changes"><?php _e('Admin Changes', 'pmpro');?>:</label>
131
+ </th>
132
+ <td>
133
+ <input type="checkbox" id="email_admin_changes" name="email_admin_changes" value="1" <?php if(!empty($email_admin_changes)) { ?>checked="checked"<?php } ?> />
134
+ <label for="email_admin_changes"><?php _e('when an admin changes a user\'s membership level through the dashboard.', 'pmpro');?></label>
135
+ </td>
136
+ </tr>
137
+ <tr>
138
+ <th scope="row" valign="top">
139
+ <label for="email_admin_cancels"><?php _e('Cancellation', 'pmpro');?>:</label>
140
+ </th>
141
+ <td>
142
+ <input type="checkbox" id="email_admin_cancels" name="email_admin_cancels" value="1" <?php if(!empty($email_admin_cancels)) { ?>checked="checked"<?php } ?> />
143
+ <label for="email_admin_cancels"><?php _e('when a user cancels his or her account.', 'pmpro');?></label>
144
+ </td>
145
+ </tr>
146
+ <tr>
147
+ <th scope="row" valign="top">
148
+ <label for="email_admin_billing"><?php _e('Bill Updates', 'pmpro');?>:</label>
149
+ </th>
150
+ <td>
151
+ <input type="checkbox" id="email_admin_billing" name="email_admin_billing" value="1" <?php if(!empty($email_admin_billing)) { ?>checked="checked"<?php } ?> />
152
+ <label for="email_admin_billing"><?php _e('when a user updates his or her billing information.', 'pmpro');?></label>
153
+ </td>
154
+ </tr>
155
+ </tbody>
156
+ </table>
157
+
158
+ <h3><?php _e('Send members emails', 'pmpro');?>:</h3>
159
+
160
+ <table class="form-table">
161
+ <tbody>
162
+ <tr>
163
+ <th scope="row" valign="top">
164
+ <label for="email_member_notification"><?php _e('New Users', 'pmpro');?>:</label>
165
+ </th>
166
+ <td>
167
+ <input type="checkbox" id="email_member_notification" name="email_member_notification" value="1" <?php if(!empty($email_member_notification)) { ?>checked="checked"<?php } ?> />
168
+ <label for="email_member_notification"><?php _e('Default WP notification email. (Recommended: Leave unchecked. Members will still get an email confirmation from PMPro after checkout.)', 'pmpro');?></label>
169
+ </td>
170
+ </tr>
171
+ </tbody>
172
+ </table>
173
+
174
+ <p class="submit">
175
+ <input name="savesettings" type="submit" class="button-primary" value="Save Settings" />
176
+ </p>
177
+ </form>
178
+
179
+ <?php
180
+ require_once(dirname(__FILE__) . "/admin_footer.php");
181
+ ?>
adminpages/functions.php CHANGED
@@ -1,256 +1,256 @@
1
- <?php
2
- /****************************************************************
3
-
4
- IMPORTANT. PLEASE READ.
5
-
6
- DO NOT EDIT THIS FILE or any other file in the /wp-content/plugins/paid-memberships-pro/ directory.
7
- Doing so could break the PMPro plugin and/or keep you from upgrading this plugin in the future.
8
- We regularly release updates to the plugin, including important security fixes and new features.
9
- You want to be able to upgrade.
10
-
11
- If you were asked to insert code into "your functions.php file", it was meant that you edit the functions.php
12
- in the root folder of your active theme. e.g. /wp-content/themes/twentytwelve/functions.php
13
- You can also create a custom plugin to place customization code into. Instructions are here:
14
- http://www.paidmembershipspro.com/2012/08/create-a-plugin-for-pmpro-customizations/
15
-
16
- Further documentation for customizing Paid Memberships Pro can be found here:
17
- http://www.paidmembershipspro.com/documentation/
18
-
19
- ****************************************************************/
20
-
21
- /*
22
- Checks if PMPro settings are complete or if there are any errors.
23
- */
24
- function pmpro_checkLevelForStripeCompatibility($level = NULL)
25
- {
26
- $gateway = pmpro_getOption("gateway");
27
- if($gateway == "stripe")
28
- {
29
- global $wpdb;
30
-
31
- //check ALL the levels
32
- if(empty($level))
33
- {
34
- $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ORDER BY id ASC";
35
- $levels = $wpdb->get_results($sqlQuery, OBJECT);
36
- if(!empty($levels))
37
- {
38
- foreach($levels as $level)
39
- {
40
- /*
41
- Stripe currently does not support:
42
- * Billing Limits.
43
- */
44
- if($level->billing_limit > 0)
45
- {
46
- return false;
47
- }
48
- }
49
- }
50
- }
51
- else
52
- {
53
- //need to look it up?
54
- if(is_numeric($level))
55
- $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . esc_sql($level) . "' LIMIT 1");
56
-
57
- //check this level
58
- if(($level->cycle_number > 0 && $level->cycle_period == "Day") ||
59
- $level->billing_limit > 0)
60
- {
61
- return false;
62
- }
63
- }
64
- }
65
-
66
- return true;
67
- }
68
-
69
- /*
70
- Checks if PMPro settings are complete or if there are any errors.
71
- */
72
- function pmpro_checkLevelForPayflowCompatibility($level = NULL)
73
- {
74
- $gateway = pmpro_getOption("gateway");
75
- if($gateway == "payflowpro")
76
- {
77
- global $wpdb;
78
-
79
- //check ALL the levels
80
- if(empty($level))
81
- {
82
- $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ORDER BY id ASC";
83
- $levels = $wpdb->get_results($sqlQuery, OBJECT);
84
- if(!empty($levels))
85
- {
86
- foreach($levels as $level)
87
- {
88
- /*
89
- Payflow currently does not support:
90
- * Trial Amounts > 0.
91
- * Daily billing periods.
92
- */
93
-
94
- if($level->trial_amount > 0 ||
95
- $level->cycle_number > 1)
96
- {
97
- return false;
98
- }
99
- }
100
- }
101
- }
102
- else
103
- {
104
- //need to look it up?
105
- if(is_numeric($level))
106
- $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . esc_sql($level) . "' LIMIT 1");
107
-
108
- //check this level
109
- if($level->trial_amount > 0 ||
110
- $level->cycle_number > 1 ||
111
- ($level->cycle_number == 1 && $level->cycle_period == "Day"))
112
- {
113
- return false;
114
- }
115
- }
116
- }
117
-
118
- return true;
119
- }
120
-
121
- /*
122
- Checks if PMPro settings are complete or if there are any errors.
123
- */
124
- function pmpro_checkLevelForBraintreeCompatibility($level = NULL)
125
- {
126
- $gateway = pmpro_getOption("gateway");
127
- if($gateway == "braintree")
128
- {
129
- global $wpdb;
130
-
131
- //check ALL the levels
132
- if(empty($level))
133
- {
134
- $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ORDER BY id ASC";
135
- $levels = $wpdb->get_results($sqlQuery, OBJECT);
136
- if(!empty($levels))
137
- {
138
- foreach($levels as $level)
139
- {
140
- /*
141
- Braintree currently does not support:
142
- * Trial Amounts > 0.
143
- * Daily or Weekly billing periods.
144
- */
145
- if($level->trial_amount > 0 ||
146
- ($level->cycle_number > 0 && ($level->cycle_period == "Day" || $level->cycle_period == "Week")))
147
- {
148
- return false;
149
- }
150
- }
151
- }
152
- }
153
- else
154
- {
155
- //need to look it up?
156
- if(is_numeric($level))
157
- $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . esc_sql($level) . "' LIMIT 1");
158
-
159
- //check this level
160
- if($level->trial_amount > 0 ||
161
- ($level->cycle_number > 0 && ($level->cycle_period == "Day" || $level->cycle_period == "Week")))
162
- {
163
- return false;
164
- }
165
- }
166
- }
167
-
168
- return true;
169
- }
170
-
171
- /*
172
- Checks if PMPro settings are complete or if there are any errors.
173
- */
174
- function pmpro_checkLevelForTwoCheckoutCompatibility($level = NULL)
175
- {
176
- $gateway = pmpro_getOption("gateway");
177
- if($gateway == "twocheckout")
178
- {
179
- global $wpdb;
180
-
181
- //check ALL the levels
182
- if(empty($level))
183
- {
184
- $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ORDER BY id ASC";
185
- $levels = $wpdb->get_results($sqlQuery, OBJECT);
186
- if(!empty($levels))
187
- {
188
- foreach($levels as $level)
189
- {
190
- /*
191
- 2Checkout currently does not support:
192
- * Trial amounts less than or greater than the absolute value of amonthly recurring amount.
193
- */
194
- if(pmpro_isLevelTrial($level))
195
- {
196
- return false;
197
- }
198
- }
199
- }
200
- }
201
- else
202
- {
203
- //need to look it up?
204
- if(is_numeric($level))
205
- $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . esc_sql($level) . "' LIMIT 1");
206
-
207
- //check this level
208
- if(pmpro_isLevelTrial($level))
209
- {
210
- return false;
211
- }
212
- }
213
- }
214
-
215
- return true;
216
- }
217
-
218
- /**
219
- * Get the gateway-related classes for fields on the payment settings page.
220
- *
221
- * @param string $field The name of the field to check.
222
- * @param bool $force If true, it will rebuild the cached results.
223
- *
224
- * @since 2.0
225
- */
226
- function pmpro_getClassesForPaymentSettingsField($field, $force = false)
227
- {
228
- global $pmpro_gateway_options;
229
- $pmpro_gateways = pmpro_gateways();
230
-
231
- //build array of gateways and options
232
- if(!isset($pmpro_gateway_options) || $force)
233
- {
234
- $pmpro_gateway_options = array();
235
-
236
- foreach($pmpro_gateways as $gateway => $label)
237
- {
238
- //get options
239
- if(class_exists('PMProGateway_' . $gateway) && method_exists('PMProGateway_' . $gateway, 'getGatewayOptions'))
240
- {
241
- $pmpro_gateway_options[$gateway] = call_user_func(array('PMProGateway_' . $gateway, 'getGatewayOptions'));
242
- }
243
- }
244
- }
245
-
246
- //now check where this field shows up
247
- $rgateways = array();
248
- foreach($pmpro_gateway_options as $gateway => $options)
249
- {
250
- if(in_array($field, $options))
251
- $rgateways[] = "gateway_" . $gateway;
252
- }
253
-
254
- //return space separated string
255
- return implode(" ", $rgateways);
256
  }
1
+ <?php
2
+ /****************************************************************
3
+
4
+ IMPORTANT. PLEASE READ.
5
+
6
+ DO NOT EDIT THIS FILE or any other file in the /wp-content/plugins/paid-memberships-pro/ directory.
7
+ Doing so could break the PMPro plugin and/or keep you from upgrading this plugin in the future.
8
+ We regularly release updates to the plugin, including important security fixes and new features.
9
+ You want to be able to upgrade.
10
+
11
+ If you were asked to insert code into "your functions.php file", it was meant that you edit the functions.php
12
+ in the root folder of your active theme. e.g. /wp-content/themes/twentytwelve/functions.php
13
+ You can also create a custom plugin to place customization code into. Instructions are here:
14
+ http://www.paidmembershipspro.com/2012/08/create-a-plugin-for-pmpro-customizations/
15
+
16
+ Further documentation for customizing Paid Memberships Pro can be found here:
17
+ http://www.paidmembershipspro.com/documentation/
18
+
19
+ ****************************************************************/
20
+
21
+ /*
22
+ Checks if PMPro settings are complete or if there are any errors.
23
+ */
24
+ function pmpro_checkLevelForStripeCompatibility($level = NULL)
25
+ {
26
+ $gateway = pmpro_getOption("gateway");
27
+ if($gateway == "stripe")
28
+ {
29
+ global $wpdb;
30
+
31
+ //check ALL the levels
32
+ if(empty($level))
33
+ {
34
+ $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ORDER BY id ASC";
35
+ $levels = $wpdb->get_results($sqlQuery, OBJECT);
36
+ if(!empty($levels))
37
+ {
38
+ foreach($levels as $level)
39
+ {
40
+ /*
41
+ Stripe currently does not support:
42
+ * Billing Limits.
43
+ */
44
+ if($level->billing_limit > 0)
45
+ {
46
+ return false;
47
+ }
48
+ }
49
+ }
50
+ }
51
+ else
52
+ {
53
+ //need to look it up?
54
+ if(is_numeric($level))
55
+ $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . esc_sql($level) . "' LIMIT 1");
56
+
57
+ //check this level
58
+ if(($level->cycle_number > 0 && $level->cycle_period == "Day") ||
59
+ $level->billing_limit > 0)
60
+ {
61
+ return false;
62
+ }
63
+ }
64
+ }
65
+
66
+ return true;
67
+ }
68
+
69
+ /*
70
+ Checks if PMPro settings are complete or if there are any errors.
71
+ */
72
+ function pmpro_checkLevelForPayflowCompatibility($level = NULL)
73
+ {
74
+ $gateway = pmpro_getOption("gateway");
75
+ if($gateway == "payflowpro")
76
+ {
77
+ global $wpdb;
78
+
79
+ //check ALL the levels
80
+ if(empty($level))
81
+ {
82
+ $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ORDER BY id ASC";
83
+ $levels = $wpdb->get_results($sqlQuery, OBJECT);
84
+ if(!empty($levels))
85
+ {
86
+ foreach($levels as $level)
87
+ {
88
+ /*
89
+ Payflow currently does not support:
90
+ * Trial Amounts > 0.
91
+ * Daily billing periods.
92
+ */
93
+
94
+ if($level->trial_amount > 0 ||
95
+ $level->cycle_number > 1)
96
+ {
97
+ return false;
98
+ }
99
+ }
100
+ }
101
+ }
102
+ else
103
+ {
104
+ //need to look it up?
105
+ if(is_numeric($level))
106
+ $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . esc_sql($level) . "' LIMIT 1");
107
+
108
+ //check this level
109
+ if($level->trial_amount > 0 ||
110
+ $level->cycle_number > 1 ||
111
+ ($level->cycle_number == 1 && $level->cycle_period == "Day"))
112
+ {
113
+ return false;
114
+ }
115
+ }
116
+ }
117
+
118
+ return true;
119
+ }
120
+
121
+ /*
122
+ Checks if PMPro settings are complete or if there are any errors.
123
+ */
124
+ function pmpro_checkLevelForBraintreeCompatibility($level = NULL)
125
+ {
126
+ $gateway = pmpro_getOption("gateway");
127
+ if($gateway == "braintree")
128
+ {
129
+ global $wpdb;
130
+
131
+ //check ALL the levels
132
+ if(empty($level))
133
+ {
134
+ $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ORDER BY id ASC";
135
+ $levels = $wpdb->get_results($sqlQuery, OBJECT);
136
+ if(!empty($levels))
137
+ {
138
+ foreach($levels as $level)
139
+ {
140
+ /*
141
+ Braintree currently does not support:
142
+ * Trial Amounts > 0.
143
+ * Daily or Weekly billing periods.
144
+ */
145
+ if($level->trial_amount > 0 ||
146
+ ($level->cycle_number > 0 && ($level->cycle_period == "Day" || $level->cycle_period == "Week")))
147
+ {
148
+ return false;
149
+ }
150
+ }
151
+ }
152
+ }
153
+ else
154
+ {
155
+ //need to look it up?
156
+ if(is_numeric($level))
157
+ $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . esc_sql($level) . "' LIMIT 1");
158
+
159
+ //check this level
160
+ if($level->trial_amount > 0 ||
161
+ ($level->cycle_number > 0 && ($level->cycle_period == "Day" || $level->cycle_period == "Week")))
162
+ {
163
+ return false;
164
+ }
165
+ }
166
+ }
167
+
168
+ return true;
169
+ }
170
+
171
+ /*
172
+ Checks if PMPro settings are complete or if there are any errors.
173
+ */
174
+ function pmpro_checkLevelForTwoCheckoutCompatibility($level = NULL)
175
+ {
176
+ $gateway = pmpro_getOption("gateway");
177
+ if($gateway == "twocheckout")
178
+ {
179
+ global $wpdb;
180
+
181
+ //check ALL the levels
182
+ if(empty($level))
183
+ {
184
+ $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ORDER BY id ASC";
185
+ $levels = $wpdb->get_results($sqlQuery, OBJECT);
186
+ if(!empty($levels))
187
+ {
188
+ foreach($levels as $level)
189
+ {
190
+ /*
191
+ 2Checkout currently does not support:
192
+ * Trial amounts less than or greater than the absolute value of amonthly recurring amount.
193
+ */
194
+ if(pmpro_isLevelTrial($level))
195
+ {
196
+ return false;
197
+ }
198
+ }
199
+ }
200
+ }
201
+ else
202
+ {
203
+ //need to look it up?
204
+ if(is_numeric($level))
205
+ $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '" . esc_sql($level) . "' LIMIT 1");
206
+
207
+ //check this level
208
+ if(pmpro_isLevelTrial($level))
209
+ {
210
+ return false;
211
+ }
212
+ }
213
+ }
214
+
215
+ return true;
216
+ }
217
+
218
+ /**
219
+ * Get the gateway-related classes for fields on the payment settings page.
220
+ *
221
+ * @param string $field The name of the field to check.
222
+ * @param bool $force If true, it will rebuild the cached results.
223
+ *
224
+ * @since 2.0
225
+ */
226
+ function pmpro_getClassesForPaymentSettingsField($field, $force = false)
227
+ {
228
+ global $pmpro_gateway_options;
229
+ $pmpro_gateways = pmpro_gateways();
230
+
231
+ //build array of gateways and options
232
+ if(!isset($pmpro_gateway_options) || $force)
233
+ {
234
+ $pmpro_gateway_options = array();
235
+
236
+ foreach($pmpro_gateways as $gateway => $label)
237
+ {
238
+ //get options
239
+ if(class_exists('PMProGateway_' . $gateway) && method_exists('PMProGateway_' . $gateway, 'getGatewayOptions'))
240
+ {
241
+ $pmpro_gateway_options[$gateway] = call_user_func(array('PMProGateway_' . $gateway, 'getGatewayOptions'));
242
+ }
243
+ }
244
+ }
245
+
246
+ //now check where this field shows up
247
+ $rgateways = array();
248
+ foreach($pmpro_gateway_options as $gateway => $options)
249
+ {
250
+ if(in_array($field, $options))
251
+ $rgateways[] = "gateway_" . $gateway;
252
+ }
253
+
254
+ //return space separated string
255
+ return implode(" ", $rgateways);
256
  }
adminpages/membershiplevels.php CHANGED
@@ -1,594 +1,673 @@
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.", "pmpro"));
6
- }
7
-
8
- global $wpdb, $msg, $msgt, $pmpro_currency_symbol;
9
-
10
- //some vars
11
- $gateway = pmpro_getOption("gateway");
12
- global $pmpro_stripe_error, $pmpro_braintree_error, $pmpro_payflow_error, $pmpro_twocheckout_error, $wp_version;
13
-
14
- if(isset($_REQUEST['edit']))
15
- $edit = $_REQUEST['edit'];
16
- else
17
- $edit = false;
18
- if(isset($_REQUEST['copy']))
19
- $copy = $_REQUEST['copy'];
20
- if(isset($_REQUEST['s']))
21
- $s = $_REQUEST['s'];
22
- else
23
- $s = "";
24
-
25
- if(isset($_REQUEST['action']))
26
- $action = $_REQUEST['action'];
27
- else
28
- $action = false;
29
-
30
- if(isset($_REQUEST['saveandnext']))
31
- $saveandnext = $_REQUEST['saveandnext'];
32
-
33
- if(isset($_REQUEST['saveid']))
34
- $saveid = $_REQUEST['saveid'];
35
- if(isset($_REQUEST['deleteid']))
36
- $deleteid = $_REQUEST['deleteid'];
37
-
38
- if($action == "save_membershiplevel")
39
- {
40
- $ml_name = stripslashes($_REQUEST['name']);
41
- $ml_description = stripslashes($_REQUEST['description']);
42
- $ml_confirmation = stripslashes($_REQUEST['confirmation']);
43
- $ml_initial_payment = stripslashes($_REQUEST['initial_payment']);
44
- if(!empty($_REQUEST['recurring']))
45
- $ml_recurring = 1;
46
- else
47
- $ml_recurring = 0;
48
- $ml_billing_amount = stripslashes($_REQUEST['billing_amount']);
49
- $ml_cycle_number = stripslashes($_REQUEST['cycle_number']);
50
- $ml_cycle_period = stripslashes($_REQUEST['cycle_period']);
51
- $ml_billing_limit = stripslashes($_REQUEST['billing_limit']);
52
- if(!empty($_REQUEST['custom_trial']))
53
- $ml_custom_trial = 1;
54
- else
55
- $ml_custom_trial = 0;
56
- $ml_trial_amount = stripslashes($_REQUEST['trial_amount']);
57
- $ml_trial_limit = stripslashes($_REQUEST['trial_limit']);
58
- if(!empty($_REQUEST['expiration']))
59
- $ml_expiration = 1;
60
- else
61
- $ml_expiration = 0;
62
- $ml_expiration_number = stripslashes($_REQUEST['expiration_number']);
63
- $ml_expiration_period = stripslashes($_REQUEST['expiration_period']);
64
- $ml_categories = array();
65
-
66
- //reversing disable to allow here
67
- if(empty($_REQUEST['disable_signups']))
68
- $ml_allow_signups = 1;
69
- else
70
- $ml_allow_signups = 0;
71
-
72
- foreach ( $_REQUEST as $key => $value )
73
- {
74
- if ( $value == 'yes' && preg_match( '/^membershipcategory_(\d+)$/i', $key, $matches ) )
75
- {
76
- $ml_categories[] = $matches[1];
77
- }
78
- }
79
-
80
- //clearing out values if checkboxes aren't checked
81
- if(empty($ml_recurring))
82
- {
83
- $ml_billing_amount = $ml_cycle_number = $ml_cycle_period = $ml_billing_limit = $ml_trial_amount = $ml_trial_limit = 0;
84
- }
85
- elseif(empty($ml_custom_trial))
86
- {
87
- $ml_trial_amount = $ml_trial_limit = 0;
88
- }
89
- if(empty($ml_expiration))
90
- {
91
- $ml_expiration_number = $ml_expiration_period = 0;
92
- }
93
-
94
- if($saveid > 0)
95
- {
96
- $sqlQuery = " UPDATE {$wpdb->pmpro_membership_levels}
97
- SET name = '" . esc_sql($ml_name) . "',
98
- description = '" . esc_sql($ml_description) . "',
99
- confirmation = '" . esc_sql($ml_confirmation) . "',
100
- initial_payment = '" . esc_sql($ml_initial_payment) . "',
101
- billing_amount = '" . esc_sql($ml_billing_amount) . "',
102
- cycle_number = '" . esc_sql($ml_cycle_number) . "',
103
- cycle_period = '" . esc_sql($ml_cycle_period) . "',
104
- billing_limit = '" . esc_sql($ml_billing_limit) . "',
105
- trial_amount = '" . esc_sql($ml_trial_amount) . "',
106
- trial_limit = '" . esc_sql($ml_trial_limit) . "',
107
- expiration_number = '" . esc_sql($ml_expiration_number) . "',
108
- expiration_period = '" . esc_sql($ml_expiration_period) . "',
109
- allow_signups = '" . esc_sql($ml_allow_signups) . "'
110
- WHERE id = '$saveid' LIMIT 1;";
111
- $wpdb->query($sqlQuery);
112
-
113
- pmpro_updateMembershipCategories( $saveid, $ml_categories );
114
- if(!mysql_errno())
115
- {
116
- $edit = false;
117
- $msg = 2;
118
- $msgt = __("Membership level updated successfully.", "pmpro");
119
- }
120
- else
121
- {
122
- $msg = -2;
123
- $msg = true;
124
- $msgt = __("Error updating membership level.", "pmpro");
125
- }
126
- }
127
- else
128
- {
129
- $sqlQuery = " INSERT INTO {$wpdb->pmpro_membership_levels}
130
- ( name, description, confirmation, initial_payment, billing_amount, cycle_number, cycle_period, billing_limit, trial_amount, trial_limit, expiration_number, expiration_period, allow_signups)
131
- VALUES
132
- ( '" . esc_sql($ml_name) . "', '" . esc_sql($ml_description) . "', '" . esc_sql($ml_confirmation) . "', '" . esc_sql($ml_initial_payment) . "', '" . esc_sql($ml_billing_amount) . "', '" . esc_sql($ml_cycle_number) . "', '" . esc_sql($ml_cycle_period) . "', '" . esc_sql($ml_billing_limit) . "', '" . esc_sql($ml_trial_amount) . "', '" . esc_sql($ml_trial_limit) . "', '" . esc_sql($ml_expiration_number) . "', '" . esc_sql($ml_expiration_period) . "', '" . esc_sql($ml_allow_signups) . "' )";
133
- $wpdb->query($sqlQuery);
134
- if(!mysql_errno())
135
- {
136
- $saveid = $wpdb->insert_id;
137
- pmpro_updateMembershipCategories( $saveid, $ml_categories );
138
-
139
- $edit = false;
140
- $msg = 1;
141
- $msgt = __("Membership level added successfully.", "pmpro");
142
- }
143
- else
144
- {
145
- $msg = -1;
146
- $msgt = __("Error adding membership level.", "pmpro");
147
- }
148
- }
149
-
150
- do_action("pmpro_save_membership_level", $saveid);
151
- }
152
- elseif($action == "delete_membership_level")
153
- {
154
- global $wpdb;
155
-
156
- $ml_id = $_REQUEST['deleteid'];
157
-
158
- if($ml_id > 0)
159
- {
160
- do_action("pmpro_delete_membership_level", $ml_id);
161
-
162
- //remove any categories from the ml
163
- $sqlQuery = "DELETE FROM $wpdb->pmpro_memberships_categories WHERE membership_id = '$ml_id'";
164
- $r1 = $wpdb->query($sqlQuery);
165
-
166
- //cancel any subscriptions to the ml
167
- $r2 = true;
168
- $user_ids = $wpdb->get_col("SELECT user_id FROM $wpdb->pmpro_memberships_users WHERE membership_id = '$ml_id' AND status = 'active'");
169
- foreach($user_ids as $user_id)
170
- {
171
- //change there membership level to none. that will handle the cancel
172
- if(pmpro_changeMembershipLevel(0, $user_id))
173
- {
174
- //okay
175
- }
176
- else
177
- {
178
- //couldn't delete the subscription
179
- //we should probably notify the admin
180
- $pmproemail = new PMProEmail();
181
- $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.", "pmpro"), $user_id) . "</p>");
182
- $last_order = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_orders WHERE user_id = '" . $user_id . "' ORDER BY timestamp DESC LIMIT 1");
183
- if($last_order)
184
- $pmproemail->data["body"] .= "<p>" . __("Last Invoice", "pmpro") . ":<br />" . nl2br(var_export($last_order, true)) . "</p>";
185
- $pmproemail->sendEmail(get_bloginfo("admin_email"));
186
-
187
- $r2 = false;
188
- }
189
- }
190
-
191
- //delete the ml
192
- $sqlQuery = "DELETE FROM $wpdb->pmpro_membership_levels WHERE id = '$ml_id' LIMIT 1";
193
- $r3 = $wpdb->query($sqlQuery);
194
-
195
- if($r1 !== FALSE && $r2 !== FALSE && $r3 !== FALSE)
196
- {
197
- $msg = 3;
198
- $msgt = __("Membership level deleted successfully.", "pmpro");
199
- }
200
- else
201
- {
202
- $msg = -3;
203
- $msgt = __("Error deleting membership level.", "pmpro");
204
- }
205
- }
206
- else
207
- {
208
- $msg = -3;
209
- $msgt = __("Error deleting membership level.", "pmpro");
210
- }
211
- }
212
-
213
- require_once(dirname(__FILE__) . "/admin_header.php");
214
- ?>
215
-
216
- <?php
217
- if($edit)
218
- {
219
- ?>
220
-
221
- <h2>
222
- <?php
223
- if($edit > 0)
224
- echo __("Edit Membership Level", "pmpro");
225
- else
226
- echo __("Add New Membership Level", "pmpro");
227
- ?>
228
- </h2>
229
-
230
- <div>
231
- <?php
232
- // get the level...
233
- if(!empty($edit) && $edit > 0)
234
- {
235
- $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '$edit' LIMIT 1", OBJECT);
236
- $temp_id = $level->id;
237
- }
238
- elseif(!empty($copy) && $copy > 0)
239
- {
240
- $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '$copy' LIMIT 1", OBJECT);
241
- $temp_id = $level->id;
242
- $level->id = NULL;
243
- }
244
- else
245
-
246
- // didn't find a membership level, let's add a new one...
247
- if(empty($level))
248
- {
249
- $level = new stdClass();
250
- $level->id = NULL;
251
- $level->name = NULL;
252
- $level->description = NULL;
253
- $level->confirmation = NULL;
254
- $level->billing_amount = NULL;
255
- $level->trial_amount = NULL;
256
- $level->initial_payment = NULL;
257
- $level->billing_limit = NULL;
258
- $level->trial_limit = NULL;
259
- $level->expiration_number = NULL;
260
- $level->expiration_period = NULL;
261
- $edit = -1;
262
- }
263
-
264
- //defaults for new levels
265
- if(empty($copy) && $edit == -1)
266
- {
267
- $level->cycle_number = 1;
268
- $level->cycle_period = "Month";
269
- }
270
-
271
- // grab the categories for the given level...
272
- if(!empty($temp_id))
273
- $level->categories = $wpdb->get_col("SELECT c.category_id
274
- FROM $wpdb->pmpro_memberships_categories c
275
- WHERE c.membership_id = '" . $temp_id . "'");
276
- if(empty($level->categories))
277
- $level->categories = array();
278
-
279
- ?>
280
- <form action="" method="post" enctype="multipart/form-data">
281
- <input name="saveid" type="hidden" value="<?php echo $edit?>" />
282
- <input type="hidden" name="action" value="save_membershiplevel" />
283
- <table class="form-table">
284
- <tbody>
285
- <tr>
286
- <th scope="row" valign="top"><label><?php _e('ID', 'pmpro');?>:</label></th>
287
- <td>
288
- <?php echo $level->id?>
289
- </td>
290
- </tr>
291
-
292
- <tr>
293
- <th scope="row" valign="top"><label for="name"><?php _e('Name', 'pmpro');?>:</label></th>
294
- <td><input name="name" type="text" size="50" value="<?php echo esc_attr($level->name);?>" /></td>
295
- </tr>
296
-
297
- <tr>
298
- <th scope="row" valign="top"><label for="description"><?php _e('Description', 'pmpro');?>:</label></th>
299
- <td>
300
- <div id="poststuff" class="pmpro_description">
301
- <?php
302
- if(version_compare($wp_version, "3.3") >= 0)
303
- wp_editor($level->description, "description", array("textarea_rows"=>5));
304
- else
305
- {
306
- ?>
307
- <textarea rows="10" cols="80" name="description" id="description"><?php echo esc_textarea($level->description);?></textarea>
308
- <?php
309
- }
310
- ?>
311
- </div>
312
- </td>
313
- </tr>
314
-
315
- <tr>
316
- <th scope="row" valign="top"><label for="confirmation"><?php _e('Confirmation Message', 'pmpro');?>:</label></th>
317
- <td>
318
- <div class="pmpro_confirmation">
319
- <?php
320
- if(version_compare($wp_version, "3.3") >= 0)
321
- wp_editor($level->confirmation, "confirmation", array("textarea_rows"=>5));
322
- else
323
- {
324
- ?>
325
- <textarea rows="10" cols="80" name="confirmation" id="confirmation"><?php echo esc_textarea($level->confirmation);?></textarea>
326
- <?php
327
- }
328
- ?>
329
- </div>
330
- </td>
331
- </tr>
332
- </tbody>
333
- </table>
334
-
335
- <h3 class="topborder"><?php _e('Billing Details', 'pmpro');?></h3>
336
- <table class="form-table">
337
- <tbody>
338
- <tr>
339
- <th scope="row" valign="top"><label for="initial_payment"><?php _e('Initial Payment', 'pmpro');?>:</label></th>
340
- <td>
341
- <?php
342
- if(pmpro_getCurrencyPosition() == "left")
343
- echo $pmpro_currency_symbol;
344
- ?>
345
- <input name="initial_payment" type="text" size="20" value="<?php echo esc_attr($level->initial_payment);?>" />
346
- <?php
347
- if(pmpro_getCurrencyPosition() == "right")
348
- echo $pmpro_currency_symbol;
349
- ?>
350
- <small><?php _e('The initial amount collected at registration.', 'pmpro');?></small></td>
351
- </tr>
352
-
353
- <tr>
354
- <th scope="row" valign="top"><label><?php _e('Recurring Subscription', 'pmpro');?>:</label></th>
355
- <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.', 'pmpro');?></label></td>
356
- </tr>
357
-
358
- <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
359
- <th scope="row" valign="top"><label for="billing_amount"><?php _e('Billing Amount', 'pmpro');?>:</label></th>
360
- <td>
361
- <?php
362
- if(pmpro_getCurrencyPosition() == "left")
363
- echo $pmpro_currency_symbol;
364
- ?>
365
- <input name="billing_amount" type="text" size="20" value="<?php echo esc_attr($level->billing_amount);?>" />
366
- <?php
367
- if(pmpro_getCurrencyPosition() == "right")
368
- echo $pmpro_currency_symbol;
369
- ?>
370
- <small><?php _e('per', 'pmpro');?></small>
371
- <input id="cycle_number" name="cycle_number" type="text" size="10" value="<?php echo esc_attr($level->cycle_number);?>" />
372
- <select id="cycle_period" name="cycle_period">
373
- <?php
374
- $cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
375
- foreach ( $cycles as $name => $value ) {
376
- echo "<option value='$value'";
377
- if ( $level->cycle_period == $value ) echo " selected='selected'";
378
- echo ">$name</option>";
379
- }
380
- ?>
381
- </select>
382
- <br /><small>
383
- <?php _e('The amount to be billed one cycle after the initial payment.', 'pmpro');?>
384
- <?php if($gateway == "stripe") { ?>
385
- <br /><strong <?php if(!empty($pmpro_stripe_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Stripe integration currently only supports billing periods of "Week", "Month" or "Year".', 'pmpro');?>
386
- <?php } elseif($gateway == "braintree") { ?>
387
- <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".', 'pmpro');?>
388
- <?php } elseif($gateway == "payflowpro") { ?>
389
- <br /><strong <?php if(!empty($pmpro_payflow_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Payflow integration currently only supports billing frequencies of 1 and billing periods of "Week", "Month" or "Year".', 'pmpro');?>
390
- <?php } ?>
391
- </small>
392
- <?php if($gateway == "braintree" && $edit < 0) { ?>
393
- <p class="pmpro_message"><strong><?php _e('Note', 'pmpro');?>:</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.', 'pmpro');?></p>
394
- <?php } elseif($gateway == "braintree") { ?>
395
- <p class="pmpro_message"><strong><?php _e('Note', 'pmpro');?>:</strong> <?php _e('You will need to create a "Plan" in your Braintree dashboard with the same settings and the "Plan ID" set to', 'pmpro');?> <em>pmpro_<?php echo $level->id;?></em>.</p>
396
- <?php } ?>
397
- </td>
398
- </tr>
399
-
400
- <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
401
- <th scope="row" valign="top"><label for="billing_limit"><?php _e('Billing Cycle Limit', 'pmpro');?>:</label></th>
402
- <td>
403
- <input name="billing_limit" type="text" size="20" value="<?php echo $level->billing_limit?>" />
404
- <br /><small>
405
- <?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.', 'pmpro');?>
406
- <?php if($gateway == "stripe") { ?>
407
- <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.', 'pmpro');?></strong>
408
- <?php } ?>
409
- </small>
410
- </td>
411
- </tr>
412
-
413
- <tr class="recurring_info" <?php if (!pmpro_isLevelRecurring($level)) echo "style='display:none;'";?>>
414
- <th scope="row" valign="top"><label><?php _e('Custom Trial', 'pmpro');?>:</label></th>
415
- <td>
416
- <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.', 'pmpro');?></label>
417
-
418
- <?php if($gateway == "twocheckout") { ?>
419
- <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.', 'pmpro');?></strong></small>
420
- <?php } ?>
421
- </td>
422
- </tr>
423
-
424
- <tr class="trial_info recurring_info" <?php if (!pmpro_isLevelTrial($level)) echo "style='display:none;'";?>>
425
- <th scope="row" valign="top"><label for="trial_amount"><?php _e('Trial Billing Amount', 'pmpro');?>:</label></th>
426
- <td>
427
- <?php
428
- if(pmpro_getCurrencyPosition() == "left")
429
- echo $pmpro_currency_symbol;
430
- ?>
431
- <input name="trial_amount" type="text" size="20" value="<?php echo esc_attr($level->trial_amount);?>" />
432
- <?php
433
- if(pmpro_getCurrencyPosition() == "right")
434
- echo $pmpro_currency_symbol;
435
- ?>
436
- <small><?php _e('for the first', 'pmpro');?></small>
437
- <input name="trial_limit" type="text" size="10" value="<?php echo esc_attr($level->trial_limit);?>" />
438
- <small><?php _e('subscription payments', 'pmpro');?>.</small>
439
- <?php if($gateway == "stripe") { ?>
440
- <br /><small>
441
- <strong <?php if(!empty($pmpro_stripe_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Stripe integration currently does not support trial amounts greater than $0.', 'pmpro');?></strong>
442
- </small>
443
- <?php } elseif($gateway == "braintree") { ?>
444
- <br /><small>
445
- <strong <?php if(!empty($pmpro_braintree_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Braintree integration currently does not support trial amounts greater than $0.', 'pmpro');?></strong>
446
- </small>
447
- <?php } elseif($gateway == "payflowpro") { ?>
448
- <br /><small>
449
- <strong <?php if(!empty($pmpro_payflow_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Payflow integration currently does not support trial amounts greater than $0.', 'pmpro');?></strong>
450
- </small>
451
- <?php } ?>
452
- </td>
453
- </tr>
454
-
455
- </tbody>
456
- </table>
457
-
458
- <h3 class="topborder"><?php _e('Other Settings', 'pmpro');?></h3>
459
- <table class="form-table">
460
- <tbody>
461
- <tr>
462
- <th scope="row" valign="top"><label><?php _e('Disable New Signups', 'pmpro');?>:</label></th>
463
- <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.', 'pmpro');?></label></td>
464
- </tr>
465
-
466
- <tr>
467
- <th scope="row" valign="top"><label><?php _e('Membership Expiration', 'pmpro');?>:</label></th>
468
- <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.', 'pmpro');?></a></td>
469
- </tr>
470
-
471
- <tr class="expiration_info" <?php if(!pmpro_isLevelExpiring($level)) {?>style="display: none;"<?php } ?>>
472
- <th scope="row" valign="top"><label for="billing_amount"><?php _e('Expires In', 'pmpro');?>:</label></th>
473
- <td>
474
- <input id="expiration_number" name="expiration_number" type="text" size="10" value="<?php echo esc_attr($level->expiration_number);?>" />
475
- <select id="expiration_period" name="expiration_period">
476
- <?php
477
- $cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
478
- foreach ( $cycles as $name => $value ) {
479
- echo "<option value='$value'";
480
- if ( $level->expiration_period == $value ) echo " selected='selected'";
481
- echo ">$name</option>";
482
- }
483
- ?>
484
- </select>
485
- <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.', 'pmpro');?></small>
486
- </td>
487
- </tr>
488
- </tbody>
489
- </table>
490
-
491
- <?php do_action("pmpro_membership_level_after_other_settings"); ?>
492
-
493
- <h3 class="topborder"><?php _e('Content Settings', 'pmpro');?></h3>
494
- <table class="form-table">
495
- <tbody>
496
- <tr>
497
- <th scope="row" valign="top"><label><?php _e('Categories', 'pmpro');?>:</label></th>
498
- <td>
499
- <?php
500
- $categories = get_categories( array( 'hide_empty' => 0 ) );
501
- echo "<ul>";
502
- foreach ( $categories as $cat )
503
- {
504
- $checked = in_array( $cat->term_id, $level->categories ) ? "checked='checked'" : '';
505
- echo "<li><input id='membershipcategory_{$cat->term_id}' name='membershipcategory_{$cat->term_id}' type='checkbox' value='yes' $checked /> <label for='membershipcategory_{$cat->term_id}'>{$cat->name}</label></li>\n";
506
- }
507
- echo "</ul>";
508
- ?>
509
- </td>
510
- </tr>
511
- </tbody>
512
- </table>
513
- <p class="submit topborder">
514
- <input name="save" type="submit" class="button-primary" value="Save Level" />
515
- <input name="cancel" type="button" value="Cancel" onclick="location.href='<?php echo get_admin_url(NULL, '/admin.php?page=pmpro-membershiplevels')?>';" />
516
- </p>
517
- </form>
518
- </div>
519
-
520
- <?php
521
- }
522
- else
523
- {
524
- ?>
525
-
526
- <h2 class="alignleft"><?php _e('Membership Levels', 'pmpro');?> <a href="admin.php?page=pmpro-membershiplevels&edit=-1" class="add-new-h2"><?php _e('Add New Level', 'pmpro');?></a></h2>
527
- <form id="posts-filter" method="get" action="">
528
- <p class="search-box">
529
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search Levels', 'pmpro');?>:</label>
530
- <input type="hidden" name="page" value="pmpro-membershiplevels" />
531
- <input id="post-search-input" type="text" value="<?php echo $s?>" name="s" size="30" />
532
- <input class="button" type="submit" value="<?php _e('Search Levels', 'pmpro');?>" id="search-submit" />
533
- </p>
534
- </form>
535
-
536
- <br class="clear" />
537
-
538
- <table class="widefat">
539
- <thead>
540
- <tr>
541
- <th><?php _e('ID', 'pmpro');?></th>
542
- <th><?php _e('Name', 'pmpro');?></th>
543
- <th><?php _e('Billing Details', 'pmpro');?></th>
544
- <th><?php _e('Expiration', 'pmpro');?></th>
545
- <th><?php _e('Allow Signups', 'pmpro');?></th>
546
- <th></th>
547
- </tr>
548
- </thead>
549
- <tbody>
550
- <?php
551
- $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ";
552
- if($s)
553
- $sqlQuery .= "WHERE name LIKE '%$s%' ";
554
- $sqlQuery .= "ORDER BY id ASC";
555
-
556
- $levels = $wpdb->get_results($sqlQuery, OBJECT);
557
-
558
- foreach($levels as $level)
559
- {
560
- ?>
561
- <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 } ?>">
562
- <td><?php echo $level->id?></td>
563
- <td class="level_name"><a href="admin.php?page=pmpro-membershiplevels&edit=<?php echo $level->id?>"><?php echo $level->name?></a></td>
564
- <td>
565
- <?php if(pmpro_isLevelFree($level)) { ?>
566
- <?php _e('FREE', 'pmpro');?>
567
- <?php } else { ?>
568
- <?php echo str_replace( 'The price for membership is', '', pmpro_getLevelCost($level)); ?>
569
- <?php } ?>
570
- </td>
571
- <td>
572
- <?php if(!pmpro_isLevelExpiring($level)) { ?>
573
- --
574
- <?php } else { ?>
575
- <?php _e('After', 'pmpro');?> <?php echo $level->expiration_number?> <?php echo sornot($level->expiration_period,$level->expiration_number)?>
576
- <?php } ?>
577
- </td>
578
- <td><?php if($level->allow_signups) { ?><a href="<?php echo pmpro_url("checkout", "?level=" . $level->id);?>"><?php _e('Yes', 'pmpro');?></a><?php } else { ?><?php _e('No', 'pmpro');?><?php } ?></td>
579
-
580
- <td><a title="<?php _e('edit','pmpro'); ?>" href="admin.php?page=pmpro-membershiplevels&edit=<?php echo $level->id?>" class="button-primary"><?php _e('edit','pmpro'); ?></a>&nbsp;<a title="<?php _e('copy','pmpro'); ?>" href="admin.php?page=pmpro-membershiplevels&copy=<?php echo $level->id?>&edit=-1" class="button-secondary"><?php _e('copy','pmpro'); ?></a>&nbsp;<a title="<?php _e('delete','pmpro'); ?>" href="javascript: askfirst('<?php printf(__("Are you sure you want to delete membership level %s? All subscriptions will be cancelled.", "pmpro"), $level->name);?>','admin.php?page=pmpro-membershiplevels&action=delete_membership_level&deleteid=<?php echo $level->id?>'); void(0);" class="button-secondary"><?php _e('delete','pmpro'); ?></a></td>
581
- </tr>
582
- <?php
583
- }
584
- ?>
585
- </tbody>
586
- </table>
587
- <?php
588
- }
589
- ?>
590
-
591
- <?php
592
- require_once(dirname(__FILE__) . "/admin_footer.php");
593
- ?>
594
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.", "pmpro"));
6
+ }
7
+
8
+ global $wpdb, $msg, $msgt, $pmpro_currency_symbol;
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 = $_REQUEST['edit'];
18
+ else
19
+ $edit = false;
20
+ if(isset($_REQUEST['copy']))
21
+ $copy = $_REQUEST['copy'];
22
+ if(isset($_REQUEST['s']))
23
+ $s = $_REQUEST['s'];
24
+ else
25
+ $s = "";
26
+
27
+ if(isset($_REQUEST['action']))
28
+ $action = $_REQUEST['action'];
29
+ else
30
+ $action = false;
31
+
32
+ if(isset($_REQUEST['saveandnext']))
33
+ $saveandnext = $_REQUEST['saveandnext'];
34
+
35
+ if(isset($_REQUEST['saveid']))
36
+ $saveid = $_REQUEST['saveid'];
37
+ if(isset($_REQUEST['deleteid']))
38
+ $deleteid = $_REQUEST['deleteid'];
39
+
40
+ if($action == "save_membershiplevel")
41
+ {
42
+ $ml_name = stripslashes($_REQUEST['name']);
43
+ $ml_description = stripslashes($_REQUEST['description']);
44
+ $ml_confirmation = stripslashes($_REQUEST['confirmation']);
45
+ $ml_initial_payment = stripslashes($_REQUEST['initial_payment']);
46
+ if(!empty($_REQUEST['recurring']))
47
+ $ml_recurring = 1;
48
+ else
49
+ $ml_recurring = 0;
50
+ $ml_billing_amount = stripslashes($_REQUEST['billing_amount']);
51
+ $ml_cycle_number = stripslashes($_REQUEST['cycle_number']);
52
+ $ml_cycle_period = stripslashes($_REQUEST['cycle_period']);
53
+ $ml_billing_limit = stripslashes($_REQUEST['billing_limit']);
54
+ if(!empty($_REQUEST['custom_trial']))
55
+ $ml_custom_trial = 1;
56
+ else
57
+ $ml_custom_trial = 0;
58
+ $ml_trial_amount = stripslashes($_REQUEST['trial_amount']);
59
+ $ml_trial_limit = stripslashes($_REQUEST['trial_limit']);
60
+ if(!empty($_REQUEST['expiration']))
61
+ $ml_expiration = 1;
62
+ else
63
+ $ml_expiration = 0;
64
+ $ml_expiration_number = stripslashes($_REQUEST['expiration_number']);
65
+ $ml_expiration_period = stripslashes($_REQUEST['expiration_period']);
66
+ $ml_categories = array();
67
+
68
+ //reversing disable to allow here
69
+ if(empty($_REQUEST['disable_signups']))
70
+ $ml_allow_signups = 1;
71
+ else
72
+ $ml_allow_signups = 0;
73
+
74
+ foreach ( $_REQUEST as $key => $value )
75
+ {
76
+ if ( $value == 'yes' && preg_match( '/^membershipcategory_(\d+)$/i', $key, $matches ) )
77
+ {
78
+ $ml_categories[] = $matches[1];
79
+ }
80
+ }
81
+
82
+ //clearing out values if checkboxes aren't checked
83
+ if(empty($ml_recurring))
84
+ {
85
+ $ml_billing_amount = $ml_cycle_number = $ml_cycle_period = $ml_billing_limit = $ml_trial_amount = $ml_trial_limit = 0;
86
+ }
87
+ elseif(empty($ml_custom_trial))
88
+ {
89
+ $ml_trial_amount = $ml_trial_limit = 0;
90
+ }
91
+ if(empty($ml_expiration))
92
+ {
93
+ $ml_expiration_number = $ml_expiration_period = 0;
94
+ }
95
+
96
+ if($saveid > 0)
97
+ {
98
+ $sqlQuery = " UPDATE {$wpdb->pmpro_membership_levels}
99
+ SET name = '" . esc_sql($ml_name) . "',
100
+ description = '" . esc_sql($ml_description) . "',
101
+ confirmation = '" . esc_sql($ml_confirmation) . "',
102
+ initial_payment = '" . esc_sql($ml_initial_payment) . "',
103
+ billing_amount = '" . esc_sql($ml_billing_amount) . "',
104
+ cycle_number = '" . esc_sql($ml_cycle_number) . "',
105
+ cycle_period = '" . esc_sql($ml_cycle_period) . "',
106
+ billing_limit = '" . esc_sql($ml_billing_limit) . "',
107
+ trial_amount = '" . esc_sql($ml_trial_amount) . "',
108
+ trial_limit = '" . esc_sql($ml_trial_limit) . "',
109
+ expiration_number = '" . esc_sql($ml_expiration_number) . "',
110
+ expiration_period = '" . esc_sql($ml_expiration_period) . "',
111
+ allow_signups = '" . esc_sql($ml_allow_signups) . "'
112
+ WHERE id = '$saveid' LIMIT 1;";
113
+ $wpdb->query($sqlQuery);
114
+
115
+ pmpro_updateMembershipCategories( $saveid, $ml_categories );
116
+ if(!mysql_errno())
117
+ {
118
+ $edit = false;
119
+ $msg = 2;
120
+ $msgt = __("Membership level updated successfully.", "pmpro");
121
+ }
122
+ else
123
+ {
124
+ $msg = -2;
125
+ $msg = true;
126
+ $msgt = __("Error updating membership level.", "pmpro");
127
+ }
128
+ }
129
+ else
130
+ {
131
+ $sqlQuery = " INSERT INTO {$wpdb->pmpro_membership_levels}
132
+ ( name, description, confirmation, initial_payment, billing_amount, cycle_number, cycle_period, billing_limit, trial_amount, trial_limit, expiration_number, expiration_period, allow_signups)
133
+ VALUES
134
+ ( '" . esc_sql($ml_name) . "', '" . esc_sql($ml_description) . "', '" . esc_sql($ml_confirmation) . "', '" . esc_sql($ml_initial_payment) . "', '" . esc_sql($ml_billing_amount) . "', '" . esc_sql($ml_cycle_number) . "', '" . esc_sql($ml_cycle_period) . "', '" . esc_sql($ml_billing_limit) . "', '" . esc_sql($ml_trial_amount) . "', '" . esc_sql($ml_trial_limit) . "', '" . esc_sql($ml_expiration_number) . "', '" . esc_sql($ml_expiration_period) . "', '" . esc_sql($ml_allow_signups) . "' )";
135
+ $wpdb->query($sqlQuery);
136
+ if(!mysql_errno())
137
+ {
138
+ $saveid = $wpdb->insert_id;
139
+ pmpro_updateMembershipCategories( $saveid, $ml_categories );
140
+
141
+ $edit = false;
142
+ $msg = 1;
143
+ $msgt = __("Membership level added successfully.", "pmpro");
144
+ }
145
+ else
146
+ {
147
+ $msg = -1;
148
+ $msgt = __("Error adding membership level.", "pmpro");
149
+ }
150
+ }
151
+
152
+ do_action("pmpro_save_membership_level", $saveid);
153
+ }
154
+ elseif($action == "delete_membership_level")
155
+ {
156
+ global $wpdb;
157
+
158
+ $ml_id = $_REQUEST['deleteid'];
159
+
160
+ if($ml_id > 0)
161
+ {
162
+ do_action("pmpro_delete_membership_level", $ml_id);
163
+
164
+ //remove any categories from the ml
165
+ $sqlQuery = "DELETE FROM $wpdb->pmpro_memberships_categories WHERE membership_id = '$ml_id'";
166
+ $r1 = $wpdb->query($sqlQuery);
167
+
168
+ //cancel any subscriptions to the ml
169
+ $r2 = true;
170
+ $user_ids = $wpdb->get_col("SELECT user_id FROM $wpdb->pmpro_memberships_users WHERE membership_id = '$ml_id' AND status = 'active'");
171
+ foreach($user_ids as $user_id)
172
+ {
173
+ //change there membership level to none. that will handle the cancel
174
+ if(pmpro_changeMembershipLevel(0, $user_id))
175
+ {
176
+ //okay
177
+ }
178
+ else
179
+ {
180
+ //couldn't delete the subscription
181
+ //we should probably notify the admin
182
+ $pmproemail = new PMProEmail();
183
+ $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.", "pmpro"), $user_id) . "</p>");
184
+ $last_order = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_orders WHERE user_id = '" . $user_id . "' ORDER BY timestamp DESC LIMIT 1");
185
+ if($last_order)
186
+ $pmproemail->data["body"] .= "<p>" . __("Last Invoice", "pmpro") . ":<br />" . nl2br(var_export($last_order, true)) . "</p>";
187
+ $pmproemail->sendEmail(get_bloginfo("admin_email"));
188
+
189
+ $r2 = false;
190
+ }
191
+ }
192
+
193
+ //delete the ml
194
+ $sqlQuery = "DELETE FROM $wpdb->pmpro_membership_levels WHERE id = '$ml_id' LIMIT 1";
195
+ $r3 = $wpdb->query($sqlQuery);
196
+
197
+ if($r1 !== FALSE && $r2 !== FALSE && $r3 !== FALSE)
198
+ {
199
+ $msg = 3;
200
+ $msgt = __("Membership level deleted successfully.", "pmpro");
201
+ }
202
+ else
203
+ {
204
+ $msg = -3;
205
+ $msgt = __("Error deleting membership level.", "pmpro");
206
+ }
207
+ }
208
+ else
209
+ {
210
+ $msg = -3;
211
+ $msgt = __("Error deleting membership level.", "pmpro");
212
+ }
213
+ }
214
+
215
+ require_once(dirname(__FILE__) . "/admin_header.php");
216
+ ?>
217
+
218
+ <?php
219
+ if($edit)
220
+ {
221
+ ?>
222
+
223
+ <h2>
224
+ <?php
225
+ if($edit > 0)
226
+ echo __("Edit Membership Level", "pmpro");
227
+ else
228
+ echo __("Add New Membership Level", "pmpro");
229
+ ?>
230
+ </h2>
231
+
232
+ <div>
233
+ <?php
234
+ // get the level...
235
+ if(!empty($edit) && $edit > 0)
236
+ {
237
+ $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '$edit' LIMIT 1", OBJECT);
238
+ $temp_id = $level->id;
239
+ }
240
+ elseif(!empty($copy) && $copy > 0)
241
+ {
242
+ $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = '$copy' LIMIT 1", OBJECT);
243
+ $temp_id = $level->id;
244
+ $level->id = NULL;
245
+ }
246
+ else
247
+
248
+ // didn't find a membership level, let's add a new one...
249
+ if(empty($level))
250
+ {
251
+ $level = new stdClass();
252
+ $level->id = NULL;
253
+ $level->name = NULL;
254
+ $level->description = NULL;
255
+ $level->confirmation = NULL;
256
+ $level->billing_amount = NULL;
257
+ $level->trial_amount = NULL;
258
+ $level->initial_payment = NULL;
259
+ $level->billing_limit = NULL;
260
+ $level->trial_limit = NULL;
261
+ $level->expiration_number = NULL;
262
+ $level->expiration_period = NULL;
263
+ $edit = -1;
264
+ }
265
+
266
+ //defaults for new levels
267
+ if(empty($copy) && $edit == -1)
268
+ {
269
+ $level->cycle_number = 1;
270
+ $level->cycle_period = "Month";
271
+ }
272
+
273
+ // grab the categories for the given level...
274
+ if(!empty($temp_id))
275
+ $level->categories = $wpdb->get_col("SELECT c.category_id
276
+ FROM $wpdb->pmpro_memberships_categories c
277
+ WHERE c.membership_id = '" . $temp_id . "'");
278
+ if(empty($level->categories))
279
+ $level->categories = array();
280
+
281
+ ?>
282
+ <form action="" method="post" enctype="multipart/form-data">
283
+ <input name="saveid" type="hidden" value="<?php echo $edit?>" />
284
+ <input type="hidden" name="action" value="save_membershiplevel" />
285
+ <table class="form-table">
286
+ <tbody>
287
+ <tr>
288
+ <th scope="row" valign="top"><label><?php _e('ID', 'pmpro');?>:</label></th>
289
+ <td>
290
+ <?php echo $level->id?>
291
+ </td>
292
+ </tr>
293
+
294
+ <tr>
295
+ <th scope="row" valign="top"><label for="name"><?php _e('Name', 'pmpro');?>:</label></th>
296
+ <td><input name="name" type="text" size="50" value="<?php echo esc_attr($level->name);?>" /></td>
297
+ </tr>
298
+
299
+ <tr>
300
+ <th scope="row" valign="top"><label for="description"><?php _e('Description', 'pmpro');?>:</label></th>
301
+ <td>
302
+ <div id="poststuff" class="pmpro_description">
303
+ <?php
304
+ if(version_compare($wp_version, "3.3") >= 0)
305
+ wp_editor($level->description, "description", array("textarea_rows"=>5));
306
+ else
307
+ {
308
+ ?>
309
+ <textarea rows="10" cols="80" name="description" id="description"><?php echo esc_textarea($level->description);?></textarea>
310
+ <?php
311
+ }
312
+ ?>
313
+ </div>
314
+ </td>
315
+ </tr>
316
+
317
+ <tr>
318
+ <th scope="row" valign="top"><label for="confirmation"><?php _e('Confirmation Message', 'pmpro');?>:</label></th>
319
+ <td>
320
+ <div class="pmpro_confirmation">
321
+ <?php
322
+ if(version_compare($wp_version, "3.3") >= 0)
323
+ wp_editor($level->confirmation, "confirmation", array("textarea_rows"=>5));
324
+ else
325
+ {
326
+ ?>
327
+ <textarea rows="10" cols="80" name="confirmation" id="confirmation"><?php echo esc_textarea($level->confirmation);?></textarea>
328
+ <?php
329
+ }
330
+ ?>
331
+ </div>
332
+ </td>
333
+ </tr>
334
+ </tbody>
335
+ </table>
336
+
337
+ <h3 class="topborder"><?php _e('Billing Details', 'pmpro');?></h3>
338
+ <table class="form-table">
339
+ <tbody>
340
+ <tr>
341
+ <th scope="row" valign="top"><label for="initial_payment"><?php _e('Initial Payment', 'pmpro');?>:</label></th>
342
+ <td>
343
+ <?php
344
+ if(pmpro_getCurrencyPosition() == "left")
345
+ echo $pmpro_currency_symbol;
346
+ ?>
347
+ <input name="initial_payment" type="text" size="20" value="<?php echo esc_attr($level->initial_payment);?>" />
348
+ <?php
349
+ if(pmpro_getCurrencyPosition() == "right")
350
+ echo $pmpro_currency_symbol;
351
+ ?>
352
+ <small><?php _e('The initial amount collected at registration.', 'pmpro');?></small></td>
353
+ </tr>
354
+
355
+ <tr>
356
+ <th scope="row" valign="top"><label><?php _e('Recurring Subscription', 'pmpro');?>:</label></th>
357
+ <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.', 'pmpro');?></label></td>
358
+ </tr>
359
+
360
+ <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
361
+ <th scope="row" valign="top"><label for="billing_amount"><?php _e('Billing Amount', 'pmpro');?>:</label></th>
362
+ <td>
363
+ <?php
364
+ if(pmpro_getCurrencyPosition() == "left")
365
+ echo $pmpro_currency_symbol;
366
+ ?>
367
+ <input name="billing_amount" type="text" size="20" value="<?php echo esc_attr($level->billing_amount);?>" />
368
+ <?php
369
+ if(pmpro_getCurrencyPosition() == "right")
370
+ echo $pmpro_currency_symbol;
371
+ ?>
372
+ <small><?php _e('per', 'pmpro');?></small>
373
+ <input id="cycle_number" name="cycle_number" type="text" size="10" value="<?php echo esc_attr($level->cycle_number);?>" />
374
+ <select id="cycle_period" name="cycle_period">
375
+ <?php
376
+ $cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
377
+ foreach ( $cycles as $name => $value ) {
378
+ echo "<option value='$value'";
379
+ if ( $level->cycle_period == $value ) echo " selected='selected'";
380
+ echo ">$name</option>";
381
+ }
382
+ ?>
383
+ </select>
384
+ <br /><small>
385
+ <?php _e('The amount to be billed one cycle after the initial payment.', 'pmpro');?>
386
+ <?php if($gateway == "stripe") { ?>
387
+ <br /><strong <?php if(!empty($pmpro_stripe_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Stripe integration currently only supports billing periods of "Week", "Month" or "Year".', 'pmpro');?>
388
+ <?php } elseif($gateway == "braintree") { ?>
389
+ <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".', 'pmpro');?>
390
+ <?php } elseif($gateway == "payflowpro") { ?>
391
+ <br /><strong <?php if(!empty($pmpro_payflow_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Payflow integration currently only supports billing frequencies of 1 and billing periods of "Week", "Month" or "Year".', 'pmpro');?>
392
+ <?php } ?>
393
+ </small>
394
+ <?php if($gateway == "braintree" && $edit < 0) { ?>
395
+ <p class="pmpro_message"><strong><?php _e('Note', 'pmpro');?>:</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.', 'pmpro');?></p>
396
+ <?php } elseif($gateway == "braintree") { ?>
397
+ <p class="pmpro_message"><strong><?php _e('Note', 'pmpro');?>:</strong> <?php _e('You will need to create a "Plan" in your Braintree dashboard with the same settings and the "Plan ID" set to', 'pmpro');?> <em>pmpro_<?php echo $level->id;?></em>.</p>
398
+ <?php } ?>
399
+ </td>
400
+ </tr>
401
+
402
+ <tr class="recurring_info" <?php if(!pmpro_isLevelRecurring($level)) {?>style="display: none;"<?php } ?>>
403
+ <th scope="row" valign="top"><label for="billing_limit"><?php _e('Billing Cycle Limit', 'pmpro');?>:</label></th>
404
+ <td>
405
+ <input name="billing_limit" type="text" size="20" value="<?php echo $level->billing_limit?>" />
406
+ <br /><small>
407
+ <?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.', 'pmpro');?>
408
+ <?php if($gateway == "stripe") { ?>
409
+ <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.', 'pmpro');?></strong>
410
+ <?php } ?>
411
+ </small>
412
+ </td>
413
+ </tr>
414
+
415
+ <tr class="recurring_info" <?php if (!pmpro_isLevelRecurring($level)) echo "style='display:none;'";?>>
416
+ <th scope="row" valign="top"><label><?php _e('Custom Trial', 'pmpro');?>:</label></th>
417
+ <td>
418
+ <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.', 'pmpro');?></label>
419
+
420
+ <?php if($gateway == "twocheckout") { ?>
421
+ <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.', 'pmpro');?></strong></small>
422
+ <?php } ?>
423
+ </td>
424
+ </tr>
425
+
426
+ <tr class="trial_info recurring_info" <?php if (!pmpro_isLevelTrial($level)) echo "style='display:none;'";?>>
427
+ <th scope="row" valign="top"><label for="trial_amount"><?php _e('Trial Billing Amount', 'pmpro');?>:</label></th>
428
+ <td>
429
+ <?php
430
+ if(pmpro_getCurrencyPosition() == "left")
431
+ echo $pmpro_currency_symbol;
432
+ ?>
433
+ <input name="trial_amount" type="text" size="20" value="<?php echo esc_attr($level->trial_amount);?>" />
434
+ <?php
435
+ if(pmpro_getCurrencyPosition() == "right")
436
+ echo $pmpro_currency_symbol;
437
+ ?>
438
+ <small><?php _e('for the first', 'pmpro');?></small>
439
+ <input name="trial_limit" type="text" size="10" value="<?php echo esc_attr($level->trial_limit);?>" />
440
+ <small><?php _e('subscription payments', 'pmpro');?>.</small>
441
+ <?php if($gateway == "stripe") { ?>
442
+ <br /><small>
443
+ <strong <?php if(!empty($pmpro_stripe_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Stripe integration currently does not support trial amounts greater than $0.', 'pmpro');?></strong>
444
+ </small>
445
+ <?php } elseif($gateway == "braintree") { ?>
446
+ <br /><small>
447
+ <strong <?php if(!empty($pmpro_braintree_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Braintree integration currently does not support trial amounts greater than $0.', 'pmpro');?></strong>
448
+ </small>
449
+ <?php } elseif($gateway == "payflowpro") { ?>
450
+ <br /><small>
451
+ <strong <?php if(!empty($pmpro_payflow_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Payflow integration currently does not support trial amounts greater than $0.', 'pmpro');?></strong>
452
+ </small>
453
+ <?php } ?>
454
+ </td>
455
+ </tr>
456
+
457
+ </tbody>
458
+ </table>
459
+
460
+ <h3 class="topborder"><?php _e('Other Settings', 'pmpro');?></h3>
461
+ <table class="form-table">
462
+ <tbody>
463
+ <tr>
464
+ <th scope="row" valign="top"><label><?php _e('Disable New Signups', 'pmpro');?>:</label></th>
465
+ <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.', 'pmpro');?></label></td>
466
+ </tr>
467
+
468
+ <tr>
469
+ <th scope="row" valign="top"><label><?php _e('Membership Expiration', 'pmpro');?>:</label></th>
470
+ <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.', 'pmpro');?></a></td>
471
+ </tr>
472
+
473
+ <tr class="expiration_info" <?php if(!pmpro_isLevelExpiring($level)) {?>style="display: none;"<?php } ?>>
474
+ <th scope="row" valign="top"><label for="billing_amount"><?php _e('Expires In', 'pmpro');?>:</label></th>
475
+ <td>
476
+ <input id="expiration_number" name="expiration_number" type="text" size="10" value="<?php echo esc_attr($level->expiration_number);?>" />
477
+ <select id="expiration_period" name="expiration_period">
478
+ <?php
479
+ $cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
480
+ foreach ( $cycles as $name => $value ) {
481
+ echo "<option value='$value'";
482
+ if ( $level->expiration_period == $value ) echo " selected='selected'";
483
+ echo ">$name</option>";
484
+ }
485
+ ?>
486
+ </select>
487
+ <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.', 'pmpro');?></small>
488
+ </td>
489
+ </tr>
490
+ </tbody>
491
+ </table>
492
+
493
+ <?php do_action("pmpro_membership_level_after_other_settings"); ?>
494
+
495
+ <h3 class="topborder"><?php _e('Content Settings', 'pmpro');?></h3>
496
+ <table class="form-table">
497
+ <tbody>
498
+ <tr>
499
+ <th scope="row" valign="top"><label><?php _e('Categories', 'pmpro');?>:</label></th>
500
+ <td>
501
+ <?php
502
+ $categories = get_categories( array( 'hide_empty' => 0 ) );
503
+ echo "<ul>";
504
+ foreach ( $categories as $cat )
505
+ {
506
+ $checked = in_array( $cat->term_id, $level->categories ) ? "checked='checked'" : '';
507
+ echo "<li><input id='membershipcategory_{$cat->term_id}' name='membershipcategory_{$cat->term_id}' type='checkbox' value='yes' $checked /> <label for='membershipcategory_{$cat->term_id}'>{$cat->name}</label></li>\n";
508
+ }
509
+ echo "</ul>";
510
+ ?>
511
+ </td>
512
+ </tr>
513
+ </tbody>
514
+ </table>
515
+ <p class="submit topborder">
516
+ <input name="save" type="submit" class="button-primary" value="<?php _e('Save Level', 'pmpro'); ?>" />
517
+ <input name="cancel" type="button" value="<?php _e('Cancel', 'pmpro'); ?>" onclick="location.href='<?php echo get_admin_url(NULL, '/admin.php?page=pmpro-membershiplevels')?>';" />
518
+ </p>
519
+ </form>
520
+ </div>
521
+
522
+ <?php
523
+ }
524
+ else
525
+ {
526
+ ?>
527
+ <script>
528
+ jQuery(document).ready(function($) {
529
+
530
+ // Return a helper with preserved width of cells
531
+ // from http://www.foliotek.com/devblog/make-table-rows-sortable-using-jquery-ui-sortable/
532
+ var fixHelper = function(e, ui) {
533
+ ui.children().each(function() {
534
+ $(this).width($(this).width());
535
+ });
536
+ return ui;
537
+ };
538
+
539
+ $("table.membership-levels tbody").sortable({
540
+ helper: fixHelper,
541
+ placeholder: 'testclass',
542
+ forcePlaceholderSize: true,
543
+ update: update_level_order
544
+ });
545
+
546
+ function update_level_order(event, ui) {
547
+ level_order = [];
548
+ $("table.membership-levels tbody tr").each(function() {
549
+ $(this).removeClass('alternate');
550
+ level_order.push(parseInt( $("td:first", this).text()));
551
+ });
552
+
553
+ //update styles
554
+ $("table.membership-levels tbody tr:odd").each(function() {
555
+ $(this).addClass('alternate');
556
+ });
557
+
558
+ data = {
559
+ action: 'pmpro_update_level_order',
560
+ level_order: level_order
561
+ };
562
+
563
+ $.post(ajaxurl, data, function(response) {
564
+ });
565
+ }
566
+ });
567
+ </script>
568
+
569
+ <h2 class="alignleft"><?php _e('Membership Levels', 'pmpro');?> <a href="admin.php?page=pmpro-membershiplevels&edit=-1" class="add-new-h2"><?php _e('Add New Level', 'pmpro');?></a></h2>
570
+ <form id="posts-filter" method="get" action="">
571
+ <p class="search-box">
572
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search Levels', 'pmpro');?>:</label>
573
+ <input type="hidden" name="page" value="pmpro-membershiplevels" />
574
+ <input id="post-search-input" type="text" value="<?php echo $s?>" name="s" size="30" />
575
+ <input class="button" type="submit" value="<?php _e('Search Levels', 'pmpro');?>" id="search-submit" />
576
+ </p>
577
+ </form>
578
+ <br class="clear" />
579
+ <p><?php _e('Drag and drop membership levels to reorder them on the Levels page.', 'pmpro'); ?></p>
580
+ <table class="widefat membership-levels">
581
+ <thead>
582
+ <tr>
583
+ <th><?php _e('ID', 'pmpro');?></th>
584
+ <th><?php _e('Name', 'pmpro');?></th>
585
+ <th><?php _e('Billing Details', 'pmpro');?></th>
586
+ <th><?php _e('Expiration', 'pmpro');?></th>
587
+ <th><?php _e('Allow Signups', 'pmpro');?></th>
588
+ <th></th>
589
+ </tr>
590
+ </thead>
591
+ <tbody>
592
+ <?php
593
+ $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ";
594
+ if($s)
595
+ $sqlQuery .= "WHERE name LIKE '%$s%' ";
596
+ $sqlQuery .= "ORDER BY id ASC";
597
+
598
+ $levels = $wpdb->get_results($sqlQuery, OBJECT);
599
+
600
+ if(!empty($pmpro_level_order)) {
601
+ //reorder levels
602
+ $order = explode(',', $pmpro_level_order);
603
+
604
+ //put level ids in their own array
605
+ $level_ids = array();
606
+ foreach($levels as $level)
607
+ $level_ids[] = $level->id;
608
+
609
+ //remove levels from order if they are gone
610
+ foreach($order as $key => $level_id)
611
+ if(!in_array($level_id, $level_ids))
612
+ unset($order[$key]);
613
+
614
+ //add levels to the end if they aren't in the order array
615
+ foreach($level_ids as $level_id)
616
+ if(!in_array($level_id, $order))
617
+ $order[] = $level_id;
618
+
619
+ //remove dupes
620
+ $order = array_unique($order);
621
+
622
+ //save the level order
623
+ pmpro_setOption('level_order', implode(',', $order));
624
+
625
+ //reorder levels here
626
+ $reordered_levels = array();
627
+ foreach ($order as $level_id) {
628
+ foreach ($levels as $level) {
629
+ if ($level_id == $level->id)
630
+ $reordered_levels[] = $level;
631
+ }
632
+ }
633
+ }
634
+ else
635
+ $reordered_levels = $levels;
636
+
637
+ $count = 0;
638
+ foreach($reordered_levels as $level)
639
+ {
640
+ ?>
641
+ <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 } ?>">
642
+ <td><?php echo $level->id?></td>
643
+ <td class="level_name"><a href="admin.php?page=pmpro-membershiplevels&edit=<?php echo $level->id?>"><?php echo $level->name?></a></td>
644
+ <td>
645
+ <?php if(pmpro_isLevelFree($level)) { ?>
646
+ <?php _e('FREE', 'pmpro');?>
647
+ <?php } else { ?>
648
+ <?php echo str_replace( 'The price for membership is', '', pmpro_getLevelCost($level)); ?>
649
+ <?php } ?>
650
+ </td>
651
+ <td>
652
+ <?php if(!pmpro_isLevelExpiring($level)) { ?>
653
+ --
654
+ <?php } else { ?>
655
+ <?php _e('After', 'pmpro');?> <?php echo $level->expiration_number?> <?php echo sornot($level->expiration_period,$level->expiration_number)?>
656
+ <?php } ?>
657
+ </td>
658
+ <td><?php if($level->allow_signups) { ?><a href="<?php echo pmpro_url("checkout", "?level=" . $level->id);?>"><?php _e('Yes', 'pmpro');?></a><?php } else { ?><?php _e('No', 'pmpro');?><?php } ?></td>
659
+
660
+ <td><a title="<?php _e('edit','pmpro'); ?>" href="admin.php?page=pmpro-membershiplevels&edit=<?php echo $level->id?>" class="button-primary"><?php _e('edit','pmpro'); ?></a>&nbsp;<a title="<?php _e('copy','pmpro'); ?>" href="admin.php?page=pmpro-membershiplevels&copy=<?php echo $level->id?>&edit=-1" class="button-secondary"><?php _e('copy','pmpro'); ?></a>&nbsp;<a title="<?php _e('delete','pmpro'); ?>" href="javascript: askfirst('<?php printf(__("Are you sure you want to delete membership level %s? All subscriptions will be cancelled.", "pmpro"), $level->name);?>','admin.php?page=pmpro-membershiplevels&action=delete_membership_level&deleteid=<?php echo $level->id?>'); void(0);" class="button-secondary"><?php _e('delete','pmpro'); ?></a></td>
661
+ </tr>
662
+ <?php
663
+ }
664
+ ?>
665
+ </tbody>
666
+ </table>
667
+ <?php
668
+ }
669
+ ?>
670
+
671
+ <?php
672
+ require_once(dirname(__FILE__) . "/admin_footer.php");
673
+ ?>
adminpages/memberslist-csv.php CHANGED
@@ -1,38 +1,38 @@
1
- <?php
2
  //only admins can get this
3
  if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_memberslistcsv")))
4
  {
5
  die(__("You do not have permissions to perform this action.", "pmpro"));
6
- }
7
-
8
- global $wpdb;
9
-
10
- //get users
11
  if(isset($_REQUEST['s']))
12
  $s = $_REQUEST['s'];
13
  else
14
  $s = "";
15
-
16
  if(isset($_REQUEST['l']))
17
  $l = $_REQUEST['l'];
18
  else
19
  $l = false;
20
-
21
  //some vars for the search
22
  if(!empty($_REQUEST['pn']))
23
  $pn = intval($_REQUEST['pn']);
24
  else
25
  $pn = 1;
26
-
27
  if(!empty($_REQUEST['limit']))
28
  $limit = intval($_REQUEST['limit']);
29
  else
30
  $limit = false;
31
-
32
  if($limit)
33
- {
34
  $end = $pn * $limit;
35
- $start = $end - $limit;
36
  }
37
  else
38
  {
@@ -105,9 +105,9 @@
105
 
106
  //get users
107
  $theusers = $wpdb->get_col($sqlQuery);
108
-
109
  //begin output
110
- header("Content-type: text/csv");
111
  if($s && $l == "oldmembers")
112
  header("Content-Disposition: attachment; filename=members_list_expired_" . sanitize_file_name($s) . ".csv");
113
  elseif($s && $l)
@@ -118,17 +118,17 @@
118
  header("Content-Disposition: attachment; filename=members_list_expired.csv");
119
  else
120
  header("Content-Disposition: attachment; filename=members_list.csv");
121
-
122
  $heading = "id,username,firstname,lastname,email,billing firstname,billing lastname,address1,address2,city,state,zipcode,country,phone,membership,initial payment,fee,term,discount_code_id,discount_code,joined";
123
-
124
  if($l == "oldmembers")
125
  $heading .= ",ended";
126
  else
127
  $heading .= ",expires";
128
-
129
  $heading = apply_filters("pmpro_members_list_csv_heading", $heading);
130
  $csvoutput = $heading;
131
-
132
  //these are the meta_keys for the fields (arrays are object, property. so e.g. $theuser->ID)
133
  $default_columns = array(
134
  array("theuser", "ID"),
@@ -156,7 +156,7 @@
156
 
157
  //filter
158
  $default_columns = apply_filters("pmpro_members_list_csv_default_columns", $default_columns);
159
-
160
  //any extra columns
161
  $extra_columns = apply_filters("pmpro_members_list_csv_extra_columns", array());
162
  if(!empty($extra_columns))
@@ -166,32 +166,32 @@
166
  $csvoutput .= "," . $heading;
167
  }
168
  }
169
-
170
- $csvoutput .= "\n";
171
-
172
  //output
173
  echo $csvoutput;
174
  $csvoutput = "";
175
-
176
  if($theusers)
177
  {
178
  foreach($theusers as $user_id)
179
  {
180
  //MULTI: This query will need to be updated to support multiple levels per user. Should probably just dump multiple rows for each membership.
181
  //get meta
182
-
183
  if($l == "oldmembers")
184
  $theuser = $wpdb->get_row("SELECT u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, u.user_login, u.user_nicename, u.user_url, u.user_registered, u.user_status, u.display_name, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id WHERE u.ID = '" . $user_id . "' ORDER BY mu.id DESC LIMIT 1");
185
  else
186
  $theuser = $wpdb->get_row("SELECT u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, u.user_login, u.user_nicename, u.user_url, u.user_registered, u.user_status, u.display_name, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id AND mu.status = 'active' LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id WHERE u.ID = '" . $user_id . "' LIMIT 1");
187
-
188
- $sqlQuery = "SELECT meta_key as `key`, meta_value as `value` FROM $wpdb->usermeta WHERE $wpdb->usermeta.user_id = '" . $user_id . "'";
189
- $metavalues = pmpro_getMetavalues($sqlQuery);
190
  $theuser->metavalues = $metavalues;
191
- $sqlQuery = "SELECT c.id, c.code FROM $wpdb->pmpro_discount_codes_uses cu LEFT JOIN $wpdb->pmpro_discount_codes c ON cu.code_id = c.id WHERE cu.user_id = '" . $theuser->ID . "' ORDER BY c.id DESC LIMIT 1";
192
  $discount_code = $wpdb->get_row($sqlQuery);
193
-
194
- //default columns
195
  if(!empty($default_columns))
196
  {
197
  $count = 0;
@@ -201,16 +201,16 @@
201
  $count++;
202
  if($count > 1)
203
  $csvoutput .= ",";
204
-
205
  //checking $object->property. note the double $$
206
  if(!empty($$col[0]->$col[1]))
207
- $csvoutput .= pmpro_enclose($$col[0]->$col[1]); //output the value
208
  }
209
  }
210
-
211
  //joindate and enddate
212
  $csvoutput .= "," . pmpro_enclose(date("Y-m-d", $theuser->joindate)) . ",";
213
-
214
  if($theuser->membership_id)
215
  {
216
  if($theuser->enddate)
@@ -224,8 +224,8 @@
224
  }
225
  else
226
  $csvoutput .= "N/A";
227
-
228
- //any extra columns
229
  if(!empty($extra_columns))
230
  {
231
  foreach($extra_columns as $heading => $callback)
@@ -233,17 +233,17 @@
233
  $csvoutput .= "," . pmpro_enclose(call_user_func($callback, $theuser, $heading));
234
  }
235
  }
236
-
237
  $csvoutput .= "\n";
238
-
239
  //output
240
  echo $csvoutput;
241
- $csvoutput = "";
242
  }
243
  }
244
-
245
  print $csvoutput;
246
-
247
  function pmpro_enclose($s)
248
  {
249
  return "\"" . str_replace("\"", "\\\"", $s) . "\"";
1
+ <?php
2
  //only admins can get this
3
  if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_memberslistcsv")))
4
  {
5
  die(__("You do not have permissions to perform this action.", "pmpro"));
6
+ }
7
+
8
+ global $wpdb;
9
+
10
+ //get users
11
  if(isset($_REQUEST['s']))
12
  $s = $_REQUEST['s'];
13
  else
14
  $s = "";
15
+
16
  if(isset($_REQUEST['l']))
17
  $l = $_REQUEST['l'];
18
  else
19
  $l = false;
20
+
21
  //some vars for the search
22
  if(!empty($_REQUEST['pn']))
23
  $pn = intval($_REQUEST['pn']);
24
  else
25
  $pn = 1;
26
+
27
  if(!empty($_REQUEST['limit']))
28
  $limit = intval($_REQUEST['limit']);
29
  else
30
  $limit = false;
31
+
32
  if($limit)
33
+ {
34
  $end = $pn * $limit;
35
+ $start = $end - $limit;
36
  }
37
  else
38
  {
105
 
106
  //get users
107
  $theusers = $wpdb->get_col($sqlQuery);
108
+
109
  //begin output
110
+ header("Content-type: text/csv");
111
  if($s && $l == "oldmembers")
112
  header("Content-Disposition: attachment; filename=members_list_expired_" . sanitize_file_name($s) . ".csv");
113
  elseif($s && $l)
118
  header("Content-Disposition: attachment; filename=members_list_expired.csv");
119
  else
120
  header("Content-Disposition: attachment; filename=members_list.csv");
121
+
122
  $heading = "id,username,firstname,lastname,email,billing firstname,billing lastname,address1,address2,city,state,zipcode,country,phone,membership,initial payment,fee,term,discount_code_id,discount_code,joined";
123
+
124
  if($l == "oldmembers")
125
  $heading .= ",ended";
126
  else
127
  $heading .= ",expires";
128
+
129
  $heading = apply_filters("pmpro_members_list_csv_heading", $heading);
130
  $csvoutput = $heading;
131
+
132
  //these are the meta_keys for the fields (arrays are object, property. so e.g. $theuser->ID)
133
  $default_columns = array(
134
  array("theuser", "ID"),
156
 
157
  //filter
158
  $default_columns = apply_filters("pmpro_members_list_csv_default_columns", $default_columns);
159
+
160
  //any extra columns
161
  $extra_columns = apply_filters("pmpro_members_list_csv_extra_columns", array());
162
  if(!empty($extra_columns))
166
  $csvoutput .= "," . $heading;
167
  }
168
  }
169
+
170
+ $csvoutput .= "\n";
171
+
172
  //output
173
  echo $csvoutput;
174
  $csvoutput = "";
175
+
176
  if($theusers)
177
  {
178
  foreach($theusers as $user_id)
179
  {
180
  //MULTI: This query will need to be updated to support multiple levels per user. Should probably just dump multiple rows for each membership.
181
  //get meta
182
+
183
  if($l == "oldmembers")
184
  $theuser = $wpdb->get_row("SELECT u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, u.user_login, u.user_nicename, u.user_url, u.user_registered, u.user_status, u.display_name, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id WHERE u.ID = '" . $user_id . "' ORDER BY mu.id DESC LIMIT 1");
185
  else
186
  $theuser = $wpdb->get_row("SELECT u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, u.user_login, u.user_nicename, u.user_url, u.user_registered, u.user_status, u.display_name, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id AND mu.status = 'active' LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id WHERE u.ID = '" . $user_id . "' LIMIT 1");
187
+
188
+ $sqlQuery = "SELECT meta_key as `key`, meta_value as `value` FROM $wpdb->usermeta WHERE $wpdb->usermeta.user_id = '" . $user_id . "'";
189
+ $metavalues = pmpro_getMetavalues($sqlQuery);
190
  $theuser->metavalues = $metavalues;
191
+ $sqlQuery = "SELECT c.id, c.code FROM $wpdb->pmpro_discount_codes_uses cu LEFT JOIN $wpdb->pmpro_discount_codes c ON cu.code_id = c.id WHERE cu.user_id = '" . $theuser->ID . "' ORDER BY c.id DESC LIMIT 1";
192
  $discount_code = $wpdb->get_row($sqlQuery);
193
+
194
+ //default columns
195
  if(!empty($default_columns))
196
  {
197
  $count = 0;
201
  $count++;
202
  if($count > 1)
203
  $csvoutput .= ",";
204
+
205
  //checking $object->property. note the double $$
206
  if(!empty($$col[0]->$col[1]))
207
+ $csvoutput .= pmpro_enclose($$col[0]->$col[1]); //output the value
208
  }
209
  }
210
+
211
  //joindate and enddate
212
  $csvoutput .= "," . pmpro_enclose(date("Y-m-d", $theuser->joindate)) . ",";
213
+
214
  if($theuser->membership_id)
215
  {
216
  if($theuser->enddate)
224
  }
225
  else
226
  $csvoutput .= "N/A";
227
+
228
+ //any extra columns
229
  if(!empty($extra_columns))
230
  {
231
  foreach($extra_columns as $heading => $callback)
233
  $csvoutput .= "," . pmpro_enclose(call_user_func($callback, $theuser, $heading));
234
  }
235
  }
236
+
237
  $csvoutput .= "\n";
238
+
239
  //output
240
  echo $csvoutput;
241
+ $csvoutput = "";
242
  }
243
  }
244
+
245
  print $csvoutput;
246
+
247
  function pmpro_enclose($s)
248
  {
249
  return "\"" . str_replace("\"", "\\\"", $s) . "\"";
adminpages/memberslist.php CHANGED
@@ -3,30 +3,30 @@
3
  if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_memberslist")))
4
  {
5
  die(__("You do not have permissions to perform this action.", "pmpro"));
6
- }
7
-
8
  //vars
9
  global $wpdb;
10
  if(isset($_REQUEST['s']))
11
  $s = trim($_REQUEST['s']);
12
  else
13
  $s = "";
14
-
15
  if(isset($_REQUEST['l']))
16
  $l = $_REQUEST['l'];
17
  else
18
  $l = false;
19
-
20
- require_once(dirname(__FILE__) . "/admin_header.php");
21
  ?>
22
 
23
- <form id="posts-filter" method="get" action="">
24
  <h2>
25
  <?php _e('Members List', 'pmpro');?>
26
  <a target="_blank" href="<?php echo admin_url('admin-ajax.php');?>?action=memberslist_csv&s=<?php echo $s?>&l=<?php echo $l?>" class="add-new-h2"><?php _e('Export to CSV', 'pmpro');?></a>
27
- </h2>
28
  <ul class="subsubsub">
29
- <li>
30
  <?php _e('Show', 'pmpro');?>
31
  <select name="l" onchange="jQuery('#posts-filter').submit();">
32
  <option value="" <?php if(!$l) { ?>selected="selected"<?php } ?>><?php _e('All Levels', 'pmpro');?></option>
@@ -41,40 +41,40 @@
41
  ?>
42
  <option value="cancelled" <?php if($l == "cancelled") { ?>selected="selected"<?php } ?>><?php _e('Cancelled Members', 'pmpro');?></option>
43
  <option value="expired" <?php if($l == "expired") { ?>selected="selected"<?php } ?>><?php _e('Expired Members', 'pmpro');?></option>
44
- <option value="oldmembers" <?php if($l == "oldmembers") { ?>selected="selected"<?php } ?>><?php _e('Old Members', 'pmpro');?></option>
45
- </select>
46
  </li>
47
  </ul>
48
  <p class="search-box">
49
  <label class="hidden" for="post-search-input"><?php _e('Search Members', 'pmpro');?>:</label>
50
- <input type="hidden" name="page" value="pmpro-memberslist" />
51
  <input id="post-search-input" type="text" value="<?php echo $s?>" name="s"/>
52
  <input class="button" type="submit" value="<?php _e('Search Members', 'pmpro');?>"/>
53
  </p>
54
- <?php
55
  //some vars for the search
56
  if(isset($_REQUEST['pn']))
57
  $pn = intval($_REQUEST['pn']);
58
  else
59
  $pn = 1;
60
-
61
  if(isset($_REQUEST['limit']))
62
  $limit = intval($_REQUEST['limit']);
63
  else
64
  $limit = 15;
65
-
66
  $end = $pn * $limit;
67
- $start = $end - $limit;
68
-
69
  if($s)
70
  {
71
  $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id ";
72
-
73
  if($l == "oldmembers" || $l == "expired" || $l == "cancelled")
74
  $sqlQuery .= " LEFT JOIN $wpdb->pmpro_memberships_users mu2 ON u.ID = mu2.user_id AND mu2.status = 'active' ";
75
-
76
- $sqlQuery .= " WHERE mu.membership_id > 0 AND (u.user_login LIKE '%" . esc_sql($s) . "%' OR u.user_email LIKE '%" . esc_sql($s) . "%' OR um.meta_value LIKE '%" . esc_sql($s) . "%') ";
77
-
78
  if($l == "oldmembers")
79
  $sqlQuery .= " AND mu.status <> 'active' AND mu2.status IS NULL ";
80
  elseif($l == "expired")
@@ -82,28 +82,28 @@
82
  elseif($l == "cancelled")
83
  $sqlQuery .= " AND mu.status IN('cancelled', 'admin_cancelled') AND mu2.status IS NULL ";
84
  elseif($l)
85
- $sqlQuery .= " AND mu.status = 'active' AND mu.membership_id = '" . esc_sql($l) . "' ";
86
  else
87
- $sqlQuery .= " AND mu.status = 'active' ";
88
-
89
  $sqlQuery .= "GROUP BY u.ID ";
90
-
91
  if($l == "oldmembers" || $l == "expired" || $l == "cancelled")
92
  $sqlQuery .= "ORDER BY enddate DESC ";
93
  else
94
  $sqlQuery .= "ORDER BY u.user_registered DESC ";
95
-
96
  $sqlQuery .= "LIMIT $start, $limit";
97
  }
98
  else
99
  {
100
  $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id";
101
-
102
  if($l == "oldmembers" || $l == "expired" || $l == "cancelled")
103
  $sqlQuery .= " LEFT JOIN $wpdb->pmpro_memberships_users mu2 ON u.ID = mu2.user_id AND mu2.status = 'active' ";
104
-
105
  $sqlQuery .= " WHERE mu.membership_id > 0 ";
106
-
107
  if($l == "oldmembers")
108
  $sqlQuery .= " AND mu.status <> 'active' AND mu2.status IS NULL ";
109
  elseif($l == "expired")
@@ -115,27 +115,27 @@
115
  else
116
  $sqlQuery .= " AND mu.status = 'active' ";
117
  $sqlQuery .= "GROUP BY u.ID ";
118
-
119
  if($l == "oldmembers" || $l == "expired" || $l == "cancelled")
120
  $sqlQuery .= "ORDER BY enddate DESC ";
121
  else
122
  $sqlQuery .= "ORDER BY u.user_registered DESC ";
123
-
124
  $sqlQuery .= "LIMIT $start, $limit";
125
  }
126
-
127
  $sqlQuery = apply_filters("pmpro_members_list_sql", $sqlQuery);
128
-
129
  $theusers = $wpdb->get_results($sqlQuery);
130
  $totalrows = $wpdb->get_var("SELECT FOUND_ROWS() as found_rows");
131
-
132
  if($theusers)
133
  {
134
  $calculate_revenue = apply_filters("pmpro_memberslist_calculate_revenue", false);
135
  if($calculate_revenue)
136
  {
137
  $initial_payments = pmpro_calculateInitialPaymentRevenue($s, $l);
138
- $recurring_payments = pmpro_calculateRecurringRevenue($s, $l);
139
  ?>
140
  <p class="clear"><?php echo strval($totalrows)?> members found. These members have paid <strong>$<?php echo number_format($initial_payments)?> in initial payments</strong> and will generate an estimated <strong>$<?php echo number_format($recurring_payments)?> in revenue over the next year</strong>, or <strong>$<?php echo number_format($recurring_payments/12)?>/month</strong>. <span class="pmpro_lite">(This estimate does not take into account trial periods or billing limits.)</span></p>
141
  <?php
@@ -143,10 +143,10 @@
143
  else
144
  {
145
  ?>
146
- <p class="clear"><?php printf(__("%d members found.", "pmpro"), $totalrows);?></span></p>
147
  <?php
148
  }
149
- }
150
  ?>
151
  <table class="widefat">
152
  <thead>
@@ -158,11 +158,11 @@
158
  <th><?php _e('Email', 'pmpro');?></th>
159
  <?php do_action("pmpro_memberslist_extra_cols_header", $theusers);?>
160
  <th><?php _e('Billing Address', 'pmpro');?></th>
161
- <th><?php _e('Membership', 'pmpro');?></th>
162
  <th><?php _e('Fee', 'pmpro');?></th>
163
  <th><?php _e('Joined', 'pmpro');?></th>
164
  <th>
165
- <?php
166
  if($l == "oldmembers")
167
  _e('Ended', 'pmpro');
168
  else
@@ -171,13 +171,13 @@
171
  </th>
172
  </tr>
173
  </thead>
174
- <tbody id="users" class="list:user user-list">
175
- <?php
176
- $count = 0;
177
  foreach($theusers as $auser)
178
  {
179
- //get meta
180
- $theuser = get_userdata($auser->ID);
181
  ?>
182
  <tr <?php if($count++ % 2 == 0) { ?>class="alternate"<?php } ?>>
183
  <td><?php echo $theuser->ID?></td>
@@ -188,11 +188,11 @@
188
  $userlink = '<a href="user-edit.php?user_id=' . $theuser->ID . '">' . $theuser->user_login . '</a>';
189
  $userlink = apply_filters("pmpro_members_list_user_link", $userlink, $theuser);
190
  echo $userlink;
191
- ?>
192
  </strong>
193
- <br />
194
  <?php
195
- // Set up the hover actions for this user
196
  $actions = apply_filters( 'pmpro_memberslist_user_row_actions', array(), $theuser );
197
  $action_count = count( $actions );
198
  $i = 0;
@@ -207,7 +207,7 @@
207
  $out .= '</div>';
208
  echo $out;
209
  }
210
- ?>
211
  </td>
212
  <td><?php echo $theuser->first_name?></td>
213
  <td><?php echo $theuser->last_name?></td>
@@ -216,10 +216,10 @@
216
  <td>
217
  <?php
218
  echo pmpro_formatAddress(trim($theuser->pmpro_bfirstname . " " . $theuser->pmpro_blastname), $theuser->pmpro_baddress1, $theuser->pmpro_baddress2, $theuser->pmpro_bcity, $theuser->pmpro_bstate, $theuser->pmpro_bzipcode, $theuser->pmpro_bcountry, $theuser->pmpro_bphone);
219
- ?>
220
  </td>
221
- <td><?php echo $auser->membership?></td>
222
- <td>
223
  <?php if((float)$auser->initial_payment > 0) { ?>
224
  <?php echo pmpro_formatPrice($auser->initial_payment);?>
225
  <?php } ?>
@@ -230,11 +230,11 @@
230
  <?php if((float)$auser->initial_payment <= 0 && (float)$auser->billing_amount <= 0) { ?>
231
  -
232
  <?php } ?>
233
- </td>
234
  <td><?php echo date(get_option("date_format"), strtotime($theuser->user_registered, current_time("timestamp")))?></td>
235
  <td>
236
- <?php
237
- if($auser->enddate)
238
  echo apply_filters("pmpro_memberslist_expires_column", date(get_option('date_format'), $auser->enddate), $auser);
239
  else
240
  echo __(apply_filters("pmpro_memberslist_expires_column", "Never", $auser), "pmpro");
@@ -243,7 +243,7 @@
243
  </tr>
244
  <?php
245
  }
246
-
247
  if(!$theusers)
248
  {
249
  ?>
@@ -252,15 +252,15 @@
252
  </tr>
253
  <?php
254
  }
255
- ?>
256
  </tbody>
257
  </table>
258
  </form>
259
-
260
  <?php
261
  echo pmpro_getPaginationString($pn, $totalrows, $limit, 1, get_admin_url(NULL, "/admin.php?page=pmpro-memberslist&s=" . urlencode($s)), "&l=$l&limit=$limit&pn=");
262
  ?>
263
-
264
  <?php
265
- require_once(dirname(__FILE__) . "/admin_footer.php");
266
  ?>
3
  if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_memberslist")))
4
  {
5
  die(__("You do not have permissions to perform this action.", "pmpro"));
6
+ }
7
+
8
  //vars
9
  global $wpdb;
10
  if(isset($_REQUEST['s']))
11
  $s = trim($_REQUEST['s']);
12
  else
13
  $s = "";
14
+
15
  if(isset($_REQUEST['l']))
16
  $l = $_REQUEST['l'];
17
  else
18
  $l = false;
19
+
20
+ require_once(dirname(__FILE__) . "/admin_header.php");
21
  ?>
22
 
23
+ <form id="posts-filter" method="get" action="">
24
  <h2>
25
  <?php _e('Members List', 'pmpro');?>
26
  <a target="_blank" href="<?php echo admin_url('admin-ajax.php');?>?action=memberslist_csv&s=<?php echo $s?>&l=<?php echo $l?>" class="add-new-h2"><?php _e('Export to CSV', 'pmpro');?></a>
27
+ </h2>
28
  <ul class="subsubsub">
29
+ <li>
30
  <?php _e('Show', 'pmpro');?>
31
  <select name="l" onchange="jQuery('#posts-filter').submit();">
32
  <option value="" <?php if(!$l) { ?>selected="selected"<?php } ?>><?php _e('All Levels', 'pmpro');?></option>
41
  ?>
42
  <option value="cancelled" <?php if($l == "cancelled") { ?>selected="selected"<?php } ?>><?php _e('Cancelled Members', 'pmpro');?></option>
43
  <option value="expired" <?php if($l == "expired") { ?>selected="selected"<?php } ?>><?php _e('Expired Members', 'pmpro');?></option>
44
+ <option value="oldmembers" <?php if($l == "oldmembers") { ?>selected="selected"<?php } ?>><?php _e('Old Members', 'pmpro');?></option>
45
+ </select>
46
  </li>
47
  </ul>
48
  <p class="search-box">
49
  <label class="hidden" for="post-search-input"><?php _e('Search Members', 'pmpro');?>:</label>
50
+ <input type="hidden" name="page" value="pmpro-memberslist" />
51
  <input id="post-search-input" type="text" value="<?php echo $s?>" name="s"/>
52
  <input class="button" type="submit" value="<?php _e('Search Members', 'pmpro');?>"/>
53
  </p>
54
+ <?php
55
  //some vars for the search
56
  if(isset($_REQUEST['pn']))
57
  $pn = intval($_REQUEST['pn']);
58
  else
59
  $pn = 1;
60
+
61
  if(isset($_REQUEST['limit']))
62
  $limit = intval($_REQUEST['limit']);
63
  else
64
  $limit = 15;
65
+
66
  $end = $pn * $limit;
67
+ $start = $end - $limit;
68
+
69
  if($s)
70
  {
71
  $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id ";
72
+
73
  if($l == "oldmembers" || $l == "expired" || $l == "cancelled")
74
  $sqlQuery .= " LEFT JOIN $wpdb->pmpro_memberships_users mu2 ON u.ID = mu2.user_id AND mu2.status = 'active' ";
75
+
76
+ $sqlQuery .= " WHERE mu.membership_id > 0 AND (u.user_login LIKE '%" . esc_sql($s) . "%' OR u.user_email LIKE '%" . esc_sql($s) . "%' OR um.meta_value LIKE '%" . esc_sql($s) . "%') ";
77
+
78
  if($l == "oldmembers")
79
  $sqlQuery .= " AND mu.status <> 'active' AND mu2.status IS NULL ";
80
  elseif($l == "expired")
82
  elseif($l == "cancelled")
83
  $sqlQuery .= " AND mu.status IN('cancelled', 'admin_cancelled') AND mu2.status IS NULL ";
84
  elseif($l)
85
+ $sqlQuery .= " AND mu.status = 'active' AND mu.membership_id = '" . esc_sql($l) . "' ";
86
  else
87
+ $sqlQuery .= " AND mu.status = 'active' ";
88
+
89
  $sqlQuery .= "GROUP BY u.ID ";
90
+
91
  if($l == "oldmembers" || $l == "expired" || $l == "cancelled")
92
  $sqlQuery .= "ORDER BY enddate DESC ";
93
  else
94
  $sqlQuery .= "ORDER BY u.user_registered DESC ";
95
+
96
  $sqlQuery .= "LIMIT $start, $limit";
97
  }
98
  else
99
  {
100
  $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id";
101
+
102
  if($l == "oldmembers" || $l == "expired" || $l == "cancelled")
103
  $sqlQuery .= " LEFT JOIN $wpdb->pmpro_memberships_users mu2 ON u.ID = mu2.user_id AND mu2.status = 'active' ";
104
+
105
  $sqlQuery .= " WHERE mu.membership_id > 0 ";
106
+
107
  if($l == "oldmembers")
108
  $sqlQuery .= " AND mu.status <> 'active' AND mu2.status IS NULL ";
109
  elseif($l == "expired")
115
  else
116
  $sqlQuery .= " AND mu.status = 'active' ";
117
  $sqlQuery .= "GROUP BY u.ID ";
118
+
119
  if($l == "oldmembers" || $l == "expired" || $l == "cancelled")
120
  $sqlQuery .= "ORDER BY enddate DESC ";
121
  else
122
  $sqlQuery .= "ORDER BY u.user_registered DESC ";
123
+
124
  $sqlQuery .= "LIMIT $start, $limit";
125
  }
126
+
127
  $sqlQuery = apply_filters("pmpro_members_list_sql", $sqlQuery);
128
+
129
  $theusers = $wpdb->get_results($sqlQuery);
130
  $totalrows = $wpdb->get_var("SELECT FOUND_ROWS() as found_rows");
131
+
132
  if($theusers)
133
  {
134
  $calculate_revenue = apply_filters("pmpro_memberslist_calculate_revenue", false);
135
  if($calculate_revenue)
136
  {
137
  $initial_payments = pmpro_calculateInitialPaymentRevenue($s, $l);
138
+ $recurring_payments = pmpro_calculateRecurringRevenue($s, $l);
139
  ?>
140
  <p class="clear"><?php echo strval($totalrows)?> members found. These members have paid <strong>$<?php echo number_format($initial_payments)?> in initial payments</strong> and will generate an estimated <strong>$<?php echo number_format($recurring_payments)?> in revenue over the next year</strong>, or <strong>$<?php echo number_format($recurring_payments/12)?>/month</strong>. <span class="pmpro_lite">(This estimate does not take into account trial periods or billing limits.)</span></p>
141
  <?php
143
  else
144
  {
145
  ?>
146
+ <p class="clear"><?php printf(__("%d members found.", "pmpro"), $totalrows);?></span></p>
147
  <?php
148
  }
149
+ }
150
  ?>
151
  <table class="widefat">
152
  <thead>
158
  <th><?php _e('Email', 'pmpro');?></th>
159
  <?php do_action("pmpro_memberslist_extra_cols_header", $theusers);?>
160
  <th><?php _e('Billing Address', 'pmpro');?></th>
161
+ <th><?php _e('Membership', 'pmpro');?></th>
162
  <th><?php _e('Fee', 'pmpro');?></th>
163
  <th><?php _e('Joined', 'pmpro');?></th>
164
  <th>
165
+ <?php
166
  if($l == "oldmembers")
167
  _e('Ended', 'pmpro');
168
  else
171
  </th>
172
  </tr>
173
  </thead>
174
+ <tbody id="users" class="list:user user-list">
175
+ <?php
176
+ $count = 0;
177
  foreach($theusers as $auser)
178
  {
179
+ //get meta
180
+ $theuser = get_userdata($auser->ID);
181
  ?>
182
  <tr <?php if($count++ % 2 == 0) { ?>class="alternate"<?php } ?>>
183
  <td><?php echo $theuser->ID?></td>
188
  $userlink = '<a href="user-edit.php?user_id=' . $theuser->ID . '">' . $theuser->user_login . '</a>';
189
  $userlink = apply_filters("pmpro_members_list_user_link", $userlink, $theuser);
190
  echo $userlink;
191
+ ?>
192
  </strong>
193
+ <br />
194
  <?php
195
+ // Set up the hover actions for this user
196
  $actions = apply_filters( 'pmpro_memberslist_user_row_actions', array(), $theuser );
197
  $action_count = count( $actions );
198
  $i = 0;
207
  $out .= '</div>';
208
  echo $out;
209
  }
210
+ ?>
211
  </td>
212
  <td><?php echo $theuser->first_name?></td>
213
  <td><?php echo $theuser->last_name?></td>
216
  <td>
217
  <?php
218
  echo pmpro_formatAddress(trim($theuser->pmpro_bfirstname . " " . $theuser->pmpro_blastname), $theuser->pmpro_baddress1, $theuser->pmpro_baddress2, $theuser->pmpro_bcity, $theuser->pmpro_bstate, $theuser->pmpro_bzipcode, $theuser->pmpro_bcountry, $theuser->pmpro_bphone);
219
+ ?>
220
  </td>
221
+ <td><?php echo $auser->membership?></td>
222
+ <td>
223
  <?php if((float)$auser->initial_payment > 0) { ?>
224
  <?php echo pmpro_formatPrice($auser->initial_payment);?>
225
  <?php } ?>
230
  <?php if((float)$auser->initial_payment <= 0 && (float)$auser->billing_amount <= 0) { ?>
231
  -
232
  <?php } ?>
233
+ </td>
234
  <td><?php echo date(get_option("date_format"), strtotime($theuser->user_registered, current_time("timestamp")))?></td>
235
  <td>
236
+ <?php
237
+ if($auser->enddate)
238
  echo apply_filters("pmpro_memberslist_expires_column", date(get_option('date_format'), $auser->enddate), $auser);
239
  else
240
  echo __(apply_filters("pmpro_memberslist_expires_column", "Never", $auser), "pmpro");
243
  </tr>
244
  <?php
245
  }
246
+
247
  if(!$theusers)
248
  {
249
  ?>
252
  </tr>
253
  <?php
254
  }
255
+ ?>
256
  </tbody>
257
  </table>
258
  </form>
259
+
260
  <?php
261
  echo pmpro_getPaginationString($pn, $totalrows, $limit, 1, get_admin_url(NULL, "/admin.php?page=pmpro-memberslist&s=" . urlencode($s)), "&l=$l&limit=$limit&pn=");
262
  ?>
263
+
264
  <?php
265
+ require_once(dirname(__FILE__) . "/admin_footer.php");
266
  ?>
adminpages/orders-csv.php CHANGED
@@ -1,106 +1,106 @@
1
- <?php
2
  //only admins can get this
3
  if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_orderscsv")))
4
  {
5
  die(__("You do not have permissions to perform this action.", "pmpro"));
6
- }
7
-
8
- global $wpdb;
9
-
10
- //get users
11
  if(isset($_REQUEST['s']))
12
  $s = $_REQUEST['s'];
13
  else
14
  $s = "";
15
-
16
  if(isset($_REQUEST['l']))
17
  $l = $_REQUEST['l'];
18
  else
19
  $l = false;
20
-
21
  if(isset($_REQUEST['start-month']))
22
  $start_month = $_REQUEST['start-month'];
23
  else
24
  $start_month = "1";
25
-
26
  if(isset($_REQUEST['start-day']))
27
  $start_day = $_REQUEST['start-day'];
28
  else
29
  $start_day = "1";
30
-
31
  if(isset($_REQUEST['start-year']))
32
  $start_year = $_REQUEST['start-year'];
33
  else
34
  $start_year = date("Y");
35
-
36
  if(isset($_REQUEST['end-month']))
37
  $end_month = $_REQUEST['end-month'];
38
  else
39
  $end_month = date("n");
40
-
41
  if(isset($_REQUEST['end-day']))
42
  $end_day = $_REQUEST['end-day'];
43
  else
44
  $end_day = date("j");
45
-
46
  if(isset($_REQUEST['end-year']))
47
  $end_year = $_REQUEST['end-year'];
48
  else
49
- $end_year = date("Y");
50
-
51
  if(isset($_REQUEST['predefined-date']))
52
  $predefined_date = $_REQUEST['predefined-date'];
53
  else
54
- $predefined_date = "This Month";
55
-
56
  if(isset($_REQUEST['status']))
57
  $status = $_REQUEST['status'];
58
  else
59
  $status = "";
60
-
61
  if(isset($_REQUEST['filter']))
62
  $filter = sanitize_text_field($_REQUEST['filter']);
63
  else
64
- $filter = "all";
65
-
66
  //some vars for the search
67
  if(!empty($_REQUEST['pn']))
68
  $pn = intval($_REQUEST['pn']);
69
  else
70
  $pn = 1;
71
-
72
  if(!empty($_REQUEST['limit']))
73
  $limit = intval($_REQUEST['limit']);
74
  else
75
  $limit = false;
76
-
77
  if($limit)
78
- {
79
  $end = $pn * $limit;
80
- $start = $end - $limit;
81
  }
82
  else
83
  {
84
  $end = NULL;
85
  $start = NULL;
86
  }
87
-
88
  //filters
89
  if($filter == "all" || !$filter)
90
  $condition = "1=1";
91
  elseif($filter == "within-a-date-range")
92
- {
93
  $start_date = $start_year."-".$start_month."-".$start_day;
94
  $end_date = $end_year."-".$end_month."-".$end_day;
95
-
96
  //add times to dates
97
  $start_date = $start_date . " 00:00:00";
98
  $end_date = $end_date . " 23:59:59";
99
-
100
  $condition = "timestamp BETWEEN '".$start_date."' AND '".$end_date."'";
101
  }
102
  elseif($filter == "predefined-date-range")
103
- {
104
  if($predefined_date == "Last Month")
105
  {
106
  $start_date = date("Y-m-d", strtotime("first day of last month", current_time("timestamp")));
@@ -117,76 +117,76 @@
117
  $start_date = date("Y-m-d", strtotime("first day of January $year", current_time("timestamp")));
118
  $end_date = date("Y-m-d", strtotime("last day of December $year", current_time("timestamp")));
119
  }
120
-
121
  elseif($predefined_date == "Last Year")
122
  {
123
  $year = date('Y') - 1;
124
  $start_date = date("Y-m-d", strtotime("first day of January $year", current_time("timestamp")));
125
  $end_date = date("Y-m-d", strtotime("last day of December $year", current_time("timestamp")));
126
  }
127
-
128
  //add times to dates
129
  $start_date = $start_date . " 00:00:00";
130
  $end_date = $end_date . " 23:59:59";
131
-
132
  $condition = "timestamp BETWEEN '".esc_sql($start_date)."' AND '".esc_sql($end_date)."'";
133
- }
134
  elseif($filter == "within-a-level")
135
  {
136
  $condition = "membership_id = " . esc_sql($l);
137
- }
138
  elseif($filter == "within-a-status")
139
  {
140
  $condition = "status = '" . esc_sql($status) . "' ";
141
- }
142
-
143
  //string search
144
  if($s)
145
  {
146
  $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS o.id FROM $wpdb->pmpro_membership_orders o LEFT JOIN $wpdb->users u ON o.user_id = u.ID LEFT JOIN $wpdb->pmpro_membership_levels l ON o.membership_id = l.id ";
147
-
148
  $join_with_usermeta = apply_filters("pmpro_orders_search_usermeta", false);
149
  if($join_with_usermeta)
150
  $sqlQuery .= "LEFT JOIN $wpdb->usermeta um ON o.user_id = um.user_id ";
151
-
152
  $sqlQuery .= "WHERE (1=2 ";
153
-
154
  $fields = array("o.id", "o.code", "o.billing_name", "o.billing_street", "o.billing_city", "o.billing_state", "o.billing_zip", "o.billing_phone", "o.payment_type", "o.cardtype", "o.accountnumber", "o.status", "o.gateway", "o.gateway_environment", "o.payment_transaction_id", "o.subscription_transaction_id", "u.user_login", "u.user_email", "u.display_name", "l.name");
155
-
156
  if($join_with_usermeta)
157
  $fields[] = "um.meta_value";
158
-
159
  $fields = apply_filters("pmpro_orders_search_fields", $fields);
160
-
161
  foreach($fields as $field)
162
  $sqlQuery .= " OR " . $field . " LIKE '%" . esc_sql($s) . "%' ";
163
  $sqlQuery .= ") ";
164
-
165
  $sqlQuery .= "AND " . $condition . " ";
166
-
167
  $sqlQuery .= "GROUP BY o.id ORDER BY o.id DESC, o.timestamp DESC ";
168
  }
169
  else
170
  {
171
  $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS id FROM $wpdb->pmpro_membership_orders WHERE ".$condition." ORDER BY id DESC, timestamp DESC ";
172
  }
173
-
174
  if(!empty($start) && !empty($limit))
175
  $sqlQuery .= "LIMIT $start, $limit";
176
-
177
- $order_ids = $wpdb->get_col($sqlQuery);
178
-
179
  //begin output
180
- header("Content-type: text/csv");
181
-
182
  $filename = "orders.csv";
183
  /*
184
  Insert logic here for building filename from $filter and other values.
185
  */
186
- header("Content-Disposition: attachment; filename=$filename;");
187
-
188
  $csvoutput = "id,user_id,user_login,first_name,last_name,user_email,billing_name,billing_street,billing_city,billing_state,billing_zip,billing_country,billing_phone,membership_id,level_name,subtotal,tax,couponamount,total,payment_type,cardtype,accountnumber,expirationmonth,expirationyear,status,gateway,gateway_environment,payment_transaction_id,subscription_transaction_id,discount_code_id,discount_code,timestamp";
189
-
190
  //these are the meta_keys for the fields (arrays are object, property. so e.g. $theuser->ID)
191
  $default_columns = array(
192
  array("order", "id"),
@@ -205,7 +205,7 @@
205
  array("order", "membership_id"),
206
  array("level", "name"),
207
  array("order", "subtotal"),
208
- array("order", "tax"),
209
  array("order", "couponamount"),
210
  array("order", "total"),
211
  array("order", "payment_type"),
@@ -221,7 +221,7 @@
221
  array("discount_code", "id"),
222
  array("discount_code", "code")
223
  );
224
-
225
  //any extra columns
226
  $extra_columns = apply_filters("pmpro_orders_csv_extra_columns", array());
227
  if(!empty($extra_columns))
@@ -231,13 +231,13 @@
231
  $csvoutput .= "," . $heading;
232
  }
233
  }
234
-
235
- $csvoutput .= "\n";
236
-
237
  //output
238
  echo $csvoutput;
239
  $csvoutput = "";
240
-
241
  if($order_ids)
242
  {
243
  foreach($order_ids as $order_id)
@@ -249,8 +249,8 @@
249
  $level = $order->getMembershipLevel();
250
  $sqlQuery = "SELECT c.id, c.code FROM $wpdb->pmpro_discount_codes_uses cu LEFT JOIN $wpdb->pmpro_discount_codes c ON cu.code_id = c.id WHERE cu.order_id = '" . $order_id . "' LIMIT 1";
251
  $discount_code = $wpdb->get_row($sqlQuery);
252
-
253
- //default columns
254
  if(!empty($default_columns))
255
  {
256
  $count = 0;
@@ -260,19 +260,19 @@
260
  $count++;
261
  if($count > 1)
262
  $csvoutput .= ",";
263
-
264
- //checking $object->property. note the double $$
265
  if(!empty($col[2]) && isset($$col[0]->$col[1]->$col[2]))
266
- $csvoutput .= pmpro_enclose($$col[0]->$col[1]->$col[2]); //output the value
267
  elseif(!empty($$col[0]->$col[1]))
268
- $csvoutput .= pmpro_enclose($$col[0]->$col[1]); //output the value
269
  }
270
  }
271
-
272
  //timestamp
273
  $csvoutput .= "," . pmpro_enclose(date(get_option("date_format"), $order->timestamp));
274
-
275
- //any extra columns
276
  if(!empty($extra_columns))
277
  {
278
  foreach($extra_columns as $heading => $callback)
@@ -280,18 +280,18 @@
280
  $csvoutput .= "," . pmpro_enclose(call_user_func($callback, $order));
281
  }
282
  }
283
-
284
  $csvoutput .= "\n";
285
-
286
  //output
287
  echo $csvoutput;
288
- $csvoutput = "";
289
  }
290
- }
291
-
292
  print $csvoutput;
293
-
294
  function pmpro_enclose($s)
295
- {
296
  return "\"" . str_replace("\"", "\\\"", $s) . "\"";
297
  }
1
+ <?php
2
  //only admins can get this
3
  if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_orderscsv")))
4
  {
5
  die(__("You do not have permissions to perform this action.", "pmpro"));
6
+ }
7
+
8
+ global $wpdb;
9
+
10
+ //get users
11
  if(isset($_REQUEST['s']))
12
  $s = $_REQUEST['s'];
13
  else
14
  $s = "";
15
+
16
  if(isset($_REQUEST['l']))
17
  $l = $_REQUEST['l'];
18
  else
19
  $l = false;
20
+
21
  if(isset($_REQUEST['start-month']))
22
  $start_month = $_REQUEST['start-month'];
23
  else
24
  $start_month = "1";
25
+
26
  if(isset($_REQUEST['start-day']))
27
  $start_day = $_REQUEST['start-day'];
28
  else
29
  $start_day = "1";
30
+
31
  if(isset($_REQUEST['start-year']))
32
  $start_year = $_REQUEST['start-year'];
33
  else
34
  $start_year = date("Y");
35
+
36
  if(isset($_REQUEST['end-month']))
37
  $end_month = $_REQUEST['end-month'];
38
  else
39
  $end_month = date("n");
40
+
41
  if(isset($_REQUEST['end-day']))
42
  $end_day = $_REQUEST['end-day'];
43
  else
44
  $end_day = date("j");
45
+
46
  if(isset($_REQUEST['end-year']))
47
  $end_year = $_REQUEST['end-year'];
48
  else
49
+ $end_year = date("Y");
50
+
51
  if(isset($_REQUEST['predefined-date']))
52
  $predefined_date = $_REQUEST['predefined-date'];
53
  else
54
+ $predefined_date = "This Month";
55
+
56
  if(isset($_REQUEST['status']))
57
  $status = $_REQUEST['status'];
58
  else
59
  $status = "";
60
+
61
  if(isset($_REQUEST['filter']))
62
  $filter = sanitize_text_field($_REQUEST['filter']);
63
  else
64
+ $filter = "all";
65
+
66
  //some vars for the search
67
  if(!empty($_REQUEST['pn']))
68
  $pn = intval($_REQUEST['pn']);
69
  else
70
  $pn = 1;
71
+
72
  if(!empty($_REQUEST['limit']))
73
  $limit = intval($_REQUEST['limit']);
74
  else
75
  $limit = false;
76
+
77
  if($limit)
78
+ {
79
  $end = $pn * $limit;
80
+ $start = $end - $limit;
81
  }
82
  else
83
  {
84
  $end = NULL;
85
  $start = NULL;
86
  }
87
+
88
  //filters
89
  if($filter == "all" || !$filter)
90
  $condition = "1=1";
91
  elseif($filter == "within-a-date-range")
92
+ {
93
  $start_date = $start_year."-".$start_month."-".$start_day;
94
  $end_date = $end_year."-".$end_month."-".$end_day;
95
+
96
  //add times to dates
97
  $start_date = $start_date . " 00:00:00";
98
  $end_date = $end_date . " 23:59:59";
99
+
100
  $condition = "timestamp BETWEEN '".$start_date."' AND '".$end_date."'";
101
  }
102
  elseif($filter == "predefined-date-range")
103
+ {
104
  if($predefined_date == "Last Month")
105
  {
106
  $start_date = date("Y-m-d", strtotime("first day of last month", current_time("timestamp")));
117
  $start_date = date("Y-m-d", strtotime("first day of January $year", current_time("timestamp")));
118
  $end_date = date("Y-m-d", strtotime("last day of December $year", current_time("timestamp")));
119
  }
120
+
121
  elseif($predefined_date == "Last Year")
122
  {
123
  $year = date('Y') - 1;
124
  $start_date = date("Y-m-d", strtotime("first day of January $year", current_time("timestamp")));
125
  $end_date = date("Y-m-d", strtotime("last day of December $year", current_time("timestamp")));
126
  }
127
+
128
  //add times to dates
129
  $start_date = $start_date . " 00:00:00";
130
  $end_date = $end_date . " 23:59:59";
131
+
132
  $condition = "timestamp BETWEEN '".esc_sql($start_date)."' AND '".esc_sql($end_date)."'";
133
+ }
134
  elseif($filter == "within-a-level")
135
  {
136
  $condition = "membership_id = " . esc_sql($l);
137
+ }
138
  elseif($filter == "within-a-status")
139
  {
140
  $condition = "status = '" . esc_sql($status) . "' ";
141
+ }
142
+
143
  //string search
144
  if($s)
145
  {
146
  $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS o.id FROM $wpdb->pmpro_membership_orders o LEFT JOIN $wpdb->users u ON o.user_id = u.ID LEFT JOIN $wpdb->pmpro_membership_levels l ON o.membership_id = l.id ";
147
+
148
  $join_with_usermeta = apply_filters("pmpro_orders_search_usermeta", false);
149
  if($join_with_usermeta)
150
  $sqlQuery .= "LEFT JOIN $wpdb->usermeta um ON o.user_id = um.user_id ";
151
+
152
  $sqlQuery .= "WHERE (1=2 ";
153
+
154
  $fields = array("o.id", "o.code", "o.billing_name", "o.billing_street", "o.billing_city", "o.billing_state", "o.billing_zip", "o.billing_phone", "o.payment_type", "o.cardtype", "o.accountnumber", "o.status", "o.gateway", "o.gateway_environment", "o.payment_transaction_id", "o.subscription_transaction_id", "u.user_login", "u.user_email", "u.display_name", "l.name");
155
+
156
  if($join_with_usermeta)
157
  $fields[] = "um.meta_value";
158
+
159
  $fields = apply_filters("pmpro_orders_search_fields", $fields);
160
+
161
  foreach($fields as $field)
162
  $sqlQuery .= " OR " . $field . " LIKE '%" . esc_sql($s) . "%' ";
163
  $sqlQuery .= ") ";
164
+
165
  $sqlQuery .= "AND " . $condition . " ";
166
+
167
  $sqlQuery .= "GROUP BY o.id ORDER BY o.id DESC, o.timestamp DESC ";
168
  }
169
  else
170
  {
171
  $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS id FROM $wpdb->pmpro_membership_orders WHERE ".$condition." ORDER BY id DESC, timestamp DESC ";
172
  }
173
+
174
  if(!empty($start) && !empty($limit))
175
  $sqlQuery .= "LIMIT $start, $limit";
176
+
177
+ $order_ids = $wpdb->get_col($sqlQuery);
178
+
179
  //begin output
180
+ header("Content-type: text/csv");
181
+
182
  $filename = "orders.csv";
183
  /*
184
  Insert logic here for building filename from $filter and other values.
185
  */
186
+ header("Content-Disposition: attachment; filename=$filename;");
187
+
188
  $csvoutput = "id,user_id,user_login,first_name,last_name,user_email,billing_name,billing_street,billing_city,billing_state,billing_zip,billing_country,billing_phone,membership_id,level_name,subtotal,tax,couponamount,total,payment_type,cardtype,accountnumber,expirationmonth,expirationyear,status,gateway,gateway_environment,payment_transaction_id,subscription_transaction_id,discount_code_id,discount_code,timestamp";
189
+
190
  //these are the meta_keys for the fields (arrays are object, property. so e.g. $theuser->ID)
191
  $default_columns = array(
192
  array("order", "id"),
205
  array("order", "membership_id"),
206
  array("level", "name"),
207
  array("order", "subtotal"),
208
+ array("order", "tax"),
209
  array("order", "couponamount"),
210
  array("order", "total"),
211
  array("order", "payment_type"),
221
  array("discount_code", "id"),
222
  array("discount_code", "code")
223
  );
224
+
225
  //any extra columns
226
  $extra_columns = apply_filters("pmpro_orders_csv_extra_columns", array());
227
  if(!empty($extra_columns))
231
  $csvoutput .= "," . $heading;
232
  }
233
  }
234
+
235
+ $csvoutput .= "\n";
236
+
237
  //output
238
  echo $csvoutput;
239
  $csvoutput = "";
240
+
241
  if($order_ids)
242
  {
243
  foreach($order_ids as $order_id)
249
  $level = $order->getMembershipLevel();
250
  $sqlQuery = "SELECT c.id, c.code FROM $wpdb->pmpro_discount_codes_uses cu LEFT JOIN $wpdb->pmpro_discount_codes c ON cu.code_id = c.id WHERE cu.order_id = '" . $order_id . "' LIMIT 1";
251
  $discount_code = $wpdb->get_row($sqlQuery);
252
+
253
+ //default columns
254
  if(!empty($default_columns))
255
  {
256
  $count = 0;
260
  $count++;
261
  if($count > 1)
262
  $csvoutput .= ",";
263
+
264
+ //checking $object->property. note the double $$
265
  if(!empty($col[2]) && isset($$col[0]->$col[1]->$col[2]))
266
+ $csvoutput .= pmpro_enclose($$col[0]->$col[1]->$col[2]); //output the value
267
  elseif(!empty($$col[0]->$col[1]))
268
+ $csvoutput .= pmpro_enclose($$col[0]->$col[1]); //output the value
269
  }
270
  }
271
+
272
  //timestamp
273
  $csvoutput .= "," . pmpro_enclose(date(get_option("date_format"), $order->timestamp));
274
+
275
+ //any extra columns
276
  if(!empty($extra_columns))
277
  {
278
  foreach($extra_columns as $heading => $callback)
280
  $csvoutput .= "," . pmpro_enclose(call_user_func($callback, $order));
281
  }
282
  }
283
+
284
  $csvoutput .= "\n";
285
+
286
  //output
287
  echo $csvoutput;
288
+ $csvoutput = "";
289
  }
290
+ }
291
+
292
  print $csvoutput;
293
+
294
  function pmpro_enclose($s)
295
+ {
296
  return "\"" . str_replace("\"", "\\\"", $s) . "\"";
297
  }
adminpages/orders.php CHANGED
@@ -932,9 +932,9 @@
932
  <?php } else { ?>
933
  [<?php _e('deleted', 'pmpro');?>]
934
  <?php } ?>
935
- <br />
936
  <?php
937
- // Set up the hover actions for this user
938
  $actions = apply_filters( 'pmpro_orders_user_row_actions', array(), $order->user );
939
  $action_count = count( $actions );
940
  $i = 0;
932
  <?php } else { ?>
933
  [<?php _e('deleted', 'pmpro');?>]
934
  <?php } ?>
935
+ <br />
936
  <?php
937
+ // Set up the hover actions for this user
938
  $actions = apply_filters( 'pmpro_orders_user_row_actions', array(), $order->user );
939
  $action_count = count( $actions );
940
  $i = 0;
adminpages/pagesettings.php CHANGED
@@ -1,257 +1,260 @@
1
- <?php
2
- //only admins can get this
3
- if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_pagesettings")))
4
- {
5
- die(__("You do not have permissions to perform this action.", "pmpro"));
6
- }
7
-
8
- global $wpdb, $msg, $msgt;
9
-
10
- //get/set settings
11
- global $pmpro_pages;
12
- if(!empty($_REQUEST['savesettings']))
13
- {
14
- //page ids
15
- pmpro_setOption("account_page_id");
16
- pmpro_setOption("billing_page_id");
17
- pmpro_setOption("cancel_page_id");
18
- pmpro_setOption("checkout_page_id");
19
- pmpro_setOption("confirmation_page_id");
20
- pmpro_setOption("invoice_page_id");
21
- pmpro_setOption("levels_page_id");
22
-
23
- //update the pages array
24
- $pmpro_pages["account"] = pmpro_getOption("account_page_id");
25
- $pmpro_pages["billing"] = pmpro_getOption("billing_page_id");
26
- $pmpro_pages["cancel"] = pmpro_getOption("cancel_page_id");
27
- $pmpro_pages["checkout"] = pmpro_getOption("checkout_page_id");
28
- $pmpro_pages["confirmation"] = pmpro_getOption("confirmation_page_id");
29
- $pmpro_pages["invoice"] = pmpro_getOption("invoice_page_id");
30
- $pmpro_pages["levels"] = pmpro_getOption("levels_page_id");
31
-
32
- //assume success
33
- $msg = true;
34
- $msgt = "Your page settings have been updated.";
35
- }
36
-
37
- //are we generating pages?
38
- if(!empty($_REQUEST['createpages']))
39
- {
40
- global $pmpro_pages;
41
-
42
- $pages_created = array();
43
-
44
- //check the pages array
45
- foreach($pmpro_pages as $pmpro_page_name => $pmpro_page_id)
46
- {
47
- if(!$pmpro_page_id)
48
- {
49
- switch ($pmpro_page_name) {
50
- case 'account':
51
- $pmpro_page_title = __( 'Membership Account', 'pmpro' );
52
- break;
53
- case 'billing':
54
- $pmpro_page_title = __( 'Membership Billing', 'pmpro' );
55
- break;
56
- case 'cancel':
57
- $pmpro_page_title = __( 'Membership Cancel', 'pmpro' );
58
- break;
59
- case 'checkout':
60
- $pmpro_page_title = __( 'Membership Checkout', 'pmpro' );
61
- break;
62
- case 'confirmation':
63
- $pmpro_page_title = __( 'Membership Confirmation', 'pmpro' );
64
- break;
65
- case 'invoice':
66
- $pmpro_page_title = __( 'Membership Invoice', 'pmpro' );
67
- break;
68
- case 'levels':
69
- $pmpro_page_title = __( 'Membership Levels', 'pmpro' );
70
- break;
71
-
72
- default:
73
- $pmpro_page_title = sprintf( __( 'Membership %s', 'Page title template', 'pmpro' ), ucwords($pmpro_page_name) );
74
- break;
75
- }
76
-
77
- //no id set. create an array to store the page info
78
- $insert = array(
79
- 'post_title' => $pmpro_page_title,
80
- 'post_status' => 'publish',
81
- 'post_type' => 'page',
82
- 'post_content' => '[pmpro_' . $pmpro_page_name . ']',
83
- 'comment_status' => 'closed',
84
- 'ping_status' => 'closed'
85
- );
86
-
87
- //make non-account pages a subpage of account
88
- if($pmpro_page_name != "account")
89
- {
90
- $insert['post_parent'] = $pmpro_pages['account'];
91
- }
92
-
93
- //create the page
94
- $pmpro_pages[$pmpro_page_name] = wp_insert_post( $insert );
95
-
96
- //add besecure post option to pages that need it
97
- /* these pages are handling this themselves in the preheader
98
- if(in_array($pmpro_page_name, array("billing", "checkout")))
99
- update_post_meta($pmpro_pages[$pmpro_page_name], "besecure", 1);
100
- */
101
-
102
- //update the option too
103
- pmpro_setOption($pmpro_page_name . "_page_id", $pmpro_pages[$pmpro_page_name]);
104
- $pages_created[] = $pmpro_pages[$pmpro_page_name];
105
- }
106
- }
107
-
108
- if(!empty($pages_created))
109
- {
110
- $msg = true;
111
- $msgt = __("The following pages have been created for you", "pmpro") . ": " . implode(", ", $pages_created) . ".";
112
- }
113
- }
114
-
115
- require_once(dirname(__FILE__) . "/admin_header.php");
116
- ?>
117
-
118
-
119
- <form action="" method="post" enctype="multipart/form-data">
120
- <h2><?php _e('Pages', 'pmpro');?></h2>
121
- <?php
122
- global $pmpro_pages_ready;
123
- if($pmpro_pages_ready)
124
- {
125
- ?>
126
- <p><?php _e('Manage the WordPress pages assigned to each required Paid Memberships Pro page.', 'pmpro');?></p>
127
- <?php
128
- }
129
- else
130
- {
131
- ?>
132
- <p><?php _e('Assign the WordPress pages for each required Paid Memberships Pro page or', 'pmpro');?> <a href="?page=pmpro-pagesettings&createpages=1"><?php _e('click here to let us generate them for you', 'pmpro');?></a>.</p>
133
- <?php
134
- }
135
- ?>
136
- <table class="form-table">
137
- <tbody>
138
- <tr>
139
- <th scope="row" valign="top">
140
- <label for="account_page_id"><?php _e('Account Page', 'pmpro');?>:</label>
141
- </th>
142
- <td>
143
- <?php
144
- wp_dropdown_pages(array("name"=>"account_page_id", "show_option_none"=>"-- Choose One --", "selected"=>$pmpro_pages['account']));
145
- ?>
146
- <?php if(!empty($pmpro_pages['account'])) { ?>
147
- <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['account'];?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
148
- &nbsp;
149
- <a target="_blank" href="<?php echo get_permalink($pmpro_pages['account']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
150
- <?php } ?>
151
- <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_account].</small>
152
- </td>
153
- <tr>
154
- <th scope="row" valign="top">
155
- <label for="billing_page_id"><?php _e('Billing Information Page', 'pmpro');?>:</label>
156
- </th>
157
- <td>
158
- <?php
159
- wp_dropdown_pages(array("name"=>"billing_page_id", "show_option_none"=>"-- Choose One --", "selected"=>$pmpro_pages['billing']));
160
- ?>
161
- <?php if(!empty($pmpro_pages['billing'])) { ?>
162
- <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['billing']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
163
- &nbsp;
164
- <a target="_blank" href="<?php echo get_permalink($pmpro_pages['billing']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
165
- <?php } ?>
166
- <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_billing].</small>
167
- </td>
168
- <tr>
169
- <th scope="row" valign="top">
170
- <label for="cancel_page_id"><?php _e('Cancel Page', 'pmpro');?>:</label>
171
- </th>
172
- <td>
173
- <?php
174
- wp_dropdown_pages(array("name"=>"cancel_page_id", "show_option_none"=>"-- Choose One --", "selected"=>$pmpro_pages['cancel']));
175
- ?>
176
- <?php if(!empty($pmpro_pages['cancel'])) { ?>
177
- <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['cancel']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
178
- &nbsp;
179
- <a target="_blank" href="<?php echo get_permalink($pmpro_pages['cancel']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
180
- <?php } ?>
181
- <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_cancel].</small>
182
- </td>
183
- </tr>
184
- <tr>
185
- <th scope="row" valign="top">
186
- <label for="checkout_page_id"><?php _e('Checkout Page', 'pmpro');?>:</label>
187
- </th>
188
- <td>
189
- <?php
190
- wp_dropdown_pages(array("name"=>"checkout_page_id", "show_option_none"=>"-- Choose One --", "selected"=>$pmpro_pages['checkout']));
191
- ?>
192
- <?php if(!empty($pmpro_pages['checkout'])) { ?>
193
- <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['checkout']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
194
- &nbsp;
195
- <a target="_blank" href="<?php echo get_permalink($pmpro_pages['checkout']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
196
- <?php } ?>
197
- <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_checkout].</small>
198
- </td>
199
- </tr>
200
- <tr>
201
- <th scope="row" valign="top">
202
- <label for="confirmation_page_id"><?php _e('Confirmation Page', 'pmpro');?>:</label>
203
- </th>
204
- <td>
205
- <?php
206
- wp_dropdown_pages(array("name"=>"confirmation_page_id", "show_option_none"=>"-- Choose One --", "selected"=>$pmpro_pages['confirmation']));
207
- ?>
208
- <?php if(!empty($pmpro_pages['confirmation'])) { ?>
209
- <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['confirmation']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
210
- &nbsp;
211
- <a target="_blank" href="<?php echo get_permalink($pmpro_pages['confirmation']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
212
- <?php } ?>
213
- <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_confirmation].</small>
214
- </td>
215
- </tr>
216
- <tr>
217
- <th scope="row" valign="top">
218
- <label for="invoice_page_id"><?php _e('Invoice Page', 'pmpro');?>:</label>
219
- </th>
220
- <td>
221
- <?php
222
- wp_dropdown_pages(array("name"=>"invoice_page_id", "show_option_none"=>"-- Choose One --", "selected"=>$pmpro_pages['invoice']));
223
- ?>
224
- <?php if(!empty($pmpro_pages['invoice'])) { ?>
225
- <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['invoice']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
226
- &nbsp;
227
- <a target="_blank" href="<?php echo get_permalink($pmpro_pages['invoice']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
228
- <?php } ?>
229
- <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_invoice].</small>
230
- </td>
231
- </tr>
232
- <tr>
233
- <th scope="row" valign="top">
234
- <label for="levels_page_id"><?php _e('Levels Page', 'pmpro');?>:</label>
235
- </th>
236
- <td>
237
- <?php
238
- wp_dropdown_pages(array("name"=>"levels_page_id", "show_option_none"=>"-- Choose One --", "selected"=>$pmpro_pages['levels']));
239
- ?>
240
- <?php if(!empty($pmpro_pages['levels'])) { ?>
241
- <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['levels']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
242
- &nbsp;
243
- <a target="_blank" href="<?php echo get_permalink($pmpro_pages['levels']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
244
- <?php } ?>
245
- <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_levels].</small>
246
- </td>
247
- </tr>
248
- </tbody>
249
- </table>
250
- <p class="submit">
251
- <input name="savesettings" type="submit" class="button button-primary" value="<?php _e('Save Settings', 'pmpro');?>" />
252
- </p>
253
- </form>
254
-
255
- <?php
256
- require_once(dirname(__FILE__) . "/admin_footer.php");
257
- ?>
 
 
 
1
+ <?php
2
+ //only admins can get this
3
+ if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_pagesettings")))
4
+ {
5
+ die(__("You do not have permissions to perform this action.", "pmpro"));
6
+ }
7
+
8
+ global $wpdb, $msg, $msgt;
9
+
10
+ //get/set settings
11
+ global $pmpro_pages;
12
+ if(!empty($_REQUEST['savesettings']))
13
+ {
14
+ //page ids
15
+ pmpro_setOption("account_page_id");
16
+ pmpro_setOption("billing_page_id");
17
+ pmpro_setOption("cancel_page_id");
18
+ pmpro_setOption("checkout_page_id");
19
+ pmpro_setOption("confirmation_page_id");
20
+ pmpro_setOption("invoice_page_id");
21
+ pmpro_setOption("levels_page_id");
22
+
23
+ //update the pages array
24
+ $pmpro_pages["account"] = pmpro_getOption("account_page_id");
25
+ $pmpro_pages["billing"] = pmpro_getOption("billing_page_id");
26
+ $pmpro_pages["cancel"] = pmpro_getOption("cancel_page_id");
27
+ $pmpro_pages["checkout"] = pmpro_getOption("checkout_page_id");
28
+ $pmpro_pages["confirmation"] = pmpro_getOption("confirmation_page_id");
29
+ $pmpro_pages["invoice"] = pmpro_getOption("invoice_page_id");
30
+ $pmpro_pages["levels"] = pmpro_getOption("levels_page_id");
31
+
32
+ //assume success
33
+ $msg = true;
34
+ $msgt = "Your page settings have been updated.";
35
+ }
36
+
37
+ //are we generating pages?
38
+ if(!empty($_REQUEST['createpages']))
39
+ {
40
+ global $pmpro_pages;
41
+
42
+ $pages_created = array();
43
+
44
+ //check the pages array
45
+ foreach($pmpro_pages as $pmpro_page_name => $pmpro_page_id)
46
+ {
47
+ if(!$pmpro_page_id)
48
+ {
49
+ switch ($pmpro_page_name) {
50
+ case 'account':
51
+ $pmpro_page_title = __( 'Membership Account', 'pmpro' );
52
+ break;
53
+ case 'billing':
54
+ $pmpro_page_title = __( 'Membership Billing', 'pmpro' );
55
+ break;
56
+ case 'cancel':
57
+ $pmpro_page_title = __( 'Membership Cancel', 'pmpro' );
58
+ break;
59
+ case 'checkout':
60
+ $pmpro_page_title = __( 'Membership Checkout', 'pmpro' );
61
+ break;
62
+ case 'confirmation':
63
+ $pmpro_page_title = __( 'Membership Confirmation', 'pmpro' );
64
+ break;
65
+ case 'invoice':
66
+ $pmpro_page_title = __( 'Membership Invoice', 'pmpro' );
67
+ break;
68
+ case 'levels':
69
+ $pmpro_page_title = __( 'Membership Levels', 'pmpro' );
70
+ break;
71
+
72
+ default:
73
+ $pmpro_page_title = sprintf( __( 'Membership %s', 'Page title template', 'pmpro' ), ucwords($pmpro_page_name) );
74
+ break;
75
+ }
76
+
77
+ //no id set. create an array to store the page info
78
+ $insert = array(
79
+ 'post_title' => $pmpro_page_title,
80
+ 'post_status' => 'publish',
81
+ 'post_type' => 'page',
82
+ 'post_content' => '[pmpro_' . $pmpro_page_name . ']',
83
+ 'comment_status' => 'closed',
84
+ 'ping_status' => 'closed'
85
+ );
86
+
87
+ //make non-account pages a subpage of account
88
+ if($pmpro_page_name != "account")
89
+ {
90
+ $insert['post_parent'] = $pmpro_pages['account'];
91
+ }
92
+
93
+ //create the page
94
+ $pmpro_pages[$pmpro_page_name] = wp_insert_post( $insert );
95
+
96
+ //add besecure post option to pages that need it
97
+ /* these pages are handling this themselves in the preheader
98
+ if(in_array($pmpro_page_name, array("billing", "checkout")))
99
+ update_post_meta($pmpro_pages[$pmpro_page_name], "besecure", 1);
100
+ */
101
+
102
+ //update the option too
103
+ pmpro_setOption($pmpro_page_name . "_page_id", $pmpro_pages[$pmpro_page_name]);
104
+ $pages_created[] = $pmpro_pages[$pmpro_page_name];
105
+ }
106
+ }
107
+
108
+ if(!empty($pages_created))
109
+ {
110
+ $msg = true;
111
+ $msgt = __("The following pages have been created for you", "pmpro") . ": " . implode(", ", $pages_created) . ".";
112
+ }
113
+ }
114
+
115
+ require_once(dirname(__FILE__) . "/admin_header.php");
116
+ ?>
117
+
118
+
119
+ <form action="" method="post" enctype="multipart/form-data">
120
+ <h2><?php _e('Pages', 'pmpro');?></h2>
121
+ <?php
122
+ global $pmpro_pages_ready;
123
+ if($pmpro_pages_ready)
124
+ {
125
+ ?>
126
+ <p><?php _e('Manage the WordPress pages assigned to each required Paid Memberships Pro page.', 'pmpro');?></p>
127
+ <?php
128
+ }
129
+ else
130
+ {
131
+ ?>
132
+ <p><?php _e('Assign the WordPress pages for each required Paid Memberships Pro page or', 'pmpro');?> <a href="?page=pmpro-pagesettings&createpages=1"><?php _e('click here to let us generate them for you', 'pmpro');?></a>.</p>
133
+ <?php
134
+ }
135
+ ?>
136
+ <table class="form-table">
137
+ <tbody>
138
+ <tr>
139
+ <th scope="row" valign="top">
140
+ <label for="account_page_id"><?php _e('Account Page', 'pmpro');?>:</label>
141
+ </th>
142
+ <td>
143
+ <?php
144
+ wp_dropdown_pages(array("name"=>"account_page_id", "show_option_none"=>"-- ".__( 'Choose One', 'pmpro' )." --", "selected"=>$pmpro_pages['account']));
145
+ ?>
146
+ <?php
147
+ wp_dropdown_pages(array("name"=>"account_page_id", "show_option_none"=>"-- ".__( 'Choose One', 'pmpro' )." --", "selected"=>$pmpro_pages['account']));
148
+ ?>
149
+ <?php if(!empty($pmpro_pages['account'])) { ?>
150
+ <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['account'];?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
151
+ &nbsp;
152
+ <a target="_blank" href="<?php echo get_permalink($pmpro_pages['account']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
153
+ <?php } ?>
154
+ <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_account].</small>
155
+ </td>
156
+ <tr>
157
+ <th scope="row" valign="top">
158
+ <label for="billing_page_id"><?php _e('Billing Information Page', 'pmpro');?>:</label>
159
+ </th>
160
+ <td>
161
+ <?php
162
+ wp_dropdown_pages(array("name"=>"billing_page_id", "show_option_none"=>"-- ".__( 'Choose One', 'pmpro' )." --", "selected"=>$pmpro_pages['billing']));
163
+ ?>
164
+ <?php if(!empty($pmpro_pages['billing'])) { ?>
165
+ <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['billing']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
166
+ &nbsp;
167
+ <a target="_blank" href="<?php echo get_permalink($pmpro_pages['billing']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
168
+ <?php } ?>
169
+ <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_billing].</small>
170
+ </td>
171
+ <tr>
172
+ <th scope="row" valign="top">
173
+ <label for="cancel_page_id"><?php _e('Cancel Page', 'pmpro');?>:</label>
174
+ </th>
175
+ <td>
176
+ <?php
177
+ wp_dropdown_pages(array("name"=>"cancel_page_id", "show_option_none"=>"-- ".__( 'Choose One', 'pmpro' )." --", "selected"=>$pmpro_pages['cancel']));
178
+ ?>
179
+ <?php if(!empty($pmpro_pages['cancel'])) { ?>
180
+ <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['cancel']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
181
+ &nbsp;
182
+ <a target="_blank" href="<?php echo get_permalink($pmpro_pages['cancel']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
183
+ <?php } ?>
184
+ <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_cancel].</small>
185
+ </td>
186
+ </tr>
187
+ <tr>
188
+ <th scope="row" valign="top">
189
+ <label for="checkout_page_id"><?php _e('Checkout Page', 'pmpro');?>:</label>
190
+ </th>
191
+ <td>
192
+ <?php
193
+ wp_dropdown_pages(array("name"=>"checkout_page_id", "show_option_none"=>"-- ".__( 'Choose One', 'pmpro' )." --", "selected"=>$pmpro_pages['checkout']));
194
+ ?>
195
+ <?php if(!empty($pmpro_pages['checkout'])) { ?>
196
+ <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['checkout']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
197
+ &nbsp;
198
+ <a target="_blank" href="<?php echo get_permalink($pmpro_pages['checkout']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
199
+ <?php } ?>
200
+ <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_checkout].</small>
201
+ </td>
202
+ </tr>
203
+ <tr>
204
+ <th scope="row" valign="top">
205
+ <label for="confirmation_page_id"><?php _e('Confirmation Page', 'pmpro');?>:</label>
206
+ </th>
207
+ <td>
208
+ <?php
209
+ wp_dropdown_pages(array("name"=>"confirmation_page_id", "show_option_none"=>"-- ".__( 'Choose One', 'pmpro' )." --", "selected"=>$pmpro_pages['confirmation']));
210
+ ?>
211
+ <?php if(!empty($pmpro_pages['confirmation'])) { ?>
212
+ <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['confirmation']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
213
+ &nbsp;
214
+ <a target="_blank" href="<?php echo get_permalink($pmpro_pages['confirmation']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
215
+ <?php } ?>
216
+ <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_confirmation].</small>
217
+ </td>
218
+ </tr>
219
+ <tr>
220
+ <th scope="row" valign="top">
221
+ <label for="invoice_page_id"><?php _e('Invoice Page', 'pmpro');?>:</label>
222
+ </th>
223
+ <td>
224
+ <?php
225
+ wp_dropdown_pages(array("name"=>"invoice_page_id", "show_option_none"=>"-- ".__( 'Choose One', 'pmpro' )." --", "selected"=>$pmpro_pages['invoice']));
226
+ ?>
227
+ <?php if(!empty($pmpro_pages['invoice'])) { ?>
228
+ <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['invoice']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
229
+ &nbsp;
230
+ <a target="_blank" href="<?php echo get_permalink($pmpro_pages['invoice']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
231
+ <?php } ?>
232
+ <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_invoice].</small>
233
+ </td>
234
+ </tr>
235
+ <tr>
236
+ <th scope="row" valign="top">
237
+ <label for="levels_page_id"><?php _e('Levels Page', 'pmpro');?>:</label>
238
+ </th>
239
+ <td>
240
+ <?php
241
+ wp_dropdown_pages(array("name"=>"levels_page_id", "show_option_none"=>"-- ".__( 'Choose One', 'pmpro' )." --", "selected"=>$pmpro_pages['levels']));
242
+ ?>
243
+ <?php if(!empty($pmpro_pages['levels'])) { ?>
244
+ <a target="_blank" href="post.php?post=<?php echo $pmpro_pages['levels']?>&action=edit" class="button button-secondary pmpro_page_edit"><?php _e('edit page', 'pmpro');?></a>
245
+ &nbsp;
246
+ <a target="_blank" href="<?php echo get_permalink($pmpro_pages['levels']);?>" class="button button-secondary pmpro_page_view"><?php _e('view page', 'pmpro');?></a>
247
+ <?php } ?>
248
+ <br /><small class="pmpro_lite"><?php _e('Include the shortcode', 'pmpro');?> [pmpro_levels].</small>
249
+ </td>
250
+ </tr>
251
+ </tbody>
252
+ </table>
253
+ <p class="submit">
254
+ <input name="savesettings" type="submit" class="button button-primary" value="<?php _e('Save Settings', 'pmpro');?>" />
255
+ </p>
256
+ </form>
257
+
258
+ <?php
259
+ require_once(dirname(__FILE__) . "/admin_footer.php");
260
+ ?>
adminpages/paymentsettings.php CHANGED
@@ -1,244 +1,244 @@
1
- <?php
2
- //only admins can get this
3
- if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_paymentsettings")))
4
- {
5
- die(__("You do not have permissions to perform this action.", "pmpro"));
6
- }
7
-
8
- global $wpdb, $pmpro_currency_symbol, $msg, $msgt;
9
-
10
- /*
11
- Since 2.0, we let each gateway define what options they have in the class files
12
- */
13
- //define options
14
- $payment_options = array_unique(apply_filters("pmpro_payment_options", array('gateway')));
15
-
16
- //get/set settings
17
- if(!empty($_REQUEST['savesettings']))
18
- {
19
- /*
20
- Save any value that might have been passed in
21
- */
22
- foreach($payment_options as $option)
23
- pmpro_setOption($option);
24
-
25
- /*
26
- Some special case options still worked out here
27
- */
28
- //credit cards
29
- $pmpro_accepted_credit_cards = array();
30
- if(!empty($_REQUEST['creditcards_visa']))
31
- $pmpro_accepted_credit_cards[] = "Visa";
32
- if(!empty($_REQUEST['creditcards_mastercard']))
33
- $pmpro_accepted_credit_cards[] = "Mastercard";
34
- if(!empty($_REQUEST['creditcards_amex']))
35
- $pmpro_accepted_credit_cards[] = "American Express";
36
- if(!empty($_REQUEST['creditcards_discover']))
37
- $pmpro_accepted_credit_cards[] = "Discover";
38
- if(!empty($_REQUEST['creditcards_dinersclub']))
39
- $pmpro_accepted_credit_cards[] = "Diners Club";
40
- if(!empty($_REQUEST['creditcards_enroute']))
41
- $pmpro_accepted_credit_cards[] = "EnRoute";
42
- if(!empty($_REQUEST['creditcards_jcb']))
43
- $pmpro_accepted_credit_cards[] = "JCB";
44
-
45
- pmpro_setOption("accepted_credit_cards", implode(",", $pmpro_accepted_credit_cards));
46
-
47
- //assume success
48
- $msg = true;
49
- $msgt = __("Your payment settings have been updated.", "pmpro");
50
- }
51
-
52
- /*
53
- Extract values for use later
54
- */
55
- $payment_option_values = array();
56
- foreach($payment_options as $option)
57
- $payment_option_values[$option] = pmpro_getOption($option);
58
- extract($payment_option_values);
59
-
60
- /*
61
- Some special cases that get worked out here.
62
- */
63
- //make sure the tax rate is not > 1
64
- $tax_state = pmpro_getOption("tax_state");
65
- $tax_rate = pmpro_getOption("tax_rate");
66
- if((double)$tax_rate > 1)
67
- {
68
- //assume the entered X%
69
- $tax_rate = $tax_rate / 100;
70
- pmpro_setOption("tax_rate", $tax_rate);
71
- }
72
-
73
- //accepted credit cards
74
- $pmpro_accepted_credit_cards = $payment_option_values['accepted_credit_cards']; //this var has the pmpro_ prefix
75
-
76
- //default settings
77
- if(empty($gateway_environment))
78
- {
79
- $gateway_environment = "sandbox";
80
- pmpro_setOption("gateway_environment", $gateway_environment);
81
- }
82
- if(empty($pmpro_accepted_credit_cards))
83
- {
84
- $pmpro_accepted_credit_cards = "Visa,Mastercard,American Express,Discover";
85
- pmpro_setOption("accepted_credit_cards", $pmpro_accepted_credit_cards);
86
- }
87
- $pmpro_accepted_credit_cards = explode(",", $pmpro_accepted_credit_cards);
88
-
89
- require_once(dirname(__FILE__) . "/admin_header.php");
90
- ?>
91
-
92
- <form action="" method="post" enctype="multipart/form-data">
93
- <h2><?php _e('Payment Gateway', 'pmpro');?> &amp; <?php _e('SSL Settings', 'pmpro');?></h2>
94
-
95
- <p><?php _e('Learn more about <a title="Paid Memberships Pro - SSL Settings" target="_blank" href="http://www.paidmembershipspro.com/support/initial-plugin-setup/ssl/">SSL</a> or <a title="Paid Memberships Pro - Payment Gateway Settings" target="_blank" href="http://www.paidmembershipspro.com/support/initial-plugin-setup/payment-gateway/">Payment Gateway Settings</a>.', 'pmpro'); ?></p>
96
-
97
- <table class="form-table">
98
- <tbody>
99
- <tr class="pmpro_settings_divider">
100
- <td colspan="2">
101
- Choose a Gateway
102
- </td>
103
- </tr>
104
- <tr>
105
- <th scope="row" valign="top">
106
- <label for="gateway"><?php _e('Payment Gateway', 'pmpro');?>:</label>
107
- </th>
108
- <td>
109
- <select id="gateway" name="gateway" onchange="pmpro_changeGateway(jQuery(this).val());">
110
- <?php
111
- $pmpro_gateways = pmpro_gateways();
112
- foreach($pmpro_gateways as $pmpro_gateway_name => $pmpro_gateway_label)
113
- {
114
- ?>
115
- <option value="<?php echo esc_attr($pmpro_gateway_name);?>" <?php selected($gateway, $pmpro_gateway_name);?>><?php echo $pmpro_gateway_label;?></option>
116
- <?php
117
- }
118
- ?>
119
- </select>
120
- </td>
121
- </tr>
122
- <tr>
123
- <th scope="row" valign="top">
124
- <label for="gateway_environment"><?php _e('Gateway Environment', 'pmpro');?>:</label>
125
- </th>
126
- <td>
127
- <select name="gateway_environment">
128
- <option value="sandbox" <?php selected( $gateway_environment, "sandbox" ); ?>><?php _e('Sandbox/Testing', 'pmpro');?></option>
129
- <option value="live" <?php selected( $gateway_environment, "live" ); ?>><?php _e('Live/Production', 'pmpro');?></option>
130
- </select>
131
- <script>
132
- function pmpro_changeGateway(gateway)
133
- {
134
- //hide all gateway options
135
- jQuery('tr.gateway').hide();
136
- jQuery('tr.gateway_'+gateway).show();
137
- }
138
- pmpro_changeGateway(jQuery('#gateway').val());
139
- </script>
140
- </td>
141
- </tr>
142
-
143
- <?php /* Gateway Specific Settings */ ?>
144
- <?php do_action('pmpro_payment_option_fields', $payment_option_values, $gateway); ?>
145
-
146
- <tr class="pmpro_settings_divider">
147
- <td colspan="2">
148
- Currency and Tax Settings
149
- </td>
150
- </tr>
151
- <tr class="gateway gateway_ <?php echo esc_attr(pmpro_getClassesForPaymentSettingsField("currency"));?>" <?php if(!empty($gateway) && $gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard" && $gateway != "braintree" && $gateway != "twocheckout" && $gateway != "cybersource" && $gateway != "payflowpro" && $gateway != "stripe" && $gateway != "authorizenet") { ?>style="display: none;"<?php } ?>>
152
- <th scope="row" valign="top">
153
- <label for="currency"><?php _e('Currency', 'pmpro');?>:</label>
154
- </th>
155
- <td>
156
- <select name="currency">
157
- <?php
158
- global $pmpro_currencies;
159
- foreach($pmpro_currencies as $ccode => $cdescription)
160
- {
161
- if(is_array($cdescription))
162
- $cdescription = $cdescription['name'];
163
- ?>
164
- <option value="<?php echo $ccode?>" <?php if($currency == $ccode) { ?>selected="selected"<?php } ?>><?php echo $cdescription?></option>
165
- <?php
166
- }
167
- ?>
168
- </select>
169
- <small><?php _e( 'Not all currencies will be supported by every gateway. Please check with your gateway.', 'pmpro' ); ?></small>
170
- </td>
171
- </tr>
172
- <tr class="gateway gateway_ <?php echo esc_attr(pmpro_getClassesForPaymentSettingsField("accepted_credit_cards"));?>" <?php if(!empty($gateway) && $gateway != "authorizenet" && $gateway != "paypal" && $gateway != "stripe" && $gateway != "payflowpro" && $gateway != "braintree" && $gateway != "twocheckout" && $gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
173
- <th scope="row" valign="top">
174
- <label for="creditcards"><?php _e('Accepted Credit Card Types', 'pmpro');?></label>
175
- </th>
176
- <td>
177
- <input type="checkbox" id="creditcards_visa" name="creditcards_visa" value="1" <?php if(in_array("Visa", $pmpro_accepted_credit_cards)) { ?>checked="checked"<?php } ?> /> <label for="creditcards_visa">Visa</label><br />
178
- <input type="checkbox" id="creditcards_mastercard" name="creditcards_mastercard" value="1" <?php if(in_array("Mastercard", $pmpro_accepted_credit_cards)) { ?>checked="checked"<?php } ?> /> <label for="creditcards_mastercard">Mastercard</label><br />
179
- <input type="checkbox" id="creditcards_amex" name="creditcards_amex" value="1" <?php if(in_array("American Express", $pmpro_accepted_credit_cards)) { ?>checked="checked"<?php } ?> /> <label for="creditcards_amex">American Express</label><br />
180
- <input type="checkbox" id="creditcards_discover" name="creditcards_discover" value="1" <?php if(in_array("Discover", $pmpro_accepted_credit_cards)) { ?>checked="checked"<?php } ?> /> <label for="creditcards_discover">Discover</label><br />
181
- <input type="checkbox" id="creditcards_dinersclub" name="creditcards_dinersclub" value="1" <?php if(in_array("Diners Club", $pmpro_accepted_credit_cards)) {?>checked="checked"<?php } ?> /> <label for="creditcards_dinersclub">Diner's Club</label><br />
182
- <input type="checkbox" id="creditcards_enroute" name="creditcards_enroute" value="1" <?php if(in_array("EnRoute", $pmpro_accepted_credit_cards)) {?>checked="checked"<?php } ?> /> <label for="creditcards_enroute">EnRoute</label><br />
183
- <input type="checkbox" id="creditcards_jcb" name="creditcards_jcb" value="1" <?php if(in_array("JCB", $pmpro_accepted_credit_cards)) {?>checked="checked"<?php } ?> /> <label for="creditcards_jcb">JCB</label><br />
184
- </td>
185
- </tr>
186
- <tr class="gateway gateway_ <?php echo esc_attr(pmpro_getClassesForPaymentSettingsField("tax_rate"));?>" <?php if(!empty($gateway) && $gateway != "stripe" && $gateway != "authorizenet" && $gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "check" && $gateway != "paypalstandard" && $gateway != "payflowpro" && $gateway != "braintree" && $gateway != "twocheckout" && $gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
187
- <th scope="row" valign="top">
188
- <label for="tax"><?php _e('Sales Tax', 'pmpro');?> <small>(<?php _e('optional', 'pmpro');?>)</small></label>
189
- </th>
190
- <td>
191
- <?php _e('Tax State', 'pmpro');?>:
192
- <input type="text" id="tax_state" name="tax_state" size="4" value="<?php echo esc_attr($tax_state)?>" /> <small>(<?php _e('abbreviation, e.g. "PA"', 'pmpro');?>)</small>
193
- &nbsp; Tax Rate:
194
- <input type="text" id="tax_rate" name="tax_rate" size="10" value="<?php echo esc_attr($tax_rate)?>" /> <small>(<?php _e('decimal, e.g. "0.06"', 'pmpro');?>)</small>
195
- <p><small><?php _e('US only. If values are given, tax will be applied for any members ordering from the selected state.<br />For non-US or more complex tax rules, use the <a target="_blank" href="http://www.paidmembershipspro.com/2013/10/non-us-taxes-paid-memberships-pro/">pmpro_tax filter</a>.', 'pmpro');?></small></p>
196
- </td>
197
- </tr>
198
-
199
- <tr class="pmpro_settings_divider">
200
- <td colspan="2">
201
- SSL Settings
202
- </td>
203
- </tr>
204
- <tr class="gateway gateway_ <?php echo esc_attr(pmpro_getClassesForPaymentSettingsField("use_ssl"));?>">
205
- <th scope="row" valign="top">
206
- <label for="use_ssl"><?php _e('Force SSL', 'pmpro');?>:</label>
207
- </th>
208
- <td>
209
- <select id="use_ssl" name="use_ssl">
210
- <option value="0" <?php if(empty($use_ssl)) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
211
- <option value="1" <?php if(!empty($use_ssl) && $use_ssl == 1) { ?>selected="selected"<?php } ?>><?php _e('Yes', 'pmpro');?></option>
212
- <option value="2" <?php if(!empty($use_ssl) && $use_ssl == 2) { ?>selected="selected"<?php } ?>><?php _e('Yes (with JavaScript redirects)', 'pmpro');?></option>
213
- </select>
214
- <small>Recommended: Yes. Try the JavaScript redirects setting if you are having issues with infinite redirect loops.</small>
215
- </td>
216
- </tr>
217
- <tr>
218
- <th scope="row" valign="top">
219
- <label for="sslseal"><?php _e('SSL Seal Code', 'pmpro');?>:</label>
220
- </th>
221
- <td>
222
- <textarea id="sslseal" name="sslseal" rows="3" cols="80"><?php echo stripslashes(esc_textarea($sslseal))?></textarea>
223
- <br /><small>Your <strong><a target="_blank" href="http://www.paidmembershipspro.com/documentation/initial-plugin-setup/ssl/">SSL Certificate</a></strong> must be installed by your web host. Your <strong>SSL Seal</strong> will be a short HTML or JavaScript snippet that can be pasted here.</small>
224
- </td>
225
- </tr>
226
- <tr>
227
- <th scope="row" valign="top">
228
- <label for="nuclear_HTTPS"><?php _e('Extra HTTPS URL Filter', 'pmpro');?>:</label>
229
- </th>
230
- <td>
231
- <input type="checkbox" id="nuclear_HTTPS" name="nuclear_HTTPS" value="1" <?php if(!empty($nuclear_HTTPS)) { ?>checked="checked"<?php } ?> /> <label for="nuclear_HTTPS"><?php _e('Pass all generated HTML through a URL filter to add HTTPS to URLs used on secure pages. Check this if you are using SSL and have warnings on your checkout pages.', 'pmpro');?></label>
232
- </td>
233
- </tr>
234
-
235
- </tbody>
236
- </table>
237
- <p class="submit">
238
- <input name="savesettings" type="submit" class="button-primary" value="<?php _e('Save Settings', 'pmpro');?>" />
239
- </p>
240
- </form>
241
-
242
- <?php
243
- require_once(dirname(__FILE__) . "/admin_footer.php");
244
- ?>
1
+ <?php
2
+ //only admins can get this
3
+ if(!function_exists("current_user_can") || (!current_user_can("manage_options") && !current_user_can("pmpro_paymentsettings")))
4
+ {
5
+ die(__("You do not have permissions to perform this action.", "pmpro"));
6
+ }
7
+
8
+ global $wpdb, $pmpro_currency_symbol, $msg, $msgt;
9
+
10
+ /*
11
+ Since 2.0, we let each gateway define what options they have in the class files
12
+ */
13
+ //define options
14
+ $payment_options = array_unique(apply_filters("pmpro_payment_options", array('gateway')));
15
+
16
+ //get/set settings
17
+ if(!empty($_REQUEST['savesettings']))
18
+ {
19
+ /*
20
+ Save any value that might have been passed in
21
+ */
22
+ foreach($payment_options as $option)
23
+ pmpro_setOption($option);
24
+
25
+ /*
26
+ Some special case options still worked out here
27
+ */
28
+ //credit cards
29
+ $pmpro_accepted_credit_cards = array();
30
+ if(!empty($_REQUEST['creditcards_visa']))
31
+ $pmpro_accepted_credit_cards[] = "Visa";
32
+ if(!empty($_REQUEST['creditcards_mastercard']))
33
+ $pmpro_accepted_credit_cards[] = "Mastercard";
34
+ if(!empty($_REQUEST['creditcards_amex']))
35
+ $pmpro_accepted_credit_cards[] = "American Express";
36
+ if(!empty($_REQUEST['creditcards_discover']))
37
+ $pmpro_accepted_credit_cards[] = "Discover";
38
+ if(!empty($_REQUEST['creditcards_dinersclub']))
39
+ $pmpro_accepted_credit_cards[] = "Diners Club";
40
+ if(!empty($_REQUEST['creditcards_enroute']))
41
+ $pmpro_accepted_credit_cards[] = "EnRoute";
42
+ if(!empty($_REQUEST['creditcards_jcb']))
43
+ $pmpro_accepted_credit_cards[] = "JCB";
44
+
45
+ pmpro_setOption("accepted_credit_cards", implode(",", $pmpro_accepted_credit_cards));
46
+
47
+ //assume success
48
+ $msg = true;
49
+ $msgt = __("Your payment settings have been updated.", "pmpro");
50
+ }
51
+
52
+ /*
53
+ Extract values for use later
54
+ */
55
+ $payment_option_values = array();
56
+ foreach($payment_options as $option)
57
+ $payment_option_values[$option] = pmpro_getOption($option);
58
+ extract($payment_option_values);
59
+
60
+ /*
61
+ Some special cases that get worked out here.
62
+ */
63
+ //make sure the tax rate is not > 1
64
+ $tax_state = pmpro_getOption("tax_state");
65
+ $tax_rate = pmpro_getOption("tax_rate");
66
+ if((double)$tax_rate > 1)
67
+ {
68
+ //assume the entered X%
69
+ $tax_rate = $tax_rate / 100;
70
+ pmpro_setOption("tax_rate", $tax_rate);
71
+ }
72
+
73
+ //accepted credit cards
74
+ $pmpro_accepted_credit_cards = $payment_option_values['accepted_credit_cards']; //this var has the pmpro_ prefix
75
+
76
+ //default settings
77
+ if(empty($gateway_environment))
78
+ {
79
+ $gateway_environment = "sandbox";
80
+ pmpro_setOption("gateway_environment", $gateway_environment);
81
+ }
82
+ if(empty($pmpro_accepted_credit_cards))
83
+ {
84
+ $pmpro_accepted_credit_cards = "Visa,Mastercard,American Express,Discover";
85
+ pmpro_setOption("accepted_credit_cards", $pmpro_accepted_credit_cards);
86
+ }
87
+ $pmpro_accepted_credit_cards = explode(",", $pmpro_accepted_credit_cards);
88
+
89
+ require_once(dirname(__FILE__) . "/admin_header.php");
90
+ ?>
91
+
92
+ <form action="" method="post" enctype="multipart/form-data">
93
+ <h2><?php _e('Payment Gateway', 'pmpro');?> &amp; <?php _e('SSL Settings', 'pmpro');?></h2>
94
+
95
+ <p><?php _e('Learn more about <a title="Paid Memberships Pro - SSL Settings" target="_blank" href="http://www.paidmembershipspro.com/support/initial-plugin-setup/ssl/">SSL</a> or <a title="Paid Memberships Pro - Payment Gateway Settings" target="_blank" href="http://www.paidmembershipspro.com/support/initial-plugin-setup/payment-gateway/">Payment Gateway Settings</a>.', 'pmpro'); ?></p>
96
+
97
+ <table class="form-table">
98
+ <tbody>
99
+ <tr class="pmpro_settings_divider">
100
+ <td colspan="2">
101
+ Choose a Gateway
102
+ </td>
103
+ </tr>
104
+ <tr>
105
+ <th scope="row" valign="top">
106
+ <label for="gateway"><?php _e('Payment Gateway', 'pmpro');?>:</label>
107
+ </th>
108
+ <td>
109
+ <select id="gateway" name="gateway" onchange="pmpro_changeGateway(jQuery(this).val());">
110
+ <?php
111
+ $pmpro_gateways = pmpro_gateways();
112
+ foreach($pmpro_gateways as $pmpro_gateway_name => $pmpro_gateway_label)
113
+ {
114
+ ?>
115
+ <option value="<?php echo esc_attr($pmpro_gateway_name);?>" <?php selected($gateway, $pmpro_gateway_name);?>><?php echo $pmpro_gateway_label;?></option>
116
+ <?php
117
+ }
118
+ ?>
119
+ </select>
120
+ </td>
121
+ </tr>
122
+ <tr>
123
+ <th scope="row" valign="top">
124
+ <label for="gateway_environment"><?php _e('Gateway Environment', 'pmpro');?>:</label>
125
+ </th>
126
+ <td>
127
+ <select name="gateway_environment">
128
+ <option value="sandbox" <?php selected( $gateway_environment, "sandbox" ); ?>><?php _e('Sandbox/Testing', 'pmpro');?></option>
129
+ <option value="live" <?php selected( $gateway_environment, "live" ); ?>><?php _e('Live/Production', 'pmpro');?></option>
130
+ </select>
131
+ <script>
132
+ function pmpro_changeGateway(gateway)
133
+ {
134
+ //hide all gateway options
135
+ jQuery('tr.gateway').hide();
136
+ jQuery('tr.gateway_'+gateway).show();
137
+ }
138
+ pmpro_changeGateway(jQuery('#gateway').val());
139
+ </script>
140
+ </td>
141
+ </tr>
142
+
143
+ <?php /* Gateway Specific Settings */ ?>
144
+ <?php do_action('pmpro_payment_option_fields', $payment_option_values, $gateway); ?>
145
+
146
+ <tr class="pmpro_settings_divider">
147
+ <td colspan="2">
148
+ Currency and Tax Settings
149
+ </td>
150
+ </tr>
151
+ <tr class="gateway gateway_ <?php echo esc_attr(pmpro_getClassesForPaymentSettingsField("currency"));?>" <?php if(!empty($gateway) && $gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard" && $gateway != "braintree" && $gateway != "twocheckout" && $gateway != "cybersource" && $gateway != "payflowpro" && $gateway != "stripe" && $gateway != "authorizenet" && $gateway != "gourl") { ?>style="display: none;"<?php } ?>>
152
+ <th scope="row" valign="top">
153
+ <label for="currency"><?php _e('Currency', 'pmpro');?>:</label>
154
+ </th>
155
+ <td>
156
+ <select name="currency">
157
+ <?php
158
+ global $pmpro_currencies;
159
+ foreach($pmpro_currencies as $ccode => $cdescription)
160
+ {
161
+ if(is_array($cdescription))
162
+ $cdescription = $cdescription['name'];
163
+ ?>
164
+ <option value="<?php echo $ccode?>" <?php if($currency == $ccode) { ?>selected="selected"<?php } ?>><?php echo $cdescription?></option>
165
+ <?php
166
+ }
167
+ ?>
168
+ </select>
169
+ <small><?php _e( 'Not all currencies will be supported by every gateway. Please check with your gateway.', 'pmpro' ); ?></small>
170
+ </td>
171
+ </tr>
172
+ <tr class="gateway gateway_ <?php echo esc_attr(pmpro_getClassesForPaymentSettingsField("accepted_credit_cards"));?>" <?php if(!empty($gateway) && $gateway != "authorizenet" && $gateway != "paypal" && $gateway != "stripe" && $gateway != "payflowpro" && $gateway != "braintree" && $gateway != "twocheckout" && $gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
173
+ <th scope="row" valign="top">
174
+ <label for="creditcards"><?php _e('Accepted Credit Card Types', 'pmpro');?></label>
175
+ </th>
176
+ <td>
177
+ <input type="checkbox" id="creditcards_visa" name="creditcards_visa" value="1" <?php if(in_array("Visa", $pmpro_accepted_credit_cards)) { ?>checked="checked"<?php } ?> /> <label for="creditcards_visa">Visa</label><br />
178
+ <input type="checkbox" id="creditcards_mastercard" name="creditcards_mastercard" value="1" <?php if(in_array("Mastercard", $pmpro_accepted_credit_cards)) { ?>checked="checked"<?php } ?> /> <label for="creditcards_mastercard">Mastercard</label><br />
179
+ <input type="checkbox" id="creditcards_amex" name="creditcards_amex" value="1" <?php if(in_array("American Express", $pmpro_accepted_credit_cards)) { ?>checked="checked"<?php } ?> /> <label for="creditcards_amex">American Express</label><br />
180
+ <input type="checkbox" id="creditcards_discover" name="creditcards_discover" value="1" <?php if(in_array("Discover", $pmpro_accepted_credit_cards)) { ?>checked="checked"<?php } ?> /> <label for="creditcards_discover">Discover</label><br />
181
+ <input type="checkbox" id="creditcards_dinersclub" name="creditcards_dinersclub" value="1" <?php if(in_array("Diners Club", $pmpro_accepted_credit_cards)) {?>checked="checked"<?php } ?> /> <label for="creditcards_dinersclub">Diner's Club</label><br />
182
+ <input type="checkbox" id="creditcards_enroute" name="creditcards_enroute" value="1" <?php if(in_array("EnRoute", $pmpro_accepted_credit_cards)) {?>checked="checked"<?php } ?> /> <label for="creditcards_enroute">EnRoute</label><br />
183
+ <input type="checkbox" id="creditcards_jcb" name="creditcards_jcb" value="1" <?php if(in_array("JCB", $pmpro_accepted_credit_cards)) {?>checked="checked"<?php } ?> /> <label for="creditcards_jcb">JCB</label><br />
184
+ </td>
185
+ </tr>
186
+ <tr class="gateway gateway_ <?php echo esc_attr(pmpro_getClassesForPaymentSettingsField("tax_rate"));?>" <?php if(!empty($gateway) && $gateway != "stripe" && $gateway != "authorizenet" && $gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "check" && $gateway != "paypalstandard" && $gateway != "payflowpro" && $gateway != "braintree" && $gateway != "twocheckout" && $gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
187
+ <th scope="row" valign="top">
188
+ <label for="tax"><?php _e('Sales Tax', 'pmpro');?> <small>(<?php _e('optional', 'pmpro');?>)</small></label>
189
+ </th>
190
+ <td>
191
+ <?php _e('Tax State', 'pmpro');?>:
192
+ <input type="text" id="tax_state" name="tax_state" size="4" value="<?php echo esc_attr($tax_state)?>" /> <small>(<?php _e('abbreviation, e.g. "PA"', 'pmpro');?>)</small>
193
+ &nbsp; Tax Rate:
194
+ <input type="text" id="tax_rate" name="tax_rate" size="10" value="<?php echo esc_attr($tax_rate)?>" /> <small>(<?php _e('decimal, e.g. "0.06"', 'pmpro');?>)</small>
195
+ <p><small><?php _e('US only. If values are given, tax will be applied for any members ordering from the selected state.<br />For non-US or more complex tax rules, use the <a target="_blank" href="http://www.paidmembershipspro.com/2013/10/non-us-taxes-paid-memberships-pro/">pmpro_tax filter</a>.', 'pmpro');?></small></p>
196
+ </td>
197
+ </tr>
198
+
199
+ <tr class="pmpro_settings_divider">
200
+ <td colspan="2">
201
+ SSL Settings
202
+ </td>
203
+ </tr>
204
+ <tr class="gateway gateway_ <?php echo esc_attr(pmpro_getClassesForPaymentSettingsField("use_ssl"));?>">
205
+ <th scope="row" valign="top">
206
+ <label for="use_ssl"><?php _e('Force SSL', 'pmpro');?>:</label>
207
+ </th>
208
+ <td>
209
+ <select id="use_ssl" name="use_ssl">
210
+ <option value="0" <?php if(empty($use_ssl)) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
211
+ <option value="1" <?php if(!empty($use_ssl) && $use_ssl == 1) { ?>selected="selected"<?php } ?>><?php _e('Yes', 'pmpro');?></option>
212
+ <option value="2" <?php if(!empty($use_ssl) && $use_ssl == 2) { ?>selected="selected"<?php } ?>><?php _e('Yes (with JavaScript redirects)', 'pmpro');?></option>
213
+ </select>
214
+ <small>Recommended: Yes. Try the JavaScript redirects setting if you are having issues with infinite redirect loops.</small>
215
+ </td>
216
+ </tr>
217
+ <tr>
218
+ <th scope="row" valign="top">
219
+ <label for="sslseal"><?php _e('SSL Seal Code', 'pmpro');?>:</label>
220
+ </th>
221
+ <td>
222
+ <textarea id="sslseal" name="sslseal" rows="3" cols="80"><?php echo stripslashes(esc_textarea($sslseal))?></textarea>
223
+ <br /><small>Your <strong><a target="_blank" href="http://www.paidmembershipspro.com/documentation/initial-plugin-setup/ssl/">SSL Certificate</a></strong> must be installed by your web host. Your <strong>SSL Seal</strong> will be a short HTML or JavaScript snippet that can be pasted here.</small>
224
+ </td>
225
+ </tr>
226
+ <tr>
227
+ <th scope="row" valign="top">
228
+ <label for="nuclear_HTTPS"><?php _e('Extra HTTPS URL Filter', 'pmpro');?>:</label>
229
+ </th>
230
+ <td>
231
+ <input type="checkbox" id="nuclear_HTTPS" name="nuclear_HTTPS" value="1" <?php if(!empty($nuclear_HTTPS)) { ?>checked="checked"<?php } ?> /> <label for="nuclear_HTTPS"><?php _e('Pass all generated HTML through a URL filter to add HTTPS to URLs used on secure pages. Check this if you are using SSL and have warnings on your checkout pages.', 'pmpro');?></label>
232
+ </td>
233
+ </tr>
234
+
235
+ </tbody>
236
+ </table>
237
+ <p class="submit">
238
+ <input name="savesettings" type="submit" class="button-primary" value="<?php _e('Save Settings', 'pmpro');?>" />
239
+ </p>
240
+ </form>
241
+
242
+ <?php
243
+ require_once(dirname(__FILE__) . "/admin_footer.php");
244
+ ?>
adminpages/reports.php CHANGED
@@ -1,62 +1,62 @@
1
- <?php
2
- global $pmpro_reports;
3
-
4
- require_once(dirname(__FILE__) . "/admin_header.php");
5
-
6
- //default view, report widgets
7
- if(empty($_REQUEST['report']))
8
- {
9
- //wrapper
10
- ?>
11
- <div id="dashboard-widgets-wrap">
12
- <div id="dashboard-widgets" class="metabox-holder pmpro_reports-holder columns-2">
13
- <div id="postbox-container-1" class="postbox-container">
14
- <div id="normal-sortables" class="meta-box-sortables ui-sortable">
15
- <?php
16
-
17
- //report widgets
18
- $count = 0;
19
- $nreports = count($pmpro_reports);
20
- $split = false;
21
- foreach($pmpro_reports as $report => $title)
22
- {
23
- //make sure title is translated (since these are set before translations happen)
24
- $title = __($title, "pmpro");
25
-
26
- //put half of the report widgets in postbox-container-2
27
- if(!$split && $count++ > $nreports/2)
28
- {
29
- $split = true;
30
- ?>
31
- </div></div><div id="postbox-container-2" class="postbox-container"><div id="side-sortables" class="meta-box-sortables ui-sortable">
32
- <?php
33
- }
34
- ?>
35
- <div id="pmpro_report_<?php echo $report; ?>" class="postbox pmpro_clickable" onclick="location.href='<?php echo admin_url("admin.php?page=pmpro-reports&report=" . $report);?>';">
36
- <h3 class="hndle"><span><?php echo $title; ?></span></h3>
37
- <div class="inside">
38
- <?php call_user_func("pmpro_report_" . $report . "_widget"); ?>
39
- <div style="margin-top:10px;border-top: 1px solid #ddd; padding-top: 10px; text-align:center;">
40
- <a class="button button-primary" href="<?php echo admin_url("admin.php?page=pmpro-reports&report=" . $report);?>"><?php _e('Details', 'pmpro');?></a>
41
- </div>
42
- </div>
43
- </div>
44
- <?php
45
- }
46
-
47
- //end wrapper
48
- ?>
49
- </div>
50
- </div>
51
- </div>
52
- <?php
53
- }
54
- else
55
- {
56
- //view a single report
57
- $report = $_REQUEST['report'];
58
- call_user_func("pmpro_report_" . $report . "_page");
59
- }
60
-
61
- require_once(dirname(__FILE__) . "/admin_footer.php");
62
  ?>
1
+ <?php
2
+ global $pmpro_reports;
3
+
4
+ require_once(dirname(__FILE__) . "/admin_header.php");
5
+
6
+ //default view, report widgets
7
+ if(empty($_REQUEST['report']))
8
+ {
9
+ //wrapper
10
+ ?>
11
+ <div id="dashboard-widgets-wrap">
12
+ <div id="dashboard-widgets" class="metabox-holder pmpro_reports-holder columns-2">
13
+ <div id="postbox-container-1" class="postbox-container">
14
+ <div id="normal-sortables" class="meta-box-sortables ui-sortable">
15
+ <?php
16
+
17
+ //report widgets
18
+ $count = 0;
19
+ $nreports = count($pmpro_reports);
20
+ $split = false;
21
+ foreach($pmpro_reports as $report => $title)
22
+ {
23
+ //make sure title is translated (since these are set before translations happen)
24
+ $title = __($title, "pmpro");
25
+
26
+ //put half of the report widgets in postbox-container-2
27
+ if(!$split && $count++ > $nreports/2)
28
+ {
29
+ $split = true;
30
+ ?>
31
+ </div></div><div id="postbox-container-2" class="postbox-container"><div id="side-sortables" class="meta-box-sortables ui-sortable">
32
+ <?php
33
+ }
34
+ ?>
35
+ <div id="pmpro_report_<?php echo $report; ?>" class="postbox pmpro_clickable" onclick="location.href='<?php echo admin_url("admin.php?page=pmpro-reports&report=" . $report);?>';">
36
+ <h3 class="hndle"><span><?php echo $title; ?></span></h3>
37
+ <div class="inside">
38
+ <?php call_user_func("pmpro_report_" . $report . "_widget"); ?>
39
+ <div style="margin-top:10px;border-top: 1px solid #ddd; padding-top: 10px; text-align:center;">
40
+ <a class="button button-primary" href="<?php echo admin_url("admin.php?page=pmpro-reports&report=" . $report);?>"><?php _e('Details', 'pmpro');?></a>
41
+ </div>
42
+ </div>
43
+ </div>
44
+ <?php
45
+ }
46
+
47
+ //end wrapper
48
+ ?>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ <?php
53
+ }
54
+ else
55
+ {
56
+ //view a single report
57
+ $report = $_REQUEST['report'];
58
+ call_user_func("pmpro_report_" . $report . "_page");
59
+ }
60
+
61
+ require_once(dirname(__FILE__) . "/admin_footer.php");
62
  ?>
adminpages/reports/login.php CHANGED
@@ -1,420 +1,420 @@
1
- <?php
2
- /*
3
- PMPro Report
4
- Title: Logins
5
- Slug: login
6
-
7
- For each report, add a line like:
8
- global $pmpro_reports;
9
- $pmpro_reports['slug'] = 'Title';
10
-
11
- For each report, also write two functions:
12
- * pmpro_report_{slug}_widget() to show up on the report homepage.
13
- * pmpro_report_{slug}_page() to show up when users click on the report page widget.
14
- */
15
- global $pmpro_reports;
16
- $pmpro_reports['login'] = __('Visits, Views, and Logins', 'pmpro');
17
-
18
- function pmpro_report_login_widget()
19
- {
20
- global $wpdb;
21
- $now = current_time('timestamp');
22
- $visits = get_option("pmpro_visits", array("today"=>0, "thisday"=>date("Y-m-d", $now), "alltime"=>0, "month"=>0, "thismonth"=>date("n", $now)));
23
- $views = get_option("pmpro_views", array("today"=>0, "thisday"=>date("Y-m-d", $now), "alltime"=>0, "month"=>0, "thismonth"=>date("n", $now)));
24
- $logins = get_option("pmpro_logins", array("today"=>0, "thisday"=>date("Y-m-d", $now), "alltime"=>0, "month"=>0, "thismonth"=>date("n", $now)));
25
- ?>
26
- <div style="width: 33%; float: left;">
27
- <p><?php _e('Visits Today', 'pmpro')?>: <?php echo $visits['today'];?></p>
28
- <p><?php _e('Visits This Month', 'pmpro')?>: <?php echo $visits['month'];?></p>
29
- <p><?php _e('Visits All Time', 'pmpro')?>: <?php echo $visits['alltime'];?></p>
30
- </div>
31
- <div style="width: 33%; float: left;">
32
- <p><?php _e('Views Today', 'pmpro')?>: <?php echo $views['today'];?></p>
33
- <p><?php _e('Views This Month', 'pmpro')?>: <?php echo $views['month'];?></p>
34
- <p><?php _e('Views All Time', 'pmpro')?>: <?php echo $views['alltime'];?></p>
35
- </div>
36
- <div style="width: 33%; float: left;">
37
- <p><?php _e('Logins Today', 'pmpro')?>: <?php echo $logins['today'];?></p>
38
- <p><?php _e('Logins This Month', 'pmpro')?>: <?php echo $logins['month'];?></p>
39
- <p><?php _e('Logins All Time', 'pmpro')?>: <?php echo $logins['alltime'];?></p>
40
- </div>
41
- <div class="clear"></div>
42
- <?php
43
- }
44
-
45
- function pmpro_report_login_page()
46
- {
47
- global $wpdb;
48
- $now = current_time('timestamp');
49
-
50
- //vars
51
- if(!empty($_REQUEST['s']))
52
- $s = $_REQUEST['s'];
53
- else
54
- $s = "";
55
-
56
- if(!empty($_REQUEST['l']))
57
- $l = intval($_REQUEST['l']);
58
- else
59
- $l = "";
60
- ?>
61
- <form id="posts-filter" method="get" action="">
62
- <h2>
63
- <?php _e('Visits, Views, and Logins Report', 'pmpro');?>
64
- </h2>
65
- <ul class="subsubsub">
66
- <li>
67
- <?php _ex('Show', 'Dropdown label, e.g. Show All Users', 'pmpro')?> <select name="l" onchange="jQuery('#posts-filter').submit();">
68
- <option value="" <?php if(!$l) { ?>selected="selected"<?php } ?>><?php _e('All Users', 'pmpro')?></option>
69
- <option value="all" <?php if($l == "all") { ?>selected="selected"<?php } ?>><?php _e('All Levels', 'pmpro')?></option>
70
- <?php
71
- $levels = $wpdb->get_results("SELECT id, name FROM $wpdb->pmpro_membership_levels ORDER BY name");
72
- foreach($levels as $level)
73
- {
74
- ?>
75
- <option value="<?php echo $level->id?>" <?php if($l == $level->id) { ?>selected="selected"<?php } ?>><?php echo $level->name?></option>
76
- <?php
77
- }
78
- ?>
79
- </select>
80
- </li>
81
- </ul>
82
- <p class="search-box">
83
- <label class="hidden" for="post-search-input"><?php _ex('Search', 'Search form label', 'pmpro')?> <?php if(empty($l)) echo "Users"; else echo "Members";?>:</label>
84
- <input type="hidden" name="page" value="pmpro-reports" />
85
- <input type="hidden" name="report" value="login" />
86
- <input id="post-search-input" type="text" value="<?php echo esc_attr($s)?>" name="s"/>
87
- <input class="button" type="submit" value="Search Members"/>
88
- </p>
89
- <?php
90
- //some vars for the search
91
- if(isset($_REQUEST['pn']))
92
- $pn = intval($_REQUEST['pn']);
93
- else
94
- $pn = 1;
95
-
96
- if(isset($_REQUEST['limit']))
97
- $limit = intval($_REQUEST['limit']);
98
- else
99
- $limit = 15;
100
-
101
- $end = $pn * $limit;
102
- $start = $end - $limit;
103
-
104
- if($s)
105
- {
106
- $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id AND mu.status = 'active' LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id WHERE (u.user_login LIKE '%" . esc_sql($s) . "%' OR u.user_email LIKE '%" . esc_sql($s) . "%' OR um.meta_value LIKE '%" . esc_sql($s) . "%') ";
107
-
108
- if($l == "all")
109
- $sqlQuery .= " AND mu.status = 'active' AND mu.membership_id > 0 ";
110
- elseif($l)
111
- $sqlQuery .= " AND mu.membership_id = '" . $l . "' ";
112
-
113
- $sqlQuery .= "GROUP BY u.ID ORDER BY user_registered DESC LIMIT $start, $limit";
114
- }
115
- else
116
- {
117
- $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id AND mu.status = 'active' LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id";
118
- $sqlQuery .= " WHERE 1=1 ";
119
-
120
- if($l == "all")
121
- $sqlQuery .= " AND mu.membership_id > 0 AND mu.status = 'active' ";
122
- elseif($l)
123
- $sqlQuery .= " AND mu.membership_id = '" . $l . "' ";
124
- $sqlQuery .= "GROUP BY u.ID ORDER BY user_registered DESC LIMIT $start, $limit";
125
- }
126
-
127
- $sqlQuery = apply_filters("pmpro_members_list_sql", $sqlQuery);
128
-
129
- $theusers = $wpdb->get_results($sqlQuery);
130
- $totalrows = $wpdb->get_var("SELECT FOUND_ROWS() as found_rows");
131
-
132
- if($theusers)
133
- {
134
- ?>
135
- <p class="clear"><?php echo strval($totalrows)?> <?php if(empty($l)) echo "users"; else echo "members";?> found.
136
- <?php
137
- }
138
- ?>
139
- <table class="widefat">
140
- <thead>
141
- <tr class="thead">
142
- <th><?php _e('ID', 'pmpro')?></th>
143
- <th><?php _e('User', 'pmpro')?></th>
144
- <th><?php _e('Name', 'pmpro')?></th>
145
- <th><?php _e('Membership', 'pmpro')?></th>
146
- <th><?php _e('Joined', 'pmpro')?></th>
147
- <th><?php _e('Expires', 'pmpro')?></th>
148
- <th><?php _e('Last Visit', 'pmpro')?></th>
149
- <th><?php _e('Visits This Month', 'pmpro')?></th>
150
- <th><?php _e('Total Visits', 'pmpro')?></th>
151
- <th><?php _e('Views This Month', 'pmpro')?></th>
152
- <th><?php _e('Total Views', 'pmpro')?></th>
153
- <th><?php _e('Last Login', 'pmpro')?></th>
154
- <th><?php _e('Logins This Month', 'pmpro')?></th>
155
- <th><?php _e('Total Logins', 'pmpro')?></th>
156
- </tr>
157
- </thead>
158
- <tbody id="users" class="list:user user-list">
159
- <?php
160
- $count = 0;
161
- foreach($theusers as $auser)
162
- {
163
- //get meta
164
- $theuser = get_userdata($auser->ID);
165
- $visits = get_user_meta($auser->ID, "pmpro_visits", true);
166
- $views = get_user_meta($auser->ID, "pmpro_views", true);
167
- $logins = get_user_meta($auser->ID, "pmpro_logins", true);
168
- if(empty($logins))
169
- $logins = array("last"=>"N/A", "month"=>"N/A", "alltime"=>"N/A");
170
- ?>
171
- <tr <?php if($count++ % 2 == 0) { ?>class="alternate"<?php } ?>>
172
- <td><?php echo $theuser->ID?></td>
173
- <td>
174
- <?php echo get_avatar($theuser->ID, 32)?>
175
- <strong>
176
- <?php
177
- $userlink = '<a href="user-edit.php?user_id=' . $theuser->ID . '">' . $theuser->user_login . '</a>';
178
- $userlink = apply_filters("pmpro_members_list_user_link", $userlink, $theuser);
179
- echo $userlink;
180
- ?>
181
- </strong>
182
- </td>
183
- <td>
184
- <?php echo $theuser->display_name;?>
185
- </td>
186
- <td><?php echo $auser->membership?></td>
187
- <td><?php echo date("m/d/Y", strtotime($theuser->user_registered, current_time("timestamp")))?></td>
188
- <td>
189
- <?php
190
- if($auser->enddate)
191
- echo date(get_option('date_format'), $auser->enddate);
192
- else
193
- echo "Never";
194
- ?>
195
- </td>
196
- <td><?php if(!empty($visits['last'])) echo $visits['last'];?></td>
197
- <td><?php if(!empty($visits['month']) && pmpro_isDateThisMonth($visits['last'])) echo $visits['month'];?></td>
198
- <td><?php if(!empty($visits['alltime'])) echo $visits['alltime'];?></td>
199
- <td><?php if(!empty($views['month']) && pmpro_isDateThisMonth($views['last'])) echo $views['month'];?></td>
200
- <td><?php if(!empty($views['alltime'])) echo $views['alltime'];?></td>
201
- <td><?php if(!empty($logins['last'])) echo $logins['last'];?></td>
202
- <td><?php if(!empty($logins['month']) && pmpro_isDateThisMonth($logins['last'])) echo $logins['month'];?></td>
203
- <td><?php if(!empty($logins['alltime'])) echo $logins['alltime'];?></td>
204
- </tr>
205
- <?php
206
- }
207
-
208
- if(!$theusers)
209
- {
210
- ?>
211
- <tr>
212
- <td colspan="9"><p><?php _e('No members found.', 'pmpro')?> <?php if($l) { ?><a href="?page=pmpro-memberslist&s=<?php echo esc_attr($s)?>"><?php _e('Search all levels', 'pmpro')?></a>.<?php } ?></p></td>
213
- </tr>
214
- <?php
215
- }
216
- ?>
217
- </tbody>
218
- </table>
219
- </form>
220
-
221
- <?php
222
- echo pmpro_getPaginationString($pn, $totalrows, $limit, 1, get_admin_url(NULL, "/admin.php?page=pmpro-reports&report=login&s=" . urlencode($s)), "&l=$l&limit=$limit&pn=");
223
- ?>
224
- <?php
225
- }
226
-
227
- /*
228
- Other code required for your reports. This file is loaded every time WP loads with PMPro enabled.
229
- */
230
-
231
- //track visits
232
- function pmpro_report_login_wp_visits()
233
- {
234
- //don't track admin
235
- if(is_admin())
236
- return;
237
-
238
- //only track logged in users
239
- if(!is_user_logged_in())
240
- return;
241
-
242
- //check for cookie
243
- if(!empty($_COOKIE['pmpro_visit']))
244
- return;
245
-
246
- $now = current_time('timestamp');
247
-
248
- //set cookie, then track
249
- setcookie("pmpro_visit", "1", NULL, COOKIEPATH, COOKIE_DOMAIN, false);
250
-
251
- global $current_user;
252
- //track for user
253
- if(!empty($current_user->ID))
254
- {
255
- $visits = $current_user->pmpro_visits;
256
- if(empty($visits))
257
- $visits = array("last"=>"N/A", "thisdate"=>NULL, "month"=>0, "thismonth"=>NULL, "alltime"=>0);
258
-
259
- //track logins for user
260
- $visits['last'] = date(get_option("date_format"));
261
- $visits['alltime']++;
262
- $thismonth = date("n", $now);
263
- if($thismonth == $visits['thismonth'])
264
- $visits['month']++;
265
- else
266
- {
267
- $visits['month'] = 1;
268
- $visits['thismonth'] = $thismonth;
269
- }
270
-
271
- //update user data
272
- update_user_meta($current_user->ID, "pmpro_visits", $visits);
273
- }
274
-
275
- //track for all
276
- $visits = get_option("pmpro_visits");
277
- if(empty($visits))
278
- $visits = array("today"=>0, "thisdate"=>NULL, "month"=>0, "thismonth"=> NULL, "alltime"=>0);
279
-
280
- $visits['alltime']++;
281
- $thisdate = date("Y-d-m", $now);
282
- if($thisdate == $visits['thisdate'])
283
- $visits['today']++;
284
- else
285
- {
286
- $visits['today'] = 1;
287
- $visits['thisdate'] = $thisdate;
288
- }
289
- if($thismonth == $visits['thismonth'])
290
- $visits['month']++;
291
- else
292
- {
293
- $visits['month'] = 1;
294
- $visits['thismonth'] = $thismonth;
295
- }
296
-
297
- update_option("pmpro_visits", $visits);
298
- }
299
- add_action("wp", "pmpro_report_login_wp_visits");
300
-
301
- //we want to clear the pmpro_visit cookie on login/logout
302
- function pmpro_report_login_clear_visit_cookie()
303
- {
304
- if(isset($_COOKIE['pmpro_visit']))
305
- unset($_COOKIE['pmpro_visit']);
306
- }
307
- add_action("wp_login", "pmpro_report_login_clear_visit_cookie");
308
- add_action("wp_logout", "pmpro_report_login_clear_visit_cookie");
309
-
310
- //track views
311
- function pmpro_report_login_wp_views()
312
- {
313
- //don't track admin
314
- if(is_admin())
315
- return;
316
-
317
- global $current_user;
318
- $now = current_time('timestamp');
319
-
320
- //track for user
321
- if(!empty($current_user->ID))
322
- {
323
- $views = $current_user->pmpro_views;
324
- if(empty($views))
325
- $views = array("last"=>"N/A", "month"=>0, "alltime"=>0);
326
-
327
- //track logins for user
328
- $views['last'] = date(get_option("date_format"), $now);
329
- $views['alltime']++;
330
- $thismonth = date("n", $now);
331
- if(isset($views['thismonth']) && $thismonth == $views['thismonth'])
332
- $views['month']++;
333
- else
334
- {
335
- $views['month'] = 1;
336
- $views['thismonth'] = $thismonth;
337
- }
338
-
339
- //update user data
340
- update_user_meta($current_user->ID, "pmpro_views", $views);
341
- }
342
-
343
- //track for all
344
- $views = get_option("pmpro_views");
345
- if(empty($views))
346
- $views = array("today"=>0, "thisdate"=> NULL, "month"=>0, "thismonth"=> NULL, "alltime"=>0);
347
-
348
- $views['alltime']++;
349
- $thisdate = date("Y-d-m", $now);
350
- if($thisdate == $views['thisdate'])
351
- $views['today']++;
352
- else
353
- {
354
- $views['today'] = 1;
355
- $views['thisdate'] = $thisdate;
356
- }
357
- $thismonth = date("n", $now);
358
- if(isset($views['thismonth']) && $thismonth == $views['thismonth'])
359
- $views['month']++;
360
- else
361
- {
362
- $views['month'] = 1;
363
- $views['thismonth'] = $thismonth;
364
- }
365
-
366
- update_option("pmpro_views", $views);
367
- }
368
- add_action("wp", "pmpro_report_login_wp_views");
369
-
370
- //track logins
371
- function pmpro_report_login_wp_login($user_login)
372
- {
373
- $now = current_time('timestamp');
374
-
375
- //get user data
376
- $user = get_user_by("login", $user_login);
377
- $logins = $user->pmpro_logins;
378
- if(empty($logins))
379
- $logins = array("last"=>"N/A", "thisdate"=>NULL, "month"=>0, "thismonth"=> NULL, "alltime"=>0);
380
-
381
- //track logins for user
382
- $logins['last'] = date(get_option("date_format"), $now);
383
- $logins['alltime']++;
384
- $thismonth = date("n", $now);
385
- if($thismonth == $logins['thismonth'])
386
- $logins['month']++;
387
- else
388
- {
389
- $logins['month'] = 1;
390
- $logins['thismonth'] = $thismonth;
391
- }
392
-
393
- //update user data
394
- update_user_meta($user->ID, "pmpro_logins", $logins);
395
-
396
- //track logins overall
397
- $logins = get_option("pmpro_logins");
398
- if(empty($logins))
399
- $logins = array("today"=>0, "thisdate"=>NULL, "month"=>0, "thismonth"=>NULL, "alltime"=>0);
400
-
401
- $logins['alltime']++;
402
- $thisdate = date("Y-d-m", $now);
403
- if($thisdate == $logins['thisdate'])
404
- $logins['today']++;
405
- else
406
- {
407
- $logins['today'] = 1;
408
- $logins['thisdate'] = $thisdate;
409
- }
410
- if($thismonth == $logins['thismonth'])
411
- $logins['month']++;
412
- else
413
- {
414
- $logins['month'] = 1;
415
- $logins['thismonth'] = $thismonth;
416
- }
417
-
418
- update_option("pmpro_logins", $logins);
419
- }
420
  add_action("wp_login", "pmpro_report_login_wp_login");
1
+ <?php
2
+ /*
3
+ PMPro Report
4
+ Title: Logins
5
+ Slug: login
6
+
7
+ For each report, add a line like:
8
+ global $pmpro_reports;
9
+ $pmpro_reports['slug'] = 'Title';
10
+
11
+ For each report, also write two functions:
12
+ * pmpro_report_{slug}_widget() to show up on the report homepage.
13
+ * pmpro_report_{slug}_page() to show up when users click on the report page widget.
14
+ */
15
+ global $pmpro_reports;
16
+ $pmpro_reports['login'] = __('Visits, Views, and Logins', 'pmpro');
17
+
18
+ function pmpro_report_login_widget()
19
+ {
20
+ global $wpdb;
21
+ $now = current_time('timestamp');
22
+ $visits = get_option("pmpro_visits", array("today"=>0, "thisday"=>date("Y-m-d", $now), "alltime"=>0, "month"=>0, "thismonth"=>date("n", $now)));
23
+ $views = get_option("pmpro_views", array("today"=>0, "thisday"=>date("Y-m-d", $now), "alltime"=>0, "month"=>0, "thismonth"=>date("n", $now)));
24
+ $logins = get_option("pmpro_logins", array("today"=>0, "thisday"=>date("Y-m-d", $now), "alltime"=>0, "month"=>0, "thismonth"=>date("n", $now)));
25
+ ?>
26
+ <div style="width: 33%; float: left;">
27
+ <p><?php _e('Visits Today', 'pmpro')?>: <?php echo $visits['today'];?></p>
28
+ <p><?php _e('Visits This Month', 'pmpro')?>: <?php echo $visits['month'];?></p>
29
+ <p><?php _e('Visits All Time', 'pmpro')?>: <?php echo $visits['alltime'];?></p>
30
+ </div>
31
+ <div style="width: 33%; float: left;">
32
+ <p><?php _e('Views Today', 'pmpro')?>: <?php echo $views['today'];?></p>
33
+ <p><?php _e('Views This Month', 'pmpro')?>: <?php echo $views['month'];?></p>
34
+ <p><?php _e('Views All Time', 'pmpro')?>: <?php echo $views['alltime'];?></p>
35
+ </div>
36
+ <div style="width: 33%; float: left;">
37
+ <p><?php _e('Logins Today', 'pmpro')?>: <?php echo $logins['today'];?></p>
38
+ <p><?php _e('Logins This Month', 'pmpro')?>: <?php echo $logins['month'];?></p>
39
+ <p><?php _e('Logins All Time', 'pmpro')?>: <?php echo $logins['alltime'];?></p>
40
+ </div>
41
+ <div class="clear"></div>
42
+ <?php
43
+ }
44
+
45
+ function pmpro_report_login_page()
46
+ {
47
+ global $wpdb;
48
+ $now = current_time('timestamp');
49
+
50
+ //vars
51
+ if(!empty($_REQUEST['s']))
52
+ $s = $_REQUEST['s'];
53
+ else
54
+ $s = "";
55
+
56
+ if(!empty($_REQUEST['l']))
57
+ $l = intval($_REQUEST['l']);
58
+ else
59
+ $l = "";
60
+ ?>
61
+ <form id="posts-filter" method="get" action="">
62
+ <h2>
63
+ <?php _e('Visits, Views, and Logins Report', 'pmpro');?>
64
+ </h2>
65
+ <ul class="subsubsub">
66
+ <li>
67
+ <?php _ex('Show', 'Dropdown label, e.g. Show All Users', 'pmpro')?> <select name="l" onchange="jQuery('#posts-filter').submit();">
68
+ <option value="" <?php if(!$l) { ?>selected="selected"<?php } ?>><?php _e('All Users', 'pmpro')?></option>
69
+ <option value="all" <?php if($l == "all") { ?>selected="selected"<?php } ?>><?php _e('All Levels', 'pmpro')?></option>
70
+ <?php
71
+ $levels = $wpdb->get_results("SELECT id, name FROM $wpdb->pmpro_membership_levels ORDER BY name");
72
+ foreach($levels as $level)
73
+ {
74
+ ?>
75
+ <option value="<?php echo $level->id?>" <?php if($l == $level->id) { ?>selected="selected"<?php } ?>><?php echo $level->name?></option>
76
+ <?php
77
+ }
78
+ ?>
79
+ </select>
80
+ </li>
81
+ </ul>
82
+ <p class="search-box">
83
+ <label class="hidden" for="post-search-input"><?php _ex('Search', 'Search form label', 'pmpro')?> <?php if(empty($l)) echo "Users"; else echo "Members";?>:</label>
84
+ <input type="hidden" name="page" value="pmpro-reports" />
85
+ <input type="hidden" name="report" value="login" />
86
+ <input id="post-search-input" type="text" value="<?php echo esc_attr($s)?>" name="s"/>
87
+ <input class="button" type="submit" value="Search Members"/>
88
+ </p>
89
+ <?php
90
+ //some vars for the search
91
+ if(isset($_REQUEST['pn']))
92
+ $pn = intval($_REQUEST['pn']);
93
+ else
94
+ $pn = 1;
95
+
96
+ if(isset($_REQUEST['limit']))
97
+ $limit = intval($_REQUEST['limit']);
98
+ else
99
+ $limit = 15;
100
+
101
+ $end = $pn * $limit;
102
+ $start = $end - $limit;
103
+
104
+ if($s)
105
+ {
106
+ $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id AND mu.status = 'active' LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id WHERE (u.user_login LIKE '%" . esc_sql($s) . "%' OR u.user_email LIKE '%" . esc_sql($s) . "%' OR um.meta_value LIKE '%" . esc_sql($s) . "%') ";
107
+
108
+ if($l == "all")
109
+ $sqlQuery .= " AND mu.status = 'active' AND mu.membership_id > 0 ";
110
+ elseif($l)
111
+ $sqlQuery .= " AND mu.membership_id = '" . $l . "' ";
112
+
113
+ $sqlQuery .= "GROUP BY u.ID ORDER BY user_registered DESC LIMIT $start, $limit";
114
+ }
115
+ else
116
+ {
117
+ $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id AND mu.status = 'active' LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id";
118
+ $sqlQuery .= " WHERE 1=1 ";
119
+
120
+ if($l == "all")
121
+ $sqlQuery .= " AND mu.membership_id > 0 AND mu.status = 'active' ";
122
+ elseif($l)
123
+ $sqlQuery .= " AND mu.membership_id = '" . $l . "' ";
124
+ $sqlQuery .= "GROUP BY u.ID ORDER BY user_registered DESC LIMIT $start, $limit";
125
+ }
126
+
127
+ $sqlQuery = apply_filters("pmpro_members_list_sql", $sqlQuery);
128
+
129
+ $theusers = $wpdb->get_results($sqlQuery);
130
+ $totalrows = $wpdb->get_var("SELECT FOUND_ROWS() as found_rows");
131
+
132
+ if($theusers)
133
+ {
134
+ ?>
135
+ <p class="clear"><?php echo strval($totalrows)?> <?php if(empty($l)) echo "users"; else echo "members";?> found.
136
+ <?php
137
+ }
138
+ ?>
139
+ <table class="widefat">
140
+ <thead>
141
+ <tr class="thead">
142
+ <th><?php _e('ID', 'pmpro')?></th>
143
+ <th><?php _e('User', 'pmpro')?></th>
144
+ <th><?php _e('Name', 'pmpro')?></th>
145
+ <th><?php _e('Membership', 'pmpro')?></th>
146
+ <th><?php _e('Joined', 'pmpro')?></th>
147
+ <th><?php _e('Expires', 'pmpro')?></th>
148
+ <th><?php _e('Last Visit', 'pmpro')?></th>
149
+ <th><?php _e('Visits This Month', 'pmpro')?></th>
150
+ <th><?php _e('Total Visits', 'pmpro')?></th>
151
+ <th><?php _e('Views This Month', 'pmpro')?></th>
152
+ <th><?php _e('Total Views', 'pmpro')?></th>
153
+ <th><?php _e('Last Login', 'pmpro')?></th>
154
+ <th><?php _e('Logins This Month', 'pmpro')?></th>
155
+ <th><?php _e('Total Logins', 'pmpro')?></th>
156
+ </tr>
157
+ </thead>
158
+ <tbody id="users" class="list:user user-list">
159
+ <?php
160
+ $count = 0;
161
+ foreach($theusers as $auser)
162
+ {
163
+ //get meta
164
+ $theuser = get_userdata($auser->ID);
165
+ $visits = get_user_meta($auser->ID, "pmpro_visits", true);
166
+ $views = get_user_meta($auser->ID, "pmpro_views", true);
167
+ $logins = get_user_meta($auser->ID, "pmpro_logins", true);
168
+ if(empty($logins))
169
+ $logins = array("last"=>"N/A", "month"=>"N/A", "alltime"=>"N/A");
170
+ ?>
171
+ <tr <?php if($count++ % 2 == 0) { ?>class="alternate"<?php } ?>>
172
+ <td><?php echo $theuser->ID?></td>
173
+ <td>
174
+ <?php echo get_avatar($theuser->ID, 32)?>
175
+ <strong>
176
+ <?php
177
+ $userlink = '<a href="user-edit.php?user_id=' . $theuser->ID . '">' . $theuser->user_login . '</a>';
178
+ $userlink = apply_filters("pmpro_members_list_user_link", $userlink, $theuser);
179
+ echo $userlink;
180
+ ?>
181
+ </strong>
182
+ </td>
183
+ <td>
184
+ <?php echo $theuser->display_name;?>
185
+ </td>
186
+ <td><?php echo $auser->membership?></td>
187
+ <td><?php echo date("m/d/Y", strtotime($theuser->user_registered, current_time("timestamp")))?></td>
188
+ <td>
189
+ <?php
190
+ if($auser->enddate)
191
+ echo date(get_option('date_format'), $auser->enddate);
192
+ else
193
+ echo "Never";
194
+ ?>
195
+ </td>
196
+ <td><?php if(!empty($visits['last'])) echo $visits['last'];?></td>
197
+ <td><?php if(!empty($visits['month']) && pmpro_isDateThisMonth($visits['last'])) echo $visits['month'];?></td>
198
+ <td><?php if(!empty($visits['alltime'])) echo $visits['alltime'];?></td>
199
+ <td><?php if(!empty($views['month']) && pmpro_isDateThisMonth($views['last'])) echo $views['month'];?></td>
200
+ <td><?php if(!empty($views['alltime'])) echo $views['alltime'];?></td>
201
+ <td><?php if(!empty($logins['last'])) echo $logins['last'];?></td>
202
+ <td><?php if(!empty($logins['month']) && pmpro_isDateThisMonth($logins['last'])) echo $logins['month'];?></td>
203
+ <td><?php if(!empty($logins['alltime'])) echo $logins['alltime'];?></td>
204
+ </tr>
205
+ <?php
206
+ }
207
+
208
+ if(!$theusers)
209
+ {
210
+ ?>
211
+ <tr>
212
+ <td colspan="9"><p><?php _e('No members found.', 'pmpro')?> <?php if($l) { ?><a href="?page=pmpro-memberslist&s=<?php echo esc_attr($s)?>"><?php _e('Search all levels', 'pmpro')?></a>.<?php } ?></p></td>
213
+ </tr>
214
+ <?php
215
+ }
216
+ ?>
217
+ </tbody>
218
+ </table>
219
+ </form>
220
+
221
+ <?php
222
+ echo pmpro_getPaginationString($pn, $totalrows, $limit, 1, get_admin_url(NULL, "/admin.php?page=pmpro-reports&report=login&s=" . urlencode($s)), "&l=$l&limit=$limit&pn=");
223
+ ?>
224
+ <?php
225
+ }
226
+
227
+ /*
228
+ Other code required for your reports. This file is loaded every time WP loads with PMPro enabled.
229
+ */
230
+
231
+ //track visits
232
+ function pmpro_report_login_wp_visits()
233
+ {
234
+ //don't track admin
235
+ if(is_admin())
236
+ return;
237
+
238
+ //only track logged in users
239
+ if(!is_user_logged_in())
240
+ return;
241
+
242
+ //check for cookie
243
+ if(!empty($_COOKIE['pmpro_visit']))
244
+ return;
245
+
246
+ $now = current_time('timestamp');
247
+
248
+ //set cookie, then track
249
+ setcookie("pmpro_visit", "1", NULL, COOKIEPATH, COOKIE_DOMAIN, false);
250
+
251
+ global $current_user;
252
+ //track for user
253
+ if(!empty($current_user->ID))
254
+ {
255
+ $visits = $current_user->pmpro_visits;
256
+ if(empty($visits))
257
+ $visits = array("last"=>"N/A", "thisdate"=>NULL, "month"=>0, "thismonth"=>NULL, "alltime"=>0);
258
+
259
+ //track logins for user
260
+ $visits['last'] = date(get_option("date_format"));
261
+ $visits['alltime']++;
262
+ $thismonth = date("n", $now);
263
+ if($thismonth == $visits['thismonth'])
264
+ $visits['month']++;
265
+ else
266
+ {
267
+ $visits['month'] = 1;
268
+ $visits['thismonth'] = $thismonth;
269
+ }
270
+
271
+ //update user data
272
+ update_user_meta($current_user->ID, "pmpro_visits", $visits);
273
+ }
274
+
275
+ //track for all
276
+ $visits = get_option("pmpro_visits");
277
+ if(empty($visits))
278
+ $visits = array("today"=>0, "thisdate"=>NULL, "month"=>0, "thismonth"=> NULL, "alltime"=>0);
279
+
280
+ $visits['alltime']++;
281
+ $thisdate = date("Y-d-m", $now);
282
+ if($thisdate == $visits['thisdate'])
283
+ $visits['today']++;
284
+ else
285
+ {
286
+ $visits['today'] = 1;
287
+ $visits['thisdate'] = $thisdate;
288
+ }
289
+ if($thismonth == $visits['thismonth'])
290
+ $visits['month']++;
291
+ else
292
+ {
293
+ $visits['month'] = 1;
294
+ $visits['thismonth'] = $thismonth;
295
+ }
296
+
297
+ update_option("pmpro_visits", $visits);
298
+ }
299
+ add_action("wp", "pmpro_report_login_wp_visits");
300
+
301
+ //we want to clear the pmpro_visit cookie on login/logout
302
+ function pmpro_report_login_clear_visit_cookie()
303
+ {
304
+ if(isset($_COOKIE['pmpro_visit']))
305
+ unset($_COOKIE['pmpro_visit']);
306
+ }
307
+ add_action("wp_login", "pmpro_report_login_clear_visit_cookie");
308
+ add_action("wp_logout", "pmpro_report_login_clear_visit_cookie");
309
+
310
+ //track views
311
+ function pmpro_report_login_wp_views()
312
+ {
313
+ //don't track admin
314
+ if(is_admin())
315
+ return;
316
+
317
+ global $current_user;
318
+ $now = current_time('timestamp');
319
+
320
+ //track for user
321
+ if(!empty($current_user->ID))
322
+ {
323
+ $views = $current_user->pmpro_views;
324
+ if(empty($views))
325
+ $views = array("last"=>"N/A", "month"=>0, "alltime"=>0);
326
+
327
+ //track logins for user
328
+ $views['last'] = date(get_option("date_format"), $now);
329
+ $views['alltime']++;
330
+ $thismonth = date("n", $now);
331
+ if(isset($views['thismonth']) && $thismonth == $views['thismonth'])
332
+ $views['month']++;
333
+ else
334
+ {
335
+ $views['month'] = 1;
336
+ $views['thismonth'] = $thismonth;
337
+ }
338
+
339
+ //update user data
340
+ update_user_meta($current_user->ID, "pmpro_views", $views);
341
+ }
342
+
343
+ //track for all
344
+ $views = get_option("pmpro_views");
345
+ if(empty($views))
346
+ $views = array("today"=>0, "thisdate"=> NULL, "month"=>0, "thismonth"=> NULL, "alltime"=>0);
347
+
348
+ $views['alltime']++;
349
+ $thisdate = date("Y-d-m", $now);
350
+ if($thisdate == $views['thisdate'])
351
+ $views['today']++;
352
+ else
353
+ {
354
+ $views['today'] = 1;
355
+ $views['thisdate'] = $thisdate;
356
+ }
357
+ $thismonth = date("n", $now);
358
+ if(isset($views['thismonth']) && $thismonth == $views['thismonth'])
359
+ $views['month']++;
360
+ else
361
+ {
362
+ $views['month'] = 1;
363
+ $views['thismonth'] = $thismonth;
364
+ }
365
+
366
+ update_option("pmpro_views", $views);
367
+ }
368
+ add_action("wp", "pmpro_report_login_wp_views");
369
+
370
+ //track logins
371
+ function pmpro_report_login_wp_login($user_login)
372
+ {
373
+ $now = current_time('timestamp');
374
+
375
+ //get user data
376
+ $user = get_user_by("login", $user_login);
377
+ $logins = $user->pmpro_logins;
378
+ if(empty($logins))
379
+ $logins = array("last"=>"N/A", "thisdate"=>NULL, "month"=>0, "thismonth"=> NULL, "alltime"=>0);
380
+
381
+ //track logins for user
382
+ $logins['last'] = date(get_option("date_format"), $now);
383
+ $logins['alltime']++;
384
+ $thismonth = date("n", $now);
385
+ if($thismonth == $logins['thismonth'])
386
+ $logins['month']++;
387
+ else
388
+ {
389
+ $logins['month'] = 1;
390
+ $logins['thismonth'] = $thismonth;
391
+ }
392
+
393
+ //update user data
394
+ update_user_meta($user->ID, "pmpro_logins", $logins);
395
+
396
+ //track logins overall
397
+ $logins = get_option("pmpro_logins");
398
+ if(empty($logins))
399
+ $logins = array("today"=>0, "thisdate"=>NULL, "month"=>0, "thismonth"=>NULL, "alltime"=>0);
400
+
401
+ $logins['alltime']++;
402
+ $thisdate = date("Y-d-m", $now);
403
+ if($thisdate == $logins['thisdate'])
404
+ $logins['today']++;
405
+ else
406
+ {
407
+ $logins['today'] = 1;
408
+ $logins['thisdate'] = $thisdate;
409
+ }
410
+ if($thismonth == $logins['thismonth'])
411
+ $logins['month']++;
412
+ else
413
+ {
414
+ $logins['month'] = 1;
415
+ $logins['thismonth'] = $thismonth;
416
+ }
417
+
418
+ update_option("pmpro_logins", $logins);
419
+ }
420
  add_action("wp_login", "pmpro_report_login_wp_login");
adminpages/reports/memberships.php CHANGED
@@ -1,660 +1,660 @@
1
- <?php
2
- /*
3
- PMPro Report
4
- Title: Membership Stats
5
- Slug: memberships
6
-
7
- For each report, add a line like:
8
- global $pmpro_reports;
9
- $pmpro_reports['slug'] = 'Title';
10
-
11
- For each report, also write two functions:
12
- * pmpro_report_{slug}_widget() to show up on the report homepage.
13
- * pmpro_report_{slug}_page() to show up when users click on the report page widget.
14
- */
15
-
16
- global $pmpro_reports;
17
-
18
- $pmpro_reports['memberships'] = __('Membership Stats', 'pmpro');
19
-
20
- //queue Google Visualization JS on report page
21
- function pmpro_report_memberships_init() {
22
- if(is_admin() && isset($_REQUEST['report']) && $_REQUEST['report'] == "memberships" && isset($_REQUEST['page']) && $_REQUEST['page'] == "pmpro-reports")
23
- wp_enqueue_script("jsapi", "https://www.google.com/jsapi");
24
- }
25
- add_action( 'init', 'pmpro_report_memberships_init' );
26
-
27
-
28
- //widget
29
- function pmpro_report_memberships_widget() {
30
- global $wpdb, $pmpro_currency_symbol;
31
- ?>
32
- <style type="text/css">
33
- #pmpro_report_memberships .section-label {
34
- margin: 15px 0;
35
- font-size: 18px;
36
- text-align: left;
37
- display: block;
38
- }
39
-
40
- #pmpro_report_memberships .section-label:first-child {
41
- margin-top: 0;
42
- }
43
-
44
- #pmpro_report_memberships div {text-align: center;}
45
- #pmpro_report_memberships em {display: block; font-style: normal; font-size: 2em; margin: 5px; line-height: 26px;}
46
- </style>
47
- <span id="pmpro_report_memberships">
48
- <label class="section-label"><?php _e('Signups', 'pmpro');?>:</label>
49
- <div style="width: 25%; float: left;">
50
- <label><?php _e('All Time', 'pmpro');?></label>
51
- <em><?php echo pmpro_getSignups( 'all time' ); ?></em>
52
- </div>
53
- <div style="width: 25%; float: left;">
54
- <label><?php _e('This Year', 'pmpro');?></label>
55
- <em><?php echo pmpro_getSignups( 'this year' ); ?></em>
56
- </div>
57
- <div style="width: 25%; float: left;">
58
- <label><?php _e('This Month', 'pmpro');?></label>
59
- <em><?php echo pmpro_getSignups( 'this month' ); ?></em>
60
- </div>
61
- <div style="width: 25%; float: left;">
62
- <label><?php _e('Today', 'pmpro');?></label>
63
- <em><?php echo pmpro_getSignups( 'today' ); ?></em>
64
- </div>
65
- <div class="clear"></div>
66
-
67
- <label class="section-label"><?php _e('Cancellations', 'pmpro');?>:</label>
68
- <div style="width: 25%; float: left;">
69
- <label><?php _e('All Time', 'pmpro');?></label>
70
- <em><?php echo pmpro_getCancellations( 'all time' ); ?></em>
71
- </div>
72
- <div style="width: 25%; float: left;">
73
- <label><?php _e('This Year', 'pmpro');?></label>
74
- <em><?php echo pmpro_getCancellations( 'this year' ); ?></em>
75
- </div>
76
- <div style="width: 25%; float: left;">
77
- <label><?php _e('This Month', 'pmpro');?></label>
78
- <em><?php echo pmpro_getCancellations( 'this month' ); ?></em>
79
- </div>
80
- <div style="width: 25%; float: left;">
81
- <label><?php _e('Today', 'pmpro');?></label>
82
- <em><?php echo pmpro_getCancellations( 'today' ); ?></em>
83
- </div>
84
- <div class="clear"></div>
85
-
86
- <label class="section-label"><?php _e('Other Stats', 'pmpro');?>:</label>
87
- <div style="width: 33%; float: left;">
88
- <label><?php _e('Monthly Recurring Revenue (MRR)', 'pmpro');?></label>
89
- <em><?php echo pmpro_formatPrice(pmpro_getMRR( 'all time' )); ?></em>
90
- </div>
91
- <div style="width: 33%; float: left;">
92
- <label><?php _e('Cancellation Rate', 'pmpro');?></label>
93
- <em><?php echo pmpro_getCancellationRate('all time' ); ?>%</em>
94
- </div>
95
- <div style="width: 33%; float: left;">
96
- <label><?php _e('Lifetime Value (LTV)', 'pmpro');?></label>
97
- <em><?php echo pmpro_formatPrice(pmpro_getLTV('all time')); ?></em>
98
- </div>
99
- <div class="clear"></div>
100
- </span>
101
- <?php
102
- }
103
-
104
- function pmpro_report_memberships_page()
105
- {
106
- global $wpdb, $pmpro_currency_symbol;
107
-
108
- //get values from form
109
- if(isset($_REQUEST['type']))
110
- $type = sanitize_text_field($_REQUEST['type']);
111
- else
112
- $type = "signup_v_cancel";
113
-
114
- if(isset($_REQUEST['period']))
115
- $period = sanitize_text_field($_REQUEST['period']);
116
- else
117
- $period = "monthly";
118
-
119
- if(isset($_REQUEST['month']))
120
- $month = intval($_REQUEST['month']);
121
- else
122
- $month = date("n");
123
-
124
- $thisyear = date("Y");
125
- if(isset($_REQUEST['year']))
126
- $year = intval($_REQUEST['year']);
127
- else
128
- $year = date("Y");
129
-
130
- if(isset($_REQUEST['level']))
131
- $l = intval($_REQUEST['level']);
132
- else
133
- $l = "";
134
-
135
- //calculate start date and how to group dates returned from DB
136
- if($period == "daily")
137
- {
138
- $startdate = $year . '-' . substr("0" . $month, strlen($month) - 1, 2) . '-01';
139
- $enddate = $year . '-' . substr("0" . $month, strlen($month) - 1, 2) . '-31';
140
- $date_function = 'DAY';
141
- }
142
- elseif($period == "monthly")
143
- {
144
- $startdate = $year . '-01-01';
145
- $enddate = strval(intval($year)+1) . '-01-01';
146
- $date_function = 'MONTH';
147
- }
148
- elseif($period == "annual")
149
- {
150
- $startdate = '1960-01-01'; //all time
151
- $date_function = 'YEAR';
152
- }
153
-
154
- //testing or live data
155
- $gateway_environment = pmpro_getOption("gateway_environment");
156
-
157
- //get data
158
- if ( $type === "signup_v_cancel" ) {
159
- $sqlQuery = "SELECT $date_function(startdate) as date, COUNT(DISTINCT user_id) as signups
160
- FROM $wpdb->pmpro_memberships_users WHERE startdate >= '" . $startdate . "' ";
161
-
162
- if(!empty($enddate))
163
- $sqlQuery .= "AND startdate < '" . $enddate . "' ";
164
- }
165
- if ( $type === "mrr_ltv" ) {
166
- // Get total revenue, number of months in system, and date
167
- if ( $period == 'annual' )
168
- $sqlQuery = "SELECT SUM(total) as total, COUNT(DISTINCT MONTH(timestamp)) as months, $date_function(timestamp) as date
169
- FROM $wpdb->pmpro_membership_orders WHERE status NOT IN('refunded', 'review', 'token')
170
- AND timestamp >= '" . $startdate . "' AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
171
-
172
- if ( $period == 'monthly' )
173
- $sqlQuery = "SELECT SUM(total) as total, $date_function(timestamp) as date
174
- FROM $wpdb->pmpro_membership_orders WHERE status NOT IN('refunded', 'review', 'token')
175
- AND timestamp >= '" . $startdate . "' AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
176
-
177
- if(!empty($enddate))
178
- $sqlQuery .= "AND timestamp < '" . $enddate . "' ";
179
- }
180
-
181
- if(!empty($l))
182
- $sqlQuery .= "AND membership_id IN(" . $l . ") ";
183
-
184
- $sqlQuery .= " GROUP BY date ORDER BY date ";
185
-
186
- $dates = $wpdb->get_results($sqlQuery);
187
-
188
- //fill in blanks in dates
189
- $cols = array();
190
- if($period == "daily")
191
- {
192
- $lastday = date("t", strtotime($startdate, current_time("timestamp")));
193
-
194
- for($i = 1; $i <= $lastday; $i++)
195
- {
196
- // Signups vs. Cancellations
197
- if ( $type === "signup_v_cancel" ) {
198
- $cols[$i] = new stdClass();
199
- $cols[$i]->signups = 0;
200
- foreach($dates as $date)
201
- {
202
- if( $date->date == $i ) {
203
- $cols[$i]->signups = $date->signups;
204
- }
205
- }
206
- }
207
- }
208
- }
209
- elseif($period == "monthly")
210
- {
211
- for($i = 1; $i < 13; $i++)
212
- {
213
- // Signups vs. Cancellations
214
- if ( $type === "signup_v_cancel" ) {
215
- $cols[$i] = new stdClass();
216
- $cols[$i]->date = $i;
217
- $cols[$i]->signups = 0;
218
- foreach($dates as $date)
219
- {
220
- if( $date->date == $i ) {
221
- $cols[$i]->date = $date->date;
222
- $cols[$i]->signups = $date->signups;
223
- }
224
- }
225
- }
226
-
227
- // MRR & LTV
228
- if ( $type === "mrr_ltv" ) {
229
- $cols[$i] = new stdClass();
230
- $cols[$i]->date = $i;
231
- $cols[$i]->months = 1;
232
- foreach($dates as $date)
233
- {
234
- if( $date->date == $i ) {
235
- $cols[$i]->total = $date->total;
236
- }
237
- }
238
- }
239
- }
240
- }
241
- elseif($period == "annual") //annual
242
- {
243
- }
244
-
245
- $dates = ( ! empty( $cols ) ) ? $cols : $dates;
246
-
247
- // Signups vs. cancellations
248
- if ( $type === "signup_v_cancel" )
249
- {
250
- $sqlQuery = "SELECT $date_function(mu1.modified) as date, COUNT(DISTINCT mu1.user_id) as cancellations
251
- FROM $wpdb->pmpro_memberships_users mu1
252
- LEFT JOIN $wpdb->pmpro_memberships_users mu2 ON mu1.user_id = mu2.user_id AND
253
- mu2.modified > mu1.enddate AND
254
- DATE_ADD(mu1.modified, INTERVAL 1 DAY) > mu2.startdate
255
- WHERE mu1.status = 'inactive'
256
- AND mu2.id IS NULL
257
- AND mu1.startdate >= '" . $startdate . "'
258
- AND mu1.startdate < '" . $enddate . "' ";
259
-
260
- //restrict by level
261
- if(!empty($l))
262
- $sqlQuery .= "AND membership_id IN(" . $l . ") ";
263
-
264
- $sqlQuery .= " GROUP BY date ORDER BY date ";
265
-
266
- $cdates = $wpdb->get_results($sqlQuery, OBJECT_K);
267
-
268
- foreach( $dates as &$date )
269
- {
270
- if(!empty($cdates[$date->date]))
271
- $date->cancellations = $cdates[$date->date]->cancellations;
272
- else
273
- $date->cancellations = 0;
274
- }
275
- }
276
-
277
- // MRR & LTV
278
- if ( $type === "mrr_ltv" && count( $dates ) === 1 ) {
279
- $dummy_date = new stdClass();
280
- $dummy_date->total = 0;
281
- $dummy_date->months = 0;
282
- $dummy_date->date = $dates[0]->date - 1;
283
- array_unshift( $dates, $dummy_date ); // Add to beginning
284
- }
285
- ?>
286
- <form id="posts-filter" method="get" action="">
287
- <h2>
288
- <?php _e('Membership Stats', 'pmpro');?>
289
- </h2>
290
- <ul class="subsubsub">
291
- <li>
292
- <?php _ex('Show', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?>
293
- <select id="period" name="period">
294
- <option value="daily" <?php selected($period, "daily");?>><?php _e('Daily', 'pmpro');?></option>
295
- <option value="monthly" <?php selected($period, "monthly");?>><?php _e('Monthly', 'pmpro');?></option>
296
- <option value="annual" <?php selected($period, "annual");?>><?php _e('Annual', 'pmpro');?></option>
297
- </select>
298
- <select id="type" name="type">
299
- <option value="signup_v_cancel" <?php selected($type, "signup_v_cancel");?>><?php _e('Signups vs. Cancellations', 'pmpro');?></option>
300
- <?php /*
301
- <option value="mrr_ltv" <?php selected($type, "mrr_ltv");?>><?php _e('MRR & LTV', 'pmpro');?></option>
302
- */ ?>
303
- </select>
304
- <span id="for"><?php _ex('for', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?></span>
305
- <select id="month" name="month">
306
- <?php for($i = 1; $i < 13; $i++) { ?>
307
- <option value="<?php echo $i;?>" <?php selected($month, $i);?>><?php echo date("F", mktime(0, 0, 0, $i, 2));?></option>
308
- <?php } ?>
309
- </select>
310
- <select id="year" name="year">
311
- <?php for($i = $thisyear; $i > 2007; $i--) { ?>
312
- <option value="<?php echo $i;?>" <?php selected($year, $i);?>><?php echo $i;?></option>
313
- <?php } ?>
314
- </select>
315
- <span id="for"><?php _ex('for', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?></span>
316
- <select name="level">
317
- <option value="" <?php if(!$l) { ?>selected="selected"<?php } ?>><?php _e('All Levels', 'pmpro');?></option>
318
- <?php
319
- $levels = $wpdb->get_results("SELECT id, name FROM $wpdb->pmpro_membership_levels ORDER BY name");
320
- foreach($levels as $level)
321
- {
322
- ?>
323
- <option value="<?php echo $level->id?>" <?php if($l == $level->id) { ?>selected="selected"<?php } ?>><?php echo $level->name?></option>
324
- <?php
325
- }
326
- ?>
327
- </select>
328
-
329
- <input type="hidden" name="page" value="pmpro-reports" />
330
- <input type="hidden" name="report" value="memberships" />
331
- <input type="submit" value="<?php _ex('Generate Report', 'Submit button value.', 'pmpro');?>" />
332
- </li>
333
- </ul>
334
-
335
- <div id="chart_div" style="clear: both; width: 100%; height: 500px;"></div>
336
-
337
- <script>
338
- //update month/year when period dropdown is changed
339
- jQuery(document).ready(function() {
340
- jQuery('#period').change(function() {
341
- pmpro_ShowMonthOrYear();
342
- });
343
- });
344
-
345
- function pmpro_ShowMonthOrYear()
346
- {
347
- var period = jQuery('#period').val();
348
- if(period == 'daily')
349
- {
350
- jQuery('#for').show();
351
- jQuery('#month').show();
352
- jQuery('#year').show();
353
- }
354
- else if(period == 'monthly')
355
- {
356
- jQuery('#for').show();
357
- jQuery('#month').hide();
358
- jQuery('#year').show();
359
- }
360
- else
361
- {
362
- jQuery('#for').hide();
363
- jQuery('#month').hide();
364
- jQuery('#year').hide();
365
- }
366
- }
367
-
368
- pmpro_ShowMonthOrYear();
369
-
370
- //draw the chart
371
- google.load("visualization", "1", {packages:["corechart"]});
372
- google.setOnLoadCallback(drawChart);
373
- function drawChart() {
374
-
375
- var data = google.visualization.arrayToDataTable([
376
- <?php if ( $type === "signup_v_cancel" ) : // Signups vs. cancellations ?>
377
- ['<?php echo $date_function;?>', 'Signups', 'Cancellations'],
378
- <?php foreach($dates as $key => $value) { ?>
379
- ['<?php if($period == "monthly") echo date("M", mktime(0,0,0,$value->date,2)); else if($period == "daily") echo $key; else echo $value->date;?>', <?php echo $value->signups; ?>, <?php echo $value->cancellations; ?>],
380
- <?php } ?>
381
- <?php endif; ?>
382
-
383
- <?php if ( $type === "mrr_ltv" ) : // Signups vs. cancellations ?>
384
- ['<?php echo $date_function;?>', 'MRR', 'LTV'],
385
- <?php foreach($dates as $key => $value) { ?>
386
- ['<?php if($period == "monthly") echo date("M", mktime(0,0,0,$value->date,2)); else if($period == "daily") echo $key; else echo $value->date;?>', <?php echo (($mrr = $value->total / $value->months) && $mrr != 0) ? $mrr : 0; ?>, <?php echo pmpro_getLTV($period, NULL, $mrr ); ?>],
387
- <?php } ?>
388
- <?php endif; ?>
389
- ]);
390
-
391
- var options = {
392
- colors: ['#0099c6', '#dc3912'],
393
- hAxis: {title: '<?php echo $date_function;?>', titleTextStyle: {color: 'black'}, maxAlternation: 1},
394
- vAxis: {color: 'green', titleTextStyle: {color: '#51a351'}},
395
- };
396
-
397
- <?php if ( $type === "signup_v_cancel" ) : // Signups vs. cancellations ?>
398
- var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
399
- <?php elseif ( $type === "mrr_ltv" ) : // MRR & LTV ?>
400
-
401
- <?php
402
- //prefix or suffix?
403
- if(pmpro_getCurrencyPosition() == "right")
404
- $position = "suffix";
405
- else
406
- $position = "prefix";
407
- ?>
408
-
409
- var formatter = new google.visualization.NumberFormat({<?php echo $position;?>: '<?php echo html_entity_decode($pmpro_currency_symbol);?>'});
410
- formatter.format(data, 2);
411
- var formatter = new google.visualization.NumberFormat({<?php echo $position;?>: '<?php echo html_entity_decode($pmpro_currency_symbol);?>'});
412
- formatter.format(data, 1);
413
-
414
- var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
415
- <?php endif; ?>
416
- chart.draw(data, options);
417
- }
418
- </script>
419
-
420
- </form>
421
- <?php
422
- }
423
-
424
-
425
-
426
- /*
427
- Other code required for your reports. This file is loaded every time WP loads with PMPro enabled.
428
- */
429
-
430
- //get signups
431
- function pmpro_getSignups($period = false, $levels = 'all')
432
- {
433
- //check for a transient
434
- $cache = get_transient( 'pmpro_report_memberships_signups' );
435
- if( ! empty( $cache ) && ! empty( $cache[$period] ) && ! empty( $cache[$period][$levels] ) )
436
- return $cache[$period][$levels];
437
-
438
- //a sale is an order with status = success
439
- if( $period == 'today' )
440
- $startdate = date(' Y-m-d' );
441
- elseif( $period == 'this month')
442
- $startdate = date( 'Y-m' ) . '-01';
443
- elseif( $period == 'this year')
444
- $startdate = date( 'Y' ) . '-01-01';
445
- else
446
- $startdate = '';
447
-
448
-
449
- //build query
450
- global $wpdb;
451
-
452
- $sqlQuery = "SELECT COUNT(DISTINCT user_id) FROM $wpdb->pmpro_memberships_users WHERE startdate >= '" . $startdate . "' ";
453
-
454
- //restrict by level
455
- if(!empty($levels) && $levels != 'all')
456
- $sqlQuery .= "AND membership_id IN(" . $levels . ") ";
457
-
458
- $signups = $wpdb->get_var($sqlQuery);
459
-
460
- //save in cache
461
- if(!empty($cache) && !empty($cache[$period]))
462
- $cache[$period][$levels] = $signups;
463
- elseif(!empty($cache))
464
- $cache[$period] = array($levels => $signups);
465
- else
466
- $cache = array($period => array($levels => $signups));
467
-
468
- set_transient("pmpro_report_memberships_signups", $cache, 3600*24);
469
-
470
- return $signups;
471
- }
472
-
473
- //get cancellations
474
- function pmpro_getCancellations($period = false, $levels = 'all')
475
- {
476
- //check for a transient
477
- $cache = get_transient( 'pmpro_report_memberships_cancellations' );
478
- if( ! empty( $cache ) && ! empty( $cache[$period] ) && ! empty( $cache[$period][$levels] ) )
479
- return $cache[$period][$levels];
480
-
481
- //figure out start date
482
- if( $period == 'today' )
483
- $startdate = date(' Y-m-d' );
484
- elseif( $period == 'this month')
485
- $startdate = date( 'Y-m' ) . '-01';
486
- elseif( $period == 'this year')
487
- $startdate = date( 'Y' ) . '-01-01';
488
- else
489
- $startdate = '';
490
-
491
- $startdate_plus_one = strtotime( $startdate . + ' + 1 day', current_time("timestamp") );
492
-
493
- /*
494
- build query.
495
- cancellations are marked in the memberships users table with status = 'inactive'
496
- we try to ignore cancellations when the user gets a new level with 24 hours (probably an upgrade or downgrade)
497
- */
498
- global $wpdb;
499
-
500
- //$sqlQuery = "SELECT mu1.user_id, mu2.user_id FROM $wpdb->pmpro_memberships_users mu1 LEFT JOIN $wpdb->pmpro_memberships_users mu2 ON mu1.user_id = mu2.user_id AND mu2.status = 'inactive' AND mu2.startdate > mu1.startdate";
501
- $sqlQuery = "SELECT COUNT(mu1.id)
502
- FROM $wpdb->pmpro_memberships_users mu1
503
- LEFT JOIN $wpdb->pmpro_memberships_users mu2 ON mu1.user_id = mu2.user_id AND
504
- mu2.modified > mu1.enddate AND
505
- DATE_ADD(mu1.modified, INTERVAL 1 DAY) > mu2.startdate
506
- WHERE mu1.status = 'inactive'
507
- AND mu2.id IS NULL
508
- AND mu1.startdate >= '" . $startdate . "' ";
509
-
510
- //restrict by level
511
- if(!empty($levels) && $levels != 'all')
512
- $sqlQuery .= "AND membership_id IN(" . $levels . ") ";
513
-
514
- $cancellations = $wpdb->get_var($sqlQuery);
515
-
516
- //save in cache
517
- if(!empty($cache) && !empty($cache[$period]) && is_array($cache[$period]))
518
- $cache[$period][$levels] = $cancellations;
519
- elseif(!empty($cache))
520
- $cache[$period] = array($levels => $cancellations);
521
- else
522
- $cache = array($period => array($levels => $cancellations));
523
-
524
- set_transient("pmpro_report_memberships_cancellations", $cache, 3600*24);
525
-
526
- return $cancellations;
527
- }
528
-
529
- //get MRR
530
- function pmpro_getMRR($period, $levels = 'all')
531
- {
532
- //check for a transient
533
- //$cache = get_transient("pmpro_report_mrr");
534
- if(!empty($cache) && !empty($cache[$period]) && !empty($cache[$period][$levels]))
535
- return $cache[$period][$levels];
536
-
537
- //a sale is an order with status NOT IN refunded, review, token, error
538
- if($period == "this month")
539
- $startdate = date("Y-m") . "-01";
540
- elseif($period == "this year")
541
- $startdate = date("Y") . "-01-01";
542
- else
543
- $startdate = "";
544
-
545
- $gateway_environment = pmpro_getOption("gateway_environment");
546
-
547
- //build query
548
- global $wpdb;
549
- // Get total revenue
550
- $sqlQuery = "SELECT SUM(total) FROM $wpdb->pmpro_membership_orders WHERE status NOT IN('refunded', 'review', 'token', 'error') AND timestamp >= '" . $startdate . "' AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
551
-
552
- //restrict by level
553
- if(!empty($levels) && $levels != 'all') {
554
- $sqlQuery .= "AND membership_id IN(" . $levels . ") ";
555
- }
556
-
557
- $revenue = $wpdb->get_var($sqlQuery);
558
-
559
- //when was the first order
560
- $first_order_timestamp = $wpdb->get_var("SELECT UNIX_TIMESTAMP(`timestamp`) FROM $wpdb->pmpro_membership_orders WHERE `timestamp` IS NOT NULL AND `timestamp` > '0000-00-00 00:00:00' ORDER BY `timestamp` LIMIT 1");
561
-
562
- //if we don't have a timestamp, we can't do this
563
- if(empty($first_order_timestamp))
564
- return false;
565
-
566
- //how many months ago was the first order
567
- $months = $wpdb->get_var("SELECT PERIOD_DIFF('" . date("Ym") . "', '" . date("Ym", $first_order_timestamp) . "')");
568
-
569
- /* this works in PHP 5.3+ without using MySQL to get the diff
570
- $date1 = new DateTime(date("Y-m-d", $first_order_timestamp));
571
- $date2 = new DateTime(date("Y-m-d"));
572
- $interval = $date1->diff($date2);
573
- $years = intval($interval->format('%y'));
574
- $months = $years*12 + intval($interval->format('%m'));
575
- */
576
-
577
- if($months > 0)
578
- $mrr = $revenue / $months;
579
- else
580
- $mrr = 0;
581
-
582
- //save in cache
583
- if(!empty($cache) && !empty($cache[$period]))
584
- $cache[$period][$levels] = $mrr;
585
- elseif(!empty($cache))
586
- $cache[$period] = array($levels => $mrr);
587
- else
588
- $cache = array($period => array($levels => $mrr));
589
-
590
- set_transient("pmpro_report_mrr", $cache, 3600*24);
591
-
592
- return $mrr;
593
- }
594
-
595
- //get Cancellation Rate
596
- function pmpro_getCancellationRate($period, $levels = 'all')
597
- {
598
- //check for a transient
599
- $cache = get_transient("pmpro_report_cancellation_rate");
600
- if(!empty($cache) && !empty($cache[$period]) && !empty($cache[$period][$levels]))
601
- return $cache[$period][$levels];
602
-
603
- $signups = pmpro_getSignups($period, $levels);
604
- $cancellations = pmpro_getCancellations($period, $levels);
605
-
606
- if(empty($signups))
607
- return false;
608
-
609
- $rate = number_format(($cancellations / $signups)*100, 2);
610
-
611
- //save in cache
612
- if(!empty($cache) && !empty($cache[$period]))
613
- $cache[$period][$levels] = $rate;
614
- elseif(!empty($cache))
615
- $cache[$period] = array($levels => $rate);
616
- else
617
- $cache = array($period => array($levels => $rate));
618
-
619
- set_transient("pmpro_report_cancellation_rate", $cache, 3600*24);
620
-
621
- return $rate;
622
- }
623
-
624
- //get LTV
625
- function pmpro_getLTV($period, $levels = 'all', $mrr = NULL, $signups = NULL, $cancellation_rate = NULL)
626
- {
627
- if(empty($mrr))
628
- $mrr = pmpro_getMRR($period, $levels);
629
- if(empty($signups))
630
- $signups = pmpro_getSignups($period, $levels);
631
- if(empty($cancellation_rate))
632
- $cancellation_rate = pmpro_getCancellationRate($period, $levels);
633
-
634
- //average monthly spend
635
- if(empty($signups))
636
- return false;
637
-
638
- if($signups > 0)
639
- $ams = $mrr / $signups;
640
- else
641
- $ams = 0;
642
-
643
- if($cancellation_rate > 0)
644
- $ltv = $ams * (1/$cancellation_rate);
645
- else
646
- $ltv = $ams;
647
-
648
- return $ltv;
649
- }
650
-
651
- //delete transients when an order goes through
652
- function pmpro_report_memberships_delete_transients()
653
- {
654
- delete_transient("pmpro_report_mrr");
655
- delete_transient("pmpro_report_cancellation_rate");
656
- delete_transient("pmpro_report_memberships_cancellations");
657
- delete_transient("pmpro_report_memberships_signups");
658
- }
659
- add_action("pmpro_after_checkout", "pmpro_report_memberships_delete_transients");
660
- add_action("pmpro_updated_order", "pmpro_report_memberships_delete_transients");
1
+ <?php
2
+ /*
3
+ PMPro Report
4
+ Title: Membership Stats
5
+ Slug: memberships
6
+
7
+ For each report, add a line like:
8
+ global $pmpro_reports;
9
+ $pmpro_reports['slug'] = 'Title';
10
+
11
+ For each report, also write two functions:
12
+ * pmpro_report_{slug}_widget() to show up on the report homepage.
13
+ * pmpro_report_{slug}_page() to show up when users click on the report page widget.
14
+ */
15
+
16
+ global $pmpro_reports;
17
+
18
+ $pmpro_reports['memberships'] = __('Membership Stats', 'pmpro');
19
+
20
+ //queue Google Visualization JS on report page
21
+ function pmpro_report_memberships_init() {
22
+ if(is_admin() && isset($_REQUEST['report']) && $_REQUEST['report'] == "memberships" && isset($_REQUEST['page']) && $_REQUEST['page'] == "pmpro-reports")
23
+ wp_enqueue_script("jsapi", "https://www.google.com/jsapi");
24
+ }
25
+ add_action( 'init', 'pmpro_report_memberships_init' );
26
+
27
+
28
+ //widget
29
+ function pmpro_report_memberships_widget() {
30
+ global $wpdb, $pmpro_currency_symbol;
31
+ ?>
32
+ <style type="text/css">
33
+ #pmpro_report_memberships .section-label {
34
+ margin: 15px 0;
35
+ font-size: 18px;
36
+ text-align: left;
37
+ display: block;
38
+ }
39
+
40
+ #pmpro_report_memberships .section-label:first-child {
41
+ margin-top: 0;
42
+ }
43
+
44
+ #pmpro_report_memberships div {text-align: center;}
45
+ #pmpro_report_memberships em {display: block; font-style: normal; font-size: 2em; margin: 5px; line-height: 26px;}
46
+ </style>
47
+ <span id="pmpro_report_memberships">
48
+ <label class="section-label"><?php _e('Signups', 'pmpro');?>:</label>
49
+ <div style="width: 25%; float: left;">
50
+ <label><?php _e('All Time', 'pmpro');?></label>
51
+ <em><?php echo pmpro_getSignups( 'all time' ); ?></em>
52
+ </div>
53
+ <div style="width: 25%; float: left;">
54
+ <label><?php _e('This Year', 'pmpro');?></label>
55
+ <em><?php echo pmpro_getSignups( 'this year' ); ?></em>
56
+ </div>
57
+ <div style="width: 25%; float: left;">
58
+ <label><?php _e('This Month', 'pmpro');?></label>
59
+ <em><?php echo pmpro_getSignups( 'this month' ); ?></em>
60
+ </div>
61
+ <div style="width: 25%; float: left;">
62
+ <label><?php _e('Today', 'pmpro');?></label>
63
+ <em><?php echo pmpro_getSignups( 'today' ); ?></em>
64
+ </div>
65
+ <div class="clear"></div>
66
+
67
+ <label class="section-label"><?php _e('Cancellations', 'pmpro');?>:</label>
68
+ <div style="width: 25%; float: left;">
69
+ <label><?php _e('All Time', 'pmpro');?></label>
70
+ <em><?php echo pmpro_getCancellations( 'all time' ); ?></em>
71
+ </div>
72
+ <div style="width: 25%; float: left;">
73
+ <label><?php _e('This Year', 'pmpro');?></label>
74
+ <em><?php echo pmpro_getCancellations( 'this year' ); ?></em>
75
+ </div>
76
+ <div style="width: 25%; float: left;">
77
+ <label><?php _e('This Month', 'pmpro');?></label>
78
+ <em><?php echo pmpro_getCancellations( 'this month' ); ?></em>
79
+ </div>
80
+ <div style="width: 25%; float: left;">
81
+ <label><?php _e('Today', 'pmpro');?></label>
82
+ <em><?php echo pmpro_getCancellations( 'today' ); ?></em>
83
+ </div>
84
+ <div class="clear"></div>
85
+
86
+ <label class="section-label"><?php _e('Other Stats', 'pmpro');?>:</label>
87
+ <div style="width: 33%; float: left;">
88
+ <label><?php _e('Monthly Recurring Revenue (MRR)', 'pmpro');?></label>
89
+ <em><?php echo pmpro_formatPrice(pmpro_getMRR( 'all time' )); ?></em>
90
+ </div>
91
+ <div style="width: 33%; float: left;">
92
+ <label><?php _e('Cancellation Rate', 'pmpro');?></label>
93
+ <em><?php echo pmpro_getCancellationRate('all time' ); ?>%</em>
94
+ </div>
95
+ <div style="width: 33%; float: left;">
96
+ <label><?php _e('Lifetime Value (LTV)', 'pmpro');?></label>
97
+ <em><?php echo pmpro_formatPrice(pmpro_getLTV('all time')); ?></em>
98
+ </div>
99
+ <div class="clear"></div>
100
+ </span>
101
+ <?php
102
+ }
103
+
104
+ function pmpro_report_memberships_page()
105
+ {
106
+ global $wpdb, $pmpro_currency_symbol;
107
+
108
+ //get values from form
109
+ if(isset($_REQUEST['type']))
110
+ $type = sanitize_text_field($_REQUEST['type']);
111
+ else
112
+ $type = "signup_v_cancel";
113
+
114
+ if(isset($_REQUEST['period']))
115
+ $period = sanitize_text_field($_REQUEST['period']);
116
+ else
117
+ $period = "monthly";
118
+
119
+ if(isset($_REQUEST['month']))
120
+ $month = intval($_REQUEST['month']);
121
+ else
122
+ $month = date("n");
123
+
124
+ $thisyear = date("Y");
125
+ if(isset($_REQUEST['year']))
126
+ $year = intval($_REQUEST['year']);
127
+ else
128
+ $year = date("Y");
129
+
130
+ if(isset($_REQUEST['level']))
131
+ $l = intval($_REQUEST['level']);
132
+ else
133
+ $l = "";
134
+
135
+ //calculate start date and how to group dates returned from DB
136
+ if($period == "daily")
137
+ {
138
+ $startdate = $year . '-' . substr("0" . $month, strlen($month) - 1, 2) . '-01';
139
+ $enddate = $year . '-' . substr("0" . $month, strlen($month) - 1, 2) . '-31';
140
+ $date_function = 'DAY';
141
+ }
142
+ elseif($period == "monthly")
143
+ {
144
+ $startdate = $year . '-01-01';
145
+ $enddate = strval(intval($year)+1) . '-01-01';
146
+ $date_function = 'MONTH';
147
+ }
148
+ elseif($period == "annual")
149
+ {
150
+ $startdate = '1960-01-01'; //all time
151
+ $date_function = 'YEAR';
152
+ }
153
+
154
+ //testing or live data
155
+ $gateway_environment = pmpro_getOption("gateway_environment");
156
+
157
+ //get data
158
+ if ( $type === "signup_v_cancel" ) {
159
+ $sqlQuery = "SELECT $date_function(startdate) as date, COUNT(DISTINCT user_id) as signups
160
+ FROM $wpdb->pmpro_memberships_users WHERE startdate >= '" . $startdate . "' ";
161
+
162
+ if(!empty($enddate))
163
+ $sqlQuery .= "AND startdate < '" . $enddate . "' ";
164
+ }
165
+ if ( $type === "mrr_ltv" ) {
166
+ // Get total revenue, number of months in system, and date
167
+ if ( $period == 'annual' )
168
+ $sqlQuery = "SELECT SUM(total) as total, COUNT(DISTINCT MONTH(timestamp)) as months, $date_function(timestamp) as date
169
+ FROM $wpdb->pmpro_membership_orders WHERE status NOT IN('refunded', 'review', 'token')
170
+ AND timestamp >= '" . $startdate . "' AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
171
+
172
+ if ( $period == 'monthly' )
173
+ $sqlQuery = "SELECT SUM(total) as total, $date_function(timestamp) as date
174
+ FROM $wpdb->pmpro_membership_orders WHERE status NOT IN('refunded', 'review', 'token')
175
+ AND timestamp >= '" . $startdate . "' AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
176
+
177
+ if(!empty($enddate))
178
+ $sqlQuery .= "AND timestamp < '" . $enddate . "' ";
179
+ }
180
+
181
+ if(!empty($l))
182
+ $sqlQuery .= "AND membership_id IN(" . $l . ") ";
183
+
184
+ $sqlQuery .= " GROUP BY date ORDER BY date ";
185
+
186
+ $dates = $wpdb->get_results($sqlQuery);
187
+
188
+ //fill in blanks in dates
189
+ $cols = array();
190
+ if($period == "daily")
191
+ {
192
+ $lastday = date("t", strtotime($startdate, current_time("timestamp")));
193
+
194
+ for($i = 1; $i <= $lastday; $i++)
195
+ {
196
+ // Signups vs. Cancellations
197
+ if ( $type === "signup_v_cancel" ) {
198
+ $cols[$i] = new stdClass();
199
+ $cols[$i]->signups = 0;
200
+ foreach($dates as $date)
201
+ {
202
+ if( $date->date == $i ) {
203
+ $cols[$i]->signups = $date->signups;
204
+ }
205
+ }
206
+ }
207
+ }
208
+ }
209
+ elseif($period == "monthly")
210
+ {
211
+ for($i = 1; $i < 13; $i++)
212
+ {
213
+ // Signups vs. Cancellations
214
+ if ( $type === "signup_v_cancel" ) {
215
+ $cols[$i] = new stdClass();
216
+ $cols[$i]->date = $i;
217
+ $cols[$i]->signups = 0;
218
+ foreach($dates as $date)
219
+ {
220
+ if( $date->date == $i ) {
221
+ $cols[$i]->date = $date->date;
222
+ $cols[$i]->signups = $date->signups;
223
+ }
224
+ }
225
+ }
226
+
227
+ // MRR & LTV
228
+ if ( $type === "mrr_ltv" ) {
229
+ $cols[$i] = new stdClass();
230
+ $cols[$i]->date = $i;
231
+ $cols[$i]->months = 1;
232
+ foreach($dates as $date)
233
+ {
234
+ if( $date->date == $i ) {
235
+ $cols[$i]->total = $date->total;
236
+ }
237
+ }
238
+ }
239
+ }
240
+ }
241
+ elseif($period == "annual") //annual
242
+ {
243
+ }
244
+
245
+ $dates = ( ! empty( $cols ) ) ? $cols : $dates;
246
+
247
+ // Signups vs. cancellations
248
+ if ( $type === "signup_v_cancel" )
249
+ {
250
+ $sqlQuery = "SELECT $date_function(mu1.modified) as date, COUNT(DISTINCT mu1.user_id) as cancellations
251
+ FROM $wpdb->pmpro_memberships_users mu1
252
+ LEFT JOIN $wpdb->pmpro_memberships_users mu2 ON mu1.user_id = mu2.user_id AND
253
+ mu2.modified > mu1.enddate AND
254
+ DATE_ADD(mu1.modified, INTERVAL 1 DAY) > mu2.startdate
255
+ WHERE mu1.status = 'inactive'
256
+ AND mu2.id IS NULL
257
+ AND mu1.startdate >= '" . $startdate . "'
258
+ AND mu1.startdate < '" . $enddate . "' ";
259
+
260
+ //restrict by level
261
+ if(!empty($l))
262
+ $sqlQuery .= "AND membership_id IN(" . $l . ") ";
263
+
264
+ $sqlQuery .= " GROUP BY date ORDER BY date ";
265
+
266
+ $cdates = $wpdb->get_results($sqlQuery, OBJECT_K);
267
+
268
+ foreach( $dates as &$date )
269
+ {
270
+ if(!empty($cdates[$date->date]))
271
+ $date->cancellations = $cdates[$date->date]->cancellations;
272
+ else
273
+ $date->cancellations = 0;
274
+ }
275
+ }
276
+
277
+ // MRR & LTV
278
+ if ( $type === "mrr_ltv" && count( $dates ) === 1 ) {
279
+ $dummy_date = new stdClass();
280
+ $dummy_date->total = 0;
281
+ $dummy_date->months = 0;
282
+ $dummy_date->date = $dates[0]->date - 1;
283
+ array_unshift( $dates, $dummy_date ); // Add to beginning
284
+ }
285
+ ?>
286
+ <form id="posts-filter" method="get" action="">
287
+ <h2>
288
+ <?php _e('Membership Stats', 'pmpro');?>
289
+ </h2>
290
+ <ul class="subsubsub">
291
+ <li>
292
+ <?php _ex('Show', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?>
293
+ <select id="period" name="period">
294
+ <option value="daily" <?php selected($period, "daily");?>><?php _e('Daily', 'pmpro');?></option>
295
+ <option value="monthly" <?php selected($period, "monthly");?>><?php _e('Monthly', 'pmpro');?></option>
296
+ <option value="annual" <?php selected($period, "annual");?>><?php _e('Annual', 'pmpro');?></option>
297
+ </select>
298
+ <select id="type" name="type">
299
+ <option value="signup_v_cancel" <?php selected($type, "signup_v_cancel");?>><?php _e('Signups vs. Cancellations', 'pmpro');?></option>
300
+ <?php /*
301
+ <option value="mrr_ltv" <?php selected($type, "mrr_ltv");?>><?php _e('MRR & LTV', 'pmpro');?></option>
302
+ */ ?>
303
+ </select>
304
+ <span id="for"><?php _ex('for', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?></span>
305
+ <select id="month" name="month">
306
+ <?php for($i = 1; $i < 13; $i++) { ?>
307
+ <option value="<?php echo $i;?>" <?php selected($month, $i);?>><?php echo date("F", mktime(0, 0, 0, $i, 2));?></option>
308
+ <?php } ?>
309
+ </select>
310
+ <select id="year" name="year">
311
+ <?php for($i = $thisyear; $i > 2007; $i--) { ?>
312
+ <option value="<?php echo $i;?>" <?php selected($year, $i);?>><?php echo $i;?></option>
313
+ <?php } ?>
314
+ </select>
315
+ <span id="for"><?php _ex('for', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?></span>
316
+ <select name="level">
317
+ <option value="" <?php if(!$l) { ?>selected="selected"<?php } ?>><?php _e('All Levels', 'pmpro');?></option>
318
+ <?php
319
+ $levels = $wpdb->get_results("SELECT id, name FROM $wpdb->pmpro_membership_levels ORDER BY name");
320
+ foreach($levels as $level)
321
+ {
322
+ ?>
323
+ <option value="<?php echo $level->id?>" <?php if($l == $level->id) { ?>selected="selected"<?php } ?>><?php echo $level->name?></option>
324
+ <?php
325
+ }
326
+ ?>
327
+ </select>
328
+
329
+ <input type="hidden" name="page" value="pmpro-reports" />
330
+ <input type="hidden" name="report" value="memberships" />
331
+ <input type="submit" value="<?php _ex('Generate Report', 'Submit button value.', 'pmpro');?>" />
332
+ </li>
333
+ </ul>
334
+
335
+ <div id="chart_div" style="clear: both; width: 100%; height: 500px;"></div>
336
+
337
+ <script>
338
+ //update month/year when period dropdown is changed
339
+ jQuery(document).ready(function() {
340
+ jQuery('#period').change(function() {
341
+ pmpro_ShowMonthOrYear();
342
+ });
343
+ });
344
+
345
+ function pmpro_ShowMonthOrYear()
346
+ {
347
+ var period = jQuery('#period').val();
348
+ if(period == 'daily')
349
+ {
350
+ jQuery('#for').show();
351
+ jQuery('#month').show();
352
+ jQuery('#year').show();
353
+ }
354
+ else if(period == 'monthly')
355
+ {
356
+ jQuery('#for').show();
357
+ jQuery('#month').hide();
358
+ jQuery('#year').show();
359
+ }
360
+ else
361
+ {
362
+ jQuery('#for').hide();
363
+ jQuery('#month').hide();
364
+ jQuery('#year').hide();
365
+ }
366
+ }
367
+
368
+ pmpro_ShowMonthOrYear();
369
+
370
+ //draw the chart
371
+ google.load("visualization", "1", {packages:["corechart"]});
372
+ google.setOnLoadCallback(drawChart);
373
+ function drawChart() {
374
+
375
+ var data = google.visualization.arrayToDataTable([
376
+ <?php if ( $type === "signup_v_cancel" ) : // Signups vs. cancellations ?>
377
+ ['<?php echo $date_function;?>', 'Signups', 'Cancellations'],
378
+ <?php foreach($dates as $key => $value) { ?>
379
+ ['<?php if($period == "monthly") echo date("M", mktime(0,0,0,$value->date,2)); else if($period == "daily") echo $key; else echo $value->date;?>', <?php echo $value->signups; ?>, <?php echo $value->cancellations; ?>],
380
+ <?php } ?>
381
+ <?php endif; ?>
382
+
383
+ <?php if ( $type === "mrr_ltv" ) : // Signups vs. cancellations ?>
384
+ ['<?php echo $date_function;?>', 'MRR', 'LTV'],
385
+ <?php foreach($dates as $key => $value) { ?>
386
+ ['<?php if($period == "monthly") echo date("M", mktime(0,0,0,$value->date,2)); else if($period == "daily") echo $key; else echo $value->date;?>', <?php echo (($mrr = $value->total / $value->months) && $mrr != 0) ? $mrr : 0; ?>, <?php echo pmpro_getLTV($period, NULL, $mrr ); ?>],
387
+ <?php } ?>
388
+ <?php endif; ?>
389
+ ]);
390
+
391
+ var options = {
392
+ colors: ['#0099c6', '#dc3912'],
393
+ hAxis: {title: '<?php echo $date_function;?>', titleTextStyle: {color: 'black'}, maxAlternation: 1},
394
+ vAxis: {color: 'green', titleTextStyle: {color: '#51a351'}},
395
+ };
396
+
397
+ <?php if ( $type === "signup_v_cancel" ) : // Signups vs. cancellations ?>
398
+ var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
399
+ <?php elseif ( $type === "mrr_ltv" ) : // MRR & LTV ?>
400
+
401
+ <?php
402
+ //prefix or suffix?
403
+ if(pmpro_getCurrencyPosition() == "right")
404
+ $position = "suffix";
405
+ else
406
+ $position = "prefix";
407
+ ?>
408
+
409
+ var formatter = new google.visualization.NumberFormat({<?php echo $position;?>: '<?php echo html_entity_decode($pmpro_currency_symbol);?>'});
410
+ formatter.format(data, 2);
411
+ var formatter = new google.visualization.NumberFormat({<?php echo $position;?>: '<?php echo html_entity_decode($pmpro_currency_symbol);?>'});
412
+ formatter.format(data, 1);
413
+
414
+ var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
415
+ <?php endif; ?>
416
+ chart.draw(data, options);
417
+ }
418
+ </script>
419
+
420
+ </form>
421
+ <?php
422
+ }
423
+
424
+
425
+
426
+ /*
427
+ Other code required for your reports. This file is loaded every time WP loads with PMPro enabled.
428
+ */
429
+
430
+ //get signups
431
+ function pmpro_getSignups($period = false, $levels = 'all')
432
+ {
433
+ //check for a transient
434
+ $cache = get_transient( 'pmpro_report_memberships_signups' );
435
+ if( ! empty( $cache ) && ! empty( $cache[$period] ) && ! empty( $cache[$period][$levels] ) )
436
+ return $cache[$period][$levels];
437
+
438
+ //a sale is an order with status = success
439
+ if( $period == 'today' )
440
+ $startdate = date(' Y-m-d' );
441
+ elseif( $period == 'this month')
442
+ $startdate = date( 'Y-m' ) . '-01';
443
+ elseif( $period == 'this year')
444
+ $startdate = date( 'Y' ) . '-01-01';
445
+ else
446
+ $startdate = '';
447
+
448
+
449
+ //build query
450
+ global $wpdb;
451
+
452
+ $sqlQuery = "SELECT COUNT(DISTINCT user_id) FROM $wpdb->pmpro_memberships_users WHERE startdate >= '" . $startdate . "' ";
453
+
454
+ //restrict by level
455
+ if(!empty($levels) && $levels != 'all')
456
+ $sqlQuery .= "AND membership_id IN(" . $levels . ") ";
457
+
458
+ $signups = $wpdb->get_var($sqlQuery);
459
+
460
+ //save in cache
461
+ if(!empty($cache) && !empty($cache[$period]))
462
+ $cache[$period][$levels] = $signups;
463
+ elseif(!empty($cache))
464
+ $cache[$period] = array($levels => $signups);
465
+ else
466
+ $cache = array($period => array($levels => $signups));
467
+
468
+ set_transient("pmpro_report_memberships_signups", $cache, 3600*24);
469
+
470
+ return $signups;
471
+ }
472
+
473
+ //get cancellations
474
+ function pmpro_getCancellations($period = false, $levels = 'all')
475
+ {
476
+ //check for a transient
477
+ $cache = get_transient( 'pmpro_report_memberships_cancellations' );
478
+ if( ! empty( $cache ) && ! empty( $cache[$period] ) && ! empty( $cache[$period][$levels] ) )
479
+ return $cache[$period][$levels];
480
+
481
+ //figure out start date
482
+ if( $period == 'today' )
483
+ $startdate = date(' Y-m-d' );
484
+ elseif( $period == 'this month')
485
+ $startdate = date( 'Y-m' ) . '-01';
486
+ elseif( $period == 'this year')
487
+ $startdate = date( 'Y' ) . '-01-01';
488
+ else
489
+ $startdate = '';
490
+
491
+ $startdate_plus_one = strtotime( $startdate . + ' + 1 day', current_time("timestamp") );
492
+
493
+ /*
494
+ build query.
495
+ cancellations are marked in the memberships users table with status = 'inactive'
496
+ we try to ignore cancellations when the user gets a new level with 24 hours (probably an upgrade or downgrade)
497
+ */
498
+ global $wpdb;
499
+
500
+ //$sqlQuery = "SELECT mu1.user_id, mu2.user_id FROM $wpdb->pmpro_memberships_users mu1 LEFT JOIN $wpdb->pmpro_memberships_users mu2 ON mu1.user_id = mu2.user_id AND mu2.status = 'inactive' AND mu2.startdate > mu1.startdate";
501
+ $sqlQuery = "SELECT COUNT(mu1.id)
502
+ FROM $wpdb->pmpro_memberships_users mu1
503
+ LEFT JOIN $wpdb->pmpro_memberships_users mu2 ON mu1.user_id = mu2.user_id AND
504
+ mu2.modified > mu1.enddate AND
505
+ DATE_ADD(mu1.modified, INTERVAL 1 DAY) > mu2.startdate
506
+ WHERE mu1.status = 'inactive'
507
+ AND mu2.id IS NULL
508
+ AND mu1.startdate >= '" . $startdate . "' ";
509
+
510
+ //restrict by level
511
+ if(!empty($levels) && $levels != 'all')
512
+ $sqlQuery .= "AND membership_id IN(" . $levels . ") ";
513
+
514
+ $cancellations = $wpdb->get_var($sqlQuery);
515
+
516
+ //save in cache
517
+ if(!empty($cache) && !empty($cache[$period]) && is_array($cache[$period]))
518
+ $cache[$period][$levels] = $cancellations;
519
+ elseif(!empty($cache))
520
+ $cache[$period] = array($levels => $cancellations);
521
+ else
522
+ $cache = array($period => array($levels => $cancellations));
523
+
524
+ set_transient("pmpro_report_memberships_cancellations", $cache, 3600*24);
525
+
526
+ return $cancellations;
527
+ }
528
+
529
+ //get MRR
530
+ function pmpro_getMRR($period, $levels = 'all')
531
+ {
532
+ //check for a transient
533
+ //$cache = get_transient("pmpro_report_mrr");
534
+ if(!empty($cache) && !empty($cache[$period]) && !empty($cache[$period][$levels]))
535
+ return $cache[$period][$levels];
536
+
537
+ //a sale is an order with status NOT IN refunded, review, token, error
538
+ if($period == "this month")
539
+ $startdate = date("Y-m") . "-01";
540
+ elseif($period == "this year")
541
+ $startdate = date("Y") . "-01-01";
542
+ else
543
+ $startdate = "";
544
+
545
+ $gateway_environment = pmpro_getOption("gateway_environment");
546
+
547
+ //build query
548
+ global $wpdb;
549
+ // Get total revenue
550
+ $sqlQuery = "SELECT SUM(total) FROM $wpdb->pmpro_membership_orders WHERE status NOT IN('refunded', 'review', 'token', 'error') AND timestamp >= '" . $startdate . "' AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
551
+
552
+ //restrict by level
553
+ if(!empty($levels) && $levels != 'all') {
554
+ $sqlQuery .= "AND membership_id IN(" . $levels . ") ";
555
+ }
556
+
557
+ $revenue = $wpdb->get_var($sqlQuery);
558
+
559
+ //when was the first order
560
+ $first_order_timestamp = $wpdb->get_var("SELECT UNIX_TIMESTAMP(`timestamp`) FROM $wpdb->pmpro_membership_orders WHERE `timestamp` IS NOT NULL AND `timestamp` > '0000-00-00 00:00:00' ORDER BY `timestamp` LIMIT 1");
561
+
562
+ //if we don't have a timestamp, we can't do this
563
+ if(empty($first_order_timestamp))
564
+ return false;
565
+
566
+ //how many months ago was the first order
567
+ $months = $wpdb->get_var("SELECT PERIOD_DIFF('" . date("Ym") . "', '" . date("Ym", $first_order_timestamp) . "')");
568
+
569
+ /* this works in PHP 5.3+ without using MySQL to get the diff
570
+ $date1 = new DateTime(date("Y-m-d", $first_order_timestamp));
571
+ $date2 = new DateTime(date("Y-m-d"));
572
+ $interval = $date1->diff($date2);
573
+ $years = intval($interval->format('%y'));
574
+ $months = $years*12 + intval($interval->format('%m'));
575
+ */
576
+
577
+ if($months > 0)
578
+ $mrr = $revenue / $months;
579
+ else
580
+ $mrr = 0;
581
+
582
+ //save in cache
583
+ if(!empty($cache) && !empty($cache[$period]))
584
+ $cache[$period][$levels] = $mrr;
585
+ elseif(!empty($cache))
586
+ $cache[$period] = array($levels => $mrr);
587
+ else
588
+ $cache = array($period => array($levels => $mrr));
589
+
590
+ set_transient("pmpro_report_mrr", $cache, 3600*24);
591
+
592
+ return $mrr;
593
+ }
594
+
595
+ //get Cancellation Rate
596
+ function pmpro_getCancellationRate($period, $levels = 'all')
597
+ {
598
+ //check for a transient
599
+ $cache = get_transient("pmpro_report_cancellation_rate");
600
+ if(!empty($cache) && !empty($cache[$period]) && !empty($cache[$period][$levels]))
601
+ return $cache[$period][$levels];
602
+
603
+ $signups = pmpro_getSignups($period, $levels);
604
+ $cancellations = pmpro_getCancellations($period, $levels);
605
+
606
+ if(empty($signups))
607
+ return false;
608
+
609
+ $rate = number_format(($cancellations / $signups)*100, 2);
610
+
611
+ //save in cache
612
+ if(!empty($cache) && !empty($cache[$period]))
613
+ $cache[$period][$levels] = $rate;
614
+ elseif(!empty($cache))
615
+ $cache[$period] = array($levels => $rate);
616
+ else
617
+ $cache = array($period => array($levels => $rate));
618
+
619
+ set_transient("pmpro_report_cancellation_rate", $cache, 3600*24);
620
+
621
+ return $rate;
622
+ }
623
+
624
+ //get LTV
625
+ function pmpro_getLTV($period, $levels = 'all', $mrr = NULL, $signups = NULL, $cancellation_rate = NULL)
626
+ {
627
+ if(empty($mrr))
628
+ $mrr = pmpro_getMRR($period, $levels);
629
+ if(empty($signups))
630
+ $signups = pmpro_getSignups($period, $levels);
631
+ if(empty($cancellation_rate))
632
+ $cancellation_rate = pmpro_getCancellationRate($period, $levels);
633
+
634
+ //average monthly spend
635
+ if(empty($signups))
636
+ return false;
637
+
638
+ if($signups > 0)
639
+ $ams = $mrr / $signups;
640
+ else
641
+ $ams = 0;
642
+
643
+ if($cancellation_rate > 0)
644
+ $ltv = $ams * (1/$cancellation_rate);
645
+ else
646
+ $ltv = $ams;
647
+
648
+ return $ltv;
649
+ }
650
+
651
+ //delete transients when an order goes through
652
+ function pmpro_report_memberships_delete_transients()
653
+ {
654
+ delete_transient("pmpro_report_mrr");
655
+ delete_transient("pmpro_report_cancellation_rate");
656
+ delete_transient("pmpro_report_memberships_cancellations");
657
+ delete_transient("pmpro_report_memberships_signups");
658
+ }
659
+ add_action("pmpro_after_checkout", "pmpro_report_memberships_delete_transients");
660
+ add_action("pmpro_updated_order", "pmpro_report_memberships_delete_transients");
adminpages/reports/sales.php CHANGED
@@ -1,406 +1,406 @@
1
- <?php
2
- /*
3
- PMPro Report
4
- Title: Sales
5
- Slug: sales
6
-
7
- For each report, add a line like:
8
- global $pmpro_reports;
9
- $pmpro_reports['slug'] = 'Title';
10
-
11
- For each report, also write two functions:
12
- * pmpro_report_{slug}_widget() to show up on the report homepage.
13
- * pmpro_report_{slug}_page() to show up when users click on the report page widget.
14
- */
15
- global $pmpro_reports;
16
- $gateway_environment = pmpro_getOption("gateway_environment");
17
- if($gateway_environment == "sandbox")
18
- $pmpro_reports['sales'] = __('Sales and Revenue (Testing/Sandbox)', 'pmpro');
19
- else
20
- $pmpro_reports['sales'] = __('Sales and Revenue', 'pmpro');
21
-
22
- //queue Google Visualization JS on report page
23
- function pmpro_report_sales_init()
24
- {
25
- if(is_admin() && isset($_REQUEST['report']) && $_REQUEST['report'] == "sales" && isset($_REQUEST['page']) && $_REQUEST['page'] == "pmpro-reports")
26
- {
27
- wp_enqueue_script("jsapi", "https://www.google.com/jsapi");
28
- }
29
- }
30
- add_action("init", "pmpro_report_sales_init");
31
-
32
- //widget
33
- function pmpro_report_sales_widget()
34
- {
35
- global $wpdb;
36
- ?>
37
- <style>
38
- #pmpro_report_sales div {text-align: center;}
39
- #pmpro_report_sales em {display: block; font-style: normal; font-size: 2em; margin: 5px;}
40
- </style>
41
- <span id="#pmpro_report_sales">
42
- <div style="width: 25%; float: left;">
43
- <em><?php echo pmpro_getSales("all time");?></em>
44
- <label>All Time</label>
45
- <em><?php echo pmpro_formatPrice(pmpro_getRevenue("all time"));?></em>
46
- </div>
47
- <div style="width: 25%; float: left;">
48
- <em><?php echo pmpro_getSales("this year");?></em>
49
- <label>This Year</label>
50
- <em><?php echo pmpro_formatPrice(pmpro_getRevenue("this year"));?></em>
51
- </div>
52
- <div style="width: 25%; float: left;">
53
- <em><?php echo pmpro_getSales("this month");?></em>
54
- <label>This Month</label>
55
- <em><?php echo pmpro_formatPrice(pmpro_getRevenue("this month"));?></em>
56
- </div>
57
- <div style="width: 25%; float: left;">
58
- <em><?php echo pmpro_getSales("today");?></em>
59
- <label>Today</label>
60
- <em><?php echo pmpro_formatPrice(pmpro_getRevenue("today"));?></em>
61
- </div>
62
- <div class="clear"></div>
63
- </span>
64
- <?php
65
- }
66
-
67
- function pmpro_report_sales_page()
68
- {
69
- global $wpdb, $pmpro_currency_symbol, $pmpro_currency, $pmpro_currencies;
70
-
71
- //get values from form
72
- if(isset($_REQUEST['type']))
73
- $type = sanitize_text_field($_REQUEST['type']);
74
- else
75
- $type = "revenue";
76
-
77
- if($type == "sales")
78
- $type_function = "COUNT";
79
- else
80
- $type_function = "SUM";
81
-
82
- if(isset($_REQUEST['period']))
83
- $period = sanitize_text_field($_REQUEST['period']);
84
- else
85
- $period = "daily";
86
-
87
- if(isset($_REQUEST['month']))
88
- $month = intval($_REQUEST['month']);
89
- else
90
- $month = date("n");
91
-
92
- $thisyear = date("Y");
93
- if(isset($_REQUEST['year']))
94
- $year = intval($_REQUEST['year']);
95
- else
96
- $year = $thisyear;
97
-
98
- if(isset($_REQUEST['level']))
99
- $l = intval($_REQUEST['level']);
100
- else
101
- $l = "";
102
-
103
- //calculate start date and how to group dates returned from DB
104
- if($period == "daily")
105
- {
106
- $startdate = $year . '-' . substr("0" . $month, strlen($month) - 1, 2) . '-01';
107
- $enddate = $year . '-' . substr("0" . $month, strlen($month) - 1, 2) . '-31';
108
- $date_function = 'DAY';
109
- }
110
- elseif($period == "monthly")
111
- {
112
- $startdate = $year . '-01-01';
113
- $enddate = strval(intval($year)+1) . '-01-01';
114
- $date_function = 'MONTH';
115
- }
116
- else
117
- {
118
- $startdate = '1960-01-01'; //all time
119
- $date_function = 'YEAR';
120
- }
121
-
122
- //testing or live data
123
- $gateway_environment = pmpro_getOption("gateway_environment");
124
-
125
- //get data
126
- $sqlQuery = "SELECT $date_function(timestamp) as date, $type_function(total) as value FROM $wpdb->pmpro_membership_orders WHERE timestamp >= '" . $startdate . "' AND status NOT IN('refunded', 'review', 'token', 'error') AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
127
-
128
- if(!empty($enddate))
129
- $sqlQuery .= "AND timestamp < '" . $enddate . "' ";
130
-
131
- if(!empty($l))
132
- $sqlQuery .= "AND membership_id IN(" . $l . ") ";
133
-
134
- $sqlQuery .= " GROUP BY date ORDER BY date ";
135
-
136
- $dates = $wpdb->get_results($sqlQuery);
137
-
138
- //fill in blanks in dates
139
- $cols = array();
140
- if($period == "daily")
141
- {
142
- $lastday = date("t", strtotime($startdate, current_time("timestamp")));
143
-
144
- for($i = 1; $i <= $lastday; $i++)
145
- {
146
- $cols[$i] = 0;
147
- foreach($dates as $date)
148
- {
149
- if($date->date == $i)
150
- $cols[$i] = $date->value;
151
- }
152
- }
153
- }
154
- elseif($period == "monthly")
155
- {
156
- for($i = 1; $i < 13; $i++)
157
- {
158
- $cols[$i] = 0;
159
- foreach($dates as $date)
160
- {
161
- if($date->date == $i)
162
- $cols[$i] = $date->value;
163
- }
164
- }
165
- }
166
- else //annual
167
- {
168
- //get min and max years
169
- $min = 9999;
170
- $max = 0;
171
- foreach($dates as $date)
172
- {
173
- $min = min($min, $date->date);
174
- $max = max($max, $date->date);
175
- }
176
-
177
- for($i = $min; $i <= $max; $i++)
178
- {
179
- foreach($dates as $date)
180
- {
181
- if($date->date == $i)
182
- $cols[$i] = $date->value;
183
- }
184
- }
185
- }
186
- ?>
187
- <form id="posts-filter" method="get" action="">
188
- <h2>
189
- <?php _e('Sales and Revenue', 'pmpro');?>
190
- </h2>
191
-
192
- <div class="tablenav top">
193
- <?php _ex('Show', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?>
194
- <select id="period" name="period">
195
- <option value="daily" <?php selected($period, "daily");?>><?php _e('Daily', 'pmpro');?></option>
196
- <option value="monthly" <?php selected($period, "monthly");?>><?php _e('Monthly', 'pmpro');?></option>
197
- <option value="annual" <?php selected($period, "annual");?>><?php _e('Annual', 'pmpro');?></option>
198
- </select>
199
- <select name="type">
200
- <option value="revenue" <?php selected($type, "revenue");?>><?php _e('Revenue', 'pmpro');?></option>
201
- <option value="sales" <?php selected($type, "sales");?>><?php _e('Sales', 'pmpro');?></option>
202
- </select>
203
- <span id="for"><?php _ex('for', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?></span>
204
- <select id="month" name="month">
205
- <?php for($i = 1; $i < 13; $i++) { ?>
206
- <option value="<?php echo $i;?>" <?php selected($month, $i);?>><?php echo date("F", mktime(0, 0, 0, $i, 2));?></option>
207
- <?php } ?>
208
- </select>
209
- <select id="year" name="year">
210
- <?php for($i = $thisyear; $i > 2007; $i--) { ?>
211
- <option value="<?php echo $i;?>" <?php selected($year, $i);?>><?php echo $i;?></option>
212
- <?php } ?>
213
- </select>
214
- <span id="for"><?php _ex('for', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?></span>
215
- <select name="level">
216
- <option value="" <?php if(!$l) { ?>selected="selected"<?php } ?>><?php _e('All Levels', 'pmpro');?></option>
217
- <?php
218
- $levels = $wpdb->get_results("SELECT id, name FROM $wpdb->pmpro_membership_levels ORDER BY name");
219
- foreach($levels as $level)
220
- {
221
- ?>
222
- <option value="<?php echo $level->id?>" <?php if($l == $level->id) { ?>selected="selected"<?php } ?>><?php echo $level->name?></option>
223
- <?php
224
- }
225
- ?>
226
- </select>
227
-
228
- <input type="hidden" name="page" value="pmpro-reports" />
229
- <input type="hidden" name="report" value="sales" />
230
- <input type="submit" class="button action" value="<?php _ex('Generate Report', 'Submit button value.', 'pmpro');?>" />
231
- </div>
232
-
233
- <div id="chart_div" style="clear: both; width: 100%; height: 500px;"></div>
234
-
235
- <script>
236
- //update month/year when period dropdown is changed
237
- jQuery(document).ready(function() {
238
- jQuery('#period').change(function() {
239
- pmpro_ShowMonthOrYear();
240
- });
241
- });
242
-
243
- function pmpro_ShowMonthOrYear()
244
- {
245
- var period = jQuery('#period').val();
246
- if(period == 'daily')
247
- {
248
- jQuery('#for').show();
249
- jQuery('#month').show();
250
- jQuery('#year').show();
251
- }
252
- else if(period == 'monthly')
253
- {
254
- jQuery('#for').show();
255
- jQuery('#month').hide();
256
- jQuery('#year').show();
257
- }
258
- else
259
- {
260
- jQuery('#for').hide();
261
- jQuery('#month').hide();
262
- jQuery('#year').hide();
263
- }
264
- }
265
-
266
- pmpro_ShowMonthOrYear();
267
-
268
- //draw the chart
269
- google.load("visualization", "1", {packages:["corechart"]});
270
- google.setOnLoadCallback(drawChart);
271
- function drawChart() {
272
-
273
- var data = google.visualization.arrayToDataTable([
274
- ['<?php echo $date_function;?>', '<?php echo ucwords($type);?>'],
275
- <?php foreach($cols as $date => $value) { ?>
276
- ['<?php if($period == "monthly") echo date("M", mktime(0,0,0,$date,2)); else echo $date;?>', <?php echo $value;?>],
277
- <?php } ?>
278
- ]);
279
-
280
- var options = {
281
- colors: ['#51a351', '#387038'],
282
- hAxis: {title: '<?php echo $date_function;?>', titleTextStyle: {color: 'black'}, maxAlternation: 1},
283
- vAxis: {color: 'green', titleTextStyle: {color: '#51a351'}},
284
- };
285
-
286
- <?php
287
- if($type != "sales")
288
- {
289
- if(pmpro_getCurrencyPosition() == "right")
290
- $position = "suffix";
291
- else
292
- $position = "prefix";
293
- ?>
294
- var formatter = new google.visualization.NumberFormat({<?php echo $position;?>: '<?php echo html_entity_decode($pmpro_currency_symbol);?>'});
295
- formatter.format(data, 1);
296
- <?php
297
- }
298
- ?>
299
-
300
- var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
301
- chart.draw(data, options);
302
- }
303
- </script>
304
-
305
- </form>
306
- <?php
307
- }
308
-
309
- /*
310
- Other code required for your reports. This file is loaded every time WP loads with PMPro enabled.
311
- */
312
-
313
- //get sales
314
- function pmpro_getSales($period, $levels = NULL)
315
- {
316
- //check for a transient
317
- $cache = get_transient("pmpro_report_sales");
318
- if(!empty($cache) && !empty($cache[$period]) && !empty($cache[$period][$levels]))
319
- return $cache[$period][$levels];
320
-
321
- //a sale is an order with status NOT IN('refunded', 'review', 'token', 'error')
322
- if($period == "today")
323
- $startdate = date("Y-m-d");
324
- elseif($period == "this month")
325
- $startdate = date("Y-m") . "-01";
326
- elseif($period == "this year")
327
- $startdate = date("Y") . "-01-01";
328
- else
329
- $startdate = "";
330
-
331
- $gateway_environment = pmpro_getOption("gateway_environment");
332
-
333
- //build query
334
- global $wpdb;
335
- $sqlQuery = "SELECT COUNT(*) FROM $wpdb->pmpro_membership_orders WHERE status NOT IN('refunded', 'review', 'token', 'error') AND timestamp >= '" . $startdate . "' AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
336
-
337
- //restrict by level
338
- if(!empty($levels))
339
- $sqlQuery .= "AND membership_id IN(" . $levels . ") ";
340
-
341
- $sales = $wpdb->get_var($sqlQuery);
342
-
343
- //save in cache
344
- if(!empty($cache) && !empty($cache[$period]))
345
- $cache[$period][$levels] = $sales;
346
- elseif(!empty($cache))
347
- $cache[$period] = array($levels => $sales);
348
- else
349
- $cache = array($period => array($levels => $sales));
350
-
351
- set_transient("pmpro_report_sales", $cache, 3600*24);
352
-
353
- return $sales;
354
- }
355
-
356
- //get revenue
357
- function pmpro_getRevenue($period, $levels = NULL)
358
- {
359
- //check for a transient
360
- $cache = get_transient("pmpro_report_revenue");
361
- if(!empty($cache) && !empty($cache[$period]) && !empty($cache[$period][$levels]))
362
- return $cache[$period][$levels];
363
-
364
- //a sale is an order with status NOT IN('refunded', 'review', 'token', 'error')
365
- if($period == "today")
366
- $startdate = date("Y-m-d");
367
- elseif($period == "this month")
368
- $startdate = date("Y-m") . "-01";
369
- elseif($period == "this year")
370
- $startdate = date("Y") . "-01-01";
371
- else
372
- $startdate = "";
373
-
374
- $gateway_environment = pmpro_getOption("gateway_environment");
375
-
376
- //build query
377
- global $wpdb;
378
- $sqlQuery = "SELECT SUM(total) FROM $wpdb->pmpro_membership_orders WHERE status NOT IN('refunded', 'review', 'token', 'error') AND timestamp >= '" . $startdate . "' AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
379
-
380
- //restrict by level
381
- if(!empty($levels))
382
- $sqlQuery .= "AND membership_id IN(" . $levels . ") ";
383
-
384
- $revenue = $wpdb->get_var($sqlQuery);
385
-
386
- //save in cache
387
- if(!empty($cache) && !empty($cache[$period]))
388
- $cache[$period][$levels] = $revenue;
389
- elseif(!empty($cache))
390
- $cache[$period] = array($levels => $revenue);
391
- else
392
- $cache = array($period => array($levels => $revenue));
393
-
394
- set_transient("pmpro_report_revenue", $cache, 3600*24);
395
-
396
- return $revenue;
397
- }
398
-
399
- //delete transients when an order goes through
400
- function pmpro_report_sales_delete_transients()
401
- {
402
- delete_transient("pmpro_report_sales");
403
- delete_transient("pmpro_report_revenue");
404
- }
405
- add_action("pmpro_after_checkout", "pmpro_report_sales_delete_transients");
406
- add_action("pmpro_updated_order", "pmpro_report_sales_delete_transients");
1
+ <?php
2
+ /*
3
+ PMPro Report
4
+ Title: Sales
5
+ Slug: sales
6
+
7
+ For each report, add a line like:
8
+ global $pmpro_reports;
9
+ $pmpro_reports['slug'] = 'Title';
10
+
11
+ For each report, also write two functions:
12
+ * pmpro_report_{slug}_widget() to show up on the report homepage.
13
+ * pmpro_report_{slug}_page() to show up when users click on the report page widget.
14
+ */
15
+ global $pmpro_reports;
16
+ $gateway_environment = pmpro_getOption("gateway_environment");
17
+ if($gateway_environment == "sandbox")
18
+ $pmpro_reports['sales'] = __('Sales and Revenue (Testing/Sandbox)', 'pmpro');
19
+ else
20
+ $pmpro_reports['sales'] = __('Sales and Revenue', 'pmpro');
21
+
22
+ //queue Google Visualization JS on report page
23
+ function pmpro_report_sales_init()
24
+ {
25
+ if(is_admin() && isset($_REQUEST['report']) && $_REQUEST['report'] == "sales" && isset($_REQUEST['page']) && $_REQUEST['page'] == "pmpro-reports")
26
+ {
27
+ wp_enqueue_script("jsapi", "https://www.google.com/jsapi");
28
+ }
29
+ }
30
+ add_action("init", "pmpro_report_sales_init");
31
+
32
+ //widget
33
+ function pmpro_report_sales_widget()
34
+ {
35
+ global $wpdb;
36
+ ?>
37
+ <style>
38
+ #pmpro_report_sales div {text-align: center;}
39
+ #pmpro_report_sales em {display: block; font-style: normal; font-size: 2em; margin: 5px;}
40
+ </style>
41
+ <span id="#pmpro_report_sales">
42
+ <div style="width: 25%; float: left;">
43
+ <em><?php echo pmpro_getSales("all time");?></em>
44
+ <label>All Time</label>
45
+ <em><?php echo pmpro_formatPrice(pmpro_getRevenue("all time"));?></em>
46
+ </div>
47
+ <div style="width: 25%; float: left;">
48
+ <em><?php echo pmpro_getSales("this year");?></em>
49
+ <label>This Year</label>
50
+ <em><?php echo pmpro_formatPrice(pmpro_getRevenue("this year"));?></em>
51
+ </div>
52
+ <div style="width: 25%; float: left;">
53
+ <em><?php echo pmpro_getSales("this month");?></em>
54
+ <label>This Month</label>
55
+ <em><?php echo pmpro_formatPrice(pmpro_getRevenue("this month"));?></em>
56
+ </div>
57
+ <div style="width: 25%; float: left;">
58
+ <em><?php echo pmpro_getSales("today");?></em>
59
+ <label>Today</label>
60
+ <em><?php echo pmpro_formatPrice(pmpro_getRevenue("today"));?></em>
61
+ </div>
62
+ <div class="clear"></div>
63
+ </span>
64
+ <?php
65
+ }
66
+
67
+ function pmpro_report_sales_page()
68
+ {
69
+ global $wpdb, $pmpro_currency_symbol, $pmpro_currency, $pmpro_currencies;
70
+
71
+ //get values from form
72
+ if(isset($_REQUEST['type']))
73
+ $type = sanitize_text_field($_REQUEST['type']);
74
+ else
75
+ $type = "revenue";
76
+
77
+ if($type == "sales")
78
+ $type_function = "COUNT";
79
+ else
80
+ $type_function = "SUM";
81
+
82
+ if(isset($_REQUEST['period']))
83
+ $period = sanitize_text_field($_REQUEST['period']);
84
+ else
85
+ $period = "daily";
86
+
87
+ if(isset($_REQUEST['month']))
88
+ $month = intval($_REQUEST['month']);
89
+ else
90
+ $month = date("n");
91
+
92
+ $thisyear = date("Y");
93
+ if(isset($_REQUEST['year']))
94
+ $year = intval($_REQUEST['year']);
95
+ else
96
+ $year = $thisyear;
97
+
98
+ if(isset($_REQUEST['level']))
99
+ $l = intval($_REQUEST['level']);
100
+ else
101
+ $l = "";
102
+
103
+ //calculate start date and how to group dates returned from DB
104
+ if($period == "daily")
105
+ {
106
+ $startdate = $year . '-' . substr("0" . $month, strlen($month) - 1, 2) . '-01';
107
+ $enddate = $year . '-' . substr("0" . $month, strlen($month) - 1, 2) . '-31';
108
+ $date_function = 'DAY';
109
+ }
110
+ elseif($period == "monthly")
111
+ {
112
+ $startdate = $year . '-01-01';
113
+ $enddate = strval(intval($year)+1) . '-01-01';
114
+ $date_function = 'MONTH';
115
+ }
116
+ else
117
+ {
118
+ $startdate = '1960-01-01'; //all time
119
+ $date_function = 'YEAR';
120
+ }
121
+
122
+ //testing or live data
123
+ $gateway_environment = pmpro_getOption("gateway_environment");
124
+
125
+ //get data
126
+ $sqlQuery = "SELECT $date_function(timestamp) as date, $type_function(total) as value FROM $wpdb->pmpro_membership_orders WHERE timestamp >= '" . $startdate . "' AND status NOT IN('refunded', 'review', 'token', 'error') AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
127
+
128
+ if(!empty($enddate))
129
+ $sqlQuery .= "AND timestamp < '" . $enddate . "' ";
130
+
131
+ if(!empty($l))
132
+ $sqlQuery .= "AND membership_id IN(" . $l . ") ";
133
+
134
+ $sqlQuery .= " GROUP BY date ORDER BY date ";
135
+
136
+ $dates = $wpdb->get_results($sqlQuery);
137
+
138
+ //fill in blanks in dates
139
+ $cols = array();
140
+ if($period == "daily")
141
+ {
142
+ $lastday = date("t", strtotime($startdate, current_time("timestamp")));
143
+
144
+ for($i = 1; $i <= $lastday; $i++)
145
+ {
146
+ $cols[$i] = 0;
147
+ foreach($dates as $date)
148
+ {
149
+ if($date->date == $i)
150
+ $cols[$i] = $date->value;
151
+ }
152
+ }
153
+ }
154
+ elseif($period == "monthly")
155
+ {
156
+ for($i = 1; $i < 13; $i++)
157
+ {
158
+ $cols[$i] = 0;
159
+ foreach($dates as $date)
160
+ {
161
+ if($date->date == $i)
162
+ $cols[$i] = $date->value;
163
+ }
164
+ }
165
+ }
166
+ else //annual
167
+ {
168
+ //get min and max years
169
+ $min = 9999;
170
+ $max = 0;
171
+ foreach($dates as $date)
172
+ {
173
+ $min = min($min, $date->date);
174
+ $max = max($max, $date->date);
175
+ }
176
+
177
+ for($i = $min; $i <= $max; $i++)
178
+ {
179
+ foreach($dates as $date)
180
+ {
181
+ if($date->date == $i)
182
+ $cols[$i] = $date->value;
183
+ }
184
+ }
185
+ }
186
+ ?>
187
+ <form id="posts-filter" method="get" action="">
188
+ <h2>
189
+ <?php _e('Sales and Revenue', 'pmpro');?>
190
+ </h2>
191
+
192
+ <div class="tablenav top">
193
+ <?php _ex('Show', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?>
194
+ <select id="period" name="period">
195
+ <option value="daily" <?php selected($period, "daily");?>><?php _e('Daily', 'pmpro');?></option>
196
+ <option value="monthly" <?php selected($period, "monthly");?>><?php _e('Monthly', 'pmpro');?></option>
197
+ <option value="annual" <?php selected($period, "annual");?>><?php _e('Annual', 'pmpro');?></option>
198
+ </select>
199
+ <select name="type">
200
+ <option value="revenue" <?php selected($type, "revenue");?>><?php _e('Revenue', 'pmpro');?></option>
201
+ <option value="sales" <?php selected($type, "sales");?>><?php _e('Sales', 'pmpro');?></option>
202
+ </select>
203
+ <span id="for"><?php _ex('for', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?></span>
204
+ <select id="month" name="month">
205
+ <?php for($i = 1; $i < 13; $i++) { ?>
206
+ <option value="<?php echo $i;?>" <?php selected($month, $i);?>><?php echo date("F", mktime(0, 0, 0, $i, 2));?></option>
207
+ <?php } ?>
208
+ </select>
209
+ <select id="year" name="year">
210
+ <?php for($i = $thisyear; $i > 2007; $i--) { ?>
211
+ <option value="<?php echo $i;?>" <?php selected($year, $i);?>><?php echo $i;?></option>
212
+ <?php } ?>
213
+ </select>
214
+ <span id="for"><?php _ex('for', 'Dropdown label, e.g. Show Daily Revenue for January', 'pmpro')?></span>
215
+ <select name="level">
216
+ <option value="" <?php if(!$l) { ?>selected="selected"<?php } ?>><?php _e('All Levels', 'pmpro');?></option>
217
+ <?php
218
+ $levels = $wpdb->get_results("SELECT id, name FROM $wpdb->pmpro_membership_levels ORDER BY name");
219
+ foreach($levels as $level)
220
+ {
221
+ ?>
222
+ <option value="<?php echo $level->id?>" <?php if($l == $level->id) { ?>selected="selected"<?php } ?>><?php echo $level->name?></option>
223
+ <?php
224
+ }
225
+ ?>
226
+ </select>
227
+
228
+ <input type="hidden" name="page" value="pmpro-reports" />
229
+ <input type="hidden" name="report" value="sales" />
230
+ <input type="submit" class="button action" value="<?php _ex('Generate Report', 'Submit button value.', 'pmpro');?>" />
231
+ </div>
232
+
233
+ <div id="chart_div" style="clear: both; width: 100%; height: 500px;"></div>
234
+
235
+ <script>
236
+ //update month/year when period dropdown is changed
237
+ jQuery(document).ready(function() {
238
+ jQuery('#period').change(function() {
239
+ pmpro_ShowMonthOrYear();
240
+ });
241
+ });
242
+
243
+ function pmpro_ShowMonthOrYear()
244
+ {
245
+ var period = jQuery('#period').val();
246
+ if(period == 'daily')
247
+ {
248
+ jQuery('#for').show();
249
+ jQuery('#month').show();
250
+ jQuery('#year').show();
251
+ }
252
+ else if(period == 'monthly')
253
+ {
254
+ jQuery('#for').show();
255
+ jQuery('#month').hide();
256
+ jQuery('#year').show();
257
+ }
258
+ else
259
+ {
260
+ jQuery('#for').hide();
261
+ jQuery('#month').hide();
262
+ jQuery('#year').hide();
263
+ }
264
+ }
265
+
266
+ pmpro_ShowMonthOrYear();
267
+
268
+ //draw the chart
269
+ google.load("visualization", "1", {packages:["corechart"]});
270
+ google.setOnLoadCallback(drawChart);
271
+ function drawChart() {
272
+
273
+ var data = google.visualization.arrayToDataTable([
274
+ ['<?php echo $date_function;?>', '<?php echo ucwords($type);?>'],
275
+ <?php foreach($cols as $date => $value) { ?>
276
+ ['<?php if($period == "monthly") echo date("M", mktime(0,0,0,$date,2)); else echo $date;?>', <?php echo $value;?>],
277
+ <?php } ?>
278
+ ]);
279
+
280
+ var options = {
281
+ colors: ['#51a351', '#387038'],
282
+ hAxis: {title: '<?php echo $date_function;?>', titleTextStyle: {color: 'black'}, maxAlternation: 1},
283
+ vAxis: {color: 'green', titleTextStyle: {color: '#51a351'}},
284
+ };
285
+
286
+ <?php
287
+ if($type != "sales")
288
+ {
289
+ if(pmpro_getCurrencyPosition() == "right")
290
+ $position = "suffix";
291
+ else
292
+ $position = "prefix";
293
+ ?>
294
+ var formatter = new google.visualization.NumberFormat({<?php echo $position;?>: '<?php echo html_entity_decode($pmpro_currency_symbol);?>'});
295
+ formatter.format(data, 1);
296
+ <?php
297
+ }
298
+ ?>
299
+
300
+ var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
301
+ chart.draw(data, options);
302
+ }
303
+ </script>
304
+
305
+ </form>
306
+ <?php
307
+ }
308
+
309
+ /*
310
+ Other code required for your reports. This file is loaded every time WP loads with PMPro enabled.
311
+ */
312
+
313
+ //get sales
314
+ function pmpro_getSales($period, $levels = NULL)
315
+ {
316
+ //check for a transient
317
+ $cache = get_transient("pmpro_report_sales");
318
+ if(!empty($cache) && !empty($cache[$period]) && !empty($cache[$period][$levels]))
319
+ return $cache[$period][$levels];
320
+
321
+ //a sale is an order with status NOT IN('refunded', 'review', 'token', 'error')
322
+ if($period == "today")
323
+ $startdate = date("Y-m-d");
324
+ elseif($period == "this month")
325
+ $startdate = date("Y-m") . "-01";
326
+ elseif($period == "this year")
327
+ $startdate = date("Y") . "-01-01";
328
+ else
329
+ $startdate = "";
330
+
331
+ $gateway_environment = pmpro_getOption("gateway_environment");
332
+
333
+ //build query
334
+ global $wpdb;
335
+ $sqlQuery = "SELECT COUNT(*) FROM $wpdb->pmpro_membership_orders WHERE status NOT IN('refunded', 'review', 'token', 'error') AND timestamp >= '" . $startdate . "' AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
336
+
337
+ //restrict by level
338
+ if(!empty($levels))
339
+ $sqlQuery .= "AND membership_id IN(" . $levels . ") ";
340
+
341
+ $sales = $wpdb->get_var($sqlQuery);
342
+
343
+ //save in cache
344
+ if(!empty($cache) && !empty($cache[$period]))
345
+ $cache[$period][$levels] = $sales;
346
+ elseif(!empty($cache))
347
+ $cache[$period] = array($levels => $sales);
348
+ else
349
+ $cache = array($period => array($levels => $sales));
350
+
351
+ set_transient("pmpro_report_sales", $cache, 3600*24);
352
+
353
+ return $sales;
354
+ }
355
+
356
+ //get revenue
357
+ function pmpro_getRevenue($period, $levels = NULL)
358
+ {
359
+ //check for a transient
360
+ $cache = get_transient("pmpro_report_revenue");
361
+ if(!empty($cache) && !empty($cache[$period]) && !empty($cache[$period][$levels]))
362
+ return $cache[$period][$levels];
363
+
364
+ //a sale is an order with status NOT IN('refunded', 'review', 'token', 'error')
365
+ if($period == "today")
366
+ $startdate = date("Y-m-d");
367
+ elseif($period == "this month")
368
+ $startdate = date("Y-m") . "-01";
369
+ elseif($period == "this year")
370
+ $startdate = date("Y") . "-01-01";
371
+ else
372
+ $startdate = "";
373
+
374
+ $gateway_environment = pmpro_getOption("gateway_environment");
375
+
376
+ //build query
377
+ global $wpdb;
378
+ $sqlQuery = "SELECT SUM(total) FROM $wpdb->pmpro_membership_orders WHERE status NOT IN('refunded', 'review', 'token', 'error') AND timestamp >= '" . $startdate . "' AND gateway_environment = '" . esc_sql($gateway_environment) . "' ";
379
+
380
+ //restrict by level
381
+ if(!empty($levels))
382
+ $sqlQuery .= "AND membership_id IN(" . $levels . ") ";
383
+
384
+ $revenue = $wpdb->get_var($sqlQuery);
385
+
386
+ //save in cache
387
+ if(!empty($cache) && !empty($cache[$period]))
388
+ $cache[$period][$levels] = $revenue;
389
+ elseif(!empty($cache))
390
+ $cache[$period] = array($levels => $revenue);
391
+ else
392
+ $cache = array($period => array($levels => $revenue));
393
+
394
+ set_transient("pmpro_report_revenue", $cache, 3600*24);
395
+
396
+ return $revenue;
397
+ }
398
+
399
+ //delete transients when an order goes through
400
+ function pmpro_report_sales_delete_transients()
401
+ {
402
+ delete_transient("pmpro_report_sales");
403
+ delete_transient("pmpro_report_revenue");
404
+ }
405
+ add_action("pmpro_after_checkout", "pmpro_report_sales_delete_transients");
406
+ add_action("pmpro_updated_order", "pmpro_report_sales_delete_transients");
classes/class.memberorder.php CHANGED
@@ -246,7 +246,7 @@
246
 
247
  //filter @since v1.7.14
248
  $this->discount_code = apply_filters("pmpro_order_discount_code", $this->discount_code, $this);
249
-
250
  return $this->discount_code;
251
  }
252
 
@@ -295,9 +295,9 @@
295
  $discount_code = $this->discount_code->code;
296
  else
297
  $discount_code = $this->discount_code;
298
-
299
  $sqlQuery = "SELECT l.id, cl.*, l.name, l.description, l.allow_signups FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id LEFT JOIN $wpdb->pmpro_discount_codes dc ON dc.id = cl.code_id WHERE dc.code = '" . $discount_code . "' AND cl.level_id = '" . $this->membership_id . "' LIMIT 1";
300
-
301
  $this->membership_level = $wpdb->get_row($sqlQuery);
302
  }
303
 
246
 
247
  //filter @since v1.7.14
248
  $this->discount_code = apply_filters("pmpro_order_discount_code", $this->discount_code, $this);
249
+
250
  return $this->discount_code;
251
  }
252
 
295
  $discount_code = $this->discount_code->code;
296
  else
297
  $discount_code = $this->discount_code;
298
+
299
  $sqlQuery = "SELECT l.id, cl.*, l.name, l.description, l.allow_signups FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id LEFT JOIN $wpdb->pmpro_discount_codes dc ON dc.id = cl.code_id WHERE dc.code = '" . $discount_code . "' AND cl.level_id = '" . $this->membership_id . "' LIMIT 1";
300
+
301
  $this->membership_level = $wpdb->get_row($sqlQuery);
302
  }
303
 
classes/class.mimetype.php CHANGED
@@ -1,239 +1,239 @@
1
- <?php
2
- /**
3
- Copyright (C) 2002 Jason Sheets <jsheets@shadonet.com>.
4
- All rights reserved.
5
-
6
- THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
7
- Redistribution and use in source and binary forms, with or without
8
- modification, are permitted provided that the following conditions
9
- are met:
10
-
11
- 1. Redistributions of source code must retain the above copyright
12
- notice, this list of conditions and the following disclaimer.
13
-
14
- 2. Redistributions in binary form must reproduce the above copyright
15
- notice, this list of conditions and the following disclaimer in the
16
- documentation and/or other materials provided with the distribution.
17
-
18
- 3. Neither the name of the project nor the names of its contributors
19
- may be used to endorse or promote products derived from this software
20
- without specific prior written permission.
21
-
22
- THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
- ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
- SUCH DAMAGE.
33
- **/
34
-
35
- /**
36
- Name: PHP MimeType Class
37
-
38
- Version: 1.0
39
- Date Released: 10/20/02
40
-
41
- Description: This class allows a PHP script to determine the mime type
42
- a file based on the file extension. This class is handy for PHP versions
43
- without the benefit of other tools to determine the mime type. The class
44
- defaults to octet-stream so if the file type is not recognized the user
45
- is presented with a file download prompt.
46
-
47
- NOTES: The mime types for this version are based on Apache 1.3.27
48
- mime types may change or need to be added in the future, the mime types
49
- are stored in an array so that an awk or other script can automatically
50
- generate the code to make the array.
51
-
52
- Usage:
53
-
54
- First an instance of the mimetype class must be created, then the
55
- getType method should be called with the filename. It will return
56
- the mime type, an example follows.
57
-
58
- Example:
59
-
60
- $mimetype = new mimetype();
61
- print $mimetype->getType('acrobat.pdf');
62
-
63
- Author: Jason Sheets <jsheets@shadonet.com>
64
-
65
- License: This script is distributed under the BSD License, you are free
66
- to use, or modify it however you like. If you find this script useful please
67
- e-mail me.
68
- **/
69
-
70
- class pmpro_mimetype {
71
- function getType($filename) {
72
- // get base name of the filename provided by user
73
- $filename = basename($filename);
74
-
75
- // break file into parts seperated by .
76
- $filename = explode('.', $filename);
77
-
78
- // take the last part of the file to get the file extension
79
- $filename = $filename[count($filename)-1];
80
-
81
- // find mime type
82
- return $this->privFindType($filename);
83
- }
84
-
85
- function privFindType($ext) {
86
- // create mimetypes array
87
- $mimetypes = $this->privBuildMimeArray();
88
-
89
- // return mime type for extension
90
- if (isset($mimetypes[$ext])) {
91
- return $mimetypes[$ext];
92
- // if the extension wasn't found return octet-stream
93
- } else {
94
- return 'application/octet-stream';
95
- }
96
-
97
- }
98
-
99
- function privBuildMimeArray() {
100
- return array(
101
- "ez" => "application/andrew-inset",
102
- "hqx" => "application/mac-binhex40",
103
- "cpt" => "application/mac-compactpro",
104
- "doc" => "application/msword",
105
- "bin" => "application/octet-stream",
106
- "dms" => "application/octet-stream",
107
- "lha" => "application/octet-stream",
108
- "lzh" => "application/octet-stream",
109
- "exe" => "application/octet-stream",
110
- "class" => "application/octet-stream",
111
- "so" => "application/octet-stream",
112
- "dll" => "application/octet-stream",
113
- "oda" => "application/oda",
114
- "pdf" => "application/pdf",
115
- "ai" => "application/postscript",
116
- "eps" => "application/postscript",
117
- "ps" => "application/postscript",
118
- "smi" => "application/smil",
119
- "smil" => "application/smil",
120
- "wbxml" => "application/vnd.wap.wbxml",
121
- "wmlc" => "application/vnd.wap.wmlc",
122
- "wmlsc" => "application/vnd.wap.wmlscriptc",
123
- "bcpio" => "application/x-bcpio",
124
- "vcd" => "application/x-cdlink",
125
- "pgn" => "application/x-chess-pgn",
126
- "cpio" => "application/x-cpio",
127
- "csh" => "application/x-csh",
128
- "dcr" => "application/x-director",
129
- "dir" => "application/x-director",
130
- "dxr" => "application/x-director",
131
- "dvi" => "application/x-dvi",
132
- "spl" => "application/x-futuresplash",
133
- "gtar" => "application/x-gtar",
134
- "hdf" => "application/x-hdf",
135
- "js" => "application/x-javascript",
136
- "skp" => "application/x-koan",
137
- "skd" => "application/x-koan",
138
- "skt" => "application/x-koan",
139
- "skm" => "application/x-koan",
140
- "latex" => "application/x-latex",
141
- "nc" => "application/x-netcdf",
142
- "cdf" => "application/x-netcdf",
143
- "sh" => "application/x-sh",
144
- "shar" => "application/x-shar",
145
- "swf" => "application/x-shockwave-flash",
146
- "sit" => "application/x-stuffit",
147
- "sv4cpio" => "application/x-sv4cpio",
148
- "sv4crc" => "application/x-sv4crc",
149
- "tar" => "application/x-tar",
150
- "tcl" => "application/x-tcl",
151
- "tex" => "application/x-tex",
152
- "texinfo" => "application/x-texinfo",
153
- "texi" => "application/x-texinfo",
154
- "t" => "application/x-troff",
155
- "tr" => "application/x-troff",
156
- "roff" => "application/x-troff",
157
- "man" => "application/x-troff-man",
158
- "me" => "application/x-troff-me",
159
- "ms" => "application/x-troff-ms",
160
- "ustar" => "application/x-ustar",
161
- "src" => "application/x-wais-source",
162
- "xhtml" => "application/xhtml+xml",
163
- "xht" => "application/xhtml+xml",
164
- "zip" => "application/zip",
165
- "au" => "audio/basic",
166
- "snd" => "audio/basic",
167
- "mid" => "audio/midi",
168
- "midi" => "audio/midi",
169
- "kar" => "audio/midi",
170
- "mpga" => "audio/mpeg",
171
- "mp2" => "audio/mpeg",
172
- "mp3" => "audio/mpeg",
173
- "aif" => "audio/x-aiff",
174
- "aiff" => "audio/x-aiff",
175
- "aifc" => "audio/x-aiff",
176
- "m3u" => "audio/x-mpegurl",
177
- "ram" => "audio/x-pn-realaudio",
178
- "rm" => "audio/x-pn-realaudio",
179
- "rpm" => "audio/x-pn-realaudio-plugin",
180
- "ra" => "audio/x-realaudio",
181
- "wav" => "audio/x-wav",
182
- "pdb" => "chemical/x-pdb",
183
- "xyz" => "chemical/x-xyz",
184
- "bmp" => "image/bmp",
185
- "gif" => "image/gif",
186
- "ief" => "image/ief",
187
- "jpeg" => "image/jpeg",
188
- "jpg" => "image/jpeg",
189
- "jpe" => "image/jpeg",
190
- "png" => "image/png",
191
- "tiff" => "image/tiff",
192
- "tif" => "image/tif",
193
- "djvu" => "image/vnd.djvu",
194
- "djv" => "image/vnd.djvu",
195
- "wbmp" => "image/vnd.wap.wbmp",
196
- "ras" => "image/x-cmu-raster",
197
- "pnm" => "image/x-portable-anymap",
198
- "pbm" => "image/x-portable-bitmap",
199
- "pgm" => "image/x-portable-graymap",
200
- "ppm" => "image/x-portable-pixmap",
201
- "rgb" => "image/x-rgb",
202
- "xbm" => "image/x-xbitmap",
203
- "xpm" => "image/x-xpixmap",
204
- "xwd" => "image/x-windowdump",
205
- "igs" => "model/iges",
206
- "iges" => "model/iges",
207
- "msh" => "model/mesh",
208
- "mesh" => "model/mesh",
209
- "silo" => "model/mesh",
210
- "wrl" => "model/vrml",
211
- "vrml" => "model/vrml",
212
- "css" => "text/css",
213
- "html" => "text/html",
214
- "htm" => "text/html",
215
- "asc" => "text/plain",
216
- "txt" => "text/plain",
217
- "rtx" => "text/richtext",
218
- "rtf" => "text/rtf",
219
- "sgml" => "text/sgml",
220
- "sgm" => "text/sgml",
221
- "tsv" => "text/tab-seperated-values",
222
- "wml" => "text/vnd.wap.wml",
223
- "wmls" => "text/vnd.wap.wmlscript",
224
- "etx" => "text/x-setext",
225
- "xml" => "text/xml",
226
- "xsl" => "text/xml",
227
- "mpeg" => "video/mpeg",
228
- "mpg" => "video/mpeg",
229
- "mpe" => "video/mpeg",
230
- "qt" => "video/quicktime",
231
- "mov" => "video/quicktime",
232
- "mxu" => "video/vnd.mpegurl",
233
- "avi" => "video/x-msvideo",
234
- "movie" => "video/x-sgi-movie",
235
- "ice" => "x-conference-xcooltalk"
236
- );
237
- }
238
- }
239
  ?>
1
+ <?php
2
+ /**
3
+ Copyright (C) 2002 Jason Sheets <jsheets@shadonet.com>.
4
+ All rights reserved.
5
+
6
+ THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions
9
+ are met:
10
+
11
+ 1. Redistributions of source code must retain the above copyright
12
+ notice, this list of conditions and the following disclaimer.
13
+
14
+ 2. Redistributions in binary form must reproduce the above copyright
15
+ notice, this list of conditions and the following disclaimer in the
16
+ documentation and/or other materials provided with the distribution.
17
+
18
+ 3. Neither the name of the project nor the names of its contributors
19
+ may be used to endorse or promote products derived from this software
20
+ without specific prior written permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
+ SUCH DAMAGE.
33
+ **/
34
+
35
+ /**
36
+ Name: PHP MimeType Class
37
+
38
+ Version: 1.0
39
+ Date Released: 10/20/02
40
+
41
+ Description: This class allows a PHP script to determine the mime type
42
+ a file based on the file extension. This class is handy for PHP versions
43
+ without the benefit of other tools to determine the mime type. The class
44
+ defaults to octet-stream so if the file type is not recognized the user
45
+ is presented with a file download prompt.
46
+
47
+ NOTES: The mime types for this version are based on Apache 1.3.27
48
+ mime types may change or need to be added in the future, the mime types
49
+ are stored in an array so that an awk or other script can automatically
50
+ generate the code to make the array.
51
+
52
+ Usage:
53
+
54
+ First an instance of the mimetype class must be created, then the
55
+ getType method should be called with the filename. It will return
56
+ the mime type, an example follows.
57
+
58
+ Example:
59
+
60
+ $mimetype = new mimetype();
61
+ print $mimetype->getType('acrobat.pdf');
62
+
63
+ Author: Jason Sheets <jsheets@shadonet.com>
64
+
65
+ License: This script is distributed under the BSD License, you are free
66
+ to use, or modify it however you like. If you find this script useful please
67
+ e-mail me.
68
+ **/
69
+
70
+ class pmpro_mimetype {
71
+ function getType($filename) {
72
+ // get base name of the filename provided by user
73
+ $filename = basename($filename);
74
+
75
+ // break file into parts seperated by .
76
+ $filename = explode('.', $filename);
77
+
78
+ // take the last part of the file to get the file extension
79
+ $filename = $filename[count($filename)-1];
80
+
81
+ // find mime type
82
+ return $this->privFindType($filename);
83
+ }
84
+
85
+ function privFindType($ext) {
86
+ // create mimetypes array
87
+ $mimetypes = $this->privBuildMimeArray();
88
+
89
+ // return mime type for extension
90
+ if (isset($mimetypes[$ext])) {
91
+ return $mimetypes[$ext];
92
+ // if the extension wasn't found return octet-stream
93
+ } else {
94
+ return 'application/octet-stream';
95
+ }
96
+
97
+ }
98
+
99
+ function privBuildMimeArray() {
100
+ return array(
101
+ "ez" => "application/andrew-inset",
102
+ "hqx" => "application/mac-binhex40",
103
+ "cpt" => "application/mac-compactpro",
104
+ "doc" => "application/msword",
105
+ "bin" => "application/octet-stream",
106
+ "dms" => "application/octet-stream",
107
+ "lha" => "application/octet-stream",
108
+ "lzh" => "application/octet-stream",
109
+ "exe" => "application/octet-stream",
110
+ "class" => "application/octet-stream",
111
+ "so" => "application/octet-stream",
112
+ "dll" => "application/octet-stream",
113
+ "oda" => "application/oda",
114
+ "pdf" => "application/pdf",
115
+ "ai" => "application/postscript",
116
+ "eps" => "application/postscript",
117
+ "ps" => "application/postscript",
118
+ "smi" => "application/smil",
119
+ "smil" => "application/smil",
120
+ "wbxml" => "application/vnd.wap.wbxml",
121
+ "wmlc" => "application/vnd.wap.wmlc",
122
+ "wmlsc" => "application/vnd.wap.wmlscriptc",
123
+ "bcpio" => "application/x-bcpio",
124
+ "vcd" => "application/x-cdlink",
125
+ "pgn" => "application/x-chess-pgn",
126
+ "cpio" => "application/x-cpio",
127
+ "csh" => "application/x-csh",
128
+ "dcr" => "application/x-director",
129
+ "dir" => "application/x-director",
130
+ "dxr" => "application/x-director",
131
+ "dvi" => "application/x-dvi",
132
+ "spl" => "application/x-futuresplash",
133
+ "gtar" => "application/x-gtar",
134
+ "hdf" => "application/x-hdf",
135
+ "js" => "application/x-javascript",
136
+ "skp" => "application/x-koan",
137
+ "skd" => "application/x-koan",
138
+ "skt" => "application/x-koan",
139
+ "skm" => "application/x-koan",
140
+ "latex" => "application/x-latex",
141
+ "nc" => "application/x-netcdf",
142
+ "cdf" => "application/x-netcdf",
143
+ "sh" => "application/x-sh",
144
+ "shar" => "application/x-shar",
145
+ "swf" => "application/x-shockwave-flash",
146
+ "sit" => "application/x-stuffit",
147
+ "sv4cpio" => "application/x-sv4cpio",
148
+ "sv4crc" => "application/x-sv4crc",
149
+ "tar" => "application/x-tar",
150
+ "tcl" => "application/x-tcl",
151
+ "tex" => "application/x-tex",
152
+ "texinfo" => "application/x-texinfo",
153
+ "texi" => "application/x-texinfo",
154
+ "t" => "application/x-troff",
155
+ "tr" => "application/x-troff",
156
+ "roff" => "application/x-troff",
157
+ "man" => "application/x-troff-man",
158
+ "me" => "application/x-troff-me",
159
+ "ms" => "application/x-troff-ms",
160
+ "ustar" => "application/x-ustar",
161
+ "src" => "application/x-wais-source",
162
+ "xhtml" => "application/xhtml+xml",
163
+ "xht" => "application/xhtml+xml",
164
+ "zip" => "application/zip",
165
+ "au" => "audio/basic",
166
+ "snd" => "audio/basic",
167
+ "mid" => "audio/midi",
168
+ "midi" => "audio/midi",
169
+ "kar" => "audio/midi",
170
+ "mpga" => "audio/mpeg",
171
+ "mp2" => "audio/mpeg",
172
+ "mp3" => "audio/mpeg",
173
+ "aif" => "audio/x-aiff",
174
+ "aiff" => "audio/x-aiff",
175
+ "aifc" => "audio/x-aiff",
176
+ "m3u" => "audio/x-mpegurl",
177
+ "ram" => "audio/x-pn-realaudio",
178
+ "rm" => "audio/x-pn-realaudio",
179
+ "rpm" => "audio/x-pn-realaudio-plugin",
180
+ "ra" => "audio/x-realaudio",
181
+ "wav" => "audio/x-wav",
182
+ "pdb" => "chemical/x-pdb",
183
+ "xyz" => "chemical/x-xyz",
184
+ "bmp" => "image/bmp",
185
+ "gif" => "image/gif",
186
+ "ief" => "image/ief",
187
+ "jpeg" => "image/jpeg",
188
+ "jpg" => "image/jpeg",
189
+ "jpe" => "image/jpeg",
190
+ "png" => "image/png",
191
+ "tiff" => "image/tiff",
192
+ "tif" => "image/tif",
193
+ "djvu" => "image/vnd.djvu",
194
+ "djv" => "image/vnd.djvu",
195
+ "wbmp" => "image/vnd.wap.wbmp",
196
+ "ras" => "image/x-cmu-raster",
197
+ "pnm" => "image/x-portable-anymap",
198
+ "pbm" => "image/x-portable-bitmap",
199
+ "pgm" => "image/x-portable-graymap",
200
+ "ppm" => "image/x-portable-pixmap",
201
+ "rgb" => "image/x-rgb",
202
+ "xbm" => "image/x-xbitmap",
203
+ "xpm" => "image/x-xpixmap",
204
+ "xwd" => "image/x-windowdump",
205
+ "igs" => "model/iges",
206
+ "iges" => "model/iges",
207
+ "msh" => "model/mesh",
208
+ "mesh" => "model/mesh",
209
+ "silo" => "model/mesh",
210
+ "wrl" => "model/vrml",
211
+ "vrml" => "model/vrml",
212
+ "css" => "text/css",
213
+ "html" => "text/html",
214
+ "htm" => "text/html",
215
+ "asc" => "text/plain",
216
+ "txt" => "text/plain",
217
+ "rtx" => "text/richtext",
218
+ "rtf" => "text/rtf",
219
+ "sgml" => "text/sgml",
220
+ "sgm" => "text/sgml",
221
+ "tsv" => "text/tab-seperated-values",
222
+ "wml" => "text/vnd.wap.wml",
223
+ "wmls" => "text/vnd.wap.wmlscript",
224
+ "etx" => "text/x-setext",
225
+ "xml" => "text/xml",
226
+ "xsl" => "text/xml",
227
+ "mpeg" => "video/mpeg",
228
+ "mpg" => "video/mpeg",
229
+ "mpe" => "video/mpeg",
230
+ "qt" => "video/quicktime",
231
+ "mov" => "video/quicktime",
232
+ "mxu" => "video/vnd.mpegurl",
233
+ "avi" => "video/x-msvideo",
234
+ "movie" => "video/x-sgi-movie",
235
+ "ice" => "x-conference-xcooltalk"
236
+ );
237
+ }
238
+ }
239
  ?>
classes/class.pmproemail.php CHANGED
@@ -1,815 +1,815 @@
1
- <?php
2
- class PMProEmail
3
- {
4
- function PMProEmail()
5
- {
6
- $this->email = $this->from = $this->fromname = $this->subject = $this->template = $this->data = $this->body = NULL;
7
- }
8
-
9
- function sendEmail($email = NULL, $from = NULL, $fromname = NULL, $subject = NULL, $template = NULL, $data = NULL)
10
- {
11
- //if values were passed
12
- if($email)
13
- $this->email = $email;
14
- if($from)
15
- $this->from = $from;
16
- if($fromname)
17
- $this->fromname = $fromname;
18
- if($subject)
19
- $this->subject = $subject;
20
- if($template)
21
- $this->template = $template;
22
- if($data)
23
- $this->data = $data;
24
-
25
- //default values
26
- global $current_user;
27
- if(!$this->email)
28
- $this->email = $current_user->user_email;
29
-
30
- if(!$this->from)
31
- $this->from = pmpro_getOption("from_email");
32
-
33
- if(!$this->fromname)
34
- $this->fromname = pmpro_getOption("from_name");
35
-
36
- if(!$this->subject)
37
- $this->subject = sprintf(__("An Email From %s", "pmpro"), get_option("blogname"));
38
-
39
- //decode the subject line in case there are apostrophes/etc in it
40
- $this->subject = html_entity_decode($this->subject, ENT_QUOTES, 'UTF-8');
41
-
42
- if(!$this->template)
43
- $this->template = "default";
44
-
45
- $this->headers = array("Content-Type: text/html");
46
-
47
- $this->attachments = NULL;
48
-
49
- //load the template
50
- $locale = apply_filters("plugin_locale", get_locale(), "pmpro");
51
- if(file_exists(get_stylesheet_directory() . "/paid-memberships-pro/email/" . $this->template . ".html"))
52
- $this->body = file_get_contents(get_stylesheet_directory() . "/paid-memberships-pro/email/" . $this->template . ".html"); //email folder in pmpro folder in theme
53
- elseif(file_exists(get_stylesheet_directory() . "/membership-email-" . $this->template . ".html"))
54
- $this->body = file_get_contents(get_stylesheet_directory() . "/membership-email-" . $this->template . ".html"); //membership- file in pmpro folder in theme
55
- elseif(file_exists(TEMPLATEPATH . "/membership-email-" . $this->template . ".html"))
56
- $this->body = file_get_contents(TEMPLATEPATH . "/membership-email-" . $this->template . ".html"); //membership- file in theme root
57
- elseif(file_exists(WP_LANG_DIR . '/pmpro/email/' . $this->template . ".html"))
58
- $this->body = file_get_contents(WP_LANG_DIR . '/pmpro/email/' . $this->template . ".html"); //email folder in WP language folder
59
- elseif(file_exists(PMPRO_DIR . "/languages/" . $locale . "/" . $this->template . ".html"))
60
- $this->body = file_get_contents(PMPRO_DIR . "/languages/" . $locale . "/" . $this->template . ".html"); //email folder in PMPro language folder
61
- elseif(file_exists(PMPRO_DIR . "/email/" . $this->template . ".html"))
62
- $this->body = file_get_contents(PMPRO_DIR . "/email/" . $this->template . ".html"); //default template in plugin
63
- elseif(!empty($this->data) && !empty($this->data['body']))
64
- $this->body = $this->data['body'];
65
-
66
- //header and footer
67
- /* This is handled for all emails via the pmpro_send_html function in paid-memberships-pro now
68
- if(file_exists(TEMPLATEPATH . "/email_header.html"))
69
- {
70
- $this->body = file_get_contents(TEMPLATEPATH . "/email_header.html") . "\n" . $this->body;
71
- }
72
- if(file_exists(TEMPLATEPATH . "/email_footer.html"))
73
- {
74
- $this->body = $this->body . "\n" . file_get_contents(TEMPLATEPATH . "/email_footer.html");
75
- }
76
- */
77
-
78
- //if data is a string, assume we mean to replace !!body!! with it
79
- if(is_string($this->data))
80
- $this->data = array("body"=>$data);
81
-
82
- //filter for data
83
- $this->data = apply_filters("pmpro_email_data", $this->data, $this); //filter
84
-
85
- //swap data into body
86
- if(is_array($this->data))
87
- {
88
- foreach($this->data as $key => $value)
89
- {
90
- $this->body = str_replace("!!" . $key . "!!", $value, $this->body);
91
- }
92
- }
93
-
94
- //filters
95
- $temail = apply_filters("pmpro_email_filter", $this); //allows filtering entire email at once
96
- $this->email = apply_filters("pmpro_email_recipient", $temail->email, $this);
97
- $this->from = apply_filters("pmpro_email_sender", $temail->from, $this);
98
- $this->fromname = apply_filters("pmpro_email_sender_name", $temail->fromname, $this);
99
- $this->subject = apply_filters("pmpro_email_subject", $temail->subject, $this);
100
- $this->template = apply_filters("pmpro_email_template", $temail->template, $this);
101
- $this->body = apply_filters("pmpro_email_body", $temail->body, $this);
102
- $this->headers = apply_filters("pmpro_email_headers", $temail->headers, $this);
103
- $this->attachments = apply_filters("pmpro_email_attachments", $temail->attachments, $this);
104
-
105
- if(wp_mail($this->email,$this->subject,$this->body,$this->headers,$this->attachments))
106
- {
107
- return true;
108
- }
109
- else
110
- {
111
- return false;
112
- }
113
- }
114
-
115
- function sendCancelEmail($user = NULL)
116
- {
117
- global $current_user;
118
- if(!$user)
119
- $user = $current_user;
120
-
121
- if(!$user)
122
- return false;
123
-
124
- $this->email = $user->user_email;
125
- $this->subject = sprintf(__("Your membership at %s has been CANCELLED", "pmpro"), get_option("blogname"));
126
- $this->template = "cancel";
127
- $this->data = array("name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "siteemail" => pmpro_getOption("from_email"));
128
-
129
- return $this->sendEmail();
130
- }
131
-
132
- function sendCancelAdminEmail($user = NULL, $old_level_id)
133
- {
134
- global $wpdb, $current_user;
135
- if(!$user)
136
- $user = $current_user;
137
-
138
- if(!$user)
139
- return false;
140
-
141
- //check settings
142
- $send = pmpro_getOption("email_admin_cancels");
143
- if(empty($send))
144
- return true; //didn't send, but we also don't want to indicate failure because the settings say to not send
145
-
146
- $this->email = get_bloginfo("admin_email");
147
- $this->subject = sprintf(__("Membership for %s at %s has been CANCELLED", "pmpro"), $user->user_login, get_option("blogname"));
148
- $this->template = "cancel_admin";
149
- $this->data = array("user_login" => $user->user_login, "user_email" => $user->user_email, "display_name" => $user->display_name, "sitename" => get_option("blogname"), "siteemail" => pmpro_getOption("from_email"), "login_link" => wp_login_url());
150
- $this->data['membership_id'] = $old_level_id;
151
- $this->data['membership_level_name'] = $wpdb->get_var("SELECT name FROM $wpdb->pmpro_membership_levels WHERE id = '" . $old_level_id . "' LIMIT 1");
152
-
153
- //start and end date
154
- $startdate = $wpdb->get_var("SELECT UNIX_TIMESTAMP(startdate) as startdate FROM $wpdb->pmpro_memberships_users WHERE user_id = '" . $user->ID . "' AND membership_id = '" . $old_level_id . "' AND status = 'inactive' ORDER BY id DESC");
155
- if(!empty($startdate))
156
- $this->data['startdate'] = date(get_option('date_format'), $startdate);
157
- else
158
- $this->data['startdate'] = "";
159
- $enddate = $wpdb->get_var("SELECT UNIX_TIMESTAMP(enddate) as enddate FROM $wpdb->pmpro_memberships_users WHERE user_id = '" . $user->ID . "' AND membership_id = '" . $old_level_id . "' AND status = 'inactive' ORDER BY id DESC");
160
- if(!empty($enddate))
161
- $this->data['enddate'] = date(get_option('date_format'), $enddate);
162
- else
163
- $this->data['enddate'] = "";
164
-
165
- return $this->sendEmail();
166
- }
167
-
168
- function sendCheckoutEmail($user = NULL, $invoice = NULL)
169
- {
170
- global $wpdb, $current_user;
171
- if(!$user)
172
- $user = $current_user;
173
-
174
- if(!$user)
175
- return false;
176
-
177
- $this->email = $user->user_email;
178
- $this->subject = sprintf(__("Your membership confirmation for %s", "pmpro"), get_option("blogname"));
179
-
180
- $this->data = array(
181
- "subject" => $this->subject,
182
- "name" => $user->display_name,
183
- "user_login" => $user->user_login,
184
- "sitename" => get_option("blogname"),
185
- "siteemail" => pmpro_getOption("from_email"),
186
- "membership_id" => $user->membership_level->id,
187
- "membership_level_name" => $user->membership_level->name,
188
- "membership_cost" => pmpro_getLevelCost($user->membership_level),
189
- "login_link" => wp_login_url(pmpro_url("account")),
190
- "display_name" => $user->display_name,
191
- "user_email" => $user->user_email,0
192
- );
193
-
194
- if(!empty($invoice) && !pmpro_isLevelFree($user->membership_level))
195
- {
196
- if($invoice->gateway == "paypalexpress")
197
- $this->template = "checkout_express";
198
- elseif($invoice->gateway == "check")
199
- {
200
- $this->template = "checkout_check";
201
- $this->data["instructions"] = wpautop(pmpro_getOption("instructions"));
202
- }
203
- elseif(pmpro_isLevelTrial($user->membership_level))
204
- $this->template = "checkout_trial";
205
- else
206
- $this->template = "checkout_paid";
207
- $this->data["invoice_id"] = $invoice->code;
208
- $this->data["invoice_total"] = pmpro_formatPrice($invoice->total);
209
- $this->data["invoice_date"] = date(get_option('date_format'), $invoice->timestamp);
210
- $this->data["billing_name"] = $invoice->billing->name;
211
- $this->data["billing_street"] = $invoice->billing->street;
212
- $this->data["billing_city"] = $invoice->billing->city;
213
- $this->data["billing_state"] = $invoice->billing->state;
214
- $this->data["billing_zip"] = $invoice->billing->zip;
215
- $this->data["billing_country"] = $invoice->billing->country;
216
- $this->data["billing_phone"] = $invoice->billing->phone;
217
- $this->data["cardtype"] = $invoice->cardtype;
218
- $this->data["accountnumber"] = hideCardNumber($invoice->accountnumber);
219
- $this->data["expirationmonth"] = $invoice->expirationmonth;
220
- $this->data["expirationyear"] = $invoice->expirationyear;
221
- $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
222
- $invoice->billing->street,
223
- "", //address 2
224
- $invoice->billing->city,
225
- $invoice->billing->state,
226
- $invoice->billing->zip,
227
- $invoice->billing->country,
228
- $invoice->billing->phone);
229
-
230
- if($invoice->getDiscountCode())
231
- $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $invoice->discount_code->code . "</p>\n";
232
- else
233
- $this->data["discount_code"] = "";
234
- }
235
- elseif(pmpro_isLevelFree($user->membership_level))
236
- {
237
- $this->template = "checkout_free";
238
- global $discount_code;
239
- if(!empty($discount_code))
240
- $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $discount_code . "</p>\n";
241
- else
242
- $this->data["discount_code"] = "";
243
- }
244
- else
245
- {
246
- $this->template = "checkout_freetrial";
247
- global $discount_code;
248
- if(!empty($discount_code))
249
- $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $discount_code . "</p>\n";
250
- else
251
- $this->data["discount_code"] = "";
252
- }
253
-
254
- $enddate = $wpdb->get_var("SELECT UNIX_TIMESTAMP(enddate) FROM $wpdb->pmpro_memberships_users WHERE user_id = '" . $user->ID . "' AND status = 'active' LIMIT 1");
255
- if($enddate)
256
- $this->data["membership_expiration"] = "<p>" . sprintf(__("This membership will expire on %s.", "pmpro"), date(get_option('date_format'), $enddate)) . "</p>\n";
257
- else
258
- $this->data["membership_expiration"] = "";
259
-
260
- return $this->sendEmail();
261
- }
262
-
263
- function sendCheckoutAdminEmail($user = NULL, $invoice = NULL)
264
- {
265
- global $wpdb, $current_user;
266
- if(!$user)
267
- $user = $current_user;
268
-
269
- if(!$user)
270
- return false;
271
-
272
- //check settings
273
- $send = pmpro_getOption("email_admin_checkout");
274
- if(empty($send))
275
- return true; //didn't send, but we also don't want to indicate failure because the settings say to not send
276
-
277
- $this->email = get_bloginfo("admin_email");
278
- $this->subject = sprintf(__("Member Checkout for %s at %s", "pmpro"), $user->membership_level->name, get_option("blogname"));
279
-
280
- $this->data = array(
281
- "subject" => $this->subject,
282
- "name" => $user->display_name,
283
- "user_login" => $user->user_login,
284
- "sitename" => get_option("blogname"),
285
- "siteemail" => pmpro_getOption("from_email"),
286
- "membership_id" => $user->membership_level->id,
287
- "membership_level_name" => $user->membership_level->name,
288
- "membership_cost" => pmpro_getLevelCost($user->membership_level),
289
- "login_link" => wp_login_url(pmpro_url("account")),
290
- "display_name" => $user->display_name,
291
- "user_email" => $user->user_email,0
292
- );
293
-
294
- if(!empty($invoice) && !pmpro_isLevelFree($user->membership_level))
295
- {
296
- if($invoice->gateway == "paypalexpress")
297
- $this->template = "checkout_express_admin";
298
- elseif($invoice->gateway == "check")
299
- $this->template = "checkout_check_admin";
300
- elseif(pmpro_isLevelTrial($user->membership_level))
301
- $this->template = "checkout_trial_admin";
302
- else
303
- $this->template = "checkout_paid_admin";
304
- $this->data["invoice_id"] = $invoice->code;
305
- $this->data["invoice_total"] = pmpro_formatPrice($invoice->total);
306
- $this->data["invoice_date"] = date(get_option('date_format'), $invoice->timestamp);
307
- $this->data["billing_name"] = $invoice->billing->name;
308
- $this->data["billing_street"] = $invoice->billing->street;
309
- $this->data["billing_city"] = $invoice->billing->city;
310
- $this->data["billing_state"] = $invoice->billing->state;
311
- $this->data["billing_zip"] = $invoice->billing->zip;
312
- $this->data["billing_country"] = $invoice->billing->country;
313
- $this->data["billing_phone"] = $invoice->billing->phone;
314
- $this->data["cardtype"] = $invoice->cardtype;
315
- $this->data["accountnumber"] = hideCardNumber($invoice->accountnumber);
316
- $this->data["expirationmonth"] = $invoice->expirationmonth;
317
- $this->data["expirationyear"] = $invoice->expirationyear;
318
- $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
319
- $invoice->billing->street,
320
- "", //address 2
321
- $invoice->billing->city,
322
- $invoice->billing->state,
323
- $invoice->billing->zip,
324
- $invoice->billing->country,
325
- $invoice->billing->phone);
326
-
327
- if($invoice->getDiscountCode())
328
- $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $invoice->discount_code->code . "</p>\n";
329
- else
330
- $this->data["discount_code"] = "";
331
- }
332
- elseif(pmpro_isLevelFree($user->membership_level))
333
- {
334
- $this->template = "checkout_free_admin";
335
- global $discount_code;
336
- if(!empty($discount_code))
337
- $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $discount_code . "</p>\n";
338
- else
339
- $this->data["discount_code"] = "";
340
- }
341
- else
342
- {
343
- $this->template = "checkout_freetrial_admin";
344
- $this->data["discount_code"] = "";
345
- }
346
-
347
- $enddate = $wpdb->get_var("SELECT UNIX_TIMESTAMP(enddate) FROM $wpdb->pmpro_memberships_users WHERE user_id = '" . $user->ID . "' AND status = 'active' LIMIT 1");
348
- if($enddate)
349
- $this->data["membership_expiration"] = "<p>" . sprintf(__("This membership will expire on %s.", "pmpro"), date(get_option('date_format'), $enddate)) . "</p>\n";
350
- else
351
- $this->data["membership_expiration"] = "";
352
-
353
- return $this->sendEmail();
354
- }
355
-
356
- function sendBillingEmail($user = NULL, $invoice = NULL)
357
- {
358
- global $current_user;
359
- if(!$user)
360
- $user = $current_user;
361
-
362
- if(!$user || !$invoice)
363
- return false;
364
-
365
- $this->email = $user->user_email;
366
- $this->subject = sprintf(__("Your billing information has been udpated at %s", "pmpro"), get_option("blogname"));
367
- $this->template = "billing";
368
-
369
- $this->data = array(
370
- "subject" => $this->subject,
371
- "name" => $user->display_name,
372
- "user_login" => $user->user_login,
373
- "sitename" => get_option("blogname"),
374
- "siteemail" => pmpro_getOption("from_email"),
375
- "membership_id" => $user->membership_level->id,
376
- "membership_level_name" => $user->membership_level->name,
377
- "display_name" => $user->display_name,
378
- "user_email" => $user->user_email,
379
- "billing_name" => $invoice->billing->name,
380
- "billing_street" => $invoice->billing->street,
381
- "billing_city" => $invoice->billing->city,
382
- "billing_state" => $invoice->billing->state,
383
- "billing_zip" => $invoice->billing->zip,
384
- "billing_country" => $invoice->billing->country,
385
- "billing_phone" => $invoice->billing->phone,
386
- "cardtype" => $invoice->cardtype,
387
- "accountnumber" => hideCardNumber($invoice->accountnumber),
388
- "expirationmonth" => $invoice->expirationmonth,
389
- "expirationyear" => $invoice->expirationyear,
390
- "login_link" => wp_login_url(pmpro_url("account"))
391
- );
392
- $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
393
- $invoice->billing->street,
394
- "", //address 2
395
- $invoice->billing->city,
396
- $invoice->billing->state,
397
- $invoice->billing->zip,
398
- $invoice->billing->country,
399
- $invoice->billing->phone);
400
-
401
- return $this->sendEmail();
402
- }
403
-
404
- function sendBillingAdminEmail($user = NULL, $invoice = NULL)
405
- {
406
- global $current_user;
407
- if(!$user)
408
- $user = $current_user;
409
-
410
- if(!$user || !$invoice)
411
- return false;
412
-
413
- //check settings
414
- $send = pmpro_getOption("email_admin_billing");
415
- if(empty($send))
416
- return true; //didn't send, but we also don't want to indicate failure because the settings say to not send
417
-
418
- $this->email = get_bloginfo("admin_email");
419
- $this->subject = sprintf(__("Billing information has been udpated for %s at %s", "pmpro"), $user->user_login, get_option("blogname"));
420
- $this->template = "billing_admin";
421
-
422
- $this->data = array(
423
- "subject" => $this->subject,
424
- "name" => $user->display_name,
425
- "user_login" => $user->user_login,
426
- "sitename" => get_option("blogname"),
427
- "siteemail" => pmpro_getOption("from_email"),
428
- "membership_id" => $user->membership_level->id,
429
- "membership_level_name" => $user->membership_level->name,
430
- "display_name" => $user->display_name,
431
- "user_email" => $user->user_email,
432
- "billing_name" => $invoice->billing->name,
433
- "billing_street" => $invoice->billing->street,
434
- "billing_city" => $invoice->billing->city,
435
- "billing_state" => $invoice->billing->state,
436
- "billing_zip" => $invoice->billing->zip,
437
- "billing_country" => $invoice->billing->country,
438
- "billing_phone" => $invoice->billing->phone,
439
- "cardtype" => $invoice->cardtype,
440
- "accountnumber" => hideCardNumber($invoice->accountnumber),
441
- "expirationmonth" => $invoice->expirationmonth,
442
- "expirationyear" => $invoice->expirationyear,
443
- "login_link" => wp_login_url()
444
- );
445
- $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
446
- $invoice->billing->street,
447
- "", //address 2
448
- $invoice->billing->city,
449
- $invoice->billing->state,
450
- $invoice->billing->zip,
451
- $invoice->billing->country,
452
- $invoice->billing->phone);
453
-
454
- return $this->sendEmail();
455
- }
456
-
457
- function sendBillingFailureEmail($user = NULL, $invoice = NULL)
458
- {
459
- global $current_user;
460
- if(!$user)
461
- $user = $current_user;
462
-
463
- if(!$user || !$invoice)
464
- return false;
465
-
466
- $this->email = $user->user_email;
467
- $this->subject = sprintf(__("Membership Payment Failed at %s", "pmpro"), get_option("blogname"));
468
- $this->template = "billing_failure";
469
-
470
- $this->data = array(
471
- "subject" => $this->subject,
472
- "name" => $user->display_name,
473
- "user_login" => $user->user_login,
474
- "sitename" => get_option("blogname"),
475
- "siteemail" => pmpro_getOption("from_email"),
476
- "membership_id" => $user->membership_level->id,
477
- "membership_level_name" => $user->membership_level->name,
478
- "display_name" => $user->display_name,
479
- "user_email" => $user->user_email,
480
- "billing_name" => $invoice->billing->name,
481
- "billing_street" => $invoice->billing->street,
482
- "billing_city" => $invoice->billing->city,
483
- "billing_state" => $invoice->billing->state,
484
- "billing_zip" => $invoice->billing->zip,
485
- "billing_country" => $invoice->billing->country,
486
- "billing_phone" => $invoice->billing->phone,
487
- "cardtype" => $invoice->cardtype,
488
- "accountnumber" => hideCardNumber($invoice->accountnumber),
489
- "expirationmonth" => $invoice->expirationmonth,
490
- "expirationyear" => $invoice->expirationyear,
491
- "login_link" => wp_login_url(pmpro_url("billing"))
492
- );
493
- $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
494
- $invoice->billing->street,
495
- "", //address 2
496
- $invoice->billing->city,
497
- $invoice->billing->state,
498
- $invoice->billing->zip,
499
- $invoice->billing->country,
500
- $invoice->billing->phone);
501
-
502
- return $this->sendEmail();
503
- }
504
-
505
- function sendBillingFailureAdminEmail($email, $invoice = NULL)
506
- {
507
- if(!$invoice)
508
- return false;
509
-
510
- $user = get_userdata($invoice->user_id);
511
-
512
- $this->email = $email;
513
- $this->subject = sprintf(__("Membership Payment Failed For %s at %s", "pmpro"), $user->display_name, get_option("blogname"));
514
- $this->template = "billing_failure_admin";
515
-
516
- $this->data = array(
517
- "subject" => $this->subject,
518
- "name" => "Admin",
519
- "user_login" => $user->user_login,
520
- "sitename" => get_option("blogname"),
521
- "siteemail" => pmpro_getOption("from_email"),
522
- "membership_id" => $user->membership_level->id,
523
- "membership_level_name" => $user->membership_level->name,
524
- "display_name" => $user->display_name,
525
- "user_email" => $user->user_email,
526
- "billing_name" => $invoice->billing->name,
527
- "billing_street" => $invoice->billing->street,
528
- "billing_city" => $invoice->billing->city,
529
- "billing_state" => $invoice->billing->state,
530
- "billing_zip" => $invoice->billing->zip,
531
- "billing_country" => $invoice->billing->country,
532
- "billing_phone" => $invoice->billing->phone,
533
- "cardtype" => $invoice->cardtype,
534
- "accountnumber" => hideCardNumber($invoice->accountnumber),
535
- "expirationmonth" => $invoice->expirationmonth,
536
- "expirationyear" => $invoice->expirationyear,
537
- "login_link" => wp_login_url(pmpro_url("billing"))
538
- );
539
- $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
540
- $invoice->billing->street,
541
- "", //address 2
542
- $invoice->billing->city,
543
- $invoice->billing->state,
544
- $invoice->billing->zip,
545
- $invoice->billing->country,
546
- $invoice->billing->phone);
547
- return $this->sendEmail();
548
- }
549
-
550
- function sendCreditCardExpiringEmail($user = NULL, $invoice = NULL)
551
- {
552
- global $current_user;
553
- if(!$user)
554
- $user = $current_user;
555
-
556
- if(!$user || !$invoice)
557
- return false;
558
-
559
- $this->email = $user->user_email;
560
- $this->subject = sprintf(__("Credit Card on File Expiring Soon at %s", "pmpro"), get_option("blogname"));
561
- $this->template = "credit_card_expiring";
562
-
563
- $this->data = array(
564
- "subject" => $this->subject,
565
- "name" => $user->display_name,
566
- "user_login" => $user->user_login,
567
- "sitename" => get_option("blogname"),
568
- "siteemail" => pmpro_getOption("from_email"),
569
- "membership_id" => $user->membership_level->id,
570
- "membership_level_name" => $user->membership_level->name,
571
- "display_name" => $user->display_name,
572
- "user_email" => $user->user_email,
573
- "billing_name" => $invoice->billing->name,
574
- "billing_street" => $invoice->billing->street,
575
- "billing_city" => $invoice->billing->city,
576
- "billing_state" => $invoice->billing->state,
577
- "billing_zip" => $invoice->billing->zip,
578
- "billing_country" => $invoice->billing->country,
579
- "billing_phone" => $invoice->billing->phone,
580
- "cardtype" => $invoice->cardtype,
581
- "accountnumber" => hideCardNumber($invoice->accountnumber),
582
- "expirationmonth" => $invoice->expirationmonth,
583
- "expirationyear" => $invoice->expirationyear,
584
- "login_link" => wp_login_url(pmpro_url("billing"))
585
- );
586
- $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
587
- $invoice->billing->street,
588
- "", //address 2
589
- $invoice->billing->city,
590
- $invoice->billing->state,
591
- $invoice->billing->zip,
592
- $invoice->billing->country,
593
- $invoice->billing->phone);
594
-
595
- return $this->sendEmail();
596
- }
597
-
598
- function sendInvoiceEmail($user = NULL, $invoice = NULL)
599
- {
600
- global $wpdb, $current_user;
601
- if(!$user)
602
- $user = $current_user;
603
-
604
- if(!$user || !$invoice)
605
- return false;
606
-
607
- $this->email = $user->user_email;
608
- $this->subject = sprintf(__("INVOICE for %s membership", "pmpro"), get_option("blogname"));
609
- $this->template = "invoice";
610
-
611
- $this->data = array(
612
- "subject" => $this->subject,
613
- "name" => $user->display_name,
614
- "user_login" => $user->user_login,
615
- "sitename" => get_option("blogname"),
616
- "siteemail" => pmpro_getOption("from_email"),
617
- "membership_id" => $user->membership_level->id,
618
- "membership_level_name" => $user->membership_level->name,
619
- "display_name" => $user->display_name,
620
- "user_email" => $user->user_email,
621
- "invoice_id" => $invoice->code,
622
- "invoice_total" => pmpro_formatPrice($invoice->total),
623
- "invoice_date" => date(get_option('date_format'), $invoice->timestamp),
624
- "billing_name" => $invoice->billing->name,
625
- "billing_street" => $invoice->billing->street,
626
- "billing_city" => $invoice->billing->city,
627
- "billing_state" => $invoice->billing->state,
628
- "billing_zip" => $invoice->billing->zip,
629
- "billing_country" => $invoice->billing->country,
630
- "billing_phone" => $invoice->billing->phone,
631
- "cardtype" => $invoice->cardtype,
632
- "accountnumber" => hideCardNumber($invoice->accountnumber),
633
- "expirationmonth" => $invoice->expirationmonth,
634
- "expirationyear" => $invoice->expirationyear,
635
- "login_link" => wp_login_url(pmpro_url("account")),
636
- "invoice_link" => wp_login_url(pmpro_url("invoice", "?invoice=" . $invoice->code)
637
- ));
638
- $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
639
- $invoice->billing->street,
640
- "", //address 2
641
- $invoice->billing->city,
642
- $invoice->billing->state,
643
- $invoice->billing->zip,
644
- $invoice->billing->country,
645
- $invoice->billing->phone);
646
-
647
- if($invoice->getDiscountCode())
648
- $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $invoice->discount_code . "</p>\n";
649
- else
650
- $this->data["discount_code"] = "";
651
-
652
- $enddate = $wpdb->get_var("SELECT UNIX_TIMESTAMP(enddate) FROM $wpdb->pmpro_memberships_users WHERE user_id = '" . $user->ID . "' AND status = 'active' LIMIT 1");
653
- if($enddate)
654
- $this->data["membership_expiration"] = "<p>" . sprintf(__("This membership will expire on %s.", "pmpro"), date(get_option('date_format'), $enddate)) . "</p>\n";
655
- else
656
- $this->data["membership_expiration"] = "";
657
-
658
- return $this->sendEmail();
659
- }
660
-
661
- function sendTrialEndingEmail($user = NULL)
662
- {
663
- global $current_user, $wpdb;
664
- if(!$user)
665
- $user = $current_user;
666
-
667
- if(!$user)
668
- return false;
669
-
670
- //make sure we have the current membership level data
671
- /*$user->membership_level = $wpdb->get_row("SELECT l.id AS ID, l.name AS name, UNIX_TIMESTAMP(mu.startdate) as startdate, mu.billing_amount, mu.cycle_number, mu.cycle_period, mu.trial_amount, mu.trial_limit
672
- FROM {$wpdb->pmpro_membership_levels} AS l
673
- JOIN {$wpdb->pmpro_memberships_users} AS mu ON (l.id = mu.membership_id)
674
- WHERE mu.user_id = " . $user->ID . "
675
- LIMIT 1");*/
676
- $user->membership_level = pmpro_getMembershipLevelForUser($user->ID);
677
-
678
- $this->email = $user->user_email;
679
- $this->subject = sprintf(__("Your trial at %s is ending soon", "pmpro"), get_option("blogname"));
680
- $this->template = "trial_ending";
681
- $this->data = array(
682
- "subject" => $this->subject,
683
- "name" => $user->display_name,
684
- "user_login" => $user->user_login,
685
- "sitename" => get_option("blogname"),
686
- "membership_id" => $user->membership_level->id,
687
- "membership_level_name" => $user->membership_level->name,
688
- "siteemail" => pmpro_getOption("from_email"),
689
- "login_link" => wp_login_url(),
690
- "display_name" => $user->display_name,
691
- "user_email" => $user->user_email,
692
- "billing_amount" => pmpro_formatPrice($user->membership_level->billing_amount),
693
- "cycle_number" => $user->membership_level->cycle_number,
694
- "cycle_period" => $user->membership_level->cycle_period,
695
- "trial_amount" => pmpro_formatPrice($user->membership_level->trial_amount),
696
- "trial_limit" => $user->membership_level->trial_limit,
697
- "trial_end" => date(get_option('date_format'), strtotime(date("m/d/Y", $user->membership_level->startdate) . " + " . $user->membership_level->trial_limit . " " . $user->membership_level->cycle_period), current_time("timestamp"))
698
- );
699
-
700
- return $this->sendEmail();
701
- }
702
-
703
- function sendMembershipExpiredEmail($user = NULL)
704
- {
705
- global $current_user, $wpdb;
706
- if(!$user)
707
- $user = $current_user;
708
-
709
- if(!$user)
710
- return false;
711
-
712
- $this->email = $user->user_email;
713
- $this->subject = sprintf(__("Your membership at %s has ended", "pmpro"), get_option("blogname"));
714
- $this->template = "membership_expired";
715
- $this->data = array("subject" => $this->subject, "name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "siteemail" => pmpro_getOption("from_email"), "login_link" => wp_login_url(), "display_name" => $user->display_name, "user_email" => $user->user_email, "levels_link" => pmpro_url("levels"));
716
-
717
- return $this->sendEmail();
718
- }
719
-
720
- function sendMembershipExpiringEmail($user = NULL)
721
- {
722
- global $current_user, $wpdb;
723
- if(!$user)
724
- $user = $current_user;
725
-
726
- if(!$user)
727
- return false;
728
-
729
- //make sure we have the current membership level data
730
- /*$user->membership_level = $wpdb->get_row("SELECT l.id AS ID, l.name AS name, UNIX_TIMESTAMP(mu.enddate) as enddate
731
- FROM {$wpdb->pmpro_membership_levels} AS l
732
- JOIN {$wpdb->pmpro_memberships_users} AS mu ON (l.id = mu.membership_id)
733
- WHERE mu.user_id = " . $user->ID . "
734
- LIMIT 1");*/
735
- $user->membership_level = pmpro_getMembershipLevelForUser($user->ID);
736
-
737
- $this->email = $user->user_email;
738
- $this->subject = sprintf(__("Your membership at %s will end soon", "pmpro"), get_option("blogname"));
739
- $this->template = "membership_expiring";
740
- $this->data = array("subject" => $this->subject, "name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "membership_id" => $user->membership_level->id, "membership_level_name" => $user->membership_level->name, "siteemail" => pmpro_getOption("from_email"), "login_link" => wp_login_url(), "enddate" => date(get_option('date_format'), $user->membership_level->enddate), "display_name" => $user->display_name, "user_email" => $user->user_email);
741
-
742
- return $this->sendEmail();
743
- }
744
-
745
- function sendAdminChangeEmail($user = NULL)
746
- {
747
- global $current_user, $wpdb;
748
- if(!$user)
749
- $user = $current_user;
750
-
751
- if(!$user)
752
- return false;
753
-
754
- //make sure we have the current membership level data
755
- $user->membership_level = pmpro_getMembershipLevelForUser($user->ID);
756
-
757
- $this->email = $user->user_email;
758
- $this->subject = sprintf(__("Your membership at %s has been changed", "pmpro"), get_option("blogname"));
759
- $this->template = "admin_change";
760
- $this->data = array("subject" => $this->subject, "name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "membership_id" => $user->membership_level->id, "membership_level_name" => $user->membership_level->name, "siteemail" => pmpro_getOption("from_email"), "login_link" => wp_login_url());
761
- if($user->membership_level->ID)
762
- $this->data["membership_change"] = sprintf(__("The new level is %s", "pmpro"), $user->membership_level->name);
763
- else
764
- $this->data["membership_change"] = __("Your membership has been cancelled", "pmpro");
765
-
766
- if(!empty($user->membership_level->enddate))
767
- {
768
- $this->data["membership_change"] .= ". " . sprintf(__("This membership will expire on %s", "pmpro"), date(get_option('date_format'), $user->membership_level->enddate));
769
- }
770
- elseif(!empty($this->expiration_changed))
771
- {
772
- $this->data["membership_change"] .= ". " . __("This membership does not expire", "pmpro");
773
- }
774
-
775
- return $this->sendEmail();
776
- }
777
-
778
- function sendAdminChangeAdminEmail($user = NULL)
779
- {
780
- global $current_user, $wpdb;
781
- if(!$user)
782
- $user = $current_user;
783
-
784
- if(!$user)
785
- return false;
786
-
787
- //check settings
788
- $send = pmpro_getOption("email_admin_changes");
789
- if(empty($send))
790
- return true; //didn't send, but we also don't want to indicate failure because the settings say to not send
791
-
792
- //make sure we have the current membership level data
793
- $user->membership_level = pmpro_getMembershipLevelForUser($user->ID);
794
-
795
- $this->email = get_bloginfo("admin_email");
796
- $this->subject = sprintf(__("Membership for %s at %s has been changed", "pmpro"), $user->user_login, get_option("blogname"));
797
- $this->template = "admin_change_admin";
798
- $this->data = array("subject" => $this->subject, "name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "membership_level_name" => $user->membership_level->name, "siteemail" => get_bloginfo("admin_email"), "login_link" => wp_login_url());
799
- if($user->membership_level->ID)
800
- $this->data["membership_change"] = sprintf(__("The new level is %s", "pmpro"), $user->membership_level->name);
801
- else
802
- $this->data["membership_change"] = __("Membership has been cancelled", "pmpro");
803
-
804
- if(!empty($user->membership_level->enddate))
805
- {
806
- $this->data["membership_change"] .= ". " . sprintf(__("This membership will expire on %s", "pmpro"), date(get_option('date_format'), $user->membership_level->enddate));
807
- }
808
- elseif(!empty($this->expiration_changed))
809
- {
810
- $this->data["membership_change"] .= ". " . __("This membership does not expire", "pmpro");
811
- }
812
-
813
- return $this->sendEmail();
814
- }
815
- }
1
+ <?php
2
+ class PMProEmail
3
+ {
4
+ function PMProEmail()
5
+ {
6
+ $this->email = $this->from = $this->fromname = $this->subject = $this->template = $this->data = $this->body = NULL;
7
+ }
8
+
9
+ function sendEmail($email = NULL, $from = NULL, $fromname = NULL, $subject = NULL, $template = NULL, $data = NULL)
10
+ {
11
+ //if values were passed
12
+ if($email)
13
+ $this->email = $email;
14
+ if($from)
15
+ $this->from = $from;
16
+ if($fromname)
17
+ $this->fromname = $fromname;
18
+ if($subject)
19
+ $this->subject = $subject;
20
+ if($template)
21
+ $this->template = $template;
22
+ if($data)
23
+ $this->data = $data;
24
+
25
+ //default values
26
+ global $current_user;
27
+ if(!$this->email)
28
+ $this->email = $current_user->user_email;
29
+
30
+ if(!$this->from)
31
+ $this->from = pmpro_getOption("from_email");
32
+
33
+ if(!$this->fromname)
34
+ $this->fromname = pmpro_getOption("from_name");
35
+
36
+ if(!$this->subject)
37
+ $this->subject = sprintf(__("An Email From %s", "pmpro"), get_option("blogname"));
38
+
39
+ //decode the subject line in case there are apostrophes/etc in it
40
+ $this->subject = html_entity_decode($this->subject, ENT_QUOTES, 'UTF-8');
41
+
42
+ if(!$this->template)
43
+ $this->template = "default";
44
+
45
+ $this->headers = array("Content-Type: text/html");
46
+
47
+ $this->attachments = NULL;
48
+
49
+ //load the template
50
+ $locale = apply_filters("plugin_locale", get_locale(), "pmpro");
51
+ if(file_exists(get_stylesheet_directory() . "/paid-memberships-pro/email/" . $this->template . ".html"))
52
+ $this->body = file_get_contents(get_stylesheet_directory() . "/paid-memberships-pro/email/" . $this->template . ".html"); //email folder in pmpro folder in theme
53
+ elseif(file_exists(get_stylesheet_directory() . "/membership-email-" . $this->template . ".html"))
54
+ $this->body = file_get_contents(get_stylesheet_directory() . "/membership-email-" . $this->template . ".html"); //membership- file in pmpro folder in theme
55
+ elseif(file_exists(TEMPLATEPATH . "/membership-email-" . $this->template . ".html"))
56
+ $this->body = file_get_contents(TEMPLATEPATH . "/membership-email-" . $this->template . ".html"); //membership- file in theme root
57
+ elseif(file_exists(WP_LANG_DIR . '/pmpro/email/' . $this->template . ".html"))
58
+ $this->body = file_get_contents(WP_LANG_DIR . '/pmpro/email/' . $this->template . ".html"); //email folder in WP language folder
59
+ elseif(file_exists(PMPRO_DIR . "/languages/" . $locale . "/" . $this->template . ".html"))
60
+ $this->body = file_get_contents(PMPRO_DIR . "/languages/" . $locale . "/" . $this->template . ".html"); //email folder in PMPro language folder
61
+ elseif(file_exists(PMPRO_DIR . "/email/" . $this->template . ".html"))
62
+ $this->body = file_get_contents(PMPRO_DIR . "/email/" . $this->template . ".html"); //default template in plugin
63
+ elseif(!empty($this->data) && !empty($this->data['body']))
64
+ $this->body = $this->data['body'];
65
+
66
+ //header and footer
67
+ /* This is handled for all emails via the pmpro_send_html function in paid-memberships-pro now
68
+ if(file_exists(TEMPLATEPATH . "/email_header.html"))
69
+ {
70
+ $this->body = file_get_contents(TEMPLATEPATH . "/email_header.html") . "\n" . $this->body;
71
+ }
72
+ if(file_exists(TEMPLATEPATH . "/email_footer.html"))
73
+ {
74
+ $this->body = $this->body . "\n" . file_get_contents(TEMPLATEPATH . "/email_footer.html");
75
+ }
76
+ */
77
+
78
+ //if data is a string, assume we mean to replace !!body!! with it
79
+ if(is_string($this->data))
80
+ $this->data = array("body"=>$data);
81
+
82
+ //filter for data
83
+ $this->data = apply_filters("pmpro_email_data", $this->data, $this); //filter
84
+
85
+ //swap data into body
86
+ if(is_array($this->data))
87
+ {
88
+ foreach($this->data as $key => $value)
89
+ {
90
+ $this->body = str_replace("!!" . $key . "!!", $value, $this->body);
91
+ }
92
+ }
93
+
94
+ //filters
95
+ $temail = apply_filters("pmpro_email_filter", $this); //allows filtering entire email at once
96
+ $this->email = apply_filters("pmpro_email_recipient", $temail->email, $this);
97
+ $this->from = apply_filters("pmpro_email_sender", $temail->from, $this);
98
+ $this->fromname = apply_filters("pmpro_email_sender_name", $temail->fromname, $this);
99
+ $this->subject = apply_filters("pmpro_email_subject", $temail->subject, $this);
100
+ $this->template = apply_filters("pmpro_email_template", $temail->template, $this);
101
+ $this->body = apply_filters("pmpro_email_body", $temail->body, $this);
102
+ $this->headers = apply_filters("pmpro_email_headers", $temail->headers, $this);
103
+ $this->attachments = apply_filters("pmpro_email_attachments", $temail->attachments, $this);
104
+
105
+ if(wp_mail($this->email,$this->subject,$this->body,$this->headers,$this->attachments))
106
+ {
107
+ return true;
108
+ }
109
+ else
110
+ {
111
+ return false;
112
+ }
113
+ }
114
+
115
+ function sendCancelEmail($user = NULL)
116
+ {
117
+ global $current_user;
118
+ if(!$user)
119
+ $user = $current_user;
120
+
121
+ if(!$user)
122
+ return false;
123
+
124
+ $this->email = $user->user_email;
125
+ $this->subject = sprintf(__("Your membership at %s has been CANCELLED", "pmpro"), get_option("blogname"));
126
+ $this->template = "cancel";
127
+ $this->data = array("name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "siteemail" => pmpro_getOption("from_email"));
128
+
129
+ return $this->sendEmail();
130
+ }
131
+
132
+ function sendCancelAdminEmail($user = NULL, $old_level_id)
133
+ {
134
+ global $wpdb, $current_user;
135
+ if(!$user)
136
+ $user = $current_user;
137
+
138
+ if(!$user)
139
+ return false;
140
+
141
+ //check settings
142
+ $send = pmpro_getOption("email_admin_cancels");
143
+ if(empty($send))
144
+ return true; //didn't send, but we also don't want to indicate failure because the settings say to not send
145
+
146
+ $this->email = get_bloginfo("admin_email");
147
+ $this->subject = sprintf(__("Membership for %s at %s has been CANCELLED", "pmpro"), $user->user_login, get_option("blogname"));
148
+ $this->template = "cancel_admin";
149
+ $this->data = array("user_login" => $user->user_login, "user_email" => $user->user_email, "display_name" => $user->display_name, "sitename" => get_option("blogname"), "siteemail" => pmpro_getOption("from_email"), "login_link" => wp_login_url());
150
+ $this->data['membership_id'] = $old_level_id;
151
+ $this->data['membership_level_name'] = $wpdb->get_var("SELECT name FROM $wpdb->pmpro_membership_levels WHERE id = '" . $old_level_id . "' LIMIT 1");
152
+
153
+ //start and end date
154
+ $startdate = $wpdb->get_var("SELECT UNIX_TIMESTAMP(startdate) as startdate FROM $wpdb->pmpro_memberships_users WHERE user_id = '" . $user->ID . "' AND membership_id = '" . $old_level_id . "' AND status = 'inactive' ORDER BY id DESC");
155
+ if(!empty($startdate))
156
+ $this->data['startdate'] = date(get_option('date_format'), $startdate);
157
+ else
158
+ $this->data['startdate'] = "";
159
+ $enddate = $wpdb->get_var("SELECT UNIX_TIMESTAMP(enddate) as enddate FROM $wpdb->pmpro_memberships_users WHERE user_id = '" . $user->ID . "' AND membership_id = '" . $old_level_id . "' AND status = 'inactive' ORDER BY id DESC");
160
+ if(!empty($enddate))
161
+ $this->data['enddate'] = date(get_option('date_format'), $enddate);
162
+ else
163
+ $this->data['enddate'] = "";
164
+
165
+ return $this->sendEmail();
166
+ }
167
+
168
+ function sendCheckoutEmail($user = NULL, $invoice = NULL)
169
+ {
170
+ global $wpdb, $current_user;
171
+ if(!$user)
172
+ $user = $current_user;
173
+
174
+ if(!$user)
175
+ return false;
176
+
177
+ $this->email = $user->user_email;
178
+ $this->subject = sprintf(__("Your membership confirmation for %s", "pmpro"), get_option("blogname"));
179
+
180
+ $this->data = array(
181
+ "subject" => $this->subject,
182
+ "name" => $user->display_name,
183
+ "user_login" => $user->user_login,
184
+ "sitename" => get_option("blogname"),
185
+ "siteemail" => pmpro_getOption("from_email"),
186
+ "membership_id" => $user->membership_level->id,
187
+ "membership_level_name" => $user->membership_level->name,
188
+ "membership_cost" => pmpro_getLevelCost($user->membership_level),
189
+ "login_link" => wp_login_url(pmpro_url("account")),
190
+ "display_name" => $user->display_name,
191
+ "user_email" => $user->user_email,0
192
+ );
193
+
194
+ if(!empty($invoice) && !pmpro_isLevelFree($user->membership_level))
195
+ {
196
+ if($invoice->gateway == "paypalexpress")
197
+ $this->template = "checkout_express";
198
+ elseif($invoice->gateway == "check")
199
+ {
200
+ $this->template = "checkout_check";
201
+ $this->data["instructions"] = wpautop(pmpro_getOption("instructions"));
202
+ }
203
+ elseif(pmpro_isLevelTrial($user->membership_level))
204
+ $this->template = "checkout_trial";
205
+ else
206
+ $this->template = "checkout_paid";
207
+ $this->data["invoice_id"] = $invoice->code;
208
+ $this->data["invoice_total"] = pmpro_formatPrice($invoice->total);
209
+ $this->data["invoice_date"] = date(get_option('date_format'), $invoice->timestamp);
210
+ $this->data["billing_name"] = $invoice->billing->name;
211
+ $this->data["billing_street"] = $invoice->billing->street;
212
+ $this->data["billing_city"] = $invoice->billing->city;
213
+ $this->data["billing_state"] = $invoice->billing->state;
214
+ $this->data["billing_zip"] = $invoice->billing->zip;
215
+ $this->data["billing_country"] = $invoice->billing->country;
216
+ $this->data["billing_phone"] = $invoice->billing->phone;
217
+ $this->data["cardtype"] = $invoice->cardtype;
218
+ $this->data["accountnumber"] = hideCardNumber($invoice->accountnumber);
219
+ $this->data["expirationmonth"] = $invoice->expirationmonth;
220
+ $this->data["expirationyear"] = $invoice->expirationyear;
221
+ $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
222
+ $invoice->billing->street,
223
+ "", //address 2
224
+ $invoice->billing->city,
225
+ $invoice->billing->state,
226
+ $invoice->billing->zip,
227
+ $invoice->billing->country,
228
+ $invoice->billing->phone);
229
+
230
+ if($invoice->getDiscountCode())
231
+ $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $invoice->discount_code->code . "</p>\n";
232
+ else
233
+ $this->data["discount_code"] = "";
234
+ }
235
+ elseif(pmpro_isLevelFree($user->membership_level))
236
+ {
237
+ $this->template = "checkout_free";
238
+ global $discount_code;
239
+ if(!empty($discount_code))
240
+ $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $discount_code . "</p>\n";
241
+ else
242
+ $this->data["discount_code"] = "";
243
+ }
244
+ else
245
+ {
246
+ $this->template = "checkout_freetrial";
247
+ global $discount_code;
248
+ if(!empty($discount_code))
249
+ $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $discount_code . "</p>\n";
250
+ else
251
+ $this->data["discount_code"] = "";
252
+ }
253
+
254
+ $enddate = $wpdb->get_var("SELECT UNIX_TIMESTAMP(enddate) FROM $wpdb->pmpro_memberships_users WHERE user_id = '" . $user->ID . "' AND status = 'active' LIMIT 1");
255
+ if($enddate)
256
+ $this->data["membership_expiration"] = "<p>" . sprintf(__("This membership will expire on %s.", "pmpro"), date(get_option('date_format'), $enddate)) . "</p>\n";
257
+ else
258
+ $this->data["membership_expiration"] = "";
259
+
260
+ return $this->sendEmail();
261
+ }
262
+
263
+ function sendCheckoutAdminEmail($user = NULL, $invoice = NULL)
264
+ {
265
+ global $wpdb, $current_user;
266
+ if(!$user)
267
+ $user = $current_user;
268
+
269
+ if(!$user)
270
+ return false;
271
+
272
+ //check settings
273
+ $send = pmpro_getOption("email_admin_checkout");
274
+ if(empty($send))
275
+ return true; //didn't send, but we also don't want to indicate failure because the settings say to not send
276
+
277
+ $this->email = get_bloginfo("admin_email");
278
+ $this->subject = sprintf(__("Member Checkout for %s at %s", "pmpro"), $user->membership_level->name, get_option("blogname"));
279
+
280
+ $this->data = array(
281
+ "subject" => $this->subject,
282
+ "name" => $user->display_name,
283
+ "user_login" => $user->user_login,
284
+ "sitename" => get_option("blogname"),
285
+ "siteemail" => pmpro_getOption("from_email"),
286
+ "membership_id" => $user->membership_level->id,
287
+ "membership_level_name" => $user->membership_level->name,
288
+ "membership_cost" => pmpro_getLevelCost($user->membership_level),
289
+ "login_link" => wp_login_url(pmpro_url("account")),
290
+ "display_name" => $user->display_name,
291
+ "user_email" => $user->user_email,0
292
+ );
293
+
294
+ if(!empty($invoice) && !pmpro_isLevelFree($user->membership_level))
295
+ {
296
+ if($invoice->gateway == "paypalexpress")
297
+ $this->template = "checkout_express_admin";
298
+ elseif($invoice->gateway == "check")
299
+ $this->template = "checkout_check_admin";
300
+ elseif(pmpro_isLevelTrial($user->membership_level))
301
+ $this->template = "checkout_trial_admin";
302
+ else
303
+ $this->template = "checkout_paid_admin";
304
+ $this->data["invoice_id"] = $invoice->code;
305
+ $this->data["invoice_total"] = pmpro_formatPrice($invoice->total);
306
+ $this->data["invoice_date"] = date(get_option('date_format'), $invoice->timestamp);
307
+ $this->data["billing_name"] = $invoice->billing->name;
308
+ $this->data["billing_street"] = $invoice->billing->street;
309
+ $this->data["billing_city"] = $invoice->billing->city;
310
+ $this->data["billing_state"] = $invoice->billing->state;
311
+ $this->data["billing_zip"] = $invoice->billing->zip;
312
+ $this->data["billing_country"] = $invoice->billing->country;
313
+ $this->data["billing_phone"] = $invoice->billing->phone;
314
+ $this->data["cardtype"] = $invoice->cardtype;
315
+ $this->data["accountnumber"] = hideCardNumber($invoice->accountnumber);
316
+ $this->data["expirationmonth"] = $invoice->expirationmonth;
317
+ $this->data["expirationyear"] = $invoice->expirationyear;
318
+ $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
319
+ $invoice->billing->street,
320
+ "", //address 2
321
+ $invoice->billing->city,
322
+ $invoice->billing->state,
323
+ $invoice->billing->zip,
324
+ $invoice->billing->country,
325
+ $invoice->billing->phone);
326
+
327
+ if($invoice->getDiscountCode())
328
+ $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $invoice->discount_code->code . "</p>\n";
329
+ else
330
+ $this->data["discount_code"] = "";
331
+ }
332
+ elseif(pmpro_isLevelFree($user->membership_level))
333
+ {
334
+ $this->template = "checkout_free_admin";
335
+ global $discount_code;
336
+ if(!empty($discount_code))
337
+ $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $discount_code . "</p>\n";
338
+ else
339
+ $this->data["discount_code"] = "";
340
+ }
341
+ else
342
+ {
343
+ $this->template = "checkout_freetrial_admin";
344
+ $this->data["discount_code"] = "";
345
+ }
346
+
347
+ $enddate = $wpdb->get_var("SELECT UNIX_TIMESTAMP(enddate) FROM $wpdb->pmpro_memberships_users WHERE user_id = '" . $user->ID . "' AND status = 'active' LIMIT 1");
348
+ if($enddate)
349
+ $this->data["membership_expiration"] = "<p>" . sprintf(__("This membership will expire on %s.", "pmpro"), date(get_option('date_format'), $enddate)) . "</p>\n";
350
+ else
351
+ $this->data["membership_expiration"] = "";
352
+
353
+ return $this->sendEmail();
354
+ }
355
+
356
+ function sendBillingEmail($user = NULL, $invoice = NULL)
357
+ {
358
+ global $current_user;
359
+ if(!$user)
360
+ $user = $current_user;
361
+
362
+ if(!$user || !$invoice)
363
+ return false;
364
+
365
+ $this->email = $user->user_email;
366
+ $this->subject = sprintf(__("Your billing information has been udpated at %s", "pmpro"), get_option("blogname"));
367
+ $this->template = "billing";
368
+
369
+ $this->data = array(
370
+ "subject" => $this->subject,
371
+ "name" => $user->display_name,
372
+ "user_login" => $user->user_login,
373
+ "sitename" => get_option("blogname"),
374
+ "siteemail" => pmpro_getOption("from_email"),
375
+ "membership_id" => $user->membership_level->id,
376
+ "membership_level_name" => $user->membership_level->name,
377
+ "display_name" => $user->display_name,
378
+ "user_email" => $user->user_email,
379
+ "billing_name" => $invoice->billing->name,
380
+ "billing_street" => $invoice->billing->street,
381
+ "billing_city" => $invoice->billing->city,
382
+ "billing_state" => $invoice->billing->state,
383
+ "billing_zip" => $invoice->billing->zip,
384
+ "billing_country" => $invoice->billing->country,
385
+ "billing_phone" => $invoice->billing->phone,
386
+ "cardtype" => $invoice->cardtype,
387
+ "accountnumber" => hideCardNumber($invoice->accountnumber),
388
+ "expirationmonth" => $invoice->expirationmonth,
389
+ "expirationyear" => $invoice->expirationyear,
390
+ "login_link" => wp_login_url(pmpro_url("account"))
391
+ );
392
+ $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
393
+ $invoice->billing->street,
394
+ "", //address 2
395
+ $invoice->billing->city,
396
+ $invoice->billing->state,
397
+ $invoice->billing->zip,
398
+ $invoice->billing->country,
399
+ $invoice->billing->phone);
400
+
401
+ return $this->sendEmail();
402
+ }
403
+
404
+ function sendBillingAdminEmail($user = NULL, $invoice = NULL)
405
+ {
406
+ global $current_user;
407
+ if(!$user)
408
+ $user = $current_user;
409
+
410
+ if(!$user || !$invoice)
411
+ return false;
412
+
413
+ //check settings
414
+ $send = pmpro_getOption("email_admin_billing");
415
+ if(empty($send))
416
+ return true; //didn't send, but we also don't want to indicate failure because the settings say to not send
417
+
418
+ $this->email = get_bloginfo("admin_email");
419
+ $this->subject = sprintf(__("Billing information has been udpated for %s at %s", "pmpro"), $user->user_login, get_option("blogname"));
420
+ $this->template = "billing_admin";
421
+
422
+ $this->data = array(
423
+ "subject" => $this->subject,
424
+ "name" => $user->display_name,
425
+ "user_login" => $user->user_login,
426
+ "sitename" => get_option("blogname"),
427
+ "siteemail" => pmpro_getOption("from_email"),
428
+ "membership_id" => $user->membership_level->id,
429
+ "membership_level_name" => $user->membership_level->name,
430
+ "display_name" => $user->display_name,
431
+ "user_email" => $user->user_email,
432
+ "billing_name" => $invoice->billing->name,
433
+ "billing_street" => $invoice->billing->street,
434
+ "billing_city" => $invoice->billing->city,
435
+ "billing_state" => $invoice->billing->state,
436
+ "billing_zip" => $invoice->billing->zip,
437
+ "billing_country" => $invoice->billing->country,
438
+ "billing_phone" => $invoice->billing->phone,
439
+ "cardtype" => $invoice->cardtype,
440
+ "accountnumber" => hideCardNumber($invoice->accountnumber),
441
+ "expirationmonth" => $invoice->expirationmonth,
442
+ "expirationyear" => $invoice->expirationyear,
443
+ "login_link" => wp_login_url()
444
+ );
445
+ $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
446
+ $invoice->billing->street,
447
+ "", //address 2
448
+ $invoice->billing->city,
449
+ $invoice->billing->state,
450
+ $invoice->billing->zip,
451
+ $invoice->billing->country,
452
+ $invoice->billing->phone);
453
+
454
+ return $this->sendEmail();
455
+ }
456
+
457
+ function sendBillingFailureEmail($user = NULL, $invoice = NULL)
458
+ {
459
+ global $current_user;
460
+ if(!$user)
461
+ $user = $current_user;
462
+
463
+ if(!$user || !$invoice)
464
+ return false;
465
+
466
+ $this->email = $user->user_email;
467
+ $this->subject = sprintf(__("Membership Payment Failed at %s", "pmpro"), get_option("blogname"));
468
+ $this->template = "billing_failure";
469
+
470
+ $this->data = array(
471
+ "subject" => $this->subject,
472
+ "name" => $user->display_name,
473
+ "user_login" => $user->user_login,
474
+ "sitename" => get_option("blogname"),
475
+ "siteemail" => pmpro_getOption("from_email"),
476
+ "membership_id" => $user->membership_level->id,
477
+ "membership_level_name" => $user->membership_level->name,
478
+ "display_name" => $user->display_name,
479
+ "user_email" => $user->user_email,
480
+ "billing_name" => $invoice->billing->name,
481
+ "billing_street" => $invoice->billing->street,
482
+ "billing_city" => $invoice->billing->city,
483
+ "billing_state" => $invoice->billing->state,
484
+ "billing_zip" => $invoice->billing->zip,
485
+ "billing_country" => $invoice->billing->country,
486
+ "billing_phone" => $invoice->billing->phone,
487
+ "cardtype" => $invoice->cardtype,
488
+ "accountnumber" => hideCardNumber($invoice->accountnumber),
489
+ "expirationmonth" => $invoice->expirationmonth,
490
+ "expirationyear" => $invoice->expirationyear,
491
+ "login_link" => wp_login_url(pmpro_url("billing"))
492
+ );
493
+ $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
494
+ $invoice->billing->street,
495
+ "", //address 2
496
+ $invoice->billing->city,
497
+ $invoice->billing->state,
498
+ $invoice->billing->zip,
499
+ $invoice->billing->country,
500
+ $invoice->billing->phone);
501
+
502
+ return $this->sendEmail();
503
+ }
504
+
505
+ function sendBillingFailureAdminEmail($email, $invoice = NULL)
506
+ {
507
+ if(!$invoice)
508
+ return false;
509
+
510
+ $user = get_userdata($invoice->user_id);
511
+
512
+ $this->email = $email;
513
+ $this->subject = sprintf(__("Membership Payment Failed For %s at %s", "pmpro"), $user->display_name, get_option("blogname"));
514
+ $this->template = "billing_failure_admin";
515
+
516
+ $this->data = array(
517
+ "subject" => $this->subject,
518
+ "name" => "Admin",
519
+ "user_login" => $user->user_login,
520
+ "sitename" => get_option("blogname"),
521
+ "siteemail" => pmpro_getOption("from_email"),
522
+ "membership_id" => $user->membership_level->id,
523
+ "membership_level_name" => $user->membership_level->name,
524
+ "display_name" => $user->display_name,
525
+ "user_email" => $user->user_email,
526
+ "billing_name" => $invoice->billing->name,
527
+ "billing_street" => $invoice->billing->street,
528
+ "billing_city" => $invoice->billing->city,
529
+ "billing_state" => $invoice->billing->state,
530
+ "billing_zip" => $invoice->billing->zip,
531
+ "billing_country" => $invoice->billing->country,
532
+ "billing_phone" => $invoice->billing->phone,
533
+ "cardtype" => $invoice->cardtype,
534
+ "accountnumber" => hideCardNumber($invoice->accountnumber),
535
+ "expirationmonth" => $invoice->expirationmonth,
536
+ "expirationyear" => $invoice->expirationyear,
537
+ "login_link" => wp_login_url(pmpro_url("billing"))
538
+ );
539
+ $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
540
+ $invoice->billing->street,
541
+ "", //address 2
542
+ $invoice->billing->city,
543
+ $invoice->billing->state,
544
+ $invoice->billing->zip,
545
+ $invoice->billing->country,
546
+ $invoice->billing->phone);
547
+ return $this->sendEmail();
548
+ }
549
+
550
+ function sendCreditCardExpiringEmail($user = NULL, $invoice = NULL)
551
+ {
552
+ global $current_user;
553
+ if(!$user)
554
+ $user = $current_user;
555
+
556
+ if(!$user || !$invoice)
557
+ return false;
558
+
559
+ $this->email = $user->user_email;
560
+ $this->subject = sprintf(__("Credit Card on File Expiring Soon at %s", "pmpro"), get_option("blogname"));
561
+ $this->template = "credit_card_expiring";
562
+
563
+ $this->data = array(
564
+ "subject" => $this->subject,
565
+ "name" => $user->display_name,
566
+ "user_login" => $user->user_login,
567
+ "sitename" => get_option("blogname"),
568
+ "siteemail" => pmpro_getOption("from_email"),
569
+ "membership_id" => $user->membership_level->id,
570
+ "membership_level_name" => $user->membership_level->name,
571
+ "display_name" => $user->display_name,
572
+ "user_email" => $user->user_email,
573
+ "billing_name" => $invoice->billing->name,
574
+ "billing_street" => $invoice->billing->street,
575
+ "billing_city" => $invoice->billing->city,
576
+ "billing_state" => $invoice->billing->state,
577
+ "billing_zip" => $invoice->billing->zip,
578
+ "billing_country" => $invoice->billing->country,
579
+ "billing_phone" => $invoice->billing->phone,
580
+ "cardtype" => $invoice->cardtype,
581
+ "accountnumber" => hideCardNumber($invoice->accountnumber),
582
+ "expirationmonth" => $invoice->expirationmonth,
583
+ "expirationyear" => $invoice->expirationyear,
584
+ "login_link" => wp_login_url(pmpro_url("billing"))
585
+ );
586
+ $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
587
+ $invoice->billing->street,
588
+ "", //address 2
589
+ $invoice->billing->city,
590
+ $invoice->billing->state,
591
+ $invoice->billing->zip,
592
+ $invoice->billing->country,
593
+ $invoice->billing->phone);
594
+
595
+ return $this->sendEmail();
596
+ }
597
+
598
+ function sendInvoiceEmail($user = NULL, $invoice = NULL)
599
+ {
600
+ global $wpdb, $current_user;
601
+ if(!$user)
602
+ $user = $current_user;
603
+
604
+ if(!$user || !$invoice)
605
+ return false;
606
+
607
+ $this->email = $user->user_email;
608
+ $this->subject = sprintf(__("INVOICE for %s membership", "pmpro"), get_option("blogname"));
609
+ $this->template = "invoice";
610
+
611
+ $this->data = array(
612
+ "subject" => $this->subject,
613
+ "name" => $user->display_name,
614
+ "user_login" => $user->user_login,
615
+ "sitename" => get_option("blogname"),
616
+ "siteemail" => pmpro_getOption("from_email"),
617
+ "membership_id" => $user->membership_level->id,
618
+ "membership_level_name" => $user->membership_level->name,
619
+ "display_name" => $user->display_name,
620
+ "user_email" => $user->user_email,
621
+ "invoice_id" => $invoice->code,
622
+ "invoice_total" => pmpro_formatPrice($invoice->total),
623
+ "invoice_date" => date(get_option('date_format'), $invoice->timestamp),
624
+ "billing_name" => $invoice->billing->name,
625
+ "billing_street" => $invoice->billing->street,
626
+ "billing_city" => $invoice->billing->city,
627
+ "billing_state" => $invoice->billing->state,
628
+ "billing_zip" => $invoice->billing->zip,
629
+ "billing_country" => $invoice->billing->country,
630
+ "billing_phone" => $invoice->billing->phone,
631
+ "cardtype" => $invoice->cardtype,
632
+ "accountnumber" => hideCardNumber($invoice->accountnumber),
633
+ "expirationmonth" => $invoice->expirationmonth,
634
+ "expirationyear" => $invoice->expirationyear,
635
+ "login_link" => wp_login_url(pmpro_url("account")),
636
+ "invoice_link" => wp_login_url(pmpro_url("invoice", "?invoice=" . $invoice->code)
637
+ ));
638
+ $this->data["billing_address"] = pmpro_formatAddress($invoice->billing->name,
639
+ $invoice->billing->street,
640
+ "", //address 2
641
+ $invoice->billing->city,
642
+ $invoice->billing->state,
643
+ $invoice->billing->zip,
644
+ $invoice->billing->country,
645
+ $invoice->billing->phone);
646
+
647
+ if($invoice->getDiscountCode())
648
+ $this->data["discount_code"] = "<p>" . __("Discount Code", "pmpro") . ": " . $invoice->discount_code . "</p>\n";
649
+ else
650
+ $this->data["discount_code"] = "";
651
+
652
+ $enddate = $wpdb->get_var("SELECT UNIX_TIMESTAMP(enddate) FROM $wpdb->pmpro_memberships_users WHERE user_id = '" . $user->ID . "' AND status = 'active' LIMIT 1");
653
+ if($enddate)
654
+ $this->data["membership_expiration"] = "<p>" . sprintf(__("This membership will expire on %s.", "pmpro"), date(get_option('date_format'), $enddate)) . "</p>\n";
655
+ else
656
+ $this->data["membership_expiration"] = "";
657
+
658
+ return $this->sendEmail();
659
+ }
660
+
661
+ function sendTrialEndingEmail($user = NULL)
662
+ {
663
+ global $current_user, $wpdb;
664
+ if(!$user)
665
+ $user = $current_user;
666
+
667
+ if(!$user)
668
+ return false;
669
+
670
+ //make sure we have the current membership level data
671
+ /*$user->membership_level = $wpdb->get_row("SELECT l.id AS ID, l.name AS name, UNIX_TIMESTAMP(mu.startdate) as startdate, mu.billing_amount, mu.cycle_number, mu.cycle_period, mu.trial_amount, mu.trial_limit
672
+ FROM {$wpdb->pmpro_membership_levels} AS l
673
+ JOIN {$wpdb->pmpro_memberships_users} AS mu ON (l.id = mu.membership_id)
674
+ WHERE mu.user_id = " . $user->ID . "
675
+ LIMIT 1");*/
676
+ $user->membership_level = pmpro_getMembershipLevelForUser($user->ID);
677
+
678
+ $this->email = $user->user_email;
679
+ $this->subject = sprintf(__("Your trial at %s is ending soon", "pmpro"), get_option("blogname"));
680
+ $this->template = "trial_ending";
681
+ $this->data = array(
682
+ "subject" => $this->subject,
683
+ "name" => $user->display_name,
684
+ "user_login" => $user->user_login,
685
+ "sitename" => get_option("blogname"),
686
+ "membership_id" => $user->membership_level->id,
687
+ "membership_level_name" => $user->membership_level->name,
688
+ "siteemail" => pmpro_getOption("from_email"),
689
+ "login_link" => wp_login_url(),
690
+ "display_name" => $user->display_name,
691
+ "user_email" => $user->user_email,
692
+ "billing_amount" => pmpro_formatPrice($user->membership_level->billing_amount),
693
+ "cycle_number" => $user->membership_level->cycle_number,
694
+ "cycle_period" => $user->membership_level->cycle_period,
695
+ "trial_amount" => pmpro_formatPrice($user->membership_level->trial_amount),
696
+ "trial_limit" => $user->membership_level->trial_limit,
697
+ "trial_end" => date(get_option('date_format'), strtotime(date("m/d/Y", $user->membership_level->startdate) . " + " . $user->membership_level->trial_limit . " " . $user->membership_level->cycle_period), current_time("timestamp"))
698
+ );
699
+
700
+ return $this->sendEmail();
701
+ }
702
+
703
+ function sendMembershipExpiredEmail($user = NULL)
704
+ {
705
+ global $current_user, $wpdb;
706
+ if(!$user)
707
+ $user = $current_user;
708
+
709
+ if(!$user)
710
+ return false;
711
+
712
+ $this->email = $user->user_email;
713
+ $this->subject = sprintf(__("Your membership at %s has ended", "pmpro"), get_option("blogname"));
714
+ $this->template = "membership_expired";
715
+ $this->data = array("subject" => $this->subject, "name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "siteemail" => pmpro_getOption("from_email"), "login_link" => wp_login_url(), "display_name" => $user->display_name, "user_email" => $user->user_email, "levels_link" => pmpro_url("levels"));
716
+
717
+ return $this->sendEmail();
718
+ }
719
+
720
+ function sendMembershipExpiringEmail($user = NULL)
721
+ {
722
+ global $current_user, $wpdb;
723
+ if(!$user)
724
+ $user = $current_user;
725
+
726
+ if(!$user)
727
+ return false;
728
+
729
+ //make sure we have the current membership level data
730
+ /*$user->membership_level = $wpdb->get_row("SELECT l.id AS ID, l.name AS name, UNIX_TIMESTAMP(mu.enddate) as enddate
731
+ FROM {$wpdb->pmpro_membership_levels} AS l
732
+ JOIN {$wpdb->pmpro_memberships_users} AS mu ON (l.id = mu.membership_id)
733
+ WHERE mu.user_id = " . $user->ID . "
734
+ LIMIT 1");*/
735
+ $user->membership_level = pmpro_getMembershipLevelForUser($user->ID);
736
+
737
+ $this->email = $user->user_email;
738
+ $this->subject = sprintf(__("Your membership at %s will end soon", "pmpro"), get_option("blogname"));
739
+ $this->template = "membership_expiring";
740
+ $this->data = array("subject" => $this->subject, "name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "membership_id" => $user->membership_level->id, "membership_level_name" => $user->membership_level->name, "siteemail" => pmpro_getOption("from_email"), "login_link" => wp_login_url(), "enddate" => date(get_option('date_format'), $user->membership_level->enddate), "display_name" => $user->display_name, "user_email" => $user->user_email);
741
+
742
+ return $this->sendEmail();
743
+ }
744
+
745
+ function sendAdminChangeEmail($user = NULL)
746
+ {
747
+ global $current_user, $wpdb;
748
+ if(!$user)
749
+ $user = $current_user;
750
+
751
+ if(!$user)
752
+ return false;
753
+
754
+ //make sure we have the current membership level data
755
+ $user->membership_level = pmpro_getMembershipLevelForUser($user->ID);
756
+
757
+ $this->email = $user->user_email;
758
+ $this->subject = sprintf(__("Your membership at %s has been changed", "pmpro"), get_option("blogname"));
759
+ $this->template = "admin_change";
760
+ $this->data = array("subject" => $this->subject, "name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "membership_id" => $user->membership_level->id, "membership_level_name" => $user->membership_level->name, "siteemail" => pmpro_getOption("from_email"), "login_link" => wp_login_url());
761
+ if($user->membership_level->ID)
762
+ $this->data["membership_change"] = sprintf(__("The new level is %s", "pmpro"), $user->membership_level->name);
763
+ else
764
+ $this->data["membership_change"] = __("Your membership has been cancelled", "pmpro");
765
+
766
+ if(!empty($user->membership_level->enddate))
767
+ {
768
+ $this->data["membership_change"] .= ". " . sprintf(__("This membership will expire on %s", "pmpro"), date(get_option('date_format'), $user->membership_level->enddate));
769
+ }
770
+ elseif(!empty($this->expiration_changed))
771
+ {
772
+ $this->data["membership_change"] .= ". " . __("This membership does not expire", "pmpro");
773
+ }
774
+
775
+ return $this->sendEmail();
776
+ }
777
+
778
+ function sendAdminChangeAdminEmail($user = NULL)
779
+ {
780
+ global $current_user, $wpdb;
781
+ if(!$user)
782
+ $user = $current_user;
783
+
784
+ if(!$user)
785
+ return false;
786
+
787
+ //check settings
788
+ $send = pmpro_getOption("email_admin_changes");
789
+ if(empty($send))
790
+ return true; //didn't send, but we also don't want to indicate failure because the settings say to not send
791
+
792
+ //make sure we have the current membership level data
793
+ $user->membership_level = pmpro_getMembershipLevelForUser($user->ID);
794
+
795
+ $this->email = get_bloginfo("admin_email");
796
+ $this->subject = sprintf(__("Membership for %s at %s has been changed", "pmpro"), $user->user_login, get_option("blogname"));
797
+ $this->template = "admin_change_admin";
798
+ $this->data = array("subject" => $this->subject, "name" => $user->display_name, "user_login" => $user->user_login, "sitename" => get_option("blogname"), "membership_level_name" => $user->membership_level->name, "siteemail" => get_bloginfo("admin_email"), "login_link" => wp_login_url());
799
+ if($user->membership_level->ID)
800
+ $this->data["membership_change"] = sprintf(__("The new level is %s", "pmpro"), $user->membership_level->name);
801
+ else
802
+ $this->data["membership_change"] = __("Membership has been cancelled", "pmpro");
803
+
804
+ if(!empty($user->membership_level->enddate))
805
+ {
806
+ $this->data["membership_change"] .= ". " . sprintf(__("This membership will expire on %s", "pmpro"), date(get_option('date_format'), $user->membership_level->enddate));
807
+ }
808
+ elseif(!empty($this->expiration_changed))
809
+ {
810
+ $this->data["membership_change"] .= ". " . __("This membership does not expire", "pmpro");
811
+ }
812
+
813
+ return $this->sendEmail();
814
+ }
815
+ }
classes/gateways/class.pmprogateway.php CHANGED
@@ -1,220 +1,220 @@
1
- <?php
2
- //require_once(dirname(__FILE__) . "/class.pmprogateway.php");
3
- class PMProGateway
4
- {
5
- function PMProGateway($gateway = NULL)
6
- {
7
- $this->gateway = $gateway;
8
- return $this->gateway;
9
- }
10
-
11
- function process(&$order)
12
- {
13
- //check for initial payment
14
- if(floatval($order->InitialPayment) == 0)
15
- {
16
- //auth first, then process
17
- if($this->authorize($order))
18
- {
19
- $this->void($order);
20
- if(!pmpro_isLevelTrial($order->membership_level))
21
- {
22
- //subscription will start today with a 1 period trial
23
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
24
- $order->TrialBillingPeriod = $order->BillingPeriod;
25
- $order->TrialBillingFrequency = $order->BillingFrequency;
26
- $order->TrialBillingCycles = 1;
27
- $order->TrialAmount = 0;
28
-
29
- //add a billing cycle to make up for the trial, if applicable
30
- if(!empty($order->TotalBillingCycles))
31
- $order->TotalBillingCycles++;
32
- }
33
- elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
34
- {
35
- //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
36
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
37
- $order->TrialBillingCycles++;
38
-
39
- //add a billing cycle to make up for the trial, if applicable
40
- if($order->TotalBillingCycles)
41
- $order->TotalBillingCycles++;
42
- }
43
- else
44
- {
45
- //add a period to the start date to account for the initial payment
46
- $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
47
- }
48
-
49
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
50
- return $this->subscribe($order);
51
- }
52
- else
53
- {
54
- if(empty($order->error))
55
- $order->error = __("Unknown error: Authorization failed.", "pmpro");
56
- return false;
57
- }
58
- }
59
- else
60
- {
61
- //charge first payment
62
- if($this->charge($order))
63
- {
64
- //setup recurring billing
65
- if(pmpro_isLevelRecurring($order->membership_level))
66
- {
67
- if(!pmpro_isLevelTrial($order->membership_level))
68
- {
69
- //subscription will start today with a 1 period trial
70
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
71
- $order->TrialBillingPeriod = $order->BillingPeriod;
72
- $order->TrialBillingFrequency = $order->BillingFrequency;
73
- $order->TrialBillingCycles = 1;
74
- $order->TrialAmount = 0;
75
-
76
- //add a billing cycle to make up for the trial, if applicable
77
- if(!empty($order->TotalBillingCycles))
78
- $order->TotalBillingCycles++;
79
- }
80
- elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
81
- {
82
- //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
83
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
84
- $order->TrialBillingCycles++;
85
-
86
- //add a billing cycle to make up for the trial, if applicable
87
- if(!empty($order->TotalBillingCycles))
88
- $order->TotalBillingCycles++;
89
- }
90
- else
91
- {
92
- //add a period to the start date to account for the initial payment
93
- $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $this->BillingFrequency . " " . $this->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
94
- }
95
-
96
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
97
- if($this->subscribe($order))
98
- {
99
- return true;
100
- }
101
- else
102
- {
103
- if($this->void($order))
104
- {
105
- if(!$order->error)
106
- $order->error = __("Unknown error: Payment failed.", "pmpro");
107
- }
108
- else
109
- {
110
- if(!$order->error)
111
- $order->error = __("Unknown error: Payment failed.", "pmpro");
112
-
113
- $order->error .= " " . __("A partial payment was made that we could not void. Please contact the site owner immediately to correct this.", "pmpro");
114
- }
115
-
116
- return false;
117
- }
118
- }
119
- else
120
- {
121
- //only a one time charge
122
- $order->status = "success"; //saved on checkout page
123
- return true;
124
- }
125
- }
126
- else
127
- {
128
- if(empty($order->error))
129
- $order->error = __("Unknown error: Payment failed.", "pmpro");
130
-
131
- return false;
132
- }
133
- }
134
- }
135
-
136
- function authorize(&$order)
137
- {
138
- //create a code for the order
139
- if(empty($order->code))
140
- $order->code = $order->getRandomCode();
141
-
142
- //simulate a successful authorization
143
- $order->payment_transaction_id = "TEST" . $order->code;
144
- $order->updateStatus("authorized");
145
- return true;
146
- }
147
-
148
- function void(&$order)
149
- {
150
- //need a transaction id
151
- if(empty($order->payment_transaction_id))
152
- return false;
153
-
154
- //simulate a successful void
155
- $order->payment_transaction_id = "TEST" . $order->code;
156
- $order->updateStatus("voided");
157
- return true;
158
- }
159
-
160
- function charge(&$order)
161
- {
162
- //create a code for the order
163
- if(empty($order->code))
164
- $order->code = $order->getRandomCode();
165
-
166
- //simulate a successful charge
167
- $order->payment_transaction_id = "TEST" . $order->code;
168
- $order->updateStatus("success");
169
- return true;
170
- }
171
-
172
- function subscribe(&$order)
173
- {
174
- //create a code for the order
175
- if(empty($order->code))
176
- $order->code = $order->getRandomCode();
177
-
178
- //filter order before subscription. use with care.
179
- $order = apply_filters("pmpro_subscribe_order", $order, $this);
180
-
181
- //simulate a successful subscription processing
182
- $order->status = "success";
183
- $order->subscription_transaction_id = "TEST" . $order->code;
184
- return true;
185
- }
186
-
187
- function update(&$order)
188
- {
189
- //simulate a successful billing update
190
- return true;
191
- }
192
-
193
- function cancel(&$order)
194
- {
195
- //require a subscription id
196
- if(empty($order->subscription_transaction_id))
197
- return false;
198
-
199
- //simulate a successful cancel
200
- $order->updateStatus("cancelled");
201
- return true;
202
- }
203
-
204
- function getSubscriptionStatus(&$order)
205
- {
206
- //require a subscription id
207
- if(empty($order->subscription_transaction_id))
208
- return false;
209
-
210
- //this looks different for each gateway, but generally an array of some sort
211
- return array();
212
- }
213
-
214
- function getTransactionStatus(&$order)
215
- {
216
- //this looks different for each gateway, but generally an array of some sort
217
- return array();
218
- }
219
- }
220
- ?>
1
+ <?php
2
+ //require_once(dirname(__FILE__) . "/class.pmprogateway.php");
3
+ class PMProGateway
4
+ {
5
+ function PMProGateway($gateway = NULL)
6
+ {
7
+ $this->gateway = $gateway;
8
+ return $this->gateway;
9
+ }
10
+
11
+ function process(&$order)
12
+ {
13
+ //check for initial payment
14
+ if(floatval($order->InitialPayment) == 0)
15
+ {
16
+ //auth first, then process
17
+ if($this->authorize($order))
18
+ {
19
+ $this->void($order);
20
+ if(!pmpro_isLevelTrial($order->membership_level))
21
+ {
22
+ //subscription will start today with a 1 period trial
23
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
24
+ $order->TrialBillingPeriod = $order->BillingPeriod;
25
+ $order->TrialBillingFrequency = $order->BillingFrequency;
26
+ $order->TrialBillingCycles = 1;
27
+ $order->TrialAmount = 0;
28
+
29
+ //add a billing cycle to make up for the trial, if applicable
30
+ if(!empty($order->TotalBillingCycles))
31
+ $order->TotalBillingCycles++;
32
+ }
33
+ elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
34
+ {
35
+ //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
36
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
37
+ $order->TrialBillingCycles++;
38
+
39
+ //add a billing cycle to make up for the trial, if applicable
40
+ if($order->TotalBillingCycles)
41
+ $order->TotalBillingCycles++;
42
+ }
43
+ else
44
+ {
45
+ //add a period to the start date to account for the initial payment
46
+ $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
47
+ }
48
+
49
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
50
+ return $this->subscribe($order);
51
+ }
52
+ else
53
+ {
54
+ if(empty($order->error))
55
+ $order->error = __("Unknown error: Authorization failed.", "pmpro");
56
+ return false;
57
+ }
58
+ }
59
+ else
60
+ {
61
+ //charge first payment
62
+ if($this->charge($order))
63
+ {
64
+ //setup recurring billing
65
+ if(pmpro_isLevelRecurring($order->membership_level))
66
+ {
67
+ if(!pmpro_isLevelTrial($order->membership_level))
68
+ {
69
+ //subscription will start today with a 1 period trial
70
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
71
+ $order->TrialBillingPeriod = $order->BillingPeriod;
72
+ $order->TrialBillingFrequency = $order->BillingFrequency;
73
+ $order->TrialBillingCycles = 1;
74
+ $order->TrialAmount = 0;
75
+
76
+ //add a billing cycle to make up for the trial, if applicable
77
+ if(!empty($order->TotalBillingCycles))
78
+ $order->TotalBillingCycles++;
79
+ }
80
+ elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
81
+ {
82
+ //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
83
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
84
+ $order->TrialBillingCycles++;
85
+
86
+ //add a billing cycle to make up for the trial, if applicable
87
+ if(!empty($order->TotalBillingCycles))
88
+ $order->TotalBillingCycles++;
89
+ }
90
+ else
91
+ {
92
+ //add a period to the start date to account for the initial payment
93
+ $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $this->BillingFrequency . " " . $this->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
94
+ }
95
+
96
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
97
+ if($this->subscribe($order))
98
+ {
99
+ return true;
100
+ }
101
+ else
102
+ {
103
+ if($this->void($order))
104
+ {
105
+ if(!$order->error)
106
+ $order->error = __("Unknown error: Payment failed.", "pmpro");
107
+ }
108
+ else
109
+ {
110
+ if(!$order->error)
111
+ $order->error = __("Unknown error: Payment failed.", "pmpro");
112
+
113
+ $order->error .= " " . __("A partial payment was made that we could not void. Please contact the site owner immediately to correct this.", "pmpro");
114
+ }
115
+
116
+ return false;
117
+ }
118
+ }
119
+ else
120
+ {
121
+ //only a one time charge
122
+ $order->status = "success"; //saved on checkout page
123
+ return true;
124
+ }
125
+ }
126
+ else
127
+ {
128
+ if(empty($order->error))
129
+ $order->error = __("Unknown error: Payment failed.", "pmpro");
130
+
131
+ return false;
132
+ }
133
+ }
134
+ }
135
+
136
+ function authorize(&$order)
137
+ {
138
+ //create a code for the order
139
+ if(empty($order->code))
140
+ $order->code = $order->getRandomCode();
141
+
142
+ //simulate a successful authorization
143
+ $order->payment_transaction_id = "TEST" . $order->code;
144
+ $order->updateStatus("authorized");
145
+ return true;
146
+ }
147
+
148
+ function void(&$order)
149
+ {
150
+ //need a transaction id
151
+ if(empty($order->payment_transaction_id))
152
+ return false;
153
+
154
+ //simulate a successful void
155
+ $order->payment_transaction_id = "TEST" . $order->code;
156
+ $order->updateStatus("voided");
157
+ return true;
158
+ }
159
+
160
+ function charge(&$order)
161
+ {
162
+ //create a code for the order
163
+ if(empty($order->code))
164
+ $order->code = $order->getRandomCode();
165
+
166
+ //simulate a successful charge
167
+ $order->payment_transaction_id = "TEST" . $order->code;
168
+ $order->updateStatus("success");
169
+ return true;
170
+ }
171
+
172
+ function subscribe(&$order)
173
+ {
174
+ //create a code for the order
175
+ if(empty($order->code))
176
+ $order->code = $order->getRandomCode();
177
+
178
+ //filter order before subscription. use with care.
179
+ $order = apply_filters("pmpro_subscribe_order", $order, $this);
180
+
181
+ //simulate a successful subscription processing
182
+ $order->status = "success";
183
+ $order->subscription_transaction_id = "TEST" . $order->code;
184
+ return true;
185
+ }
186
+
187
+ function update(&$order)
188
+ {
189
+ //simulate a successful billing update
190
+ return true;
191
+ }
192
+
193
+ function cancel(&$order)
194
+ {
195
+ //require a subscription id
196
+ if(empty($order->subscription_transaction_id))
197
+ return false;
198
+
199
+ //simulate a successful cancel
200
+ $order->updateStatus("cancelled");
201
+ return true;
202
+ }
203
+
204
+ function getSubscriptionStatus(&$order)
205
+ {
206
+ //require a subscription id
207
+ if(empty($order->subscription_transaction_id))
208
+ return false;
209
+
210
+ //this looks different for each gateway, but generally an array of some sort
211
+ return array();
212
+ }
213
+
214
+ function getTransactionStatus(&$order)
215
+ {
216
+ //this looks different for each gateway, but generally an array of some sort
217
+ return array();
218
+ }
219
+ }
220
+ ?>
classes/gateways/class.pmprogateway_authorizenet.php CHANGED
@@ -1,53 +1,53 @@
1
  <?php
2
  //include pmprogateway
3
  require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
-
5
  //load classes init method
6
  add_action('init', array('PMProGateway_authorizenet', 'init'));
7
-
8
  class PMProGateway_authorizenet extends PMProGateway
9
  {
10
  function PMProGateway_authorizenet($gateway = NULL)
11
  {
12
  $this->gateway = $gateway;
13
  return $this->gateway;
14
- }
15
-
16
  /**
17
  * Run on WP init
18
- *
19
  * @since 1.8
20
  */
21
  static function init()
22
- {
23
  //make sure Authorize.net is a gateway option
24
  add_filter('pmpro_gateways', array('PMProGateway_authorizenet', 'pmpro_gateways'));
25
-
26
  //add fields to payment settings
27
  add_filter('pmpro_payment_options', array('PMProGateway_authorizenet', 'pmpro_payment_options'));
28
- add_filter('pmpro_payment_option_fields', array('PMProGateway_authorizenet', 'pmpro_payment_option_fields'), 10, 2);
29
  }
30
-
31
  /**
32
  * Make sure this gateway is in the gateways list
33
- *
34
  * @since 1.8
35
  */
36
  static function pmpro_gateways($gateways)
37
  {
38
  if(empty($gateways['authorizenet']))
39
  $gateways['authorizenet'] = __('Authorize.net', 'pmpro');
40
-
41
  return $gateways;
42
  }
43
-
44
  /**
45
  * Get a list of payment options that the this gateway needs/supports.
46
- *
47
  * @since 1.8
48
  */
49
  static function getGatewayOptions()
50
- {
51
  $options = array(
52
  'sslseal',
53
  'nuclear_HTTPS',
@@ -60,29 +60,29 @@
60
  'tax_rate',
61
  'accepted_credit_cards'
62
  );
63
-
64
  return $options;
65
  }
66
-
67
  /**
68
  * Set payment options for payment settings page.
69
- *
70
  * @since 1.8
71
  */
72
  static function pmpro_payment_options($options)
73
- {
74
  //get stripe options
75
  $authorizenet_options = PMProGateway_authorizenet::getGatewayOptions();
76
-
77
  //merge with others.
78
  $options = array_merge($authorizenet_options, $options);
79
-
80
  return $options;
81
  }
82
-
83
  /**
84
  * Display fields for this gateway's options.
85
- *
86
  * @since 1.8
87
  */
88
  static function pmpro_payment_option_fields($values, $gateway)
@@ -119,10 +119,10 @@
119
  </tr>
120
  <?php
121
  }
122
-
123
  /**
124
  * Process checkout.
125
- *
126
  */
127
  function process(&$order)
128
  {
@@ -131,17 +131,17 @@
131
  {
132
  //auth first, then process
133
  if($this->authorize($order))
134
- {
135
- $this->void($order);
136
  if(!pmpro_isLevelTrial($order->membership_level))
137
  {
138
  //subscription will start today with a 1 period trial
139
  $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
140
  $order->TrialBillingPeriod = $order->BillingPeriod;
141
- $order->TrialBillingFrequency = $order->BillingFrequency;
142
  $order->TrialBillingCycles = 1;
143
  $order->TrialAmount = 0;
144
-
145
  //add a billing cycle to make up for the trial, if applicable
146
  if(!empty($order->TotalBillingCycles))
147
  $order->TotalBillingCycles++;
@@ -149,9 +149,9 @@
149
  elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
150
  {
151
  //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
152
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
153
  $order->TrialBillingCycles++;
154
-
155
  //add a billing cycle to make up for the trial, if applicable
156
  if(!empty($order->TotalBillingCycles))
157
  $order->TotalBillingCycles++;
@@ -161,12 +161,12 @@
161
  //add a period to the start date to account for the initial payment
162
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
163
  }
164
-
165
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
166
  return $this->subscribe($order);
167
  }
168
  else
169
- {
170
  if(empty($order->error))
171
  $order->error = __("Unknown error: Authorization failed.", "pmpro");
172
  return false;
@@ -176,19 +176,19 @@
176
  {
177
  //charge first payment
178
  if($this->charge($order))
179
- {
180
  //setup recurring billing
181
  if(pmpro_isLevelRecurring($order->membership_level))
182
- {
183
  if(!pmpro_isLevelTrial($order->membership_level))
184
  {
185
  //subscription will start today with a 1 period trial
186
  $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
187
  $order->TrialBillingPeriod = $order->BillingPeriod;
188
- $order->TrialBillingFrequency = $order->BillingFrequency;
189
  $order->TrialBillingCycles = 1;
190
  $order->TrialAmount = 0;
191
-
192
  //add a billing cycle to make up for the trial, if applicable
193
  if(!empty($order->TotalBillingCycles))
194
  $order->TotalBillingCycles++;
@@ -196,9 +196,9 @@
196
  elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
197
  {
198
  //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
199
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
200
  $order->TrialBillingCycles++;
201
-
202
  //add a billing cycle to make up for the trial, if applicable
203
  if(!empty($order->TotalBillingCycles))
204
  $order->TotalBillingCycles++;
@@ -208,7 +208,7 @@
208
  //add a period to the start date to account for the initial payment
209
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
210
  }
211
-
212
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
213
  if($this->subscribe($order))
214
  {
@@ -224,66 +224,66 @@
224
  else
225
  {
226
  if(!$order->error)
227
- $order->error = __("Unknown error: Payment failed.", "pmpro");
228
  $order->error .= " " . __("A partial payment was made that we could not void. Please contact the site owner immediately to correct this.", "pmpro");
229
  }
230
-
231
- return false;
232
  }
233
  }
234
  else
235
  {
236
  //only a one time charge
237
- $order->status = "success"; //saved on checkout page
238
  return true;
239
  }
240
  }
241
  else
242
- {
243
  if(empty($order->error))
244
  $order->error = __("Unknown error: Payment failed.", "pmpro");
245
-
246
  return false;
247
- }
248
- }
249
  }
250
-
251
  function authorize(&$order)
252
  {
253
  if(empty($order->code))
254
  $order->code = $order->getRandomCode();
255
-
256
  if(empty($order->gateway_environment))
257
  $gateway_environment = pmpro_getOption("gateway_environment");
258
  else
259
  $gateway_environment = $order->gateway_environment;
260
  if($gateway_environment == "live")
261
- $host = "secure.authorize.net";
262
  else
263
- $host = "test.authorize.net";
264
-
265
- $path = "/gateway/transact.dll";
266
  $post_url = "https://" . $host . $path;
267
 
268
  $post_url = apply_filters("pmpro_authorizenet_post_url", $post_url, $gateway_environment);
269
-
270
  //what amount to authorize? just $1 to test
271
- $amount = "1.00";
272
-
273
- //combine address
274
  $address = $order->Address1;
275
  if(!empty($order->Address2))
276
  $address .= "\n" . $order->Address2;
277
-
278
  //customer stuff
279
  $customer_email = $order->Email;
280
  $customer_phone = $order->billing->phone;
281
-
282
  if(!isset($order->membership_level->name))
283
  $order->membership_level->name = "";
284
-
285
  $post_values = array(
286
-
287
  // the API Login ID and Transaction Key must be replaced with valid values
288
  "x_login" => pmpro_getOption("loginname"),
289
  "x_tran_key" => pmpro_getOption("transactionkey"),
@@ -298,7 +298,7 @@
298
  "x_card_type" => $order->cardtype,
299
  "x_card_num" => $order->accountnumber,
300
  "x_exp_date" => $order->ExpirationDate,
301
-
302
  "x_amount" => $amount,
303
  "x_description" => $order->membership_level->name . " " . __("Membership", "pmpro"),
304
 
@@ -315,17 +315,17 @@
315
  // Additional fields can be added here as outlined in the AIM integration
316
  // guide at: http://developer.authorize.net
317
  );
318
-
319
  if(!empty($order->CVV2))
320
  $post_values["x_card_code"] = $order->CVV2;
321
-
322
  // This section takes the input fields and converts them to the proper format
323
  // for an http post. For example: "x_login=username&x_tran_key=a1B2c3D4"
324
  $post_string = "";
325
  foreach( $post_values as $key => $value )
326
  { $post_string .= "$key=" . urlencode( str_replace("#", "%23", $value) ) . "&"; }
327
  $post_string = rtrim( $post_string, "& " );
328
-
329
  //curl
330
  $request = curl_init($post_url); // initiate curl object
331
  curl_setopt($request, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response
@@ -336,15 +336,15 @@
336
  // additional options may be required depending upon your server configuration
337
  // you can find documentation on curl options at http://www.php.net/curl_setopt
338
  curl_close ($request); // close curl object
339
-
340
  // This line takes the response and breaks it into an array using the specified delimiting character
341
  $response_array = explode($post_values["x_delim_char"],$post_response);
342
-
343
  if($response_array[0] == 1)
344
  {
345
  $order->payment_transaction_id = $response_array[6];
346
- $order->updateStatus("authorized");
347
-
348
  return true;
349
  }
350
  else
@@ -354,30 +354,30 @@
354
  $order->error = $response_array[3];
355
  $order->shorterror = $response_array[3];
356
  return false;
357
- }
358
  }
359
-
360
  function void(&$order)
361
  {
362
  if(empty($order->payment_transaction_id))
363
  return false;
364
-
365
  if(empty($order->gateway_environment))
366
  $gateway_environment = pmpro_getOption("gateway_environment");
367
  else
368
  $gateway_environment = $order->gateway_environment;
369
  if($gateway_environment == "live")
370
- $host = "secure.authorize.net";
371
  else
372
- $host = "test.authorize.net";
373
-
374
- $path = "/gateway/transact.dll";
375
  $post_url = "https://" . $host . $path;
376
-
377
  $post_url = apply_filters("pmpro_authorizenet_post_url", $post_url, $gateway_environment);
378
-
379
  $post_values = array(
380
-
381
  // the API Login ID and Transaction Key must be replaced with valid values
382
  "x_login" => pmpro_getOption("loginname"),
383
  "x_tran_key" => pmpro_getOption("transactionkey"),
@@ -392,14 +392,14 @@
392
  // Additional fields can be added here as outlined in the AIM integration
393
  // guide at: http://developer.authorize.net
394
  );
395
-
396
  // This section takes the input fields and converts them to the proper format
397
  // for an http post. For example: "x_login=username&x_tran_key=a1B2c3D4"
398
  $post_string = "";
399
  foreach( $post_values as $key => $value )
400
  { $post_string .= "$key=" . urlencode( str_replace("#", "%23", $value) ) . "&"; }
401
  $post_string = rtrim( $post_string, "& " );
402
-
403
  //curl
404
  $request = curl_init($post_url); // initiate curl object
405
  curl_setopt($request, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response
@@ -410,13 +410,13 @@
410
  // additional options may be required depending upon your server configuration
411
  // you can find documentation on curl options at http://www.php.net/curl_setopt
412
  curl_close ($request); // close curl object
413
-
414
  // This line takes the response and breaks it into an array using the specified delimiting character
415
  $response_array = explode($post_values["x_delim_char"],$post_response);
416
  if($response_array[0] == 1)
417
  {
418
  $order->payment_transaction_id = $response_array[4];
419
- $order->updateStatus("voided");
420
  return true;
421
  }
422
  else
@@ -426,50 +426,50 @@
426
  $order->error = $response_array[3];
427
  $order->shorterror = $response_array[3];
428
  return false;
429
- }
430
- }
431
-
432
  function charge(&$order)
433
  {
434
  if(empty($order->code))
435
  $order->code = $order->getRandomCode();
436
-
437
  if(!empty($order->gateway_environment))
438
  $gateway_environment = $order->gateway_environment;
439
  if(empty($gateway_environment))
440
  $gateway_environment = pmpro_getOption("gateway_environment");
441
  if($gateway_environment == "live")
442
- $host = "secure.authorize.net";
443
  else
444
- $host = "test.authorize.net";
445
-
446
- $path = "/gateway/transact.dll";
447
  $post_url = "https://" . $host . $path;
448
 
449
  $post_url = apply_filters("pmpro_authorizenet_post_url", $post_url, $gateway_environment);
450
-
451
- //what amount to charge?
452
  $amount = $order->InitialPayment;
453
-
454
  //tax
455
  $order->subtotal = $amount;
456
  $tax = $order->getTax(true);
457
  $amount = round((float)$order->subtotal + (float)$tax, 2);
458
-
459
- //combine address
460
  $address = $order->Address1;
461
  if(!empty($order->Address2))
462
  $address .= "\n" . $order->Address2;
463
-
464
  //customer stuff
465
  $customer_email = $order->Email;
466
  $customer_phone = $order->billing->phone;
467
-
468
  if(!isset($order->membership_level->name))
469
  $order->membership_level->name = "";
470
-
471
  $post_values = array(
472
-
473
  // the API Login ID and Transaction Key must be replaced with valid values
474
  "x_login" => pmpro_getOption("loginname"),
475
  "x_tran_key" => pmpro_getOption("transactionkey"),
@@ -483,8 +483,8 @@
483
  "x_method" => "CC",
484
  "x_card_type" => $order->cardtype,
485
  "x_card_num" => $order->accountnumber,
486
- "x_exp_date" => $order->ExpirationDate,
487
-
488
  "x_amount" => $amount,
489
  "x_tax" => $tax,
490
  "x_description" => $order->membership_level->name . " Membership",
@@ -499,21 +499,21 @@
499
  "x_invoice_num" => $order->code,
500
  "x_phone" => $customer_phone,
501
  "x_email" => $order->Email
502
-
503
  // Additional fields can be added here as outlined in the AIM integration
504
  // guide at: http://developer.authorize.net
505
- );
506
-
507
  if(!empty($order->CVV2))
508
  $post_values["x_card_code"] = $order->CVV2;
509
-
510
  // This section takes the input fields and converts them to the proper format
511
  // for an http post. For example: "x_login=username&x_tran_key=a1B2c3D4"
512
  $post_string = "";
513
  foreach( $post_values as $key => $value )
514
  { $post_string .= "$key=" . urlencode( str_replace("#", "%23", $value) ) . "&"; }
515
  $post_string = rtrim( $post_string, "& " );
516
-
517
  //curl
518
  $request = curl_init($post_url); // initiate curl object
519
  curl_setopt($request, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response
@@ -524,13 +524,13 @@
524
  // additional options may be required depending upon your server configuration
525
  // you can find documentation on curl options at http://www.php.net/curl_setopt
526
  curl_close ($request); // close curl object
527
-
528
  // This line takes the response and breaks it into an array using the specified delimiting character
529
  $response_array = explode($post_values["x_delim_char"],$post_response);
530
  if($response_array[0] == 1)
531
  {
532
  $order->payment_transaction_id = $response_array[6];
533
- $order->updateStatus("success");
534
  return true;
535
  }
536
  else
@@ -540,38 +540,38 @@
540
  $order->error = $response_array[3];
541
  $order->shorterror = $response_array[3];
542
  return false;
543
- }
544
  }
545
-
546
  function subscribe(&$order)
547
  {
548
  //define variables to send
549
 
550
  if(empty($order->code))
551
  $order->code = $order->getRandomCode();
552
-
553
  //filter order before subscription. use with care.
554
  $order = apply_filters("pmpro_subscribe_order", $order, $this);
555
-
556
  if(!empty($order->gateway_environment))
557
  $gateway_environment = $order->gateway_environment;
558
  if(empty($gateway_environment))
559
  $gateway_environment = pmpro_getOption("gateway_environment");
560
  if($gateway_environment == "live")
561
- $host = "api.authorize.net";
562
  else
563
- $host = "apitest.authorize.net";
564
-
565
  $path = "/xml/v1/request.api";
566
-
567
  $loginname = pmpro_getOption("loginname");
568
  $transactionkey = pmpro_getOption("transactionkey");
569
-
570
  $amount = $order->PaymentAmount;
571
  $refId = $order->code;
572
  $name = $order->membership_name;
573
  $length = (int)$order->BillingFrequency;
574
-
575
  if($order->BillingPeriod == "Month")
576
  $unit = "months";
577
  elseif($order->BillingPeriod == "Day")
@@ -588,13 +588,13 @@
588
  }
589
  else
590
  return false; //authorize.net only supports months and days
591
-
592
  $startDate = substr($order->ProfileStartDate, 0, 10);
593
  if(!empty($order->TotalBillingCycles))
594
  $totalOccurrences = (int)$order->TotalBillingCycles;
595
  if(empty($totalOccurrences))
596
- $totalOccurrences = 9999;
597
- if(isset($order->TrialBillingCycles))
598
  $trialOccurrences = (int)$order->TrialBillingCycles;
599
  else
600
  $trialOccurrences = 0;
@@ -602,26 +602,26 @@
602
  $trialAmount = $order->TrialAmount;
603
  else
604
  $trialAmount = NULL;
605
-
606
  //taxes
607
  $amount_tax = $order->getTaxForPrice($amount);
608
  $trial_tax = $order->getTaxForPrice($trialAmount);
609
-
610
  $amount = round((float)$amount + (float)$amount_tax, 2);
611
  $trialAmount = round((float)$trialAmount + (float)$trial_tax, 2);
612
-
613
  //authorize.net doesn't support different periods between trial and actual
614
-
615
  if(!empty($order->TrialBillingPeriod) && $order->TrialBillingPeriod != $order->BillingPeriod)
616
  {
617
  echo "F";
618
  return false;
619
  }
620
-
621
- $cardNumber = $order->accountnumber;
622
- $expirationDate = $order->ExpirationDate_YdashM;
623
  $cardCode = $order->CVV2;
624
-
625
  $firstName = $order->FirstName;
626
  $lastName = $order->LastName;
627
 
@@ -632,20 +632,20 @@
632
  $city = $order->billing->city;
633
  $state = $order->billing->state;
634
  $zip = $order->billing->zip;
635
- $country = $order->billing->country;
636
-
637
  //customer stuff
638
  $customer_email = $order->Email;
639
  if(strpos($order->billing->phone, "+") === false)
640
  $customer_phone = $order->billing->phone;
641
  else
642
  $customer_phone = "";
643
-
644
  //make sure the phone is in an okay format
645
  $customer_phone = preg_replace("/[^0-9]/", "", $customer_phone);
646
  if(strlen($customer_phone) > 10)
647
  $customer_phone = "";
648
-
649
  //build xml to post
650
  $this->content =
651
  "<?xml version=\"1.0\" encoding=\"utf-8\"?>" .
@@ -665,9 +665,9 @@
665
  "<startDate>" . $startDate . "</startDate>".
666
  "<totalOccurrences>". $totalOccurrences . "</totalOccurrences>";
667
  if(!empty($trialOccurrences))
668
- $this->content .=
669
  "<trialOccurrences>". $trialOccurrences . "</trialOccurrences>";
670
- $this->content .=
671
  "</paymentSchedule>".
672
  "<amount>". $amount ."</amount>";
673
  if(!empty($trialOccurrences))
@@ -680,7 +680,7 @@
680
  "<expirationDate>" . $expirationDate . "</expirationDate>";
681
  if(!empty($cardCode))
682
  $this->content .= "<cardCode>" . $cardCode . "</cardCode>";
683
- $this->content .=
684
  "</creditCard>".
685
  "</payment>".
686
  "<order><invoiceNumber>" . substr($order->code, 0, 20) . "</invoiceNumber></order>".
@@ -695,24 +695,24 @@
695
  "<city><![CDATA[" . substr($city, 0, 40) . "]]></city>".
696
  "<state>". substr($state, 0, 2) . "</state>".
697
  "<zip>" . substr($zip, 0, 20) . "</zip>".
698
- "<country>". substr($country, 0, 60) . "</country>".
699
  "</billTo>".
700
  "</subscription>".
701
  "</ARBCreateSubscriptionRequest>";
702
-
703
  //send the xml via curl
704
  $this->response = $this->send_request_via_curl($host,$path,$this->content);
705
  //if curl is unavilable you can try using fsockopen
706
  /*
707
  $response = send_request_via_fsockopen($host,$path,$content);
708
  */
709
-
710
- if(!empty($this->response)) {
711
  list ($refId, $resultCode, $code, $text, $subscriptionId) = $this->parse_return($this->response);
712
  if($resultCode == "Ok")
713
  {
714
- $order->status = "success"; //saved on checkout page
715
- $order->subscription_transaction_id = $subscriptionId;
716
  return true;
717
  }
718
  else
@@ -720,41 +720,41 @@
720
  $order->status = "error";
721
  $order->errorcode = $code;
722
  $order->error = $text;
723
- $order->shorterror = $text;
724
  return false;
725
  }
726
- } else {
727
  $order->status = "error";
728
  $order->error = "Could not connect to Authorize.net";
729
  $order->shorterror = "Could not connect to Authorize.net";
730
- return false;
731
  }
732
- }
733
-
734
  function update(&$order)
735
  {
736
- //define variables to send
737
  $gateway_environment = $order->gateway_environment;
738
  if(empty($gateway_environment))
739
  $gateway_environment = pmpro_getOption("gateway_environment");
740
  if($gateway_environment == "live")
741
- $host = "api.authorize.net";
742
  else
743
- $host = "apitest.authorize.net";
744
-
745
  $path = "/xml/v1/request.api";
746
-
747
  $loginname = pmpro_getOption("loginname");
748
  $transactionkey = pmpro_getOption("transactionkey");
749
-
750
  //$amount = $order->PaymentAmount;
751
  $refId = $order->code;
752
- $subscriptionId = $order->subscription_transaction_id;
753
-
754
- $cardNumber = $order->accountnumber;
755
- $expirationDate = $order->ExpirationDate_YdashM;
756
  $cardCode = $order->CVV2;
757
-
758
  $firstName = $order->FirstName;
759
  $lastName = $order->LastName;
760
 
@@ -765,14 +765,14 @@
765
  $city = $order->billing->city;
766
  $state = $order->billing->state;
767
  $zip = $order->billing->zip;
768
- $country = $order->billing->country;
769
-
770
  //customer stuff
771
  $customer_email = $order->Email;
772
  if(strpos($order->billing->phone, "+") === false)
773
  $customer_phone = $order->billing->phone;
774
-
775
-
776
  //build xml to post
777
  $this->content =
778
  "<?xml version=\"1.0\" encoding=\"utf-8\"?>" .
@@ -783,14 +783,14 @@
783
  "</merchantAuthentication>".
784
  "<refId>" . substr($refId, 0, 20) . "</refId>".
785
  "<subscriptionId>" . $subscriptionId . "</subscriptionId>".
786
- "<subscription>".
787
  "<payment>".
788
  "<creditCard>".
789
  "<cardNumber>" . $cardNumber . "</cardNumber>".
790
  "<expirationDate>" . $expirationDate . "</expirationDate>";
791
  if(!empty($cardCode))
792
  $this->content .= "<cardCode>" . $cardCode . "</cardCode>";
793
- $this->content .=
794
  "</creditCard>".
795
  "</payment>".
796
  "<customer>".
@@ -804,24 +804,24 @@
804
  "<city><![CDATA[" . substr($city, 0, 40) . "]]></city>".
805
  "<state><![CDATA[". substr($state, 0, 2) . "]]></state>".
806
  "<zip>" . substr($zip, 0, 20) . "</zip>".
807
- "<country>". substr($country, 0, 60) . "</country>".
808
  "</billTo>".
809
  "</subscription>".
810
  "</ARBUpdateSubscriptionRequest>";
811
-
812
  //send the xml via curl
813
  $this->response = $this->send_request_via_curl($host,$path,$this->content);
814
  //if curl is unavilable you can try using fsockopen
815
  /*
816
  $response = send_request_via_fsockopen($host,$path,$order->content);
817
  */
818
-
819
-
820
- if(!empty($this->response)) {
821
- list ($resultCode, $code, $text, $subscriptionId) = $this->parse_return($this->response);
822
-
823
  if($resultCode == "Ok" || $code == "Ok")
824
- {
825
  return true;
826
  }
827
  else
@@ -832,39 +832,39 @@
832
  $order->shorterror = $text;
833
  return false;
834
  }
835
- } else {
836
  $order->status = "error";
837
  $order->error = "Could not connect to Authorize.net";
838
  $order->shorterror = "Could not connect to Authorize.net";
839
- return false;
840
  }
841
  }
842
-
843
  function cancel(&$order)
844
  {
845
- //define variables to send
846
  if(!empty($order->subscription_transaction_id))
847
  $subscriptionId = $order->subscription_transaction_id;
848
  else
849
  $subscriptionId = "";
850
  $loginname = pmpro_getOption("loginname");
851
  $transactionkey = pmpro_getOption("transactionkey");
852
-
853
  if(!empty($order->gateway_environment))
854
  $gateway_environment = $order->gateway_environment;
855
  else
856
- $gateway_environment = pmpro_getOption("gateway_environment");
857
-
858
  if($gateway_environment == "live")
859
- $host = "api.authorize.net";
860
  else
861
- $host = "apitest.authorize.net";
862
-
863
  $path = "/xml/v1/request.api";
864
-
865
  if(!$subscriptionId || !$loginname || !$transactionkey)
866
  return false;
867
-
868
  //build xml to post
869
  $content =
870
  "<?xml version=\"1.0\" encoding=\"utf-8\"?>".
@@ -875,22 +875,22 @@
875
  "</merchantAuthentication>" .
876
  "<subscriptionId>" . $subscriptionId . "</subscriptionId>".
877
  "</ARBCancelSubscriptionRequest>";
878
-
879
  //send the xml via curl
880
  $response = $this->send_request_via_curl($host,$path,$content);
881
  //if curl is unavilable you can try using fsockopen
882
  /*
883
  $response = send_request_via_fsockopen($host,$path,$content);
884
  */
885
-
886
  //if the connection and send worked $response holds the return from Authorize.net
887
  if ($response)
888
- {
889
- list ($resultCode, $code, $text, $subscriptionId) = $this->parse_return($response);
890
-
891
  if($resultCode == "Ok" || $code == "Ok")
892
  {
893
- $order->updateStatus("cancelled");
894
  return true;
895
  }
896
  else
@@ -901,41 +901,41 @@
901
  $order->shorterror = $text;
902
  return false;
903
  }
904
- }
905
- else
906
- {
907
  $order->status = "error";
908
  $order->error = __("Could not connect to Authorize.net", "pmpro");
909
  $order->shorterror = __("Could not connect to Authorize.net", "pmpro");
910
- return false;
911
  }
912
- }
913
-
914
  function getSubscriptionStatus(&$order)
915
- {
916
- //define variables to send
917
  if(!empty($order->subscription_transaction_id))
918
  $subscriptionId = $order->subscription_transaction_id;
919
  else
920
  $subscriptionId = "";
921
  $loginname = pmpro_getOption("loginname");
922
  $transactionkey = pmpro_getOption("transactionkey");
923
-
924
  if(!empty($order->gateway_environment))
925
  $gateway_environment = $order->gateway_environment;
926
  else
927
- $gateway_environment = pmpro_getOption("gateway_environment");
928
-
929
  if($gateway_environment == "live")
930
- $host = "api.authorize.net";
931
  else
932
- $host = "apitest.authorize.net";
933
-
934
  $path = "/xml/v1/request.api";
935
-
936
  if(!$subscriptionId || !$loginname || !$transactionkey)
937
  return false;
938
-
939
  //build xml to post
940
  $content =
941
  "<?xml version=\"1.0\" encoding=\"utf-8\"?>".
@@ -946,43 +946,43 @@
946
  "</merchantAuthentication>" .
947
  "<subscriptionId>" . $subscriptionId . "</subscriptionId>".
948
  "</ARBGetSubscriptionStatusRequest>";
949
-
950
  //send the xml via curl
951
  $response = $this->send_request_via_curl($host,$path,$content);
952
-
953
  //if curl is unavilable you can try using fsockopen
954
  /*
955
  $response = send_request_via_fsockopen($host,$path,$content);
956
  */
957
-
958
  //if the connection and send worked $response holds the return from Authorize.net
959
  if($response)
960
- {
961
- list ($resultCode, $code, $text, $subscriptionId) = $this->parse_return($response);
962
-
963
  $status = $this->substring_between($response,'<status>','</status>');
964
-
965
  if($resultCode == "Ok" || $code == "Ok")
966
  {
967
  return $status;
968
  }
969
  else
970
- {
971
  $order->status = "error";
972
  $order->errorcode = $resultCode;
973
  $order->error = $message;
974
  $order->shorterror = $text;
975
  }
976
- }
977
- else
978
- {
979
  $order->status = "error";
980
  $order->errorcode = $resultCode;
981
  $order->error = $message;
982
  $order->shorterror = $text;
983
  }
984
- }
985
-
986
  //Authorize.net Function
987
  //function to send xml request via fsockopen
988
  function send_request_via_fsockopen($host,$path,$content)
@@ -1048,13 +1048,13 @@
1048
 
1049
  //Authorize.net Function
1050
  //helper function for parsing response
1051
- function substring_between($haystack,$start,$end)
1052
  {
1053
- if (strpos($haystack,$start) === false || strpos($haystack,$end) === false)
1054
  {
1055
  return false;
1056
- }
1057
- else
1058
  {
1059
  $start_position = strpos($haystack,$start)+strlen($start);
1060
  $end_position = strpos($haystack,$end);
1
  <?php
2
  //include pmprogateway
3
  require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
+
5
  //load classes init method
6
  add_action('init', array('PMProGateway_authorizenet', 'init'));
7
+
8
  class PMProGateway_authorizenet extends PMProGateway
9
  {
10
  function PMProGateway_authorizenet($gateway = NULL)
11
  {
12
  $this->gateway = $gateway;
13
  return $this->gateway;
14
+ }
15
+
16
  /**
17
  * Run on WP init
18
+ *
19
  * @since 1.8
20
  */
21
  static function init()
22
+ {
23
  //make sure Authorize.net is a gateway option
24
  add_filter('pmpro_gateways', array('PMProGateway_authorizenet', 'pmpro_gateways'));
25
+
26
  //add fields to payment settings
27
  add_filter('pmpro_payment_options', array('PMProGateway_authorizenet', 'pmpro_payment_options'));
28
+ add_filter('pmpro_payment_option_fields', array('PMProGateway_authorizenet', 'pmpro_payment_option_fields'), 10, 2);
29
  }
30
+
31
  /**
32
  * Make sure this gateway is in the gateways list
33
+ *
34
  * @since 1.8
35
  */
36
  static function pmpro_gateways($gateways)
37
  {
38
  if(empty($gateways['authorizenet']))
39
  $gateways['authorizenet'] = __('Authorize.net', 'pmpro');
40
+
41
  return $gateways;
42
  }
43
+
44
  /**
45
  * Get a list of payment options that the this gateway needs/supports.
46
+ *
47
  * @since 1.8
48
  */
49
  static function getGatewayOptions()
50
+ {
51
  $options = array(
52
  'sslseal',
53
  'nuclear_HTTPS',
60
  'tax_rate',
61
  'accepted_credit_cards'
62
  );
63
+
64
  return $options;
65
  }
66
+
67
  /**
68
  * Set payment options for payment settings page.
69
+ *
70
  * @since 1.8
71
  */
72
  static function pmpro_payment_options($options)
73
+ {
74
  //get stripe options
75
  $authorizenet_options = PMProGateway_authorizenet::getGatewayOptions();
76
+
77
  //merge with others.
78
  $options = array_merge($authorizenet_options, $options);
79
+
80
  return $options;
81
  }
82
+
83
  /**
84
  * Display fields for this gateway's options.
85
+ *
86
  * @since 1.8
87
  */
88
  static function pmpro_payment_option_fields($values, $gateway)
119
  </tr>
120
  <?php
121
  }
122
+
123
  /**
124
  * Process checkout.
125
+ *
126
  */
127
  function process(&$order)
128
  {
131
  {
132
  //auth first, then process
133
  if($this->authorize($order))
134
+ {
135
+ $this->void($order);
136
  if(!pmpro_isLevelTrial($order->membership_level))
137
  {
138
  //subscription will start today with a 1 period trial
139
  $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
140
  $order->TrialBillingPeriod = $order->BillingPeriod;
141
+ $order->TrialBillingFrequency = $order->BillingFrequency;
142
  $order->TrialBillingCycles = 1;
143
  $order->TrialAmount = 0;
144
+
145
  //add a billing cycle to make up for the trial, if applicable
146
  if(!empty($order->TotalBillingCycles))
147
  $order->TotalBillingCycles++;
149
  elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
150
  {
151
  //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
152
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
153
  $order->TrialBillingCycles++;
154
+
155
  //add a billing cycle to make up for the trial, if applicable
156
  if(!empty($order->TotalBillingCycles))
157
  $order->TotalBillingCycles++;
161
  //add a period to the start date to account for the initial payment
162
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
163
  }
164
+
165
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
166
  return $this->subscribe($order);
167
  }
168
  else
169
+ {
170
  if(empty($order->error))
171
  $order->error = __("Unknown error: Authorization failed.", "pmpro");
172
  return false;
176
  {
177
  //charge first payment
178
  if($this->charge($order))
179
+ {
180
  //setup recurring billing
181
  if(pmpro_isLevelRecurring($order->membership_level))
182
+ {
183
  if(!pmpro_isLevelTrial($order->membership_level))
184
  {
185
  //subscription will start today with a 1 period trial
186
  $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
187
  $order->TrialBillingPeriod = $order->BillingPeriod;
188
+ $order->TrialBillingFrequency = $order->BillingFrequency;
189
  $order->TrialBillingCycles = 1;
190
  $order->TrialAmount = 0;
191
+
192
  //add a billing cycle to make up for the trial, if applicable
193
  if(!empty($order->TotalBillingCycles))
194
  $order->TotalBillingCycles++;
196
  elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
197
  {
198
  //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
199
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
200
  $order->TrialBillingCycles++;
201
+
202
  //add a billing cycle to make up for the trial, if applicable
203
  if(!empty($order->TotalBillingCycles))
204
  $order->TotalBillingCycles++;
208
  //add a period to the start date to account for the initial payment
209
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
210
  }
211
+
212
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
213
  if($this->subscribe($order))
214
  {
224
  else
225
  {
226
  if(!$order->error)
227
+ $order->error = __("Unknown error: Payment failed.", "pmpro");
228
  $order->error .= " " . __("A partial payment was made that we could not void. Please contact the site owner immediately to correct this.", "pmpro");
229
  }
230
+
231
+ return false;
232
  }
233
  }
234
  else
235
  {
236
  //only a one time charge
237
+ $order->status = "success"; //saved on checkout page
238
  return true;
239
  }
240
  }
241
  else
242
+ {
243
  if(empty($order->error))
244
  $order->error = __("Unknown error: Payment failed.", "pmpro");
245
+
246
  return false;
247
+ }
248
+ }
249
  }
250
+
251
  function authorize(&$order)
252
  {
253
  if(empty($order->code))
254
  $order->code = $order->getRandomCode();
255
+
256
  if(empty($order->gateway_environment))
257
  $gateway_environment = pmpro_getOption("gateway_environment");
258
  else
259
  $gateway_environment = $order->gateway_environment;
260
  if($gateway_environment == "live")
261
+ $host = "secure.authorize.net";
262
  else
263
+ $host = "test.authorize.net";
264
+
265
+ $path = "/gateway/transact.dll";
266
  $post_url = "https://" . $host . $path;
267
 
268
  $post_url = apply_filters("pmpro_authorizenet_post_url", $post_url, $gateway_environment);
269
+
270
  //what amount to authorize? just $1 to test
271
+ $amount = "1.00";
272
+
273
+ //combine address
274
  $address = $order->Address1;
275
  if(!empty($order->Address2))
276
  $address .= "\n" . $order->Address2;
277
+
278
  //customer stuff
279
  $customer_email = $order->Email;
280
  $customer_phone = $order->billing->phone;
281
+
282
  if(!isset($order->membership_level->name))
283
  $order->membership_level->name = "";
284
+
285
  $post_values = array(
286
+
287
  // the API Login ID and Transaction Key must be replaced with valid values
288
  "x_login" => pmpro_getOption("loginname"),
289
  "x_tran_key" => pmpro_getOption("transactionkey"),
298
  "x_card_type" => $order->cardtype,
299
  "x_card_num" => $order->accountnumber,
300
  "x_exp_date" => $order->ExpirationDate,
301
+
302
  "x_amount" => $amount,
303
  "x_description" => $order->membership_level->name . " " . __("Membership", "pmpro"),
304
 
315
  // Additional fields can be added here as outlined in the AIM integration
316
  // guide at: http://developer.authorize.net
317
  );
318
+
319
  if(!empty($order->CVV2))
320
  $post_values["x_card_code"] = $order->CVV2;
321
+
322
  // This section takes the input fields and converts them to the proper format
323
  // for an http post. For example: "x_login=username&x_tran_key=a1B2c3D4"
324
  $post_string = "";
325
  foreach( $post_values as $key => $value )
326
  { $post_string .= "$key=" . urlencode( str_replace("#", "%23", $value) ) . "&"; }
327
  $post_string = rtrim( $post_string, "& " );
328
+
329
  //curl
330
  $request = curl_init($post_url); // initiate curl object
331
  curl_setopt($request, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response
336
  // additional options may be required depending upon your server configuration
337
  // you can find documentation on curl options at http://www.php.net/curl_setopt
338
  curl_close ($request); // close curl object
339
+
340
  // This line takes the response and breaks it into an array using the specified delimiting character
341
  $response_array = explode($post_values["x_delim_char"],$post_response);
342
+
343
  if($response_array[0] == 1)
344
  {
345
  $order->payment_transaction_id = $response_array[6];
346
+ $order->updateStatus("authorized");
347
+
348
  return true;
349
  }
350
  else
354
  $order->error = $response_array[3];
355
  $order->shorterror = $response_array[3];
356
  return false;
357
+ }
358
  }
359
+
360
  function void(&$order)
361
  {
362
  if(empty($order->payment_transaction_id))
363
  return false;
364
+
365
  if(empty($order->gateway_environment))
366
  $gateway_environment = pmpro_getOption("gateway_environment");
367
  else
368
  $gateway_environment = $order->gateway_environment;
369
  if($gateway_environment == "live")
370
+ $host = "secure.authorize.net";
371
  else
372
+ $host = "test.authorize.net";
373
+
374
+ $path = "/gateway/transact.dll";
375
  $post_url = "https://" . $host . $path;
376
+
377
  $post_url = apply_filters("pmpro_authorizenet_post_url", $post_url, $gateway_environment);
378
+
379
  $post_values = array(
380
+
381
  // the API Login ID and Transaction Key must be replaced with valid values
382
  "x_login" => pmpro_getOption("loginname"),
383
  "x_tran_key" => pmpro_getOption("transactionkey"),
392
  // Additional fields can be added here as outlined in the AIM integration
393
  // guide at: http://developer.authorize.net
394
  );
395
+
396
  // This section takes the input fields and converts them to the proper format
397
  // for an http post. For example: "x_login=username&x_tran_key=a1B2c3D4"
398
  $post_string = "";
399
  foreach( $post_values as $key => $value )
400
  { $post_string .= "$key=" . urlencode( str_replace("#", "%23", $value) ) . "&"; }
401
  $post_string = rtrim( $post_string, "& " );
402
+
403
  //curl
404
  $request = curl_init($post_url); // initiate curl object
405
  curl_setopt($request, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response
410
  // additional options may be required depending upon your server configuration
411
  // you can find documentation on curl options at http://www.php.net/curl_setopt
412
  curl_close ($request); // close curl object
413
+
414
  // This line takes the response and breaks it into an array using the specified delimiting character
415
  $response_array = explode($post_values["x_delim_char"],$post_response);
416
  if($response_array[0] == 1)
417
  {
418
  $order->payment_transaction_id = $response_array[4];
419
+ $order->updateStatus("voided");
420
  return true;
421
  }
422
  else
426
  $order->error = $response_array[3];
427
  $order->shorterror = $response_array[3];
428
  return false;
429
+ }
430
+ }
431
+
432
  function charge(&$order)
433
  {
434
  if(empty($order->code))
435
  $order->code = $order->getRandomCode();
436
+
437
  if(!empty($order->gateway_environment))
438
  $gateway_environment = $order->gateway_environment;
439
  if(empty($gateway_environment))
440
  $gateway_environment = pmpro_getOption("gateway_environment");
441
  if($gateway_environment == "live")
442
+ $host = "secure.authorize.net";
443
  else
444
+ $host = "test.authorize.net";
445
+
446
+ $path = "/gateway/transact.dll";
447
  $post_url = "https://" . $host . $path;
448
 
449
  $post_url = apply_filters("pmpro_authorizenet_post_url", $post_url, $gateway_environment);
450
+
451
+ //what amount to charge?
452
  $amount = $order->InitialPayment;
453
+
454
  //tax
455
  $order->subtotal = $amount;
456
  $tax = $order->getTax(true);
457
  $amount = round((float)$order->subtotal + (float)$tax, 2);
458
+
459
+ //combine address
460
  $address = $order->Address1;
461
  if(!empty($order->Address2))
462
  $address .= "\n" . $order->Address2;
463
+
464
  //customer stuff
465
  $customer_email = $order->Email;
466
  $customer_phone = $order->billing->phone;
467
+
468
  if(!isset($order->membership_level->name))
469
  $order->membership_level->name = "";
470
+
471
  $post_values = array(
472
+
473
  // the API Login ID and Transaction Key must be replaced with valid values
474
  "x_login" => pmpro_getOption("loginname"),
475
  "x_tran_key" => pmpro_getOption("transactionkey"),
483
  "x_method" => "CC",
484
  "x_card_type" => $order->cardtype,
485
  "x_card_num" => $order->accountnumber,
486
+ "x_exp_date" => $order->ExpirationDate,
487
+
488
  "x_amount" => $amount,
489
  "x_tax" => $tax,
490
  "x_description" => $order->membership_level->name . " Membership",
499
  "x_invoice_num" => $order->code,
500
  "x_phone" => $customer_phone,
501
  "x_email" => $order->Email
502
+
503
  // Additional fields can be added here as outlined in the AIM integration
504
  // guide at: http://developer.authorize.net
505
+ );
506
+
507
  if(!empty($order->CVV2))
508
  $post_values["x_card_code"] = $order->CVV2;
509
+
510
  // This section takes the input fields and converts them to the proper format
511
  // for an http post. For example: "x_login=username&x_tran_key=a1B2c3D4"
512
  $post_string = "";
513
  foreach( $post_values as $key => $value )
514
  { $post_string .= "$key=" . urlencode( str_replace("#", "%23", $value) ) . "&"; }
515
  $post_string = rtrim( $post_string, "& " );
516
+
517
  //curl
518
  $request = curl_init($post_url); // initiate curl object
519
  curl_setopt($request, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response
524
  // additional options may be required depending upon your server configuration
525
  // you can find documentation on curl options at http://www.php.net/curl_setopt
526
  curl_close ($request); // close curl object
527
+
528
  // This line takes the response and breaks it into an array using the specified delimiting character
529
  $response_array = explode($post_values["x_delim_char"],$post_response);
530
  if($response_array[0] == 1)
531
  {
532
  $order->payment_transaction_id = $response_array[6];
533
+ $order->updateStatus("success");
534
  return true;
535
  }
536
  else
540
  $order->error = $response_array[3];
541
  $order->shorterror = $response_array[3];
542
  return false;
543
+ }
544
  }
545
+
546
  function subscribe(&$order)
547
  {
548
  //define variables to send
549
 
550
  if(empty($order->code))
551
  $order->code = $order->getRandomCode();
552
+
553
  //filter order before subscription. use with care.
554
  $order = apply_filters("pmpro_subscribe_order", $order, $this);
555
+
556
  if(!empty($order->gateway_environment))
557
  $gateway_environment = $order->gateway_environment;
558
  if(empty($gateway_environment))
559
  $gateway_environment = pmpro_getOption("gateway_environment");
560
  if($gateway_environment == "live")
561
+ $host = "api.authorize.net";
562
  else
563
+ $host = "apitest.authorize.net";
564
+
565
  $path = "/xml/v1/request.api";
566
+
567
  $loginname = pmpro_getOption("loginname");
568
  $transactionkey = pmpro_getOption("transactionkey");
569
+
570
  $amount = $order->PaymentAmount;
571
  $refId = $order->code;
572
  $name = $order->membership_name;
573
  $length = (int)$order->BillingFrequency;
574
+
575
  if($order->BillingPeriod == "Month")
576
  $unit = "months";
577
  elseif($order->BillingPeriod == "Day")
588
  }
589
  else
590
  return false; //authorize.net only supports months and days
591
+
592
  $startDate = substr($order->ProfileStartDate, 0, 10);
593
  if(!empty($order->TotalBillingCycles))
594
  $totalOccurrences = (int)$order->TotalBillingCycles;
595
  if(empty($totalOccurrences))
596
+ $totalOccurrences = 9999;
597
+ if(isset($order->TrialBillingCycles))
598
  $trialOccurrences = (int)$order->TrialBillingCycles;
599
  else
600
  $trialOccurrences = 0;
602
  $trialAmount = $order->TrialAmount;
603
  else
604
  $trialAmount = NULL;
605
+
606
  //taxes
607
  $amount_tax = $order->getTaxForPrice($amount);
608
  $trial_tax = $order->getTaxForPrice($trialAmount);
609
+
610
  $amount = round((float)$amount + (float)$amount_tax, 2);
611
  $trialAmount = round((float)$trialAmount + (float)$trial_tax, 2);
612
+
613
  //authorize.net doesn't support different periods between trial and actual
614
+
615
  if(!empty($order->TrialBillingPeriod) && $order->TrialBillingPeriod != $order->BillingPeriod)
616
  {
617
  echo "F";
618
  return false;
619
  }
620
+
621
+ $cardNumber = $order->accountnumber;
622
+ $expirationDate = $order->ExpirationDate_YdashM;
623
  $cardCode = $order->CVV2;
624
+
625
  $firstName = $order->FirstName;
626
  $lastName = $order->LastName;
627
 
632
  $city = $order->billing->city;
633
  $state = $order->billing->state;
634
  $zip = $order->billing->zip;
635
+ $country = $order->billing->country;
636
+
637
  //customer stuff
638
  $customer_email = $order->Email;
639
  if(strpos($order->billing->phone, "+") === false)
640
  $customer_phone = $order->billing->phone;
641
  else
642
  $customer_phone = "";
643
+
644
  //make sure the phone is in an okay format
645
  $customer_phone = preg_replace("/[^0-9]/", "", $customer_phone);
646
  if(strlen($customer_phone) > 10)
647
  $customer_phone = "";
648
+
649
  //build xml to post
650
  $this->content =
651
  "<?xml version=\"1.0\" encoding=\"utf-8\"?>" .
665
  "<startDate>" . $startDate . "</startDate>".
666
  "<totalOccurrences>". $totalOccurrences . "</totalOccurrences>";
667
  if(!empty($trialOccurrences))
668
+ $this->content .=
669
  "<trialOccurrences>". $trialOccurrences . "</trialOccurrences>";
670
+ $this->content .=
671
  "</paymentSchedule>".
672
  "<amount>". $amount ."</amount>";
673
  if(!empty($trialOccurrences))
680
  "<expirationDate>" . $expirationDate . "</expirationDate>";
681
  if(!empty($cardCode))
682
  $this->content .= "<cardCode>" . $cardCode . "</cardCode>";
683
+ $this->content .=
684
  "</creditCard>".
685
  "</payment>".
686
  "<order><invoiceNumber>" . substr($order->code, 0, 20) . "</invoiceNumber></order>".
695
  "<city><![CDATA[" . substr($city, 0, 40) . "]]></city>".
696
  "<state>". substr($state, 0, 2) . "</state>".
697
  "<zip>" . substr($zip, 0, 20) . "</zip>".
698
+ "<country>". substr($country, 0, 60) . "</country>".
699
  "</billTo>".
700
  "</subscription>".
701
  "</ARBCreateSubscriptionRequest>";
702
+
703
  //send the xml via curl
704
  $this->response = $this->send_request_via_curl($host,$path,$this->content);
705
  //if curl is unavilable you can try using fsockopen
706
  /*
707
  $response = send_request_via_fsockopen($host,$path,$content);
708
  */
709
+
710
+ if(!empty($this->response)) {
711
  list ($refId, $resultCode, $code, $text, $subscriptionId) = $this->parse_return($this->response);
712
  if($resultCode == "Ok")
713
  {
714
+ $order->status = "success"; //saved on checkout page
715
+ $order->subscription_transaction_id = $subscriptionId;
716
  return true;
717
  }
718
  else
720
  $order->status = "error";
721
  $order->errorcode = $code;
722
  $order->error = $text;
723
+ $order->shorterror = $text;
724
  return false;
725
  }
726
+ } else {
727
  $order->status = "error";
728
  $order->error = "Could not connect to Authorize.net";
729
  $order->shorterror = "Could not connect to Authorize.net";
730
+ return false;
731
  }
732
+ }
733
+
734
  function update(&$order)
735
  {
736
+ //define variables to send
737
  $gateway_environment = $order->gateway_environment;
738
  if(empty($gateway_environment))
739
  $gateway_environment = pmpro_getOption("gateway_environment");
740
  if($gateway_environment == "live")
741
+ $host = "api.authorize.net";
742
  else
743
+ $host = "apitest.authorize.net";
744
+
745
  $path = "/xml/v1/request.api";
746
+
747
  $loginname = pmpro_getOption("loginname");
748
  $transactionkey = pmpro_getOption("transactionkey");
749
+
750
  //$amount = $order->PaymentAmount;
751
  $refId = $order->code;
752
+ $subscriptionId = $order->subscription_transaction_id;
753
+
754
+ $cardNumber = $order->accountnumber;
755
+ $expirationDate = $order->ExpirationDate_YdashM;
756
  $cardCode = $order->CVV2;
757
+
758
  $firstName = $order->FirstName;
759
  $lastName = $order->LastName;
760
 
765
  $city = $order->billing->city;
766
  $state = $order->billing->state;
767
  $zip = $order->billing->zip;
768
+ $country = $order->billing->country;
769
+
770
  //customer stuff
771
  $customer_email = $order->Email;
772
  if(strpos($order->billing->phone, "+") === false)
773
  $customer_phone = $order->billing->phone;
774
+
775
+
776
  //build xml to post
777
  $this->content =
778
  "<?xml version=\"1.0\" encoding=\"utf-8\"?>" .
783
  "</merchantAuthentication>".
784
  "<refId>" . substr($refId, 0, 20) . "</refId>".
785
  "<subscriptionId>" . $subscriptionId . "</subscriptionId>".
786
+ "<subscription>".
787
  "<payment>".
788
  "<creditCard>".
789
  "<cardNumber>" . $cardNumber . "</cardNumber>".
790
  "<expirationDate>" . $expirationDate . "</expirationDate>";
791
  if(!empty($cardCode))
792
  $this->content .= "<cardCode>" . $cardCode . "</cardCode>";
793
+ $this->content .=
794
  "</creditCard>".
795
  "</payment>".
796
  "<customer>".
804
  "<city><![CDATA[" . substr($city, 0, 40) . "]]></city>".
805
  "<state><![CDATA[". substr($state, 0, 2) . "]]></state>".
806
  "<zip>" . substr($zip, 0, 20) . "</zip>".
807
+ "<country>". substr($country, 0, 60) . "</country>".
808
  "</billTo>".
809
  "</subscription>".
810
  "</ARBUpdateSubscriptionRequest>";
811
+
812
  //send the xml via curl
813
  $this->response = $this->send_request_via_curl($host,$path,$this->content);
814
  //if curl is unavilable you can try using fsockopen
815
  /*
816
  $response = send_request_via_fsockopen($host,$path,$order->content);
817
  */
818
+
819
+
820
+ if(!empty($this->response)) {
821
+ list ($resultCode, $code, $text, $subscriptionId) = $this->parse_return($this->response);
822
+
823
  if($resultCode == "Ok" || $code == "Ok")
824
+ {
825
  return true;
826
  }
827
  else
832
  $order->shorterror = $text;
833
  return false;
834
  }
835
+ } else {
836
  $order->status = "error";
837
  $order->error = "Could not connect to Authorize.net";
838
  $order->shorterror = "Could not connect to Authorize.net";
839
+ return false;
840
  }
841
  }
842
+
843
  function cancel(&$order)
844
  {
845
+ //define variables to send
846
  if(!empty($order->subscription_transaction_id))
847
  $subscriptionId = $order->subscription_transaction_id;
848
  else
849
  $subscriptionId = "";
850
  $loginname = pmpro_getOption("loginname");
851
  $transactionkey = pmpro_getOption("transactionkey");
852
+
853
  if(!empty($order->gateway_environment))
854
  $gateway_environment = $order->gateway_environment;
855
  else
856
+ $gateway_environment = pmpro_getOption("gateway_environment");
857
+
858
  if($gateway_environment == "live")
859
+ $host = "api.authorize.net";
860
  else
861
+ $host = "apitest.authorize.net";
862
+
863
  $path = "/xml/v1/request.api";
864
+
865
  if(!$subscriptionId || !$loginname || !$transactionkey)
866
  return false;
867
+
868
  //build xml to post
869
  $content =
870
  "<?xml version=\"1.0\" encoding=\"utf-8\"?>".
875
  "</merchantAuthentication>" .
876
  "<subscriptionId>" . $subscriptionId . "</subscriptionId>".
877
  "</ARBCancelSubscriptionRequest>";
878
+
879
  //send the xml via curl
880
  $response = $this->send_request_via_curl($host,$path,$content);
881
  //if curl is unavilable you can try using fsockopen
882
  /*
883
  $response = send_request_via_fsockopen($host,$path,$content);
884
  */
885
+
886
  //if the connection and send worked $response holds the return from Authorize.net
887
  if ($response)
888
+ {
889
+ list ($resultCode, $code, $text, $subscriptionId) = $this->parse_return($response);
890
+
891
  if($resultCode == "Ok" || $code == "Ok")
892
  {
893
+ $order->updateStatus("cancelled");
894
  return true;
895
  }
896
  else
901
  $order->shorterror = $text;
902
  return false;
903
  }
904
+ }
905
+ else
906
+ {
907
  $order->status = "error";
908
  $order->error = __("Could not connect to Authorize.net", "pmpro");
909
  $order->shorterror = __("Could not connect to Authorize.net", "pmpro");
910
+ return false;
911
  }
912
+ }
913
+
914
  function getSubscriptionStatus(&$order)
915
+ {
916
+ //define variables to send
917
  if(!empty($order->subscription_transaction_id))
918
  $subscriptionId = $order->subscription_transaction_id;
919
  else
920
  $subscriptionId = "";
921
  $loginname = pmpro_getOption("loginname");
922
  $transactionkey = pmpro_getOption("transactionkey");
923
+
924
  if(!empty($order->gateway_environment))
925
  $gateway_environment = $order->gateway_environment;
926
  else
927
+ $gateway_environment = pmpro_getOption("gateway_environment");
928
+
929
  if($gateway_environment == "live")
930
+ $host = "api.authorize.net";
931
  else
932
+ $host = "apitest.authorize.net";
933
+
934
  $path = "/xml/v1/request.api";
935
+
936
  if(!$subscriptionId || !$loginname || !$transactionkey)
937
  return false;
938
+
939
  //build xml to post
940
  $content =
941
  "<?xml version=\"1.0\" encoding=\"utf-8\"?>".
946
  "</merchantAuthentication>" .
947
  "<subscriptionId>" . $subscriptionId . "</subscriptionId>".
948
  "</ARBGetSubscriptionStatusRequest>";
949
+
950
  //send the xml via curl
951
  $response = $this->send_request_via_curl($host,$path,$content);
952
+
953
  //if curl is unavilable you can try using fsockopen
954
  /*
955
  $response = send_request_via_fsockopen($host,$path,$content);
956
  */
957
+
958
  //if the connection and send worked $response holds the return from Authorize.net
959
  if($response)
960
+ {
961
+ list ($resultCode, $code, $text, $subscriptionId) = $this->parse_return($response);
962
+
963
  $status = $this->substring_between($response,'<status>','</status>');
964
+
965
  if($resultCode == "Ok" || $code == "Ok")
966
  {
967
  return $status;
968
  }
969
  else
970
+ {
971
  $order->status = "error";
972
  $order->errorcode = $resultCode;
973
  $order->error = $message;
974
  $order->shorterror = $text;
975
  }
976
+ }
977
+ else
978
+ {
979
  $order->status = "error";
980
  $order->errorcode = $resultCode;
981
  $order->error = $message;
982
  $order->shorterror = $text;
983
  }
984
+ }
985
+
986
  //Authorize.net Function
987
  //function to send xml request via fsockopen
988
  function send_request_via_fsockopen($host,$path,$content)
1048
 
1049
  //Authorize.net Function
1050
  //helper function for parsing response
1051
+ function substring_between($haystack,$start,$end)
1052
  {
1053
+ if (strpos($haystack,$start) === false || strpos($haystack,$end) === false)
1054
  {
1055
  return false;
1056
+ }
1057
+ else
1058
  {
1059
  $start_position = strpos($haystack,$start)+strlen($start);
1060
  $end_position = strpos($haystack,$end);
classes/gateways/class.pmprogateway_braintree.php CHANGED
@@ -1,824 +1,824 @@
1
- <?php
2
- //include pmprogateway
3
- require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
-
5
- //load classes init method
6
- add_action('init', array('PMProGateway_braintree', 'init'));
7
-
8
- class PMProGateway_braintree extends PMProGateway
9
- {
10
- function PMProGateway_braintree($gateway = NULL)
11
- {
12
- $this->gateway = $gateway;
13
- $this->gateway_environment = pmpro_getOption("gateway_environment");
14
-
15
- $this->loadBraintreeLibrary();
16
-
17
- //convert to braintree nomenclature
18
- $environment = $this->gateway_environment;
19
- if($environment == "live")
20
- $environment = "production";
21
-
22
- Braintree_Configuration::environment($environment);
23
- Braintree_Configuration::merchantId(pmpro_getOption("braintree_merchantid"));
24
- Braintree_Configuration::publicKey(pmpro_getOption("braintree_publickey"));
25
- Braintree_Configuration::privateKey(pmpro_getOption("braintree_privatekey"));
26
-
27
- return $this->gateway;
28
- }
29
-
30
- /**
31
- * Load the Braintree API library.
32
- *
33
- * @since 1.8.1
34
- * Moved into a method in version 1.8.1 so we only load it when needed.
35
- */
36
- function loadBraintreeLibrary()
37
- {
38
- //load Braintree library if it hasn't been loaded already (usually by another plugin using Braintree)
39
- if(!class_exists("Braintree"))
40
- require_once(dirname(__FILE__) . "/../../includes/lib/Braintree/Braintree.php");
41
- }
42
-
43
- /**
44
- * Run on WP init
45
- *
46
- * @since 1.8
47
- */
48
- static function init()
49
- {
50
- //make sure Braintree Payments is a gateway option
51
- add_filter('pmpro_gateways', array('PMProGateway_braintree', 'pmpro_gateways'));
52
-
53
- //add fields to payment settings
54
- add_filter('pmpro_payment_options', array('PMProGateway_braintree', 'pmpro_payment_options'));
55
- add_filter('pmpro_payment_option_fields', array('PMProGateway_braintree', 'pmpro_payment_option_fields'), 10, 2);
56
-
57
- //code to add at checkout if Braintree is the current gateway
58
- $gateway = pmpro_getGateway();
59
- if($gateway == "braintree")
60
- {
61
- add_action('pmpro_checkout_before_submit_button', array('PMProGateway_braintree', 'pmpro_checkout_before_submit_button'));
62
- add_filter('pmpro_checkout_order', array('PMProGateway_braintree', 'pmpro_checkout_order'));
63
- add_filter('pmpro_required_billing_fields', array('PMProGateway_braintree', 'pmpro_required_billing_fields'));
64
- add_filter('pmpro_include_payment_information_fields', array('PMProGateway_braintree', 'pmpro_include_payment_information_fields'));
65
- }
66
- }
67
-
68
- /**
69
- * Make sure this gateway is in the gateways list
70
- *
71
- * @since 1.8
72
- */
73
- static function pmpro_gateways($gateways)
74
- {
75
- if(empty($gateways['braintree']))
76
- $gateways['braintree'] = __('Braintree Payments', 'pmpro');
77
-
78
- return $gateways;
79
- }
80
-
81
- /**
82
- * Get a list of payment options that the this gateway needs/supports.
83
- *
84
- * @since 1.8
85
- */
86
- static function getGatewayOptions()
87
- {
88
- $options = array(
89
- 'sslseal',
90
- 'nuclear_HTTPS',
91
- 'gateway_environment',
92
- 'braintree_merchantid',
93
- 'braintree_publickey',
94
- 'braintree_privatekey',
95
- 'braintree_encryptionkey',
96
- 'currency',
97
- 'use_ssl',
98
- 'tax_state',
99
- 'tax_rate',
100
- 'accepted_credit_cards'
101
- );
102
-
103
- return $options;
104
- }
105
-
106
- /**
107
- * Set payment options for payment settings page.
108
- *
109
- * @since 1.8
110
- */
111
- static function pmpro_payment_options($options)
112
- {
113
- //get stripe options
114
- $braintree_options = PMProGateway_braintree::getGatewayOptions();
115
-
116
- //merge with others.
117
- $options = array_merge($braintree_options, $options);
118
-
119
- return $options;
120
- }
121
-
122
- /**
123
- * Display fields for this gateway's options.
124
- *
125
- * @since 1.8
126
- */
127
- static function pmpro_payment_option_fields($values, $gateway)
128
- {
129
- ?>
130
- <tr class="pmpro_settings_divider gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
131
- <td colspan="2">
132
- <?php _e('Braintree Settings', 'pmpro'); ?>
133
- </td>
134
- </tr>
135
- <tr class="gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
136
- <th scope="row" valign="top">
137
- <label for="braintree_merchantid"><?php _e('Merchant ID', 'pmpro');?>:</label>
138
- </th>
139
- <td>
140
- <input type="text" id="braintree_merchantid" name="braintree_merchantid" size="60" value="<?php echo esc_attr($values['braintree_merchantid'])?>" />
141
- </td>
142
- </tr>
143
- <tr class="gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
144
- <th scope="row" valign="top">
145
- <label for="braintree_publickey"><?php _e('Public Key', 'pmpro');?>:</label>
146
- </th>
147
- <td>
148
- <input type="text" id="braintree_publickey" name="braintree_publickey" size="60" value="<?php echo esc_attr($values['braintree_publickey'])?>" />
149
- </td>
150
- </tr>
151
- <tr class="gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
152
- <th scope="row" valign="top">
153
- <label for="braintree_privatekey"><?php _e('Private Key', 'pmpro');?>:</label>
154
- </th>
155
- <td>
156
- <input type="text" id="braintree_privatekey" name="braintree_privatekey" size="60" value="<?php echo esc_attr($values['braintree_privatekey'])?>" />
157
- </td>
158
- </tr>
159
- <tr class="gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
160
- <th scope="row" valign="top">
161
- <label for="braintree_encryptionkey"><?php _e('Client-Side Encryption Key', 'pmpro');?>:</label>
162
- </th>
163
- <td>
164
- <textarea id="braintree_encryptionkey" name="braintree_encryptionkey" rows="3" cols="80"><?php echo esc_textarea($values['braintree_encryptionkey'])?></textarea>
165
- </td>
166
- </tr>
167
- <tr class="gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
168
- <th scope="row" valign="top">
169
- <label><?php _e('Web Hook URL', 'pmpro');?>:</label>
170
- </th>
171
- <td>
172
- <p>
173
- <?php _e('To fully integrate with Braintree, be sure to set your Web Hook URL to', 'pmpro');?>
174
- <pre><?php
175
- //echo admin_url("admin-ajax.php") . "?action=braintree_webhook";
176
- echo PMPRO_URL . "/services/braintree-webhook.php";
177
- ?></pre>
178
- </p>
179
- </td>
180
- </tr>
181
- <?php
182
- }
183
-
184
- /**
185
- * Filtering orders at checkout.
186
- *
187
- * @since 1.8
188
- */
189
- static function pmpro_checkout_order($morder)
190
- {
191
- //load up values
192
- if(isset($_REQUEST['number']))
193
- $braintree_number = $_REQUEST['number'];
194
- else
195
- $braintree_number = "";
196
-
197
- if(isset($_REQUEST['expiration_date']))
198
- $braintree_expiration_date = $_REQUEST['expiration_date'];
199
- else
200
- $braintree_expiration_date = "";
201
-
202
- if(isset($_REQUEST['cvv']))
203
- $braintree_cvv = $_REQUEST['cvv'];
204
- else
205
- $braintree_cvv = "";
206
-
207
- $morder->braintree = new stdClass();
208
- $morder->braintree->number = $braintree_number;
209
- $morder->braintree->expiration_date = $braintree_expiration_date;
210
- $morder->braintree->cvv = $braintree_cvv;
211
-
212
- return $morder;
213
- }
214
-
215
- /**
216
- * Don't require the CVV, but look for cvv (lowercase) that braintree sends
217
- *
218
- */
219
- static function pmpro_required_billing_fields($fields)
220
- {
221
- unset($fields['CVV']);
222
- $fields['cvv'] = true;
223
- return $fields;
224
- }
225
-
226
- /**
227
- * Add some hidden fields and JavaScript to checkout.
228
- *
229
- */
230
- static function pmpro_checkout_before_submit_button()
231
- {
232
- ?>
233
- <input type='hidden' data-encrypted-name='expiration_date' id='credit_card_exp' />
234
- <input type='hidden' name='AccountNumber' id='BraintreeAccountNumber' />
235
- <script type="text/javascript" src="https://js.braintreegateway.com/v1/braintree.js"></script>
236
- <script type="text/javascript">
237
- //setup braintree encryption
238
- var braintree = Braintree.create('<?php echo pmpro_getOption("braintree_encryptionkey"); ?>');
239
- braintree.onSubmitEncryptForm('pmpro_form');
240
-
241
- //pass expiration dates in original format
242
- function pmpro_updateBraintreeCardExp()
243
- {
244
- jQuery('#credit_card_exp').val(jQuery('#ExpirationMonth').val() + "/" + jQuery('#ExpirationYear').val());
245
- }
246
- jQuery('#ExpirationMonth, #ExpirationYear').change(function() {
247
- pmpro_updateBraintreeCardExp();
248
- });
249
- pmpro_updateBraintreeCardExp();
250
-
251
- //pass last 4 of credit card
252
- function pmpro_updateBraintreeAccountNumber()
253
- {
254
- jQuery('#BraintreeAccountNumber').val('XXXXXXXXXXXXX' + jQuery('#AccountNumber').val().substr(jQuery('#AccountNumber').val().length - 4));
255
- }
256
- jQuery('#AccountNumber').change(function() {
257
- pmpro_updateBraintreeAccountNumber();
258
- });
259
- pmpro_updateBraintreeAccountNumber();
260
- </script>
261
- <?php
262
- }
263
-
264
- /**
265
- * Use our own payment fields at checkout. (Remove the name attributes and set some data-encrypted-name attributes.)
266
- * @since 1.8
267
- */
268
- static function pmpro_include_payment_information_fields($include)
269
- {
270
- //global vars
271
- global $pmpro_requirebilling, $pmpro_show_discount_code, $discount_code, $CardType, $AccountNumber, $ExpirationMonth, $ExpirationYear;
272
-
273
- //get accepted credit cards
274
- $pmpro_accepted_credit_cards = pmpro_getOption("accepted_credit_cards");
275
- $pmpro_accepted_credit_cards = explode(",", $pmpro_accepted_credit_cards);
276
- $pmpro_accepted_credit_cards_string = pmpro_implodeToEnglish($pmpro_accepted_credit_cards);
277
-
278
- //include ours
279
- ?>
280
- <table id="pmpro_payment_information_fields" class="pmpro_checkout top1em" width="100%" cellpadding="0" cellspacing="0" border="0" <?php if(!$pmpro_requirebilling || apply_filters("pmpro_hide_payment_information_fields", false) ) { ?>style="display: none;"<?php } ?>>
281
- <thead>
282
- <tr>
283
- <th><span class="pmpro_thead-msg"><?php printf(__('We Accept %s', 'pmpro'), $pmpro_accepted_credit_cards_string);?></span><?php _e('Payment Information', 'pmpro');?></th>
284
- </tr>
285
- </thead>
286
- <tbody>
287
- <tr valign="top">
288
- <td>
289
- <?php
290
- $sslseal = pmpro_getOption("sslseal");
291
- if($sslseal)
292
- {
293
- ?>
294
- <div class="pmpro_sslseal"><?php echo stripslashes($sslseal)?></div>
295
- <?php
296
- }
297
- ?>
298
- <?php
299
- $pmpro_include_cardtype_field = apply_filters('pmpro_include_cardtype_field', true);
300
- if($pmpro_include_cardtype_field)
301
- {
302
- ?>
303
- <div class="pmpro_payment-card-type">
304
- <label for="CardType"><?php _e('Card Type', 'pmpro');?></label>
305
- <select id="CardType" name="CardType" class=" <?php echo pmpro_getClassForField("CardType");?>">
306
- <?php foreach($pmpro_accepted_credit_cards as $cc) { ?>
307
- <option value="<?php echo $cc?>" <?php if($CardType == $cc) { ?>selected="selected"<?php } ?>><?php echo $cc?></option>
308
- <?php } ?>
309
- </select>
310
- </div>
311
- <?php
312
- }
313
- ?>
314
-
315
- <div class="pmpro_payment-account-number">
316
- <label for="AccountNumber"><?php _e('Card Number', 'pmpro');?></label>
317
- <input id="AccountNumber" name="AccountNumber" class="input <?php echo pmpro_getClassForField("AccountNumber");?>" type="text" size="25" value="<?php echo esc_attr($AccountNumber)?>" data-encrypted-name="number" autocomplete="off" />
318
- </div>
319
-
320
- <div class="pmpro_payment-expiration">
321
- <label for="ExpirationMonth"><?php _e('Expiration Date', 'pmpro');?></label>
322
- <select id="ExpirationMonth" name="ExpirationMonth" class=" <?php echo pmpro_getClassForField("ExpirationMonth");?>">
323
- <option value="01" <?php if($ExpirationMonth == "01") { ?>selected="selected"<?php } ?>>01</option>
324
- <option value="02" <?php if($ExpirationMonth == "02") { ?>selected="selected"<?php } ?>>02</option>
325
- <option value="03" <?php if($ExpirationMonth == "03") { ?>selected="selected"<?php } ?>>03</option>
326
- <option value="04" <?php if($ExpirationMonth == "04") { ?>selected="selected"<?php } ?>>04</option>
327
- <option value="05" <?php if($ExpirationMonth == "05") { ?>selected="selected"<?php } ?>>05</option>
328
- <option value="06" <?php if($ExpirationMonth == "06") { ?>selected="selected"<?php } ?>>06</option>
329
- <option value="07" <?php if($ExpirationMonth == "07") { ?>selected="selected"<?php } ?>>07</option>
330
- <option value="08" <?php if($ExpirationMonth == "08") { ?>selected="selected"<?php } ?>>08</option>
331
- <option value="09" <?php if($ExpirationMonth == "09") { ?>selected="selected"<?php } ?>>09</option>
332
- <option value="10" <?php if($ExpirationMonth == "10") { ?>selected="selected"<?php } ?>>10</option>
333
- <option value="11" <?php if($ExpirationMonth == "11") { ?>selected="selected"<?php } ?>>11</option>
334
- <option value="12" <?php if($ExpirationMonth == "12") { ?>selected="selected"<?php } ?>>12</option>
335
- </select>/<select id="ExpirationYear" name="ExpirationYear" class=" <?php echo pmpro_getClassForField("ExpirationYear");?>">
336
- <?php
337
- for($i = date("Y"); $i < date("Y") + 10; $i++)
338
- {
339
- ?>
340
- <option value="<?php echo $i?>" <?php if($ExpirationYear == $i) { ?>selected="selected"<?php } ?>><?php echo $i?></option>
341
- <?php
342
- }
343
- ?>
344
- </select>
345
- </div>
346
-
347
- <?php
348
- $pmpro_show_cvv = apply_filters("pmpro_show_cvv", true);
349
- if($pmpro_show_cvv)
350
- {
351
- ?>
352
- <div class="pmpro_payment-cvv">
353
- <label for="CVV"><?php _ex('CVV', 'Credit card security code, CVV/CCV/CVV2', 'pmpro');?></label>
354
- <input class="input" id="CVV" name="cvv" type="text" size="4" value="<?php if(!empty($_REQUEST['CVV'])) { echo esc_attr($_REQUEST['CVV']); }?>" class=" <?php echo pmpro_getClassForField("CVV");?>" data-encrypted-name="cvv" /> <small>(<a href="javascript:void(0);" onclick="javascript:window.open('<?php echo pmpro_https_filter(PMPRO_URL)?>/pages/popup-cvv.html','cvv','toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=600, height=475');"><?php _ex("what's this?", 'link to CVV help', 'pmpro');?></a>)</small>
355
- </div>
356
- <?php
357
- }
358
- ?>
359
-
360
- <?php if($pmpro_show_discount_code) { ?>
361
- <div class="pmpro_payment-discount-code">
362
- <label for="discount_code"><?php _e('Discount Code', 'pmpro');?></label>
363
- <input class="input <?php echo pmpro_getClassForField("discount_code");?>" id="discount_code" name="discount_code" type="text" size="20" value="<?php echo esc_attr($discount_code)?>" />
364
- <input type="button" id="discount_code_button" name="discount_code_button" value="<?php _e('Apply', 'pmpro');?>" />
365
- <p id="discount_code_message" class="pmpro_message" style="display: none;"></p>
366
- </div>
367
- <?php } ?>
368
-
369
- </td>
370
- </tr>
371
- </tbody>
372
- </table>
373
- <?php
374
-
375
- //don't include the default
376
- return false;
377
- }
378
-
379
- /**
380
- * Process checkout.
381
- *
382
- */
383
- function process(&$order)
384
- {
385
- //check for initial payment
386
- if(floatval($order->InitialPayment) == 0)
387
- {
388
- //just subscribe
389
- return $this->subscribe($order);
390
- }
391
- else
392
- {
393
- //charge then subscribe
394
- if($this->charge($order))
395
- {
396
- if(pmpro_isLevelRecurring($order->membership_level))
397
- {
398
- if($this->subscribe($order))
399
- {
400
- //yay!
401
- return true;
402
- }
403
- else
404
- {
405
- //try to refund initial charge
406
- return false;
407
- }
408
- }
409
- else
410
- {
411
- //only a one time charge
412
- $order->status = "success"; //saved on checkout page
413
- return true;
414
- }
415
- }
416
- else
417
- {
418
- if(empty($order->error))
419
- $order->error = __("Unknown error: Initial payment failed.", "pmpro");
420
- return false;
421
- }
422
- }
423
- }
424
-
425
- function charge(&$order)
426
- {
427
- //create a code for the order
428
- if(empty($order->code))
429
- $order->code = $order->getRandomCode();
430
-
431
- //what amount to charge?
432
- $amount = $order->InitialPayment;
433
-
434
- //tax
435
- $order->subtotal = $amount;
436
- $tax = $order->getTax(true);
437
- $amount = round((float)$order->subtotal + (float)$tax, 2);
438
-
439
- //create a customer
440
- $this->getCustomer($order);
441
- if(empty($this->customer))
442
- {
443
- //failed to create customer
444
- return false;
445
- }
446
-
447
- //charge
448
- try
449
- {
450
- $response = Braintree_Transaction::sale(array(
451
- 'amount' => $amount,
452
- 'customerId' => $this->customer->id
453
- ));
454
- }
455
- catch (Exception $e)
456
- {
457
- //$order->status = "error";
458
- $order->errorcode = true;
459
- $order->error = "Error: " . $e->getMessage();
460
- $order->shorterror = $order->error;
461
- return false;
462
- }
463
-
464
- if($response->success)
465
- {
466
- //successful charge
467
- $transaction_id = $response->transaction->id;
468
- $response = Braintree_Transaction::submitForSettlement($transaction_id);
469
- if($response->success)
470
- {
471
- $order->payment_transaction_id = $transaction_id;
472
- $order->updateStatus("success");
473
- return true;
474
- }
475
- else
476
- {
477
- $order->errorcode = true;
478
- $order->error = __("Error during settlement:", "pmpro") . " " . $response->message;
479
- $order->shorterror = $response->message;
480
- return false;
481
- }
482
- }
483
- else
484
- {
485
- //$order->status = "error";
486
- $order->errorcode = true;
487
- $order->error = __("Error during charge:", "pmpro") . " " . $response->message;
488
- $order->shorterror = $response->message;
489
- return false;
490
- }
491
- }
492
-
493
- /*
494
- This function will return a Braintree customer object.
495
- If $this->customer is set, it returns it.
496
- It first checks if the order has a subscription_transaction_id. If so, that's the customer id.
497
- If not, it checks for a user_id on the order and searches for a customer id in the user meta.
498
- If a customer id is found, it checks for a customer through the Braintree API.
499
- If a customer is found and there is an AccountNumber on the order passed, it will update the customer.
500
- If no customer is found and there is an AccountNumber on the order passed, it will create a customer.
501
- */
502
- function getCustomer(&$order, $force = false)
503
- {
504
- global $current_user;
505
-
506
- //already have it?
507
- if(!empty($this->customer) && !$force)
508
- return $this->customer;
509
-
510
- //try based on user id
511
- if(!empty($order->user_id))
512
- $user_id = $order->user_id;
513
-
514
- //if no id passed, check the current user
515
- if(empty($user_id) && !empty($current_user->ID))
516
- $user_id = $current_user->ID;
517
-
518
- //check for a braintree customer id
519
- if(!empty($user_id))
520
- {
521
- $customer_id = get_user_meta($user_id, "pmpro_braintree_customerid", true);
522
- }
523
-
524
- //check for an existing stripe customer
525
- if(!empty($customer_id))
526
- {
527
- try
528
- {
529
- $this->customer = Braintree_Customer::find($customer_id);
530
-
531
- //update the customer address, description and card
532
- if(!empty($order->accountnumber))
533
- {
534
- //put data in array for Braintree API calls
535
- $update_array = array(
536
- 'firstName' => $order->FirstName,
537
- 'lastName' => $order->LastName,
538
- 'creditCard' => array(
539
- 'number' => $order->braintree->number,
540
- 'expirationDate' => $order->braintree->expiration_date,
541
- 'cardholderName' => trim($order->FirstName . " " . $order->LastName),
542
- 'options' => array(
543
- 'updateExistingToken' => $this->customer->creditCards[0]->token
544
- )
545
- )
546
- );
547
-
548
- //address too?
549
- if(!empty($order->billing))
550
- //make sure Address2 is set
551
- if(!isset($order->Address2))
552
- $order->Address2 = '';
553
-
554
- //add billing address to array
555
- $update_array['creditCard']['billingAddress'] = array(
556
- 'firstName' => $order->FirstName,
557
- 'lastName' => $order->LastName,
558
- 'streetAddress' => $order->Address1,
559
- 'extendedAddress' => $order->Address2,
560
- 'locality' => $order->billing->city,
561
- 'region' => $order->billing->state,
562
- 'postalCode' => $order->billing->zip,
563
- 'countryCodeAlpha2' => $order->billing->country,
564
- 'options' => array(
565
- 'updateExisting' => true
566
- )
567
- );
568
-
569
- //update
570
- $response = Braintree_Customer::update($customer_id, $update_array);
571
-
572
- if($response->success)
573
- {
574
- $this->customer = $response->customer;
575
- return $this->customer;
576
- }
577
- else
578
- {
579
- $order->error = __("Failed to update customer.", "pmpro") . " " . $response->message;
580
- $order->shorterror = $order->error;
581
- return false;
582
- }
583
- }
584
-
585
- return $this->customer;
586
- }
587
- catch (Exception $e)
588
- {
589
- //assume no customer found
590
- }
591
- }
592
-
593
- //no customer id, create one
594
- if(!empty($order->accountnumber))
595
- {
596
- try
597
- {
598
- $result = Braintree_Customer::create(array(
599
- 'firstName' => $order->FirstName,
600
- 'lastName' => $order->LastName,
601
- 'email' => $order->Email,
602
- 'phone' => $order->billing->phone,
603
- 'creditCard' => array(
604
- 'number' => $order->braintree->number,
605
- 'expirationDate' => $order->braintree->expiration_date,
606
- 'cvv' => $order->braintree->cvv,
607
- 'cardholderName' => trim($order->FirstName . " " . $order->LastName),
608
- 'billingAddress' => array(
609
- 'firstName' => $order->FirstName,
610
- 'lastName' => $order->LastName,
611
- 'streetAddress' => $order->Address1,
612
- 'extendedAddress' => $order->Address2,
613
- 'locality' => $order->billing->city,
614
- 'region' => $order->billing->state,
615
- 'postalCode' => $order->billing->zip,
616
- 'countryCodeAlpha2' => $order->billing->country
617
- )
618
- )
619
- ));
620
-
621
- if($result->success)
622
- {
623
- $this->customer = $result->customer;
624
- }
625
- else
626
- {
627
- $order->error = __("Failed to create customer.", "pmpro") . " " . $result->message;
628
- $order->shorterror = $order->error;
629
- return false;
630
- }
631
- }
632
- catch (Exception $e)
633
- {
634
- $order->error = __("Error creating customer record with Braintree:", "pmpro") . " " . $e->getMessage();
635
- $order->shorterror = $order->error;
636
- return false;
637
- }
638
-
639
- //if we have no user id, we need to set the customer id after the user is created
640
- if(empty($user_id))
641
- {
642
- global $pmpro_braintree_customerid;
643
- $pmpro_braintree_customerid = $this->customer->id;
644
- add_action('user_register', array('PMProGateway_braintree','user_register'));
645
- }
646
- else
647
- update_user_meta($user_id, "pmpro_braintree_customerid", $this->customer->id);
648
-
649
- return $this->customer;
650
- }
651
-
652
- return false;
653
- }
654
-
655
- function subscribe(&$order)
656
- {
657
- //create a code for the order
658
- if(empty($order->code))
659
- $order->code = $order->getRandomCode();
660
-
661
- //setup customer
662
- $this->getCustomer($order);
663
- if(empty($this->customer))
664
- return false; //error retrieving customer
665
-
666
- //figure out the amounts
667
- $amount = $order->PaymentAmount;
668
- $amount_tax = $order->getTaxForPrice($amount);
669
- $amount = round((float)$amount + (float)$amount_tax, 2);
670
-
671
- /*
672
- There are two parts to the trial. Part 1 is simply the delay until the first payment
673
- since we are doing the first payment as a separate transaction.
674
- The second part is the actual "trial" set by the admin.
675
-
676
- Stripe only supports Year or Month for billing periods, but we account for Days and Weeks just in case.
677
- */
678
- //figure out the trial length (first payment handled by initial charge)
679
- if($order->BillingPeriod == "Year")
680
- $trial_period_days = $order->BillingFrequency * 365; //annual
681
- elseif($order->BillingPeriod == "Day")
682
- $trial_period_days = $order->BillingFrequency * 1; //daily
683
- elseif($order->BillingPeriod == "Week")
684
- $trial_period_days = $order->BillingFrequency * 7; //weekly
685
- else
686
- $trial_period_days = $order->BillingFrequency * 30; //assume monthly
687
-
688
- //convert to a profile start date
689
- $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
690
-
691
- //filter the start date
692
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
693
-
694
- //convert back to days
695
- $trial_period_days = ceil(abs(strtotime(date("Y-m-d")) - strtotime($order->ProfileStartDate, current_time("timestamp"))) / 86400);
696
-
697
- //now add the actual trial set by the site
698
- if(!empty($order->TrialBillingCycles))
699
- {
700
- $trialOccurrences = (int)$order->TrialBillingCycles;
701
- if($order->BillingPeriod == "Year")
702
- $trial_period_days = $trial_period_days + (365 * $order->BillingFrequency * $trialOccurrences); //annual
703
- elseif($order->BillingPeriod == "Day")
704
- $trial_period_days = $trial_period_days + (1 * $order->BillingFrequency * $trialOccurrences); //daily
705
- elseif($order->BillingPeriod == "Week")
706
- $trial_period_days = $trial_period_days + (7 * $order->BillingFrequency * $trialOccurrences); //weekly
707
- else
708
- $trial_period_days = $trial_period_days + (30 * $order->BillingFrequency * $trialOccurrences); //assume monthly
709
- }
710
-
711
- //subscribe to the plan
712
- try
713
- {
714
- $details = array(
715
- 'paymentMethodToken' => $this->customer->creditCards[0]->token,
716
- 'planId' => 'pmpro_' . $order->membership_id,
717
- 'price' => $amount
718
- );
719
-
720
- if(!empty($trial_period_days))
721
- {
722
- $details['trialPeriod'] = true;
723
- $details['trialDuration'] = $trial_period_days;
724
- $details['trialDurationUnit'] = "day";
725
- }
726
-
727
- if(!empty($order->TotalBillingCycles))
728
- $details['numberOfBillingCycles'] = $order->TotalBillingCycles;
729
-
730
- $result = Braintree_Subscription::create($details);
731
- }
732
- catch (Exception $e)
733
- {
734
- $order->error = __("Error subscribing customer to plan with Braintree:", "pmpro") . " " . $e->getMessage();
735
- //return error
736
- $order->shorterror = $order->error;
737
- return false;
738
- }
739
-
740
- if($result->success)
741
- {
742
- //if we got this far, we're all good
743
- $order->status = "success";
744
- $order->subscription_transaction_id = $result->subscription->id;
745
- return true;
746
- }
747
- else
748
- {
749
- $order->error = __("Failed to subscribe with Braintree:", "pmpro") . " " . $result->message;
750
- $order->shorterror = $result->message;
751
- return false;
752
- }
753
- }
754
-
755
- function update(&$order)
756
- {
757
- //we just have to run getCustomer which will look for the customer and update it with the new token
758
- $this->getCustomer($order, true);
759
-
760
- if(!empty($this->customer) && empty($order->error))
761
- {
762
- return true;
763
- }
764
- else
765
- {
766
- return false; //couldn't find the customer
767
- }
768
- }
769
-
770
- function cancel(&$order)
771
- {
772
- //require a subscription id
773
- if(empty($order->subscription_transaction_id))
774
- return false;
775
-
776
- //find the customer
777
- if(!empty($order->subscription_transaction_id))
778
- {
779
- //cancel
780
- try
781
- {
782
- $result = Braintree_Subscription::cancel($order->subscription_transaction_id);
783
- }
784
- catch(Exception $e)
785
- {
786
- $order->updateStatus("cancelled"); //assume it's been cancelled already
787
- $order->error = __("Could not find the subscription.", "pmpro") . " " . $e->getMessage();
788
- $order->shorterror = $order->error;
789
- return false; //no subscription found
790
- }
791
-
792
- if($result->success)
793
- {
794
- $order->updateStatus("cancelled");
795
- return true;
796
- }
797
- else
798
- {
799
- $order->updateStatus("cancelled"); //assume it's been cancelled already
800
- $order->error = __("Could not find the subscription.", "pmpro") . " " . $result->message;
801
- $order->shorterror = $order->error;
802
- return false; //no subscription found
803
- }
804
- }
805
- else
806
- {
807
- $order->error = __("Could not find the subscription.", "pmpro");
808
- $order->shorterror = $order->error;
809
- return false; //no customer found
810
- }
811
- }
812
-
813
- /*
814
- Save Braintree customer id after the user is registered.
815
- */
816
- static function user_register($user_id)
817
- {
818
- global $pmpro_braintree_customerid;
819
- if(!empty($pmpro_braintree_customerid))
820
- {
821
- update_user_meta($user_id, 'pmpro_braintree_customerid', $pmpro_braintree_customerid);
822
- }
823
- }
824
- }
1
+ <?php
2
+ //include pmprogateway
3
+ require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
+
5
+ //load classes init method
6
+ add_action('init', array('PMProGateway_braintree', 'init'));
7
+
8
+ class PMProGateway_braintree extends PMProGateway
9
+ {
10
+ function PMProGateway_braintree($gateway = NULL)
11
+ {
12
+ $this->gateway = $gateway;
13
+ $this->gateway_environment = pmpro_getOption("gateway_environment");
14
+
15
+ $this->loadBraintreeLibrary();
16
+
17
+ //convert to braintree nomenclature
18
+ $environment = $this->gateway_environment;
19
+ if($environment == "live")
20
+ $environment = "production";
21
+
22
+ Braintree_Configuration::environment($environment);
23
+ Braintree_Configuration::merchantId(pmpro_getOption("braintree_merchantid"));
24
+ Braintree_Configuration::publicKey(pmpro_getOption("braintree_publickey"));
25
+ Braintree_Configuration::privateKey(pmpro_getOption("braintree_privatekey"));
26
+
27
+ return $this->gateway;
28
+ }
29
+
30
+ /**
31
+ * Load the Braintree API library.
32
+ *
33
+ * @since 1.8.1
34
+ * Moved into a method in version 1.8.1 so we only load it when needed.
35
+ */
36
+ function loadBraintreeLibrary()
37
+ {
38
+ //load Braintree library if it hasn't been loaded already (usually by another plugin using Braintree)
39
+ if(!class_exists("Braintree"))
40
+ require_once(dirname(__FILE__) . "/../../includes/lib/Braintree/Braintree.php");
41
+ }
42
+
43
+ /**
44
+ * Run on WP init
45
+ *
46
+ * @since 1.8
47
+ */
48
+ static function init()
49
+ {
50
+ //make sure Braintree Payments is a gateway option
51
+ add_filter('pmpro_gateways', array('PMProGateway_braintree', 'pmpro_gateways'));
52
+
53
+ //add fields to payment settings
54
+ add_filter('pmpro_payment_options', array('PMProGateway_braintree', 'pmpro_payment_options'));
55
+ add_filter('pmpro_payment_option_fields', array('PMProGateway_braintree', 'pmpro_payment_option_fields'), 10, 2);
56
+
57
+ //code to add at checkout if Braintree is the current gateway
58
+ $gateway = pmpro_getGateway();
59
+ if($gateway == "braintree")
60
+ {
61
+ add_action('pmpro_checkout_before_submit_button', array('PMProGateway_braintree', 'pmpro_checkout_before_submit_button'));
62
+ add_filter('pmpro_checkout_order', array('PMProGateway_braintree', 'pmpro_checkout_order'));
63
+ add_filter('pmpro_required_billing_fields', array('PMProGateway_braintree', 'pmpro_required_billing_fields'));
64
+ add_filter('pmpro_include_payment_information_fields', array('PMProGateway_braintree', 'pmpro_include_payment_information_fields'));
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Make sure this gateway is in the gateways list
70
+ *
71
+ * @since 1.8
72
+ */
73
+ static function pmpro_gateways($gateways)
74
+ {
75
+ if(empty($gateways['braintree']))
76
+ $gateways['braintree'] = __('Braintree Payments', 'pmpro');
77
+
78
+ return $gateways;
79
+ }
80
+
81
+ /**
82
+ * Get a list of payment options that the this gateway needs/supports.
83
+ *
84
+ * @since 1.8
85
+ */
86
+ static function getGatewayOptions()
87
+ {
88
+ $options = array(
89
+ 'sslseal',
90
+ 'nuclear_HTTPS',
91
+ 'gateway_environment',
92
+ 'braintree_merchantid',
93
+ 'braintree_publickey',
94
+ 'braintree_privatekey',
95
+ 'braintree_encryptionkey',
96
+ 'currency',
97
+ 'use_ssl',
98
+ 'tax_state',
99
+ 'tax_rate',
100
+ 'accepted_credit_cards'
101
+ );
102
+
103
+ return $options;
104
+ }
105
+
106
+ /**
107
+ * Set payment options for payment settings page.
108
+ *
109
+ * @since 1.8
110
+ */
111
+ static function pmpro_payment_options($options)
112
+ {
113
+ //get stripe options
114
+ $braintree_options = PMProGateway_braintree::getGatewayOptions();
115
+
116
+ //merge with others.
117
+ $options = array_merge($braintree_options, $options);
118
+
119
+ return $options;
120
+ }
121
+
122
+ /**
123
+ * Display fields for this gateway's options.
124
+ *
125
+ * @since 1.8
126
+ */
127
+ static function pmpro_payment_option_fields($values, $gateway)
128
+ {
129
+ ?>
130
+ <tr class="pmpro_settings_divider gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
131
+ <td colspan="2">
132
+ <?php _e('Braintree Settings', 'pmpro'); ?>
133
+ </td>
134
+ </tr>
135
+ <tr class="gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
136
+ <th scope="row" valign="top">
137
+ <label for="braintree_merchantid"><?php _e('Merchant ID', 'pmpro');?>:</label>
138
+ </th>
139
+ <td>
140
+ <input type="text" id="braintree_merchantid" name="braintree_merchantid" size="60" value="<?php echo esc_attr($values['braintree_merchantid'])?>" />
141
+ </td>
142
+ </tr>
143
+ <tr class="gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
144
+ <th scope="row" valign="top">
145
+ <label for="braintree_publickey"><?php _e('Public Key', 'pmpro');?>:</label>
146
+ </th>
147
+ <td>
148
+ <input type="text" id="braintree_publickey" name="braintree_publickey" size="60" value="<?php echo esc_attr($values['braintree_publickey'])?>" />
149
+ </td>
150
+ </tr>
151
+ <tr class="gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
152
+ <th scope="row" valign="top">
153
+ <label for="braintree_privatekey"><?php _e('Private Key', 'pmpro');?>:</label>
154
+ </th>
155
+ <td>
156
+ <input type="text" id="braintree_privatekey" name="braintree_privatekey" size="60" value="<?php echo esc_attr($values['braintree_privatekey'])?>" />
157
+ </td>
158
+ </tr>
159
+ <tr class="gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
160
+ <th scope="row" valign="top">
161
+ <label for="braintree_encryptionkey"><?php _e('Client-Side Encryption Key', 'pmpro');?>:</label>
162
+ </th>
163
+ <td>
164
+ <textarea id="braintree_encryptionkey" name="braintree_encryptionkey" rows="3" cols="80"><?php echo esc_textarea($values['braintree_encryptionkey'])?></textarea>
165
+ </td>
166
+ </tr>
167
+ <tr class="gateway gateway_braintree" <?php if($gateway != "braintree") { ?>style="display: none;"<?php } ?>>
168
+ <th scope="row" valign="top">
169
+ <label><?php _e('Web Hook URL', 'pmpro');?>:</label>
170
+ </th>
171
+ <td>
172
+ <p>
173
+ <?php _e('To fully integrate with Braintree, be sure to set your Web Hook URL to', 'pmpro');?>
174
+ <pre><?php
175
+ //echo admin_url("admin-ajax.php") . "?action=braintree_webhook";
176
+ echo PMPRO_URL . "/services/braintree-webhook.php";
177
+ ?></pre>
178
+ </p>
179
+ </td>
180
+ </tr>
181
+ <?php
182
+ }
183
+
184
+ /**
185
+ * Filtering orders at checkout.
186
+ *
187
+ * @since 1.8
188
+ */
189
+ static function pmpro_checkout_order($morder)
190
+ {
191
+ //load up values
192
+ if(isset($_REQUEST['number']))
193
+ $braintree_number = $_REQUEST['number'];
194
+ else
195
+ $braintree_number = "";
196
+
197
+ if(isset($_REQUEST['expiration_date']))
198
+ $braintree_expiration_date = $_REQUEST['expiration_date'];
199
+ else
200
+ $braintree_expiration_date = "";
201
+
202
+ if(isset($_REQUEST['cvv']))
203
+ $braintree_cvv = $_REQUEST['cvv'];
204
+ else
205
+ $braintree_cvv = "";
206
+
207
+ $morder->braintree = new stdClass();
208
+ $morder->braintree->number = $braintree_number;
209
+ $morder->braintree->expiration_date = $braintree_expiration_date;
210
+ $morder->braintree->cvv = $braintree_cvv;
211
+
212
+ return $morder;
213
+ }
214
+
215
+ /**
216
+ * Don't require the CVV, but look for cvv (lowercase) that braintree sends
217
+ *
218
+ */
219
+ static function pmpro_required_billing_fields($fields)
220
+ {
221
+ unset($fields['CVV']);
222
+ $fields['cvv'] = true;
223
+ return $fields;
224
+ }
225
+
226
+ /**
227
+ * Add some hidden fields and JavaScript to checkout.
228
+ *
229
+ */
230
+ static function pmpro_checkout_before_submit_button()
231
+ {
232
+ ?>
233
+ <input type='hidden' data-encrypted-name='expiration_date' id='credit_card_exp' />
234
+ <input type='hidden' name='AccountNumber' id='BraintreeAccountNumber' />
235
+ <script type="text/javascript" src="https://js.braintreegateway.com/v1/braintree.js"></script>
236
+ <script type="text/javascript">
237
+ //setup braintree encryption
238
+ var braintree = Braintree.create('<?php echo pmpro_getOption("braintree_encryptionkey"); ?>');
239
+ braintree.onSubmitEncryptForm('pmpro_form');
240
+
241
+ //pass expiration dates in original format
242
+ function pmpro_updateBraintreeCardExp()
243
+ {
244
+ jQuery('#credit_card_exp').val(jQuery('#ExpirationMonth').val() + "/" + jQuery('#ExpirationYear').val());
245
+ }
246
+ jQuery('#ExpirationMonth, #ExpirationYear').change(function() {
247
+ pmpro_updateBraintreeCardExp();
248
+ });
249
+ pmpro_updateBraintreeCardExp();
250
+
251
+ //pass last 4 of credit card
252
+ function pmpro_updateBraintreeAccountNumber()
253
+ {
254
+ jQuery('#BraintreeAccountNumber').val('XXXXXXXXXXXXX' + jQuery('#AccountNumber').val().substr(jQuery('#AccountNumber').val().length - 4));
255
+ }
256
+ jQuery('#AccountNumber').change(function() {
257
+ pmpro_updateBraintreeAccountNumber();
258
+ });
259
+ pmpro_updateBraintreeAccountNumber();
260
+ </script>
261
+ <?php
262
+ }
263
+
264
+ /**
265
+ * Use our own payment fields at checkout. (Remove the name attributes and set some data-encrypted-name attributes.)
266
+ * @since 1.8
267
+ */
268
+ static function pmpro_include_payment_information_fields($include)
269
+ {
270
+ //global vars
271
+ global $pmpro_requirebilling, $pmpro_show_discount_code, $discount_code, $CardType, $AccountNumber, $ExpirationMonth, $ExpirationYear;
272
+
273
+ //get accepted credit cards
274
+ $pmpro_accepted_credit_cards = pmpro_getOption("accepted_credit_cards");
275
+ $pmpro_accepted_credit_cards = explode(",", $pmpro_accepted_credit_cards);
276
+ $pmpro_accepted_credit_cards_string = pmpro_implodeToEnglish($pmpro_accepted_credit_cards);
277
+
278
+ //include ours
279
+ ?>
280
+ <table id="pmpro_payment_information_fields" class="pmpro_checkout top1em" width="100%" cellpadding="0" cellspacing="0" border="0" <?php if(!$pmpro_requirebilling || apply_filters("pmpro_hide_payment_information_fields", false) ) { ?>style="display: none;"<?php } ?>>
281
+ <thead>
282
+ <tr>
283
+ <th><span class="pmpro_thead-msg"><?php printf(__('We Accept %s', 'pmpro'), $pmpro_accepted_credit_cards_string);?></span><?php _e('Payment Information', 'pmpro');?></th>
284
+ </tr>
285
+ </thead>
286
+ <tbody>
287
+ <tr valign="top">
288
+ <td>
289
+ <?php
290
+ $sslseal = pmpro_getOption("sslseal");
291
+ if($sslseal)
292
+ {
293
+ ?>
294
+ <div class="pmpro_sslseal"><?php echo stripslashes($sslseal)?></div>
295
+ <?php
296
+ }
297
+ ?>
298
+ <?php
299
+ $pmpro_include_cardtype_field = apply_filters('pmpro_include_cardtype_field', true);
300
+ if($pmpro_include_cardtype_field)
301
+ {
302
+ ?>
303
+ <div class="pmpro_payment-card-type">
304
+ <label for="CardType"><?php _e('Card Type', 'pmpro');?></label>
305
+ <select id="CardType" name="CardType" class=" <?php echo pmpro_getClassForField("CardType");?>">
306
+ <?php foreach($pmpro_accepted_credit_cards as $cc) { ?>
307
+ <option value="<?php echo $cc?>" <?php if($CardType == $cc) { ?>selected="selected"<?php } ?>><?php echo $cc?></option>
308
+ <?php } ?>
309
+ </select>
310
+ </div>
311
+ <?php
312
+ }
313
+ ?>
314
+
315
+ <div class="pmpro_payment-account-number">
316
+ <label for="AccountNumber"><?php _e('Card Number', 'pmpro');?></label>
317
+ <input id="AccountNumber" name="AccountNumber" class="input <?php echo pmpro_getClassForField("AccountNumber");?>" type="text" size="25" value="<?php echo esc_attr($AccountNumber)?>" data-encrypted-name="number" autocomplete="off" />
318
+ </div>
319
+
320
+ <div class="pmpro_payment-expiration">
321
+ <label for="ExpirationMonth"><?php _e('Expiration Date', 'pmpro');?></label>
322
+ <select id="ExpirationMonth" name="ExpirationMonth" class=" <?php echo pmpro_getClassForField("ExpirationMonth");?>">
323
+ <option value="01" <?php if($ExpirationMonth == "01") { ?>selected="selected"<?php } ?>>01</option>
324
+ <option value="02" <?php if($ExpirationMonth == "02") { ?>selected="selected"<?php } ?>>02</option>
325
+ <option value="03" <?php if($ExpirationMonth == "03") { ?>selected="selected"<?php } ?>>03</option>
326
+ <option value="04" <?php if($ExpirationMonth == "04") { ?>selected="selected"<?php } ?>>04</option>
327
+ <option value="05" <?php if($ExpirationMonth == "05") { ?>selected="selected"<?php } ?>>05</option>
328
+ <option value="06" <?php if($ExpirationMonth == "06") { ?>selected="selected"<?php } ?>>06</option>
329
+ <option value="07" <?php if($ExpirationMonth == "07") { ?>selected="selected"<?php } ?>>07</option>
330
+ <option value="08" <?php if($ExpirationMonth == "08") { ?>selected="selected"<?php } ?>>08</option>
331
+ <option value="09" <?php if($ExpirationMonth == "09") { ?>selected="selected"<?php } ?>>09</option>
332
+ <option value="10" <?php if($ExpirationMonth == "10") { ?>selected="selected"<?php } ?>>10</option>
333
+ <option value="11" <?php if($ExpirationMonth == "11") { ?>selected="selected"<?php } ?>>11</option>
334
+ <option value="12" <?php if($ExpirationMonth == "12") { ?>selected="selected"<?php } ?>>12</option>
335
+ </select>/<select id="ExpirationYear" name="ExpirationYear" class=" <?php echo pmpro_getClassForField("ExpirationYear");?>">
336
+ <?php
337
+ for($i = date("Y"); $i < date("Y") + 10; $i++)
338
+ {
339
+ ?>
340
+ <option value="<?php echo $i?>" <?php if($ExpirationYear == $i) { ?>selected="selected"<?php } ?>><?php echo $i?></option>
341
+ <?php
342
+ }
343
+ ?>
344
+ </select>
345
+ </div>
346
+
347
+ <?php
348
+ $pmpro_show_cvv = apply_filters("pmpro_show_cvv", true);
349
+ if($pmpro_show_cvv)
350
+ {
351
+ ?>
352
+ <div class="pmpro_payment-cvv">
353
+ <label for="CVV"><?php _ex('CVV', 'Credit card security code, CVV/CCV/CVV2', 'pmpro');?></label>
354
+ <input class="input" id="CVV" name="cvv" type="text" size="4" value="<?php if(!empty($_REQUEST['CVV'])) { echo esc_attr($_REQUEST['CVV']); }?>" class=" <?php echo pmpro_getClassForField("CVV");?>" data-encrypted-name="cvv" /> <small>(<a href="javascript:void(0);" onclick="javascript:window.open('<?php echo pmpro_https_filter(PMPRO_URL)?>/pages/popup-cvv.html','cvv','toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=600, height=475');"><?php _ex("what's this?", 'link to CVV help', 'pmpro');?></a>)</small>
355
+ </div>
356
+ <?php
357
+ }
358
+ ?>
359
+
360
+ <?php if($pmpro_show_discount_code) { ?>
361
+ <div class="pmpro_payment-discount-code">
362
+ <label for="discount_code"><?php _e('Discount Code', 'pmpro');?></label>
363
+ <input class="input <?php echo pmpro_getClassForField("discount_code");?>" id="discount_code" name="discount_code" type="text" size="20" value="<?php echo esc_attr($discount_code)?>" />
364
+ <input type="button" id="discount_code_button" name="discount_code_button" value="<?php _e('Apply', 'pmpro');?>" />
365
+ <p id="discount_code_message" class="pmpro_message" style="display: none;"></p>
366
+ </div>
367
+ <?php } ?>
368
+
369
+ </td>
370
+ </tr>
371
+ </tbody>
372
+ </table>
373
+ <?php
374
+
375
+ //don't include the default
376
+ return false;
377
+ }
378
+
379
+ /**
380
+ * Process checkout.
381
+ *
382
+ */
383
+ function process(&$order)
384
+ {
385
+ //check for initial payment
386
+ if(floatval($order->InitialPayment) == 0)
387
+ {
388
+ //just subscribe
389
+ return $this->subscribe($order);
390
+ }
391
+ else
392
+ {
393
+ //charge then subscribe
394
+ if($this->charge($order))
395
+ {
396
+ if(pmpro_isLevelRecurring($order->membership_level))
397
+ {
398
+ if($this->subscribe($order))
399
+ {
400
+ //yay!
401
+ return true;
402
+ }
403
+ else
404
+ {
405
+ //try to refund initial charge
406
+ return false;
407
+ }
408
+ }
409
+ else
410
+ {
411
+ //only a one time charge
412
+ $order->status = "success"; //saved on checkout page
413
+ return true;
414
+ }
415
+ }
416
+ else
417
+ {
418
+ if(empty($order->error))
419
+ $order->error = __("Unknown error: Initial payment failed.", "pmpro");
420
+ return false;
421
+ }
422
+ }
423
+ }
424
+
425
+ function charge(&$order)
426
+ {
427
+ //create a code for the order
428
+ if(empty($order->code))
429
+ $order->code = $order->getRandomCode();
430
+
431
+ //what amount to charge?
432
+ $amount = $order->InitialPayment;
433
+
434
+ //tax
435
+ $order->subtotal = $amount;
436
+ $tax = $order->getTax(true);
437
+ $amount = round((float)$order->subtotal + (float)$tax, 2);
438
+
439
+ //create a customer
440
+ $this->getCustomer($order);
441
+ if(empty($this->customer) || !empty($order->error))
442
+ {
443
+ //failed to create customer
444
+ return false;
445
+ }
446
+
447
+ //charge
448
+ try
449
+ {
450
+ $response = Braintree_Transaction::sale(array(
451
+ 'amount' => $amount,
452
+ 'customerId' => $this->customer->id
453
+ ));
454
+ }
455
+ catch (Exception $e)
456
+ {
457
+ //$order->status = "error";
458
+ $order->errorcode = true;
459
+ $order->error = "Error: " . $e->getMessage();
460
+ $order->shorterror = $order->error;
461
+ return false;
462
+ }
463
+
464
+ if($response->success)
465
+ {
466
+ //successful charge
467
+ $transaction_id = $response->transaction->id;
468
+ $response = Braintree_Transaction::submitForSettlement($transaction_id);
469
+ if($response->success)
470
+ {
471
+ $order->payment_transaction_id = $transaction_id;
472
+ $order->updateStatus("success");
473
+ return true;
474
+ }
475
+ else
476
+ {
477
+ $order->errorcode = true;
478
+ $order->error = __("Error during settlement:", "pmpro") . " " . $response->message;
479
+ $order->shorterror = $response->message;
480
+ return false;
481
+ }
482
+ }
483
+ else
484
+ {
485
+ //$order->status = "error";
486
+ $order->errorcode = true;
487
+ $order->error = __("Error during charge:", "pmpro") . " " . $response->message;
488
+ $order->shorterror = $response->message;
489
+ return false;
490
+ }
491
+ }
492
+
493
+ /*
494
+ This function will return a Braintree customer object.
495
+ If $this->customer is set, it returns it.
496
+ It first checks if the order has a subscription_transaction_id. If so, that's the customer id.
497
+ If not, it checks for a user_id on the order and searches for a customer id in the user meta.
498
+ If a customer id is found, it checks for a customer through the Braintree API.
499
+ If a customer is found and there is an AccountNumber on the order passed, it will update the customer.
500
+ If no customer is found and there is an AccountNumber on the order passed, it will create a customer.
501
+ */
502
+ function getCustomer(&$order, $force = false)
503
+ {
504
+ global $current_user;
505
+
506
+ //already have it?
507
+ if(!empty($this->customer) && !$force)
508
+ return $this->customer;
509
+
510
+ //try based on user id
511
+ if(!empty($order->user_id))
512
+ $user_id = $order->user_id;
513
+
514
+ //if no id passed, check the current user
515
+ if(empty($user_id) && !empty($current_user->ID))
516
+ $user_id = $current_user->ID;
517
+
518
+ //check for a braintree customer id
519
+ if(!empty($user_id))
520
+ {
521
+ $customer_id = get_user_meta($user_id, "pmpro_braintree_customerid", true);
522
+ }
523
+
524
+ //check for an existing stripe customer
525
+ if(!empty($customer_id))
526
+ {
527
+ try
528
+ {
529
+ $this->customer = Braintree_Customer::find($customer_id);
530
+
531
+ //update the customer address, description and card
532
+ if(!empty($order->accountnumber))
533
+ {
534
+ //put data in array for Braintree API calls
535
+ $update_array = array(
536
+ 'firstName' => $order->FirstName,
537
+ 'lastName' => $order->LastName,
538
+ 'creditCard' => array(
539
+ 'number' => $order->braintree->number,
540
+ 'expirationDate' => $order->braintree->expiration_date,
541
+ 'cardholderName' => trim($order->FirstName . " " . $order->LastName),
542
+ 'options' => array(
543
+ 'updateExistingToken' => $this->customer->creditCards[0]->token
544
+ )
545
+ )
546
+ );
547
+
548
+ //address too?
549
+ if(!empty($order->billing))
550
+ //make sure Address2 is set
551
+ if(!isset($order->Address2))
552
+ $order->Address2 = '';
553
+
554
+ //add billing address to array
555
+ $update_array['creditCard']['billingAddress'] = array(
556
+ 'firstName' => $order->FirstName,
557
+ 'lastName' => $order->LastName,
558
+ 'streetAddress' => $order->Address1,
559
+ 'extendedAddress' => $order->Address2,
560
+ 'locality' => $order->billing->city,
561
+ 'region' => $order->billing->state,
562
+ 'postalCode' => $order->billing->zip,
563
+ 'countryCodeAlpha2' => $order->billing->country,
564
+ 'options' => array(
565
+ 'updateExisting' => true
566
+ )
567
+ );
568
+
569
+ //update
570
+ $response = Braintree_Customer::update($customer_id, $update_array);
571
+
572
+ if($response->success)
573
+ {
574
+ $this->customer = $response->customer;
575
+ return $this->customer;
576
+ }
577
+ else
578
+ {
579
+ $order->error = __("Failed to update customer.", "pmpro") . " " . $response->message;
580
+ $order->shorterror = $order->error;
581
+ return false;
582
+ }
583
+ }
584
+
585
+ return $this->customer;
586
+ }
587
+ catch (Exception $e)
588
+ {
589
+ //assume no customer found
590
+ }
591
+ }
592
+
593
+ //no customer id, create one
594
+ if(!empty($order->accountnumber))
595
+ {
596
+ try
597
+ {
598
+ $result = Braintree_Customer::create(array(
599
+ 'firstName' => $order->FirstName,
600
+ 'lastName' => $order->LastName,
601
+ 'email' => $order->Email,
602
+ 'phone' => $order->billing->phone,
603
+ 'creditCard' => array(
604
+ 'number' => $order->braintree->number,
605
+ 'expirationDate' => $order->braintree->expiration_date,
606
+ 'cvv' => $order->braintree->cvv,
607
+ 'cardholderName' => trim($order->FirstName . " " . $order->LastName),
608
+ 'billingAddress' => array(
609
+ 'firstName' => $order->FirstName,
610
+ 'lastName' => $order->LastName,
611
+ 'streetAddress' => $order->Address1,
612
+ 'extendedAddress' => $order->Address2,
613
+ 'locality' => $order->billing->city,
614
+ 'region' => $order->billing->state,
615
+ 'postalCode' => $order->billing->zip,
616
+ 'countryCodeAlpha2' => $order->billing->country
617
+ )
618
+ )
619
+ ));
620
+
621
+ if($result->success)
622
+ {
623
+ $this->customer = $result->customer;
624
+ }
625
+ else
626
+ {
627
+ $order->error = __("Failed to create customer.", "pmpro") . " " . $result->message;
628
+ $order->shorterror = $order->error;
629
+ return false;
630
+ }
631
+ }
632
+ catch (Exception $e)
633
+ {
634
+ $order->error = __("Error creating customer record with Braintree:", "pmpro") . " " . $e->getMessage();
635
+ $order->shorterror = $order->error;
636
+ return false;
637
+ }
638
+
639
+ //if we have no user id, we need to set the customer id after the user is created
640
+ if(empty($user_id))
641
+ {
642
+ global $pmpro_braintree_customerid;
643
+ $pmpro_braintree_customerid = $this->customer->id;
644
+ add_action('user_register', array('PMProGateway_braintree','user_register'));
645
+ }
646
+ else
647
+ update_user_meta($user_id, "pmpro_braintree_customerid", $this->customer->id);
648
+
649
+ return $this->customer;
650
+ }
651
+
652
+ return false;
653
+ }
654
+
655
+ function subscribe(&$order)
656
+ {
657
+ //create a code for the order
658
+ if(empty($order->code))
659
+ $order->code = $order->getRandomCode();
660
+
661
+ //setup customer
662
+ $this->getCustomer($order);
663
+ if(empty($this->customer) || !empty($order->error))
664
+ return false; //error retrieving customer
665
+
666
+ //figure out the amounts
667
+ $amount = $order->PaymentAmount;
668
+ $amount_tax = $order->getTaxForPrice($amount);
669
+ $amount = round((float)$amount + (float)$amount_tax, 2);
670
+
671
+ /*
672
+ There are two parts to the trial. Part 1 is simply the delay until the first payment
673
+ since we are doing the first payment as a separate transaction.
674
+ The second part is the actual "trial" set by the admin.
675
+
676
+ Stripe only supports Year or Month for billing periods, but we account for Days and Weeks just in case.
677
+ */
678
+ //figure out the trial length (first payment handled by initial charge)
679
+ if($order->BillingPeriod == "Year")
680
+ $trial_period_days = $order->BillingFrequency * 365; //annual
681
+ elseif($order->BillingPeriod == "Day")
682
+ $trial_period_days = $order->BillingFrequency * 1; //daily
683
+ elseif($order->BillingPeriod == "Week")
684
+ $trial_period_days = $order->BillingFrequency * 7; //weekly
685
+ else
686
+ $trial_period_days = $order->BillingFrequency * 30; //assume monthly
687
+
688
+ //convert to a profile start date
689
+ $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
690
+
691
+ //filter the start date
692
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
693
+
694
+ //convert back to days
695
+ $trial_period_days = ceil(abs(strtotime(date("Y-m-d")) - strtotime($order->ProfileStartDate, current_time("timestamp"))) / 86400);
696
+
697
+ //now add the actual trial set by the site
698
+ if(!empty($order->TrialBillingCycles))
699
+ {
700
+ $trialOccurrences = (int)$order->TrialBillingCycles;
701
+ if($order->BillingPeriod == "Year")
702
+ $trial_period_days = $trial_period_days + (365 * $order->BillingFrequency * $trialOccurrences); //annual
703
+ elseif($order->BillingPeriod == "Day")
704
+ $trial_period_days = $trial_period_days + (1 * $order->BillingFrequency * $trialOccurrences); //daily
705
+ elseif($order->BillingPeriod == "Week")
706
+ $trial_period_days = $trial_period_days + (7 * $order->BillingFrequency * $trialOccurrences); //weekly
707
+ else
708
+ $trial_period_days = $trial_period_days + (30 * $order->BillingFrequency * $trialOccurrences); //assume monthly
709
+ }
710
+
711
+ //subscribe to the plan
712
+ try
713
+ {
714
+ $details = array(
715
+ 'paymentMethodToken' => $this->customer->creditCards[0]->token,
716
+ 'planId' => 'pmpro_' . $order->membership_id,
717
+ 'price' => $amount
718
+ );
719
+
720
+ if(!empty($trial_period_days))
721
+ {
722
+ $details['trialPeriod'] = true;
723
+ $details['trialDuration'] = $trial_period_days;
724
+ $details['trialDurationUnit'] = "day";
725
+ }
726
+
727
+ if(!empty($order->TotalBillingCycles))
728
+ $details['numberOfBillingCycles'] = $order->TotalBillingCycles;
729
+
730
+ $result = Braintree_Subscription::create($details);
731
+ }
732
+ catch (Exception $e)
733
+ {
734
+ $order->error = __("Error subscribing customer to plan with Braintree:", "pmpro") . " " . $e->getMessage();
735
+ //return error
736
+ $order->shorterror = $order->error;
737
+ return false;
738
+ }
739
+
740
+ if($result->success)
741
+ {
742
+ //if we got this far, we're all good
743
+ $order->status = "success";
744
+ $order->subscription_transaction_id = $result->subscription->id;
745
+ return true;
746
+ }
747
+ else
748
+ {
749
+ $order->error = __("Failed to subscribe with Braintree:", "pmpro") . " " . $result->message;
750
+ $order->shorterror = $result->message;
751
+ return false;
752
+ }
753
+ }
754
+
755
+ function update(&$order)
756
+ {
757
+ //we just have to run getCustomer which will look for the customer and update it with the new token
758
+ $this->getCustomer($order, true);
759
+
760
+ if(!empty($this->customer) && empty($order->error))
761
+ {
762
+ return true;
763
+ }
764
+ else
765
+ {
766
+ return false; //couldn't find the customer
767
+ }
768
+ }
769
+
770
+ function cancel(&$order)
771
+ {
772
+ //require a subscription id
773
+ if(empty($order->subscription_transaction_id))
774
+ return false;
775
+
776
+ //find the customer
777
+ if(!empty($order->subscription_transaction_id))
778
+ {
779
+ //cancel
780
+ try
781
+ {
782
+ $result = Braintree_Subscription::cancel($order->subscription_transaction_id);
783
+ }
784
+ catch(Exception $e)
785
+ {
786
+ $order->updateStatus("cancelled"); //assume it's been cancelled already
787
+ $order->error = __("Could not find the subscription.", "pmpro") . " " . $e->getMessage();
788
+ $order->shorterror = $order->error;
789
+ return false; //no subscription found
790
+ }
791
+
792
+ if($result->success)
793
+ {
794
+ $order->updateStatus("cancelled");
795
+ return true;
796
+ }
797
+ else
798
+ {
799
+ $order->updateStatus("cancelled"); //assume it's been cancelled already
800
+ $order->error = __("Could not find the subscription.", "pmpro") . " " . $result->message;
801
+ $order->shorterror = $order->error;
802
+ return false; //no subscription found
803
+ }
804
+ }
805
+ else
806
+ {
807
+ $order->error = __("Could not find the subscription.", "pmpro");
808
+ $order->shorterror = $order->error;
809
+ return false; //no customer found
810
+ }
811
+ }
812
+
813
+ /*
814
+ Save Braintree customer id after the user is registered.
815
+ */
816
+ static function user_register($user_id)
817
+ {
818
+ global $pmpro_braintree_customerid;
819
+ if(!empty($pmpro_braintree_customerid))
820
+ {
821
+ update_user_meta($user_id, 'pmpro_braintree_customerid', $pmpro_braintree_customerid);
822
+ }
823
+ }
824
+ }
classes/gateways/class.pmprogateway_check.php CHANGED
@@ -1,341 +1,341 @@
1
- <?php
2
- //include pmprogateway
3
- require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
-
5
- //load classes init method
6
- add_action('init', array('PMProGateway_check', 'init'));
7
-
8
- class PMProGateway_check extends PMProGateway
9
- {
10
- function PMProGateway_check($gateway = NULL)
11
- {
12
- $this->gateway = $gateway;
13
- return $this->gateway;
14
- }
15
-
16
- /**
17
- * Run on WP init
18
- *
19
- * @since 1.8
20
- */
21
- static function init()
22
- {
23
- //make sure Pay by Check is a gateway option
24
- add_filter('pmpro_gateways', array('PMProGateway_check', 'pmpro_gateways'));
25
-
26
- //add fields to payment settings
27
- add_filter('pmpro_payment_options', array('PMProGateway_check', 'pmpro_payment_options'));
28
- add_filter('pmpro_payment_option_fields', array('PMProGateway_check', 'pmpro_payment_option_fields'), 10, 2);
29
-
30
- //code to add at checkout
31
- $gateway = pmpro_getGateway();
32
- if($gateway == "check")
33
- {
34
- add_filter('pmpro_include_billing_address_fields', '__return_false');
35
- add_filter('pmpro_include_payment_information_fields', '__return_false');
36
- add_filter('pmpro_required_billing_fields', array('PMProGateway_check', 'pmpro_required_billing_fields'));
37
- }
38
- }
39
-
40
- /**
41
- * Make sure Check is in the gateways list
42
- *
43
- * @since 1.8
44
- */
45
- static function pmpro_gateways($gateways)
46
- {
47
- if(empty($gateways['check']))
48
- $gateways['check'] = __('Pay by Check', 'pmpro');
49
-
50
- return $gateways;
51
- }
52
-
53
- /**
54
- * Get a list of payment options that the Check gateway needs/supports.
55
- *
56
- * @since 1.8
57
- */
58
- static function getGatewayOptions()
59
- {
60
- $options = array(
61
- 'sslseal',
62
- 'nuclear_HTTPS',
63
- 'gateway_environment',
64
- 'instructions',
65
- 'currency',
66
- 'use_ssl',
67
- 'tax_state',
68
- 'tax_rate'
69
- );
70
-
71
- return $options;
72
- }
73
-
74
- /**
75
- * Set payment options for payment settings page.
76
- *
77
- * @since 1.8
78
- */
79
- static function pmpro_payment_options($options)
80
- {
81
- //get stripe options
82
- $check_options = PMProGateway_check::getGatewayOptions();
83
-
84
- //merge with others.
85
- $options = array_merge($check_options, $options);
86
-
87
- return $options;
88
- }
89
-
90
- /**
91
- * Display fields for Check options.
92
- *
93
- * @since 1.8
94
- */
95
- static function pmpro_payment_option_fields($values, $gateway)
96
- {
97
- ?>
98
- <tr class="pmpro_settings_divider gateway gateway_check" <?php if($gateway != "check") { ?>style="display: none;"<?php } ?>>
99
- <td colspan="2">
100
- <?php _e('Pay by Check Settings', 'pmpro'); ?>
101
- </td>
102
- </tr>
103
- <tr class="gateway gateway_check" <?php if($gateway != "check") { ?>style="display: none;"<?php } ?>>
104
- <th scope="row" valign="top">
105
- <label for="instructions"><?php _e('Instructions', 'pmpro');?></label>
106
- </th>
107
- <td>
108
- <textarea id="instructions" name="instructions" rows="3" cols="80"><?php echo esc_textarea($values['instructions'])?></textarea>
109
- <p><small><?php _e('Who to write the check out to. Where to mail it. Shown on checkout, confirmation, and invoice pages.', 'pmpro');?></small></p>
110
- </td>
111
- </tr>
112
- <?php
113
- }
114
-
115
- /**
116
- * Remove required billing fields
117
- *
118
- * @since 1.8
119
- */
120
- static function pmpro_required_billing_fields($fields)
121
- {
122
- unset($fields['bfirstname']);
123
- unset($fields['blastname']);
124
- unset($fields['baddress1']);
125
- unset($fields['bcity']);
126
- unset($fields['bstate']);
127
- unset($fields['bzipcode']);
128
- unset($fields['bphone']);
129
- unset($fields['bemail']);
130
- unset($fields['bcountry']);
131
- unset($fields['CardType']);
132
- unset($fields['AccountNumber']);
133
- unset($fields['ExpirationMonth']);
134
- unset($fields['ExpirationYear']);
135
- unset($fields['CVV']);
136
-
137
- return $fields;
138
- }
139
-
140
- /**
141
- * Process checkout.
142
- *
143
- */
144
- function process(&$order)
145
- {
146
- //clean up a couple values
147
- $order->payment_type = "Check";
148
- $order->CardType = "";
149
- $order->cardtype = "";
150
-
151
- //check for initial payment
152
- if(floatval($order->InitialPayment) == 0)
153
- {
154
- //auth first, then process
155
- if($this->authorize($order))
156
- {
157
- $this->void($order);
158
- if(!pmpro_isLevelTrial($order->membership_level))
159
- {
160
- //subscription will start today with a 1 period trial
161
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
162
- $order->TrialBillingPeriod = $order->BillingPeriod;
163
- $order->TrialBillingFrequency = $order->BillingFrequency;
164
- $order->TrialBillingCycles = 1;
165
- $order->TrialAmount = 0;
166
-
167
- //add a billing cycle to make up for the trial, if applicable
168
- if(!empty($order->TotalBillingCycles))
169
- $order->TotalBillingCycles++;
170
- }
171
- elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
172
- {
173
- //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
174
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
175
- $order->TrialBillingCycles++;
176
-
177
- //add a billing cycle to make up for the trial, if applicable
178
- if($order->TotalBillingCycles)
179
- $order->TotalBillingCycles++;
180
- }
181
- else
182
- {
183
- //add a period to the start date to account for the initial payment
184
- $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
185
- }
186
-
187
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
188
- return $this->subscribe($order);
189
- }
190
- else
191
- {
192
- if(empty($order->error))
193
- $order->error = __("Unknown error: Authorization failed.", "pmpro");
194
- return false;
195
- }
196
- }
197
- else
198
- {
199
- //charge first payment
200
- if($this->charge($order))
201
- {
202
- //setup recurring billing
203
- if(pmpro_isLevelRecurring($order->membership_level))
204
- {
205
- if(!pmpro_isLevelTrial($order->membership_level))
206
- {
207
- //subscription will start today with a 1 period trial
208
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
209
- $order->TrialBillingPeriod = $order->BillingPeriod;
210
- $order->TrialBillingFrequency = $order->BillingFrequency;
211
- $order->TrialBillingCycles = 1;
212
- $order->TrialAmount = 0;
213
-
214
- //add a billing cycle to make up for the trial, if applicable
215
- if(!empty($order->TotalBillingCycles))
216
- $order->TotalBillingCycles++;
217
- }
218
- elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
219
- {
220
- //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
221
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
222
- $order->TrialBillingCycles++;
223
-
224
- //add a billing cycle to make up for the trial, if applicable
225
- if(!empty($order->TotalBillingCycles))
226
- $order->TotalBillingCycles++;
227
- }
228
- else
229
- {
230
- //add a period to the start date to account for the initial payment
231
- $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $this->BillingFrequency . " " . $this->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
232
- }
233
-
234
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
235
- if($this->subscribe($order))
236
- {
237
- return true;
238
- }
239
- else
240
- {
241
- if($this->void($order))
242
- {
243
- if(!$order->error)
244
- $order->error = __("Unknown error: Payment failed.", "pmpro");
245
- }
246
- else
247
- {
248
- if(!$order->error)
249
- $order->error = __("Unknown error: Payment failed.", "pmpro");
250
-
251
- $order->error .= " " . __("A partial payment was made that we could not void. Please contact the site owner immediately to correct this.", "pmpro");
252
- }
253
-
254
- return false;
255
- }
256
- }
257
- else
258
- {
259
- //only a one time charge
260
- $order->status = apply_filters("pmpro_check_status_after_checkout", "success"); //saved on checkout page
261
- return true;
262
- }
263
- }
264
- else
265
- {
266
- if(empty($order->error))
267
- $order->error = __("Unknown error: Payment failed.", "pmpro");
268
-
269
- return false;
270
- }
271
- }
272
- }
273
-
274
- function authorize(&$order)
275
- {
276
- //create a code for the order
277
- if(empty($order->code))
278
- $order->code = $order->getRandomCode();
279
-
280
- //simulate a successful authorization
281
- $order->payment_transaction_id = "CHECK" . $order->code;
282
- $order->updateStatus("authorized");
283
- return true;
284
- }
285
-
286
- function void(&$order)
287
- {
288
- //need a transaction id
289
- if(empty($order->payment_transaction_id))
290
- return false;
291
-
292
- //simulate a successful void
293
- $order->payment_transaction_id = "CHECK" . $order->code;
294
- $order->updateStatus("voided");
295
- return true;
296
- }
297
-
298
- function charge(&$order)
299
- {
300
- //create a code for the order
301
- if(empty($order->code))
302
- $order->code = $order->getRandomCode();
303
-
304
- //simulate a successful charge
305
- $order->payment_transaction_id = "CHECK" . $order->code;
306
- $order->updateStatus("success");
307
- return true;
308
- }
309
-
310
- function subscribe(&$order)
311
- {
312
- //create a code for the order
313
- if(empty($order->code))
314
- $order->code = $order->getRandomCode();
315
-
316
- //filter order before subscription. use with care.
317
- $order = apply_filters("pmpro_subscribe_order", $order, $this);
318
-
319
- //simulate a successful subscription processing
320
- $order->status = "success";
321
- $order->subscription_transaction_id = "CHECK" . $order->code;
322
- return true;
323
- }
324
-
325
- function update(&$order)
326
- {
327
- //simulate a successful billing update
328
- return true;
329
- }
330
-
331
- function cancel(&$order)
332
- {
333
- //require a subscription id
334
- if(empty($order->subscription_transaction_id))
335
- return false;
336
-
337
- //simulate a successful cancel
338
- $order->updateStatus("cancelled");
339
- return true;
340
- }
341
  }
1
+ <?php
2
+ //include pmprogateway
3
+ require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
+
5
+ //load classes init method
6
+ add_action('init', array('PMProGateway_check', 'init'));
7
+
8
+ class PMProGateway_check extends PMProGateway
9
+ {
10
+ function PMProGateway_check($gateway = NULL)
11
+ {
12
+ $this->gateway = $gateway;
13
+ return $this->gateway;
14
+ }
15
+
16
+ /**
17
+ * Run on WP init
18
+ *
19
+ * @since 1.8
20
+ */
21
+ static function init()
22
+ {
23
+ //make sure Pay by Check is a gateway option
24
+ add_filter('pmpro_gateways', array('PMProGateway_check', 'pmpro_gateways'));
25
+
26
+ //add fields to payment settings
27
+ add_filter('pmpro_payment_options', array('PMProGateway_check', 'pmpro_payment_options'));
28
+ add_filter('pmpro_payment_option_fields', array('PMProGateway_check', 'pmpro_payment_option_fields'), 10, 2);
29
+
30
+ //code to add at checkout
31
+ $gateway = pmpro_getGateway();
32
+ if($gateway == "check")
33
+ {
34
+ add_filter('pmpro_include_billing_address_fields', '__return_false');
35
+ add_filter('pmpro_include_payment_information_fields', '__return_false');
36
+ add_filter('pmpro_required_billing_fields', array('PMProGateway_check', 'pmpro_required_billing_fields'));
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Make sure Check is in the gateways list
42
+ *
43
+ * @since 1.8
44
+ */
45
+ static function pmpro_gateways($gateways)
46
+ {
47
+ if(empty($gateways['check']))
48
+ $gateways['check'] = __('Pay by Check', 'pmpro');
49
+
50
+ return $gateways;
51
+ }
52
+
53
+ /**
54
+ * Get a list of payment options that the Check gateway needs/supports.
55
+ *
56
+ * @since 1.8
57
+ */
58
+ static function getGatewayOptions()
59
+ {
60
+ $options = array(
61
+ 'sslseal',
62
+ 'nuclear_HTTPS',
63
+ 'gateway_environment',
64
+ 'instructions',
65
+ 'currency',
66
+ 'use_ssl',
67
+ 'tax_state',
68
+ 'tax_rate'
69
+ );
70
+
71
+ return $options;
72
+ }
73
+
74
+ /**
75
+ * Set payment options for payment settings page.
76
+ *
77
+ * @since 1.8
78
+ */
79
+ static function pmpro_payment_options($options)
80
+ {
81
+ //get stripe options
82
+ $check_options = PMProGateway_check::getGatewayOptions();
83
+
84
+ //merge with others.
85
+ $options = array_merge($check_options, $options);
86
+
87
+ return $options;
88
+ }
89
+
90
+ /**
91
+ * Display fields for Check options.
92
+ *
93
+ * @since 1.8
94
+ */
95
+ static function pmpro_payment_option_fields($values, $gateway)
96
+ {
97
+ ?>
98
+ <tr class="pmpro_settings_divider gateway gateway_check" <?php if($gateway != "check") { ?>style="display: none;"<?php } ?>>
99
+ <td colspan="2">
100
+ <?php _e('Pay by Check Settings', 'pmpro'); ?>
101
+ </td>
102
+ </tr>
103
+ <tr class="gateway gateway_check" <?php if($gateway != "check") { ?>style="display: none;"<?php } ?>>
104
+ <th scope="row" valign="top">
105
+ <label for="instructions"><?php _e('Instructions', 'pmpro');?></label>
106
+ </th>
107
+ <td>
108
+ <textarea id="instructions" name="instructions" rows="3" cols="80"><?php echo esc_textarea($values['instructions'])?></textarea>
109
+ <p><small><?php _e('Who to write the check out to. Where to mail it. Shown on checkout, confirmation, and invoice pages.', 'pmpro');?></small></p>
110
+ </td>
111
+ </tr>
112
+ <?php
113
+ }
114
+
115
+ /**
116
+ * Remove required billing fields
117
+ *
118
+ * @since 1.8
119
+ */
120
+ static function pmpro_required_billing_fields($fields)
121
+ {
122
+ unset($fields['bfirstname']);
123
+ unset($fields['blastname']);
124
+ unset($fields['baddress1']);
125
+ unset($fields['bcity']);
126
+ unset($fields['bstate']);
127
+ unset($fields['bzipcode']);
128
+ unset($fields['bphone']);
129
+ unset($fields['bemail']);
130
+ unset($fields['bcountry']);
131
+ unset($fields['CardType']);
132
+ unset($fields['AccountNumber']);
133
+ unset($fields['ExpirationMonth']);
134
+ unset($fields['ExpirationYear']);
135
+ unset($fields['CVV']);
136
+
137
+ return $fields;
138
+ }
139
+
140
+ /**
141
+ * Process checkout.
142
+ *
143
+ */
144
+ function process(&$order)
145
+ {
146
+ //clean up a couple values
147
+ $order->payment_type = "Check";
148
+ $order->CardType = "";
149
+ $order->cardtype = "";
150
+
151
+ //check for initial payment
152
+ if(floatval($order->InitialPayment) == 0)
153
+ {
154
+ //auth first, then process
155
+ if($this->authorize($order))
156
+ {
157
+ $this->void($order);
158
+ if(!pmpro_isLevelTrial($order->membership_level))
159
+ {
160
+ //subscription will start today with a 1 period trial
161
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
162
+ $order->TrialBillingPeriod = $order->BillingPeriod;
163
+ $order->TrialBillingFrequency = $order->BillingFrequency;
164
+ $order->TrialBillingCycles = 1;
165
+ $order->TrialAmount = 0;
166
+
167
+ //add a billing cycle to make up for the trial, if applicable
168
+ if(!empty($order->TotalBillingCycles))
169
+ $order->TotalBillingCycles++;
170
+ }
171
+ elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
172
+ {
173
+ //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
174
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
175
+ $order->TrialBillingCycles++;
176
+
177
+ //add a billing cycle to make up for the trial, if applicable
178
+ if($order->TotalBillingCycles)
179
+ $order->TotalBillingCycles++;
180
+ }
181
+ else
182
+ {
183
+ //add a period to the start date to account for the initial payment
184
+ $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
185
+ }
186
+
187
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
188
+ return $this->subscribe($order);
189
+ }
190
+ else
191
+ {
192
+ if(empty($order->error))
193
+ $order->error = __("Unknown error: Authorization failed.", "pmpro");
194
+ return false;
195
+ }
196
+ }
197
+ else
198
+ {
199
+ //charge first payment
200
+ if($this->charge($order))
201
+ {
202
+ //setup recurring billing
203
+ if(pmpro_isLevelRecurring($order->membership_level))
204
+ {
205
+ if(!pmpro_isLevelTrial($order->membership_level))
206
+ {
207
+ //subscription will start today with a 1 period trial
208
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
209
+ $order->TrialBillingPeriod = $order->BillingPeriod;
210
+ $order->TrialBillingFrequency = $order->BillingFrequency;
211
+ $order->TrialBillingCycles = 1;
212
+ $order->TrialAmount = 0;
213
+
214
+ //add a billing cycle to make up for the trial, if applicable
215
+ if(!empty($order->TotalBillingCycles))
216
+ $order->TotalBillingCycles++;
217
+ }
218
+ elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
219
+ {
220
+ //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
221
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
222
+ $order->TrialBillingCycles++;
223
+
224
+ //add a billing cycle to make up for the trial, if applicable
225
+ if(!empty($order->TotalBillingCycles))
226
+ $order->TotalBillingCycles++;
227
+ }
228
+ else
229
+ {
230
+ //add a period to the start date to account for the initial payment
231
+ $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $this->BillingFrequency . " " . $this->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
232
+ }
233
+
234
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
235
+ if($this->subscribe($order))
236
+ {
237
+ return true;
238
+ }
239
+ else
240
+ {
241
+ if($this->void($order))
242
+ {
243
+ if(!$order->error)
244
+ $order->error = __("Unknown error: Payment failed.", "pmpro");
245
+ }
246
+ else
247
+ {
248
+ if(!$order->error)
249
+ $order->error = __("Unknown error: Payment failed.", "pmpro");
250
+
251
+ $order->error .= " " . __("A partial payment was made that we could not void. Please contact the site owner immediately to correct this.", "pmpro");
252
+ }
253
+
254
+ return false;
255
+ }
256
+ }
257
+ else
258
+ {
259
+ //only a one time charge
260
+ $order->status = apply_filters("pmpro_check_status_after_checkout", "success"); //saved on checkout page
261
+ return true;
262
+ }
263
+ }
264
+ else
265
+ {
266
+ if(empty($order->error))
267
+ $order->error = __("Unknown error: Payment failed.", "pmpro");
268
+
269
+ return false;
270
+ }
271
+ }
272
+ }
273
+
274
+ function authorize(&$order)
275
+ {
276
+ //create a code for the order
277
+ if(empty($order->code))
278
+ $order->code = $order->getRandomCode();
279
+
280
+ //simulate a successful authorization
281
+ $order->payment_transaction_id = "CHECK" . $order->code;
282
+ $order->updateStatus("authorized");
283
+ return true;
284
+ }
285
+
286
+ function void(&$order)
287
+ {
288
+ //need a transaction id
289
+ if(empty($order->payment_transaction_id))
290
+ return false;
291
+
292
+ //simulate a successful void
293
+ $order->payment_transaction_id = "CHECK" . $order->code;
294
+ $order->updateStatus("voided");
295
+ return true;
296
+ }
297
+
298
+ function charge(&$order)
299
+ {
300
+ //create a code for the order
301
+ if(empty($order->code))
302
+ $order->code = $order->getRandomCode();
303
+
304
+ //simulate a successful charge
305
+ $order->payment_transaction_id = "CHECK" . $order->code;
306
+ $order->updateStatus("success");
307
+ return true;
308
+ }
309
+
310
+ function subscribe(&$order)
311
+ {
312
+ //create a code for the order
313
+ if(empty($order->code))
314
+ $order->code = $order->getRandomCode();
315
+
316
+ //filter order before subscription. use with care.
317
+ $order = apply_filters("pmpro_subscribe_order", $order, $this);
318
+
319
+ //simulate a successful subscription processing
320
+ $order->status = "success";
321
+ $order->subscription_transaction_id = "CHECK" . $order->code;
322
+ return true;
323
+ }
324
+
325
+ function update(&$order)
326
+ {
327
+ //simulate a successful billing update
328
+ return true;
329
+ }
330
+
331
+ function cancel(&$order)
332
+ {
333
+ //require a subscription id
334
+ if(empty($order->subscription_transaction_id))
335
+ return false;
336
+
337
+ //simulate a successful cancel
338
+ $order->updateStatus("cancelled");
339
+ return true;
340
+ }
341
  }
classes/gateways/class.pmprogateway_cybersource.php CHANGED
@@ -1,884 +1,884 @@
1
- <?php
2
- //include pmprogateway
3
- require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
-
5
- //load classes init method
6
- add_action('init', array('PMProGateway_cybersource', 'init'));
7
-
8
- class PMProGateway_cybersource extends PMProGateway
9
- {
10
- function PMProGateway_cybersource($gateway = NULL)
11
- {
12
- if(!class_exists("CyberSourceSoapClient"))
13
- require_once(dirname(__FILE__) . "/../../includes/lib/CyberSource/cyber_source_soap_client.php");
14
-
15
- $this->gateway = $gateway;
16
- return $this->gateway;
17
- }
18
-
19
- /**
20
- * Run on WP init
21
- *
22
- * @since 1.8
23
- */
24
- static function init()
25
- {
26
- //make sure CyberSource is a gateway option
27
- add_filter('pmpro_gateways', array('PMProGateway_cybersource', 'pmpro_gateways'));
28
-
29
- //add fields to payment settings
30
- add_filter('pmpro_payment_options', array('PMProGateway_cybersource', 'pmpro_payment_options'));
31
- add_filter('pmpro_payment_option_fields', array('PMProGateway_cybersource', 'pmpro_payment_option_fields'), 10, 2);
32
- }
33
-
34
- /**
35
- * Make sure this gateway is in the gateways list
36
- *
37
- * @since 1.8
38
- */
39
- static function pmpro_gateways($gateways)
40
- {
41
- if(empty($gateways['cybersource']))
42
- $gateways['cybersource'] = __('CyberSource', 'pmpro');
43
-
44
- return $gateways;
45
- }
46
-
47
- /**
48
- * Get a list of payment options that the this gateway needs/supports.
49
- *
50
- * @since 1.8
51
- */
52
- static function getGatewayOptions()
53
- {
54
- $options = array(
55
- 'sslseal',
56
- 'nuclear_HTTPS',
57
- 'gateway_environment',
58
- 'cybersource_merchantid',
59
- 'cybersource_securitykey',
60
- 'currency',
61
- 'use_ssl',
62
- 'tax_state',
63
- 'tax_rate',
64
- 'accepted_credit_cards'
65
- );
66
-
67
- return $options;
68
- }
69
-
70
- /**
71
- * Set payment options for payment settings page.
72
- *
73
- * @since 1.8
74
- */
75
- static function pmpro_payment_options($options)
76
- {
77
- //get stripe options
78
- $cybersource_options = PMProGateway_cybersource::getGatewayOptions();
79
-
80
- //merge with others.
81
- $options = array_merge($cybersource_options, $options);
82
-
83
- return $options;
84
- }
85
-
86
- /**
87
- * Display fields for this gateway's options.
88
- *
89
- * @since 1.8
90
- */
91
- static function pmpro_payment_option_fields($values, $gateway)
92
- {
93
- ?>
94
- <tr class="pmpro_settings_divider gateway gateway_cybersource" <?php if($gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
95
- <td colspan="2">
96
- <?php _e('CyberSource Settings', 'pmpro'); ?>
97
- </td>
98
- </tr>
99
- <tr class="gateway gateway_cybersource" <?php if($gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
100
- <td colspan="2">
101
- <strong><?php _e('Note', 'pmpro');?>:</strong> <?php _e('This gateway option is in beta. Some functionality may not be available. Please contact Paid Memberships Pro with any issues you run into. <strong>Please be sure to upgrade Paid Memberships Pro to the latest versions when available.</strong>', 'pmpro');?>
102
- </td>
103
- </tr>
104
- <tr class="gateway gateway_cybersource" <?php if($gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
105
- <th scope="row" valign="top">
106
- <label for="cybersource_merchantid"><?php _e('Merchant ID', 'pmpro');?>:</label>
107
- </th>
108
- <td>
109
- <input type="text" id="cybersource_merchantid" name="cybersource_merchantid" size="60" value="<?php echo esc_attr($values['cybersource_merchantid'])?>" />
110
- </td>
111
- </tr>
112
- <tr class="gateway gateway_cybersource" <?php if($gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
113
- <th scope="row" valign="top">
114
- <label for="cybersource_securitykey"><?php _e('Transaction Security Key', 'pmpro');?>:</label>
115
- </th>
116
- <td>
117
- <textarea id="cybersource_securitykey" name="cybersource_securitykey" rows="3" cols="80"><?php echo esc_textarea($values['cybersource_securitykey']);?></textarea>
118
- </td>
119
- </tr>
120
- <?php
121
- }
122
-
123
- /**
124
- * Process checkout.
125
- *
126
- */
127
- function process(&$order)
128
- {
129
- //check for initial payment
130
- if(floatval($order->InitialPayment) == 0)
131
- {
132
- //auth first, then process
133
- if($this->authorize($order))
134
- {
135
- $this->void($order);
136
- if(!pmpro_isLevelTrial($order->membership_level))
137
- {
138
- //subscription will start today with a 1 period trial
139
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
140
- $order->TrialBillingPeriod = $order->BillingPeriod;
141
- $order->TrialBillingFrequency = $order->BillingFrequency;
142
- $order->TrialBillingCycles = 1;
143
- $order->TrialAmount = 0;
144
-
145
- //add a billing cycle to make up for the trial, if applicable
146
- if(!empty($order->TotalBillingCycles))
147
- $order->TotalBillingCycles++;
148
- }
149
- elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
150
- {
151
- //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
152
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
153
- $order->TrialBillingCycles++;
154
-
155
- //add a billing cycle to make up for the trial, if applicable
156
- if($order->TotalBillingCycles)
157
- $order->TotalBillingCycles++;
158
- }
159
- else
160
- {
161
- //add a period to the start date to account for the initial payment
162
- $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
163
- }
164
-
165
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
166
- return $this->subscribe($order);
167
- }
168
- else
169
- {
170
- if(empty($order->error))
171
- $order->error = __("Unknown error: Authorization failed.", "pmpro");
172
- return false;
173
- }
174
- }
175
- else
176
- {
177
- //charge first payment
178
- if($this->charge($order))
179
- {
180
- //setup recurring billing
181
- if(pmpro_isLevelRecurring($order->membership_level))
182
- {
183
- if(!pmpro_isLevelTrial($order->membership_level))
184
- {
185
- //subscription will start today with a 1 period trial
186
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
187
- $order->TrialBillingPeriod = $order->BillingPeriod;
188
- $order->TrialBillingFrequency = $order->BillingFrequency;
189
- $order->TrialBillingCycles = 1;
190
- $order->TrialAmount = 0;
191
-
192
- //add a billing cycle to make up for the trial, if applicable
193
- if(!empty($order->TotalBillingCycles))
194
- $order->TotalBillingCycles++;
195
- }
196
- elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
197
- {
198
- //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
199
- $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
200
- $order->TrialBillingCycles++;
201
-
202
- //add a billing cycle to make up for the trial, if applicable
203
- if(!empty($order->TotalBillingCycles))
204
- $order->TotalBillingCycles++;
205
- }
206
- else
207
- {
208
- //add a period to the start date to account for the initial payment
209
- $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $this->BillingFrequency . " " . $this->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
210
- }
211
-
212
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
213
- if($this->subscribe($order))
214
- {
215
- return true;
216
- }
217
- else
218
- {
219
- if($this->void($order))
220
- {
221
- if(!$order->error)
222
- $order->error = __("Unknown error: Payment failed.", "pmpro");
223
- }
224
- else
225
- {
226
- if(!$order->error)
227
- $order->error = __("Unknown error: Payment failed.", "pmpro");
228
-
229
- $order->error .= " " . __("A partial payment was made that we could not void. Please contact the site owner immediately to correct this.", "pmpro");
230
- }
231
-
232
- return false;
233
- }
234
- }
235
- else
236
- {
237
- //only a one time charge
238
- $order->status = "success"; //saved on checkout page
239
- return true;
240
- }
241
- }
242
- else
243
- {
244
- if(empty($order->error))
245
- $order->error = __("Unknown error: Payment failed.", "pmpro");
246
-
247
- return false;
248
- }
249
- }
250
- }
251
-
252
- function getCardType($name)
253
- {
254
- $card_types = array(
255
- 'Visa' => '001',
256
- 'MasterCard' => '002',
257
- 'Master Card' => '002',
258
- 'AMEX' => '003',
259
- 'American Express' => '003',
260
- 'Discover' => '004',
261
- 'Diners Club' => '005',
262
- 'Carte Blanche' => '006',
263
- 'JCB' => '007'
264
- );
265
-
266
- if(isset($card_types[$name]))
267
- return $card_types[$name];
268
- else
269
- return false;
270
- }
271
-
272
- function getWSDL($order)
273
- {
274
- //which gateway environment?
275
- if(empty($order->gateway_environment))
276
- $gateway_environment = pmpro_getOption("gateway_environment");
277
- else
278
- $gateway_environment = $order->gateway_environment;
279
-
280
- //which host?
281
- if($gateway_environment == "live")
282
- $host = "ics2ws.ic3.com";
283
- else
284
- $host = "ics2wstest.ic3.com";
285
-
286
- //path
287
- $path = "/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.90.wsdl";
288
-
289
- //build url
290
- $wsdl_url = "https://" . $host . $path;
291
-
292
- //filter
293
- $wsdl_url = apply_filters("pmpro_cybersource_wsdl_url", $wsdl_url, $gateway_environment);
294
-
295
- return $wsdl_url;
296
- }
297
-
298
- function authorize(&$order)
299
- {
300
- global $pmpro_currency;
301
-
302
- if(empty($order->code))
303
- $order->code = $order->getRandomCode();
304
-
305
- $wsdl_url = $this->getWSDL($order);
306
-
307
- //what amount to authorize? just $1 to test
308
- $amount = "1.00";
309
-
310
- //combine address
311
- $address = $order->Address1;
312
- if(!empty($order->Address2))
313
- $address .= "\n" . $order->Address2;
314
-
315
- //customer stuff
316
- $customer_email = $order->Email;
317
- $customer_phone = $order->billing->phone;
318
-
319
- if(!isset($order->membership_level->name))
320
- $order->membership_level->name = "";
321
-
322
- //to store our request
323
- $request = new stdClass();
324
-
325
- //which service?
326
- $ccAuthService = new stdClass();
327
- $ccAuthService->run = "true";
328
- $request->ccAuthService = $ccAuthService;
329
-
330
- //merchant id and order code
331
- $request->merchantID = pmpro_getOption("cybersource_merchantid");
332
- $request->merchantReferenceCode = $order->code;
333
-
334
- //bill to
335
- $billTo = new stdClass();
336
- $billTo->firstName = $order->FirstName;
337
- $billTo->lastName = $order->LastName;
338
- $billTo->street1 = $address;
339
- $billTo->city = $order->billing->city;
340
- $billTo->state = $order->billing->state;
341
- $billTo->postalCode = $order->billing->zip;
342
- $billTo->country = $order->billing->country;
343
- $billTo->email = $order->Email;
344
- $billTo->ipAddress = $_SERVER['REMOTE_ADDR'];
345
- $request->billTo = $billTo;
346
-
347
- //card
348
- $card = new stdClass();
349
- $card->cardType = $this->getCardType($order->cardtype);
350
- $card->accountNumber = $order->accountnumber;
351
- $card->expirationMonth = $order->expirationmonth;
352
- $card->expirationYear = $order->expirationyear;
353
- $card->cvNumber = $order->CVV2;
354
- $request->card = $card;
355
-
356
- //currency
357
- $purchaseTotals = new stdClass();
358
- $purchaseTotals->currency = $pmpro_currency;
359
- $request->purchaseTotals = $purchaseTotals;
360
-
361
- //item/price
362
- $item0 = new stdClass();
363
- $item0->unitPrice = $amount;
364
- $item0->quantity = "1";
365
- $item0->productName = $order->membership_level->name . " Membership";
366
- $item0->productSKU = $order->membership_level->id;
367
- $item0->id = $order->membership_id;
368
- $request->item = array($item0);
369
-
370
- $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
371
- $reply = $soapClient->runTransaction($request);
372
-
373
- if($reply->reasonCode == "100")
374
- {
375
- //success
376
- $order->payment_transaction_id = $reply->requestID;
377
- $order->updateStatus("authorized");
378
- return true;
379
- }
380
- else
381
- {
382
- //error
383
- $order->errorcode = $reply->reasonCode;
384
- $order->error = $this->getErrorFromCode($reply->reasonCode);
385
- $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
386
- return false;
387
- }
388
- }
389
-
390
- function void(&$order)
391
- {
392
- //need a transaction id
393
- if(empty($order->payment_transaction_id))
394
- return false;
395
-
396
- //get wsdl
397
- $wsdl_url = $this->getWSDL($order);
398
-
399
- //to store our request
400
- $request = new stdClass();
401
-
402
- //which service?
403
- $voidService = new stdClass();
404
- $voidService->run = "true";
405
- $voidService->voidRequestID = $order->payment_transaction_id;
406
- $request->voidService = $voidService;
407
-
408
- //merchant id and order code
409
- $request->merchantID = pmpro_getOption("cybersource_merchantid");
410
- $request->merchantReferenceCode = $order->code;
411
-
412
- $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
413
- $reply = $soapClient->runTransaction($request);
414
-
415
- if($reply->reasonCode == "100")
416
- {
417
- //success
418
- $order->payment_transaction_id = $reply->requestID;
419
- $order->updateStatus("voided");
420
- return true;
421
- }
422
- else
423
- {
424
- //error
425
- $order->errorcode = $reply->reasonCode;
426
- $order->error = $this->getErrorFromCode($reply->reasonCode);
427
- $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
428
- return false;
429
- }
430
- }
431
-
432
- function charge(&$order)
433
- {
434
- global $pmpro_currency;
435
-
436
- //get a code
437
- if(empty($order->code))
438
- $order->code = $order->getRandomCode();
439
-
440
- //get wsdl
441
- $wsdl_url = $this->getWSDL($order);
442
-
443
- //what amount to charge?
444
- $amount = $order->InitialPayment;
445
-
446
- //tax
447
- $order->subtotal = $amount;
448
- $tax = $order->getTax(true);
449
- $amount = round((float)$order->subtotal + (float)$tax, 2);
450
-
451
- //combine address
452
- $address = $order->Address1;
453
- if(!empty($order->Address2))
454
- $address .= "\n" . $order->Address2;
455
-
456
- //customer stuff
457
- $customer_email = $order->Email;
458
- $customer_phone = $order->billing->phone;
459
-
460
- if(!isset($order->membership_level->name))
461
- $order->membership_level->name = "";
462
-
463
- //to store our request
464
- $request = new stdClass();
465
-
466
- //authorize and capture
467
- $ccAuthService = new stdClass();
468
- $ccAuthService->run = "true";
469
- $request->ccAuthService = $ccAuthService;
470
-
471
- $ccCaptureService = new stdClass();
472
- $ccCaptureService->run = "true";
473
- $request->ccCaptureService = $ccCaptureService;
474
-
475
- //merchant id and order code
476
- $request->merchantID = pmpro_getOption("cybersource_merchantid");
477
- $request->merchantReferenceCode = $order->code;
478
-
479
- //bill to
480
- $billTo = new stdClass();
481
- $billTo->firstName = $order->FirstName;
482
- $billTo->lastName = $order->LastName;
483
- $billTo->street1 = $address;
484
- $billTo->city = $order->billing->city;
485
- $billTo->state = $order->billing->state;
486
- $billTo->postalCode = $order->billing->zip;
487
- $billTo->country = $order->billing->country;
488
- $billTo->email = $order->Email;
489
- $billTo->ipAddress = $_SERVER['REMOTE_ADDR'];
490
- $request->billTo = $billTo;
491
-
492
- //card
493
- $card = new stdClass();
494
- $card->cardType = $this->getCardType($order->cardtype);
495
- $card->accountNumber = $order->accountnumber;
496
- $card->expirationMonth = $order->expirationmonth;
497
- $card->expirationYear = $order->expirationyear;
498
- $card->cvNumber = $order->CVV2;
499
- $request->card = $card;
500
-
501
- //currency
502
- $purchaseTotals = new stdClass();
503
- $purchaseTotals->currency = $pmpro_currency;
504
- $request->purchaseTotals = $purchaseTotals;
505
-
506
- //item/price
507
- $item0 = new stdClass();
508
- $item0->unitPrice = $amount;
509
- $item0->quantity = "1";
510
- $item0->productName = $order->membership_level->name . " Membership";
511
- $item0->productSKU = $order->membership_level->id;
512
- $item0->id = $order->membership_id;
513
- $request->item = array($item0);
514
-
515
- $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
516
- $reply = $soapClient->runTransaction($request);
517
-
518
- if($reply->reasonCode == "100")
519
- {
520
- //success
521
- $order->payment_transaction_id = $reply->requestID;
522
- $order->updateStatus("success");
523
- return true;
524
- }
525
- else
526
- {
527
- //error
528
- $order->errorcode = $reply->reasonCode;
529
- $order->error = $this->getErrorFromCode($reply->reasonCode);
530
- $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
531
- return false;
532
- }
533
- }
534
-
535
- function subscribe(&$order)
536
- {
537
- global $currency;
538
-
539
- //create a code for the order
540
- if(empty($order->code))
541
- $order->code = $order->getRandomCode();
542
-
543
- //filter order before subscription. use with care.
544
- $order = apply_filters("pmpro_subscribe_order", $order, $this);
545
-
546
- //get wsdl
547
- $wsdl_url = $this->getWSDL($order);
548
-
549
- //to store our request
550
- $request = new stdClass();
551
-
552
- //set service type
553
- $paySubscriptionCreateService = new stdClass();
554
- $paySubscriptionCreateService->run = 'true';
555
- $paySubscriptionCreateService->disableAutoAuth = 'true'; //we do our own auth check
556
- $request->paySubscriptionCreateService = $paySubscriptionCreateService;
557
-
558
- //merchant id and order code
559
- $request->merchantID = pmpro_getOption("cybersource_merchantid");
560
- $request->merchantReferenceCode = $order->code;
561
-
562
- /*
563
- setup billing amount/etc
564
- */
565
- //figure out the amounts
566
- $amount = $order->PaymentAmount;
567
- $amount_tax = $order->getTaxForPrice($amount);
568
- $amount = round((float)$amount + (float)$amount_tax, 2);
569
-
570
- /*
571
- There are two parts to the trial. Part 1 is simply the delay until the first payment
572
- since we are doing the first payment as a separate transaction.
573
- The second part is the actual "trial" set by the admin.
574
- */
575
- //figure out the trial length (first payment handled by initial charge)
576
- if($order->BillingPeriod == "Year")
577
- $trial_period_days = $order->BillingFrequency * 365; //annual
578
- elseif($order->BillingPeriod == "Day")
579
- $trial_period_days = $order->BillingFrequency * 1; //daily
580
- elseif($order->BillingPeriod == "Week")
581
- $trial_period_days = $order->BillingFrequency * 7; //weekly
582
- else
583
- $trial_period_days = $order->BillingFrequency * 30; //assume monthly
584
-
585
- //convert to a profile start date
586
- $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
587
-
588
- //filter the start date
589
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
590
-
591
- //convert back to days
592
- $trial_period_days = ceil(abs(strtotime(date("Y-m-d"), current_time('timestamp')) - strtotime($order->ProfileStartDate, current_time("timestamp"))) / 86400);
593
-
594
- //now add the actual trial set by the site
595
- if(!empty($order->TrialBillingCycles))
596
- {
597
- $trialOccurrences = (int)$order->TrialBillingCycles;
598
- if($order->BillingPeriod == "Year")
599
- $trial_period_days = $trial_period_days + (365 * $order->BillingFrequency * $trialOccurrences); //annual
600
- elseif($order->BillingPeriod == "Day")
601
- $trial_period_days = $trial_period_days + (1 * $order->BillingFrequency * $trialOccurrences); //daily
602
- elseif($order->BillingPeriod == "Week")
603
- $trial_period_days = $trial_period_days + (7 * $order->BillingFrequency * $trialOccurrences); //weekly
604
- else
605
- $trial_period_days = $trial_period_days + (30 * $order->BillingFrequency * $trialOccurrences); //assume monthly
606
- }
607
-
608
- //convert back into a date
609
- $profile_start_date = date("Ymd", strtotime("+ " . $trial_period_days . " Days"));
610
-
611
- //figure out the frequency
612
- if($order->BillingPeriod == "Year")
613
- {
614
- $frequency = "annually"; //ignoring BillingFrequency set on level.
615
- }
616
- elseif($order->BillingPeriod == "Month")
617
- {
618
- if($order->BillingFrequency == 6)
619
- $frequency = "semi annually";
620
- elseif($order->BillingFrequency == 3)
621
- $frequency = "quarterly";
622
- else
623
- $frequency = "monthly";
624
- }
625
- elseif($order->BillingPeriod == "Week")
626
- {
627
- if($order->BillingFrequency == 4)
628
- $frequency = "quad-weekly";
629
- elseif($order->BillingFrequency == 2)
630
- $frequency = "bi-weekly";
631
- else
632
- $frequency = "weekly";
633
- }
634
- elseif($order->BillingPeriod == "Day")
635
- {
636
- if($order->BillingFrequency == 365)
637
- $frequency = "annually";
638
- elseif($order->BillingFrequency == 182)
639
- $frequency = "semi annually";
640
- elseif($order->BillingFrequency == 183)
641
- $frequency = "semi annually";
642
- elseif($order->BillingFrequency == 90)
643
- $frequency = "quaterly";
644
- elseif($order->BillingFrequency == 30)
645
- $frequency = "monthly";
646
- elseif($order->BillingFrequency == 15)
647
- $frequency = "semi-monthly";
648
- elseif($order->BillingFrequency == 28)
649
- $frequency = "quad-weekly";
650
- elseif($order->BillingFrequency == 14)
651
- $frequency = "bi-weekly";
652
- elseif($order->BillingFrequency == 7)
653
- $frequency = "weekly";
654
- }
655
-
656
- //set subscription info for API
657
- $subscription = new stdClass();
658
- $subscription->title = $order->membership_level->name;
659
- $subscription->paymentMethod = "credit card";
660
- $request->subscription = $subscription;
661
-
662
- //recurring info
663
- $recurringSubscriptionInfo = new stdClass();
664
- $recurringSubscriptionInfo->amount = number_format($amount, 2);
665
- $recurringSubscriptionInfo->startDate = $profile_start_date;
666
- $recurringSubscriptionInfo->frequency = $frequency;
667
- if(!empty($order->TotalBillingCycles))
668
- $recurringSubscriptionInfo->numberOfPayments = $order->TotalBillingCycles;
669
- $request->recurringSubscriptionInfo = $recurringSubscriptionInfo;
670
-
671
- //combine address
672
- $address = $order->Address1;
673
- if(!empty($order->Address2))
674
- $address .= "\n" . $order->Address2;
675
-
676
- //bill to
677
- $billTo = new stdClass();
678
- $billTo->firstName = $order->FirstName;
679
- $billTo->lastName = $order->LastName;
680
- $billTo->street1 = $address;
681
- $billTo->city = $order->billing->city;
682
- $billTo->state = $order->billing->state;
683
- $billTo->postalCode = $order->billing->zip;
684
- $billTo->country = $order->billing->country;
685
- $billTo->email = $order->Email;
686
- $billTo->ipAddress = $_SERVER['REMOTE_ADDR'];
687
- $request->billTo = $billTo;
688
-
689
- //card
690
- $card = new stdClass();
691
- $card->cardType = $this->getCardType($order->cardtype);
692
- $card->accountNumber = $order->accountnumber;
693
- $card->expirationMonth = $order->expirationmonth;
694
- $card->expirationYear = $order->expirationyear;
695
- $card->cvNumber = $order->CVV2;
696
- $request->card = $card;
697
-
698
- //currency
699
- $purchaseTotals = new stdClass();
700
- $purchaseTotals->currency = $pmpro_currency;
701
- $request->purchaseTotals = $purchaseTotals;
702
-
703
- $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
704
- $reply = $soapClient->runTransaction($request);
705
-
706
- if($reply->reasonCode == "100")
707
- {
708
- //success
709
- $order->subscription_transaction_id = $reply->requestID;
710
- $order->status = "success";
711
- return true;
712
- }
713
- else
714
- {
715
- //error
716
- $order->status = "error";
717
- $order->errorcode = $reply->reasonCode;
718
- $order->error = $this->getErrorFromCode($reply->reasonCode);
719
- $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
720
- return false;
721
- }
722
- }
723
-
724
- function update(&$order)
725
- {
726
- //get wsdl
727
- $wsdl_url = $this->getWSDL($order);
728
-
729
- //to store our request
730
- $request = new stdClass();
731
-
732
- //set service type
733
- $paySubscriptionUpdateService = new stdClass();
734
- $paySubscriptionUpdateService ->run = "true";
735
- $request->paySubscriptionUpdateService = $paySubscriptionUpdateService ;
736
-
737
- //merchant id and order code
738
- $request->merchantID = pmpro_getOption("cybersource_merchantid");
739
- $request->merchantReferenceCode = $order->code;
740
-
741
- //set subscription info for API
742
- $recurringSubscriptionInfo = new stdClass();
743
- $recurringSubscriptionInfo->subscriptionID = $order->subscription_transaction_id;
744
- $request->recurringSubscriptionInfo = $recurringSubscriptionInfo;
745
-
746
- //combine address
747
- $address = $order->Address1;
748
- if(!empty($order->Address2))
749
- $address .= "\n" . $order->Address2;
750
-
751
- //bill to
752
- $billTo = new stdClass();
753
- $billTo->firstName = $order->FirstName;
754
- $billTo->lastName = $order->LastName;
755
- $billTo->street1 = $address;
756
- $billTo->city = $order->billing->city;
757
- $billTo->state = $order->billing->state;
758
- $billTo->postalCode = $order->billing->zip;
759
- $billTo->country = $order->billing->country;
760
- $billTo->email = $order->Email;
761
- $billTo->ipAddress = $_SERVER['REMOTE_ADDR'];
762
- $request->billTo = $billTo;
763
-
764
- //card
765
- $card = new stdClass();
766
- $card->cardType = $this->getCardType($order->cardtype);
767
- $card->accountNumber = $order->accountnumber;
768
- $card->expirationMonth = $order->expirationmonth;
769
- $card->expirationYear = $order->expirationyear;
770
- $card->cvNumber = $order->CVV2;
771
- $request->card = $card;
772
-
773
- $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
774
- $reply = $soapClient->runTransaction($request);
775
-
776
- if($reply->reasonCode == "100")
777
- {
778
- //success
779
- return true;
780
- }
781
- else
782
- {
783
- //error
784
- $order->errorcode = $reply->reasonCode;
785
- $order->error = $this->getErrorFromCode($reply->reasonCode);
786
- $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
787
- return false;
788
- }
789
- }
790
-
791
- function cancel(&$order)
792
- {
793
- //require a subscription id
794
- if(empty($order->subscription_transaction_id))
795
- return false;
796
-
797
- //get wsdl
798
- $wsdl_url = $this->getWSDL($order);
799
-
800
- //to store our request
801
- $request = new stdClass();
802
-
803
- //which service?
804
- $paySubscriptionDeleteService = new stdClass();
805
- $paySubscriptionDeleteService ->run = "true";
806
- $request->paySubscriptionDeleteService = $paySubscriptionDeleteService ;
807
-
808
- //which order
809
- $recurringSubscriptionInfo = new stdClass();
810
- $recurringSubscriptionInfo->subscriptionID = $order->subscription_transaction_id;
811
- $request->recurringSubscriptionInfo = $recurringSubscriptionInfo;
812
-
813
- //merchant id and order code
814
- $request->merchantID = pmpro_getOption("cybersource_merchantid");
815
- $request->merchantReferenceCode = $order->code;
816
-
817
- $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
818
- $reply = $soapClient->runTransaction($request);
819
-
820
- if($reply->reasonCode == "100")
821
- {
822
- //success
823
- $order->updateStatus("cancelled");
824
- return true;
825
- }
826
- else
827
- {
828
- //error
829
- $order->errorcode = $reply->reasonCode;
830
- $order->error = $this->getErrorFromCode($reply->reasonCode);
831
- $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
832
- return false;
833
- }
834
- }
835
-
836
- function getErrorFromCode($code)
837
- {
838
- $error_messages = array(
839
- "100" => "Successful transaction.",
840
- "101" => "The request is missing one or more required fields.",
841
- "102" => "One or more fields in the request contains invalid data. Check that your billing address is valid.",
842
- "104" => "Duplicate order detected.",
843
- "110" => "Only partial amount was approved.",
844
- "150" => "Error: General system failure.",
845
- "151" => "Error: The request was received but there was a server timeout.",
846
- "152" => "Error: The request was received, but a service did not finish running in time. ",
847
- "200" => "Address Verification Service (AVS) failure.",
848
- "201" => "Authorization failed.",
849
- "202" => "Expired card or invalid expiration date.",
850
- "203" => "The card was declined.",
851
- "204" => "Insufficient funds in the account.",
852
- "205" => "Stolen or lost card.",
853
- "207" => "Issuing bank unavailable.",
854
- "208" => "Inactive card or card not authorized for card-not-present transactions.",
855
- "209" => "American Express Card Identification Digits (CID) did not match.",
856
- "210" => "The card has reached the credit limit. ",
857
- "211" => "Invalid card verification number.",
858
- "221" => "The customer matched an entry on the processors negative file. ",
859
- "230" => "Card verification (CV) check failed.",
860
- "231" => "Invalid account number.",
861
- "232" => "The card type is not accepted by the payment processor.",
862
- "233" => "General decline by the processor.",
863
- "234" => "There is a problem with your CyberSource merchant configuration.",
864
- "235" => "The requested amount exceeds the originally authorized amount.",
865
- "236" => "Processor failure.",
866
- "237" => "The authorization has already been reversed.",
867
- "238" => "The authorization has already been captured.",
868
- "239" => "The requested transaction amount must match the previous transaction amount.",
869
- "240" => "The card type sent is invalid or does not correlate with the credit card number.",
870
- "241" => "The referenced request id is invalid for all follow-on transactions.",
871
- "242" => "The request ID is invalid.",
872
- "243" => "The transaction has already been settled or reversed.",
873
- "246" => "The capture or credit is not voidable because the capture or credit information has already been submitted to your processor. Or, you requested a void for a type of transaction that cannot be voided.",
874
- "247" => "You requested a credit for a capture that was previously voided.",
875
- "250" => "Error: The request was received, but there was a timeout at the payment processor.",
876
- "520" => "Smart Authorization failed."
877
- );
878
-
879
- if(isset($error_messages[$code]))
880
- return $error_messages[$code];
881
- else
882
- return "Unknown error.";
883
- }
884
- }
1
+ <?php
2
+ //include pmprogateway
3
+ require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
+
5
+ //load classes init method
6
+ add_action('init', array('PMProGateway_cybersource', 'init'));
7
+
8
+ class PMProGateway_cybersource extends PMProGateway
9
+ {
10
+ function PMProGateway_cybersource($gateway = NULL)
11
+ {
12
+ if(!class_exists("CyberSourceSoapClient"))
13
+ require_once(dirname(__FILE__) . "/../../includes/lib/CyberSource/cyber_source_soap_client.php");
14
+
15
+ $this->gateway = $gateway;
16
+ return $this->gateway;
17
+ }
18
+
19
+ /**
20
+ * Run on WP init
21
+ *
22
+ * @since 1.8
23
+ */
24
+ static function init()
25
+ {
26
+ //make sure CyberSource is a gateway option
27
+ add_filter('pmpro_gateways', array('PMProGateway_cybersource', 'pmpro_gateways'));
28
+
29
+ //add fields to payment settings
30
+ add_filter('pmpro_payment_options', array('PMProGateway_cybersource', 'pmpro_payment_options'));
31
+ add_filter('pmpro_payment_option_fields', array('PMProGateway_cybersource', 'pmpro_payment_option_fields'), 10, 2);
32
+ }
33
+
34
+ /**
35
+ * Make sure this gateway is in the gateways list
36
+ *
37
+ * @since 1.8
38
+ */
39
+ static function pmpro_gateways($gateways)
40
+ {
41
+ if(empty($gateways['cybersource']))
42
+ $gateways['cybersource'] = __('CyberSource', 'pmpro');
43
+
44
+ return $gateways;
45
+ }
46
+
47
+ /**
48
+ * Get a list of payment options that the this gateway needs/supports.
49
+ *
50
+ * @since 1.8
51
+ */
52
+ static function getGatewayOptions()
53
+ {
54
+ $options = array(
55
+ 'sslseal',
56
+ 'nuclear_HTTPS',
57
+ 'gateway_environment',
58
+ 'cybersource_merchantid',
59
+ 'cybersource_securitykey',
60
+ 'currency',
61
+ 'use_ssl',
62
+ 'tax_state',
63
+ 'tax_rate',
64
+ 'accepted_credit_cards'
65
+ );
66
+
67
+ return $options;
68
+ }
69
+
70
+ /**
71
+ * Set payment options for payment settings page.
72
+ *
73
+ * @since 1.8
74
+ */
75
+ static function pmpro_payment_options($options)
76
+ {
77
+ //get stripe options
78
+ $cybersource_options = PMProGateway_cybersource::getGatewayOptions();
79
+
80
+ //merge with others.
81
+ $options = array_merge($cybersource_options, $options);
82
+
83
+ return $options;
84
+ }
85
+
86
+ /**
87
+ * Display fields for this gateway's options.
88
+ *
89
+ * @since 1.8
90
+ */
91
+ static function pmpro_payment_option_fields($values, $gateway)
92
+ {
93
+ ?>
94
+ <tr class="pmpro_settings_divider gateway gateway_cybersource" <?php if($gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
95
+ <td colspan="2">
96
+ <?php _e('CyberSource Settings', 'pmpro'); ?>
97
+ </td>
98
+ </tr>
99
+ <tr class="gateway gateway_cybersource" <?php if($gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
100
+ <td colspan="2">
101
+ <strong><?php _e('Note', 'pmpro');?>:</strong> <?php _e('This gateway option is in beta. Some functionality may not be available. Please contact Paid Memberships Pro with any issues you run into. <strong>Please be sure to upgrade Paid Memberships Pro to the latest versions when available.</strong>', 'pmpro');?>
102
+ </td>
103
+ </tr>
104
+ <tr class="gateway gateway_cybersource" <?php if($gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
105
+ <th scope="row" valign="top">
106
+ <label for="cybersource_merchantid"><?php _e('Merchant ID', 'pmpro');?>:</label>
107
+ </th>
108
+ <td>
109
+ <input type="text" id="cybersource_merchantid" name="cybersource_merchantid" size="60" value="<?php echo esc_attr($values['cybersource_merchantid'])?>" />
110
+ </td>
111
+ </tr>
112
+ <tr class="gateway gateway_cybersource" <?php if($gateway != "cybersource") { ?>style="display: none;"<?php } ?>>
113
+ <th scope="row" valign="top">
114
+ <label for="cybersource_securitykey"><?php _e('Transaction Security Key', 'pmpro');?>:</label>
115
+ </th>
116
+ <td>
117
+ <textarea id="cybersource_securitykey" name="cybersource_securitykey" rows="3" cols="80"><?php echo esc_textarea($values['cybersource_securitykey']);?></textarea>
118
+ </td>
119
+ </tr>
120
+ <?php
121
+ }
122
+
123
+ /**
124
+ * Process checkout.
125
+ *
126
+ */
127
+ function process(&$order)
128
+ {
129
+ //check for initial payment
130
+ if(floatval($order->InitialPayment) == 0)
131
+ {
132
+ //auth first, then process
133
+ if($this->authorize($order))
134
+ {
135
+ $this->void($order);
136
+ if(!pmpro_isLevelTrial($order->membership_level))
137
+ {
138
+ //subscription will start today with a 1 period trial
139
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
140
+ $order->TrialBillingPeriod = $order->BillingPeriod;
141
+ $order->TrialBillingFrequency = $order->BillingFrequency;
142
+ $order->TrialBillingCycles = 1;
143
+ $order->TrialAmount = 0;
144
+
145
+ //add a billing cycle to make up for the trial, if applicable
146
+ if(!empty($order->TotalBillingCycles))
147
+ $order->TotalBillingCycles++;
148
+ }
149
+ elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
150
+ {
151
+ //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
152
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
153
+ $order->TrialBillingCycles++;
154
+
155
+ //add a billing cycle to make up for the trial, if applicable
156
+ if($order->TotalBillingCycles)
157
+ $order->TotalBillingCycles++;
158
+ }
159
+ else
160
+ {
161
+ //add a period to the start date to account for the initial payment
162
+ $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
163
+ }
164
+
165
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
166
+ return $this->subscribe($order);
167
+ }
168
+ else
169
+ {
170
+ if(empty($order->error))
171
+ $order->error = __("Unknown error: Authorization failed.", "pmpro");
172
+ return false;
173
+ }
174
+ }
175
+ else
176
+ {
177
+ //charge first payment
178
+ if($this->charge($order))
179
+ {
180
+ //setup recurring billing
181
+ if(pmpro_isLevelRecurring($order->membership_level))
182
+ {
183
+ if(!pmpro_isLevelTrial($order->membership_level))
184
+ {
185
+ //subscription will start today with a 1 period trial
186
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
187
+ $order->TrialBillingPeriod = $order->BillingPeriod;
188
+ $order->TrialBillingFrequency = $order->BillingFrequency;
189
+ $order->TrialBillingCycles = 1;
190
+ $order->TrialAmount = 0;
191
+
192
+ //add a billing cycle to make up for the trial, if applicable
193
+ if(!empty($order->TotalBillingCycles))
194
+ $order->TotalBillingCycles++;
195
+ }
196
+ elseif($order->InitialPayment == 0 && $order->TrialAmount == 0)
197
+ {
198
+ //it has a trial, but the amount is the same as the initial payment, so we can squeeze it in there
199
+ $order->ProfileStartDate = date("Y-m-d") . "T0:0:0";
200
+ $order->TrialBillingCycles++;
201
+
202
+ //add a billing cycle to make up for the trial, if applicable
203
+ if(!empty($order->TotalBillingCycles))
204
+ $order->TotalBillingCycles++;
205
+ }
206
+ else
207
+ {
208
+ //add a period to the start date to account for the initial payment
209
+ $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $this->BillingFrequency . " " . $this->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
210
+ }
211
+
212
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
213
+ if($this->subscribe($order))
214
+ {
215
+ return true;
216
+ }
217
+ else
218
+ {
219
+ if($this->void($order))
220
+ {
221
+ if(!$order->error)
222
+ $order->error = __("Unknown error: Payment failed.", "pmpro");
223
+ }
224
+ else
225
+ {
226
+ if(!$order->error)
227
+ $order->error = __("Unknown error: Payment failed.", "pmpro");
228
+
229
+ $order->error .= " " . __("A partial payment was made that we could not void. Please contact the site owner immediately to correct this.", "pmpro");
230
+ }
231
+
232
+ return false;
233
+ }
234
+ }
235
+ else
236
+ {
237
+ //only a one time charge
238
+ $order->status = "success"; //saved on checkout page
239
+ return true;
240
+ }
241
+ }
242
+ else
243
+ {
244
+ if(empty($order->error))
245
+ $order->error = __("Unknown error: Payment failed.", "pmpro");
246
+
247
+ return false;
248
+ }
249
+ }
250
+ }
251
+
252
+ function getCardType($name)
253
+ {
254
+ $card_types = array(
255
+ 'Visa' => '001',
256
+ 'MasterCard' => '002',
257
+ 'Master Card' => '002',
258
+ 'AMEX' => '003',
259
+ 'American Express' => '003',
260
+ 'Discover' => '004',
261
+ 'Diners Club' => '005',
262
+ 'Carte Blanche' => '006',
263
+ 'JCB' => '007'
264
+ );
265
+
266
+ if(isset($card_types[$name]))
267
+ return $card_types[$name];
268
+ else
269
+ return false;
270
+ }
271
+
272
+ function getWSDL($order)
273
+ {
274
+ //which gateway environment?
275
+ if(empty($order->gateway_environment))
276
+ $gateway_environment = pmpro_getOption("gateway_environment");
277
+ else
278
+ $gateway_environment = $order->gateway_environment;
279
+
280
+ //which host?
281
+ if($gateway_environment == "live")
282
+ $host = "ics2ws.ic3.com";
283
+ else
284
+ $host = "ics2wstest.ic3.com";
285
+
286
+ //path
287
+ $path = "/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.90.wsdl";
288
+
289
+ //build url
290
+ $wsdl_url = "https://" . $host . $path;
291
+
292
+ //filter
293
+ $wsdl_url = apply_filters("pmpro_cybersource_wsdl_url", $wsdl_url, $gateway_environment);
294
+
295
+ return $wsdl_url;
296
+ }
297
+
298
+ function authorize(&$order)
299
+ {
300
+ global $pmpro_currency;
301
+
302
+ if(empty($order->code))
303
+ $order->code = $order->getRandomCode();
304
+
305
+ $wsdl_url = $this->getWSDL($order);
306
+
307
+ //what amount to authorize? just $1 to test
308
+ $amount = "1.00";
309
+
310
+ //combine address
311
+ $address = $order->Address1;
312
+ if(!empty($order->Address2))
313
+ $address .= "\n" . $order->Address2;
314
+
315
+ //customer stuff
316
+ $customer_email = $order->Email;
317
+ $customer_phone = $order->billing->phone;
318
+
319
+ if(!isset($order->membership_level->name))
320
+ $order->membership_level->name = "";
321
+
322
+ //to store our request
323
+ $request = new stdClass();
324
+
325
+ //which service?
326
+ $ccAuthService = new stdClass();
327
+ $ccAuthService->run = "true";
328
+ $request->ccAuthService = $ccAuthService;
329
+
330
+ //merchant id and order code
331
+ $request->merchantID = pmpro_getOption("cybersource_merchantid");
332
+ $request->merchantReferenceCode = $order->code;
333
+
334
+ //bill to
335
+ $billTo = new stdClass();
336
+ $billTo->firstName = $order->FirstName;
337
+ $billTo->lastName = $order->LastName;
338
+ $billTo->street1 = $address;
339
+ $billTo->city = $order->billing->city;
340
+ $billTo->state = $order->billing->state;
341
+ $billTo->postalCode = $order->billing->zip;
342
+ $billTo->country = $order->billing->country;
343
+ $billTo->email = $order->Email;
344
+ $billTo->ipAddress = $_SERVER['REMOTE_ADDR'];
345
+ $request->billTo = $billTo;
346
+
347
+ //card
348
+ $card = new stdClass();
349
+ $card->cardType = $this->getCardType($order->cardtype);
350
+ $card->accountNumber = $order->accountnumber;
351
+ $card->expirationMonth = $order->expirationmonth;
352
+ $card->expirationYear = $order->expirationyear;
353
+ $card->cvNumber = $order->CVV2;
354
+ $request->card = $card;
355
+
356
+ //currency
357
+ $purchaseTotals = new stdClass();
358
+ $purchaseTotals->currency = $pmpro_currency;
359
+ $request->purchaseTotals = $purchaseTotals;
360
+
361
+ //item/price
362
+ $item0 = new stdClass();
363
+ $item0->unitPrice = $amount;
364
+ $item0->quantity = "1";
365
+ $item0->productName = $order->membership_level->name . " Membership";
366
+ $item0->productSKU = $order->membership_level->id;
367
+ $item0->id = $order->membership_id;
368
+ $request->item = array($item0);
369
+
370
+ $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
371
+ $reply = $soapClient->runTransaction($request);
372
+
373
+ if($reply->reasonCode == "100")
374
+ {
375
+ //success
376
+ $order->payment_transaction_id = $reply->requestID;
377
+ $order->updateStatus("authorized");
378
+ return true;
379
+ }
380
+ else
381
+ {
382
+ //error
383
+ $order->errorcode = $reply->reasonCode;
384
+ $order->error = $this->getErrorFromCode($reply->reasonCode);
385
+ $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
386
+ return false;
387
+ }
388
+ }
389
+
390
+ function void(&$order)
391
+ {
392
+ //need a transaction id
393
+ if(empty($order->payment_transaction_id))
394
+ return false;
395
+
396
+ //get wsdl
397
+ $wsdl_url = $this->getWSDL($order);
398
+
399
+ //to store our request
400
+ $request = new stdClass();
401
+
402
+ //which service?
403
+ $voidService = new stdClass();
404
+ $voidService->run = "true";
405
+ $voidService->voidRequestID = $order->payment_transaction_id;
406
+ $request->voidService = $voidService;
407
+
408
+ //merchant id and order code
409
+ $request->merchantID = pmpro_getOption("cybersource_merchantid");
410
+ $request->merchantReferenceCode = $order->code;
411
+
412
+ $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
413
+ $reply = $soapClient->runTransaction($request);
414
+
415
+ if($reply->reasonCode == "100")
416
+ {
417
+ //success
418
+ $order->payment_transaction_id = $reply->requestID;
419
+ $order->updateStatus("voided");
420
+ return true;
421
+ }
422
+ else
423
+ {
424
+ //error
425
+ $order->errorcode = $reply->reasonCode;
426
+ $order->error = $this->getErrorFromCode($reply->reasonCode);
427
+ $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
428
+ return false;
429
+ }
430
+ }
431
+
432
+ function charge(&$order)
433
+ {
434
+ global $pmpro_currency;
435
+
436
+ //get a code
437
+ if(empty($order->code))
438
+ $order->code = $order->getRandomCode();
439
+
440
+ //get wsdl
441
+ $wsdl_url = $this->getWSDL($order);
442
+
443
+ //what amount to charge?
444
+ $amount = $order->InitialPayment;
445
+
446
+ //tax
447
+ $order->subtotal = $amount;
448
+ $tax = $order->getTax(true);
449
+ $amount = round((float)$order->subtotal + (float)$tax, 2);
450
+
451
+ //combine address
452
+ $address = $order->Address1;
453
+ if(!empty($order->Address2))
454
+ $address .= "\n" . $order->Address2;
455
+
456
+ //customer stuff
457
+ $customer_email = $order->Email;
458
+ $customer_phone = $order->billing->phone;
459
+
460
+ if(!isset($order->membership_level->name))
461
+ $order->membership_level->name = "";
462
+
463
+ //to store our request
464
+ $request = new stdClass();
465
+
466
+ //authorize and capture
467
+ $ccAuthService = new stdClass();
468
+ $ccAuthService->run = "true";
469
+ $request->ccAuthService = $ccAuthService;
470
+
471
+ $ccCaptureService = new stdClass();
472
+ $ccCaptureService->run = "true";
473
+ $request->ccCaptureService = $ccCaptureService;
474
+
475
+ //merchant id and order code
476
+ $request->merchantID = pmpro_getOption("cybersource_merchantid");
477
+ $request->merchantReferenceCode = $order->code;
478
+
479
+ //bill to
480
+ $billTo = new stdClass();
481
+ $billTo->firstName = $order->FirstName;
482
+ $billTo->lastName = $order->LastName;
483
+ $billTo->street1 = $address;
484
+ $billTo->city = $order->billing->city;
485
+ $billTo->state = $order->billing->state;
486
+ $billTo->postalCode = $order->billing->zip;
487
+ $billTo->country = $order->billing->country;
488
+ $billTo->email = $order->Email;
489
+ $billTo->ipAddress = $_SERVER['REMOTE_ADDR'];
490
+ $request->billTo = $billTo;
491
+
492
+ //card
493
+ $card = new stdClass();
494
+ $card->cardType = $this->getCardType($order->cardtype);
495
+ $card->accountNumber = $order->accountnumber;
496
+ $card->expirationMonth = $order->expirationmonth;
497
+ $card->expirationYear = $order->expirationyear;
498
+ $card->cvNumber = $order->CVV2;
499
+ $request->card = $card;
500
+
501
+ //currency
502
+ $purchaseTotals = new stdClass();
503
+ $purchaseTotals->currency = $pmpro_currency;
504
+ $request->purchaseTotals = $purchaseTotals;
505
+
506
+ //item/price
507
+ $item0 = new stdClass();
508
+ $item0->unitPrice = $amount;
509
+ $item0->quantity = "1";
510
+ $item0->productName = $order->membership_level->name . " Membership";
511
+ $item0->productSKU = $order->membership_level->id;
512
+ $item0->id = $order->membership_id;
513
+ $request->item = array($item0);
514
+
515
+ $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
516
+ $reply = $soapClient->runTransaction($request);
517
+
518
+ if($reply->reasonCode == "100")
519
+ {
520
+ //success
521
+ $order->payment_transaction_id = $reply->requestID;
522
+ $order->updateStatus("success");
523
+ return true;
524
+ }
525
+ else
526
+ {
527
+ //error
528
+ $order->errorcode = $reply->reasonCode;
529
+ $order->error = $this->getErrorFromCode($reply->reasonCode);
530
+ $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
531
+ return false;
532
+ }
533
+ }
534
+
535
+ function subscribe(&$order)
536
+ {
537
+ global $currency;
538
+
539
+ //create a code for the order
540
+ if(empty($order->code))
541
+ $order->code = $order->getRandomCode();
542
+
543
+ //filter order before subscription. use with care.
544
+ $order = apply_filters("pmpro_subscribe_order", $order, $this);
545
+
546
+ //get wsdl
547
+ $wsdl_url = $this->getWSDL($order);
548
+
549
+ //to store our request
550
+ $request = new stdClass();
551
+
552
+ //set service type
553
+ $paySubscriptionCreateService = new stdClass();
554
+ $paySubscriptionCreateService->run = 'true';
555
+ $paySubscriptionCreateService->disableAutoAuth = 'true'; //we do our own auth check
556
+ $request->paySubscriptionCreateService = $paySubscriptionCreateService;
557
+
558
+ //merchant id and order code
559
+ $request->merchantID = pmpro_getOption("cybersource_merchantid");
560
+ $request->merchantReferenceCode = $order->code;
561
+
562
+ /*
563
+ setup billing amount/etc
564
+ */
565
+ //figure out the amounts
566
+ $amount = $order->PaymentAmount;
567
+ $amount_tax = $order->getTaxForPrice($amount);
568
+ $amount = round((float)$amount + (float)$amount_tax, 2);
569
+
570
+ /*
571
+ There are two parts to the trial. Part 1 is simply the delay until the first payment
572
+ since we are doing the first payment as a separate transaction.
573
+ The second part is the actual "trial" set by the admin.
574
+ */
575
+ //figure out the trial length (first payment handled by initial charge)
576
+ if($order->BillingPeriod == "Year")
577
+ $trial_period_days = $order->BillingFrequency * 365; //annual
578
+ elseif($order->BillingPeriod == "Day")
579
+ $trial_period_days = $order->BillingFrequency * 1; //daily
580
+ elseif($order->BillingPeriod == "Week")
581
+ $trial_period_days = $order->BillingFrequency * 7; //weekly
582
+ else
583
+ $trial_period_days = $order->BillingFrequency * 30; //assume monthly
584
+
585
+ //convert to a profile start date
586
+ $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
587
+
588
+ //filter the start date
589
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
590
+
591
+ //convert back to days
592
+ $trial_period_days = ceil(abs(strtotime(date("Y-m-d"), current_time('timestamp')) - strtotime($order->ProfileStartDate, current_time("timestamp"))) / 86400);
593
+
594
+ //now add the actual trial set by the site
595
+ if(!empty($order->TrialBillingCycles))
596
+ {
597
+ $trialOccurrences = (int)$order->TrialBillingCycles;
598
+ if($order->BillingPeriod == "Year")
599
+ $trial_period_days = $trial_period_days + (365 * $order->BillingFrequency * $trialOccurrences); //annual
600
+ elseif($order->BillingPeriod == "Day")
601
+ $trial_period_days = $trial_period_days + (1 * $order->BillingFrequency * $trialOccurrences); //daily
602
+ elseif($order->BillingPeriod == "Week")
603
+ $trial_period_days = $trial_period_days + (7 * $order->BillingFrequency * $trialOccurrences); //weekly
604
+ else
605
+ $trial_period_days = $trial_period_days + (30 * $order->BillingFrequency * $trialOccurrences); //assume monthly
606
+ }
607
+
608
+ //convert back into a date
609
+ $profile_start_date = date("Ymd", strtotime("+ " . $trial_period_days . " Days"));
610
+
611
+ //figure out the frequency
612
+ if($order->BillingPeriod == "Year")
613
+ {
614
+ $frequency = "annually"; //ignoring BillingFrequency set on level.
615
+ }
616
+ elseif($order->BillingPeriod == "Month")
617
+ {
618
+ if($order->BillingFrequency == 6)
619
+ $frequency = "semi annually";
620
+ elseif($order->BillingFrequency == 3)
621
+ $frequency = "quarterly";
622
+ else
623
+ $frequency = "monthly";
624
+ }
625
+ elseif($order->BillingPeriod == "Week")
626
+ {
627
+ if($order->BillingFrequency == 4)
628
+ $frequency = "quad-weekly";
629
+ elseif($order->BillingFrequency == 2)
630
+ $frequency = "bi-weekly";
631
+ else
632
+ $frequency = "weekly";
633
+ }
634
+ elseif($order->BillingPeriod == "Day")
635
+ {
636
+ if($order->BillingFrequency == 365)
637
+ $frequency = "annually";
638
+ elseif($order->BillingFrequency == 182)
639
+ $frequency = "semi annually";
640
+ elseif($order->BillingFrequency == 183)
641
+ $frequency = "semi annually";
642
+ elseif($order->BillingFrequency == 90)
643
+ $frequency = "quaterly";
644
+ elseif($order->BillingFrequency == 30)
645
+ $frequency = "monthly";
646
+ elseif($order->BillingFrequency == 15)
647
+ $frequency = "semi-monthly";
648
+ elseif($order->BillingFrequency == 28)
649
+ $frequency = "quad-weekly";
650
+ elseif($order->BillingFrequency == 14)
651
+ $frequency = "bi-weekly";
652
+ elseif($order->BillingFrequency == 7)
653
+ $frequency = "weekly";
654
+ }
655
+
656
+ //set subscription info for API
657
+ $subscription = new stdClass();
658
+ $subscription->title = $order->membership_level->name;
659
+ $subscription->paymentMethod = "credit card";
660
+ $request->subscription = $subscription;
661
+
662
+ //recurring info
663
+ $recurringSubscriptionInfo = new stdClass();
664
+ $recurringSubscriptionInfo->amount = number_format($amount, 2);
665
+ $recurringSubscriptionInfo->startDate = $profile_start_date;
666
+ $recurringSubscriptionInfo->frequency = $frequency;
667
+ if(!empty($order->TotalBillingCycles))
668
+ $recurringSubscriptionInfo->numberOfPayments = $order->TotalBillingCycles;
669
+ $request->recurringSubscriptionInfo = $recurringSubscriptionInfo;
670
+
671
+ //combine address
672
+ $address = $order->Address1;
673
+ if(!empty($order->Address2))
674
+ $address .= "\n" . $order->Address2;
675
+
676
+ //bill to
677
+ $billTo = new stdClass();
678
+ $billTo->firstName = $order->FirstName;
679
+ $billTo->lastName = $order->LastName;
680
+ $billTo->street1 = $address;
681
+ $billTo->city = $order->billing->city;
682
+ $billTo->state = $order->billing->state;
683
+ $billTo->postalCode = $order->billing->zip;
684
+ $billTo->country = $order->billing->country;
685
+ $billTo->email = $order->Email;
686
+ $billTo->ipAddress = $_SERVER['REMOTE_ADDR'];
687
+ $request->billTo = $billTo;
688
+
689
+ //card
690
+ $card = new stdClass();
691
+ $card->cardType = $this->getCardType($order->cardtype);
692
+ $card->accountNumber = $order->accountnumber;
693
+ $card->expirationMonth = $order->expirationmonth;
694
+ $card->expirationYear = $order->expirationyear;
695
+ $card->cvNumber = $order->CVV2;
696
+ $request->card = $card;
697
+
698
+ //currency
699
+ $purchaseTotals = new stdClass();
700
+ $purchaseTotals->currency = $pmpro_currency;
701
+ $request->purchaseTotals = $purchaseTotals;
702
+
703
+ $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
704
+ $reply = $soapClient->runTransaction($request);
705
+
706
+ if($reply->reasonCode == "100")
707
+ {
708
+ //success
709
+ $order->subscription_transaction_id = $reply->requestID;
710
+ $order->status = "success";
711
+ return true;
712
+ }
713
+ else
714
+ {
715
+ //error
716
+ $order->status = "error";
717
+ $order->errorcode = $reply->reasonCode;
718
+ $order->error = $this->getErrorFromCode($reply->reasonCode);
719
+ $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
720
+ return false;
721
+ }
722
+ }
723
+
724
+ function update(&$order)
725
+ {
726
+ //get wsdl
727
+ $wsdl_url = $this->getWSDL($order);
728
+
729
+ //to store our request
730
+ $request = new stdClass();
731
+
732
+ //set service type
733
+ $paySubscriptionUpdateService = new stdClass();
734
+ $paySubscriptionUpdateService ->run = "true";
735
+ $request->paySubscriptionUpdateService = $paySubscriptionUpdateService ;
736
+
737
+ //merchant id and order code
738
+ $request->merchantID = pmpro_getOption("cybersource_merchantid");
739
+ $request->merchantReferenceCode = $order->code;
740
+
741
+ //set subscription info for API
742
+ $recurringSubscriptionInfo = new stdClass();
743
+ $recurringSubscriptionInfo->subscriptionID = $order->subscription_transaction_id;
744
+ $request->recurringSubscriptionInfo = $recurringSubscriptionInfo;
745
+
746
+ //combine address
747
+ $address = $order->Address1;
748
+ if(!empty($order->Address2))
749
+ $address .= "\n" . $order->Address2;
750
+
751
+ //bill to
752
+ $billTo = new stdClass();
753
+ $billTo->firstName = $order->FirstName;
754
+ $billTo->lastName = $order->LastName;
755
+ $billTo->street1 = $address;
756
+ $billTo->city = $order->billing->city;
757
+ $billTo->state = $order->billing->state;
758
+ $billTo->postalCode = $order->billing->zip;
759
+ $billTo->country = $order->billing->country;
760
+ $billTo->email = $order->Email;
761
+ $billTo->ipAddress = $_SERVER['REMOTE_ADDR'];
762
+ $request->billTo = $billTo;
763
+
764
+ //card
765
+ $card = new stdClass();
766
+ $card->cardType = $this->getCardType($order->cardtype);
767
+ $card->accountNumber = $order->accountnumber;
768
+ $card->expirationMonth = $order->expirationmonth;
769
+ $card->expirationYear = $order->expirationyear;
770
+ $card->cvNumber = $order->CVV2;
771
+ $request->card = $card;
772
+
773
+ $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
774
+ $reply = $soapClient->runTransaction($request);
775
+
776
+ if($reply->reasonCode == "100")
777
+ {
778
+ //success
779
+ return true;
780
+ }
781
+ else
782
+ {
783
+ //error
784
+ $order->errorcode = $reply->reasonCode;
785
+ $order->error = $this->getErrorFromCode($reply->reasonCode);
786
+ $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
787
+ return false;
788
+ }
789
+ }
790
+
791
+ function cancel(&$order)
792
+ {
793
+ //require a subscription id
794
+ if(empty($order->subscription_transaction_id))
795
+ return false;
796
+
797
+ //get wsdl
798
+ $wsdl_url = $this->getWSDL($order);
799
+
800
+ //to store our request
801
+ $request = new stdClass();
802
+
803
+ //which service?
804
+ $paySubscriptionDeleteService = new stdClass();
805
+ $paySubscriptionDeleteService ->run = "true";
806
+ $request->paySubscriptionDeleteService = $paySubscriptionDeleteService ;
807
+
808
+ //which order
809
+ $recurringSubscriptionInfo = new stdClass();
810
+ $recurringSubscriptionInfo->subscriptionID = $order->subscription_transaction_id;
811
+ $request->recurringSubscriptionInfo = $recurringSubscriptionInfo;
812
+
813
+ //merchant id and order code
814
+ $request->merchantID = pmpro_getOption("cybersource_merchantid");
815
+ $request->merchantReferenceCode = $order->code;
816
+
817
+ $soapClient = new CyberSourceSoapClient($wsdl_url, array("merchantID"=>pmpro_getOption("cybersource_merchantid"), "transactionKey"=>pmpro_getOption("cybersource_securitykey")));
818
+ $reply = $soapClient->runTransaction($request);
819
+
820
+ if($reply->reasonCode == "100")
821
+ {
822
+ //success
823
+ $order->updateStatus("cancelled");
824
+ return true;
825
+ }
826
+ else
827
+ {
828
+ //error
829
+ $order->errorcode = $reply->reasonCode;
830
+ $order->error = $this->getErrorFromCode($reply->reasonCode);
831
+ $order->shorterror = $this->getErrorFromCode($reply->reasonCode);
832
+ return false;
833
+ }
834
+ }
835
+
836
+ function getErrorFromCode($code)
837
+ {
838
+ $error_messages = array(
839
+ "100" => "Successful transaction.",
840
+ "101" => "The request is missing one or more required fields.",
841
+ "102" => "One or more fields in the request contains invalid data. Check that your billing address is valid.",
842
+ "104" => "Duplicate order detected.",
843
+ "110" => "Only partial amount was approved.",
844
+ "150" => "Error: General system failure.",
845
+ "151" => "Error: The request was received but there was a server timeout.",
846
+ "152" => "Error: The request was received, but a service did not finish running in time. ",
847
+ "200" => "Address Verification Service (AVS) failure.",
848
+ "201" => "Authorization failed.",
849
+ "202" => "Expired card or invalid expiration date.",
850
+ "203" => "The card was declined.",
851
+ "204" => "Insufficient funds in the account.",
852
+ "205" => "Stolen or lost card.",
853
+ "207" => "Issuing bank unavailable.",
854
+ "208" => "Inactive card or card not authorized for card-not-present transactions.",
855
+ "209" => "American Express Card Identification Digits (CID) did not match.",
856
+ "210" => "The card has reached the credit limit. ",
857
+ "211" => "Invalid card verification number.",
858
+ "221" => "The customer matched an entry on the processors negative file. ",
859
+ "230" => "Card verification (CV) check failed.",
860
+ "231" => "Invalid account number.",
861
+ "232" => "The card type is not accepted by the payment processor.",
862
+ "233" => "General decline by the processor.",
863
+ "234" => "There is a problem with your CyberSource merchant configuration.",
864
+ "235" => "The requested amount exceeds the originally authorized amount.",
865
+ "236" => "Processor failure.",
866
+ "237" => "The authorization has already been reversed.",
867
+ "238" => "The authorization has already been captured.",
868
+ "239" => "The requested transaction amount must match the previous transaction amount.",
869
+ "240" => "The card type sent is invalid or does not correlate with the credit card number.",
870
+ "241" => "The referenced request id is invalid for all follow-on transactions.",
871
+ "242" => "The request ID is invalid.",
872
+ "243" => "The transaction has already been settled or reversed.",
873
+ "246" => "The capture or credit is not voidable because the capture or credit information has already been submitted to your processor. Or, you requested a void for a type of transaction that cannot be voided.",
874
+ "247" => "You requested a credit for a capture that was previously voided.",
875
+ "250" => "Error: The request was received, but there was a timeout at the payment processor.",
876
+ "520" => "Smart Authorization failed."
877
+ );
878
+
879
+ if(isset($error_messages[$code]))
880
+ return $error_messages[$code];
881
+ else
882
+ return "Unknown error.";
883
+ }
884
+ }
classes/gateways/class.pmprogateway_payflowpro.php CHANGED
@@ -1,53 +1,53 @@
1
  <?php
2
  //include pmprogateway
3
  require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
-
5
  //load classes init method
6
  add_action('init', array('PMProGateway_payflowpro', 'init'));
7
-
8
  class PMProGateway_payflowpro extends PMProGateway
9
  {
10
  function PMProGateway_payflowpro($gateway = NULL)
11
  {
12
  $this->gateway = $gateway;
13
  return $this->gateway;
14
- }
15
-
16
  /**
17
  * Run on WP init
18
- *
19
  * @since 1.8
20
  */
21
  static function init()
22
- {
23
  //make sure Payflow Pro/PayPal Pro is a gateway option
24
  add_filter('pmpro_gateways', array('PMProGateway_payflowpro', 'pmpro_gateways'));
25
-
26
  //add fields to payment settings
27
  add_filter('pmpro_payment_options', array('PMProGateway_payflowpro', 'pmpro_payment_options'));
28
- add_filter('pmpro_payment_option_fields', array('PMProGateway_payflowpro', 'pmpro_payment_option_fields'), 10, 2);
29
  }
30
-
31
  /**
32
  * Make sure this gateway is in the gateways list
33
- *
34
  * @since 1.8
35
  */
36
  static function pmpro_gateways($gateways)
37
  {
38
  if(empty($gateways['payflowpro']))
39
  $gateways['payflowpro'] = __('Payflow Pro/PayPal Pro', 'pmpro');
40
-
41
  return $gateways;
42
  }
43
-
44
  /**
45
  * Get a list of payment options that the this gateway needs/supports.
46
- *
47
  * @since 1.8
48
  */
49
  static function getGatewayOptions()
50
- {
51
  $options = array(
52
  'sslseal',
53
  'nuclear_HTTPS',
@@ -62,29 +62,29 @@
62
  'tax_rate',
63
  'accepted_credit_cards'
64
  );
65
-
66
  return $options;
67
  }
68
-
69
  /**
70
  * Set payment options for payment settings page.
71
- *
72
  * @since 1.8
73
  */
74
  static function pmpro_payment_options($options)
75
- {
76
  //get stripe options
77
  $payflowpro_options = PMProGateway_payflowpro::getGatewayOptions();
78
-
79
  //merge with others.
80
  $options = array_merge($payflowpro_options, $options);
81
-
82
  return $options;
83
  }
84
-
85
  /**
86
  * Display fields for this gateway's options.
87
- *
88
  * @since 1.8
89
  */
90
  static function pmpro_payment_option_fields($values, $gateway)
@@ -96,7 +96,7 @@
96
  </td>
97
  </tr>
98
  <tr class="gateway gateway_payflowpro" <?php if($gateway != "payflowpro") { ?>style="display: none;"<?php } ?>>
99
- <th scope="row" valign="top">
100
  <label for="payflow_partner"><?php _e('Partner', 'pmpro');?>:</label>
101
  </th>
102
  <td>
@@ -104,7 +104,7 @@
104
  </td>
105
  </tr>
106
  <tr class="gateway gateway_payflowpro" <?php if($gateway != "payflowpro") { ?>style="display: none;"<?php } ?>>
107
- <th scope="row" valign="top">
108
  <label for="payflow_vendor"><?php _e('Vendor', 'pmpro');?>:</label>
109
  </th>
110
  <td>
@@ -112,7 +112,7 @@
112
  </td>
113
  </tr>
114
  <tr class="gateway gateway_payflowpro" <?php if($gateway != "payflowpro") { ?>style="display: none;"<?php } ?>>
115
- <th scope="row" valign="top">
116
  <label for="payflow_user"><?php _e('User', 'pmpro');?>:</label>
117
  </th>
118
  <td>
@@ -120,7 +120,7 @@
120
  </td>
121
  </tr>
122
  <tr class="gateway gateway_payflowpro" <?php if($gateway != "payflowpro") { ?>style="display: none;"<?php } ?>>
123
- <th scope="row" valign="top">
124
  <label for="payflow_pwd"><?php _e('Password', 'pmpro');?>:</label>
125
  </th>
126
  <td>
@@ -132,7 +132,7 @@
132
  <label><?php _e('IPN Handler', 'pmpro');?>:</label>
133
  </th>
134
  <td>
135
- <p><?php
136
  $addon_url = "http://www.paidmembershipspro.com/add-ons/plugins-on-github/payflow-recurring-orders-addon/";
137
  printf(__('Payflow does not use IPN. To sync recurring subscriptions, please see <a target="_blank" href="%s">this addon</a>.', 'pmpro'), $addon_url);?>
138
  </p>
@@ -140,20 +140,20 @@
140
  </tr>
141
  <?php
142
  }
143
-
144
  /**
145
  * Process checkout.
146
- *
147
  */
148
  function process(&$order)
149
  {
150
  if(floatval($order->InitialPayment) == 0)
151
  {
152
  //auth first, then process
153
- $authorization_id = $this->authorize($order);
154
  if($authorization_id)
155
  {
156
- $this->void($order, $authorization_id);
157
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
158
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
159
  return $this->subscribe($order);
@@ -166,21 +166,21 @@
166
  }
167
  }
168
  else
169
- {
170
  //charge first payment
171
  if($this->charge($order))
172
- {
173
  //setup recurring billing
174
  if(pmpro_isLevelRecurring($order->membership_level))
175
  {
176
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
177
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
178
  if($this->subscribe($order))
179
- {
180
  return true;
181
  }
182
  else
183
- {
184
  if($this->void($order, $order->payment_transaction_id))
185
  {
186
  if(empty($order->error))
@@ -190,195 +190,195 @@
190
  {
191
  if(empty($order->error))
192
  $order->error = __("Unknown error: Payment failed.", "pmpro");
193
-
194
  $order->error .= " " . __("A partial payment was made that we could not refund. Please contact the site owner immediately to correct this.", "pmpro");
195
  }
196
-
197
- return false;
198
  }
199
  }
200
  else
201
  {
202
- //only a one time charge
203
- $order->status = "success"; //saved on checkout page
204
  $order->saveOrder();
205
  return true;
206
  }
207
- }
208
- }
209
  }
210
-
211
  function authorize(&$order)
212
  {
213
  if(empty($order->code))
214
  $order->code = $order->getRandomCode();
215
-
216
  //paypal profile stuff
217
  $nvpStr = "";
218
-
219
- $nvpStr .="&AMT=1.00";
220
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
221
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
222
-
223
  $nvpStr .= "&CUSTIP=" . $_SERVER['REMOTE_ADDR'] . "&INVNUM=" . $order->code;
224
-
225
  //credit card fields
226
  if($order->cardtype == "American Express")
227
  $cardtype = "Amex";
228
  else
229
  $cardtype = $order->cardtype;
230
-
231
  if(!empty($order->accountnumber))
232
  $nvpStr .= "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->expirationmonth . substr($order->expirationyear, 2, 2) . "&CVV2=" . $order->CVV2;
233
-
234
  //billing address, etc
235
  if(!empty($order->Address1))
236
  {
237
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
238
-
239
  if($order->Address2)
240
  $nvpStr .= " " . $order->Address2;
241
-
242
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
243
  }
244
 
245
  //for debugging, let's attach this to the class object
246
  $this->nvpStr = $nvpStr;
247
-
248
  $this->httpParsedResponseAr = $this->PPHttpPost('A', $nvpStr);
249
-
250
  if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
251
  $order->authorization_id = $this->httpParsedResponseAr['PNREF'];
252
- $order->updateStatus("authorized");
253
- return $order->authorization_id;
254
- } else {
255
  $order->status = "error";
256
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
257
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
258
  $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
259
- return false;
260
- }
261
  }
262
-
263
  function void(&$order, $authorization_id = null)
264
  {
265
  if(empty($authorization_id))
266
  return false;
267
-
268
  //paypal profile stuff
269
  $nvpStr="&ORIGID=" . $authorization_id;
270
-
271
- $this->httpParsedResponseAr = $this->PPHttpPost('V', $nvpStr);
272
-
273
- if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
274
- return true;
275
- } else {
276
  $order->status = "error";
277
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
278
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
279
  $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
280
- return false;
281
- }
282
- }
283
-
284
  function charge(&$order)
285
  {
286
  global $pmpro_currency;
287
-
288
  if(empty($order->code))
289
  $order->code = $order->getRandomCode();
290
-
291
  //taxes on the amount
292
  $amount = $order->InitialPayment;
293
- $amount_tax = $order->getTaxForPrice($amount);
294
  $order->subtotal = $amount;
295
  $amount = round((float)$amount + (float)$amount_tax, 2);
296
-
297
  //paypal profile stuff
298
- $nvpStr = "";
299
- $nvpStr .="&AMT=" . $amount . "&TAXAMT=" . $amount_tax . "&CURRENCY=" . $pmpro_currency;
300
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
301
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
302
-
303
- $nvpStr .= "&CUSTIP=" . $_SERVER['REMOTE_ADDR'] . "&INVNUM=" . $order->code;
304
-
305
  if(!empty($order->accountnumber))
306
  $nvpStr .= "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->expirationmonth . substr($order->expirationyear, 2, 2) . "&CVV2=" . $order->CVV2;
307
-
308
  //billing address, etc
309
  if($order->Address1)
310
  {
311
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
312
-
313
  if($order->Address2)
314
  $nvpStr .= " " . $order->Address2;
315
-
316
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
317
  }
318
 
319
- $this->nvpStr = $nvpStr;
320
  $this->httpParsedResponseAr = $this->PPHttpPost('S', $nvpStr);
321
-
322
  if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
323
  $order->payment_transaction_id = $this->httpParsedResponseAr['PNREF'];
324
- $order->updateStatus("success");
325
- return true;
326
- } else {
327
  $order->status = "error";
328
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
329
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
330
- $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
331
- return false;
332
- }
333
  }
334
-
335
  function subscribe(&$order)
336
  {
337
  global $pmpro_currency;
338
-
339
  if(empty($order->code))
340
- $order->code = $order->getRandomCode();
341
-
342
  //filter order before subscription. use with care.
343
  $order = apply_filters("pmpro_subscribe_order", $order, $this);
344
-
345
  //taxes on the amount
346
  $amount = $order->PaymentAmount;
347
- $amount_tax = $order->getTaxForPrice($amount);
348
  $amount = round((float)$amount + (float)$amount_tax, 2);
349
-
350
  if($order->BillingPeriod == "Week")
351
  $payperiod = "WEEK";
352
  elseif($order->BillingPeriod == "Month")
353
  $payperiod = "MONT";
354
  elseif($order->BillingPeriod == "Year")
355
  $payperiod = "YEAR";
356
-
357
  //paypal profile stuff
358
- $nvpStr = "&ACTION=A";
359
  $nvpStr .="&AMT=" . $amount . "&TAXAMT=" . $amount_tax . "&CURRENCY=" . $pmpro_currency;
360
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
361
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
362
-
363
  $nvpStr .= "&PROFILENAME=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
364
-
365
  $nvpStr .= "&PAYPERIOD=" . $payperiod;
366
-
367
- $nvpStr .= "&CUSTIP=" . $_SERVER['REMOTE_ADDR']; // . "&INVNUM=" . $order->code;
368
 
369
- //if billing cycles are defined
 
 
370
  if(!empty($order->TotalBillingCycles))
371
  $nvpStr .= "&TERM=" . $order->TotalBillingCycles;
372
  else
373
  $nvpStr .= "&TERM=0";
374
-
375
  if(!empty($order->accountnumber))
376
  $nvpStr .= "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->expirationmonth . substr($order->expirationyear, 2, 2) . "&CVV2=" . $order->CVV2;
377
-
378
  /*
379
  Let's figure out the start date. There are two parts.
380
  1. We need to add the billing period to the start date to account for the initial payment.
381
- 2. We can allow for free trials by further delaying the start date of the subscription.
382
  */
383
  if($order->BillingPeriod == "Year")
384
  $trial_period_days = $order->BillingFrequency * 365; //annual
@@ -388,18 +388,18 @@
388
  $trial_period_days = $order->BillingFrequency * 7; //weekly
389
  else
390
  $trial_period_days = $order->BillingFrequency * 30; //assume monthly
391
-
392
  //convert to a profile start date
393
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
394
-
395
  //filter the start date
396
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
397
 
398
  //convert back to days
399
  $trial_period_days = ceil(abs(strtotime(date("Y-m-d"), current_time('timestamp')) - strtotime($order->ProfileStartDate, current_time("timestamp"))) / 86400);
400
 
401
  //now add the actual trial set by the site
402
- if(!empty($order->TrialBillingCycles))
403
  {
404
  $trialOccurrences = (int)$order->TrialBillingCycles;
405
  if($order->BillingPeriod == "Year")
@@ -409,114 +409,114 @@
409
  elseif($order->BillingPeriod == "Week")
410
  $trial_period_days = $trial_period_days + (7 * $order->BillingFrequency * $trialOccurrences); //weekly
411
  else
412
- $trial_period_days = $trial_period_days + (30 * $order->BillingFrequency * $trialOccurrences); //assume monthly
413
- }
414
-
415
  //convert back into a date
416
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
417
-
418
  //start date
419
  $nvpStr .= "&START=" . date("mdY", strtotime($order->ProfileStartDate));
420
-
421
  if(!empty($order->accountnumber))
422
  $nvpStr .= "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->expirationmonth . substr($order->expirationyear, 2, 2) . "&CVV2=" . $order->CVV2;
423
-
424
  //billing address, etc
425
  if($order->Address1)
426
  {
427
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
428
-
429
  if($order->Address2)
430
  $nvpStr .= " " . $order->Address2;
431
-
432
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
433
  }
434
 
435
- $this->nvpStr = $nvpStr;
436
  $this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
437
-
438
  if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
439
  $order->subscription_transaction_id = $this->httpParsedResponseAr['PROFILEID'];
440
- $order->status = "success";
441
- return true;
442
- } else {
443
  $order->status = "error";
444
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
445
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
446
- $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
447
- return false;
448
- }
449
- }
450
-
451
  function update(&$order)
452
  {
453
  $order->getMembershipLevel();
454
-
455
  //paypal profile stuff
456
- $nvpStr = "&ORIGPROFILEID=" . $order->subscription_transaction_id . "&ACTION=M";
457
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
458
-
459
  $nvpStr .= "&PROFILENAME=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
460
-
461
- $nvpStr .= "&CUSTIP=" . $_SERVER['REMOTE_ADDR']; // . "&INVNUM=" . $order->code;
462
-
463
  if(!empty($order->accountnumber))
464
  $nvpStr .= "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->expirationmonth . substr($order->expirationyear, 2, 2) . "&CVV2=" . $order->CVV2;
465
-
466
  //billing address, etc
467
  if($order->Address1)
468
  {
469
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
470
-
471
  if($order->Address2)
472
  $nvpStr .= " " . $order->Address2;
473
-
474
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
475
  }
476
 
477
  $this->nvpStr = $nvpStr;
478
  $this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
479
-
480
  if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
481
  $order->subscription_transaction_id = $this->httpParsedResponseAr['PROFILEID'];
482
- $order->updateStatus("success");
483
- return true;
484
- } else {
485
  $order->status = "error";
486
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
487
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
488
- $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
489
- return false;
490
- }
491
  }
492
-
493
  function cancel(&$order)
494
  {
495
  //require a subscription id
496
  if(empty($order->subscription_transaction_id))
497
  return false;
498
-
499
  //paypal profile stuff
500
- $nvpStr = "&ORIGPROFILEID=" . $order->subscription_transaction_id . "&ACTION=C";
501
-
502
  $this->nvpStr = $nvpStr;
503
  $this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
504
-
505
- if("0" == strtoupper($this->httpParsedResponseAr["RESULT"]))
506
- {
507
- $order->updateStatus("cancelled");
508
- return true;
509
  }
510
  else
511
- {
512
  $order->status = "error";
513
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
514
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
515
- $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
516
  return false;
517
  }
518
- }
519
-
520
  /**
521
  * PAYPAL Function
522
  * Send HTTP POST Request
@@ -527,8 +527,8 @@
527
  */
528
  function PPHttpPost($methodName_, $nvpStr_) {
529
  global $gateway_environment;
530
- $environment = $gateway_environment;
531
-
532
  $PARTNER = pmpro_getOption("payflow_partner");
533
  $VENDOR = pmpro_getOption("payflow_vendor");
534
  $USER = pmpro_getOption("payflow_user");
@@ -536,40 +536,40 @@
536
  $API_Endpoint = "https://payflowpro.paypal.com";
537
  if("sandbox" === $environment || "beta-sandbox" === $environment) {
538
  $API_Endpoint = "https://pilot-payflowpro.paypal.com";
539
- }
540
-
541
  $version = urlencode('4');
542
-
543
  // setting the curl parameters.
544
  $ch = curl_init();
545
  curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
546
  curl_setopt($ch, CURLOPT_VERBOSE, 1);
547
-
548
  // turning off the server and peer verification(TrustManager Concept).
549
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
550
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
551
-
552
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
553
  curl_setopt($ch, CURLOPT_POST, 1);
554
-
555
  // NVPRequest for submitting to server
556
  $nvpreq = "TRXTYPE=" . $methodName_ . "&TENDER=C&PARTNER=" . $PARTNER . "&VENDOR=" . $VENDOR . "&USER=" . $USER . "&PWD=" . $PWD . "&VERBOSITY=medium" . "&BUTTONSOURCE=" . urlencode(PAYPAL_BN_CODE) . $nvpStr_;
557
-
558
  //$nvpreq = "TRXTYPE=" . urlencode($methodName_) . "&TENDER=C&PARTNER=" . urlencode($PARTNER) . "&VENDOR=" . urlencode($VENDOR) . "&USER=" . urlencode($USER) . "&PWD=" . urlencode($PWD) . "&VERBOSITY=medium" . $nvpStr_;
559
-
560
  // setting the nvpreq as POST FIELD to curl
561
  curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
562
-
563
  // getting response from server
564
  $httpResponse = curl_exec($ch);
565
-
566
  if(empty($httpResponse)) {
567
  exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
568
  }
569
-
570
  // Extract the RefundTransaction response details
571
  $httpResponseAr = explode("&", $httpResponse);
572
-
573
  $httpParsedResponseAr = array();
574
  foreach ($httpResponseAr as $i => $value) {
575
  $tmpAr = explode("=", $value);
@@ -577,11 +577,11 @@
577
  $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
578
  }
579
  }
580
-
581
  if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('RESULT', $httpParsedResponseAr)) {
582
  exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
583
  }
584
-
585
  return $httpParsedResponseAr;
586
  }
587
  }
1
  <?php
2
  //include pmprogateway
3
  require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
+
5
  //load classes init method
6
  add_action('init', array('PMProGateway_payflowpro', 'init'));
7
+
8
  class PMProGateway_payflowpro extends PMProGateway
9
  {
10
  function PMProGateway_payflowpro($gateway = NULL)
11
  {
12
  $this->gateway = $gateway;
13
  return $this->gateway;
14
+ }
15
+
16
  /**
17
  * Run on WP init
18
+ *
19
  * @since 1.8
20
  */
21
  static function init()
22
+ {
23
  //make sure Payflow Pro/PayPal Pro is a gateway option
24
  add_filter('pmpro_gateways', array('PMProGateway_payflowpro', 'pmpro_gateways'));
25
+
26
  //add fields to payment settings
27
  add_filter('pmpro_payment_options', array('PMProGateway_payflowpro', 'pmpro_payment_options'));
28
+ add_filter('pmpro_payment_option_fields', array('PMProGateway_payflowpro', 'pmpro_payment_option_fields'), 10, 2);
29
  }
30
+
31
  /**
32
  * Make sure this gateway is in the gateways list
33
+ *
34
  * @since 1.8
35
  */
36
  static function pmpro_gateways($gateways)
37
  {
38
  if(empty($gateways['payflowpro']))
39
  $gateways['payflowpro'] = __('Payflow Pro/PayPal Pro', 'pmpro');
40
+
41
  return $gateways;
42
  }
43
+
44
  /**
45
  * Get a list of payment options that the this gateway needs/supports.
46
+ *
47
  * @since 1.8
48
  */
49
  static function getGatewayOptions()
50
+ {
51
  $options = array(
52
  'sslseal',
53
  'nuclear_HTTPS',
62
  'tax_rate',
63
  'accepted_credit_cards'
64
  );
65
+
66
  return $options;
67
  }
68
+
69
  /**
70
  * Set payment options for payment settings page.
71
+ *
72
  * @since 1.8
73
  */
74
  static function pmpro_payment_options($options)
75
+ {
76
  //get stripe options
77
  $payflowpro_options = PMProGateway_payflowpro::getGatewayOptions();
78
+
79
  //merge with others.
80
  $options = array_merge($payflowpro_options, $options);
81
+
82
  return $options;
83
  }
84
+
85
  /**
86
  * Display fields for this gateway's options.
87
+ *
88
  * @since 1.8
89
  */
90
  static function pmpro_payment_option_fields($values, $gateway)
96
  </td>
97
  </tr>
98
  <tr class="gateway gateway_payflowpro" <?php if($gateway != "payflowpro") { ?>style="display: none;"<?php } ?>>
99
+ <th scope="row" valign="top">
100
  <label for="payflow_partner"><?php _e('Partner', 'pmpro');?>:</label>
101
  </th>
102
  <td>
104
  </td>
105
  </tr>
106
  <tr class="gateway gateway_payflowpro" <?php if($gateway != "payflowpro") { ?>style="display: none;"<?php } ?>>
107
+ <th scope="row" valign="top">
108
  <label for="payflow_vendor"><?php _e('Vendor', 'pmpro');?>:</label>
109
  </th>
110
  <td>
112
  </td>
113
  </tr>
114
  <tr class="gateway gateway_payflowpro" <?php if($gateway != "payflowpro") { ?>style="display: none;"<?php } ?>>
115
+ <th scope="row" valign="top">
116
  <label for="payflow_user"><?php _e('User', 'pmpro');?>:</label>
117
  </th>
118
  <td>
120
  </td>
121
  </tr>
122
  <tr class="gateway gateway_payflowpro" <?php if($gateway != "payflowpro") { ?>style="display: none;"<?php } ?>>
123
+ <th scope="row" valign="top">
124
  <label for="payflow_pwd"><?php _e('Password', 'pmpro');?>:</label>
125
  </th>
126
  <td>
132
  <label><?php _e('IPN Handler', 'pmpro');?>:</label>
133
  </th>
134
  <td>
135
+ <p><?php
136
  $addon_url = "http://www.paidmembershipspro.com/add-ons/plugins-on-github/payflow-recurring-orders-addon/";
137
  printf(__('Payflow does not use IPN. To sync recurring subscriptions, please see <a target="_blank" href="%s">this addon</a>.', 'pmpro'), $addon_url);?>
138
  </p>
140
  </tr>
141
  <?php
142
  }
143
+
144
  /**
145
  * Process checkout.
146
+ *
147
  */
148
  function process(&$order)
149
  {
150
  if(floatval($order->InitialPayment) == 0)
151
  {
152
  //auth first, then process
153
+ $authorization_id = $this->authorize($order);
154
  if($authorization_id)
155
  {
156
+ $this->void($order, $authorization_id);
157
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
158
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
159
  return $this->subscribe($order);
166
  }
167
  }
168
  else
169
+ {
170
  //charge first payment
171
  if($this->charge($order))
172
+ {
173
  //setup recurring billing
174
  if(pmpro_isLevelRecurring($order->membership_level))
175
  {
176
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
177
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
178
  if($this->subscribe($order))
179
+ {
180
  return true;
181
  }
182
  else
183
+ {
184
  if($this->void($order, $order->payment_transaction_id))
185
  {
186
  if(empty($order->error))
190
  {
191
  if(empty($order->error))
192
  $order->error = __("Unknown error: Payment failed.", "pmpro");
193
+
194
  $order->error .= " " . __("A partial payment was made that we could not refund. Please contact the site owner immediately to correct this.", "pmpro");
195
  }
196
+
197
+ return false;
198
  }
199
  }
200
  else
201
  {
202
+ //only a one time charge
203
+ $order->status = "success"; //saved on checkout page
204
  $order->saveOrder();
205
  return true;
206
  }
207
+ }
208
+ }
209
  }
210
+
211
  function authorize(&$order)
212
  {
213
  if(empty($order->code))
214
  $order->code = $order->getRandomCode();
215
+
216
  //paypal profile stuff
217
  $nvpStr = "";
218
+
219
+ $nvpStr .="&AMT=1.00";
220
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
221
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
222
+
223
  $nvpStr .= "&CUSTIP=" . $_SERVER['REMOTE_ADDR'] . "&INVNUM=" . $order->code;
224
+
225
  //credit card fields
226
  if($order->cardtype == "American Express")
227
  $cardtype = "Amex";
228
  else
229
  $cardtype = $order->cardtype;
230
+
231
  if(!empty($order->accountnumber))
232
  $nvpStr .= "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->expirationmonth . substr($order->expirationyear, 2, 2) . "&CVV2=" . $order->CVV2;
233
+
234
  //billing address, etc
235
  if(!empty($order->Address1))
236
  {
237
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
238
+
239
  if($order->Address2)
240
  $nvpStr .= " " . $order->Address2;
241
+
242
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
243
  }
244
 
245
  //for debugging, let's attach this to the class object
246
  $this->nvpStr = $nvpStr;
247
+
248
  $this->httpParsedResponseAr = $this->PPHttpPost('A', $nvpStr);
249
+
250
  if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
251
  $order->authorization_id = $this->httpParsedResponseAr['PNREF'];
252
+ $order->updateStatus("authorized");
253
+ return $order->authorization_id;
254
+ } else {
255
  $order->status = "error";
256
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
257
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
258
  $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
259
+ return false;
260
+ }
261
  }
262
+
263
  function void(&$order, $authorization_id = null)
264
  {
265
  if(empty($authorization_id))
266
  return false;
267
+
268
  //paypal profile stuff
269
  $nvpStr="&ORIGID=" . $authorization_id;
270
+
271
+ $this->httpParsedResponseAr = $this->PPHttpPost('V', $nvpStr);
272
+
273
+ if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
274
+ return true;
275
+ } else {
276
  $order->status = "error";
277
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
278
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
279
  $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
280
+ return false;
281
+ }
282
+ }
283
+
284
  function charge(&$order)
285
  {
286
  global $pmpro_currency;
287
+
288
  if(empty($order->code))
289
  $order->code = $order->getRandomCode();
290
+
291
  //taxes on the amount
292
  $amount = $order->InitialPayment;
293
+ $amount_tax = $order->getTaxForPrice($amount);
294
  $order->subtotal = $amount;
295
  $amount = round((float)$amount + (float)$amount_tax, 2);
296
+
297
  //paypal profile stuff
298
+ $nvpStr = "";
299
+ $nvpStr .="&AMT=" . $amount . "&TAXAMT=" . $amount_tax . "&CURRENCY=" . $pmpro_currency;
300
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
301
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
302
+
303
+ $nvpStr .= "&CUSTIP=" . $_SERVER['REMOTE_ADDR'] . "&INVNUM=" . $order->code;
304
+
305
  if(!empty($order->accountnumber))
306
  $nvpStr .= "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->expirationmonth . substr($order->expirationyear, 2, 2) . "&CVV2=" . $order->CVV2;
307
+
308
  //billing address, etc
309
  if($order->Address1)
310
  {
311
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
312
+
313
  if($order->Address2)
314
  $nvpStr .= " " . $order->Address2;
315
+
316
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
317
  }
318
 
319
+ $this->nvpStr = $nvpStr;
320
  $this->httpParsedResponseAr = $this->PPHttpPost('S', $nvpStr);
321
+
322
  if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
323
  $order->payment_transaction_id = $this->httpParsedResponseAr['PNREF'];
324
+ $order->updateStatus("success");
325
+ return true;
326
+ } else {
327
  $order->status = "error";
328
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
329
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
330
+ $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
331
+ return false;
332
+ }
333
  }
334
+
335
  function subscribe(&$order)
336
  {
337
  global $pmpro_currency;
338
+
339
  if(empty($order->code))
340
+ $order->code = $order->getRandomCode();
341
+
342
  //filter order before subscription. use with care.
343
  $order = apply_filters("pmpro_subscribe_order", $order, $this);
344
+
345
  //taxes on the amount
346
  $amount = $order->PaymentAmount;
347
+ $amount_tax = $order->getTaxForPrice($amount);
348
  $amount = round((float)$amount + (float)$amount_tax, 2);
349
+
350
  if($order->BillingPeriod == "Week")
351
  $payperiod = "WEEK";
352
  elseif($order->BillingPeriod == "Month")
353
  $payperiod = "MONT";
354
  elseif($order->BillingPeriod == "Year")
355
  $payperiod = "YEAR";
356
+
357
  //paypal profile stuff
358
+ $nvpStr = "&ACTION=A";
359
  $nvpStr .="&AMT=" . $amount . "&TAXAMT=" . $amount_tax . "&CURRENCY=" . $pmpro_currency;
360
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
361
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
362
+
363
  $nvpStr .= "&PROFILENAME=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
364
+
365
  $nvpStr .= "&PAYPERIOD=" . $payperiod;
 
 
366
 
367
+ $nvpStr .= "&CUSTIP=" . $_SERVER['REMOTE_ADDR']; // . "&INVNUM=" . $order->code;
368
+
369
+ //if billing cycles are defined
370
  if(!empty($order->TotalBillingCycles))
371
  $nvpStr .= "&TERM=" . $order->TotalBillingCycles;
372
  else
373
  $nvpStr .= "&TERM=0";
374
+
375
  if(!empty($order->accountnumber))
376
  $nvpStr .= "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->expirationmonth . substr($order->expirationyear, 2, 2) . "&CVV2=" . $order->CVV2;
377
+
378
  /*
379
  Let's figure out the start date. There are two parts.
380
  1. We need to add the billing period to the start date to account for the initial payment.
381
+ 2. We can allow for free trials by further delaying the start date of the subscription.
382
  */
383
  if($order->BillingPeriod == "Year")
384
  $trial_period_days = $order->BillingFrequency * 365; //annual
388
  $trial_period_days = $order->BillingFrequency * 7; //weekly
389
  else
390
  $trial_period_days = $order->BillingFrequency * 30; //assume monthly
391
+
392
  //convert to a profile start date
393
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
394
+
395
  //filter the start date
396
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
397
 
398
  //convert back to days
399
  $trial_period_days = ceil(abs(strtotime(date("Y-m-d"), current_time('timestamp')) - strtotime($order->ProfileStartDate, current_time("timestamp"))) / 86400);
400
 
401
  //now add the actual trial set by the site
402
+ if(!empty($order->TrialBillingCycles))
403
  {
404
  $trialOccurrences = (int)$order->TrialBillingCycles;
405
  if($order->BillingPeriod == "Year")
409
  elseif($order->BillingPeriod == "Week")
410
  $trial_period_days = $trial_period_days + (7 * $order->BillingFrequency * $trialOccurrences); //weekly
411
  else
412
+ $trial_period_days = $trial_period_days + (30 * $order->BillingFrequency * $trialOccurrences); //assume monthly
413
+ }
414
+
415
  //convert back into a date
416
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
417
+
418
  //start date
419
  $nvpStr .= "&START=" . date("mdY", strtotime($order->ProfileStartDate));
420
+
421
  if(!empty($order->accountnumber))
422
  $nvpStr .= "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->expirationmonth . substr($order->expirationyear, 2, 2) . "&CVV2=" . $order->CVV2;
423
+
424
  //billing address, etc
425
  if($order->Address1)
426
  {
427
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
428
+
429
  if($order->Address2)
430
  $nvpStr .= " " . $order->Address2;
431
+
432
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
433
  }
434
 
435
+ $this->nvpStr = $nvpStr;
436
  $this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
437
+
438
  if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
439
  $order->subscription_transaction_id = $this->httpParsedResponseAr['PROFILEID'];
440
+ $order->status = "success";
441
+ return true;
442
+ } else {
443
  $order->status = "error";
444
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
445
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
446
+ $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
447
+ return false;
448
+ }
449
+ }
450
+
451
  function update(&$order)
452
  {
453
  $order->getMembershipLevel();
454
+
455
  //paypal profile stuff
456
+ $nvpStr = "&ORIGPROFILEID=" . $order->subscription_transaction_id . "&ACTION=M";
457
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
458
+
459
  $nvpStr .= "&PROFILENAME=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
460
+
461
+ $nvpStr .= "&CUSTIP=" . $_SERVER['REMOTE_ADDR']; // . "&INVNUM=" . $order->code;
462
+
463
  if(!empty($order->accountnumber))
464
  $nvpStr .= "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->expirationmonth . substr($order->expirationyear, 2, 2) . "&CVV2=" . $order->CVV2;
465
+
466
  //billing address, etc
467
  if($order->Address1)
468
  {
469
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
470
+
471
  if($order->Address2)
472
  $nvpStr .= " " . $order->Address2;
473
+
474
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&BILLTOCOUNTRY=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&PHONENUM=" . $order->billing->phone;
475
  }
476
 
477
  $this->nvpStr = $nvpStr;
478
  $this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
479
+
480
  if("0" == strtoupper($this->httpParsedResponseAr["RESULT"])) {
481
  $order->subscription_transaction_id = $this->httpParsedResponseAr['PROFILEID'];
482
+ $order->updateStatus("success");
483
+ return true;
484
+ } else {
485
  $order->status = "error";
486
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
487
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
488
+ $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
489
+ return false;
490
+ }
491
  }
492
+
493
  function cancel(&$order)
494
  {
495
  //require a subscription id
496
  if(empty($order->subscription_transaction_id))
497
  return false;
498
+
499
  //paypal profile stuff
500
+ $nvpStr = "&ORIGPROFILEID=" . $order->subscription_transaction_id . "&ACTION=C";
501
+
502
  $this->nvpStr = $nvpStr;
503
  $this->httpParsedResponseAr = $this->PPHttpPost('R', $nvpStr);
504
+
505
+ if("0" == strtoupper($this->httpParsedResponseAr["RESULT"]))
506
+ {
507
+ $order->updateStatus("cancelled");
508
+ return true;
509
  }
510
  else
511
+ {
512
  $order->status = "error";
513
  $order->errorcode = $this->httpParsedResponseAr['RESULT'];
514
  $order->error = urldecode($this->httpParsedResponseAr['RESPMSG']);
515
+ $order->shorterror = urldecode($this->httpParsedResponseAr['RESPMSG']);
516
  return false;
517
  }
518
+ }
519
+
520
  /**
521
  * PAYPAL Function
522
  * Send HTTP POST Request
527
  */
528
  function PPHttpPost($methodName_, $nvpStr_) {
529
  global $gateway_environment;
530
+ $environment = $gateway_environment;
531
+
532
  $PARTNER = pmpro_getOption("payflow_partner");
533
  $VENDOR = pmpro_getOption("payflow_vendor");
534
  $USER = pmpro_getOption("payflow_user");
536
  $API_Endpoint = "https://payflowpro.paypal.com";
537
  if("sandbox" === $environment || "beta-sandbox" === $environment) {
538
  $API_Endpoint = "https://pilot-payflowpro.paypal.com";
539
+ }
540
+
541
  $version = urlencode('4');
542
+
543
  // setting the curl parameters.
544
  $ch = curl_init();
545
  curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
546
  curl_setopt($ch, CURLOPT_VERBOSE, 1);
547
+
548
  // turning off the server and peer verification(TrustManager Concept).
549
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
550
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
551
+
552
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
553
  curl_setopt($ch, CURLOPT_POST, 1);
554
+
555
  // NVPRequest for submitting to server
556
  $nvpreq = "TRXTYPE=" . $methodName_ . "&TENDER=C&PARTNER=" . $PARTNER . "&VENDOR=" . $VENDOR . "&USER=" . $USER . "&PWD=" . $PWD . "&VERBOSITY=medium" . "&BUTTONSOURCE=" . urlencode(PAYPAL_BN_CODE) . $nvpStr_;
557
+
558
  //$nvpreq = "TRXTYPE=" . urlencode($methodName_) . "&TENDER=C&PARTNER=" . urlencode($PARTNER) . "&VENDOR=" . urlencode($VENDOR) . "&USER=" . urlencode($USER) . "&PWD=" . urlencode($PWD) . "&VERBOSITY=medium" . $nvpStr_;
559
+
560
  // setting the nvpreq as POST FIELD to curl
561
  curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
562
+
563
  // getting response from server
564
  $httpResponse = curl_exec($ch);
565
+
566
  if(empty($httpResponse)) {
567
  exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
568
  }
569
+
570
  // Extract the RefundTransaction response details
571
  $httpResponseAr = explode("&", $httpResponse);
572
+
573
  $httpParsedResponseAr = array();
574
  foreach ($httpResponseAr as $i => $value) {
575
  $tmpAr = explode("=", $value);
577
  $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
578
  }
579
  }
580
+
581
  if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('RESULT', $httpParsedResponseAr)) {
582
  exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
583
  }
584
+
585
  return $httpParsedResponseAr;
586
  }
587
  }
classes/gateways/class.pmprogateway_paypal.php CHANGED
@@ -1,71 +1,71 @@
1
  <?php
2
  //include pmprogateway
3
  require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
-
5
  //load classes init method
6
  add_action('init', array('PMProGateway_paypal', 'init'));
7
-
8
  class PMProGateway_paypal extends PMProGateway
9
  {
10
  function PMProGateway_paypal($gateway = NULL)
11
  {
12
  $this->gateway = $gateway;
13
  return $this->gateway;
14
- }
15
-
16
  /**
17
  * Run on WP init
18
- *
19
  * @since 1.8
20
  */
21
  static function init()
22
- {
23
  //make sure PayPal Website Payments Pro is a gateway option
24
  add_filter('pmpro_gateways', array('PMProGateway_paypal', 'pmpro_gateways'));
25
-
26
  //add fields to payment settings
27
  add_filter('pmpro_payment_options', array('PMProGateway_paypal', 'pmpro_payment_options'));
28
-
29
  /*
30
  This code is the same for PayPal Website Payments Pro, PayPal Express, and PayPal Standard
31
  So we only load it if we haven't already.
32
  */
33
  global $pmpro_payment_option_fields_for_paypal;
34
  if(empty($pmpro_payment_option_fields_for_paypal))
35
- {
36
- add_filter('pmpro_payment_option_fields', array('PMProGateway_paypal', 'pmpro_payment_option_fields'), 10, 2);
37
  $pmpro_payment_option_fields_for_paypal = true;
38
  }
39
-
40
  //code to add at checkout
41
  $gateway = pmpro_getGateway();
42
  if($gateway == "paypal")
43
- {
44
  add_filter('pmpro_checkout_default_submit_button', array('PMProGateway_paypal', 'pmpro_checkout_default_submit_button'));
45
  add_action('pmpro_checkout_after_form', array('PMProGateway_paypal', 'pmpro_checkout_after_form'));
46
  }
47
  }
48
-
49
  /**
50
  * Make sure this gateway is in the gateways list
51
- *
52
  * @since 1.8
53
  */
54
  static function pmpro_gateways($gateways)
55
  {
56
  if(empty($gateways['paypal']))
57
  $gateways['paypal'] = __('PayPal Website Payments Pro', 'pmpro');
58
-
59
  return $gateways;
60
  }
61
-
62
  /**
63
  * Get a list of payment options that the this gateway needs/supports.
64
- *
65
  * @since 1.8
66
  */
67
  static function getGatewayOptions()
68
- {
69
  $options = array(
70
  'sslseal',
71
  'nuclear_HTTPS',
@@ -80,29 +80,29 @@
80
  'tax_rate',
81
  'accepted_credit_cards'
82
  );
83
-
84
  return $options;
85
  }
86
-
87
  /**
88
  * Set payment options for payment settings page.
89
- *
90
  * @since 1.8
91
  */
92
  static function pmpro_payment_options($options)
93
- {
94
  //get stripe options
95
  $paypal_options = PMProGateway_paypal::getGatewayOptions();
96
-
97
  //merge with others.
98
  $options = array_merge($paypal_options, $options);
99
-
100
  return $options;
101
  }
102
-
103
  /**
104
  * Display fields for this gateway's options.
105
- *
106
  * @since 1.8
107
  */
108
  static function pmpro_payment_option_fields($values, $gateway)
@@ -112,20 +112,20 @@
112
  <td colspan="2">
113
  <?php _e('PayPal Settings', 'pmpro'); ?>
114
  </td>
115
- </tr>
116
  <tr class="gateway gateway_paypalstandard" <?php if($gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
117
  <td colspan="2">
118
  <strong><?php _e('Note', 'pmpro');?>:</strong> <?php _e('We do not recommend using PayPal Standard. We suggest using PayPal Express, Website Payments Pro (Legacy), or PayPal Pro (Payflow Pro). <a target="_blank" href="http://www.paidmembershipspro.com/2013/09/read-using-paypal-standard-paid-memberships-pro/">More information on why can be found here.</a>', 'pmpro');?>
119
- </td>
120
- </tr>
121
  <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
122
- <th scope="row" valign="top">
123
  <label for="gateway_email"><?php _e('Gateway Account Email', 'pmpro');?>:</label>
124
  </th>
125
  <td>
126
  <input type="text" id="gateway_email" name="gateway_email" size="60" value="<?php echo esc_attr($values['gateway_email'])?>" />
127
  </td>
128
- </tr>
129
  <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
130
  <th scope="row" valign="top">
131
  <label for="apiusername"><?php _e('API Username', 'pmpro');?>:</label>
@@ -141,7 +141,7 @@
141
  <td>
142
  <input type="text" id="apipassword" name="apipassword" size="60" value="<?php echo esc_attr($values['apipassword'])?>" />
143
  </td>
144
- </tr>
145
  <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
146
  <th scope="row" valign="top">
147
  <label for="apisignature"><?php _e('API Signature', 'pmpro');?>:</label>
@@ -149,7 +149,7 @@
149
  <td>
150
  <input type="text" id="apisignature" name="apisignature" size="60" value="<?php echo esc_attr($values['apisignature'])?>" />
151
  </td>
152
- </tr>
153
  <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
154
  <th scope="row" valign="top">
155
  <label><?php _e('IPN Handler URL', 'pmpro');?>:</label>
@@ -160,7 +160,7 @@
160
  </tr>
161
  <?php
162
  }
163
-
164
  /**
165
  * Swap in our submit buttons.
166
  *
@@ -169,26 +169,26 @@
169
  static function pmpro_checkout_default_submit_button($show)
170
  {
171
  global $gateway, $pmpro_requirebilling;
172
-
173
  //show our submit buttons
174
  ?>
175
  <?php if($gateway == "paypal" || $gateway == "paypalexpress" || $gateway == "paypalstandard") { ?>
176
  <span id="pmpro_paypalexpress_checkout" <?php if(($gateway != "paypalexpress" && $gateway != "paypalstandard") || !$pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
177
- <input type="hidden" name="submit-checkout" value="1" />
178
  <input type="image" value="<?php _e('Check Out with PayPal', 'pmpro');?> &raquo;" src="<?php echo apply_filters("pmpro_paypal_button_image", "https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif");?>" />
179
  </span>
180
  <?php } ?>
181
-
182
  <span id="pmpro_submit_span" <?php if(($gateway == "paypalexpress" || $gateway == "paypalstandard") && $pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
183
- <input type="hidden" name="submit-checkout" value="1" />
184
- <input type="submit" class="pmpro_btn pmpro_btn-submit-checkout" value="<?php if($pmpro_requirebilling) { _e('Submit and Check Out', 'pmpro'); } else { _e('Submit and Confirm', 'pmpro');}?> &raquo;" />
185
  </span>
186
  <?php
187
-
188
  //don't show the default
189
  return false;
190
  }
191
-
192
  /**
193
  * Scripts for checkout page.
194
  *
@@ -197,25 +197,25 @@
197
  static function pmpro_checkout_after_form()
198
  {
199
  ?>
200
- <script>
201
  //choosing payment method
202
- jQuery('input[name=gateway]').click(function() {
203
  if(jQuery(this).val() == 'paypal')
204
  {
205
  jQuery('#pmpro_paypalexpress_checkout').hide();
206
  jQuery('#pmpro_billing_address_fields').show();
207
- jQuery('#pmpro_payment_information_fields').show();
208
  jQuery('#pmpro_submit_span').show();
209
  }
210
  else
211
- {
212
  jQuery('#pmpro_billing_address_fields').hide();
213
- jQuery('#pmpro_payment_information_fields').hide();
214
  jQuery('#pmpro_submit_span').hide();
215
  jQuery('#pmpro_paypalexpress_checkout').show();
216
  }
217
  });
218
-
219
  //select the radio button if the label is clicked on
220
  jQuery('a.pmpro_radio').click(function() {
221
  jQuery(this).prev().click();
@@ -223,20 +223,20 @@
223
  </script>
224
  <?php
225
  }
226
-
227
  /**
228
  * Process checkout.
229
- *
230
  */
231
  function process(&$order)
232
  {
233
  if(floatval($order->InitialPayment) == 0)
234
  {
235
  //auth first, then process
236
- $authorization_id = $this->authorize($order);
237
  if($authorization_id)
238
  {
239
- $this->void($order, $authorization_id);
240
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
241
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
242
  return $this->subscribe($order);
@@ -252,18 +252,18 @@
252
  {
253
  //charge first payment
254
  if($this->charge($order))
255
- {
256
  //setup recurring billing
257
  if(pmpro_isLevelRecurring($order->membership_level))
258
  {
259
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
260
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
261
  if($this->subscribe($order))
262
- {
263
  return true;
264
  }
265
  else
266
- {
267
  if($this->refund($order, $order->payment_transaction_id))
268
  {
269
  if(empty($order->error))
@@ -273,146 +273,146 @@
273
  {
274
  if(empty($order->error))
275
  $order->error = "Unknown error: Payment failed.";
276
-
277
  $order->error .= " " . __("A partial payment was made that we could not refund. Please contact the site owner immediately to correct this.", "pmpro");
278
  }
279
-
280
- return false;
281
  }
282
  }
283
  else
284
  {
285
- //only a one time charge
286
- $order->status = "success"; //saved on checkout page
287
  $order->saveOrder();
288
  return true;
289
  }
290
- }
291
- }
292
  }
293
-
294
  function authorize(&$order)
295
  {
296
  if(empty($order->code))
297
  $order->code = $order->getRandomCode();
298
-
299
  //paypal profile stuff
300
  $nvpStr = "";
301
  if(!empty($order->Token))
302
  $nvpStr .= "&TOKEN=" . $order->Token;
303
- $nvpStr .="&AMT=1.00&CURRENCYCODE=" . pmpro_getOption("currency");
304
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
305
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
306
-
307
  $nvpStr .= "&PAYMENTACTION=Authorization&IPADDRESS=" . $_SERVER['REMOTE_ADDR'] . "&INVNUM=" . $order->code;
308
-
309
  //credit card fields
310
  if($order->cardtype == "American Express")
311
  $cardtype = "Amex";
312
  else
313
  $cardtype = $order->cardtype;
314
-
315
  if(!empty($cardtype))
316
  $nvpStr .= "&CREDITCARDTYPE=" . $cardtype . "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->ExpirationDate . "&CVV2=" . $order->CVV2;
317
 
318
  //Maestro/Solo card fields. (Who uses these?) :)
319
  if(!empty($order->StartDate))
320
  $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber;
321
-
322
  //billing address, etc
323
  if(!empty($order->Address1))
324
  {
325
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
326
-
327
  if($order->Address2)
328
  $nvpStr .= "&STREET2=" . $order->Address2;
329
-
330
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&SHIPTOPHONENUM=" . $order->billing->phone;
331
  }
332
 
333
  //for debugging, let's attach this to the class object
334
  $this->nvpStr = $nvpStr;
335
-
336
  $this->httpParsedResponseAr = $this->PPHttpPost('DoDirectPayment', $nvpStr);
337
-
338
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
339
  $order->authorization_id = $this->httpParsedResponseAr['TRANSACTIONID'];
340
- $order->updateStatus("authorized");
341
- return $order->authorization_id;
342
- } else {
343
  $order->status = "error";
344
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
345
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
346
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
347
- return false;
348
- }
349
  }
350
-
351
  function void(&$order, $authorization_id = null)
352
  {
353
  if(empty($authorization_id))
354
  return false;
355
-
356
  //paypal profile stuff
357
  $nvpStr="&AUTHORIZATIONID=" . $authorization_id . "&NOTE=Voiding an authorization for a recurring payment setup.";
358
-
359
  $this->httpParsedResponseAr = $this->PPHttpPost('DoVoid', $nvpStr);
360
-
361
- if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
362
- return true;
363
- } else {
364
  $order->status = "error";
365
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
366
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
367
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
368
- return false;
369
- }
370
- }
371
-
372
  function refund(&$order, $transaction_id)
373
  {
374
  if(empty($transaction_id))
375
  return false;
376
-
377
  //paypal profile stuff
378
  $nvpStr="&TRANSACTIONID=" . $transaction_id . "&NOTE=Refunding a charge.";
379
-
380
  $this->httpParsedResponseAr = $this->PPHttpPost('RefundTransaction', $nvpStr);
381
-
382
- if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
383
- return true;
384
- } else {
385
  $order->status = "error";
386
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
387
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
388
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
389
- return false;
390
- }
391
  }
392
-
393
  function charge(&$order)
394
  {
395
  global $pmpro_currency;
396
-
397
  if(empty($order->code))
398
  $order->code = $order->getRandomCode();
399
-
400
  //taxes on the amount
401
  $amount = $order->InitialPayment;
402
- $amount_tax = $order->getTaxForPrice($amount);
403
  $order->subtotal = $amount;
404
  $amount = round((float)$amount + (float)$amount_tax, 2);
405
-
406
  //paypal profile stuff
407
  $nvpStr = "";
408
  if(!empty($order->Token))
409
  $nvpStr .= "&TOKEN=" . $order->Token;
410
- $nvpStr .="&AMT=" . $amount . "&ITEMAMT=" . $order->InitialPayment . "&TAXAMT=" . $amount_tax . "&CURRENCYCODE=" . $pmpro_currency;
411
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
412
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
413
-
414
- $nvpStr .= "&PAYMENTACTION=Sale&IPADDRESS=" . $_SERVER['REMOTE_ADDR'] . "&INVNUM=" . $order->code;
415
-
416
  //credit card fields
417
  if($order->cardtype == "American Express")
418
  $cardtype = "Amex";
@@ -425,48 +425,48 @@
425
  //Maestro/Solo card fields. (Who uses these?) :)
426
  if(!empty($order->StartDate))
427
  $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber;
428
-
429
  //billing address, etc
430
  if($order->Address1)
431
  {
432
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
433
-
434
  if($order->Address2)
435
  $nvpStr .= "&STREET2=" . $order->Address2;
436
-
437
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&SHIPTOPHONENUM=" . $order->billing->phone;
438
  }
439
 
440
  $this->httpParsedResponseAr = $this->PPHttpPost('DoDirectPayment', $nvpStr);
441
-
442
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
443
  $order->payment_transaction_id = $this->httpParsedResponseAr['TRANSACTIONID'];
444
- $order->updateStatus("success");
445
- return true;
446
- } else {
447
  $order->status = "error";
448
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
449
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
450
- $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
451
- return false;
452
- }
453
  }
454
-
455
  function subscribe(&$order)
456
  {
457
  global $pmpro_currency;
458
-
459
  if(empty($order->code))
460
- $order->code = $order->getRandomCode();
461
-
462
  //filter order before subscription. use with care.
463
  $order = apply_filters("pmpro_subscribe_order", $order, $this);
464
-
465
  //taxes on the amount
466
  $amount = $order->PaymentAmount;
467
- $amount_tax = $order->getTaxForPrice($amount);
468
  $amount = round((float)$amount + (float)$amount_tax, 2);
469
-
470
  //paypal profile stuff
471
  $nvpStr = "";
472
  if(!empty($order->Token))
@@ -476,58 +476,58 @@
476
  $nvpStr .= "&DESC=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
477
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
478
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
479
-
480
- //if billing cycles are defined
481
  if(!empty($order->TotalBillingCycles))
482
  $nvpStr .= "&TOTALBILLINGCYCLES=" . $order->TotalBillingCycles;
483
-
484
  //if a trial period is defined
485
  if(!empty($order->TrialBillingPeriod))
486
  {
487
- $trial_amount = $order->TrialAmount;
488
  $trial_tax = $order->getTaxForPrice($trial_amount);
489
  $trial_amount = round((float)$trial_amount + (float)$trial_tax, 2);
490
-
491
  $nvpStr .= "&TRIALBILLINGPERIOD=" . $order->TrialBillingPeriod . "&TRIALBILLINGFREQUENCY=" . $order->TrialBillingFrequency . "&TRIALAMT=" . $trial_amount;
492
  }
493
  if(!empty($order->TrialBillingCycles))
494
  $nvpStr .= "&TRIALTOTALBILLINGCYCLES=" . $order->TrialBillingCycles;
495
-
496
  //credit card fields
497
  if($order->cardtype == "American Express")
498
  $cardtype = "Amex";
499
  else
500
  $cardtype = $order->cardtype;
501
-
502
- if($cardtype)
503
  $nvpStr .= "&CREDITCARDTYPE=" . $cardtype . "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->ExpirationDate . "&CVV2=" . $order->CVV2;
504
 
505
  //Maestro/Solo card fields. (Who uses these?) :)
506
  if(!empty($order->StartDate))
507
  $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber;
508
-
509
  //billing address, etc
510
  if($order->Address1)
511
  {
512
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
513
-
514
  if($order->Address2)
515
  $nvpStr .= "&STREET2=" . $order->Address2;
516
-
517
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&SHIPTOPHONENUM=" . $order->billing->phone;
518
  }
519
 
520
  //for debugging let's add this to the class object
521
  $this->nvpStr = $nvpStr;
522
-
523
  $this->httpParsedResponseAr = $this->PPHttpPost('CreateRecurringPaymentsProfile', $nvpStr);
524
-
525
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
526
- $order->status = "success";
527
  $order->subscription_transaction_id = urldecode($this->httpParsedResponseAr['PROFILEID']);
528
  return true;
529
  //exit('CreateRecurringPaymentsProfile Completed Successfully: '.print_r($this->httpParsedResponseAr, true));
530
- } else {
531
  $order->status = "error";
532
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
533
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
@@ -535,47 +535,47 @@
535
  return false;
536
  //exit('CreateRecurringPaymentsProfile failed: ' . print_r($httpParsedResponseAr, true));
537
  }
538
- }
539
-
540
  function update(&$order)
541
  {
542
  //paypal profile stuff
543
- $nvpStr = "";
544
  $nvpStr .= "&PROFILEID=" . $order->subscription_transaction_id;
545
-
546
  //credit card fields
547
  if($order->cardtype == "American Express")
548
  $cardtype = "Amex";
549
  else
550
  $cardtype = $order->cardtype;
551
-
552
  //credit card fields
553
- if($cardtype)
554
  $nvpStr .= "&CREDITCARDTYPE=" . $cardtype . "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->ExpirationDate . "&CVV2=" . $order->CVV2;
555
 
556
  //Maestro/Solo card fields. (Who uses these?) :)
557
  if($order->StartDate)
558
  $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber;
559
-
560
  //billing address, etc
561
  if($order->Address1)
562
  {
563
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
564
-
565
  if($order->Address2)
566
  $nvpStr .= "&STREET2=" . $order->Address2;
567
-
568
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip;
569
- }
570
-
571
  $this->httpParsedResponseAr = $this->PPHttpPost('UpdateRecurringPaymentsProfile', $nvpStr);
572
-
573
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
574
  $order->status = "success";
575
  $order->subscription_transaction_id = urldecode($this->httpParsedResponseAr['PROFILEID']);
576
  return true;
577
  //exit('CreateRecurringPaymentsProfile Completed Successfully: '.print_r($this->httpParsedResponseAr, true));
578
- } else {
579
  $order->status = "error";
580
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
581
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
@@ -584,31 +584,31 @@
584
  //exit('CreateRecurringPaymentsProfile failed: ' . print_r($httpParsedResponseAr, true));
585
  }
586
  }
587
-
588
  function cancel(&$order)
589
  {
590
  //paypal profile stuff
591
- $nvpStr = "";
592
- $nvpStr .= "&PROFILEID=" . urlencode($order->subscription_transaction_id) . "&ACTION=Cancel&NOTE=" . urlencode("User requested cancel.");
593
-
594
  $this->httpParsedResponseAr = $this->PPHttpPost('ManageRecurringPaymentsProfileStatus', $nvpStr);
595
-
596
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"]))
597
- {
598
- $order->updateStatus("cancelled");
599
- return true;
600
  }
601
  else
602
- {
603
  $order->status = "error";
604
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
605
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']) . ". " . __("Please contact the site owner or cancel your subscription from within PayPal to make sure you are not charged going forward.", "pmpro");
606
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
607
-
608
- return false;
609
  }
610
- }
611
-
612
  /**
613
  * PAYPAL Function
614
  * Send HTTP POST Request
@@ -619,46 +619,46 @@
619
  */
620
  function PPHttpPost($methodName_, $nvpStr_) {
621
  global $gateway_environment;
622
- $environment = $gateway_environment;
623
-
624
  $API_UserName = pmpro_getOption("apiusername");
625
  $API_Password = pmpro_getOption("apipassword");
626
  $API_Signature = pmpro_getOption("apisignature");
627
  $API_Endpoint = "https://api-3t.paypal.com/nvp";
628
  if("sandbox" === $environment || "beta-sandbox" === $environment) {
629
  $API_Endpoint = "https://api-3t.$environment.paypal.com/nvp";
630
- }
631
-
632
  $version = urlencode('72.0');
633
-
634
  // setting the curl parameters.
635
  $ch = curl_init();
636
  curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
637
  curl_setopt($ch, CURLOPT_VERBOSE, 1);
638
-
639
  // turning off the server and peer verification(TrustManager Concept).
640
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
641
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
642
-
643
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
644
  curl_setopt($ch, CURLOPT_POST, 1);
645
-
646
  // NVPRequest for submitting to server
647
  $nvpreq = "METHOD=" . urlencode($methodName_) . "&VERSION=" . urlencode($version) . "&PWD=" . urlencode($API_Password) . "&USER=" . urlencode($API_UserName) . "&SIGNATURE=" . urlencode($API_Signature) . "&BUTTONSOURCE=" . urlencode(PAYPAL_BN_CODE) . $nvpStr_;
648
-
649
  // setting the nvpreq as POST FIELD to curl
650
  curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
651
-
652
  // getting response from server
653
  $httpResponse = curl_exec($ch);
654
-
655
  if(empty($httpResponse)) {
656
  exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
657
  }
658
-
659
  // Extract the RefundTransaction response details
660
  $httpResponseAr = explode("&", $httpResponse);
661
-
662
  $httpParsedResponseAr = array();
663
  foreach ($httpResponseAr as $i => $value) {
664
  $tmpAr = explode("=", $value);
@@ -666,11 +666,11 @@
666
  $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
667
  }
668
  }
669
-
670
  if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
671
  exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
672
  }
673
-
674
  return $httpParsedResponseAr;
675
  }
676
  }
1
  <?php
2
  //include pmprogateway
3
  require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
+
5
  //load classes init method
6
  add_action('init', array('PMProGateway_paypal', 'init'));
7
+
8
  class PMProGateway_paypal extends PMProGateway
9
  {
10
  function PMProGateway_paypal($gateway = NULL)
11
  {
12
  $this->gateway = $gateway;
13
  return $this->gateway;
14
+ }
15
+
16
  /**
17
  * Run on WP init
18
+ *
19
  * @since 1.8
20
  */
21
  static function init()
22
+ {
23
  //make sure PayPal Website Payments Pro is a gateway option
24
  add_filter('pmpro_gateways', array('PMProGateway_paypal', 'pmpro_gateways'));
25
+
26
  //add fields to payment settings
27
  add_filter('pmpro_payment_options', array('PMProGateway_paypal', 'pmpro_payment_options'));
28
+
29
  /*
30
  This code is the same for PayPal Website Payments Pro, PayPal Express, and PayPal Standard
31
  So we only load it if we haven't already.
32
  */
33
  global $pmpro_payment_option_fields_for_paypal;
34
  if(empty($pmpro_payment_option_fields_for_paypal))
35
+ {
36
+ add_filter('pmpro_payment_option_fields', array('PMProGateway_paypal', 'pmpro_payment_option_fields'), 10, 2);
37
  $pmpro_payment_option_fields_for_paypal = true;
38
  }
39
+
40
  //code to add at checkout
41
  $gateway = pmpro_getGateway();
42
  if($gateway == "paypal")
43
+ {
44
  add_filter('pmpro_checkout_default_submit_button', array('PMProGateway_paypal', 'pmpro_checkout_default_submit_button'));
45
  add_action('pmpro_checkout_after_form', array('PMProGateway_paypal', 'pmpro_checkout_after_form'));
46
  }
47
  }
48
+
49
  /**
50
  * Make sure this gateway is in the gateways list
51
+ *
52
  * @since 1.8
53
  */
54
  static function pmpro_gateways($gateways)
55
  {
56
  if(empty($gateways['paypal']))
57
  $gateways['paypal'] = __('PayPal Website Payments Pro', 'pmpro');
58
+
59
  return $gateways;
60
  }
61
+
62
  /**
63
  * Get a list of payment options that the this gateway needs/supports.
64
+ *
65
  * @since 1.8
66
  */
67
  static function getGatewayOptions()
68
+ {
69
  $options = array(
70
  'sslseal',
71
  'nuclear_HTTPS',
80
  'tax_rate',
81
  'accepted_credit_cards'
82
  );
83
+
84
  return $options;
85
  }
86
+
87
  /**
88
  * Set payment options for payment settings page.
89
+ *
90
  * @since 1.8
91
  */
92
  static function pmpro_payment_options($options)
93
+ {
94
  //get stripe options
95
  $paypal_options = PMProGateway_paypal::getGatewayOptions();
96
+
97
  //merge with others.
98
  $options = array_merge($paypal_options, $options);
99
+
100
  return $options;
101
  }
102
+
103
  /**
104
  * Display fields for this gateway's options.
105
+ *
106
  * @since 1.8
107
  */
108
  static function pmpro_payment_option_fields($values, $gateway)
112
  <td colspan="2">
113
  <?php _e('PayPal Settings', 'pmpro'); ?>
114
  </td>
115
+ </tr>
116
  <tr class="gateway gateway_paypalstandard" <?php if($gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
117
  <td colspan="2">
118
  <strong><?php _e('Note', 'pmpro');?>:</strong> <?php _e('We do not recommend using PayPal Standard. We suggest using PayPal Express, Website Payments Pro (Legacy), or PayPal Pro (Payflow Pro). <a target="_blank" href="http://www.paidmembershipspro.com/2013/09/read-using-paypal-standard-paid-memberships-pro/">More information on why can be found here.</a>', 'pmpro');?>
119
+ </td>
120
+ </tr>
121
  <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
122
+ <th scope="row" valign="top">
123
  <label for="gateway_email"><?php _e('Gateway Account Email', 'pmpro');?>:</label>
124
  </th>
125
  <td>
126
  <input type="text" id="gateway_email" name="gateway_email" size="60" value="<?php echo esc_attr($values['gateway_email'])?>" />
127
  </td>
128
+ </tr>
129
  <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
130
  <th scope="row" valign="top">
131
  <label for="apiusername"><?php _e('API Username', 'pmpro');?>:</label>
141
  <td>
142
  <input type="text" id="apipassword" name="apipassword" size="60" value="<?php echo esc_attr($values['apipassword'])?>" />
143
  </td>
144
+ </tr>
145
  <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
146
  <th scope="row" valign="top">
147
  <label for="apisignature"><?php _e('API Signature', 'pmpro');?>:</label>
149
  <td>
150
  <input type="text" id="apisignature" name="apisignature" size="60" value="<?php echo esc_attr($values['apisignature'])?>" />
151
  </td>
152
+ </tr>
153
  <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
154
  <th scope="row" valign="top">
155
  <label><?php _e('IPN Handler URL', 'pmpro');?>:</label>
160
  </tr>
161
  <?php
162
  }
163
+
164
  /**
165
  * Swap in our submit buttons.
166
  *
169
  static function pmpro_checkout_default_submit_button($show)
170
  {
171
  global $gateway, $pmpro_requirebilling;
172
+
173
  //show our submit buttons
174
  ?>
175
  <?php if($gateway == "paypal" || $gateway == "paypalexpress" || $gateway == "paypalstandard") { ?>
176
  <span id="pmpro_paypalexpress_checkout" <?php if(($gateway != "paypalexpress" && $gateway != "paypalstandard") || !$pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
177
+ <input type="hidden" name="submit-checkout" value="1" />
178
  <input type="image" value="<?php _e('Check Out with PayPal', 'pmpro');?> &raquo;" src="<?php echo apply_filters("pmpro_paypal_button_image", "https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif");?>" />
179
  </span>
180
  <?php } ?>
181
+
182
  <span id="pmpro_submit_span" <?php if(($gateway == "paypalexpress" || $gateway == "paypalstandard") && $pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
183
+ <input type="hidden" name="submit-checkout" value="1" />
184
+ <input type="submit" class="pmpro_btn pmpro_btn-submit-checkout" value="<?php if($pmpro_requirebilling) { _e('Submit and Check Out', 'pmpro'); } else { _e('Submit and Confirm', 'pmpro');}?> &raquo;" />
185
  </span>
186
  <?php
187
+
188
  //don't show the default
189
  return false;
190
  }
191
+
192
  /**
193
  * Scripts for checkout page.
194
  *
197
  static function pmpro_checkout_after_form()
198
  {
199
  ?>
200
+ <script>
201
  //choosing payment method
202
+ jQuery('input[name=gateway]').click(function() {
203
  if(jQuery(this).val() == 'paypal')
204
  {
205
  jQuery('#pmpro_paypalexpress_checkout').hide();
206
  jQuery('#pmpro_billing_address_fields').show();
207
+ jQuery('#pmpro_payment_information_fields').show();
208
  jQuery('#pmpro_submit_span').show();
209
  }
210
  else
211
+ {
212
  jQuery('#pmpro_billing_address_fields').hide();
213
+ jQuery('#pmpro_payment_information_fields').hide();
214
  jQuery('#pmpro_submit_span').hide();
215
  jQuery('#pmpro_paypalexpress_checkout').show();
216
  }
217
  });
218
+
219
  //select the radio button if the label is clicked on
220
  jQuery('a.pmpro_radio').click(function() {
221
  jQuery(this).prev().click();
223
  </script>
224
  <?php
225
  }
226
+
227
  /**
228
  * Process checkout.
229
+ *
230
  */
231
  function process(&$order)
232
  {
233
  if(floatval($order->InitialPayment) == 0)
234
  {
235
  //auth first, then process
236
+ $authorization_id = $this->authorize($order);
237
  if($authorization_id)
238
  {
239
+ $this->void($order, $authorization_id);
240
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
241
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
242
  return $this->subscribe($order);
252
  {
253
  //charge first payment
254
  if($this->charge($order))
255
+ {
256
  //setup recurring billing
257
  if(pmpro_isLevelRecurring($order->membership_level))
258
  {
259
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
260
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
261
  if($this->subscribe($order))
262
+ {
263
  return true;
264
  }
265
  else
266
+ {
267
  if($this->refund($order, $order->payment_transaction_id))
268
  {
269
  if(empty($order->error))
273
  {
274
  if(empty($order->error))
275
  $order->error = "Unknown error: Payment failed.";
276
+
277
  $order->error .= " " . __("A partial payment was made that we could not refund. Please contact the site owner immediately to correct this.", "pmpro");
278
  }
279
+
280
+ return false;
281
  }
282
  }
283
  else
284
  {
285
+ //only a one time charge
286
+ $order->status = "success"; //saved on checkout page
287
  $order->saveOrder();
288
  return true;
289
  }
290
+ }
291
+ }
292
  }
293
+
294
  function authorize(&$order)
295
  {
296
  if(empty($order->code))
297
  $order->code = $order->getRandomCode();
298
+
299
  //paypal profile stuff
300
  $nvpStr = "";
301
  if(!empty($order->Token))
302
  $nvpStr .= "&TOKEN=" . $order->Token;
303
+ $nvpStr .="&AMT=1.00&CURRENCYCODE=" . pmpro_getOption("currency");
304
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
305
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
306
+
307
  $nvpStr .= "&PAYMENTACTION=Authorization&IPADDRESS=" . $_SERVER['REMOTE_ADDR'] . "&INVNUM=" . $order->code;
308
+
309
  //credit card fields
310
  if($order->cardtype == "American Express")
311
  $cardtype = "Amex";
312
  else
313
  $cardtype = $order->cardtype;
314
+
315
  if(!empty($cardtype))
316
  $nvpStr .= "&CREDITCARDTYPE=" . $cardtype . "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->ExpirationDate . "&CVV2=" . $order->CVV2;
317
 
318
  //Maestro/Solo card fields. (Who uses these?) :)
319
  if(!empty($order->StartDate))
320
  $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber;
321
+
322
  //billing address, etc
323
  if(!empty($order->Address1))
324
  {
325
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
326
+
327
  if($order->Address2)
328
  $nvpStr .= "&STREET2=" . $order->Address2;
329
+
330
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&SHIPTOPHONENUM=" . $order->billing->phone;
331
  }
332
 
333
  //for debugging, let's attach this to the class object
334
  $this->nvpStr = $nvpStr;
335
+
336
  $this->httpParsedResponseAr = $this->PPHttpPost('DoDirectPayment', $nvpStr);
337
+
338
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
339
  $order->authorization_id = $this->httpParsedResponseAr['TRANSACTIONID'];
340
+ $order->updateStatus("authorized");
341
+ return $order->authorization_id;
342
+ } else {
343
  $order->status = "error";
344
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
345
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
346
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
347
+ return false;
348
+ }
349
  }
350
+
351
  function void(&$order, $authorization_id = null)
352
  {
353
  if(empty($authorization_id))
354
  return false;
355
+
356
  //paypal profile stuff
357
  $nvpStr="&AUTHORIZATIONID=" . $authorization_id . "&NOTE=Voiding an authorization for a recurring payment setup.";
358
+
359
  $this->httpParsedResponseAr = $this->PPHttpPost('DoVoid', $nvpStr);
360
+
361
+ if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
362
+ return true;
363
+ } else {
364
  $order->status = "error";
365
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
366
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
367
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
368
+ return false;
369
+ }
370
+ }
371
+
372
  function refund(&$order, $transaction_id)
373
  {
374
  if(empty($transaction_id))
375
  return false;
376
+
377
  //paypal profile stuff
378
  $nvpStr="&TRANSACTIONID=" . $transaction_id . "&NOTE=Refunding a charge.";
379
+
380
  $this->httpParsedResponseAr = $this->PPHttpPost('RefundTransaction', $nvpStr);
381
+
382
+ if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
383
+ return true;
384
+ } else {
385
  $order->status = "error";
386
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
387
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
388
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
389
+ return false;
390
+ }
391
  }
392
+
393
  function charge(&$order)
394
  {
395
  global $pmpro_currency;
396
+
397
  if(empty($order->code))
398
  $order->code = $order->getRandomCode();
399
+
400
  //taxes on the amount
401
  $amount = $order->InitialPayment;
402
+ $amount_tax = $order->getTaxForPrice($amount);
403
  $order->subtotal = $amount;
404
  $amount = round((float)$amount + (float)$amount_tax, 2);
405
+
406
  //paypal profile stuff
407
  $nvpStr = "";
408
  if(!empty($order->Token))
409
  $nvpStr .= "&TOKEN=" . $order->Token;
410
+ $nvpStr .="&AMT=" . $amount . "&ITEMAMT=" . $order->InitialPayment . "&TAXAMT=" . $amount_tax . "&CURRENCYCODE=" . $pmpro_currency;
411
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
412
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
413
+
414
+ $nvpStr .= "&PAYMENTACTION=Sale&IPADDRESS=" . $_SERVER['REMOTE_ADDR'] . "&INVNUM=" . $order->code;
415
+
416
  //credit card fields
417
  if($order->cardtype == "American Express")
418
  $cardtype = "Amex";
425
  //Maestro/Solo card fields. (Who uses these?) :)
426
  if(!empty($order->StartDate))
427
  $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber;
428
+
429
  //billing address, etc
430
  if($order->Address1)
431
  {
432
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
433
+
434
  if($order->Address2)
435
  $nvpStr .= "&STREET2=" . $order->Address2;
436
+
437
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&SHIPTOPHONENUM=" . $order->billing->phone;
438
  }
439
 
440
  $this->httpParsedResponseAr = $this->PPHttpPost('DoDirectPayment', $nvpStr);
441
+
442
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
443
  $order->payment_transaction_id = $this->httpParsedResponseAr['TRANSACTIONID'];
444
+ $order->updateStatus("success");
445
+ return true;
446
+ } else {
447
  $order->status = "error";
448
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
449
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
450
+ $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
451
+ return false;
452
+ }
453
  }
454
+
455
  function subscribe(&$order)
456
  {
457
  global $pmpro_currency;
458
+
459
  if(empty($order->code))
460
+ $order->code = $order->getRandomCode();
461
+
462
  //filter order before subscription. use with care.
463
  $order = apply_filters("pmpro_subscribe_order", $order, $this);
464
+
465
  //taxes on the amount
466
  $amount = $order->PaymentAmount;
467
+ $amount_tax = $order->getTaxForPrice($amount);
468
  $amount = round((float)$amount + (float)$amount_tax, 2);
469
+
470
  //paypal profile stuff
471
  $nvpStr = "";
472
  if(!empty($order->Token))
476
  $nvpStr .= "&DESC=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
477
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
478
  //$nvpStr .= "&L_BILLINGTYPE0=RecurringPayments&L_BILLINGAGREEMENTDESCRIPTION0=" . $order->PaymentAmount;
479
+
480
+ //if billing cycles are defined
481
  if(!empty($order->TotalBillingCycles))
482
  $nvpStr .= "&TOTALBILLINGCYCLES=" . $order->TotalBillingCycles;
483
+
484
  //if a trial period is defined
485
  if(!empty($order->TrialBillingPeriod))
486
  {
487
+ $trial_amount = $order->TrialAmount;
488
  $trial_tax = $order->getTaxForPrice($trial_amount);
489
  $trial_amount = round((float)$trial_amount + (float)$trial_tax, 2);
490
+
491
  $nvpStr .= "&TRIALBILLINGPERIOD=" . $order->TrialBillingPeriod . "&TRIALBILLINGFREQUENCY=" . $order->TrialBillingFrequency . "&TRIALAMT=" . $trial_amount;
492
  }
493
  if(!empty($order->TrialBillingCycles))
494
  $nvpStr .= "&TRIALTOTALBILLINGCYCLES=" . $order->TrialBillingCycles;
495
+
496
  //credit card fields
497
  if($order->cardtype == "American Express")
498
  $cardtype = "Amex";
499
  else
500
  $cardtype = $order->cardtype;
501
+
502
+ if($cardtype)
503
  $nvpStr .= "&CREDITCARDTYPE=" . $cardtype . "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->ExpirationDate . "&CVV2=" . $order->CVV2;
504
 
505
  //Maestro/Solo card fields. (Who uses these?) :)
506
  if(!empty($order->StartDate))
507
  $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber;
508
+
509
  //billing address, etc
510
  if($order->Address1)
511
  {
512
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
513
+
514
  if($order->Address2)
515
  $nvpStr .= "&STREET2=" . $order->Address2;
516
+
517
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip . "&SHIPTOPHONENUM=" . $order->billing->phone;
518
  }
519
 
520
  //for debugging let's add this to the class object
521
  $this->nvpStr = $nvpStr;
522
+
523
  $this->httpParsedResponseAr = $this->PPHttpPost('CreateRecurringPaymentsProfile', $nvpStr);
524
+
525
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
526
+ $order->status = "success";
527
  $order->subscription_transaction_id = urldecode($this->httpParsedResponseAr['PROFILEID']);
528
  return true;
529
  //exit('CreateRecurringPaymentsProfile Completed Successfully: '.print_r($this->httpParsedResponseAr, true));
530
+ } else {
531
  $order->status = "error";
532
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
533
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
535
  return false;
536
  //exit('CreateRecurringPaymentsProfile failed: ' . print_r($httpParsedResponseAr, true));
537
  }
538
+ }
539
+
540
  function update(&$order)
541
  {
542
  //paypal profile stuff
543
+ $nvpStr = "";
544
  $nvpStr .= "&PROFILEID=" . $order->subscription_transaction_id;
545
+
546
  //credit card fields
547
  if($order->cardtype == "American Express")
548
  $cardtype = "Amex";
549
  else
550
  $cardtype = $order->cardtype;
551
+
552
  //credit card fields
553
+ if($cardtype)
554
  $nvpStr .= "&CREDITCARDTYPE=" . $cardtype . "&ACCT=" . $order->accountnumber . "&EXPDATE=" . $order->ExpirationDate . "&CVV2=" . $order->CVV2;
555
 
556
  //Maestro/Solo card fields. (Who uses these?) :)
557
  if($order->StartDate)
558
  $nvpStr .= "&STARTDATE=" . $order->StartDate . "&ISSUENUMBER=" . $order->IssueNumber;
559
+
560
  //billing address, etc
561
  if($order->Address1)
562
  {
563
  $nvpStr .= "&EMAIL=" . $order->Email . "&FIRSTNAME=" . $order->FirstName . "&LASTNAME=" . $order->LastName . "&STREET=" . $order->Address1;
564
+
565
  if($order->Address2)
566
  $nvpStr .= "&STREET2=" . $order->Address2;
567
+
568
  $nvpStr .= "&CITY=" . $order->billing->city . "&STATE=" . $order->billing->state . "&COUNTRYCODE=" . $order->billing->country . "&ZIP=" . $order->billing->zip;
569
+ }
570
+
571
  $this->httpParsedResponseAr = $this->PPHttpPost('UpdateRecurringPaymentsProfile', $nvpStr);
572
+
573
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
574
  $order->status = "success";
575
  $order->subscription_transaction_id = urldecode($this->httpParsedResponseAr['PROFILEID']);
576
  return true;
577
  //exit('CreateRecurringPaymentsProfile Completed Successfully: '.print_r($this->httpParsedResponseAr, true));
578
+ } else {
579
  $order->status = "error";
580
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
581
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
584
  //exit('CreateRecurringPaymentsProfile failed: ' . print_r($httpParsedResponseAr, true));
585
  }
586
  }
587
+
588
  function cancel(&$order)
589
  {
590
  //paypal profile stuff
591
+ $nvpStr = "";
592
+ $nvpStr .= "&PROFILEID=" . urlencode($order->subscription_transaction_id) . "&ACTION=Cancel&NOTE=" . urlencode("User requested cancel.");
593
+
594
  $this->httpParsedResponseAr = $this->PPHttpPost('ManageRecurringPaymentsProfileStatus', $nvpStr);
595
+
596
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"]))
597
+ {
598
+ $order->updateStatus("cancelled");
599
+ return true;
600
  }
601
  else
602
+ {
603
  $order->status = "error";
604
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
605
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']) . ". " . __("Please contact the site owner or cancel your subscription from within PayPal to make sure you are not charged going forward.", "pmpro");
606
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
607
+
608
+ return false;
609
  }
610
+ }
611
+
612
  /**
613
  * PAYPAL Function
614
  * Send HTTP POST Request
619
  */
620
  function PPHttpPost($methodName_, $nvpStr_) {
621
  global $gateway_environment;
622
+ $environment = $gateway_environment;
623
+
624
  $API_UserName = pmpro_getOption("apiusername");
625
  $API_Password = pmpro_getOption("apipassword");
626
  $API_Signature = pmpro_getOption("apisignature");
627
  $API_Endpoint = "https://api-3t.paypal.com/nvp";
628
  if("sandbox" === $environment || "beta-sandbox" === $environment) {
629
  $API_Endpoint = "https://api-3t.$environment.paypal.com/nvp";
630
+ }
631
+
632
  $version = urlencode('72.0');
633
+
634
  // setting the curl parameters.
635
  $ch = curl_init();
636
  curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
637
  curl_setopt($ch, CURLOPT_VERBOSE, 1);
638
+
639
  // turning off the server and peer verification(TrustManager Concept).
640
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
641
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
642
+
643
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
644
  curl_setopt($ch, CURLOPT_POST, 1);
645
+
646
  // NVPRequest for submitting to server
647
  $nvpreq = "METHOD=" . urlencode($methodName_) . "&VERSION=" . urlencode($version) . "&PWD=" . urlencode($API_Password) . "&USER=" . urlencode($API_UserName) . "&SIGNATURE=" . urlencode($API_Signature) . "&BUTTONSOURCE=" . urlencode(PAYPAL_BN_CODE) . $nvpStr_;
648
+
649
  // setting the nvpreq as POST FIELD to curl
650
  curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
651
+
652
  // getting response from server
653
  $httpResponse = curl_exec($ch);
654
+
655
  if(empty($httpResponse)) {
656
  exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
657
  }
658
+
659
  // Extract the RefundTransaction response details
660
  $httpResponseAr = explode("&", $httpResponse);
661
+
662
  $httpParsedResponseAr = array();
663
  foreach ($httpResponseAr as $i => $value) {
664
  $tmpAr = explode("=", $value);
666
  $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
667
  }
668
  }
669
+
670
  if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
671
  exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
672
  }
673
+
674
  return $httpParsedResponseAr;
675
  }
676
  }
classes/gateways/class.pmprogateway_paypalexpress.php CHANGED
@@ -1,46 +1,46 @@
1
  <?php
2
  //include pmprogateway
3
  require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
-
5
  //load classes init method
6
  add_action('init', array('PMProGateway_paypalexpress', 'init'));
7
-
8
  class PMProGateway_paypalexpress extends PMProGateway
9
  {
10
  function PMProGateway_paypalexpress($gateway = NULL)
11
  {
12
  $this->gateway = $gateway;
13
  return $this->gateway;
14
- }
15
-
16
  /**
17
  * Run on WP init
18
- *
19
  * @since 1.8
20
  */
21
  static function init()
22
- {
23
  //make sure PayPal Express is a gateway option
24
  add_filter('pmpro_gateways', array('PMProGateway_paypalexpress', 'pmpro_gateways'));
25
-
26
  //add fields to payment settings
27
  add_filter('pmpro_payment_options', array('PMProGateway_paypalexpress', 'pmpro_payment_options'));
28
-
29
  /*
30
  This code is the same for PayPal Website Payments Pro, PayPal Express, and PayPal Standard
31
  So we only load it if we haven't already.
32
  */
33
  global $pmpro_payment_option_fields_for_paypal;
34
  if(empty($pmpro_payment_option_fields_for_paypal))
35
- {
36
- add_filter('pmpro_payment_option_fields', array('PMProGateway_paypalexpress', 'pmpro_payment_option_fields'), 10, 2);
37
  $pmpro_payment_option_fields_for_paypal = true;
38
  }
39
-
40
  //code to add at checkout
41
  $gateway = pmpro_getGateway();
42
  if($gateway == "paypalexpress")
43
- {
44
  add_filter('pmpro_include_billing_address_fields', '__return_false');
45
  add_filter('pmpro_include_payment_information_fields', '__return_false');
46
  add_filter('pmpro_required_billing_fields', array('PMProGateway_paypalexpress', 'pmpro_required_billing_fields'));
@@ -51,27 +51,27 @@
51
  add_action('pmpro_checkout_after_form', array('PMProGateway_paypalexpress', 'pmpro_checkout_after_form'));
52
  }
53
  }
54
-
55
  /**
56
  * Make sure this gateway is in the gateways list
57
- *
58
  * @since 1.8
59
  */
60
  static function pmpro_gateways($gateways)
61
  {
62
  if(empty($gateways['paypalexpress']))
63
  $gateways['paypalexpress'] = __('PayPal Express', 'pmpro');
64
-
65
  return $gateways;
66
  }
67
-
68
  /**
69
  * Get a list of payment options that the this gateway needs/supports.
70
- *
71
  * @since 1.8
72
  */
73
  static function getGatewayOptions()
74
- {
75
  $options = array(
76
  'sslseal',
77
  'nuclear_HTTPS',
@@ -85,29 +85,29 @@
85
  'tax_state',
86
  'tax_rate'
87
  );
88
-
89
  return $options;
90
  }
91
-
92
  /**
93
  * Set payment options for payment settings page.
94
- *
95
  * @since 1.8
96
  */
97
  static function pmpro_payment_options($options)
98
- {
99
  //get stripe options
100
  $paypal_options = PMProGateway_paypalexpress::getGatewayOptions();
101
-
102
  //merge with others.
103
  $options = array_merge($paypal_options, $options);
104
-
105
  return $options;
106
  }
107
-
108
  /**
109
  * Display fields for this gateway's options.
110
- *
111
  * @since 1.8
112
  */
113
  static function pmpro_payment_option_fields($values, $gateway)
@@ -117,20 +117,20 @@
117
  <td colspan="2">
118
  <?php _e('PayPal Settings', 'pmpro'); ?>
119
  </td>
120
- </tr>
121
  <tr class="gateway gateway_paypalstandard" <?php if($gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
122
  <td colspan="2">
123
  <strong><?php _e('Note', 'pmpro');?>:</strong> <?php _e('We do not recommend using PayPal Standard. We suggest using PayPal Express, Website Payments Pro (Legacy), or PayPal Pro (Payflow Pro). <a target="_blank" href="http://www.paidmembershipspro.com/2013/09/read-using-paypal-standard-paid-memberships-pro/">More information on why can be found here.</a>', 'pmpro');?>
124
- </td>
125
- </tr>
126
  <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
127
- <th scope="row" valign="top">
128
  <label for="gateway_email"><?php _e('Gateway Account Email', 'pmpro');?>:</label>
129
  </th>
130
  <td>
131
  <input type="text" id="gateway_email" name="gateway_email" size="60" value="<?php echo esc_attr($values['gateway_email'])?>" />
132
  </td>
133
- </tr>
134
  <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
135
  <th scope="row" valign="top">
136
  <label for="apiusername"><?php _e('API Username', 'pmpro');?>:</label>
@@ -146,7 +146,7 @@
146
  <td>
147
  <input type="text" id="apipassword" name="apipassword" size="60" value="<?php echo esc_attr($values['apipassword'])?>" />
148
  </td>
149
- </tr>
150
  <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
151
  <th scope="row" valign="top">
152
  <label for="apisignature"><?php _e('API Signature', 'pmpro');?>:</label>
@@ -154,7 +154,7 @@
154
  <td>
155
  <input type="text" id="apisignature" name="apisignature" size="60" value="<?php echo esc_attr($values['apisignature'])?>" />
156
  </td>
157
- </tr>
158
  <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
159
  <th scope="row" valign="top">
160
  <label><?php _e('IPN Handler URL', 'pmpro');?>:</label>
@@ -165,10 +165,10 @@
165
  </tr>
166
  <?php
167
  }
168
-
169
  /**
170
  * Remove required billing fields
171
- *
172
  * @since 1.8
173
  */
174
  static function pmpro_required_billing_fields($fields)
@@ -187,10 +187,10 @@
187
  unset($fields['ExpirationMonth']);
188
  unset($fields['ExpirationYear']);
189
  unset($fields['CVV']);
190
-
191
  return $fields;
192
  }
193
-
194
  /**
195
  * Save session vars before processing
196
  *
@@ -199,8 +199,8 @@
199
  static function pmpro_checkout_before_processing()
200
  {
201
  global $current_user, $gateway;
202
-
203
- //save user fields for PayPal Express
204
  if(!$current_user->ID)
205
  {
206
  //get values from post
@@ -213,32 +213,32 @@
213
  else
214
  $password = "";
215
  if(isset($_REQUEST['bemail']))
216
- $bemail = $_REQUEST['bemail'];
217
  else
218
  $bemail = "";
219
-
220
  //save to session
221
  $_SESSION['pmpro_signup_username'] = $username;
222
  $_SESSION['pmpro_signup_password'] = $password;
223
- $_SESSION['pmpro_signup_email'] = $bemail;
224
  }
225
-
226
  //can use this hook to save some other variables to the session
227
  do_action("pmpro_paypalexpress_session_vars");
228
  }
229
-
230
  /**
231
  * Review and Confirmation code.
232
  *
233
- * @since 1.8
234
  */
235
  static function pmpro_checkout_confirmed($pmpro_confirmed)
236
  {
237
  global $pmpro_msg, $pmpro_msgt, $pmpro_level, $current_user, $pmpro_review, $pmpro_paypal_token, $discount_code, $bemail;
238
-
239
  //PayPal Express Call Backs
240
  if(!empty($_REQUEST['review']))
241
- {
242
  if(!empty($_REQUEST['PayerID']))
243
  $_SESSION['payer_id'] = $_REQUEST['PayerID'];
244
  if(!empty($_REQUEST['paymentAmount']))
@@ -247,10 +247,10 @@
247
  $_SESSION['currCodeType'] = $_REQUEST['currencyCodeType'];
248
  if(!empty($_REQUEST['paymentType']))
249
  $_SESSION['paymentType'] = $_REQUEST['paymentType'];
250
-
251
  $morder = new MemberOrder();
252
  $morder->getMemberOrderByPayPalToken($_REQUEST['token']);
253
- $morder->Token = $morder->paypal_token; $pmpro_paypal_token = $morder->paypal_token;
254
  if($morder->Token)
255
  {
256
  if($morder->Gateway->getExpressCheckoutDetails($morder))
@@ -261,7 +261,7 @@
261
  {
262
  $pmpro_msg = $morder->error;
263
  $pmpro_msgt = "pmpro_error";
264
- }
265
  }
266
  else
267
  {
@@ -270,12 +270,12 @@
270
  }
271
  }
272
  elseif(!empty($_REQUEST['confirm']))
273
- {
274
  $morder = new MemberOrder();
275
  $morder->getMemberOrderByPayPalToken($_REQUEST['token']);
276
- $morder->Token = $morder->paypal_token; $pmpro_paypal_token = $morder->paypal_token;
277
  if($morder->Token)
278
- {
279
  //setup values
280
  $morder->membership_id = $pmpro_level->id;
281
  $morder->membership_name = $pmpro_level->name;
@@ -286,17 +286,17 @@
286
  $morder->BillingPeriod = $pmpro_level->cycle_period;
287
  $morder->BillingFrequency = $pmpro_level->cycle_number;
288
  $morder->Email = $bemail;
289
-
290
  //setup level var
291
- $morder->getMembershipLevel();
292
  $morder->membership_level = apply_filters("pmpro_checkout_level", $morder->membership_level);
293
-
294
  //tax
295
  $morder->subtotal = $morder->InitialPayment;
296
- $morder->getTax();
297
  if($pmpro_level->billing_limit)
298
  $morder->TotalBillingCycles = $pmpro_level->billing_limit;
299
-
300
  if(pmpro_isLevelTrial($pmpro_level))
301
  {
302
  $morder->TrialBillingPeriod = $pmpro_level->cycle_period;
@@ -304,13 +304,13 @@
304
  $morder->TrialBillingCycles = $pmpro_level->trial_limit;
305
  $morder->TrialAmount = $pmpro_level->trial_amount;
306
  }
307
-
308
  if($morder->confirm())
309
- {
310
- $pmpro_confirmed = true;
311
  }
312
  else
313
- {
314
  $pmpro_msg = $morder->error;
315
  $pmpro_msgt = "pmpro_error";
316
  }
@@ -321,38 +321,38 @@
321
  $pmpro_msgt = "pmpro_error";
322
  }
323
  }
324
-
325
  if(!empty($morder))
326
  return array("pmpro_confirmed"=>$pmpro_confirmed, "morder"=>$morder);
327
  else
328
  return $pmpro_confirmed;
329
  }
330
-
331
  /**
332
  * Swap in user/pass/etc from session
333
  *
334
- * @since 1.8
335
  */
336
  static function pmpro_checkout_new_user_array($new_user_array)
337
  {
338
  global $current_user;
339
-
340
  if(!$current_user->ID)
341
  {
342
- //reload the user fields
343
  $new_user_array['user_login'] = $_SESSION['pmpro_signup_username'];
344
- $new_user_array['user_pass'] = $_SESSION['pmpro_signup_password'];
345
  $new_user_array['user_email'] = $_SESSION['pmpro_signup_email'];
346
-
347
  //unset the user fields in session
348
  unset($_SESSION['pmpro_signup_username']);
349
  unset($_SESSION['pmpro_signup_password']);
350
  unset($_SESSION['pmpro_signup_email']);
351
  }
352
-
353
  return $new_user_array;
354
  }
355
-
356
  /**
357
  * Process at checkout
358
  *
@@ -363,28 +363,28 @@
363
  $order->payment_type = "PayPal Express";
364
  $order->cardtype = "";
365
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod)) . "T0:0:0";
366
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
367
-
368
  return $this->setExpressCheckout($order);
369
  }
370
-
371
  /**
372
  * Process charge or subscription after confirmation.
373
  *
374
  * @since 1.8
375
  */
376
  function confirm(&$order)
377
- {
378
  if(pmpro_isLevelRecurring($order->membership_level))
379
  {
380
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
381
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
382
- return $this->subscribe($order);
383
  }
384
  else
385
- return $this->charge($order);
386
  }
387
-
388
  /**
389
  * Swap in our submit buttons.
390
  *
@@ -393,26 +393,26 @@
393
  static function pmpro_checkout_default_submit_button($show)
394
  {
395
  global $gateway, $pmpro_requirebilling;
396
-
397
  //show our submit buttons
398
  ?>
399
  <?php if($gateway == "paypal" || $gateway == "paypalexpress" || $gateway == "paypalstandard") { ?>
400
  <span id="pmpro_paypalexpress_checkout" <?php if(($gateway != "paypalexpress" && $gateway != "paypalstandard") || !$pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
401
- <input type="hidden" name="submit-checkout" value="1" />
402
  <input type="image" value="<?php _e('Check Out with PayPal', 'pmpro');?> &raquo;" src="<?php echo apply_filters("pmpro_paypal_button_image", "https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif");?>" />
403
  </span>
404
  <?php } ?>
405
-
406
  <span id="pmpro_submit_span" <?php if(($gateway == "paypalexpress" || $gateway == "paypalstandard") && $pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
407
- <input type="hidden" name="submit-checkout" value="1" />
408
- <input type="submit" class="pmpro_btn pmpro_btn-submit-checkout" value="<?php if($pmpro_requirebilling) { _e('Submit and Check Out', 'pmpro'); } else { _e('Submit and Confirm', 'pmpro');}?> &raquo;" />
409
  </span>
410
  <?php
411
-
412
  //don't show the default
413
  return false;
414
  }
415
-
416
  /**
417
  * Scripts for checkout page.
418
  *
@@ -421,25 +421,25 @@
421
  static function pmpro_checkout_after_form()
422
  {
423
  ?>
424
- <script>
425
  //choosing payment method
426
- jQuery('input[name=gateway]').click(function() {
427
  if(jQuery(this).val() == 'paypal')
428
  {
429
  jQuery('#pmpro_paypalexpress_checkout').hide();
430
  jQuery('#pmpro_billing_address_fields').show();
431
- jQuery('#pmpro_payment_information_fields').show();
432
  jQuery('#pmpro_submit_span').show();
433
  }
434
  else
435
- {
436
  jQuery('#pmpro_billing_address_fields').hide();
437
- jQuery('#pmpro_payment_information_fields').hide();
438
  jQuery('#pmpro_submit_span').hide();
439
  jQuery('#pmpro_paypalexpress_checkout').show();
440
  }
441
  });
442
-
443
  //select the radio button if the label is clicked on
444
  jQuery('a.pmpro_radio').click(function() {
445
  jQuery(this).prev().click();
@@ -447,106 +447,106 @@
447
  </script>
448
  <?php
449
  }
450
-
451
  //PayPal Express, this is run first to authorize from PayPal
452
  function setExpressCheckout(&$order)
453
- {
454
  global $pmpro_currency;
455
-
456
  if(empty($order->code))
457
- $order->code = $order->getRandomCode();
458
-
459
  //clean up a couple values
460
  $order->payment_type = "PayPal Express";
461
  $order->CardType = "";
462
  $order->cardtype = "";
463
-
464
  //taxes on initial amount
465
  $initial_payment = $order->InitialPayment;
466
  $initial_payment_tax = $order->getTaxForPrice($initial_payment);
467
  $initial_payment = round((float)$initial_payment + (float)$initial_payment_tax, 2);
468
-
469
  //taxes on the amount
470
  $amount = $order->PaymentAmount;
471
- $amount_tax = $order->getTaxForPrice($amount);
472
  $amount = round((float)$amount + (float)$amount_tax, 2);
473
-
474
  //paypal profile stuff
475
  $nvpStr = "";
476
  $nvpStr .="&AMT=" . $initial_payment . "&CURRENCYCODE=" . $pmpro_currency;
477
  if(!empty($order->ProfileStartDate) && strtotime($order->ProfileStartDate, current_time("timestamp")) > 0)
478
- $nvpStr .= "&PROFILESTARTDATE=" . $order->ProfileStartDate;
479
  if(!empty($order->BillingFrequency))
480
  $nvpStr .= "&BILLINGPERIOD=" . $order->BillingPeriod . "&BILLINGFREQUENCY=" . $order->BillingFrequency . "&AUTOBILLAMT=AddToNextBilling&L_BILLINGTYPE0=RecurringPayments";
481
  $nvpStr .= "&DESC=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
482
- $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
483
  $nvpStr .= "&NOSHIPPING=1&L_BILLINGAGREEMENTDESCRIPTION0=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127)) . "&L_PAYMENTTYPE0=Any";
484
-
485
- //if billing cycles are defined
486
  if(!empty($order->TotalBillingCycles))
487
  $nvpStr .= "&TOTALBILLINGCYCLES=" . $order->TotalBillingCycles;
488
-
489
  //if a trial period is defined
490
  if(!empty($order->TrialBillingPeriod))
491
  {
492
  $trial_amount = $order->TrialAmount;
493
  $trial_tax = $order->getTaxForPrice($trial_amount);
494
  $trial_amount = round((float)$trial_amount + (float)$trial_tax, 2);
495
-
496
  $nvpStr .= "&TRIALBILLINGPERIOD=" . $order->TrialBillingPeriod . "&TRIALBILLINGFREQUENCY=" . $order->TrialBillingFrequency . "&TRIALAMT=" . $trial_amount;
497
  }
498
  if(!empty($order->TrialBillingCycles))
499
  $nvpStr .= "&TRIALTOTALBILLINGCYCLES=" . $order->TrialBillingCycles;
500
-
501
  if(!empty($order->discount_code))
502
  {
503
- $nvpStr .= "&ReturnUrl=" . urlencode(pmpro_url("checkout", "?level=" . $order->membership_level->id . "&discount_code=" . $order->discount_code . "&review=" . $order->code));
504
  }
505
  else
506
  {
507
- $nvpStr .= "&ReturnUrl=" . urlencode(pmpro_url("checkout", "?level=" . $order->membership_level->id . "&review=" . $order->code));
508
  }
509
-
510
- $additional_parameters = apply_filters("pmpro_paypal_express_return_url_parameters", array());
511
  if(!empty($additional_parameters))
512
  {
513
- foreach($additional_parameters as $key => $value)
514
  $nvpStr .= urlencode("&" . $key . "=" . $value);
515
- }
516
-
517
- $nvpStr .= "&CANCELURL=" . urlencode(pmpro_url("levels"));
518
-
519
  $account_optional = apply_filters('pmpro_paypal_account_optional', true);
520
  if ($account_optional)
521
  $nvpStr .= '&SOLUTIONTYPE=Sole&LANDINGPAGE=Billing';
522
-
523
- $nvpStr = apply_filters("pmpro_set_express_checkout_nvpstr", $nvpStr, $order);
524
-
525
  ///echo str_replace("&", "&<br />", $nvpStr);
526
  ///exit;
527
-
528
- $this->httpParsedResponseAr = $this->PPHttpPost('SetExpressCheckout', $nvpStr);
529
-
530
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
531
- $order->status = "token";
532
- $order->paypal_token = urldecode($this->httpParsedResponseAr['TOKEN']);
533
-
534
  //update order
535
- $order->saveOrder();
536
-
537
  //redirect to paypal
538
  $paypal_url = "https://www.paypal.com/webscr&cmd=_express-checkout&useraction=commit&token=" . $this->httpParsedResponseAr['TOKEN'];
539
- $environment = pmpro_getOption("gateway_environment");
540
- if("sandbox" === $environment || "beta-sandbox" === $environment)
541
  {
542
  $paypal_url = "https://www.sandbox.paypal.com/webscr&useraction=commit&cmd=_express-checkout&token=" . $this->httpParsedResponseAr['TOKEN'];
543
- }
544
-
545
- wp_redirect($paypal_url);
546
  exit;
547
-
548
  //exit('SetExpressCheckout Completed Successfully: '.print_r($this->httpParsedResponseAr, true));
549
- } else {
550
  $order->status = "error";
551
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
552
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
@@ -554,32 +554,32 @@
554
  return false;
555
  //exit('SetExpressCheckout failed: ' . print_r($httpParsedResponseAr, true));
556
  }
557
-
558
  //write session?
559
-
560
  //redirect to PayPal
561
  }
562
-
563
  function getExpressCheckoutDetails(&$order)
564
- {
565
  $nvpStr="&TOKEN=".$order->Token;
566
-
567
  $nvpStr = apply_filters("pmpro_get_express_checkout_details_nvpstr", $nvpStr, $order);
568
-
569
  /* Make the API call and store the results in an array. If the
570
  call was a success, show the authorization details, and provide
571
  an action to complete the payment. If failed, show the error
572
  */
573
  $this->httpParsedResponseAr = $this->PPHttpPost('GetExpressCheckoutDetails', $nvpStr);
574
-
575
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
576
- $order->status = "review";
577
-
578
  //update order
579
- $order->saveOrder();
580
-
581
- return true;
582
- } else {
583
  $order->status = "error";
584
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
585
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
@@ -588,20 +588,20 @@
588
  //exit('SetExpressCheckout failed: ' . print_r($httpParsedResponseAr, true));
589
  }
590
  }
591
-
592
  function charge(&$order)
593
  {
594
  global $pmpro_currency;
595
-
596
  if(empty($order->code))
597
- $order->code = $order->getRandomCode();
598
-
599
  //taxes on the amount
600
  $amount = $order->InitialPayment;
601
- $amount_tax = $order->getTaxForPrice($amount);
602
  $order->subtotal = $amount;
603
  $amount = round((float)$amount + (float)$amount_tax, 2);
604
-
605
  //paypal profile stuff
606
  $nvpStr = "";
607
  if(!empty($order->Token))
@@ -612,28 +612,28 @@
612
  $nvpStr .= "&TAXAMT=" . $amount_tax;
613
  */
614
  if(!empty($order->BillingFrequency))
615
- $nvpStr .= "&BILLINGPERIOD=" . $order->BillingPeriod . "&BILLINGFREQUENCY=" . $order->BillingFrequency . "&AUTOBILLAMT=AddToNextBilling";
616
  $nvpStr .= "&DESC=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
617
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
618
  $nvpStr .= "&NOSHIPPING=1";
619
-
620
- $nvpStr .= "&PAYERID=" . $_SESSION['payer_id'] . "&PAYMENTACTION=sale";
621
-
622
  $nvpStr = apply_filters("pmpro_do_express_checkout_payment_nvpstr", $nvpStr, $order);
623
-
624
  $order->nvpStr = $nvpStr;
625
-
626
  $this->httpParsedResponseAr = $this->PPHttpPost('DoExpressCheckoutPayment', $nvpStr);
627
-
628
- if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
629
- $order->payment_transaction_id = urldecode($this->httpParsedResponseAr['TRANSACTIONID']);
630
- $order->status = "success";
631
 
632
  //update order
633
- $order->saveOrder();
634
-
635
- return true;
636
- } else {
637
  $order->status = "error";
638
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
639
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
@@ -642,136 +642,136 @@
642
  //exit('SetExpressCheckout failed: ' . print_r($httpParsedResponseAr, true));
643
  }
644
  }
645
-
646
  function subscribe(&$order)
647
- {
648
  global $pmpro_currency;
649
-
650
  if(empty($order->code))
651
- $order->code = $order->getRandomCode();
652
 
653
  //filter order before subscription. use with care.
654
  $order = apply_filters("pmpro_subscribe_order", $order, $this);
655
-
656
  //taxes on initial amount
657
  $initial_payment = $order->InitialPayment;
658
  $initial_payment_tax = $order->getTaxForPrice($initial_payment);
659
  $initial_payment = round((float)$initial_payment + (float)$initial_payment_tax, 2);
660
-
661
  //taxes on the amount
662
  $amount = $order->PaymentAmount;
663
- $amount_tax = $order->getTaxForPrice($amount);
664
  //$amount = round((float)$amount + (float)$amount_tax, 2);
665
-
666
  //paypal profile stuff
667
  $nvpStr = "";
668
  if(!empty($order->Token))
669
- $nvpStr .= "&TOKEN=" . $order->Token;
670
  $nvpStr .="&INITAMT=" . $initial_payment . "&AMT=" . $amount . "&CURRENCYCODE=" . $pmpro_currency . "&PROFILESTARTDATE=" . $order->ProfileStartDate;
671
  if(!empty($amount_tax))
672
  $nvpStr .= "&TAXAMT=" . $amount_tax;
673
- $nvpStr .= "&BILLINGPERIOD=" . $order->BillingPeriod . "&BILLINGFREQUENCY=" . $order->BillingFrequency . "&AUTOBILLAMT=AddToNextBilling";
674
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
675
  $nvpStr .= "&DESC=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
676
-
677
- //if billing cycles are defined
678
  if(!empty($order->TotalBillingCycles))
679
  $nvpStr .= "&TOTALBILLINGCYCLES=" . $order->TotalBillingCycles;
680
-
681
  //if a trial period is defined
682
  if(!empty($order->TrialBillingPeriod))
683
  {
684
  $trial_amount = $order->TrialAmount;
685
  $trial_tax = $order->getTaxForPrice($trial_amount);
686
  $trial_amount = round((float)$trial_amount + (float)$trial_tax, 2);
687
-
688
  $nvpStr .= "&TRIALBILLINGPERIOD=" . $order->TrialBillingPeriod . "&TRIALBILLINGFREQUENCY=" . $order->TrialBillingFrequency . "&TRIALAMT=" . $trial_amount;
689
  }
690
  if(!empty($order->TrialBillingCycles))
691
  $nvpStr .= "&TRIALTOTALBILLINGCYCLES=" . $order->TrialBillingCycles;
692
-
693
  $nvpStr = apply_filters("pmpro_create_recurring_payments_profile_nvpstr", $nvpStr, $order);
694
-
695
- $this->nvpStr = $nvpStr;
696
-
697
  ///echo str_replace("&", "&<br />", $nvpStr);
698
  ///exit;
699
-
700
  $this->httpParsedResponseAr = $this->PPHttpPost('CreateRecurringPaymentsProfile', $nvpStr);
701
-
702
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
703
- $order->status = "success";
704
  $order->payment_transaction_id = urldecode($this->httpParsedResponseAr['PROFILEID']);
705
  $order->subscription_transaction_id = urldecode($this->httpParsedResponseAr['PROFILEID']);
706
-
707
  //update order
708
- $order->saveOrder();
709
-
710
- return true;
711
- } else {
712
  $order->status = "error";
713
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
714
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
715
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
716
-
717
- return false;
718
  }
719
  }
720
-
721
  function cancel(&$order)
722
- {
723
  //paypal profile stuff
724
- $nvpStr = "";
725
- $nvpStr .= "&PROFILEID=" . urlencode($order->subscription_transaction_id) . "&ACTION=Cancel&NOTE=" . urlencode("User requested cancel.");
726
-
727
  $nvpStr = apply_filters("pmpro_manage_recurring_payments_profile_status_nvpstr", $nvpStr, $order);
728
-
729
- $this->httpParsedResponseAr = $this->PPHttpPost('ManageRecurringPaymentsProfileStatus', $nvpStr);
730
-
731
- if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"]))
732
- {
733
- $order->updateStatus("cancelled");
734
- return true;
735
- }
736
- else
737
  {
738
  $order->status = "error";
739
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
740
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']) . ". " . __("Please contact the site owner or cancel your subscription from within PayPal to make sure you are not charged going forward.", "pmpro");
741
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
742
-
743
- return false;
744
  }
745
  }
746
 
747
  function getSubscriptionStatus(&$order)
748
- {
749
  if(empty($order->subscription_transaction_id))
750
  return false;
751
-
752
  //paypal profile stuff
753
- $nvpStr = "";
754
- $nvpStr .= "&PROFILEID=" . urlencode($order->subscription_transaction_id);
755
-
756
  $nvpStr = apply_filters("pmpro_get_recurring_payments_profile_details_nvpstr", $nvpStr, $order);
757
-
758
- $this->httpParsedResponseAr = $this->PPHttpPost('GetRecurringPaymentsProfileDetails', $nvpStr);
759
-
760
- if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"]))
761
- {
762
- return $this->httpParsedResponseAr;
763
- }
764
- else
765
  {
766
  $order->status = "error";
767
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
768
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
769
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
770
-
771
- return false;
772
  }
773
- }
774
-
775
  /**
776
  * PAYPAL Function
777
  * Send HTTP POST Request
@@ -782,46 +782,46 @@
782
  */
783
  function PPHttpPost($methodName_, $nvpStr_) {
784
  global $gateway_environment;
785
- $environment = $gateway_environment;
786
-
787
  $API_UserName = pmpro_getOption("apiusername");
788
  $API_Password = pmpro_getOption("apipassword");
789
  $API_Signature = pmpro_getOption("apisignature");
790
  $API_Endpoint = "https://api-3t.paypal.com/nvp";
791
  if("sandbox" === $environment || "beta-sandbox" === $environment) {
792
  $API_Endpoint = "https://api-3t.$environment.paypal.com/nvp";
793
- }
794
-
795
  $version = urlencode('72.0');
796
-
797
  // setting the curl parameters.
798
  $ch = curl_init();
799
  curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
800
  curl_setopt($ch, CURLOPT_VERBOSE, 1);
801
-
802
  // turning off the server and peer verification(TrustManager Concept).
803
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
804
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
805
-
806
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
807
  curl_setopt($ch, CURLOPT_POST, 1);
808
-
809
  // NVPRequest for submitting to server
810
  $nvpreq = "METHOD=" . urlencode($methodName_) . "&VERSION=" . urlencode($version) . "&PWD=" . urlencode($API_Password) . "&USER=" . urlencode($API_UserName) . "&SIGNATURE=" . urlencode($API_Signature) . "&BUTTONSOURCE=" . urlencode(PAYPAL_BN_CODE) . $nvpStr_;
811
-
812
  // setting the nvpreq as POST FIELD to curl
813
  curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
814
-
815
  // getting response from server
816
  $httpResponse = curl_exec($ch);
817
-
818
  if(!$httpResponse) {
819
  exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
820
  }
821
-
822
  // Extract the RefundTransaction response details
823
  $httpResponseAr = explode("&", $httpResponse);
824
-
825
  $httpParsedResponseAr = array();
826
  foreach ($httpResponseAr as $i => $value) {
827
  $tmpAr = explode("=", $value);
@@ -829,11 +829,11 @@
829
  $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
830
  }
831
  }
832
-
833
  if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
834
  exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
835
  }
836
-
837
  return $httpParsedResponseAr;
838
  }
839
  }
1
  <?php
2
  //include pmprogateway
3
  require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
+
5
  //load classes init method
6
  add_action('init', array('PMProGateway_paypalexpress', 'init'));
7
+
8
  class PMProGateway_paypalexpress extends PMProGateway
9
  {
10
  function PMProGateway_paypalexpress($gateway = NULL)
11
  {
12
  $this->gateway = $gateway;
13
  return $this->gateway;
14
+ }
15
+
16
  /**
17
  * Run on WP init
18
+ *
19
  * @since 1.8
20
  */
21
  static function init()
22
+ {
23
  //make sure PayPal Express is a gateway option
24
  add_filter('pmpro_gateways', array('PMProGateway_paypalexpress', 'pmpro_gateways'));
25
+
26
  //add fields to payment settings
27
  add_filter('pmpro_payment_options', array('PMProGateway_paypalexpress', 'pmpro_payment_options'));
28
+
29
  /*
30
  This code is the same for PayPal Website Payments Pro, PayPal Express, and PayPal Standard
31
  So we only load it if we haven't already.
32
  */
33
  global $pmpro_payment_option_fields_for_paypal;
34
  if(empty($pmpro_payment_option_fields_for_paypal))
35
+ {
36
+ add_filter('pmpro_payment_option_fields', array('PMProGateway_paypalexpress', 'pmpro_payment_option_fields'), 10, 2);
37
  $pmpro_payment_option_fields_for_paypal = true;
38
  }
39
+
40
  //code to add at checkout
41
  $gateway = pmpro_getGateway();
42
  if($gateway == "paypalexpress")
43
+ {
44
  add_filter('pmpro_include_billing_address_fields', '__return_false');
45
  add_filter('pmpro_include_payment_information_fields', '__return_false');
46
  add_filter('pmpro_required_billing_fields', array('PMProGateway_paypalexpress', 'pmpro_required_billing_fields'));
51
  add_action('pmpro_checkout_after_form', array('PMProGateway_paypalexpress', 'pmpro_checkout_after_form'));
52
  }
53
  }
54
+
55
  /**
56
  * Make sure this gateway is in the gateways list
57
+ *
58
  * @since 1.8
59
  */
60
  static function pmpro_gateways($gateways)
61
  {
62
  if(empty($gateways['paypalexpress']))
63
  $gateways['paypalexpress'] = __('PayPal Express', 'pmpro');
64
+
65
  return $gateways;
66
  }
67
+
68
  /**
69
  * Get a list of payment options that the this gateway needs/supports.
70
+ *
71
  * @since 1.8
72
  */
73
  static function getGatewayOptions()
74
+ {
75
  $options = array(
76
  'sslseal',
77
  'nuclear_HTTPS',
85
  'tax_state',
86
  'tax_rate'
87
  );
88
+
89
  return $options;
90
  }
91
+
92
  /**
93
  * Set payment options for payment settings page.
94
+ *
95
  * @since 1.8
96
  */
97
  static function pmpro_payment_options($options)
98
+ {
99
  //get stripe options
100
  $paypal_options = PMProGateway_paypalexpress::getGatewayOptions();
101
+
102
  //merge with others.
103
  $options = array_merge($paypal_options, $options);
104
+
105
  return $options;
106
  }
107
+
108
  /**
109
  * Display fields for this gateway's options.
110
+ *
111
  * @since 1.8
112
  */
113
  static function pmpro_payment_option_fields($values, $gateway)
117
  <td colspan="2">
118
  <?php _e('PayPal Settings', 'pmpro'); ?>
119
  </td>
120
+ </tr>
121
  <tr class="gateway gateway_paypalstandard" <?php if($gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
122
  <td colspan="2">
123
  <strong><?php _e('Note', 'pmpro');?>:</strong> <?php _e('We do not recommend using PayPal Standard. We suggest using PayPal Express, Website Payments Pro (Legacy), or PayPal Pro (Payflow Pro). <a target="_blank" href="http://www.paidmembershipspro.com/2013/09/read-using-paypal-standard-paid-memberships-pro/">More information on why can be found here.</a>', 'pmpro');?>
124
+ </td>
125
+ </tr>
126
  <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
127
+ <th scope="row" valign="top">
128
  <label for="gateway_email"><?php _e('Gateway Account Email', 'pmpro');?>:</label>
129
  </th>
130
  <td>
131
  <input type="text" id="gateway_email" name="gateway_email" size="60" value="<?php echo esc_attr($values['gateway_email'])?>" />
132
  </td>
133
+ </tr>
134
  <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
135
  <th scope="row" valign="top">
136
  <label for="apiusername"><?php _e('API Username', 'pmpro');?>:</label>
146
  <td>
147
  <input type="text" id="apipassword" name="apipassword" size="60" value="<?php echo esc_attr($values['apipassword'])?>" />
148
  </td>
149
+ </tr>
150
  <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
151
  <th scope="row" valign="top">
152
  <label for="apisignature"><?php _e('API Signature', 'pmpro');?>:</label>
154
  <td>
155
  <input type="text" id="apisignature" name="apisignature" size="60" value="<?php echo esc_attr($values['apisignature'])?>" />
156
  </td>
157
+ </tr>
158
  <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
159
  <th scope="row" valign="top">
160
  <label><?php _e('IPN Handler URL', 'pmpro');?>:</label>
165
  </tr>
166
  <?php
167
  }
168
+
169
  /**
170
  * Remove required billing fields
171
+ *
172
  * @since 1.8
173
  */
174
  static function pmpro_required_billing_fields($fields)
187
  unset($fields['ExpirationMonth']);
188
  unset($fields['ExpirationYear']);
189
  unset($fields['CVV']);
190
+
191
  return $fields;
192
  }
193
+
194
  /**
195
  * Save session vars before processing
196
  *
199
  static function pmpro_checkout_before_processing()
200
  {
201
  global $current_user, $gateway;
202
+
203
+ //save user fields for PayPal Express
204
  if(!$current_user->ID)
205
  {
206
  //get values from post
213
  else
214
  $password = "";
215
  if(isset($_REQUEST['bemail']))
216
+ $bemail = $_REQUEST['bemail'];
217
  else
218
  $bemail = "";
219
+
220
  //save to session
221
  $_SESSION['pmpro_signup_username'] = $username;
222
  $_SESSION['pmpro_signup_password'] = $password;
223
+ $_SESSION['pmpro_signup_email'] = $bemail;
224
  }
225
+
226
  //can use this hook to save some other variables to the session
227
  do_action("pmpro_paypalexpress_session_vars");
228
  }
229
+
230
  /**
231
  * Review and Confirmation code.
232
  *
233
+ * @since 1.8
234
  */
235
  static function pmpro_checkout_confirmed($pmpro_confirmed)
236
  {
237
  global $pmpro_msg, $pmpro_msgt, $pmpro_level, $current_user, $pmpro_review, $pmpro_paypal_token, $discount_code, $bemail;
238
+
239
  //PayPal Express Call Backs
240
  if(!empty($_REQUEST['review']))
241
+ {
242
  if(!empty($_REQUEST['PayerID']))
243
  $_SESSION['payer_id'] = $_REQUEST['PayerID'];
244
  if(!empty($_REQUEST['paymentAmount']))
247
  $_SESSION['currCodeType'] = $_REQUEST['currencyCodeType'];
248
  if(!empty($_REQUEST['paymentType']))
249
  $_SESSION['paymentType'] = $_REQUEST['paymentType'];
250
+
251
  $morder = new MemberOrder();
252
  $morder->getMemberOrderByPayPalToken($_REQUEST['token']);
253
+ $morder->Token = $morder->paypal_token; $pmpro_paypal_token = $morder->paypal_token;
254
  if($morder->Token)
255
  {
256
  if($morder->Gateway->getExpressCheckoutDetails($morder))
261
  {
262
  $pmpro_msg = $morder->error;
263
  $pmpro_msgt = "pmpro_error";
264
+ }
265
  }
266
  else
267
  {
270
  }
271
  }
272
  elseif(!empty($_REQUEST['confirm']))
273
+ {
274
  $morder = new MemberOrder();
275
  $morder->getMemberOrderByPayPalToken($_REQUEST['token']);
276
+ $morder->Token = $morder->paypal_token; $pmpro_paypal_token = $morder->paypal_token;
277
  if($morder->Token)
278
+ {
279
  //setup values
280
  $morder->membership_id = $pmpro_level->id;
281
  $morder->membership_name = $pmpro_level->name;
286
  $morder->BillingPeriod = $pmpro_level->cycle_period;
287
  $morder->BillingFrequency = $pmpro_level->cycle_number;
288
  $morder->Email = $bemail;
289
+
290
  //setup level var
291
+ $morder->getMembershipLevel();
292
  $morder->membership_level = apply_filters("pmpro_checkout_level", $morder->membership_level);
293
+
294
  //tax
295
  $morder->subtotal = $morder->InitialPayment;
296
+ $morder->getTax();
297
  if($pmpro_level->billing_limit)
298
  $morder->TotalBillingCycles = $pmpro_level->billing_limit;
299
+
300
  if(pmpro_isLevelTrial($pmpro_level))
301
  {
302
  $morder->TrialBillingPeriod = $pmpro_level->cycle_period;
304
  $morder->TrialBillingCycles = $pmpro_level->trial_limit;
305
  $morder->TrialAmount = $pmpro_level->trial_amount;
306
  }
307
+
308
  if($morder->confirm())
309
+ {
310
+ $pmpro_confirmed = true;
311
  }
312
  else
313
+ {
314
  $pmpro_msg = $morder->error;
315
  $pmpro_msgt = "pmpro_error";
316
  }
321
  $pmpro_msgt = "pmpro_error";
322
  }
323
  }
324
+
325
  if(!empty($morder))
326
  return array("pmpro_confirmed"=>$pmpro_confirmed, "morder"=>$morder);
327
  else
328
  return $pmpro_confirmed;
329
  }
330
+
331
  /**
332
  * Swap in user/pass/etc from session
333
  *
334
+ * @since 1.8
335
  */
336
  static function pmpro_checkout_new_user_array($new_user_array)
337
  {
338
  global $current_user;
339
+
340
  if(!$current_user->ID)
341
  {
342
+ //reload the user fields
343
  $new_user_array['user_login'] = $_SESSION['pmpro_signup_username'];
344
+ $new_user_array['user_pass'] = $_SESSION['pmpro_signup_password'];
345
  $new_user_array['user_email'] = $_SESSION['pmpro_signup_email'];
346
+
347
  //unset the user fields in session
348
  unset($_SESSION['pmpro_signup_username']);
349
  unset($_SESSION['pmpro_signup_password']);
350
  unset($_SESSION['pmpro_signup_email']);
351
  }
352
+
353
  return $new_user_array;
354
  }
355
+
356
  /**
357
  * Process at checkout
358
  *
363
  $order->payment_type = "PayPal Express";
364
  $order->cardtype = "";
365
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod)) . "T0:0:0";
366
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
367
+
368
  return $this->setExpressCheckout($order);
369
  }
370
+
371
  /**
372
  * Process charge or subscription after confirmation.
373
  *
374
  * @since 1.8
375
  */
376
  function confirm(&$order)
377
+ {
378
  if(pmpro_isLevelRecurring($order->membership_level))
379
  {
380
  $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
381
  $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
382
+ return $this->subscribe($order);
383
  }
384
  else
385
+ return $this->charge($order);
386
  }
387
+
388
  /**
389
  * Swap in our submit buttons.
390
  *
393
  static function pmpro_checkout_default_submit_button($show)
394
  {
395
  global $gateway, $pmpro_requirebilling;
396
+
397
  //show our submit buttons
398
  ?>
399
  <?php if($gateway == "paypal" || $gateway == "paypalexpress" || $gateway == "paypalstandard") { ?>
400
  <span id="pmpro_paypalexpress_checkout" <?php if(($gateway != "paypalexpress" && $gateway != "paypalstandard") || !$pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
401
+ <input type="hidden" name="submit-checkout" value="1" />
402
  <input type="image" value="<?php _e('Check Out with PayPal', 'pmpro');?> &raquo;" src="<?php echo apply_filters("pmpro_paypal_button_image", "https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif");?>" />
403
  </span>
404
  <?php } ?>
405
+
406
  <span id="pmpro_submit_span" <?php if(($gateway == "paypalexpress" || $gateway == "paypalstandard") && $pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
407
+ <input type="hidden" name="submit-checkout" value="1" />
408
+ <input type="submit" class="pmpro_btn pmpro_btn-submit-checkout" value="<?php if($pmpro_requirebilling) { _e('Submit and Check Out', 'pmpro'); } else { _e('Submit and Confirm', 'pmpro');}?> &raquo;" />
409
  </span>
410
  <?php
411
+
412
  //don't show the default
413
  return false;
414
  }
415
+
416
  /**
417
  * Scripts for checkout page.
418
  *
421
  static function pmpro_checkout_after_form()
422
  {
423
  ?>
424
+ <script>
425
  //choosing payment method
426
+ jQuery('input[name=gateway]').click(function() {
427
  if(jQuery(this).val() == 'paypal')
428
  {
429
  jQuery('#pmpro_paypalexpress_checkout').hide();
430
  jQuery('#pmpro_billing_address_fields').show();
431
+ jQuery('#pmpro_payment_information_fields').show();
432
  jQuery('#pmpro_submit_span').show();
433
  }
434
  else
435
+ {
436
  jQuery('#pmpro_billing_address_fields').hide();
437
+ jQuery('#pmpro_payment_information_fields').hide();
438
  jQuery('#pmpro_submit_span').hide();
439
  jQuery('#pmpro_paypalexpress_checkout').show();
440
  }
441
  });
442
+
443
  //select the radio button if the label is clicked on
444
  jQuery('a.pmpro_radio').click(function() {
445
  jQuery(this).prev().click();
447
  </script>
448
  <?php
449
  }
450
+
451
  //PayPal Express, this is run first to authorize from PayPal
452
  function setExpressCheckout(&$order)
453
+ {
454
  global $pmpro_currency;
455
+
456
  if(empty($order->code))
457
+ $order->code = $order->getRandomCode();
458
+
459
  //clean up a couple values
460
  $order->payment_type = "PayPal Express";
461
  $order->CardType = "";
462
  $order->cardtype = "";
463
+
464
  //taxes on initial amount
465
  $initial_payment = $order->InitialPayment;
466
  $initial_payment_tax = $order->getTaxForPrice($initial_payment);
467
  $initial_payment = round((float)$initial_payment + (float)$initial_payment_tax, 2);
468
+
469
  //taxes on the amount
470
  $amount = $order->PaymentAmount;
471
+ $amount_tax = $order->getTaxForPrice($amount);
472
  $amount = round((float)$amount + (float)$amount_tax, 2);
473
+
474
  //paypal profile stuff
475
  $nvpStr = "";
476
  $nvpStr .="&AMT=" . $initial_payment . "&CURRENCYCODE=" . $pmpro_currency;
477
  if(!empty($order->ProfileStartDate) && strtotime($order->ProfileStartDate, current_time("timestamp")) > 0)
478
+ $nvpStr .= "&PROFILESTARTDATE=" . $order->ProfileStartDate;
479
  if(!empty($order->BillingFrequency))
480
  $nvpStr .= "&BILLINGPERIOD=" . $order->BillingPeriod . "&BILLINGFREQUENCY=" . $order->BillingFrequency . "&AUTOBILLAMT=AddToNextBilling&L_BILLINGTYPE0=RecurringPayments";
481
  $nvpStr .= "&DESC=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
482
+ $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
483
  $nvpStr .= "&NOSHIPPING=1&L_BILLINGAGREEMENTDESCRIPTION0=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127)) . "&L_PAYMENTTYPE0=Any";
484
+
485
+ //if billing cycles are defined
486
  if(!empty($order->TotalBillingCycles))
487
  $nvpStr .= "&TOTALBILLINGCYCLES=" . $order->TotalBillingCycles;
488
+
489
  //if a trial period is defined
490
  if(!empty($order->TrialBillingPeriod))
491
  {
492
  $trial_amount = $order->TrialAmount;
493
  $trial_tax = $order->getTaxForPrice($trial_amount);
494
  $trial_amount = round((float)$trial_amount + (float)$trial_tax, 2);
495
+
496
  $nvpStr .= "&TRIALBILLINGPERIOD=" . $order->TrialBillingPeriod . "&TRIALBILLINGFREQUENCY=" . $order->TrialBillingFrequency . "&TRIALAMT=" . $trial_amount;
497
  }
498
  if(!empty($order->TrialBillingCycles))
499
  $nvpStr .= "&TRIALTOTALBILLINGCYCLES=" . $order->TrialBillingCycles;
500
+
501
  if(!empty($order->discount_code))
502
  {
503
+ $nvpStr .= "&ReturnUrl=" . urlencode(pmpro_url("checkout", "?level=" . $order->membership_level->id . "&discount_code=" . $order->discount_code . "&review=" . $order->code));
504
  }
505
  else
506
  {
507
+ $nvpStr .= "&ReturnUrl=" . urlencode(pmpro_url("checkout", "?level=" . $order->membership_level->id . "&review=" . $order->code));
508
  }
509
+
510
+ $additional_parameters = apply_filters("pmpro_paypal_express_return_url_parameters", array());
511
  if(!empty($additional_parameters))
512
  {
513
+ foreach($additional_parameters as $key => $value)
514
  $nvpStr .= urlencode("&" . $key . "=" . $value);
515
+ }
516
+
517
+ $nvpStr .= "&CANCELURL=" . urlencode(pmpro_url("levels"));
518
+
519
  $account_optional = apply_filters('pmpro_paypal_account_optional', true);
520
  if ($account_optional)
521
  $nvpStr .= '&SOLUTIONTYPE=Sole&LANDINGPAGE=Billing';
522
+
523
+ $nvpStr = apply_filters("pmpro_set_express_checkout_nvpstr", $nvpStr, $order);
524
+
525
  ///echo str_replace("&", "&<br />", $nvpStr);
526
  ///exit;
527
+
528
+ $this->httpParsedResponseAr = $this->PPHttpPost('SetExpressCheckout', $nvpStr);
529
+
530
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
531
+ $order->status = "token";
532
+ $order->paypal_token = urldecode($this->httpParsedResponseAr['TOKEN']);
533
+
534
  //update order
535
+ $order->saveOrder();
536
+
537
  //redirect to paypal
538
  $paypal_url = "https://www.paypal.com/webscr&cmd=_express-checkout&useraction=commit&token=" . $this->httpParsedResponseAr['TOKEN'];
539
+ $environment = pmpro_getOption("gateway_environment");
540
+ if("sandbox" === $environment || "beta-sandbox" === $environment)
541
  {
542
  $paypal_url = "https://www.sandbox.paypal.com/webscr&useraction=commit&cmd=_express-checkout&token=" . $this->httpParsedResponseAr['TOKEN'];
543
+ }
544
+
545
+ wp_redirect($paypal_url);
546
  exit;
547
+
548
  //exit('SetExpressCheckout Completed Successfully: '.print_r($this->httpParsedResponseAr, true));
549
+ } else {
550
  $order->status = "error";
551
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
552
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
554
  return false;
555
  //exit('SetExpressCheckout failed: ' . print_r($httpParsedResponseAr, true));
556
  }
557
+
558
  //write session?
559
+
560
  //redirect to PayPal
561
  }
562
+
563
  function getExpressCheckoutDetails(&$order)
564
+ {
565
  $nvpStr="&TOKEN=".$order->Token;
566
+
567
  $nvpStr = apply_filters("pmpro_get_express_checkout_details_nvpstr", $nvpStr, $order);
568
+
569
  /* Make the API call and store the results in an array. If the
570
  call was a success, show the authorization details, and provide
571
  an action to complete the payment. If failed, show the error
572
  */
573
  $this->httpParsedResponseAr = $this->PPHttpPost('GetExpressCheckoutDetails', $nvpStr);
574
+
575
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
576
+ $order->status = "review";
577
+
578
  //update order
579
+ $order->saveOrder();
580
+
581
+ return true;
582
+ } else {
583
  $order->status = "error";
584
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
585
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
588
  //exit('SetExpressCheckout failed: ' . print_r($httpParsedResponseAr, true));
589
  }
590
  }
591
+
592
  function charge(&$order)
593
  {
594
  global $pmpro_currency;
595
+
596
  if(empty($order->code))
597
+ $order->code = $order->getRandomCode();
598
+
599
  //taxes on the amount
600
  $amount = $order->InitialPayment;
601
+ $amount_tax = $order->getTaxForPrice($amount);
602
  $order->subtotal = $amount;
603
  $amount = round((float)$amount + (float)$amount_tax, 2);
604
+
605
  //paypal profile stuff
606
  $nvpStr = "";
607
  if(!empty($order->Token))
612
  $nvpStr .= "&TAXAMT=" . $amount_tax;
613
  */
614
  if(!empty($order->BillingFrequency))
615
+ $nvpStr .= "&BILLINGPERIOD=" . $order->BillingPeriod . "&BILLINGFREQUENCY=" . $order->BillingFrequency . "&AUTOBILLAMT=AddToNextBilling";
616
  $nvpStr .= "&DESC=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
617
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
618
  $nvpStr .= "&NOSHIPPING=1";
619
+
620
+ $nvpStr .= "&PAYERID=" . $_SESSION['payer_id'] . "&PAYMENTACTION=sale";
621
+
622
  $nvpStr = apply_filters("pmpro_do_express_checkout_payment_nvpstr", $nvpStr, $order);
623
+
624
  $order->nvpStr = $nvpStr;
625
+
626
  $this->httpParsedResponseAr = $this->PPHttpPost('DoExpressCheckoutPayment', $nvpStr);
627
+
628
+ if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
629
+ $order->payment_transaction_id = urldecode($this->httpParsedResponseAr['TRANSACTIONID']);
630
+ $order->status = "success";
631
 
632
  //update order
633
+ $order->saveOrder();
634
+
635
+ return true;
636
+ } else {
637
  $order->status = "error";
638
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
639
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
642
  //exit('SetExpressCheckout failed: ' . print_r($httpParsedResponseAr, true));
643
  }
644
  }
645
+
646
  function subscribe(&$order)
647
+ {
648
  global $pmpro_currency;
649
+
650
  if(empty($order->code))
651
+ $order->code = $order->getRandomCode();
652
 
653
  //filter order before subscription. use with care.
654
  $order = apply_filters("pmpro_subscribe_order", $order, $this);
655
+
656
  //taxes on initial amount
657
  $initial_payment = $order->InitialPayment;
658
  $initial_payment_tax = $order->getTaxForPrice($initial_payment);
659
  $initial_payment = round((float)$initial_payment + (float)$initial_payment_tax, 2);
660
+
661
  //taxes on the amount
662
  $amount = $order->PaymentAmount;
663
+ $amount_tax = $order->getTaxForPrice($amount);
664
  //$amount = round((float)$amount + (float)$amount_tax, 2);
665
+
666
  //paypal profile stuff
667
  $nvpStr = "";
668
  if(!empty($order->Token))
669
+ $nvpStr .= "&TOKEN=" . $order->Token;
670
  $nvpStr .="&INITAMT=" . $initial_payment . "&AMT=" . $amount . "&CURRENCYCODE=" . $pmpro_currency . "&PROFILESTARTDATE=" . $order->ProfileStartDate;
671
  if(!empty($amount_tax))
672
  $nvpStr .= "&TAXAMT=" . $amount_tax;
673
+ $nvpStr .= "&BILLINGPERIOD=" . $order->BillingPeriod . "&BILLINGFREQUENCY=" . $order->BillingFrequency . "&AUTOBILLAMT=AddToNextBilling";
674
  $nvpStr .= "&NOTIFYURL=" . urlencode(admin_url('admin-ajax.php') . "?action=ipnhandler");
675
  $nvpStr .= "&DESC=" . urlencode(substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127));
676
+
677
+ //if billing cycles are defined
678
  if(!empty($order->TotalBillingCycles))
679
  $nvpStr .= "&TOTALBILLINGCYCLES=" . $order->TotalBillingCycles;
680
+
681
  //if a trial period is defined
682
  if(!empty($order->TrialBillingPeriod))
683
  {
684
  $trial_amount = $order->TrialAmount;
685
  $trial_tax = $order->getTaxForPrice($trial_amount);
686
  $trial_amount = round((float)$trial_amount + (float)$trial_tax, 2);
687
+
688
  $nvpStr .= "&TRIALBILLINGPERIOD=" . $order->TrialBillingPeriod . "&TRIALBILLINGFREQUENCY=" . $order->TrialBillingFrequency . "&TRIALAMT=" . $trial_amount;
689
  }
690
  if(!empty($order->TrialBillingCycles))
691
  $nvpStr .= "&TRIALTOTALBILLINGCYCLES=" . $order->TrialBillingCycles;
692
+
693
  $nvpStr = apply_filters("pmpro_create_recurring_payments_profile_nvpstr", $nvpStr, $order);
694
+
695
+ $this->nvpStr = $nvpStr;
696
+
697
  ///echo str_replace("&", "&<br />", $nvpStr);
698
  ///exit;
699
+
700
  $this->httpParsedResponseAr = $this->PPHttpPost('CreateRecurringPaymentsProfile', $nvpStr);
701
+
702
  if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"])) {
703
+ $order->status = "success";
704
  $order->payment_transaction_id = urldecode($this->httpParsedResponseAr['PROFILEID']);
705
  $order->subscription_transaction_id = urldecode($this->httpParsedResponseAr['PROFILEID']);
706
+
707
  //update order
708
+ $order->saveOrder();
709
+
710
+ return true;
711
+ } else {
712
  $order->status = "error";
713
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
714
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
715
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
716
+
717
+ return false;
718
  }
719
  }
720
+
721
  function cancel(&$order)
722
+ {
723
  //paypal profile stuff
724
+ $nvpStr = "";
725
+ $nvpStr .= "&PROFILEID=" . urlencode($order->subscription_transaction_id) . "&ACTION=Cancel&NOTE=" . urlencode("User requested cancel.");
726
+
727
  $nvpStr = apply_filters("pmpro_manage_recurring_payments_profile_status_nvpstr", $nvpStr, $order);
728
+
729
+ $this->httpParsedResponseAr = $this->PPHttpPost('ManageRecurringPaymentsProfileStatus', $nvpStr);
730
+
731
+ if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"]))
732
+ {
733
+ $order->updateStatus("cancelled");
734
+ return true;
735
+ }
736
+ else
737
  {
738
  $order->status = "error";
739
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
740
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']) . ". " . __("Please contact the site owner or cancel your subscription from within PayPal to make sure you are not charged going forward.", "pmpro");
741
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
742
+
743
+ return false;
744
  }
745
  }
746
 
747
  function getSubscriptionStatus(&$order)
748
+ {
749
  if(empty($order->subscription_transaction_id))
750
  return false;
751
+
752
  //paypal profile stuff
753
+ $nvpStr = "";
754
+ $nvpStr .= "&PROFILEID=" . urlencode($order->subscription_transaction_id);
755
+
756
  $nvpStr = apply_filters("pmpro_get_recurring_payments_profile_details_nvpstr", $nvpStr, $order);
757
+
758
+ $this->httpParsedResponseAr = $this->PPHttpPost('GetRecurringPaymentsProfileDetails', $nvpStr);
759
+
760
+ if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"]))
761
+ {
762
+ return $this->httpParsedResponseAr;
763
+ }
764
+ else
765
  {
766
  $order->status = "error";
767
  $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
768
  $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']);
769
  $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
770
+
771
+ return false;
772
  }
773
+ }
774
+
775
  /**
776
  * PAYPAL Function
777
  * Send HTTP POST Request
782
  */
783
  function PPHttpPost($methodName_, $nvpStr_) {
784
  global $gateway_environment;
785
+ $environment = $gateway_environment;
786
+
787
  $API_UserName = pmpro_getOption("apiusername");
788
  $API_Password = pmpro_getOption("apipassword");
789
  $API_Signature = pmpro_getOption("apisignature");
790
  $API_Endpoint = "https://api-3t.paypal.com/nvp";
791
  if("sandbox" === $environment || "beta-sandbox" === $environment) {
792
  $API_Endpoint = "https://api-3t.$environment.paypal.com/nvp";
793
+ }
794
+
795
  $version = urlencode('72.0');
796
+
797
  // setting the curl parameters.
798
  $ch = curl_init();
799
  curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
800
  curl_setopt($ch, CURLOPT_VERBOSE, 1);
801
+
802
  // turning off the server and peer verification(TrustManager Concept).
803
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
804
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
805
+
806
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
807
  curl_setopt($ch, CURLOPT_POST, 1);
808
+
809
  // NVPRequest for submitting to server
810
  $nvpreq = "METHOD=" . urlencode($methodName_) . "&VERSION=" . urlencode($version) . "&PWD=" . urlencode($API_Password) . "&USER=" . urlencode($API_UserName) . "&SIGNATURE=" . urlencode($API_Signature) . "&BUTTONSOURCE=" . urlencode(PAYPAL_BN_CODE) . $nvpStr_;
811
+
812
  // setting the nvpreq as POST FIELD to curl
813
  curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
814
+
815
  // getting response from server
816
  $httpResponse = curl_exec($ch);
817
+
818
  if(!$httpResponse) {
819
  exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
820
  }
821
+
822
  // Extract the RefundTransaction response details
823
  $httpResponseAr = explode("&", $httpResponse);
824
+
825
  $httpParsedResponseAr = array();
826
  foreach ($httpResponseAr as $i => $value) {
827
  $tmpAr = explode("=", $value);
829
  $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
830
  }
831
  }
832
+
833
  if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
834
  exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
835
  }
836
+
837
  return $httpParsedResponseAr;
838
  }
839
  }
classes/gateways/class.pmprogateway_paypalstandard.php CHANGED
@@ -1,537 +1,537 @@
1
- <?php
2
- //include pmprogateway
3
- require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
-
5
- //load classes init method
6
- add_action('init', array('PMProGateway_paypalstandard', 'init'));
7
-
8
- class PMProGateway_paypalstandard extends PMProGateway
9
- {
10
- function PMProGateway_paypalstandard($gateway = NULL)
11
- {
12
- $this->gateway = $gateway;
13
- return $this->gateway;
14
- }
15
-
16
- /**
17
- * Run on WP init
18
- *
19
- * @since 1.8
20
- */
21
- static function init()
22
- {
23
- //make sure PayPal Express is a gateway option
24
- add_filter('pmpro_gateways', array('PMProGateway_paypalstandard', 'pmpro_gateways'));
25
-
26
- //add fields to payment settings
27
- add_filter('pmpro_payment_options', array('PMProGateway_paypalstandard', 'pmpro_payment_options'));
28
-
29
- /*
30
- This code is the same for PayPal Website Payments Pro, PayPal Express, and PayPal Standard
31
- So we only load it if we haven't already.
32
- */
33
- global $pmpro_payment_option_fields_for_paypal;
34
- if(empty($pmpro_payment_option_fields_for_paypal))
35
- {
36
- add_filter('pmpro_payment_option_fields', array('PMProGateway_paypalstandard', 'pmpro_payment_option_fields'), 10, 2);
37
- $pmpro_payment_option_fields_for_paypal = true;
38
- }
39
-
40
- //code to add at checkout
41
- $gateway = pmpro_getGateway();
42
- if($gateway == "paypalstandard")
43
- {
44
- add_filter('pmpro_include_billing_address_fields', '__return_false');
45
- add_filter('pmpro_include_payment_information_fields', '__return_false');
46
- add_filter('pmpro_required_billing_fields', array('PMProGateway_paypalstandard', 'pmpro_required_billing_fields'));
47
- add_filter('pmpro_checkout_default_submit_button', array('PMProGateway_paypalstandard', 'pmpro_checkout_default_submit_button'));
48
- add_filter('pmpro_checkout_before_change_membership_level', array('PMProGateway_paypalstandard', 'pmpro_checkout_before_change_membership_level'), 10, 2);
49
- }
50
- }
51
-
52
- /**
53
- * Make sure this gateway is in the gateways list
54
- *
55
- * @since 1.8
56
- */
57
- static function pmpro_gateways($gateways)
58
- {
59
- if(empty($gateways['paypalstandard']))
60
- $gateways['paypalstandard'] = __('PayPal Standard', 'pmpro');
61
-
62
- return $gateways;
63
- }
64
-
65
- /**
66
- * Get a list of payment options that the this gateway needs/supports.
67
- *
68
- * @since 1.8
69
- */
70
- static function getGatewayOptions()
71
- {
72
- $options = array(
73
- 'sslseal',
74
- 'nuclear_HTTPS',
75
- 'gateway_environment',
76
- 'gateway_email',
77
- 'currency',
78
- 'use_ssl',
79
- 'tax_state',
80
- 'tax_rate'
81
- );
82
-
83
- return $options;
84
- }
85
-
86
- /**
87
- * Set payment options for payment settings page.
88
- *
89
- * @since 1.8
90
- */
91
- static function pmpro_payment_options($options)
92
- {
93
- //get stripe options
94
- $paypal_options = PMProGateway_paypalexpress::getGatewayOptions();
95
-
96
- //merge with others.
97
- $options = array_merge($paypal_options, $options);
98
-
99
- return $options;
100
- }
101
-
102
- /**
103
- * Display fields for this gateway's options.
104
- *
105
- * @since 1.8
106
- */
107
- static function pmpro_payment_option_fields($values, $gateway)
108
- {
109
- ?>
110
- <tr class="pmpro_settings_divider gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
111
- <td colspan="2">
112
- <?php _e('PayPal Settings', 'pmpro'); ?>
113
- </td>
114
- </tr>
115
- <tr class="gateway gateway_paypalstandard" <?php if($gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
116
- <td colspan="2">
117
- <strong><?php _e('Note', 'pmpro');?>:</strong> <?php _e('We do not recommend using PayPal Standard. We suggest using PayPal Express, Website Payments Pro (Legacy), or PayPal Pro (Payflow Pro). <a target="_blank" href="http://www.paidmembershipspro.com/2013/09/read-using-paypal-standard-paid-memberships-pro/">More information on why can be found here.</a>', 'pmpro');?>
118
- </td>
119
- </tr>
120
- <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
121
- <th scope="row" valign="top">
122
- <label for="gateway_email"><?php _e('Gateway Account Email', 'pmpro');?>:</label>
123
- </th>
124
- <td>
125
- <input type="text" id="gateway_email" name="gateway_email" size="60" value="<?php echo esc_attr($values['gateway_email'])?>" />
126
- </td>
127
- </tr>
128
- <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
129
- <th scope="row" valign="top">
130
- <label for="apiusername"><?php _e('API Username', 'pmpro');?>:</label>
131
- </th>
132
- <td>
133
- <input type="text" id="apiusername" name="apiusername" size="60" value="<?php echo esc_attr($values['apiusername'])?>" />
134
- </td>
135
- </tr>
136
- <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
137
- <th scope="row" valign="top">
138
- <label for="apipassword"><?php _e('API Password', 'pmpro');?>:</label>
139
- </th>
140
- <td>
141
- <input type="text" id="apipassword" name="apipassword" size="60" value="<?php echo esc_attr($values['apipassword'])?>" />
142
- </td>
143
- </tr>
144
- <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
145
- <th scope="row" valign="top">
146
- <label for="apisignature"><?php _e('API Signature', 'pmpro');?>:</label>
147
- </th>
148
- <td>
149
- <input type="text" id="apisignature" name="apisignature" size="60" value="<?php echo esc_attr($values['apisignature'])?>" />
150
- </td>
151
- </tr>
152
- <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
153
- <th scope="row" valign="top">
154
- <label><?php _e('IPN Handler URL', 'pmpro');?>:</label>
155
- </th>
156
- <td>
157
- <p><?php _e('Here is your IPN URL for reference. You SHOULD NOT set this in your PayPal settings.', 'pmpro');?> <pre><?php echo admin_url("admin-ajax.php") . "?action=ipnhandler";?></pre></p>
158
- </td>
159
- </tr>
160
- <?php
161
- }
162
-
163
- /**
164
- * Remove required billing fields
165
- *
166
- * @since 1.8
167
- */
168
- static function pmpro_required_billing_fields($fields)
169
- {
170
- unset($fields['bfirstname']);
171
- unset($fields['blastname']);
172
- unset($fields['baddress1']);
173
- unset($fields['bcity']);
174
- unset($fields['bstate']);
175
- unset($fields['bzipcode']);
176
- unset($fields['bphone']);
177
- unset($fields['bemail']);
178
- unset($fields['bcountry']);
179
- unset($fields['CardType']);
180
- unset($fields['AccountNumber']);
181
- unset($fields['ExpirationMonth']);
182
- unset($fields['ExpirationYear']);
183
- unset($fields['CVV']);
184
-
185
- return $fields;
186
- }
187
-
188
- /**
189
- * Swap in our submit buttons.
190
- *
191
- * @since 1.8
192
- */
193
- static function pmpro_checkout_default_submit_button($show)
194
- {
195
- global $gateway, $pmpro_requirebilling;
196
-
197
- //show our submit buttons
198
- ?>
199
- <?php if($gateway == "paypal" || $gateway == "paypalexpress" || $gateway == "paypalstandard") { ?>
200
- <span id="pmpro_paypalexpress_checkout" <?php if(($gateway != "paypalexpress" && $gateway != "paypalstandard") || !$pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
201
- <input type="hidden" name="submit-checkout" value="1" />
202
- <input type="image" value="<?php _e('Check Out with PayPal', 'pmpro');?> &raquo;" src="<?php echo apply_filters("pmpro_paypal_button_image", "https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif");?>" />
203
- </span>
204
- <?php } ?>
205
-
206
- <span id="pmpro_submit_span" <?php if(($gateway == "paypalexpress" || $gateway == "paypalstandard") && $pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
207
- <input type="hidden" name="submit-checkout" value="1" />
208
- <input type="submit" class="pmpro_btn pmpro_btn-submit-checkout" value="<?php if($pmpro_requirebilling) { _e('Submit and Check Out', 'pmpro'); } else { _e('Submit and Confirm', 'pmpro');}?> &raquo;" />
209
- </span>
210
- <?php
211
-
212
- //don't show the default
213
- return false;
214
- }
215
-
216
- /**
217
- * Instead of change membership levels, send users to PayPal to pay.
218
- *
219
- * @since 1.8
220
- */
221
- static function pmpro_checkout_before_change_membership_level($user_id, $morder)
222
- {
223
- global $discount_code_id, $wpdb;
224
-
225
- //if no order, no need to pay
226
- if(empty($morder))
227
- return;
228
-
229
- $morder->user_id = $user_id;
230
- $morder->saveOrder();
231
-
232
- //save discount code use
233
- if(!empty($discount_code_id))
234
- $wpdb->query("INSERT INTO $wpdb->pmpro_discount_codes_uses (code_id, user_id, order_id, timestamp) VALUES('" . $discount_code_id . "', '" . $user_id . "', '" . $morder->id . "', now())");
235
-
236
- do_action("pmpro_before_send_to_paypal_standard", $user_id, $morder);
237
-
238
- $morder->Gateway->sendToPayPal($morder);
239
- }
240
-
241
- /**
242
- * Process checkout.
243
- *
244
- */
245
- function process(&$order)
246
- {
247
- if(empty($order->code))
248
- $order->code = $order->getRandomCode();
249
-
250
- //clean up a couple values
251
- $order->payment_type = "PayPal Standard";
252
- $order->CardType = "";
253
- $order->cardtype = "";
254
-
255
- //just save, the user will go to PayPal to pay
256
- $order->status = "review";
257
- $order->saveOrder();
258
-
259
- return true;
260
- }
261
-
262
- function sendToPayPal(&$order)
263
- {
264
- global $pmpro_currency;
265
-
266
- //taxes on initial amount
267
- $initial_payment = $order->InitialPayment;
268
- $initial_payment_tax = $order->getTaxForPrice($initial_payment);
269
- $initial_payment = round((float)$initial_payment + (float)$initial_payment_tax, 2);
270
-
271
- //taxes on the amount
272
- $amount = $order->PaymentAmount;
273
- $amount_tax = $order->getTaxForPrice($amount);
274
- $amount = round((float)$amount + (float)$amount_tax, 2);
275
-
276
- //build PayPal Redirect
277
- $environment = pmpro_getOption("gateway_environment");
278
- if("sandbox" === $environment || "beta-sandbox" === $environment)
279
- $paypal_url ="https://www.sandbox.paypal.com/cgi-bin/webscr?business=" . urlencode(pmpro_getOption("gateway_email"));
280
- else
281
- $paypal_url = "https://www.paypal.com/cgi-bin/webscr?business=" . urlencode(pmpro_getOption("gateway_email"));
282
-
283
- if(pmpro_isLevelRecurring($order->membership_level))
284
- {
285
- //convert billing period
286
- if($order->BillingPeriod == "Day")
287
- $period = "D";
288
- elseif($order->BillingPeriod == "Week")
289
- $period = "W";
290
- elseif($order->BillingPeriod == "Month")
291
- $period = "M";
292
- elseif($order->BillingPeriod == "Year")
293
- $period = "Y";
294
- else
295
- {
296
- $order->error = "Invalid billing period: " . $order->BillingPeriod;
297
- $order->shorterror = "Invalid billing period: " . $order->BillingPeriod;
298
- return false;
299
- }
300
-
301
- //other args
302
- $paypal_args = array(
303
- 'cmd' => '_xclick-subscriptions',
304
- 'a1' => number_format($initial_payment, 2),
305
- 'p1' => $order->BillingFrequency,
306
- 't1' => $period,
307
- 'a3' => number_format($amount, 2),
308
- 'p3' => $order->BillingFrequency,
309
- 't3' => $period,
310
- 'item_name' => substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127),
311
- 'email' => $order->Email,
312
- 'no_shipping' => '1',
313
- 'shipping' => '0',
314
- 'no_note' => '1',
315
- 'currency_code' => $pmpro_currency,
316
- 'item_number' => $order->code,
317
- 'charset' => get_bloginfo( 'charset' ),
318
- 'rm' => '2',
319
- 'return' => pmpro_url("confirmation", "?level=" . $order->membership_level->id),
320
- 'notify_url' => admin_url("admin-ajax.php") . "?action=ipnhandler",
321
- 'src' => '1',
322
- 'sra' => '1',
323
- 'bn' => PAYPAL_BN_CODE
324
- );
325
-
326
- //trial?
327
- /*
328
- Note here that the TrialBillingCycles value is being ignored. PayPal Standard only offers 1 payment during each trial period.
329
- */
330
- if(!empty($order->TrialBillingPeriod))
331
- {
332
- //if a1 and a2 are 0, let's just combine them. PayPal doesn't like a2 = 0.
333
- if($paypal_args['a1'] == 0 && $order->TrialAmount == 0)
334
- {
335
- $paypal_args['p1'] = $paypal_args['p1'] + $order->TrialBillingFrequency;
336
- }
337
- else
338
- {
339
- $trial_amount = $order->TrialAmount;
340
- $trial_tax = $order->getTaxForPrice($trial_amount);
341
- $trial_amount = round((float)$trial_amount + (float)$trial_tax, 2);
342
-
343
- $paypal_args['a2'] = $trial_amount;
344
- $paypal_args['p2'] = $order->TrialBillingFrequency;
345
- $paypal_args['t2'] = $period;
346
- }
347
- }
348
- else
349
- {
350
- //we can try to work in any change in ProfileStartDate
351
- $psd = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
352
- $adjusted_psd = apply_filters("pmpro_profile_start_date", $psd, $order);
353
- if($psd != $adjusted_psd)
354
- {
355
- //someone is trying to push the start date back
356
- $adjusted_psd_time = strtotime($adjusted_psd, current_time("timestamp"));
357
- $seconds_til_psd = $adjusted_psd_time - current_time('timestamp');
358
- $days_til_psd = floor($seconds_til_psd/(60*60*24));
359
-
360
- //push back trial one by days_til_psd
361
- if($days_til_psd > 90)
362
- {
363
- //we need to convert to weeks, because PayPal limits t1 to 90 days
364
- $weeks_til_psd = round($days_til_psd / 7);
365
- $paypal_args['p1'] = $weeks_til_psd;
366
- $paypal_args['t1'] = "W";
367
- }
368
- elseif($days_til_psd > 0)
369
- {
370
- //use days
371
- $paypal_args['p1'] = $days_til_psd;
372
- $paypal_args['t1'] = "D";
373
- }
374
- }
375
- }
376
-
377
- //billing limit?
378
- if(!empty($order->TotalBillingCycles))
379
- {
380
- if(!empty($trial_amount))
381
- {
382
-
383
- $srt = intval($order->TotalBillingCycles) - 1; //subtract one for the trial period
384
- }
385
- else
386
- {
387
- $srt = intval($order->TotalBillingCycles);
388
- }
389
-
390
- //srt must be at least 2 or the subscription is not "recurring" according to paypal
391
- if($srt > 1)
392
- $paypal_args['srt'] = $srt;
393
- else
394
- $paypal_args['src'] = '0';
395
- }
396
- else
397
- $paypal_args['srt'] = '0'; //indefinite subscription
398
- }
399
- else
400
- {
401
- //other args
402
- $paypal_args = array(
403
- 'cmd' => '_xclick',
404
- 'amount' => number_format($initial_payment, 2),
405
- 'item_name' => substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127),
406
- 'email' => $order->Email,
407
- 'no_shipping' => '1',
408
- 'shipping' => '0',
409
- 'no_note' => '1',
410
- 'currency_code' => $pmpro_currency,
411
- 'item_number' => $order->code,
412
- 'charset' => get_bloginfo( 'charset' ),
413
- 'rm' => '2',
414
- 'return' => pmpro_url("confirmation", "?level=" . $order->membership_level->id),
415
- 'notify_url' => admin_url("admin-ajax.php") . "?action=ipnhandler",
416
- 'bn' => PAYPAL_BN_CODE
417
- );
418
- }
419
-
420
- $nvpStr = "";
421
- foreach($paypal_args as $key => $value)
422
- {
423
- $nvpStr .= "&" . $key . "=" . urlencode($value);
424
- }
425
-
426
- //anything modders might add
427
- $additional_parameters = apply_filters("pmpro_paypal_express_return_url_parameters", array());
428
- if(!empty($additional_parameters))
429
- {
430
- foreach($additional_parameters as $key => $value)
431
- $nvpStr .= urlencode("&" . $key . "=" . $value);
432
- }
433
-
434
- $account_optional = apply_filters('pmpro_paypal_account_optional', true);
435
- if ($account_optional)
436
- $nvpStr .= '&SOLUTIONTYPE=Sole&LANDINGPAGE=Billing';
437
-
438
- $nvpStr = apply_filters("pmpro_paypal_standard_nvpstr", $nvpStr, $order);
439
-
440
- //redirect to paypal
441
- $paypal_url .= $nvpStr;
442
-
443
- //wp_die(str_replace("&", "<br />", $paypal_url));
444
-
445
- wp_redirect($paypal_url);
446
- exit;
447
- }
448
-
449
- function cancel(&$order)
450
- {
451
- //paypal profile stuff
452
- $nvpStr = "";
453
- $nvpStr .= "&PROFILEID=" . urlencode($order->subscription_transaction_id) . "&ACTION=Cancel&NOTE=" . urlencode("User requested cancel.");
454
-
455
- $this->httpParsedResponseAr = $this->PPHttpPost('ManageRecurringPaymentsProfileStatus', $nvpStr);
456
-
457
- if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"]))
458
- {
459
- $order->updateStatus("cancelled");
460
- return true;
461
- }
462
- else
463
- {
464
- $order->status = "error";
465
- $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
466
- $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']) . ". " . __("Please contact the site owner or cancel your subscription from within PayPal to make sure you are not charged going forward.", "pmpro");
467
- $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
468
-
469
- return false;
470
- }
471
- }
472
-
473
- /**
474
- * PAYPAL Function
475
- * Send HTTP POST Request
476
- *
477
- * @param string The API method name
478
- * @param string The POST Message fields in &name=value pair format
479
- * @return array Parsed HTTP Response body
480
- */
481
- function PPHttpPost($methodName_, $nvpStr_) {
482
- global $gateway_environment;
483
- $environment = $gateway_environment;
484
-
485
- $API_UserName = pmpro_getOption("apiusername");
486
- $API_Password = pmpro_getOption("apipassword");
487
- $API_Signature = pmpro_getOption("apisignature");
488
- $API_Endpoint = "https://api-3t.paypal.com/nvp";
489
- if("sandbox" === $environment || "beta-sandbox" === $environment) {
490
- $API_Endpoint = "https://api-3t.$environment.paypal.com/nvp";
491
- }
492
-
493
- $version = urlencode('72.0');
494
-
495
- // setting the curl parameters.
496
- $ch = curl_init();
497
- curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
498
- curl_setopt($ch, CURLOPT_VERBOSE, 1);
499
-
500
- // turning off the server and peer verification(TrustManager Concept).
501
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
502
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
503
-
504
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
505
- curl_setopt($ch, CURLOPT_POST, 1);
506
-
507
- // NVPRequest for submitting to server
508
- $nvpreq = "METHOD=" . urlencode($methodName_) . "&VERSION=" . urlencode($version) . "&PWD=" . urlencode($API_Password) . "&USER=" . urlencode($API_UserName) . "&SIGNATURE=" . urlencode($API_Signature) . "&bn=" . urlencode(PAYPAL_BN_CODE) . $nvpStr_;
509
-
510
- // setting the nvpreq as POST FIELD to curl
511
- curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
512
-
513
- // getting response from server
514
- $httpResponse = curl_exec($ch);
515
-
516
- if(!$httpResponse) {
517
- exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
518
- }
519
-
520
- // Extract the RefundTransaction response details
521
- $httpResponseAr = explode("&", $httpResponse);
522
-
523
- $httpParsedResponseAr = array();
524
- foreach ($httpResponseAr as $i => $value) {
525
- $tmpAr = explode("=", $value);
526
- if(sizeof($tmpAr) > 1) {
527
- $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
528
- }
529
- }
530
-
531
- if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
532
- exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
533
- }
534
-
535
- return $httpParsedResponseAr;
536
- }
537
- }
1
+ <?php
2
+ //include pmprogateway
3
+ require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
+
5
+ //load classes init method
6
+ add_action('init', array('PMProGateway_paypalstandard', 'init'));
7
+
8
+ class PMProGateway_paypalstandard extends PMProGateway
9
+ {
10
+ function PMProGateway_paypalstandard($gateway = NULL)
11
+ {
12
+ $this->gateway = $gateway;
13
+ return $this->gateway;
14
+ }
15
+
16
+ /**
17
+ * Run on WP init
18
+ *
19
+ * @since 1.8
20
+ */
21
+ static function init()
22
+ {
23
+ //make sure PayPal Express is a gateway option
24
+ add_filter('pmpro_gateways', array('PMProGateway_paypalstandard', 'pmpro_gateways'));
25
+
26
+ //add fields to payment settings
27
+ add_filter('pmpro_payment_options', array('PMProGateway_paypalstandard', 'pmpro_payment_options'));
28
+
29
+ /*
30
+ This code is the same for PayPal Website Payments Pro, PayPal Express, and PayPal Standard
31
+ So we only load it if we haven't already.
32
+ */
33
+ global $pmpro_payment_option_fields_for_paypal;
34
+ if(empty($pmpro_payment_option_fields_for_paypal))
35
+ {
36
+ add_filter('pmpro_payment_option_fields', array('PMProGateway_paypalstandard', 'pmpro_payment_option_fields'), 10, 2);
37
+ $pmpro_payment_option_fields_for_paypal = true;
38
+ }
39
+
40
+ //code to add at checkout
41
+ $gateway = pmpro_getGateway();
42
+ if($gateway == "paypalstandard")
43
+ {
44
+ add_filter('pmpro_include_billing_address_fields', '__return_false');
45
+ add_filter('pmpro_include_payment_information_fields', '__return_false');
46
+ add_filter('pmpro_required_billing_fields', array('PMProGateway_paypalstandard', 'pmpro_required_billing_fields'));
47
+ add_filter('pmpro_checkout_default_submit_button', array('PMProGateway_paypalstandard', 'pmpro_checkout_default_submit_button'));
48
+ add_filter('pmpro_checkout_before_change_membership_level', array('PMProGateway_paypalstandard', 'pmpro_checkout_before_change_membership_level'), 10, 2);
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Make sure this gateway is in the gateways list
54
+ *
55
+ * @since 1.8
56
+ */
57
+ static function pmpro_gateways($gateways)
58
+ {
59
+ if(empty($gateways['paypalstandard']))
60
+ $gateways['paypalstandard'] = __('PayPal Standard', 'pmpro');
61
+
62
+ return $gateways;
63
+ }
64
+
65
+ /**
66
+ * Get a list of payment options that the this gateway needs/supports.
67
+ *
68
+ * @since 1.8
69
+ */
70
+ static function getGatewayOptions()
71
+ {
72
+ $options = array(
73
+ 'sslseal',
74
+ 'nuclear_HTTPS',
75
+ 'gateway_environment',
76
+ 'gateway_email',
77
+ 'currency',
78
+ 'use_ssl',
79
+ 'tax_state',
80
+ 'tax_rate'
81
+ );
82
+
83
+ return $options;
84
+ }
85
+
86
+ /**
87
+ * Set payment options for payment settings page.
88
+ *
89
+ * @since 1.8
90
+ */
91
+ static function pmpro_payment_options($options)
92
+ {
93
+ //get stripe options
94
+ $paypal_options = PMProGateway_paypalexpress::getGatewayOptions();
95
+
96
+ //merge with others.
97
+ $options = array_merge($paypal_options, $options);
98
+
99
+ return $options;
100
+ }
101
+
102
+ /**
103
+ * Display fields for this gateway's options.
104
+ *
105
+ * @since 1.8
106
+ */
107
+ static function pmpro_payment_option_fields($values, $gateway)
108
+ {
109
+ ?>
110
+ <tr class="pmpro_settings_divider gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
111
+ <td colspan="2">
112
+ <?php _e('PayPal Settings', 'pmpro'); ?>
113
+ </td>
114
+ </tr>
115
+ <tr class="gateway gateway_paypalstandard" <?php if($gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
116
+ <td colspan="2">
117
+ <strong><?php _e('Note', 'pmpro');?>:</strong> <?php _e('We do not recommend using PayPal Standard. We suggest using PayPal Express, Website Payments Pro (Legacy), or PayPal Pro (Payflow Pro). <a target="_blank" href="http://www.paidmembershipspro.com/2013/09/read-using-paypal-standard-paid-memberships-pro/">More information on why can be found here.</a>', 'pmpro');?>
118
+ </td>
119
+ </tr>
120
+ <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
121
+ <th scope="row" valign="top">
122
+ <label for="gateway_email"><?php _e('Gateway Account Email', 'pmpro');?>:</label>
123
+ </th>
124
+ <td>
125
+ <input type="text" id="gateway_email" name="gateway_email" size="60" value="<?php echo esc_attr($values['gateway_email'])?>" />
126
+ </td>
127
+ </tr>
128
+ <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
129
+ <th scope="row" valign="top">
130
+ <label for="apiusername"><?php _e('API Username', 'pmpro');?>:</label>
131
+ </th>
132
+ <td>
133
+ <input type="text" id="apiusername" name="apiusername" size="60" value="<?php echo esc_attr($values['apiusername'])?>" />
134
+ </td>
135
+ </tr>
136
+ <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
137
+ <th scope="row" valign="top">
138
+ <label for="apipassword"><?php _e('API Password', 'pmpro');?>:</label>
139
+ </th>
140
+ <td>
141
+ <input type="text" id="apipassword" name="apipassword" size="60" value="<?php echo esc_attr($values['apipassword'])?>" />
142
+ </td>
143
+ </tr>
144
+ <tr class="gateway gateway_paypal gateway_paypalexpress" <?php if($gateway != "paypal" && $gateway != "paypalexpress") { ?>style="display: none;"<?php } ?>>
145
+ <th scope="row" valign="top">
146
+ <label for="apisignature"><?php _e('API Signature', 'pmpro');?>:</label>
147
+ </th>
148
+ <td>
149
+ <input type="text" id="apisignature" name="apisignature" size="60" value="<?php echo esc_attr($values['apisignature'])?>" />
150
+ </td>
151
+ </tr>
152
+ <tr class="gateway gateway_paypal gateway_paypalexpress gateway_paypalstandard" <?php if($gateway != "paypal" && $gateway != "paypalexpress" && $gateway != "paypalstandard") { ?>style="display: none;"<?php } ?>>
153
+ <th scope="row" valign="top">
154
+ <label><?php _e('IPN Handler URL', 'pmpro');?>:</label>
155
+ </th>
156
+ <td>
157
+ <p><?php _e('Here is your IPN URL for reference. You SHOULD NOT set this in your PayPal settings.', 'pmpro');?> <pre><?php echo admin_url("admin-ajax.php") . "?action=ipnhandler";?></pre></p>
158
+ </td>
159
+ </tr>
160
+ <?php
161
+ }
162
+
163
+ /**
164
+ * Remove required billing fields
165
+ *
166
+ * @since 1.8
167
+ */
168
+ static function pmpro_required_billing_fields($fields)
169
+ {
170
+ unset($fields['bfirstname']);
171
+ unset($fields['blastname']);
172
+ unset($fields['baddress1']);
173
+ unset($fields['bcity']);
174
+ unset($fields['bstate']);
175
+ unset($fields['bzipcode']);
176
+ unset($fields['bphone']);
177
+ unset($fields['bemail']);
178
+ unset($fields['bcountry']);
179
+ unset($fields['CardType']);
180
+ unset($fields['AccountNumber']);
181
+ unset($fields['ExpirationMonth']);
182
+ unset($fields['ExpirationYear']);
183
+ unset($fields['CVV']);
184
+
185
+ return $fields;
186
+ }
187
+
188
+ /**
189
+ * Swap in our submit buttons.
190
+ *
191
+ * @since 1.8
192
+ */
193
+ static function pmpro_checkout_default_submit_button($show)
194
+ {
195
+ global $gateway, $pmpro_requirebilling;
196
+
197
+ //show our submit buttons
198
+ ?>
199
+ <?php if($gateway == "paypal" || $gateway == "paypalexpress" || $gateway == "paypalstandard") { ?>
200
+ <span id="pmpro_paypalexpress_checkout" <?php if(($gateway != "paypalexpress" && $gateway != "paypalstandard") || !$pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
201
+ <input type="hidden" name="submit-checkout" value="1" />
202
+ <input type="image" value="<?php _e('Check Out with PayPal', 'pmpro');?> &raquo;" src="<?php echo apply_filters("pmpro_paypal_button_image", "https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif");?>" />
203
+ </span>
204
+ <?php } ?>
205
+
206
+ <span id="pmpro_submit_span" <?php if(($gateway == "paypalexpress" || $gateway == "paypalstandard") && $pmpro_requirebilling) { ?>style="display: none;"<?php } ?>>
207
+ <input type="hidden" name="submit-checkout" value="1" />
208
+ <input type="submit" class="pmpro_btn pmpro_btn-submit-checkout" value="<?php if($pmpro_requirebilling) { _e('Submit and Check Out', 'pmpro'); } else { _e('Submit and Confirm', 'pmpro');}?> &raquo;" />
209
+ </span>
210
+ <?php
211
+
212
+ //don't show the default
213
+ return false;
214
+ }
215
+
216
+ /**
217
+ * Instead of change membership levels, send users to PayPal to pay.
218
+ *
219
+ * @since 1.8
220
+ */
221
+ static function pmpro_checkout_before_change_membership_level($user_id, $morder)
222
+ {
223
+ global $discount_code_id, $wpdb;
224
+
225
+ //if no order, no need to pay
226
+ if(empty($morder))
227
+ return;
228
+
229
+ $morder->user_id = $user_id;
230
+ $morder->saveOrder();
231
+
232
+ //save discount code use
233
+ if(!empty($discount_code_id))
234
+ $wpdb->query("INSERT INTO $wpdb->pmpro_discount_codes_uses (code_id, user_id, order_id, timestamp) VALUES('" . $discount_code_id . "', '" . $user_id . "', '" . $morder->id . "', now())");
235
+
236
+ do_action("pmpro_before_send_to_paypal_standard", $user_id, $morder);
237
+
238
+ $morder->Gateway->sendToPayPal($morder);
239
+ }
240
+
241
+ /**
242
+ * Process checkout.
243
+ *
244
+ */
245
+ function process(&$order)
246
+ {
247
+ if(empty($order->code))
248
+ $order->code = $order->getRandomCode();
249
+
250
+ //clean up a couple values
251
+ $order->payment_type = "PayPal Standard";
252
+ $order->CardType = "";
253
+ $order->cardtype = "";
254
+
255
+ //just save, the user will go to PayPal to pay
256
+ $order->status = "review";
257
+ $order->saveOrder();
258
+
259
+ return true;
260
+ }
261
+
262
+ function sendToPayPal(&$order)
263
+ {
264
+ global $pmpro_currency;
265
+
266
+ //taxes on initial amount
267
+ $initial_payment = $order->InitialPayment;
268
+ $initial_payment_tax = $order->getTaxForPrice($initial_payment);
269
+ $initial_payment = round((float)$initial_payment + (float)$initial_payment_tax, 2);
270
+
271
+ //taxes on the amount
272
+ $amount = $order->PaymentAmount;
273
+ $amount_tax = $order->getTaxForPrice($amount);
274
+ $amount = round((float)$amount + (float)$amount_tax, 2);
275
+
276
+ //build PayPal Redirect
277
+ $environment = pmpro_getOption("gateway_environment");
278
+ if("sandbox" === $environment || "beta-sandbox" === $environment)
279
+ $paypal_url ="https://www.sandbox.paypal.com/cgi-bin/webscr?business=" . urlencode(pmpro_getOption("gateway_email"));
280
+ else
281
+ $paypal_url = "https://www.paypal.com/cgi-bin/webscr?business=" . urlencode(pmpro_getOption("gateway_email"));
282
+
283
+ if(pmpro_isLevelRecurring($order->membership_level))
284
+ {
285
+ //convert billing period
286
+ if($order->BillingPeriod == "Day")
287
+ $period = "D";
288
+ elseif($order->BillingPeriod == "Week")
289
+ $period = "W";
290
+ elseif($order->BillingPeriod == "Month")
291
+ $period = "M";
292
+ elseif($order->BillingPeriod == "Year")
293
+ $period = "Y";
294
+ else
295
+ {
296
+ $order->error = "Invalid billing period: " . $order->BillingPeriod;
297
+ $order->shorterror = "Invalid billing period: " . $order->BillingPeriod;
298
+ return false;
299
+ }
300
+
301
+ //other args
302
+ $paypal_args = array(
303
+ 'cmd' => '_xclick-subscriptions',
304
+ 'a1' => number_format($initial_payment, 2),
305
+ 'p1' => $order->BillingFrequency,
306
+ 't1' => $period,
307
+ 'a3' => number_format($amount, 2),
308
+ 'p3' => $order->BillingFrequency,
309
+ 't3' => $period,
310
+ 'item_name' => substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127),
311
+ 'email' => $order->Email,
312
+ 'no_shipping' => '1',
313
+ 'shipping' => '0',
314
+ 'no_note' => '1',
315
+ 'currency_code' => $pmpro_currency,
316
+ 'item_number' => $order->code,
317
+ 'charset' => get_bloginfo( 'charset' ),
318
+ 'rm' => '2',
319
+ 'return' => pmpro_url("confirmation", "?level=" . $order->membership_level->id),
320
+ 'notify_url' => admin_url("admin-ajax.php") . "?action=ipnhandler",
321
+ 'src' => '1',
322
+ 'sra' => '1',
323
+ 'bn' => PAYPAL_BN_CODE
324
+ );
325
+
326
+ //trial?
327
+ /*
328
+ Note here that the TrialBillingCycles value is being ignored. PayPal Standard only offers 1 payment during each trial period.
329
+ */
330
+ if(!empty($order->TrialBillingPeriod))
331
+ {
332
+ //if a1 and a2 are 0, let's just combine them. PayPal doesn't like a2 = 0.
333
+ if($paypal_args['a1'] == 0 && $order->TrialAmount == 0)
334
+ {
335
+ $paypal_args['p1'] = $paypal_args['p1'] + $order->TrialBillingFrequency;
336
+ }
337
+ else
338
+ {
339
+ $trial_amount = $order->TrialAmount;
340
+ $trial_tax = $order->getTaxForPrice($trial_amount);
341
+ $trial_amount = round((float)$trial_amount + (float)$trial_tax, 2);
342
+
343
+ $paypal_args['a2'] = $trial_amount;
344
+ $paypal_args['p2'] = $order->TrialBillingFrequency;
345
+ $paypal_args['t2'] = $period;
346
+ }
347
+ }
348
+ else
349
+ {
350
+ //we can try to work in any change in ProfileStartDate
351
+ $psd = date("Y-m-d", strtotime("+ " . $order->BillingFrequency . " " . $order->BillingPeriod, current_time("timestamp"))) . "T0:0:0";
352
+ $adjusted_psd = apply_filters("pmpro_profile_start_date", $psd, $order);
353
+ if($psd != $adjusted_psd)
354
+ {
355
+ //someone is trying to push the start date back
356
+ $adjusted_psd_time = strtotime($adjusted_psd, current_time("timestamp"));
357
+ $seconds_til_psd = $adjusted_psd_time - current_time('timestamp');
358
+ $days_til_psd = floor($seconds_til_psd/(60*60*24));
359
+
360
+ //push back trial one by days_til_psd
361
+ if($days_til_psd > 90)
362
+ {
363
+ //we need to convert to weeks, because PayPal limits t1 to 90 days
364
+ $weeks_til_psd = round($days_til_psd / 7);
365
+ $paypal_args['p1'] = $weeks_til_psd;
366
+ $paypal_args['t1'] = "W";
367
+ }
368
+ elseif($days_til_psd > 0)
369
+ {
370
+ //use days
371
+ $paypal_args['p1'] = $days_til_psd;
372
+ $paypal_args['t1'] = "D";
373
+ }
374
+ }
375
+ }
376
+
377
+ //billing limit?
378
+ if(!empty($order->TotalBillingCycles))
379
+ {
380
+ if(!empty($trial_amount))
381
+ {
382
+
383
+ $srt = intval($order->TotalBillingCycles) - 1; //subtract one for the trial period
384
+ }
385
+ else
386
+ {
387
+ $srt = intval($order->TotalBillingCycles);
388
+ }
389
+
390
+ //srt must be at least 2 or the subscription is not "recurring" according to paypal
391
+ if($srt > 1)
392
+ $paypal_args['srt'] = $srt;
393
+ else
394
+ $paypal_args['src'] = '0';
395
+ }
396
+ else
397
+ $paypal_args['srt'] = '0'; //indefinite subscription
398
+ }
399
+ else
400
+ {
401
+ //other args
402
+ $paypal_args = array(
403
+ 'cmd' => '_xclick',
404
+ 'amount' => number_format($initial_payment, 2),
405
+ 'item_name' => substr($order->membership_level->name . " at " . get_bloginfo("name"), 0, 127),
406
+ 'email' => $order->Email,
407
+ 'no_shipping' => '1',
408
+ 'shipping' => '0',
409
+ 'no_note' => '1',
410
+ 'currency_code' => $pmpro_currency,
411
+ 'item_number' => $order->code,
412
+ 'charset' => get_bloginfo( 'charset' ),
413
+ 'rm' => '2',
414
+ 'return' => pmpro_url("confirmation", "?level=" . $order->membership_level->id),
415
+ 'notify_url' => admin_url("admin-ajax.php") . "?action=ipnhandler",
416
+ 'bn' => PAYPAL_BN_CODE
417
+ );
418
+ }
419
+
420
+ $nvpStr = "";
421
+ foreach($paypal_args as $key => $value)
422
+ {
423
+ $nvpStr .= "&" . $key . "=" . urlencode($value);
424
+ }
425
+
426
+ //anything modders might add
427
+ $additional_parameters = apply_filters("pmpro_paypal_express_return_url_parameters", array());
428
+ if(!empty($additional_parameters))
429
+ {
430
+ foreach($additional_parameters as $key => $value)
431
+ $nvpStr .= urlencode("&" . $key . "=" . $value);
432
+ }
433
+
434
+ $account_optional = apply_filters('pmpro_paypal_account_optional', true);
435
+ if ($account_optional)
436
+ $nvpStr .= '&SOLUTIONTYPE=Sole&LANDINGPAGE=Billing';
437
+
438
+ $nvpStr = apply_filters("pmpro_paypal_standard_nvpstr", $nvpStr, $order);
439
+
440
+ //redirect to paypal
441
+ $paypal_url .= $nvpStr;
442
+
443
+ //wp_die(str_replace("&", "<br />", $paypal_url));
444
+
445
+ wp_redirect($paypal_url);
446
+ exit;
447
+ }
448
+
449
+ function cancel(&$order)
450
+ {
451
+ //paypal profile stuff
452
+ $nvpStr = "";
453
+ $nvpStr .= "&PROFILEID=" . urlencode($order->subscription_transaction_id) . "&ACTION=Cancel&NOTE=" . urlencode("User requested cancel.");
454
+
455
+ $this->httpParsedResponseAr = $this->PPHttpPost('ManageRecurringPaymentsProfileStatus', $nvpStr);
456
+
457
+ if("SUCCESS" == strtoupper($this->httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($this->httpParsedResponseAr["ACK"]))
458
+ {
459
+ $order->updateStatus("cancelled");
460
+ return true;
461
+ }
462
+ else
463
+ {
464
+ $order->status = "error";
465
+ $order->errorcode = $this->httpParsedResponseAr['L_ERRORCODE0'];
466
+ $order->error = urldecode($this->httpParsedResponseAr['L_LONGMESSAGE0']) . ". " . __("Please contact the site owner or cancel your subscription from within PayPal to make sure you are not charged going forward.", "pmpro");
467
+ $order->shorterror = urldecode($this->httpParsedResponseAr['L_SHORTMESSAGE0']);
468
+
469
+ return false;
470
+ }
471
+ }
472
+
473
+ /**
474
+ * PAYPAL Function
475
+ * Send HTTP POST Request
476
+ *
477
+ * @param string The API method name
478
+ * @param string The POST Message fields in &name=value pair format
479
+ * @return array Parsed HTTP Response body
480
+ */
481
+ function PPHttpPost($methodName_, $nvpStr_) {
482
+ global $gateway_environment;
483
+ $environment = $gateway_environment;
484
+
485
+ $API_UserName = pmpro_getOption("apiusername");
486
+ $API_Password = pmpro_getOption("apipassword");
487
+ $API_Signature = pmpro_getOption("apisignature");
488
+ $API_Endpoint = "https://api-3t.paypal.com/nvp";
489
+ if("sandbox" === $environment || "beta-sandbox" === $environment) {
490
+ $API_Endpoint = "https://api-3t.$environment.paypal.com/nvp";
491
+ }
492
+
493
+ $version = urlencode('72.0');
494
+
495
+ // setting the curl parameters.
496
+ $ch = curl_init();
497
+ curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
498
+ curl_setopt($ch, CURLOPT_VERBOSE, 1);
499
+
500
+ // turning off the server and peer verification(TrustManager Concept).
501
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
502
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
503
+
504
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
505
+ curl_setopt($ch, CURLOPT_POST, 1);
506
+
507
+ // NVPRequest for submitting to server
508
+ $nvpreq = "METHOD=" . urlencode($methodName_) . "&VERSION=" . urlencode($version) . "&PWD=" . urlencode($API_Password) . "&USER=" . urlencode($API_UserName) . "&SIGNATURE=" . urlencode($API_Signature) . "&bn=" . urlencode(PAYPAL_BN_CODE) . $nvpStr_;
509
+
510
+ // setting the nvpreq as POST FIELD to curl
511
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
512
+
513
+ // getting response from server
514
+ $httpResponse = curl_exec($ch);
515
+
516
+ if(!$httpResponse) {
517
+ exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
518
+ }
519
+
520
+ // Extract the RefundTransaction response details
521
+ $httpResponseAr = explode("&", $httpResponse);
522
+
523
+ $httpParsedResponseAr = array();
524
+ foreach ($httpResponseAr as $i => $value) {
525
+ $tmpAr = explode("=", $value);
526
+ if(sizeof($tmpAr) > 1) {
527
+ $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
528
+ }
529
+ }
530
+
531
+ if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
532
+ exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
533
+ }
534
+
535
+ return $httpParsedResponseAr;
536
+ }
537
+ }
classes/gateways/class.pmprogateway_stripe.php CHANGED
@@ -1,1617 +1,1617 @@
1
- <?php
2
- //include pmprogateway
3
- require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
-
5
- //load classes init method
6
- add_action('init', array('PMProGateway_stripe', 'init'));
7
-
8
- /**
9
- * PMProGateway_stripe Class
10
- *
11
- * Handles Stripe integration.
12
- *
13
- * @since 1.4
14
- */
15
- class PMProGateway_stripe extends PMProGateway
16
- {
17
- /**
18
- * Stripe Class Constructor
19
- *
20
- * @since 1.4
21
- */
22
- function PMProGateway_stripe($gateway = NULL)
23
- {
24
- $this->gateway = $gateway;
25
- $this->gateway_environment = pmpro_getOption("gateway_environment");
26
-
27
- $this->loadStripeLibrary();
28
- Stripe::setApiKey(pmpro_getOption("stripe_secretkey"));
29
-
30
- return $this->gateway;
31
- }
32
-
33
- /**
34
- * Load the Stripe API library.
35
- *
36
- * @since 1.8
37
- * Moved into a method in version 1.8 so we only load it when needed.
38
- */
39
- function loadStripeLibrary()
40
- {
41
- //load Stripe library if it hasn't been loaded already (usually by another plugin using Stripe)
42
- if(!class_exists("Stripe"))
43
- require_once(dirname(__FILE__) . "/../../includes/lib/Stripe/Stripe.php");
44
- }
45
-
46
- /**
47
- * Run on WP init
48
- *
49
- * @since 1.8
50
- */
51
- static function init()
52
- {
53
- //make sure Stripe is a gateway option
54
- add_filter('pmpro_gateways', array('PMProGateway_stripe', 'pmpro_gateways'));
55
-
56
- //add fields to payment settings
57
- add_filter('pmpro_payment_options', array('PMProGateway_stripe', 'pmpro_payment_options'));
58
- add_filter('pmpro_payment_option_fields', array('PMProGateway_stripe', 'pmpro_payment_option_fields'), 10, 2);
59
-
60
- //add some fields to edit user page (Updates)
61
- add_action('pmpro_after_membership_level_profile_fields', array('PMProGateway_stripe', 'user_profile_fields'));
62
- add_action('profile_update', array('PMProGateway_stripe', 'user_profile_fields_save'));
63
-
64
- //old global RE showing billing address or not
65
- global $pmpro_stripe_lite;
66
- $pmpro_stripe_lite = apply_filters("pmpro_stripe_lite", !pmpro_getOption("stripe_billingaddress")); //default is oposite of the stripe_billingaddress setting
67
-
68
- //updates cron
69
- add_action('pmpro_activation', array('PMProGateway_stripe', 'pmpro_activation'));
70
- add_action('pmpro_deactivation', array('PMProGateway_stripe', 'pmpro_deactivation'));
71
- add_action('pmpro_cron_stripe_subscription_updates', array('PMProGateway_stripe', 'pmpro_cron_stripe_subscription_updates'));
72
-
73
- //code to add at checkout if Stripe is the current gateway
74
- $gateway = pmpro_getOption("gateway");
75
- if($gateway == "stripe")
76
- {
77
- add_action('pmpro_checkout_preheader', array('PMProGateway_stripe', 'pmpro_checkout_preheader'));
78
- add_filter('pmpro_checkout_order', array('PMProGateway_stripe', 'pmpro_checkout_order'));
79
- add_filter('pmpro_include_billing_address_fields', array('PMProGateway_stripe', 'pmpro_include_billing_address_fields'));
80
- add_filter('pmpro_include_cardtype_field', array('PMProGateway_stripe', 'pmpro_include_billing_address_fields'));
81
- add_filter('pmpro_include_payment_information_fields', array('PMProGateway_stripe', 'pmpro_include_payment_information_fields'));
82
- }
83
- }
84
-
85
- /**
86
- * Make sure Stripe is in the gateways list
87
- *
88
- * @since 1.8
89
- */
90
- static function pmpro_gateways($gateways)
91
- {
92
- if(empty($gateways['stripe']))
93
- $gateways['stripe'] = __('Stripe', 'pmpro');
94
-
95
- return $gateways;
96
- }
97
-
98
- /**
99
- * Get a list of payment options that the Stripe gateway needs/supports.
100
- *
101
- * @since 1.8
102
- */
103
- static function getGatewayOptions()
104
- {
105
- $options = array(
106
- 'sslseal',
107
- 'nuclear_HTTPS',
108
- 'gateway_environment',
109
- 'stripe_secretkey',
110
- 'stripe_publishablekey',
111
- 'stripe_billingaddress',
112
- 'currency',
113
- 'use_ssl',
114
- 'tax_state',
115
- 'tax_rate',
116
- 'accepted_credit_cards'
117
- );
118
-
119
- return $options;
120
- }
121
-
122
- /**
123
- * Set payment options for payment settings page.
124
- *
125
- * @since 1.8
126
- */
127
- static function pmpro_payment_options($options)
128
- {
129
- //get stripe options
130
- $stripe_options = PMProGateway_stripe::getGatewayOptions();
131
-
132
- //merge with others.
133
- $options = array_merge($stripe_options, $options);
134
-
135
- return $options;
136
- }
137
-
138
- /**
139
- * Display fields for Stripe options.
140
- *
141
- * @since 1.8
142
- */
143
- static function pmpro_payment_option_fields($values, $gateway)
144
- {
145
- ?>
146
- <tr class="pmpro_settings_divider gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
147
- <td colspan="2">
148
- <?php _e('Stripe Settings', 'pmpro'); ?>
149
- </td>
150
- </tr>
151
- <tr class="gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
152
- <th scope="row" valign="top">
153
- <label for="stripe_secretkey"><?php _e('Secret Key', 'pmpro');?>:</label>
154
- </th>
155
- <td>
156
- <input type="text" id="stripe_secretkey" name="stripe_secretkey" size="60" value="<?php echo esc_attr($values['stripe_secretkey'])?>" />
157
- </td>
158
- </tr>
159
- <tr class="gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
160
- <th scope="row" valign="top">
161
- <label for="stripe_publishablekey"><?php _e('Publishable Key', 'pmpro');?>:</label>
162
- </th>
163
- <td>
164
- <input type="text" id="stripe_publishablekey" name="stripe_publishablekey" size="60" value="<?php echo esc_attr($values['stripe_publishablekey'])?>" />
165
- </td>
166
- </tr>
167
- <tr class="gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
168
- <th scope="row" valign="top">
169
- <label for="stripe_billingaddress"><?php _e('Show Billing Address Fields', 'pmpro');?>:</label>
170
- </th>
171
- <td>
172
- <select id="stripe_billingaddress" name="stripe_billingaddress">
173
- <option value="0" <?php if(empty($values['stripe_billingaddress'])) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
174
- <option value="1" <?php if(!empty($values['stripe_billingaddress'])) { ?>selected="selected"<?php } ?>><?php _e('Yes', 'pmpro');?></option>
175
- </select>
176
- <small><?php _e("Stripe doesn't require billing address fields. Choose 'No' to hide them on the checkout page.<br /><strong>If No, make sure you disable address verification in the Stripe dashboard settings.</strong>", 'pmpro');?></small>
177
- </td>
178
- </tr>
179
- <tr class="gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
180
- <th scope="row" valign="top">
181
- <label><?php _e('Web Hook URL', 'pmpro');?>:</label>
182
- </th>
183
- <td>
184
- <p><?php _e('To fully integrate with Stripe, be sure to set your Web Hook URL to', 'pmpro');?> <pre><?php echo admin_url("admin-ajax.php") . "?action=stripe_webhook";?></pre></p>
185
- </td>
186
- </tr>
187
- <?php
188
- }
189
-
190
- /**
191
- * Code added to checkout preheader.
192
- *
193
- * @since 1.8
194
- */
195
- static function pmpro_checkout_preheader()
196
- {
197
- global $gateway, $pmpro_level;
198
-
199
- if($gateway == "stripe" && !pmpro_isLevelFree($pmpro_level))
200
- {
201
- //stripe js library
202
- wp_enqueue_script("stripe", "https://js.stripe.com/v2/", array(), NULL);
203
-
204
- //stripe js code for checkout
205
- function pmpro_stripe_javascript()
206
- {
207
- global $pmpro_gateway, $pmpro_level, $pmpro_stripe_lite;
208
- ?>
209
- <script type="text/javascript">
210
- // this identifies your website in the createToken call below
211
- Stripe.setPublishableKey('<?php echo pmpro_getOption("stripe_publishablekey"); ?>');
212
-
213
- var pmpro_require_billing = true;
214
-
215
- jQuery(document).ready(function() {
216
- jQuery("#pmpro_form, .pmpro_form").submit(function(event) {
217
-
218
- //double check in case a discount code made the level free
219
- if(pmpro_require_billing)
220
- {
221
- //build array for creating token
222
- var args = {
223
- number: jQuery('#AccountNumber').val(),
224
- cvc: jQuery('#CVV').val(),
225
- exp_month: jQuery('#ExpirationMonth').val(),
226
- exp_year: jQuery('#ExpirationYear').val()
227
- <?php
228
- $pmpro_stripe_verify_address = apply_filters("pmpro_stripe_verify_address", pmpro_getOption('stripe_billingaddress'));
229
- if(!empty($pmpro_stripe_verify_address))
230
- {
231
- ?>
232
- ,address_line1: jQuery('#baddress1').val(),
233
- address_line2: jQuery('#baddress2').val(),
234
- address_city: jQuery('#bcity').val(),
235
- address_state: jQuery('#bstate').val(),
236
- address_zip: jQuery('#bzipcode').val(),
237
- address_country: jQuery('#bcountry').val()
238
- <?php
239
- }
240
- ?>
241
- };
242
-
243
- if (jQuery('#bfirstname').length && jQuery('#blastname').length)
244
- args['name'] = jQuery.trim(jQuery('#bfirstname').val() + ' ' + jQuery('#blastname').val());
245
-
246
- //create token
247
- Stripe.createToken(args, stripeResponseHandler);
248
-
249
- // prevent the form from submitting with the default action
250
- return false;
251
- }
252
- else
253
- return true; //not using Stripe anymore
254
- });
255
- });
256
-
257
- function stripeResponseHandler(status, response) {
258
- if (response.error) {
259
- // re-enable the submit button
260
- jQuery('.pmpro_btn-submit-checkout').removeAttr("disabled");
261
-
262
- //hide processing message
263
- jQuery('#pmpro_processing_message').css('visibility', 'hidden');
264
-
265
- // show the errors on the form
266
- alert(response.error.message);
267
- jQuery(".payment-errors").text(response.error.message);
268
- } else {
269
- var form$ = jQuery("#pmpro_form, .pmpro_form");
270
- // token contains id, last4, and card type
271
- var token = response['id'];
272
- // insert the token into the form so it gets submitted to the server
273
- form$.append("<input type='hidden' name='stripeToken' value='" + token + "'/>");
274
-
275
- console.log(response);
276
-
277
- //insert fields for other card fields
278
- if(jQuery('#CardType[name=CardType]').length)
279
- jQuery('#CardType').val(response['card']['brand']);
280
- else
281
- form$.append("<input type='hidden' name='CardType' value='" + response['card']['brand'] + "'/>");
282
- form$.append("<input type='hidden' name='AccountNumber' value='XXXXXXXXXXXXX" + response['card']['last4'] + "'/>");
283
- form$.append("<input type='hidden' name='ExpirationMonth' value='" + ("0" + response['card']['exp_month']).slice(-2) + "'/>");
284
- form$.append("<input type='hidden' name='ExpirationYear' value='" + response['card']['exp_year'] + "'/>");
285
-
286
- // and submit
287
- form$.get(0).submit();
288
- }
289
- }
290
- </script>
291
- <?php
292
- }
293
- add_action("wp_head", "pmpro_stripe_javascript");
294
-
295
- //don't require the CVV
296
- function pmpro_stripe_dont_require_CVV($fields)
297
- {
298
- unset($fields['CVV']);
299
- return $fields;
300
- }
301
- add_filter("pmpro_required_billing_fields", "pmpro_stripe_dont_require_CVV");
302
- }
303
- }
304
-
305
- /**
306
- * Filtering orders at checkout.
307
- *
308
- * @since 1.8
309
- */
310
- static function pmpro_checkout_order($morder)
311
- {
312
- //load up token values
313
- if(isset($_REQUEST['stripeToken']))
314
- {
315
- $morder->stripeToken = $_REQUEST['stripeToken'];
316
- }
317
-
318
- //stripe lite code to get name from other sources if available
319
- global $pmpro_stripe_lite, $current_user;
320
- if(!empty($pmpro_stripe_lite) && empty($morder->FirstName) && empty($morder->LastName))
321
- {
322
- if(!empty($current_user->ID))
323
- {
324
- $morder->FirstName = get_user_meta($current_user->ID, "first_name", true);
325
- $morder->LastName = get_user_meta($current_user->ID, "last_name", true);
326
- }
327
- elseif(!empty($_REQUEST['first_name']) && !empty($_REQUEST['last_name']))
328
- {
329
- $morder->FirstName = $_REQUEST['first_name'];
330
- $morder->LastName = $_REQUEST['last_name'];
331
- }
332
- }
333
-
334
- return $morder;
335
- }
336
-
337
- /**
338
- * Code to run after checkout
339
- *
340
- * @since 1.8
341
- */
342
- static function pmpro_after_checkout($user_id, $morder)
343
- {
344
- global $gateway;
345
-
346
- if($gateway == "stripe")
347
- {
348
- if(!empty($morder) && !empty($morer->Gateway) && !empty($morder->Gateway->customer) && !empty($morder->Gateway->customer->id))
349
- {
350
- update_user_meta($user_id, "pmpro_stripe_customerid", $morder->Gateway->customer->id);
351
- }
352
- }
353
- }
354
-
355
- /**
356
- * Check settings if billing address should be shown.
357
- * @since 1.8
358
- */
359
- static function pmpro_include_billing_address_fields($include)
360
- {
361
- //check settings RE showing billing address
362
- if(!pmpro_getOption("stripe_billingaddress"))
363
- $include = false;
364
-
365
- return $include;
366
- }
367
-
368
- /**
369
- * Use our own payment fields at checkout. (Remove the name attributes.)
370
- * @since 1.8
371
- */
372
- static function pmpro_include_payment_information_fields($include)
373
- {
374
- //global vars
375
- global $pmpro_requirebilling, $pmpro_show_discount_code, $discount_code, $CardType, $AccountNumber, $ExpirationMonth, $ExpirationYear;
376
-
377
- //get accepted credit cards
378
- $pmpro_accepted_credit_cards = pmpro_getOption("accepted_credit_cards");
379
- $pmpro_accepted_credit_cards = explode(",", $pmpro_accepted_credit_cards);
380
- $pmpro_accepted_credit_cards_string = pmpro_implodeToEnglish($pmpro_accepted_credit_cards);
381
-
382
- //include ours
383
- ?>
384
- <table id="pmpro_payment_information_fields" class="pmpro_checkout top1em" width="100%" cellpadding="0" cellspacing="0" border="0" <?php if(!$pmpro_requirebilling || apply_filters("pmpro_hide_payment_information_fields", false) ) { ?>style="display: none;"<?php } ?>>
385
- <thead>
386
- <tr>
387
- <th><span class="pmpro_thead-msg"><?php printf(__('We Accept %s', 'pmpro'), $pmpro_accepted_credit_cards_string);?></span><?php _e('Payment Information', 'pmpro');?></th>
388
- </tr>
389
- </thead>
390
- <tbody>
391
- <tr valign="top">
392
- <td>
393
- <?php
394
- $sslseal = pmpro_getOption("sslseal");
395
- if($sslseal)
396
- {
397
- ?>
398
- <div class="pmpro_sslseal"><?php echo stripslashes($sslseal)?></div>
399
- <?php
400
- }
401
- ?>
402
- <?php
403
- $pmpro_include_cardtype_field = apply_filters('pmpro_include_cardtype_field', false);
404
- if($pmpro_include_cardtype_field)
405
- {
406
- ?>
407
- <div class="pmpro_payment-card-type">
408
- <label for="CardType"><?php _e('Card Type', 'pmpro');?></label>
409
- <select id="CardType" class=" <?php echo pmpro_getClassForField("CardType");?>">
410
- <?php foreach($pmpro_accepted_credit_cards as $cc) { ?>
411
- <option value="<?php echo $cc?>" <?php if($CardType == $cc) { ?>selected="selected"<?php } ?>><?php echo $cc?></option>
412
- <?php } ?>
413
- </select>
414
- </div>
415
- <?php
416
- }
417
- else
418
- {
419
- ?>
420
- <input type="hidden" id="CardType" name="CardType" value="<?php echo esc_attr($CardType);?>" />
421
- <script>
422
- jQuery(document).ready(function() {
423
- jQuery('#AccountNumber').validateCreditCard(function(result) {
424
- var cardtypenames = {
425
- "amex":"American Express",
426
- "diners_club_carte_blanche":"Diners Club Carte Blanche",
427
- "diners_club_international":"Diners Club International",
428
- "discover":"Discover",
429
- "jcb":"JCB",
430
- "laser":"Laser",
431
- "maestro":"Maestro",
432
- "mastercard":"Mastercard",
433
- "visa":"Visa",
434
- "visa_electron":"Visa Electron"
435
- }
436
-
437
- if(result.card_type)
438
- jQuery('#CardType').val(cardtypenames[result.card_type.name]);
439
- else
440
- jQuery('#CardType').val('Unknown Card Type');
441
- });
442
- });
443
- </script>
444
- <?php
445
- }
446
- ?>
447
-
448
- <div class="pmpro_payment-account-number">
449
- <label for="AccountNumber"><?php _e('Card Number', 'pmpro');?></label>
450
- <input id="AccountNumber" class="input <?php echo pmpro_getClassForField("AccountNumber");?>" type="text" size="25" value="<?php echo esc_attr($AccountNumber)?>" autocomplete="off" />
451
- </div>
452
-
453
- <div class="pmpro_payment-expiration">
454
- <label for="ExpirationMonth"><?php _e('Expiration Date', 'pmpro');?></label>
455
- <select id="ExpirationMonth" class=" <?php echo pmpro_getClassForField("ExpirationMonth");?>">
456
- <option value="01" <?php if($ExpirationMonth == "01") { ?>selected="selected"<?php } ?>>01</option>
457
- <option value="02" <?php if($ExpirationMonth == "02") { ?>selected="selected"<?php } ?>>02</option>
458
- <option value="03" <?php if($ExpirationMonth == "03") { ?>selected="selected"<?php } ?>>03</option>
459
- <option value="04" <?php if($ExpirationMonth == "04") { ?>selected="selected"<?php } ?>>04</option>
460
- <option value="05" <?php if($ExpirationMonth == "05") { ?>selected="selected"<?php } ?>>05</option>
461
- <option value="06" <?php if($ExpirationMonth == "06") { ?>selected="selected"<?php } ?>>06</option>
462
- <option value="07" <?php if($ExpirationMonth == "07") { ?>selected="selected"<?php } ?>>07</option>
463
- <option value="08" <?php if($ExpirationMonth == "08") { ?>selected="selected"<?php } ?>>08</option>
464
- <option value="09" <?php if($ExpirationMonth == "09") { ?>selected="selected"<?php } ?>>09</option>
465
- <option value="10" <?php if($ExpirationMonth == "10") { ?>selected="selected"<?php } ?>>10</option>
466
- <option value="11" <?php if($ExpirationMonth == "11") { ?>selected="selected"<?php } ?>>11</option>
467
- <option value="12" <?php if($ExpirationMonth == "12") { ?>selected="selected"<?php } ?>>12</option>
468
- </select>/<select id="ExpirationYear" class=" <?php echo pmpro_getClassForField("ExpirationYear");?>">
469
- <?php
470
- for($i = date("Y"); $i < date("Y") + 10; $i++)
471
- {
472
- ?>
473
- <option value="<?php echo $i?>" <?php if($ExpirationYear == $i) { ?>selected="selected"<?php } ?>><?php echo $i?></option>
474
- <?php
475
- }
476
- ?>
477
- </select>
478
- </div>
479
-
480
- <?php
481
- $pmpro_show_cvv = apply_filters("pmpro_show_cvv", true);
482
- if($pmpro_show_cvv)
483
- {
484
- ?>
485
- <div class="pmpro_payment-cvv">
486
- <label for="CVV"><?php _ex('CVV', 'Credit card security code, CVV/CCV/CVV2', 'pmpro');?></label>
487
- <input class="input" id="CVV" type="text" size="4" value="<?php if(!empty($_REQUEST['CVV'])) { echo esc_attr($_REQUEST['CVV']); }?>" class=" <?php echo pmpro_getClassForField("CVV");?>" /> <small>(<a href="javascript:void(0);" onclick="javascript:window.open('<?php echo pmpro_https_filter(PMPRO_URL)?>/pages/popup-cvv.html','cvv','toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=600, height=475');"><?php _ex("what's this?", 'link to CVV help', 'pmpro');?></a>)</small>
488
- </div>
489
- <?php
490
- }
491
- ?>
492
-
493
- <?php if($pmpro_show_discount_code) { ?>
494
- <div class="pmpro_payment-discount-code">
495
- <label for="discount_code"><?php _e('Discount Code', 'pmpro');?></label>
496
- <input class="input <?php echo pmpro_getClassForField("discount_code");?>" id="discount_code" name="discount_code" type="text" size="20" value="<?php echo esc_attr($discount_code)?>" />
497
- <input type="button" id="discount_code_button" name="discount_code_button" value="<?php _e('Apply', 'pmpro');?>" />
498
- <p id="discount_code_message" class="pmpro_message" style="display: none;"></p>
499
- </div>
500
- <?php } ?>
501
-
502
- </td>
503
- </tr>
504
- </tbody>
505
- </table>
506
- <?php
507
-
508
- //don't include the default
509
- return false;
510
- }
511
-
512
- /**
513
- * Fields shown on edit user page
514
- *
515
- * @since 1.8
516
- */
517
- static function user_profile_fields($user)
518
- {
519
- global $wpdb, $current_user, $pmpro_currency_symbol;
520
-
521
- $cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
522
- $current_year = date("Y");
523
- $current_month = date("m");
524
-
525
- //make sure the current user has privileges
526
- $membership_level_capability = apply_filters("pmpro_edit_member_capability", "manage_options");
527
- if(!current_user_can($membership_level_capability))
528
- return false;
529
-
530
- //more privelges they should have
531
- $show_membership_level = apply_filters("pmpro_profile_show_membership_level", true, $user);
532
- if(!$show_membership_level)
533
- return false;
534
-
535
- //check that user has a current subscription at Stripe
536
- $last_order = new MemberOrder();
537
- $last_order->getLastMemberOrder($user->ID);
538
-
539
- //assume no sub to start
540
- $sub = false;
541
-
542
- //check that gateway is Stripe
543
- if($last_order->gateway == "stripe")
544
- {
545
- //is there a customer?
546
- $sub = $last_order->Gateway->getSubscription($last_order);
547
- }
548
-
549
- $customer_id = $user->pmpro_stripe_customerid;
550
-
551
- if(empty($sub))
552
- {
553
- //make sure we delete stripe updates
554
- update_user_meta($user->ID, "pmpro_stripe_updates", array());
555
-
556
- //if the last order has a sub id, let the admin know there is no sub at Stripe
557
- if(!empty($last_order) && $last_order->gateway == "stripe" && !empty($last_order->subscription_transaction_id) && strpos($last_order->subscription_transaction_id, "sub_") !== false)
558
- {
559
- ?>
560
- <p><strong>Note:</strong> Subscription <strong><?php echo $last_order->subscription_transaction_id;?></strong> could not be found at Stripe. It might have been deleted.</p>
561
- <?php
562
- }
563
- }
564
- else
565
- {
566
- ?>
567
- <h3><?php _e("Subscription Updates", "pmpro"); ?></h3>
568
- <p>
569
- <?php
570
- if(empty($_REQUEST['user_id']))
571
- _e("Subscription updates, allow you to change the member's subscription values at predefined times. Be sure to click Update Profile after making changes.", 'pmpro');
572
- else
573
- _e("Subscription updates, allow you to change the member's subscription values at predefined times. Be sure to click Update User after making changes.", 'pmpro');
574
- ?>
575
- </p>
576
- <table class="form-table">
577
- <tr>
578
- <th><label for="membership_level"><?php _e("Update", "pmpro"); ?></label></th>
579
- <td id="updates_td">
580
- <?php
581
- $old_updates = $user->pmpro_stripe_updates;
582
- if(is_array($old_updates))
583
- {
584
- $updates = array_merge(
585
- array(array('template'=>true, 'when'=>'now', 'date_month'=>'', 'date_day'=>'', 'date_year'=>'', 'billing_amount'=>'', 'cycle_number'=>'', 'cycle_period'=>'Month')),
586
- $old_updates
587
- );
588
- }
589
- else
590
- $updates = array(array('template'=>true, 'when'=>'now', 'date_month'=>'', 'date_day'=>'', 'date_year'=>'', 'billing_amount'=>'', 'cycle_number'=>'', 'cycle_period'=>'Month'));
591
-
592
- foreach($updates as $update)
593
- {
594
- ?>
595
- <div class="updates_update" <?php if(!empty($update['template'])) { ?>style="display: none;"<?php } ?>>
596
- <select class="updates_when" name="updates_when[]">
597
- <option value="now" <?php selected($update['when'], "now");?>>Now</option>
598
- <option value="payment" <?php selected($update['when'], "payment");?>>After Next Payment</option>
599
- <option value="date" <?php selected($update['when'], "date");?>>On Date</option>
600
- </select>
601
- <span class="updates_date" <?php if($uwhen != "date") { ?>style="display: none;"<?php } ?>>
602
- <select name="updates_date_month[]">
603
- <?php
604
- for($i = 1; $i < 13; $i++)
605
- {
606
- ?>
607
- <option value="<?php echo str_pad($i, 2, "0", STR_PAD_LEFT);?>" <?php if(!empty($update['date_month']) && $update['date_month'] == $i) { ?>selected="selected"<?php } ?>>
608
- <?php echo date("M", strtotime($i . "/1/" . $current_year));?>
609
- </option>
610
- <?php
611
- }
612
- ?>
613
- </select>
614
- <input name="updates_date_day[]" type="text" size="2" value="<?php if(!empty($update['date_day'])) echo esc_attr($update['date_day']);?>" />
615
- <input name="updates_date_year[]" type="text" size="4" value="<?php if(!empty($update['date_year'])) echo esc_attr($update['date_year']);?>" />
616
- </span>
617
- <span class="updates_billing" <?php if($uwhen == "no") { ?>style="display: none;"<?php } ?>>
618
- <?php echo $pmpro_currency_symbol?><input name="updates_billing_amount[]" type="text" size="10" value="<?php echo esc_attr($update['billing_amount']);?>" />
619
- <small><?php _e('per', 'pmpro');?></small>
620
- <input name="updates_cycle_number[]" type="text" size="5" value="<?php echo esc_attr($update['cycle_number']);?>" />
621
- <select name="updates_cycle_period[]">
622
- <?php
623
- foreach ( $cycles as $name => $value ) {
624
- echo "<option value='$value'";
625
- if(!empty($update['cycle_period']) && $update['cycle_period'] == $value) echo " selected='selected'";
626
- echo ">$name</option>";
627
- }
628
- ?>
629
- </select>
630
- </span>
631
- <span>
632
- <a class="updates_remove" href="javascript:void(0);">Remove</a>
633
- </span>
634
- </div>
635
- <?php
636
- }
637
- ?>
638
- <p><a id="updates_new_update" href="javascript:void(0);">+ New Update</a></p>
639
- </td>
640
- </tr>
641
- </table>
642
- <script>
643
- jQuery(document).ready(function() {
644
- //function to update dropdowns/etc based on when field
645
- function updateSubscriptionUpdateFields(when)
646
- {
647
- if(jQuery(when).val() == 'date')
648
- jQuery(when).parent().children('.updates_date').show();
649
- else
650
- jQuery(when).parent().children('.updates_date').hide();
651
-
652
- if(jQuery(when).val() == 'no')
653
- jQuery(when).parent().children('.updates_billing').hide();
654
- else
655
- jQuery(when).parent().children('.updates_billing').show();
656
- }
657
-
658
- //and update on page load
659
- jQuery('.updates_when').each(function() { if(jQuery(this).parent().css('display') != 'none') updateSubscriptionUpdateFields(this); });
660
-
661
- //add a new update when clicking to
662
- var num_updates_divs = <?php echo count($updates);?>;
663
- jQuery('#updates_new_update').click(function() {
664
- //get updates
665
- updates = jQuery('.updates_update').toArray();
666
-
667
- //clone the first one
668
- new_div = jQuery(updates[0]).clone();
669
-
670
- //append
671
- new_div.insertBefore('#updates_new_update');
672
-
673
- //update events
674
- addUpdateEvents()
675
-
676
- //unhide it
677
- new_div.show();
678
- updateSubscriptionUpdateFields(new_div.children('.updates_when'));
679
- });
680
-
681
- function addUpdateEvents()
682
- {
683
- //update when when changes
684
- jQuery('.updates_when').change(function() {
685
- updateSubscriptionUpdateFields(this);
686
- });
687
-
688
- //remove updates when clicking
689
- jQuery('.updates_remove').click(function() {
690
- jQuery(this).parent().parent().remove();
691
- });
692
- }
693
- addUpdateEvents();
694
- });
695
- </script>
696
- <?php
697
- }
698
- }
699
-
700
- /**
701
- * Process fields from the edit user page
702
- *
703
- * @since 1.8
704
- */
705
- static function user_profile_fields_save($user_id)
706
- {
707
- global $wpdb;
708
-
709
- //check capabilities
710
- $membership_level_capability = apply_filters("pmpro_edit_member_capability", "manage_options");
711
- if(!current_user_can($membership_level_capability))
712
- return false;
713
-
714
- //make sure some value was passed
715
- if(!isset($_POST['updates_when']) || !is_array($_POST['updates_when']))
716
- return;
717
-
718
- //vars
719
- $updates = array();
720
- $next_on_date_update = "";
721
-
722
- //build array of updates (we skip the first because it's the template field for the JavaScript
723
- for($i = 1; $i < count($_POST['updates_when']); $i++)
724
- {
725
- $update = array();
726
-
727
- //all updates have these values
728
- $update['when'] = $_POST['updates_when'][$i];
729
- $update['billing_amount'] = $_POST['updates_billing_amount'][$i];
730
- $update['cycle_number'] = $_POST['updates_cycle_number'][$i];
731
- $update['cycle_period'] = $_POST['updates_cycle_period'][$i];
732
-
733
- //these values only for on date updates
734
- if($_POST['updates_when'][$i] == "date")
735
- {
736
- $update['date_month'] = str_pad($_POST['updates_date_month'][$i], 2, "0", STR_PAD_LEFT);
737
- $update['date_day'] = str_pad($_POST['updates_date_day'][$i], 2, "0", STR_PAD_LEFT);
738
- $update['date_year'] = $_POST['updates_date_year'][$i];
739
- }
740
-
741
- //make sure the update is valid
742
- if(empty($update['cycle_number']))
743
- continue;
744
-
745
- //if when is now, update the subscription
746
- if($update['when'] == "now")
747
- {
748
- //get level for user
749
- $user_level = pmpro_getMembershipLevelForUser($user_id);
750
-
751
- //get current plan at Stripe to get payment date
752
- $last_order = new MemberOrder();
753
- $last_order->getLastMemberOrder($user_id);
754
- $last_order->setGateway('stripe');
755
- $last_order->Gateway->getCustomer($last_order);
756
-
757
- $subscription = $last_order->Gateway->getSubscription($last_order);
758
-
759
- if(!empty($subscription))
760
- {
761
- $end_timestamp = $subscription->current_period_end;
762
-
763
- //cancel the old subscription
764
- if(!$last_order->Gateway->cancelSubscriptionAtGateway($subscription))
765
- {
766
- //throw error and halt save
767
- function pmpro_stripe_user_profile_fields_save_error($errors, $update, $user)
768
- {
769
- $errors->add('pmpro_stripe_updates',__('Could not cancel the old subscription. Updates have not been processed.', 'pmpro'));
770
- }
771
- add_filter('user_profile_update_errors', 'pmpro_stripe_user_profile_fields_save_error', 10, 3);
772
-
773
- //stop processing updates
774
- return;
775
- }
776
- }
777
-
778
- //if we didn't get an end date, let's set one one cycle out
779
- if(empty($end_timestamp))
780
- $end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period'], current_time('timestamp'));
781
-
782
- //build order object
783
- $update_order = new MemberOrder();
784
- $update_order->setGateway('stripe');
785
- $update_order->user_id = $user_id;
786
- $update_order->membership_id = $user_level->id;
787
- $update_order->membership_name = $user_level->name;
788
- $update_order->InitialPayment = 0;
789
- $update_order->PaymentAmount = $update['billing_amount'];
790
- $update_order->ProfileStartDate = date("Y-m-d", $end_timestamp);
791
- $update_order->BillingPeriod = $update['cycle_period'];
792
- $update_order->BillingFrequency = $update['cycle_number'];
793
-
794
- //need filter to reset ProfileStartDate
795
- add_filter('pmpro_profile_start_date', create_function('$startdate, $order', 'return "' . $update_order->ProfileStartDate . 'T0:0:0";'), 10, 2);
796
-
797
- //update subscription
798
- $update_order->Gateway->subscribe($update_order, false);
799
-
800
- //update membership
801
- $sqlQuery = "UPDATE $wpdb->pmpro_memberships_users
802
- SET billing_amount = '" . esc_sql($update['billing_amount']) . "',
803
- cycle_number = '" . esc_sql($update['cycle_number']) . "',
804
- cycle_period = '" . esc_sql($update['cycle_period']) . "',
805
- trial_amount = '',
806
- trial_limit = ''
807
- WHERE user_id = '" . esc_sql($user_id) . "'
808
- AND membership_id = '" . esc_sql($last_order->membership_id) . "'
809
- AND status = 'active'
810
- LIMIT 1";
811
-
812
- $wpdb->query($sqlQuery);
813
-
814
- //save order so we know which plan to look for at stripe (order code = plan id)
815
- $update_order->status = "success";
816
- $update_order->saveOrder();
817
-
818
- continue;
819
- }
820
- elseif($update['when'] == 'date')
821
- {
822
- if(!empty($next_on_date_update))
823
- $next_on_date_update = min($next_on_date_update, $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day']);
824
- else
825
- $next_on_date_update = $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'];
826
- }
827
-
828
- //add to array
829
- $updates[] = $update;
830
- }
831
-
832
- //save in user meta
833
- update_user_meta($user_id, "pmpro_stripe_updates", $updates);
834
-
835
- //save date of next on-date update to make it easier to query for these in cron job
836
- update_user_meta($user_id, "pmpro_stripe_next_on_date_update", $next_on_date_update);
837
- }
838
-
839
- /**
840
- * Cron activation for subscription updates.
841
- *
842
- * @since 1.8
843
- */
844
- static function pmpro_activation()
845
- {
846
- wp_schedule_event(time(), 'daily', 'pmpro_cron_stripe_subscription_updates');
847
- }
848
-
849
- /**
850
- * Cron deactivation for subscription updates.
851
- *
852
- * @since 1.8
853
- */
854
- static function pmpro_deactivation()
855
- {
856
- wp_clear_scheduled_hook('pmpro_cron_stripe_subscription_updates');
857
- }
858
-
859
- /**
860
- * Cron job for subscription updates.
861
- *
862
- * @since 1.8
863
- */
864
- static function pmpro_cron_stripe_subscription_updates()
865
- {
866
- global $wpdb;
867
-
868
- //get all updates for today (or before today)
869
- $sqlQuery = "SELECT *
870
- FROM $wpdb->usermeta
871
- WHERE meta_key = 'pmpro_stripe_next_on_date_update'
872
- AND meta_value IS NOT NULL
873
- AND meta_value <> ''
874
- AND meta_value < '" . date("Y-m-d", strtotime("+1 day")) . "'";
875
- $updates = $wpdb->get_results($sqlQuery);
876
-
877
- if(!empty($updates))
878
- {
879
- //loop through
880
- foreach($updates as $update)
881
- {
882
- //pull values from update
883
- $user_id = $update->user_id;
884
-
885
- $user = get_userdata($user_id);
886
-
887
- //if user is missing, delete the update info and continue
888
- if(empty($user) || empty($user->ID))
889
- {
890
- delete_user_meta($user_id, "pmpro_stripe_updates");
891
- delete_user_meta($user_id, "pmpro_stripe_next_on_date_update");
892
-
893
- continue;
894
- }
895
-
896
- $user_updates = $user->pmpro_stripe_updates;
897
- $next_on_date_update = "";
898
-
899
- //loop through updates looking for updates happening today or earlier
900
- if(!empty($user_updates))
901
- {
902
- foreach($user_updates as $key => $update)
903
- {
904
- if($update['when'] == 'date' &&
905
- $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'] <= date("Y-m-d")
906
- )
907
- {
908
- //get level for user
909
- $user_level = pmpro_getMembershipLevelForUser($user_id);
910
-
911
- //get current plan at Stripe to get payment date
912
- $last_order = new MemberOrder();
913
- $last_order->getLastMemberOrder($user_id);
914
- $last_order->setGateway('stripe');
915
- $last_order->Gateway->getCustomer($last_order);
916
-
917
- if(!empty($last_order->Gateway->customer))
918
- {
919
- //find the first subscription
920
- if(!empty($last_order->Gateway->customer->subscriptions['data'][0]))
921
- {
922
- $first_sub = $last_order->Gateway->customer->subscriptions['data'][0]->__toArray();
923
- $end_timestamp = $first_sub['current_period_end'];
924
- }
925
- }
926
-
927
- //if we didn't get an end date, let's set one one cycle out
928
- $end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period']);
929
-
930
- //build order object
931
- $update_order = new MemberOrder();
932
- $update_order->setGateway('stripe');
933
- $update_order->user_id = $user_id;
934
- $update_order->membership_id = $user_level->id;
935
- $update_order->membership_name = $user_level->name;
936
- $update_order->InitialPayment = 0;
937
- $update_order->PaymentAmount = $update['billing_amount'];
938
- $update_order->ProfileStartDate = date("Y-m-d", $end_timestamp);
939
- $update_order->BillingPeriod = $update['cycle_period'];
940
- $update_order->BillingFrequency = $update['cycle_number'];
941
-
942
- //update subscription
943
- $update_order->Gateway->subscribe($update_order, false);
944
-
945
- //update membership
946
- $sqlQuery = "UPDATE $wpdb->pmpro_memberships_users
947
- SET billing_amount = '" . esc_sql($update['billing_amount']) . "',
948
- cycle_number = '" . esc_sql($update['cycle_number']) . "',
949
- cycle_period = '" . esc_sql($update['cycle_period']) . "'
950
- WHERE user_id = '" . esc_sql($user_id) . "'
951
- AND membership_id = '" . esc_sql($last_order->membership_id) . "'
952
- AND status = 'active'
953
- LIMIT 1";
954
-
955
- $wpdb->query($sqlQuery);
956
-
957
- //save order
958
- $update_order->status = "success";
959
- $update_order->save();
960
-
961
- //remove update from list
962
- unset($user_updates[$key]);
963
- }
964
- elseif($update['when'] == 'date')
965
- {
966
- //this is an on date update for the future, update the next on date update
967
- if(!empty($next_on_date_update))
968
- $next_on_date_update = min($next_on_date_update, $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day']);
969
- else
970
- $next_on_date_update = $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'];
971
- }
972
- }
973
- }
974
-
975
- //save updates in case we removed some
976
- update_user_meta($user_id, "pmpro_stripe_updates", $user_updates);
977
-
978
- //save date of next on-date update to make it easier to query for these in cron job
979
- update_user_meta($user_id, "pmpro_stripe_next_on_date_update", $next_on_date_update);
980
- }
981
- }
982
- }
983
-
984
- /**
985
- * Process checkout and decide if a charge and or subscribe is needed
986
- *
987
- * @since 1.4
988
- */
989
- function process(&$order)
990
- {
991
- //check for initial payment
992
- if(floatval($order->InitialPayment) == 0)
993
- {
994
- //just subscribe
995
- return $this->subscribe($order);
996
- }
997
- else
998
- {
999
- //charge then subscribe
1000
- if($this->charge($order))
1001
- {
1002
- if(pmpro_isLevelRecurring($order->membership_level))
1003
- {
1004
- if($this->subscribe($order))
1005
- {
1006
- //yay!
1007
- return true;
1008
- }
1009
- else
1010
- {
1011
- //try to refund initial charge
1012
- return false;
1013
- }
1014
- }
1015
- else
1016
- {
1017
- //only a one time charge
1018
- $order->status = "success"; //saved on checkout page
1019
- return true;
1020
- }
1021
- }
1022
- else
1023
- {
1024
- if(empty($order->error))
1025
- $order->error = __("Unknown error: Initial payment failed.", "pmpro");
1026
- return false;
1027
- }
1028
- }
1029
- }
1030
-
1031
- /**
1032
- * Make a one-time charge with Stripe
1033
- *
1034
- * @since 1.4
1035
- */
1036
- function charge(&$order)
1037
- {
1038
- global $pmpro_currency;
1039
-
1040
- //create a code for the order
1041
- if(empty($order->code))
1042
- $order->code = $order->getRandomCode();
1043
-
1044
- //what amount to charge?
1045
- $amount = $order->InitialPayment;
1046
-
1047
- //tax
1048
- $order->subtotal = $amount;
1049
- $tax = $order->getTax(true);
1050
- $amount = round((float)$order->subtotal + (float)$tax, 2);
1051
-
1052
- //create a customer
1053
- $result = $this->getCustomer($order);
1054
-
1055
- if(empty($result))
1056
- {
1057
- //failed to create customer
1058
- return false;
1059
- }
1060
-
1061
- //charge
1062
- try
1063
- {
1064
- $response = Stripe_Charge::create(array(
1065
- "amount" => $amount * 100, # amount in cents, again
1066
- "currency" => strtolower($pmpro_currency),
1067
- "customer" => $this->customer->id,
1068
- "description" => "Order #" . $order->code . ", " . trim($order->FirstName . " " . $order->LastName) . " (" . $order->Email . ")"
1069
- )
1070
- );
1071
- }
1072
- catch (Exception $e)
1073
- {
1074
- //$order->status = "error";
1075
- $order->errorcode = true;
1076
- $order->error = "Error: " . $e->getMessage();
1077
- $order->shorterror = $order->error;
1078
- return false;
1079
- }
1080
-
1081
- if(empty($response["failure_message"]))
1082
- {
1083
- //successful charge
1084
- $order->payment_transaction_id = $response["id"];
1085
- $order->updateStatus("success");
1086
- $order->saveOrder();
1087
- return true;
1088
- }
1089
- else
1090
- {
1091
- //$order->status = "error";
1092
- $order->errorcode = true;
1093
- $order->error = $response['failure_message'];
1094
- $order->shorterror = $response['failure_message'];
1095
- return false;
1096
- }
1097
- }
1098
-
1099
- /**
1100
- * Get a Stripe customer object.
1101
- *
1102
- * If $this->customer is set, it returns it.
1103
- * It first checks if the order has a subscription_transaction_id. If so, that's the customer id.
1104
- * If not, it checks for a user_id on the order and searches for a customer id in the user meta.
1105
- * If a customer id is found, it checks for a customer through the Stripe API.
1106
- * If a customer is found and there is a stripeToken on the order passed, it will update the customer.
1107
- * If no customer is found and there is a stripeToken on the order passed, it will create a customer.
1108
- *
1109
- * @since 1.4
1110
- * @return Stripe_Customer|false
1111
- */
1112
- function getCustomer(&$order = false, $force = false)
1113
- {
1114
- global $current_user;
1115
-
1116
- //already have it?
1117
- if(!empty($this->customer) && !$force)
1118
- return $this->customer;
1119
-
1120
- //figure out user_id and user
1121
- if(!empty($order->user_id))
1122
- $user_id = $order->user_id;
1123
-
1124
- //if no id passed, check the current user
1125
- if(empty($user_id) && !empty($current_user->ID))
1126
- $user_id = $current_user->ID;
1127
-
1128
- if(!empty($user_id))
1129
- $user = get_userdata($user_id);
1130
- else
1131
- $user = NULL;
1132
-
1133
- //transaction id?
1134
- if(!empty($order->subscription_transaction_id) && strpos($order->subscription_transaction_id, "cus_") !== false)
1135
- $customer_id = $order->subscription_transaction_id;
1136
- else
1137
- {
1138
- //try based on user id
1139
- if(!empty($user_id))
1140
- {
1141
- $customer_id = get_user_meta($user_id, "pmpro_stripe_customerid", true);
1142
- }
1143
- }
1144
-
1145
- //get name and email values from order in case we update
1146
- $name = trim($order->FirstName . " " . $order->LastName);
1147
- if(empty($name) && !empty($user->ID))
1148
- {
1149
- $name = trim($user->first_name . " " . $user->last_name);
1150
-
1151
- //still empty?
1152
- if(empty($name))
1153
- $name = $user->user_login;
1154
- }
1155
- elseif(empty($name))
1156
- $name = "No Name";
1157
-
1158
- $email = $order->Email;
1159
- if(empty($email) && !empty($user->ID))
1160
- {
1161
- $email = $user->user_email;
1162
- }
1163
- elseif(empty($email))
1164
- $email = "No Email";
1165
-
1166
- //check for an existing stripe customer
1167
- if(!empty($customer_id))
1168
- {
1169
- try
1170
- {
1171
- $this->customer = Stripe_Customer::retrieve($customer_id);
1172
-
1173
- //update the customer description and card
1174
- if(!empty($order->stripeToken))
1175
- {
1176
- $this->customer->description = $name . " (" . $email . ")";
1177
- $this->customer->email = $email;
1178
- $this->customer->card = $order->stripeToken;
1179
- $this->customer->save();
1180
- }
1181
-
1182
- return $this->customer;
1183
- }
1184
- catch (Exception $e)
1185
- {
1186
- //assume no customer found
1187
- }
1188
- }
1189
-
1190
- //no customer id, create one
1191
- if(!empty($order->stripeToken))
1192
- {
1193
- try
1194
- {
1195
- $this->customer = Stripe_Customer::create(array(
1196
- "description" => trim($order->FirstName . " " . $order->LastName) . " (" . $order->Email . ")",
1197
- "email" => $order->Email,
1198
- "card" => $order->stripeToken
1199
- ));
1200
- }
1201
- catch (Exception $e)
1202
- {
1203
- $order->error = __("Error creating customer record with Stripe:", "pmpro") . " " . $e->getMessage();
1204
- $order->shorterror = $order->error;
1205
- return false;
1206
- }
1207
-
1208
- if(!empty($user_id))
1209
- {
1210
- //user logged in/etc
1211
- update_user_meta($user_id, "pmpro_stripe_customerid", $this->customer->id);
1212
- }
1213
- else
1214
- {
1215
- //user not registered yet, queue it up
1216
- global $pmpro_stripe_customer_id;
1217
- $pmpro_stripe_customer_id = $this->customer->id;
1218
- function pmpro_user_register_stripe_customerid($user_id)
1219
- {
1220
- global $pmpro_stripe_customer_id;
1221
- update_user_meta($user_id, "pmpro_stripe_customerid", $pmpro_stripe_customer_id);
1222
- }
1223
- add_action("user_register", "pmpro_user_register_stripe_customerid");
1224
- }
1225
-
1226
- return apply_filters('pmpro_stripe_create_customer', $this->customer);
1227
- }
1228
-
1229
- return false;
1230
- }
1231
-
1232
- /**
1233
- * Get a Stripe subscription from a PMPro order
1234
- *
1235
- * @since 1.8
1236
- */
1237
- function getSubscription(&$order)
1238
- {
1239
- global $wpdb;
1240
-
1241
- //no order?
1242
- if(empty($order) || empty($order->code))
1243
- return false;
1244
-
1245
- $result = $this->getCustomer($order, true); //force so we don't get a cached sub for someone else
1246
-
1247
- //no customer?
1248
- if(empty($result))
1249
- return false;
1250
-
1251
- //is there a subscription transaction id pointing to a sub?
1252
- if(!empty($order->subscription_transaction_id) && strpos($order->subscription_transaction_id, "sub_") !== false)
1253
- {
1254
- try
1255
- {
1256
- $sub = $this->customer->subscriptions->retrieve($order->subscription_transaction_id);
1257
- }
1258
- catch (Exception $e)
1259
- {
1260
- $order->error = __("Error creating plan with Stripe:", "pmpro") . $e->getMessage();
1261
- $order->shorterror = $order->error;
1262
- return false;
1263
- }
1264
-
1265
- return $sub;
1266
- }
1267
-
1268
- //no subscriptions object in customer
1269
- if(empty($this->customer->subscriptions))
1270
- return false;
1271
-
1272
- //find subscription based on customer id and order/plan id
1273
- $subscriptions = $this->customer->subscriptions->all();
1274
-
1275
- //no subscriptions
1276
- if(empty($subscriptions) || empty($subscriptions->data))
1277
- return false;
1278
-
1279
- //we really want to test against the order codes of all orders with the same subscription_transaction_id (customer id)
1280
- $codes = $wpdb->get_col("SELECT code FROM $wpdb->pmpro_membership_orders WHERE user_id = '" . $order->user_id . "' AND subscription_transaction_id = '" . $order->subscription_transaction_id . "' AND status NOT IN('refunded', 'review', 'token', 'error')");
1281
-
1282
- //find the one for this order
1283
- foreach($subscriptions->data as $sub)
1284
- {
1285
- if(in_array($sub->plan->id, $codes))
1286
- {
1287
- return $sub;
1288
- }
1289
- }
1290
-
1291
- //didn't find anything yet
1292
- return false;
1293
- }
1294
-
1295
- /**
1296
- * Create a new subscription with Stripe
1297
- *
1298
- * @since 1.4
1299
- */
1300
- function subscribe(&$order, $checkout = true)
1301
- {
1302
- global $pmpro_currency;
1303
-
1304
- //create a code for the order
1305
- if(empty($order->code))
1306
- $order->code = $order->getRandomCode();
1307
-
1308
- //filter order before subscription. use with care.
1309
- $order = apply_filters("pmpro_subscribe_order", $order, $this);
1310
-
1311
- //figure out the user
1312
- if(!empty($order->user_id))
1313
- $user_id = $order->user_id;
1314
- else
1315
- {
1316
- global $current_user;
1317
- $user_id = $current_user->ID;
1318
- }
1319
-
1320
- //setup customer
1321
- $result = $this->getCustomer($order);
1322
- if(empty($result))
1323
- return false; //error retrieving customer
1324
-
1325
- //set subscription id to custom id
1326
- $order->subscription_transaction_id = $this->customer['id']; //transaction id is the customer id, we save it in user meta later too
1327
-
1328
- //figure out the amounts
1329
- $amount = $order->PaymentAmount;
1330
- $amount_tax = $order->getTaxForPrice($amount);
1331
- $amount = round((float)$amount + (float)$amount_tax, 2);
1332
-
1333
- /*
1334
- There are two parts to the trial. Part 1 is simply the delay until the first payment
1335
- since we are doing the first payment as a separate transaction.
1336
- The second part is the actual "trial" set by the admin.
1337
-
1338
- Stripe only supports Year or Month for billing periods, but we account for Days and Weeks just in case.
1339
- */
1340
- //figure out the trial length (first payment handled by initial charge)
1341
- if($order->BillingPeriod == "Year")
1342
- $trial_period_days = $order->BillingFrequency * 365; //annual
1343
- elseif($order->BillingPeriod == "Day")
1344
- $trial_period_days = $order->BillingFrequency * 1; //daily
1345
- elseif($order->BillingPeriod == "Week")
1346
- $trial_period_days = $order->BillingFrequency * 7; //weekly
1347
- else
1348
- $trial_period_days = $order->BillingFrequency * 30; //assume monthly
1349
-
1350
- //convert to a profile start date
1351
- $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
1352
-
1353
- //filter the start date
1354
- $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
1355
-
1356
- //convert back to days
1357
- $trial_period_days = ceil(abs(strtotime(date("Y-m-d"), current_time("timestamp")) - strtotime($order->ProfileStartDate, current_time("timestamp"))) / 86400);
1358
-
1359
- //for free trials, just push the start date of the subscription back
1360
- if(!empty($order->TrialBillingCycles) && $order->TrialAmount == 0)
1361
- {
1362
- $trialOccurrences = (int)$order->TrialBillingCycles;
1363
- if($order->BillingPeriod == "Year")
1364
- $trial_period_days = $trial_period_days + (365 * $order->BillingFrequency * $trialOccurrences); //annual
1365
- elseif($order->BillingPeriod == "Day")
1366
- $trial_period_days = $trial_period_days + (1 * $order->BillingFrequency * $trialOccurrences); //daily
1367
- elseif($order->BillingPeriod == "Week")
1368
- $trial_period_days = $trial_period_days + (7 * $order->BillingFrequency * $trialOccurrences); //weekly
1369
- else
1370
- $trial_period_days = $trial_period_days + (30 * $order->BillingFrequency * $trialOccurrences); //assume monthly
1371
- }
1372
- elseif(!empty($order->TrialBillingCycles))
1373
- {
1374
- /*
1375
- Let's set the subscription to the trial and give the user an "update" to change the sub later to full price (since v2.0)
1376
-
1377
- This will force TrialBillingCycles > 1 to act as if they were 1
1378
- */
1379
- $new_user_updates = array();
1380
- $new_user_updates[] = array(
1381
- 'when' => 'payment',
1382
- 'billing_amount' => $order->PaymentAmount,
1383
- 'cycle_period' => $order->BillingPeriod,
1384
- 'cycle_number' => $order->BillingFrequency
1385
- );
1386
-
1387
- //now amount to equal the trial #s
1388
- $amount = $order->TrialAmount;
1389
- $amount_tax = $order->getTaxForPrice($amount);
1390
- $amount = round((float)$amount + (float)$amount_tax, 2);
1391
- }
1392
-
1393
- //create a plan
1394
- try
1395
- {
1396
- $plan = array(
1397
- "amount" => $amount * 100,
1398
- "interval_count" => $order->BillingFrequency,
1399
- "interval" => strtolower($order->BillingPeriod),
1400
- "trial_period_days" => $trial_period_days,
1401
- "name" => $order->membership_name . " for order " . $order->code,
1402
- "currency" => strtolower($pmpro_currency),
1403
- "id" => $order->code
1404
- );
1405
-
1406
- $plan = Stripe_Plan::create(apply_filters('pmpro_stripe_create_plan_array', $plan));
1407
- }
1408
- catch (Exception $e)
1409
- {
1410
- $order->error = __("Error creating plan with Stripe:", "pmpro") . $e->getMessage();
1411
- $order->shorterror = $order->error;
1412
- return false;
1413
- }
1414
-
1415
- //before subscribing, let's clear out the updates so we don't trigger any during sub
1416
- if(!empty($user_id))
1417
- {
1418
- $old_user_updates = get_user_meta($user_id, "pmpro_stripe_updates", true);
1419
- update_user_meta($user_id, "pmpro_stripe_updates", array());
1420
- }
1421
-
1422
- if(empty($order->subscription_transaction_id) && !empty($this->customer['id']))
1423
- $order->subscription_transaction_id = $this->customer['id'];
1424
-
1425
- //subscribe to the plan
1426
- try
1427
- {
1428
- $subscription = array("plan" => $order->code);
1429
- $result = $this->customer->subscriptions->create(apply_filters('pmpro_stripe_create_subscription_array', $subscription));
1430
- }
1431
- catch (Exception $e)
1432
- {
1433
- //try to delete the plan
1434
- $plan->delete();
1435
-
1436
- //give the user any old updates back
1437
- if(!empty($user_id))
1438
- update_user_meta($user_id, "pmpro_stripe_updates", $old_user_updates);
1439
-
1440
- //return error
1441
- $order->error = __("Error subscribing customer to plan with Stripe:", "pmpro") . $e->getMessage();
1442
- $order->shorterror = $order->error;
1443
- return false;
1444
- }
1445
-
1446
- //delete the plan
1447
- $plan = Stripe_Plan::retrieve($order->code);
1448
- $plan->delete();
1449
-
1450
- //if we got this far, we're all good
1451
- $order->status = "success";
1452
- $order->subscription_transaction_id = $result['id'];
1453
-
1454
- //save new updates if this is at checkout
1455
- if($checkout)
1456
- {
1457
- //empty out updates unless set above
1458
- if(empty($new_user_updates))
1459
- $new_user_updates = array();
1460
-
1461
- //update user meta
1462
- if(!empty($user_id))
1463
- update_user_meta($user_id, "pmpro_stripe_updates", $new_user_updates);
1464
- else
1465
- {
1466
- //need to remember the user updates to save later
1467
- global $pmpro_stripe_updates;
1468
- $pmpro_stripe_updates = $new_user_updates;
1469
- function pmpro_user_register_stripe_updates($user_id)
1470
- {
1471
- global $pmpro_stripe_updates;
1472
- update_user_meta($user_id, "pmpro_stripe_updates", $pmpro_stripe_updates);
1473
- }
1474
- add_action("user_register", "pmpro_user_register_stripe_updates");
1475
- }
1476
- }
1477
- else
1478
- {
1479
- //give them their old updates back
1480
- update_user_meta($user_id, "pmpro_stripe_updates", $old_user_updates);
1481
- }
1482
-
1483
- return true;
1484
- }
1485
-
1486
- /**
1487
- * Helper method to update the customer info via getCustomer
1488
- *
1489
- * @since 1.4
1490
- */
1491
- function update(&$order)
1492
- {
1493
- //we just have to run getCustomer which will look for the customer and update it with the new token
1494
- $result = $this->getCustomer($order);
1495
-
1496
- if(!empty($result))
1497
- {
1498
- return true;
1499
- }
1500
- else
1501
- {
1502
- return false; //couldn't find the customer
1503
- }
1504
- }
1505
-
1506
- /**
1507
- * Cancel a subscription at Stripe
1508
- *
1509
- * @since 1.4
1510
- */
1511
- function cancel(&$order, $update_status = true)
1512
- {
1513
- //no matter what happens below, we're going to cancel the order in our system
1514
- if($update_status)
1515
- $order->updateStatus("cancelled");
1516
-
1517
- //require a subscription id
1518
- if(empty($order->subscription_transaction_id))
1519
- return false;
1520
-
1521
- //find the customer
1522
- $result = $this->getCustomer($order);
1523
-
1524
- if(!empty($result))
1525
- {
1526
- //find subscription with this order code
1527
- $subscription = $this->getSubscription($order);
1528
-
1529
- if(!empty($subscription))
1530
- {
1531
- if($this->cancelSubscriptionAtGateway($subscription))
1532
- {
1533
- //we're okay, going to return true later
1534
- }
1535
- else
1536
- {
1537
- $order->error = __("Could not cancel old subscription.", "pmpro");
1538
- $order->shorterror = $order->error;
1539
-
1540
- return false;
1541
- }
1542
- }
1543
-
1544
- /*
1545
- Clear updates for this user. (But not if checking out, we would have already done that.)
1546
- */
1547
- if(empty($_REQUEST['submit-checkout']))
1548
- update_user_meta($order->user_id, "pmpro_stripe_updates", array());
1549
-
1550
- return true;
1551
- }
1552
- else
1553
- {
1554
- $order->error = __("Could not find the customer.", "pmpro");
1555
- $order->shorterror = $order->error;
1556
- return false; //no customer found
1557
- }
1558
- }
1559
-
1560
- /**
1561
- * Helper method to cancel a subscription at Stripe and also clear up any upaid invoices.
1562
- *
1563
- * @since 1.8
1564
- */
1565
- function cancelSubscriptionAtGateway($subscription)
1566
- {
1567
- //need a valid sub
1568
- if(empty($subscription->id))
1569
- return false;
1570
-
1571
- //make sure we get the customer for this subscription
1572
- $order = new MemberOrder();
1573
- $order->getLastMemberOrderBySubscriptionTransactionID($subscription->id);
1574
-
1575
- //no order?
1576
- if(empty($order))
1577
- {
1578
- //lets cancel anyway, but this is suspicious
1579
- $r = $subscription->cancel();
1580
-
1581
- return true;
1582
- }
1583
-
1584
- //okay have an order, so get customer so we can cancel invoices too
1585
- $this->getCustomer($order);
1586
-
1587
- //get open invoices
1588
- $invoices = $this->customer->invoices();
1589
- $invoices = $invoices->all();
1590
-
1591
- //found it, cancel it
1592
- try
1593
- {
1594
- //find any open invoices for this subscription and forgive them
1595
- if(!empty($invoices))
1596
- {
1597
- foreach($invoices->data as $invoice)
1598
- {
1599
- if(!$invoice->closed && $invoice->subscription == $subscription->id)
1600
- {
1601
- $invoice->closed = true;
1602
- $invoice->save();
1603
- }
1604
- }
1605
- }
1606
-
1607
- //cancel
1608
- $r = $subscription->cancel();
1609
-
1610
- return true;
1611
- }
1612
- catch(Exception $e)
1613
- {
1614
- return false;
1615
- }
1616
- }
1617
  }
1
+ <?php
2
+ //include pmprogateway
3
+ require_once(dirname(__FILE__) . "/class.pmprogateway.php");
4
+
5
+ //load classes init method
6
+ add_action('init', array('PMProGateway_stripe', 'init'));
7
+
8
+ /**
9
+ * PMProGateway_stripe Class
10
+ *
11
+ * Handles Stripe integration.
12
+ *
13
+ * @since 1.4
14
+ */
15
+ class PMProGateway_stripe extends PMProGateway
16
+ {
17
+ /**
18
+ * Stripe Class Constructor
19
+ *
20
+ * @since 1.4
21
+ */
22
+ function PMProGateway_stripe($gateway = NULL)
23
+ {
24
+ $this->gateway = $gateway;
25
+ $this->gateway_environment = pmpro_getOption("gateway_environment");
26
+
27
+ $this->loadStripeLibrary();
28
+ Stripe::setApiKey(pmpro_getOption("stripe_secretkey"));
29
+
30
+ return $this->gateway;
31
+ }
32
+
33
+ /**
34
+ * Load the Stripe API library.
35
+ *
36
+ * @since 1.8
37
+ * Moved into a method in version 1.8 so we only load it when needed.
38
+ */
39
+ function loadStripeLibrary()
40
+ {
41
+ //load Stripe library if it hasn't been loaded already (usually by another plugin using Stripe)
42
+ if(!class_exists("Stripe"))
43
+ require_once(dirname(__FILE__) . "/../../includes/lib/Stripe/Stripe.php");
44
+ }
45
+
46
+ /**
47
+ * Run on WP init
48
+ *
49
+ * @since 1.8
50
+ */
51
+ static function init()
52
+ {
53
+ //make sure Stripe is a gateway option
54
+ add_filter('pmpro_gateways', array('PMProGateway_stripe', 'pmpro_gateways'));
55
+
56
+ //add fields to payment settings
57
+ add_filter('pmpro_payment_options', array('PMProGateway_stripe', 'pmpro_payment_options'));
58
+ add_filter('pmpro_payment_option_fields', array('PMProGateway_stripe', 'pmpro_payment_option_fields'), 10, 2);
59
+
60
+ //add some fields to edit user page (Updates)
61
+ add_action('pmpro_after_membership_level_profile_fields', array('PMProGateway_stripe', 'user_profile_fields'));
62
+ add_action('profile_update', array('PMProGateway_stripe', 'user_profile_fields_save'));
63
+
64
+ //old global RE showing billing address or not
65
+ global $pmpro_stripe_lite;
66
+ $pmpro_stripe_lite = apply_filters("pmpro_stripe_lite", !pmpro_getOption("stripe_billingaddress")); //default is oposite of the stripe_billingaddress setting
67
+
68
+ //updates cron
69
+ add_action('pmpro_activation', array('PMProGateway_stripe', 'pmpro_activation'));
70
+ add_action('pmpro_deactivation', array('PMProGateway_stripe', 'pmpro_deactivation'));
71
+ add_action('pmpro_cron_stripe_subscription_updates', array('PMProGateway_stripe', 'pmpro_cron_stripe_subscription_updates'));
72
+
73
+ //code to add at checkout if Stripe is the current gateway
74
+ $gateway = pmpro_getOption("gateway");
75
+ if($gateway == "stripe")
76
+ {
77
+ add_action('pmpro_checkout_preheader', array('PMProGateway_stripe', 'pmpro_checkout_preheader'));
78
+ add_filter('pmpro_checkout_order', array('PMProGateway_stripe', 'pmpro_checkout_order'));
79
+ add_filter('pmpro_include_billing_address_fields', array('PMProGateway_stripe', 'pmpro_include_billing_address_fields'));
80
+ add_filter('pmpro_include_cardtype_field', array('PMProGateway_stripe', 'pmpro_include_billing_address_fields'));
81
+ add_filter('pmpro_include_payment_information_fields', array('PMProGateway_stripe', 'pmpro_include_payment_information_fields'));
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Make sure Stripe is in the gateways list
87
+ *
88
+ * @since 1.8
89
+ */
90
+ static function pmpro_gateways($gateways)
91
+ {
92
+ if(empty($gateways['stripe']))
93
+ $gateways['stripe'] = __('Stripe', 'pmpro');
94
+
95
+ return $gateways;
96
+ }
97
+
98
+ /**
99
+ * Get a list of payment options that the Stripe gateway needs/supports.
100
+ *
101
+ * @since 1.8
102
+ */
103
+ static function getGatewayOptions()
104
+ {
105
+ $options = array(
106
+ 'sslseal',
107
+ 'nuclear_HTTPS',
108
+ 'gateway_environment',
109
+ 'stripe_secretkey',
110
+ 'stripe_publishablekey',
111
+ 'stripe_billingaddress',
112
+ 'currency',
113
+ 'use_ssl',
114
+ 'tax_state',
115
+ 'tax_rate',
116
+ 'accepted_credit_cards'
117
+ );
118
+
119
+ return $options;
120
+ }
121
+
122
+ /**
123
+ * Set payment options for payment settings page.
124
+ *
125
+ * @since 1.8
126
+ */
127
+ static function pmpro_payment_options($options)
128
+ {
129
+ //get stripe options
130
+ $stripe_options = PMProGateway_stripe::getGatewayOptions();
131
+
132
+ //merge with others.
133
+ $options = array_merge($stripe_options, $options);
134
+
135
+ return $options;
136
+ }
137
+
138
+ /**
139
+ * Display fields for Stripe options.
140
+ *
141
+ * @since 1.8
142
+ */
143
+ static function pmpro_payment_option_fields($values, $gateway)
144
+ {
145
+ ?>
146
+ <tr class="pmpro_settings_divider gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
147
+ <td colspan="2">
148
+ <?php _e('Stripe Settings', 'pmpro'); ?>
149
+ </td>
150
+ </tr>
151
+ <tr class="gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
152
+ <th scope="row" valign="top">
153
+ <label for="stripe_secretkey"><?php _e('Secret Key', 'pmpro');?>:</label>
154
+ </th>
155
+ <td>
156
+ <input type="text" id="stripe_secretkey" name="stripe_secretkey" size="60" value="<?php echo esc_attr($values['stripe_secretkey'])?>" />
157
+ </td>
158
+ </tr>
159
+ <tr class="gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
160
+ <th scope="row" valign="top">
161
+ <label for="stripe_publishablekey"><?php _e('Publishable Key', 'pmpro');?>:</label>
162
+ </th>
163
+ <td>
164
+ <input type="text" id="stripe_publishablekey" name="stripe_publishablekey" size="60" value="<?php echo esc_attr($values['stripe_publishablekey'])?>" />
165
+ </td>
166
+ </tr>
167
+ <tr class="gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
168
+ <th scope="row" valign="top">
169
+ <label for="stripe_billingaddress"><?php _e('Show Billing Address Fields', 'pmpro');?>:</label>
170
+ </th>
171
+ <td>
172
+ <select id="stripe_billingaddress" name="stripe_billingaddress">
173
+ <option value="0" <?php if(empty($values['stripe_billingaddress'])) { ?>selected="selected"<?php } ?>><?php _e('No', 'pmpro');?></option>
174
+ <option value="1" <?php if(!empty($values['stripe_billingaddress'])) { ?>selected="selected"<?php } ?>><?php _e('Yes', 'pmpro');?></option>
175
+ </select>
176
+ <small><?php _e("Stripe doesn't require billing address fields. Choose 'No' to hide them on the checkout page.<br /><strong>If No, make sure you disable address verification in the Stripe dashboard settings.</strong>", 'pmpro');?></small>
177
+ </td>
178
+ </tr>
179
+ <tr class="gateway gateway_stripe" <?php if($gateway != "stripe") { ?>style="display: none;"<?php } ?>>
180
+ <th scope="row" valign="top">
181
+ <label><?php _e('Web Hook URL', 'pmpro');?>:</label>
182
+ </th>
183
+ <td>
184
+ <p><?php _e('To fully integrate with Stripe, be sure to set your Web Hook URL to', 'pmpro');?> <pre><?php echo admin_url("admin-ajax.php") . "?action=stripe_webhook";?></pre></p>
185
+ </td>
186
+ </tr>
187
+ <?php
188
+ }
189
+
190
+ /**
191
+ * Code added to checkout preheader.
192
+ *
193
+ * @since 1.8
194
+ */
195
+ static function pmpro_checkout_preheader()
196
+ {
197
+ global $gateway, $pmpro_level;
198
+
199
+ if($gateway == "stripe" && !pmpro_isLevelFree($pmpro_level))
200
+ {
201
+ //stripe js library
202
+ wp_enqueue_script("stripe", "https://js.stripe.com/v2/", array(), NULL);
203
+
204
+ //stripe js code for checkout
205
+ function pmpro_stripe_javascript()
206
+ {
207
+ global $pmpro_gateway, $pmpro_level, $pmpro_stripe_lite;
208
+ ?>
209
+ <script type="text/javascript">
210
+ // this identifies your website in the createToken call below
211
+ Stripe.setPublishableKey('<?php echo pmpro_getOption("stripe_publishablekey"); ?>');
212
+
213
+ var pmpro_require_billing = true;
214
+
215
+ jQuery(document).ready(function() {
216
+ jQuery("#pmpro_form, .pmpro_form").submit(function(event) {
217
+
218
+ //double check in case a discount code made the level free
219
+ if(pmpro_require_billing)
220
+ {
221
+ //build array for creating token
222
+ var args = {
223
+ number: jQuery('#AccountNumber').val(),
224
+ cvc: jQuery('#CVV').val(),
225
+ exp_month: jQuery('#ExpirationMonth').val(),
226
+ exp_year: jQuery('#ExpirationYear').val()
227
+ <?php
228
+ $pmpro_stripe_verify_address = apply_filters("pmpro_stripe_verify_address", pmpro_getOption('stripe_billingaddress'));
229
+ if(!empty($pmpro_stripe_verify_address))
230
+ {
231
+ ?>
232
+ ,address_line1: jQuery('#baddress1').val(),
233
+ address_line2: jQuery('#baddress2').val(),
234
+ address_city: jQuery('#bcity').val(),
235
+ address_state: jQuery('#bstate').val(),
236
+ address_zip: jQuery('#bzipcode').val(),
237
+ address_country: jQuery('#bcountry').val()
238
+ <?php
239
+ }
240
+ ?>
241
+ };
242
+
243
+ if (jQuery('#bfirstname').length && jQuery('#blastname').length)
244
+ args['name'] = jQuery.trim(jQuery('#bfirstname').val() + ' ' + jQuery('#blastname').val());
245
+
246
+ //create token
247
+ Stripe.createToken(args, stripeResponseHandler);
248
+
249
+ // prevent the form from submitting with the default action
250
+ return false;
251
+ }
252
+ else
253
+ return true; //not using Stripe anymore
254
+ });
255
+ });
256
+
257
+ function stripeResponseHandler(status, response) {
258
+ if (response.error) {
259
+ // re-enable the submit button
260
+ jQuery('.pmpro_btn-submit-checkout').removeAttr("disabled");
261
+
262
+ //hide processing message
263
+ jQuery('#pmpro_processing_message').css('visibility', 'hidden');
264
+
265
+ // show the errors on the form
266
+ alert(response.error.message);
267
+ jQuery(".payment-errors").text(response.error.message);
268
+ } else {
269
+ var form$ = jQuery("#pmpro_form, .pmpro_form");
270
+ // token contains id, last4, and card type
271
+ var token = response['id'];
272
+ // insert the token into the form so it gets submitted to the server
273
+ form$.append("<input type='hidden' name='stripeToken' value='" + token + "'/>");
274
+
275
+ console.log(response);
276
+
277
+ //insert fields for other card fields
278
+ if(jQuery('#CardType[name=CardType]').length)
279
+ jQuery('#CardType').val(response['card']['brand']);
280
+ else
281
+ form$.append("<input type='hidden' name='CardType' value='" + response['card']['brand'] + "'/>");
282
+ form$.append("<input type='hidden' name='AccountNumber' value='XXXXXXXXXXXXX" + response['card']['last4'] + "'/>");
283
+ form$.append("<input type='hidden' name='ExpirationMonth' value='" + ("0" + response['card']['exp_month']).slice(-2) + "'/>");
284
+ form$.append("<input type='hidden' name='ExpirationYear' value='" + response['card']['exp_year'] + "'/>");
285
+
286
+ // and submit
287
+ form$.get(0).submit();
288
+ }
289
+ }
290
+ </script>
291
+ <?php
292
+ }
293
+ add_action("wp_head", "pmpro_stripe_javascript");
294
+
295
+ //don't require the CVV
296
+ function pmpro_stripe_dont_require_CVV($fields)
297
+ {
298
+ unset($fields['CVV']);
299
+ return $fields;
300
+ }
301
+ add_filter("pmpro_required_billing_fields", "pmpro_stripe_dont_require_CVV");
302
+ }
303
+ }
304
+
305
+ /**
306
+ * Filtering orders at checkout.
307
+ *
308
+ * @since 1.8
309
+ */
310
+ static function pmpro_checkout_order($morder)
311
+ {
312
+ //load up token values
313
+ if(isset($_REQUEST['stripeToken']))
314
+ {
315
+ $morder->stripeToken = $_REQUEST['stripeToken'];
316
+ }
317
+
318
+ //stripe lite code to get name from other sources if available
319
+ global $pmpro_stripe_lite, $current_user;
320
+ if(!empty($pmpro_stripe_lite) && empty($morder->FirstName) && empty($morder->LastName))
321
+ {
322
+ if(!empty($current_user->ID))
323
+ {
324
+ $morder->FirstName = get_user_meta($current_user->ID, "first_name", true);
325
+ $morder->LastName = get_user_meta($current_user->ID, "last_name", true);
326
+ }
327
+ elseif(!empty($_REQUEST['first_name']) && !empty($_REQUEST['last_name']))
328
+ {
329
+ $morder->FirstName = $_REQUEST['first_name'];
330
+ $morder->LastName = $_REQUEST['last_name'];
331
+ }
332
+ }
333
+
334
+ return $morder;
335
+ }
336
+
337
+ /**
338
+ * Code to run after checkout
339
+ *
340
+ * @since 1.8
341
+ */
342
+ static function pmpro_after_checkout($user_id, $morder)
343
+ {
344
+ global $gateway;
345
+
346
+ if($gateway == "stripe")
347
+ {
348
+ if(!empty($morder) && !empty($morer->Gateway) && !empty($morder->Gateway->customer) && !empty($morder->Gateway->customer->id))
349
+ {
350
+ update_user_meta($user_id, "pmpro_stripe_customerid", $morder->Gateway->customer->id);
351
+ }
352
+ }
353
+ }
354
+
355
+ /**
356
+ * Check settings if billing address should be shown.
357
+ * @since 1.8
358
+ */
359
+ static function pmpro_include_billing_address_fields($include)
360
+ {
361
+ //check settings RE showing billing address
362
+ if(!pmpro_getOption("stripe_billingaddress"))
363
+ $include = false;
364
+
365
+ return $include;
366
+ }
367
+
368
+ /**
369
+ * Use our own payment fields at checkout. (Remove the name attributes.)
370
+ * @since 1.8
371
+ */
372
+ static function pmpro_include_payment_information_fields($include)
373
+ {
374
+ //global vars
375
+ global $pmpro_requirebilling, $pmpro_show_discount_code, $discount_code, $CardType, $AccountNumber, $ExpirationMonth, $ExpirationYear;
376
+
377
+ //get accepted credit cards
378
+ $pmpro_accepted_credit_cards = pmpro_getOption("accepted_credit_cards");
379
+ $pmpro_accepted_credit_cards = explode(",", $pmpro_accepted_credit_cards);
380
+ $pmpro_accepted_credit_cards_string = pmpro_implodeToEnglish($pmpro_accepted_credit_cards);
381
+
382
+ //include ours
383
+ ?>
384
+ <table id="pmpro_payment_information_fields" class="pmpro_checkout top1em" width="100%" cellpadding="0" cellspacing="0" border="0" <?php if(!$pmpro_requirebilling || apply_filters("pmpro_hide_payment_information_fields", false) ) { ?>style="display: none;"<?php } ?>>
385
+ <thead>
386
+ <tr>
387
+ <th><span class="pmpro_thead-msg"><?php printf(__('We Accept %s', 'pmpro'), $pmpro_accepted_credit_cards_string);?></span><?php _e('Payment Information', 'pmpro');?></th>
388
+ </tr>
389
+ </thead>
390
+ <tbody>
391
+ <tr valign="top">
392
+ <td>
393
+ <?php
394
+ $sslseal = pmpro_getOption("sslseal");
395
+ if($sslseal)
396
+ {
397
+ ?>
398
+ <div class="pmpro_sslseal"><?php echo stripslashes($sslseal)?></div>
399
+ <?php
400
+ }
401
+ ?>
402
+ <?php
403
+ $pmpro_include_cardtype_field = apply_filters('pmpro_include_cardtype_field', false);
404
+ if($pmpro_include_cardtype_field)
405
+ {
406
+ ?>
407
+ <div class="pmpro_payment-card-type">
408
+ <label for="CardType"><?php _e('Card Type', 'pmpro');?></label>
409
+ <select id="CardType" class=" <?php echo pmpro_getClassForField("CardType");?>">
410
+ <?php foreach($pmpro_accepted_credit_cards as $cc) { ?>
411
+ <option value="<?php echo $cc?>" <?php if($CardType == $cc) { ?>selected="selected"<?php } ?>><?php echo $cc?></option>
412
+ <?php } ?>
413
+ </select>
414
+ </div>
415
+ <?php
416
+ }
417
+ else
418
+ {
419
+ ?>
420
+ <input type="hidden" id="CardType" name="CardType" value="<?php echo esc_attr($CardType);?>" />
421
+ <script>
422
+ jQuery(document).ready(function() {
423
+ jQuery('#AccountNumber').validateCreditCard(function(result) {
424
+ var cardtypenames = {
425
+ "amex":"American Express",
426
+ "diners_club_carte_blanche":"Diners Club Carte Blanche",
427
+ "diners_club_international":"Diners Club International",
428
+ "discover":"Discover",
429
+ "jcb":"JCB",
430
+ "laser":"Laser",
431
+ "maestro":"Maestro",
432
+ "mastercard":"Mastercard",
433
+ "visa":"Visa",
434
+ "visa_electron":"Visa Electron"
435
+ }
436
+
437
+ if(result.card_type)
438
+ jQuery('#CardType').val(cardtypenames[result.card_type.name]);
439
+ else
440
+ jQuery('#CardType').val('Unknown Card Type');
441
+ });
442
+ });
443
+ </script>
444
+ <?php
445
+ }
446
+ ?>
447
+
448
+ <div class="pmpro_payment-account-number">
449
+ <label for="AccountNumber"><?php _e('Card Number', 'pmpro');?></label>
450
+ <input id="AccountNumber" class="input <?php echo pmpro_getClassForField("AccountNumber");?>" type="text" size="25" value="<?php echo esc_attr($AccountNumber)?>" autocomplete="off" />
451
+ </div>
452
+
453
+ <div class="pmpro_payment-expiration">
454
+ <label for="ExpirationMonth"><?php _e('Expiration Date', 'pmpro');?></label>
455
+ <select id="ExpirationMonth" class=" <?php echo pmpro_getClassForField("ExpirationMonth");?>">
456
+ <option value="01" <?php if($ExpirationMonth == "01") { ?>selected="selected"<?php } ?>>01</option>
457
+ <option value="02" <?php if($ExpirationMonth == "02") { ?>selected="selected"<?php } ?>>02</option>
458
+ <option value="03" <?php if($ExpirationMonth == "03") { ?>selected="selected"<?php } ?>>03</option>
459
+ <option value="04" <?php if($ExpirationMonth == "04") { ?>selected="selected"<?php } ?>>04</option>
460
+ <option value="05" <?php if($ExpirationMonth == "05") { ?>selected="selected"<?php } ?>>05</option>
461
+ <option value="06" <?php if($ExpirationMonth == "06") { ?>selected="selected"<?php } ?>>06</option>
462
+ <option value="07" <?php if($ExpirationMonth == "07") { ?>selected="selected"<?php } ?>>07</option>
463
+ <option value="08" <?php if($ExpirationMonth == "08") { ?>selected="selected"<?php } ?>>08</option>
464
+ <option value="09" <?php if($ExpirationMonth == "09") { ?>selected="selected"<?php } ?>>09</option>
465
+ <option value="10" <?php if($ExpirationMonth == "10") { ?>selected="selected"<?php } ?>>10</option>
466
+ <option value="11" <?php if($ExpirationMonth == "11") { ?>selected="selected"<?php } ?>>11</option>
467
+ <option value="12" <?php if($ExpirationMonth == "12") { ?>selected="selected"<?php } ?>>12</option>
468
+ </select>/<select id="ExpirationYear" class=" <?php echo pmpro_getClassForField("ExpirationYear");?>">
469
+ <?php
470
+ for($i = date("Y"); $i < date("Y") + 10; $i++)
471
+ {
472
+ ?>
473
+ <option value="<?php echo $i?>" <?php if($ExpirationYear == $i) { ?>selected="selected"<?php } ?>><?php echo $i?></option>
474
+ <?php
475
+ }
476
+ ?>
477
+ </select>
478
+ </div>
479
+
480
+ <?php
481
+ $pmpro_show_cvv = apply_filters("pmpro_show_cvv", true);
482
+ if($pmpro_show_cvv)
483
+ {
484
+ ?>
485
+ <div class="pmpro_payment-cvv">
486
+ <label for="CVV"><?php _ex('CVV', 'Credit card security code, CVV/CCV/CVV2', 'pmpro');?></label>
487
+ <input class="input" id="CVV" type="text" size="4" value="<?php if(!empty($_REQUEST['CVV'])) { echo esc_attr($_REQUEST['CVV']); }?>" class=" <?php echo pmpro_getClassForField("CVV");?>" /> <small>(<a href="javascript:void(0);" onclick="javascript:window.open('<?php echo pmpro_https_filter(PMPRO_URL)?>/pages/popup-cvv.html','cvv','toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=600, height=475');"><?php _ex("what's this?", 'link to CVV help', 'pmpro');?></a>)</small>
488
+ </div>
489
+ <?php
490
+ }
491
+ ?>
492
+
493
+ <?php if($pmpro_show_discount_code) { ?>
494
+ <div class="pmpro_payment-discount-code">
495
+ <label for="discount_code"><?php _e('Discount Code', 'pmpro');?></label>
496
+ <input class="input <?php echo pmpro_getClassForField("discount_code");?>" id="discount_code" name="discount_code" type="text" size="20" value="<?php echo esc_attr($discount_code)?>" />
497
+ <input type="button" id="discount_code_button" name="discount_code_button" value="<?php _e('Apply', 'pmpro');?>" />
498
+ <p id="discount_code_message" class="pmpro_message" style="display: none;"></p>
499
+ </div>
500
+ <?php } ?>
501
+
502
+ </td>
503
+ </tr>
504
+ </tbody>
505
+ </table>
506
+ <?php
507
+
508
+ //don't include the default
509
+ return false;
510
+ }
511
+
512
+ /**
513
+ * Fields shown on edit user page
514
+ *
515
+ * @since 1.8
516
+ */
517
+ static function user_profile_fields($user)
518
+ {
519
+ global $wpdb, $current_user, $pmpro_currency_symbol;
520
+
521
+ $cycles = array( __('Day(s)', 'pmpro') => 'Day', __('Week(s)', 'pmpro') => 'Week', __('Month(s)', 'pmpro') => 'Month', __('Year(s)', 'pmpro') => 'Year' );
522
+ $current_year = date("Y");
523
+ $current_month = date("m");
524
+
525
+ //make sure the current user has privileges
526
+ $membership_level_capability = apply_filters("pmpro_edit_member_capability", "manage_options");
527
+ if(!current_user_can($membership_level_capability))
528
+ return false;
529
+
530
+ //more privelges they should have
531
+ $show_membership_level = apply_filters("pmpro_profile_show_membership_level", true, $user);
532
+ if(!$show_membership_level)
533
+ return false;
534
+
535
+ //check that user has a current subscription at Stripe
536
+ $last_order = new MemberOrder();
537
+ $last_order->getLastMemberOrder($user->ID);
538
+
539
+ //assume no sub to start
540
+ $sub = false;
541
+
542
+ //check that gateway is Stripe
543
+ if($last_order->gateway == "stripe")
544
+ {
545
+ //is there a customer?
546
+ $sub = $last_order->Gateway->getSubscription($last_order);
547
+ }
548
+
549
+ $customer_id = $user->pmpro_stripe_customerid;
550
+
551
+ if(empty($sub))
552
+ {
553
+ //make sure we delete stripe updates
554
+ update_user_meta($user->ID, "pmpro_stripe_updates", array());
555
+
556
+ //if the last order has a sub id, let the admin know there is no sub at Stripe
557
+ if(!empty($last_order) && $last_order->gateway == "stripe" && !empty($last_order->subscription_transaction_id) && strpos($last_order->subscription_transaction_id, "sub_") !== false)
558
+ {
559
+ ?>
560
+ <p><strong>Note:</strong> Subscription <strong><?php echo $last_order->subscription_transaction_id;?></strong> could not be found at Stripe. It might have been deleted.</p>
561
+ <?php
562
+ }
563
+ }
564
+ else
565
+ {
566
+ ?>
567
+ <h3><?php _e("Subscription Updates", "pmpro"); ?></h3>
568
+ <p>
569
+ <?php
570
+ if(empty($_REQUEST['user_id']))
571
+ _e("Subscription updates, allow you to change the member's subscription values at predefined times. Be sure to click Update Profile after making changes.", 'pmpro');
572
+ else
573
+ _e("Subscription updates, allow you to change the member's subscription values at predefined times. Be sure to click Update User after making changes.", 'pmpro');
574
+ ?>
575
+ </p>
576
+ <table class="form-table">
577
+ <tr>
578
+ <th><label for="membership_level"><?php _e("Update", "pmpro"); ?></label></th>
579
+ <td id="updates_td">
580
+ <?php
581
+ $old_updates = $user->pmpro_stripe_updates;
582
+ if(is_array($old_updates))
583
+ {
584
+ $updates = array_merge(
585
+ array(array('template'=>true, 'when'=>'now', 'date_month'=>'', 'date_day'=>'', 'date_year'=>'', 'billing_amount'=>'', 'cycle_number'=>'', 'cycle_period'=>'Month')),
586
+ $old_updates
587
+ );
588
+ }
589
+ else
590
+ $updates = array(array('template'=>true, 'when'=>'now', 'date_month'=>'', 'date_day'=>'', 'date_year'=>'', 'billing_amount'=>'', 'cycle_number'=>'', 'cycle_period'=>'Month'));
591
+
592
+ foreach($updates as $update)
593
+ {
594
+ ?>
595
+ <div class="updates_update" <?php if(!empty($update['template'])) { ?>style="display: none;"<?php } ?>>
596
+ <select class="updates_when" name="updates_when[]">
597
+ <option value="now" <?php selected($update['when'], "now");?>>Now</option>
598
+ <option value="payment" <?php selected($update['when'], "payment");?>>After Next Payment</option>
599
+ <option value="date" <?php selected($update['when'], "date");?>>On Date</option>
600
+ </select>
601
+ <span class="updates_date" <?php if($uwhen != "date") { ?>style="display: none;"<?php } ?>>
602
+ <select name="updates_date_month[]">
603
+ <?php
604
+ for($i = 1; $i < 13; $i++)
605
+ {
606
+ ?>
607
+ <option value="<?php echo str_pad($i, 2, "0", STR_PAD_LEFT);?>" <?php if(!empty($update['date_month']) && $update['date_month'] == $i) { ?>selected="selected"<?php } ?>>
608
+ <?php echo date("M", strtotime($i . "/1/" . $current_year));?>
609
+ </option>
610
+ <?php
611
+ }
612
+ ?>
613
+ </select>
614
+ <input name="updates_date_day[]" type="text" size="2" value="<?php if(!empty($update['date_day'])) echo esc_attr($update['date_day']);?>" />
615
+ <input name="updates_date_year[]" type="text" size="4" value="<?php if(!empty($update['date_year'])) echo esc_attr($update['date_year']);?>" />
616
+ </span>
617
+ <span class="updates_billing" <?php if($uwhen == "no") { ?>style="display: none;"<?php } ?>>
618
+ <?php echo $pmpro_currency_symbol?><input name="updates_billing_amount[]" type="text" size="10" value="<?php echo esc_attr($update['billing_amount']);?>" />
619
+ <small><?php _e('per', 'pmpro');?></small>
620
+ <input name="updates_cycle_number[]" type="text" size="5" value="<?php echo esc_attr($update['cycle_number']);?>" />
621
+ <select name="updates_cycle_period[]">
622
+ <?php
623
+ foreach ( $cycles as $name => $value ) {
624
+ echo "<option value='$value'";
625
+ if(!empty($update['cycle_period']) && $update['cycle_period'] == $value) echo " selected='selected'";
626
+ echo ">$name</option>";
627
+ }
628
+ ?>
629
+ </select>
630
+ </span>
631
+ <span>
632
+ <a class="updates_remove" href="javascript:void(0);">Remove</a>
633
+ </span>
634
+ </div>
635
+ <?php
636
+ }
637
+ ?>
638
+ <p><a id="updates_new_update" href="javascript:void(0);">+ New Update</a></p>
639
+ </td>
640
+ </tr>
641
+ </table>
642
+ <script>
643
+ jQuery(document).ready(function() {
644
+ //function to update dropdowns/etc based on when field
645
+ function updateSubscriptionUpdateFields(when)
646
+ {
647
+ if(jQuery(when).val() == 'date')
648
+ jQuery(when).parent().children('.updates_date').show();
649
+ else
650
+ jQuery(when).parent().children('.updates_date').hide();
651
+
652
+ if(jQuery(when).val() == 'no')
653
+ jQuery(when).parent().children('.updates_billing').hide();
654
+ else
655
+ jQuery(when).parent().children('.updates_billing').show();
656
+ }
657
+
658
+ //and update on page load
659
+ jQuery('.updates_when').each(function() { if(jQuery(this).parent().css('display') != 'none') updateSubscriptionUpdateFields(this); });
660
+
661
+ //add a new update when clicking to
662
+ var num_updates_divs = <?php echo count($updates);?>;
663
+ jQuery('#updates_new_update').click(function() {
664
+ //get updates
665
+ updates = jQuery('.updates_update').toArray();
666
+
667
+ //clone the first one
668
+ new_div = jQuery(updates[0]).clone();
669
+
670
+ //append
671
+ new_div.insertBefore('#updates_new_update');
672
+
673
+ //update events
674
+ addUpdateEvents()
675
+
676
+ //unhide it
677
+ new_div.show();
678
+ updateSubscriptionUpdateFields(new_div.children('.updates_when'));
679
+ });
680
+
681
+ function addUpdateEvents()
682
+ {
683
+ //update when when changes
684
+ jQuery('.updates_when').change(function() {
685
+ updateSubscriptionUpdateFields(this);
686
+ });
687
+
688
+ //remove updates when clicking
689
+ jQuery('.updates_remove').click(function() {
690
+ jQuery(this).parent().parent().remove();
691
+ });
692
+ }
693
+ addUpdateEvents();
694
+ });
695
+ </script>
696
+ <?php
697
+ }
698
+ }
699
+
700
+ /**
701
+ * Process fields from the edit user page
702
+ *
703
+ * @since 1.8
704
+ */
705
+ static function user_profile_fields_save($user_id)
706
+ {
707
+ global $wpdb;
708
+
709
+ //check capabilities
710
+ $membership_level_capability = apply_filters("pmpro_edit_member_capability", "manage_options");
711
+ if(!current_user_can($membership_level_capability))
712
+ return false;
713
+
714
+ //make sure some value was passed
715
+ if(!isset($_POST['updates_when']) || !is_array($_POST['updates_when']))
716
+ return;
717
+
718
+ //vars
719
+ $updates = array();
720
+ $next_on_date_update = "";
721
+
722
+ //build array of updates (we skip the first because it's the template field for the JavaScript
723
+ for($i = 1; $i < count($_POST['updates_when']); $i++)
724
+ {
725
+ $update = array();
726
+
727
+ //all updates have these values
728
+ $update['when'] = $_POST['updates_when'][$i];
729
+ $update['billing_amount'] = $_POST['updates_billing_amount'][$i];
730
+ $update['cycle_number'] = $_POST['updates_cycle_number'][$i];
731
+ $update['cycle_period'] = $_POST['updates_cycle_period'][$i];
732
+
733
+ //these values only for on date updates
734
+ if($_POST['updates_when'][$i] == "date")
735
+ {
736
+ $update['date_month'] = str_pad($_POST['updates_date_month'][$i], 2, "0", STR_PAD_LEFT);
737
+ $update['date_day'] = str_pad($_POST['updates_date_day'][$i], 2, "0", STR_PAD_LEFT);
738
+ $update['date_year'] = $_POST['updates_date_year'][$i];
739
+ }
740
+
741
+ //make sure the update is valid
742
+ if(empty($update['cycle_number']))
743
+ continue;
744
+
745
+ //if when is now, update the subscription
746
+ if($update['when'] == "now")
747
+ {
748
+ //get level for user
749
+ $user_level = pmpro_getMembershipLevelForUser($user_id);
750
+
751
+ //get current plan at Stripe to get payment date
752
+ $last_order = new MemberOrder();
753
+ $last_order->getLastMemberOrder($user_id);
754
+ $last_order->setGateway('stripe');
755
+ $last_order->Gateway->getCustomer($last_order);
756
+
757
+ $subscription = $last_order->Gateway->getSubscription($last_order);
758
+
759
+ if(!empty($subscription))
760
+ {
761
+ $end_timestamp = $subscription->current_period_end;
762
+
763
+ //cancel the old subscription
764
+ if(!$last_order->Gateway->cancelSubscriptionAtGateway($subscription))
765
+ {
766
+ //throw error and halt save
767
+ function pmpro_stripe_user_profile_fields_save_error($errors, $update, $user)
768
+ {
769
+ $errors->add('pmpro_stripe_updates',__('Could not cancel the old subscription. Updates have not been processed.', 'pmpro'));
770
+ }
771
+ add_filter('user_profile_update_errors', 'pmpro_stripe_user_profile_fields_save_error', 10, 3);
772
+
773
+ //stop processing updates
774
+ return;
775
+ }
776
+ }
777
+
778
+ //if we didn't get an end date, let's set one one cycle out
779
+ if(empty($end_timestamp))
780
+ $end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period'], current_time('timestamp'));
781
+
782
+ //build order object
783
+ $update_order = new MemberOrder();
784
+ $update_order->setGateway('stripe');
785
+ $update_order->user_id = $user_id;
786
+ $update_order->membership_id = $user_level->id;
787
+ $update_order->membership_name = $user_level->name;
788
+ $update_order->InitialPayment = 0;
789
+ $update_order->PaymentAmount = $update['billing_amount'];
790
+ $update_order->ProfileStartDate = date("Y-m-d", $end_timestamp);
791
+ $update_order->BillingPeriod = $update['cycle_period'];
792
+ $update_order->BillingFrequency = $update['cycle_number'];
793
+
794
+ //need filter to reset ProfileStartDate
795
+ add_filter('pmpro_profile_start_date', create_function('$startdate, $order', 'return "' . $update_order->ProfileStartDate . 'T0:0:0";'), 10, 2);
796
+
797
+ //update subscription
798
+ $update_order->Gateway->subscribe($update_order, false);
799
+
800
+ //update membership
801
+ $sqlQuery = "UPDATE $wpdb->pmpro_memberships_users
802
+ SET billing_amount = '" . esc_sql($update['billing_amount']) . "',
803
+ cycle_number = '" . esc_sql($update['cycle_number']) . "',
804
+ cycle_period = '" . esc_sql($update['cycle_period']) . "',
805
+ trial_amount = '',
806
+ trial_limit = ''
807
+ WHERE user_id = '" . esc_sql($user_id) . "'
808
+ AND membership_id = '" . esc_sql($last_order->membership_id) . "'
809
+ AND status = 'active'
810
+ LIMIT 1";
811
+
812
+ $wpdb->query($sqlQuery);
813
+
814
+ //save order so we know which plan to look for at stripe (order code = plan id)
815
+ $update_order->status = "success";
816
+ $update_order->saveOrder();
817
+
818
+ continue;
819
+ }
820
+ elseif($update['when'] == 'date')
821
+ {
822
+ if(!empty($next_on_date_update))
823
+ $next_on_date_update = min($next_on_date_update, $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day']);
824
+ else
825
+ $next_on_date_update = $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'];
826
+ }
827
+
828
+ //add to array
829
+ $updates[] = $update;
830
+ }
831
+
832
+ //save in user meta
833
+ update_user_meta($user_id, "pmpro_stripe_updates", $updates);
834
+
835
+ //save date of next on-date update to make it easier to query for these in cron job
836
+ update_user_meta($user_id, "pmpro_stripe_next_on_date_update", $next_on_date_update);
837
+ }
838
+
839
+ /**
840
+ * Cron activation for subscription updates.
841
+ *
842
+ * @since 1.8
843
+ */
844
+ static function pmpro_activation()
845
+ {
846
+ wp_schedule_event(time(), 'daily', 'pmpro_cron_stripe_subscription_updates');
847
+ }
848
+
849
+ /**
850
+ * Cron deactivation for subscription updates.
851
+ *
852
+ * @since 1.8
853
+ */
854
+ static function pmpro_deactivation()
855
+ {
856
+ wp_clear_scheduled_hook('pmpro_cron_stripe_subscription_updates');
857
+ }
858
+
859
+ /**
860
+ * Cron job for subscription updates.
861
+ *
862
+ * @since 1.8
863
+ */
864
+ static function pmpro_cron_stripe_subscription_updates()
865
+ {
866
+ global $wpdb;
867
+
868
+ //get all updates for today (or before today)
869
+ $sqlQuery = "SELECT *
870
+ FROM $wpdb->usermeta
871
+ WHERE meta_key = 'pmpro_stripe_next_on_date_update'
872
+ AND meta_value IS NOT NULL
873
+ AND meta_value <> ''
874
+ AND meta_value < '" . date("Y-m-d", strtotime("+1 day")) . "'";
875
+ $updates = $wpdb->get_results($sqlQuery);
876
+
877
+ if(!empty($updates))
878
+ {
879
+ //loop through
880
+ foreach($updates as $update)
881
+ {
882
+ //pull values from update
883
+ $user_id = $update->user_id;
884
+
885
+ $user = get_userdata($user_id);
886
+
887
+ //if user is missing, delete the update info and continue
888
+ if(empty($user) || empty($user->ID))
889
+ {
890
+ delete_user_meta($user_id, "pmpro_stripe_updates");
891
+ delete_user_meta($user_id, "pmpro_stripe_next_on_date_update");
892
+
893
+ continue;
894
+ }
895
+
896
+ $user_updates = $user->pmpro_stripe_updates;
897
+ $next_on_date_update = "";
898
+
899
+ //loop through updates looking for updates happening today or earlier
900
+ if(!empty($user_updates))
901
+ {
902
+ foreach($user_updates as $key => $update)
903
+ {
904
+ if($update['when'] == 'date' &&
905
+ $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'] <= date("Y-m-d")
906
+ )
907
+ {
908
+ //get level for user
909
+ $user_level = pmpro_getMembershipLevelForUser($user_id);
910
+
911
+ //get current plan at Stripe to get payment date
912
+ $last_order = new MemberOrder();
913
+ $last_order->getLastMemberOrder($user_id);
914
+ $last_order->setGateway('stripe');
915
+ $last_order->Gateway->getCustomer($last_order);
916
+
917
+ if(!empty($last_order->Gateway->customer))
918
+ {
919
+ //find the first subscription
920
+ if(!empty($last_order->Gateway->customer->subscriptions['data'][0]))
921
+ {
922
+ $first_sub = $last_order->Gateway->customer->subscriptions['data'][0]->__toArray();
923
+ $end_timestamp = $first_sub['current_period_end'];
924
+ }
925
+ }
926
+
927
+ //if we didn't get an end date, let's set one one cycle out
928
+ $end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period']);
929
+
930
+ //build order object
931
+ $update_order = new MemberOrder();
932
+ $update_order->setGateway('stripe');
933
+ $update_order->user_id = $user_id;
934
+ $update_order->membership_id = $user_level->id;
935
+ $update_order->membership_name = $user_level->name;
936
+ $update_order->InitialPayment = 0;
937
+ $update_order->PaymentAmount = $update['billing_amount'];
938
+ $update_order->ProfileStartDate = date("Y-m-d", $end_timestamp);
939
+ $update_order->BillingPeriod = $update['cycle_period'];
940
+ $update_order->BillingFrequency = $update['cycle_number'];
941
+
942
+ //update subscription
943
+ $update_order->Gateway->subscribe($update_order, false);
944
+
945
+ //update membership
946
+ $sqlQuery = "UPDATE $wpdb->pmpro_memberships_users
947
+ SET billing_amount = '" . esc_sql($update['billing_amount']) . "',
948
+ cycle_number = '" . esc_sql($update['cycle_number']) . "',
949
+ cycle_period = '" . esc_sql($update['cycle_period']) . "'
950
+ WHERE user_id = '" . esc_sql($user_id) . "'
951
+ AND membership_id = '" . esc_sql($last_order->membership_id) . "'
952
+ AND status = 'active'
953
+ LIMIT 1";
954
+
955
+ $wpdb->query($sqlQuery);
956
+
957
+ //save order
958
+ $update_order->status = "success";
959
+ $update_order->save();
960
+
961
+ //remove update from list
962
+ unset($user_updates[$key]);
963
+ }
964
+ elseif($update['when'] == 'date')
965
+ {
966
+ //this is an on date update for the future, update the next on date update
967
+ if(!empty($next_on_date_update))
968
+ $next_on_date_update = min($next_on_date_update, $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day']);
969
+ else
970
+ $next_on_date_update = $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'];
971
+ }
972
+ }
973
+ }
974
+
975
+ //save updates in case we removed some
976
+ update_user_meta($user_id, "pmpro_stripe_updates", $user_updates);
977
+
978
+ //save date of next on-date update to make it easier to query for these in cron job
979
+ update_user_meta($user_id, "pmpro_stripe_next_on_date_update", $next_on_date_update);
980
+ }
981
+ }
982
+ }
983
+
984
+ /**
985
+ * Process checkout and decide if a charge and or subscribe is needed
986
+ *
987
+ * @since 1.4
988
+ */
989
+ function process(&$order)
990
+ {
991
+ //check for initial payment
992
+ if(floatval($order->InitialPayment) == 0)
993
+ {
994
+ //just subscribe
995
+ return $this->subscribe($order);
996
+ }
997
+ else
998
+ {
999
+ //charge then subscribe
1000
+ if($this->charge($order))
1001
+ {
1002
+ if(pmpro_isLevelRecurring($order->membership_level))
1003
+ {
1004
+ if($this->subscribe($order))
1005
+ {
1006
+ //yay!
1007
+ return true;
1008
+ }
1009
+ else
1010
+ {
1011
+ //try to refund initial charge
1012
+ return false;
1013
+ }
1014
+ }
1015
+ else
1016
+ {
1017
+ //only a one time charge
1018
+ $order->status = "success"; //saved on checkout page
1019
+ return true;
1020
+ }
1021
+ }
1022
+ else
1023
+ {
1024
+ if(empty($order->error))
1025
+ $order->error = __("Unknown error: Initial payment failed.", "pmpro");
1026
+ return false;
1027
+ }
1028
+ }
1029
+ }
1030
+
1031
+ /**
1032
+ * Make a one-time charge with Stripe
1033
+ *
1034
+ * @since 1.4
1035
+ */
1036
+ function charge(&$order)
1037
+ {
1038
+ global $pmpro_currency;
1039
+
1040
+ //create a code for the order
1041
+ if(empty($order->code))
1042
+ $order->code = $order->getRandomCode();
1043
+
1044
+ //what amount to charge?
1045
+ $amount = $order->InitialPayment;
1046
+
1047
+ //tax
1048
+ $order->subtotal = $amount;
1049
+ $tax = $order->getTax(true);
1050
+ $amount = round((float)$order->subtotal + (float)$tax, 2);
1051
+
1052
+ //create a customer
1053
+ $result = $this->getCustomer($order);
1054
+
1055
+ if(empty($result))
1056
+ {
1057
+ //failed to create customer
1058
+ return false;
1059
+ }
1060
+
1061
+ //charge
1062
+ try
1063
+ {
1064
+ $response = Stripe_Charge::create(array(
1065
+ "amount" => $amount * 100, # amount in cents, again
1066
+ "currency" => strtolower($pmpro_currency),
1067
+ "customer" => $this->customer->id,
1068
+ "description" => "Order #" . $order->code . ", " . trim($order->FirstName . " " . $order->LastName) . " (" . $order->Email . ")"
1069
+ )
1070
+ );
1071
+ }
1072
+ catch (Exception $e)
1073
+ {
1074
+ //$order->status = "error";
1075
+ $order->errorcode = true;
1076
+ $order->error = "Error: " . $e->getMessage();
1077
+ $order->shorterror = $order->error;
1078
+ return false;
1079
+ }
1080
+
1081
+ if(empty($response["failure_message"]))
1082
+ {
1083
+ //successful charge
1084
+ $order->payment_transaction_id = $response["id"];
1085
+ $order->updateStatus("success");
1086
+ $order->saveOrder();
1087
+ return true;
1088
+ }
1089
+ else
1090
+ {
1091
+ //$order->status = "error";
1092
+ $order->errorcode = true;
1093
+ $order->error = $response['failure_message'];
1094
+ $order->shorterror = $response['failure_message'];
1095
+ return false;
1096
+ }
1097
+ }
1098
+
1099
+ /**
1100
+ * Get a Stripe customer object.
1101
+ *
1102
+ * If $this->customer is set, it returns it.
1103
+ * It first checks if the order has a subscription_transaction_id. If so, that's the customer id.
1104
+ * If not, it checks for a user_id on the order and searches for a customer id in the user meta.
1105
+ * If a customer id is found, it checks for a customer through the Stripe API.
1106
+ * If a customer is found and there is a stripeToken on the order passed, it will update the customer.
1107
+ * If no customer is found and there is a stripeToken on the order passed, it will create a customer.
1108
+ *
1109
+ * @since 1.4
1110
+ * @return Stripe_Customer|false
1111
+ */
1112
+ function getCustomer(&$order = false, $force = false)
1113
+ {
1114
+ global $current_user;
1115
+
1116
+ //already have it?
1117
+ if(!empty($this->customer) && !$force)
1118
+ return $this->customer;
1119
+
1120
+ //figure out user_id and user
1121
+ if(!empty($order->user_id))
1122
+ $user_id = $order->user_id;
1123
+
1124
+ //if no id passed, check the current user
1125
+ if(empty($user_id) && !empty($current_user->ID))
1126
+ $user_id = $current_user->ID;
1127
+
1128
+ if(!empty($user_id))
1129
+ $user = get_userdata($user_id);
1130
+ else
1131
+ $user = NULL;
1132
+
1133
+ //transaction id?
1134
+ if(!empty($order->subscription_transaction_id) && strpos($order->subscription_transaction_id, "cus_") !== false)
1135
+ $customer_id = $order->subscription_transaction_id;
1136
+ else
1137
+ {
1138
+ //try based on user id
1139
+ if(!empty($user_id))
1140
+ {
1141
+ $customer_id = get_user_meta($user_id, "pmpro_stripe_customerid", true);
1142
+ }
1143
+ }
1144
+
1145
+ //get name and email values from order in case we update
1146
+ $name = trim($order->FirstName . " " . $order->LastName);
1147
+ if(empty($name) && !empty($user->ID))
1148
+ {
1149
+ $name = trim($user->first_name . " " . $user->last_name);
1150
+
1151
+ //still empty?
1152
+ if(empty($name))
1153
+ $name = $user->user_login;
1154
+ }
1155
+ elseif(empty($name))
1156
+ $name = "No Name";
1157
+
1158
+ $email = $order->Email;
1159
+ if(empty($email) && !empty($user->ID))
1160
+ {
1161
+ $email = $user->user_email;
1162
+ }
1163
+ elseif(empty($email))
1164
+ $email = "No Email";
1165
+
1166
+ //check for an existing stripe customer
1167
+ if(!empty($customer_id))
1168
+ {
1169
+ try
1170
+ {
1171
+ $this->customer = Stripe_Customer::retrieve($customer_id);
1172
+
1173
+ //update the customer description and card
1174
+ if(!empty($order->stripeToken))
1175
+ {
1176
+ $this->customer->description = $name . " (" . $email . ")";
1177
+ $this->customer->email = $email;
1178
+ $this->customer->card = $order->stripeToken;
1179
+ $this->customer->save();
1180
+ }
1181
+
1182
+ return $this->customer;
1183
+ }
1184
+ catch (Exception $e)
1185
+ {
1186
+ //assume no customer found
1187
+ }
1188
+ }
1189
+
1190
+ //no customer id, create one
1191
+ if(!empty($order->stripeToken))
1192
+ {
1193
+ try
1194
+ {
1195
+ $this->customer = Stripe_Customer::create(array(
1196
+ "description" => $name . " (" . $email . ")",
1197
+ "email" => $order->Email,
1198
+ "card" => $order->stripeToken
1199
+ ));
1200
+ }
1201
+ catch (Exception $e)
1202
+ {
1203
+ $order->error = __("Error creating customer record with Stripe:", "pmpro") . " " . $e->getMessage();
1204
+ $order->shorterror = $order->error;
1205
+ return false;
1206
+ }
1207
+
1208
+ if(!empty($user_id))
1209
+ {
1210
+ //user logged in/etc
1211
+ update_user_meta($user_id, "pmpro_stripe_customerid", $this->customer->id);
1212
+ }
1213
+ else
1214
+ {
1215
+ //user not registered yet, queue it up
1216
+ global $pmpro_stripe_customer_id;
1217
+ $pmpro_stripe_customer_id = $this->customer->id;
1218
+ function pmpro_user_register_stripe_customerid($user_id)
1219
+ {
1220
+ global $pmpro_stripe_customer_id;
1221
+ update_user_meta($user_id, "pmpro_stripe_customerid", $pmpro_stripe_customer_id);
1222
+ }
1223
+ add_action("user_register", "pmpro_user_register_stripe_customerid");
1224
+ }
1225
+
1226
+ return apply_filters('pmpro_stripe_create_customer', $this->customer);
1227
+ }
1228
+
1229
+ return false;
1230
+ }
1231
+
1232
+ /**
1233
+ * Get a Stripe subscription from a PMPro order
1234
+ *
1235
+ * @since 1.8
1236
+ */
1237
+ function getSubscription(&$order)
1238
+ {
1239
+ global $wpdb;
1240
+
1241
+ //no order?
1242
+ if(empty($order) || empty($order->code))
1243
+ return false;
1244
+
1245
+ $result = $this->getCustomer($order, true); //force so we don't get a cached sub for someone else
1246
+
1247
+ //no customer?
1248
+ if(empty($result))
1249
+ return false;
1250
+
1251
+ //is there a subscription transaction id pointing to a sub?
1252
+ if(!empty($order->subscription_transaction_id) && strpos($order->subscription_transaction_id, "sub_") !== false)
1253
+ {
1254
+ try
1255
+ {
1256
+ $sub = $this->customer->subscriptions->retrieve($order->subscription_transaction_id);
1257
+ }
1258
+ catch (Exception $e)
1259
+ {
1260
+ $order->error = __("Error creating plan with Stripe:", "pmpro") . $e->getMessage();
1261
+ $order->shorterror = $order->error;
1262
+ return false;
1263
+ }
1264
+
1265
+ return $sub;
1266
+ }
1267
+
1268
+ //no subscriptions object in customer
1269
+ if(empty($this->customer->subscriptions))
1270
+ return false;
1271
+
1272
+ //find subscription based on customer id and order/plan id
1273
+ $subscriptions = $this->customer->subscriptions->all();
1274
+
1275
+ //no subscriptions
1276
+ if(empty($subscriptions) || empty($subscriptions->data))
1277
+ return false;
1278
+
1279
+ //we really want to test against the order codes of all orders with the same subscription_transaction_id (customer id)
1280
+ $codes = $wpdb->get_col("SELECT code FROM $wpdb->pmpro_membership_orders WHERE user_id = '" . $order->user_id . "' AND subscription_transaction_id = '" . $order->subscription_transaction_id . "' AND status NOT IN('refunded', 'review', 'token', 'error')");
1281
+
1282
+ //find the one for this order
1283
+ foreach($subscriptions->data as $sub)
1284
+ {
1285
+ if(in_array($sub->plan->id, $codes))
1286
+ {
1287
+ return $sub;
1288
+ }
1289
+ }
1290
+
1291
+ //didn't find anything yet
1292
+ return false;
1293
+ }
1294
+
1295
+ /**
1296
+ * Create a new subscription with Stripe
1297
+ *
1298
+ * @since 1.4
1299
+ */
1300
+ function subscribe(&$order, $checkout = true)
1301
+ {
1302
+ global $pmpro_currency;
1303
+
1304
+ //create a code for the order
1305
+ if(empty($order->code))
1306
+ $order->code = $order->getRandomCode();
1307
+
1308
+ //filter order before subscription. use with care.
1309
+ $order = apply_filters("pmpro_subscribe_order", $order, $this);
1310
+
1311
+ //figure out the user
1312
+ if(!empty($order->user_id))
1313
+ $user_id = $order->user_id;
1314
+ else
1315
+ {
1316
+ global $current_user;
1317
+ $user_id = $current_user->ID;
1318
+ }
1319
+
1320
+ //setup customer
1321
+ $result = $this->getCustomer($order);
1322
+ if(empty($result))
1323
+ return false; //error retrieving customer
1324
+
1325
+ //set subscription id to custom id
1326
+ $order->subscription_transaction_id = $this->customer['id']; //transaction id is the customer id, we save it in user meta later too
1327
+
1328
+ //figure out the amounts
1329
+ $amount = $order->PaymentAmount;
1330
+ $amount_tax = $order->getTaxForPrice($amount);
1331
+ $amount = round((float)$amount + (float)$amount_tax, 2);
1332
+
1333
+ /*
1334
+ There are two parts to the trial. Part 1 is simply the delay until the first payment
1335
+ since we are doing the first payment as a separate transaction.
1336
+ The second part is the actual "trial" set by the admin.
1337
+
1338
+ Stripe only supports Year or Month for billing periods, but we account for Days and Weeks just in case.
1339
+ */
1340
+ //figure out the trial length (first payment handled by initial charge)
1341
+ if($order->BillingPeriod == "Year")
1342
+ $trial_period_days = $order->BillingFrequency * 365; //annual
1343
+ elseif($order->BillingPeriod == "Day")
1344
+ $trial_period_days = $order->BillingFrequency * 1; //daily
1345
+ elseif($order->BillingPeriod == "Week")
1346
+ $trial_period_days = $order->BillingFrequency * 7; //weekly
1347
+ else
1348
+ $trial_period_days = $order->BillingFrequency * 30; //assume monthly
1349
+
1350
+ //convert to a profile start date
1351
+ $order->ProfileStartDate = date("Y-m-d", strtotime("+ " . $trial_period_days . " Day", current_time("timestamp"))) . "T0:0:0";
1352
+
1353
+ //filter the start date
1354
+ $order->ProfileStartDate = apply_filters("pmpro_profile_start_date", $order->ProfileStartDate, $order);
1355
+
1356
+ //convert back to days
1357
+ $trial_period_days = ceil(abs(strtotime(date("Y-m-d"), current_time("timestamp")) - strtotime($order->ProfileStartDate, current_time("timestamp"))) / 86400);
1358
+
1359
+ //for free trials, just push the start date of the subscription back
1360
+ if(!empty($order->TrialBillingCycles) && $order->TrialAmount == 0)
1361
+ {
1362
+ $trialOccurrences = (int)$order->TrialBillingCycles;
1363
+ if($order->BillingPeriod == "Year")
1364
+ $trial_period_days = $trial_period_days + (365 * $order->BillingFrequency * $trialOccurrences); //annual
1365
+ elseif($order->BillingPeriod == "Day")
1366
+ $trial_period_days = $trial_period_days + (1 * $order->BillingFrequency * $trialOccurrences); //daily
1367
+ elseif($order->BillingPeriod == "Week")
1368
+ $trial_period_days = $trial_period_days + (7 * $order->BillingFrequency * $trialOccurrences); //weekly
1369
+ else
1370
+ $trial_period_days = $trial_period_days + (30 * $order->BillingFrequency * $trialOccurrences); //assume monthly
1371
+ }
1372
+ elseif(!empty($order->TrialBillingCycles))
1373
+ {
1374
+ /*
1375
+ Let's set the subscription to the trial and give the user an "update" to change the sub later to full price (since v2.0)
1376
+
1377
+ This will force TrialBillingCycles > 1 to act as if they were 1
1378
+ */
1379
+ $new_user_updates = array();
1380
+ $new_user_updates[] = array(
1381
+ 'when' => 'payment',
1382
+ 'billing_amount' => $order->PaymentAmount,
1383
+ 'cycle_period' => $order->BillingPeriod,
1384
+ 'cycle_number' => $order->BillingFrequency
1385
+ );
1386
+
1387
+ //now amount to equal the trial #s
1388
+ $amount = $order->TrialAmount;
1389
+ $amount_tax = $order->getTaxForPrice($amount);
1390
+ $amount = round((float)$amount + (float)$amount_tax, 2);
1391
+ }
1392
+
1393
+ //create a plan
1394
+ try
1395
+ {
1396
+ $plan = array(
1397
+ "amount" => $amount * 100,
1398
+ "interval_count" => $order->BillingFrequency,
1399
+ "interval" => strtolower($order->BillingPeriod),
1400
+ "trial_period_days" => $trial_period_days,
1401
+ "name" => $order->membership_name . " for order " . $order->code,
1402
+ "currency" => strtolower($pmpro_currency),
1403
+ "id" => $order->code
1404
+ );
1405
+
1406
+ $plan = Stripe_Plan::create(apply_filters('pmpro_stripe_create_plan_array', $plan));
1407
+ }
1408
+ catch (Exception $e)
1409
+ {
1410
+ $order->error = __("Error creating plan with Stripe:", "pmpro") . $e->getMessage();
1411
+ $order->shorterror = $order->error;
1412
+ return false;
1413
+ }
1414
+
1415
+ //before subscribing, let's clear out the updates so we don't trigger any during sub
1416
+ if(!empty($user_id))
1417
+ {
1418
+ $old_user_updates = get_user_meta($user_id, "pmpro_stripe_updates", true);
1419
+ update_user_meta($user_id, "pmpro_stripe_updates", array());
1420
+ }
1421
+
1422
+ if(empty($order->subscription_transaction_id) && !empty($this->customer['id']))
1423
+ $order->subscription_transaction_id = $this->customer['id'];
1424
+
1425
+ //subscribe to the plan
1426
+ try
1427
+ {
1428
+ $subscription = array("plan" => $order->code);
1429
+ $result = $this->customer->subscriptions->create(apply_filters('pmpro_stripe_create_subscription_array', $subscription));
1430
+ }
1431
+ catch (Exception $e)
1432
+ {
1433
+ //try to delete the plan
1434
+ $plan->delete();
1435
+
1436
+ //give the user any old updates back
1437
+ if(!empty($user_id))
1438
+ update_user_meta($user_id, "pmpro_stripe_updates", $old_user_updates);
1439
+
1440
+ //return error
1441
+ $order->error = __("Error subscribing customer to plan with Stripe:", "pmpro") . $e->getMessage();
1442
+ $order->shorterror = $order->error;
1443
+ return false;
1444
+ }
1445
+
1446
+ //delete the plan
1447
+ $plan = Stripe_Plan::retrieve($order->code);
1448
+ $plan->delete();
1449
+
1450
+ //if we got this far, we're all good
1451
+ $order->status = "success";
1452
+ $order->subscription_transaction_id = $result['id'];
1453
+
1454
+ //save new updates if this is at checkout
1455
+ if($checkout)
1456
+ {
1457
+ //empty out updates unless set above
1458
+ if(empty($new_user_updates))
1459
+ $new_user_updates = array();
1460
+
1461
+ //update user meta
1462
+ if(!empty($user_id))
1463
+ update_user_meta($user_id, "pmpro_stripe_updates", $new_user_updates);
1464
+ else
1465
+ {
1466
+ //need to remember the user updates to save later
1467
+ global $pmpro_stripe_updates;
1468
+ $pmpro_stripe_updates = $new_user_updates;
1469
+ function pmpro_user_register_stripe_updates($user_id)
1470
+ {
1471
+ global $pmpro_stripe_updates;
1472
+ update_user_meta($user_id, "pmpro_stripe_updates", $pmpro_stripe_updates);
1473
+ }
1474
+ add_action("user_register", "pmpro_user_register_stripe_updates");
1475
+ }
1476
+ }
1477
+ else
1478
+ {
1479
+ //give them their old updates back
1480
+ update_user_meta($user_id, "pmpro_stripe_updates", $old_user_updates);
1481
+ }
1482
+
1483
+ return true;
1484
+ }
1485
+
1486
+ /**
1487
+ * Helper method to update the customer info via getCustomer
1488
+ *
1489
+ * @since 1.4
1490
+ */
1491
+ function update(&$order)
1492
+ {
1493
+ //we just have to run getCustomer which will look for the customer and update it with the new token
1494
+ $result = $this->getCustomer($order);
1495
+
1496
+ if(!empty($result))
1497
+ {
1498
+ return true;
1499
+ }
1500
+ else
1501
+ {
1502
+ return false; //couldn't find the customer
1503
+ }
1504
+ }
1505
+
1506
+ /**
1507
+ * Cancel a subscription at Stripe
1508
+ *
1509
+ * @since 1.4
1510
+ */
1511
+ function cancel(&$order, $update_status = true)
1512
+ {
1513
+ //no matter what happens below, we're going to cancel the order in our system
1514
+ if($update_status)
1515
+ $order->updateStatus("cancelled");
1516
+
1517
+ //require a subscription id
1518
+ if(empty($order->subscription_transaction_id))
1519
+ return false;
1520
+
1521
+ //find the customer
1522
+ $result = $this->getCustomer($order);
1523
+
1524
+ if(!empty($result))
1525
+ {
1526
+ //find subscription with this order code
1527
+ $subscription = $this->getSubscription($order);
1528
+
1529
+ if(!empty($subscription))
1530
+ {
1531
+ if($this->cancelSubscriptionAtGateway($subscription))
1532
+ {
1533
+ //we're okay, going to return true later
1534
+ }
1535
+ else
1536
+ {
1537
+ $order->error = __("Could not cancel old subscription.", "pmpro");
1538
+ $order->shorterror = $order->error;
1539
+
1540
+ return false;
1541
+ }
1542
+ }
1543
+
1544
+ /*
1545
+ Clear updates for this user. (But not if checking out, we would have already done that.)
1546
+ */
1547
+ if(empty($_REQUEST['submit-checkout']))
1548
+ update_user_meta($order->user_id, "pmpro_stripe_updates", array());
1549
+
1550
+ return true;
1551
+ }
1552
+ else
1553
+ {
1554
+ $order->error = __("Could not find the customer.", "pmpro");
1555
+ $order->shorterror = $order->error;
1556
+ return false; //no customer found
1557
+ }
1558
+ }
1559
+
1560
+ /**
1561
+ * Helper method to cancel a subscription at Stripe and also clear up any upaid invoices.
1562
+ *
1563
+ * @since 1.8
1564
+ */
1565
+ function cancelSubscriptionAtGateway($subscription)
1566
+ {
1567
+ //need a valid sub
1568
+ if(empty($subscription->id))
1569
+ return false;
1570
+
1571
+ //make sure we get the customer for this subscription
1572
+ $order = new MemberOrder();
1573
+ $order->getLastMemberOrderBySubscriptionTransactionID($subscription->id);
1574
+
1575
+ //no order?
1576
+ if(empty($order))
1577
+ {
1578
+ //lets cancel anyway, but this is suspicious
1579
+ $r = $subscription->cancel();
1580
+
1581
+ return true;
1582
+ }
1583
+
1584
+ //okay have an order, so get customer so we can cancel invoices too
1585
+ $this->getCustomer($order);
1586
+
1587
+ //get open invoices
1588
+ $invoices = $this->customer->invoices();
1589
+ $invoices = $invoices->all();
1590
+
1591
+ //found it, cancel it
1592
+ try
1593
+ {
1594
+ //find any open invoices for this subscription and forgive them
1595
+ if(!empty($invoices))
1596
+ {
1597
+ foreach($invoices->data as $invoice)
1598
+ {
1599
+ if(!$invoice->closed && $invoice->subscription == $subscription->id)
1600
+ {
1601
+ $invoice->closed = true;
1602
+ $invoice->save();
1603
+ }
1604
+ }
1605
+ }
1606
+
1607
+ //cancel
1608
+ $r = $subscription->cancel();
1609
+
1610
+ return true;
1611
+ }
1612
+ catch(Exception $e)
1613
+ {
1614
+ return false;
1615
+ }
1616
+ }
1617
  }
classes/gateways/class.pmprogateway_twocheckout.php CHANGED
@@ -12,6 +12,13 @@
12
  if(!class_exists("Twocheckout"))
13
  require_once(dirname(__FILE__) . "/../../includes/lib/Twocheckout/Twocheckout.php");
14
 
 
 
 
 
 
 
 
15
  $this->gateway = $gateway;
16
  return $this->gateway;
17
  }
@@ -68,6 +75,7 @@
68
  'gateway_environment',
69
  'twocheckout_apiusername',
70
  'twocheckout_apipassword',
 
71
  'twocheckout_accountnumber',
72
  'twocheckout_secretword',
73
  'currency',
@@ -114,6 +122,7 @@
114
  </th>
115
  <td>
116
  <input type="text" id="twocheckout_apiusername" name="twocheckout_apiusername" size="60" value="<?php echo esc_attr($values['twocheckout_apiusername'])?>" />
 
117
  </td>
118
  </tr>
119
  <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>>
@@ -122,6 +131,16 @@
122
  </th>
123
  <td>
124
  <input type="text" id="twocheckout_apipassword" name="twocheckout_apipassword" size="60" value="<?php echo esc_attr($values['twocheckout_apipassword'])?>" />
 
 
 
 
 
 
 
 
 
 
125
  </td>
126
  </tr>
127
  <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>>
@@ -130,6 +149,7 @@
130
  </th>
131
  <td>
132
  <input type="text" name="twocheckout_accountnumber" size="60" value="<?php echo $values['twocheckout_accountnumber']?>" />
 
133
  </td>
134
  </tr>
135
  <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>>
@@ -138,6 +158,7 @@
138
  </th>
139
  <td>
140
  <input type="text" name="twocheckout_secretword" size="60" value="<?php echo $values['twocheckout_secretword']?>" />
 
141
  </td>
142
  </tr>
143
  <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>>
@@ -145,7 +166,8 @@
145
  <label><?php _e('TwoCheckout INS URL', 'pmpro');?>:</label>
146
  </th>
147
  <td>
148
- <p><?php _e('To fully integrate with 2Checkout, be sure to set your 2Checkout INS URL ', 'pmpro');?> <pre><?php echo admin_url("admin-ajax.php") . "?action=twocheckout-ins";?></pre></p>
 
149
  </td>
150
  </tr>
151
  <?php
@@ -204,7 +226,7 @@
204
  */
205
  static function pmpro_checkout_before_change_membership_level($user_id, $morder)
206
  {
207
- global $discount_code_id;
208
 
209
  //if no order, no need to pay
210
  if(empty($morder))
@@ -246,9 +268,7 @@
246
  function sendToTwocheckout(&$order)
247
  {
248
  global $pmpro_currency;
249
- // Set up credentials
250
- Twocheckout::setCredentials( pmpro_getOption("twocheckout_apiusername"), pmpro_getOption("twocheckout_apipassword") );
251
-
252
  $tco_args = array(
253
  'sid' => pmpro_getOption("twocheckout_accountnumber"),
254
  'mode' => '2CO', // will always be 2CO according to docs (@see https://www.2checkout.com/documentation/checkout/parameter-sets/pass-through-products/)
@@ -295,9 +315,17 @@
295
  }
296
 
297
  // Demo mode?
298
- $environment = pmpro_getOption("gateway_environment");
299
- if("sandbox" === $environment || "beta-sandbox" === $environment)
 
 
 
 
 
300
  $tco_args['demo'] = 'Y';
 
 
 
301
 
302
  // Trial?
303
  //li_#_startup_fee Any start up fees for the product or service. Can be negative to provide discounted first installment pricing, but cannot equal or surpass the product price.
@@ -322,39 +350,64 @@
322
 
323
  $ptpStr = apply_filters( 'pmpro_twocheckout_ptpstr', $ptpStr, $order );
324
 
325
- //echo str_replace("&", "&<br />", $ptpStr);
326
- //exit;
 
327
 
328
- //redirect to 2checkout
329
- $tco_url = 'https://www.2checkout.com/checkout/purchase' . $ptpStr;
 
 
 
 
330
 
331
- //echo $tco_url;
332
- //die();
333
  wp_redirect( $tco_url );
334
  exit;
335
  }
336
 
337
  function cancel(&$order) {
338
- // If recurring, stop the recurring payment
339
- if(pmpro_isLevelRecurring($order->membership_level)) {
340
- $params['sale_id'] = $order->payment_transaction_id;
341
- $result = Twocheckout_Sale::stop( $params ); // Stop the recurring billing
 
 
342
 
343
- // Successfully cancelled
344
- if (isset($result['response_code']) && $result['response_code'] === 'OK') {
345
- $order->updateStatus("cancelled");
346
- return true;
347
- }
348
- // Failed
349
- else {
350
- $order->status = "error";
351
- $order->errorcode = $result->getCode();
352
- $order->error = $result->getMessage();
353
-
354
- return false;
355
- }
 
356
  }
 
 
357
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
  return $order;
359
  }
360
  }
12
  if(!class_exists("Twocheckout"))
13
  require_once(dirname(__FILE__) . "/../../includes/lib/Twocheckout/Twocheckout.php");
14
 
15
+ //set API connection vars
16
+ Twocheckout::sellerId(pmpro_getOption('twocheckout_accountnumber'));
17
+ Twocheckout::privateKey(pmpro_getOption('twocheckout_privatekey'));
18
+ Twocheckout::username(pmpro_getOption('twocheckout_apiusername'));
19
+ Twocheckout::password(pmpro_getOption('twocheckout_apipassword'));
20
+ Twocheckout::$verifySSL = false;
21
+
22
  $this->gateway = $gateway;
23
  return $this->gateway;
24
  }
75
  'gateway_environment',
76
  'twocheckout_apiusername',
77
  'twocheckout_apipassword',
78
+ 'twocheckout_privatekey',
79
  'twocheckout_accountnumber',
80
  'twocheckout_secretword',
81
  'currency',
122
  </th>
123
  <td>
124
  <input type="text" id="twocheckout_apiusername" name="twocheckout_apiusername" size="60" value="<?php echo esc_attr($values['twocheckout_apiusername'])?>" />
125
+ <br /><small><?php _e('Go to Account &raquo; User Management in 2Checkout and create a user with API Access and API Updating.');?></small>
126
  </td>
127
  </tr>
128
  <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>>
131
  </th>
132
  <td>
133
  <input type="text" id="twocheckout_apipassword" name="twocheckout_apipassword" size="60" value="<?php echo esc_attr($values['twocheckout_apipassword'])?>" />
134
+ <br /><small><?php _e('Password for the API user created.');?></small>
135
+ </td>
136
+ </tr>
137
+ <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>>
138
+ <th scope="row" valign="top">
139
+ <label for="twocheckout_privatekey"><?php _e('API Private Key', 'pmpro');?>:</label>
140
+ </th>
141
+ <td>
142
+ <input type="text" name="twocheckout_privatekey" size="60" value="<?php echo $values['twocheckout_privatekey']?>" />
143
+ <br /><small><?php _e('Go to API in 2Checkout and generate a new key pair. Paste the Private Key here.');?></small>
144
  </td>
145
  </tr>
146
  <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>>
149
  </th>
150
  <td>
151
  <input type="text" name="twocheckout_accountnumber" size="60" value="<?php echo $values['twocheckout_accountnumber']?>" />
152
+ <br /><small><?php _e('Click on the profile icon in 2Checkout to find your Account Number.');?></small>
153
  </td>
154
  </tr>
155
  <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>>
158
  </th>
159
  <td>
160
  <input type="text" name="twocheckout_secretword" size="60" value="<?php echo $values['twocheckout_secretword']?>" />
161
+ <br /><small><?php _e('Go to Account &raquo; Site Management. Look under Checkout Options to find the Secret Word.');?></small>
162
  </td>
163
  </tr>
164
  <tr class="gateway gateway_twocheckout" <?php if($gateway != "twocheckout") { ?>style="display: none;"<?php } ?>>
166
  <label><?php _e('TwoCheckout INS URL', 'pmpro');?>:</label>
167
  </th>
168
  <td>
169
+ <p><?php _e('To fully integrate with 2Checkout, be sure to use the following for your INS URL and Approved URL', 'pmpro');?> <pre><?php echo admin_url("admin-ajax.php") . "?action=twocheckout-ins";?></pre></p>
170
+
171
  </td>
172
  </tr>
173
  <?php
226
  */
227
  static function pmpro_checkout_before_change_membership_level($user_id, $morder)
228
  {
229
+ global $wpdb, $discount_code_id;
230
 
231
  //if no order, no need to pay
232
  if(empty($morder))
268
  function sendToTwocheckout(&$order)
269
  {
270
  global $pmpro_currency;
271
+
 
 
272
  $tco_args = array(
273
  'sid' => pmpro_getOption("twocheckout_accountnumber"),
274
  'mode' => '2CO', // will always be 2CO according to docs (@see https://www.2checkout.com/documentation/checkout/parameter-sets/pass-through-products/)
315
  }
316
 
317
  // Demo mode?
318
+ if(empty($order->gateway_environment))
319
+ $gateway_environment = pmpro_getOption("gateway_environment");
320
+ else
321
+ $gateway_environment = $order->gateway_environment;
322
+ if("sandbox" === $gateway_environment || "beta-sandbox" === $gateway_environment)
323
+ {
324
+ Twocheckout::sandbox(true);
325
  $tco_args['demo'] = 'Y';
326
+ }
327
+ else
328
+ Twocheckout::sandbox(false);
329
 
330
  // Trial?
331
  //li_#_startup_fee Any start up fees for the product or service. Can be negative to provide discounted first installment pricing, but cannot equal or surpass the product price.
350
 
351
  $ptpStr = apply_filters( 'pmpro_twocheckout_ptpstr', $ptpStr, $order );
352
 
353
+ ///useful for debugging
354
+ ///echo str_replace("&", "&<br />", $ptpStr);
355
+ ///exit;
356
 
357
+ //figure out gateway environment and URL to use
358
+ if($gateway_environment == "live")
359
+ $host = "www.2checkout.com";
360
+ else
361
+ $host = "sandbox.2checkout.com";
362
+ $tco_url = 'https://' . $host . '/checkout/purchase' . $ptpStr;
363
 
364
+ //redirect to 2checkout
 
365
  wp_redirect( $tco_url );
366
  exit;
367
  }
368
 
369
  function cancel(&$order) {
370
+ //no matter what happens below, we're going to cancel the order in our system
371
+ $order->updateStatus("cancelled");
372
+
373
+ //require a subscription id
374
+ if(empty($order->subscription_transaction_id))
375
+ return false;
376
 
377
+ //build api params
378
+ $params = array();
379
+ $params['sale_id'] = $order->subscription_transaction_id;
380
+
381
+ // Demo mode?
382
+ if(empty($order->gateway_environment))
383
+ $gateway_environment = pmpro_getOption("gateway_environment");
384
+ else
385
+ $gateway_environment = $order->gateway_environment;
386
+
387
+ if("sandbox" === $gateway_environment || "beta-sandbox" === $gateway_environment)
388
+ {
389
+ Twocheckout::sandbox(true);
390
+ $params['demo'] = 'Y';
391
  }
392
+ else
393
+ Twocheckout::sandbox(false);
394
 
395
+ $result = Twocheckout_Sale::stop( $params ); // Stop the recurring billing
396
+
397
+ // Successfully cancelled
398
+ if (isset($result['response_code']) && $result['response_code'] === 'OK') {
399
+ $order->updateStatus("cancelled");
400
+ return true;
401
+ }
402
+ // Failed
403
+ else {
404
+ $order->status = "error";
405
+ $order->errorcode = $result->getCode();
406
+ $order->error = $result->getMessage();
407
+
408
+ return false;
409
+ }
410
+
411
  return $order;
412
  }
413
  }
css/admin.css CHANGED
@@ -1,114 +1,118 @@
1
- /* icon */
2
- #wp-admin-bar-paid-memberships-pro .ab-item .ab-icon:before {
3
- font-family: "dashicons";
4
- content: "\f307";
5
- }
6
- .pmpro_admin tr td .dashicons {padding-top: 5px; }
7
-
8
- /* header/etc */
9
- .pmpro_admin {background: url(../images/Paid-Memberships-Pro_watermark.png) bottom right no-repeat !important; padding: 1em 0 70px 0; }
10
-
11
- .pmpro_admin .pmpro_banner h2 {float: left; }
12
- .pmpro_admin .pmpro_banner .pmpro_meta {float: left; margin: 26px 0 0 0; font-size: 12px; }
13
- .pmpro_admin .pmpro_banner .pmpro_meta .pmpro_tag-blue {margin: 0 0 0 5px; }
14
- .pmpro_admin .pmpro_banner .pmpro_logo {float: left; margin: 0 1em 0 0; width: 350px; height: 75px; }
15
- .pmpro_admin .pmpro_banner ul.pmpro_menu {clear: both; border: 1px solid #CCC; border-radius: 5px; -moz-border-radius: 5px; background: #FFF; }
16
- .pmpro_admin .pmpro_banner ul.pmpro_menu li {display: inline-block; margin: 10px 0; padding: 0px 10px; border-right: 1px solid #CCC; }
17
- .pmpro_admin .pmpro_banner ul.pmpro_menu li a, .pmpro_admin .pmpro_banner ul.pmpro_menu li a:link {color: #1e0741; text-decoration: none; }
18
- .pmpro_admin .pmpro_banner ul.pmpro_menu li a:hover {text-decoration: underline; color: #412f5b; }
19
-
20
- .pmpro_admin .pmpro_tag-grey {display: inline-block; font-size: 11px; font-weight: bold; position: relative; padding: 2px 5px; border: 1px solid #CCC; background: whiteSmoke; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; }
21
- .pmpro_admin .pmpro_tag-blue {display: inline-block; font-size: 11px; font-weight: bold; position: relative; padding: 2px 5px; border: 1px solid #2997c8; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; background: #2997c8; color: #FFF; text-decoration: none; }
22
- .pmpro_admin a.pmpro_tag-blue:hover {background: #77a02e; border: 1px solid #77a02e; }
23
-
24
- .pmpro_admin .topborder {border-top: 1px solid #CCC; margin-top: 1em; padding-top: 1em; }
25
- .pmpro_admin #editorcontainer #description {width: 100%; height: 180px; }
26
- .pmpro_admin .widefat {margin-top: 1em; }
27
-
28
- /* checkboxes */
29
- .checkbox_box {width: 300px; background: #FFFFFF; border: 1px solid #CCC;}
30
- .checkbox_box div {border-bottom: 1px solid #CCC; padding: 3px;}
31
- .checkbox_box .clickable {cursor: pointer;}
32
- .checkbox_box .clickable:hover {background: #FFC;}
33
-
34
- /* levels */
35
- tr.pmpro_gray td {color: #AAA;}
36
- tr td.level_name a {font-size: 115%; font-weight: bold; }
37
-
38
- /* settings */
39
- tr.pmpro_settings_divider td {padding: 5px; margin: 0; color: #555; border-top: 1px solid #CCC; border-bottom: 1px solid #CCC;}
40
- tr.pmpro_settings_divider td:before {content: "- ";}
41
- tr.pmpro_settings_divider td:after {content: " -";}
42
-
43
- /* messages */
44
- .pmpro_message {background-color: #D5E4F7; background-image: url(../images/icon_information.gif); background-position: 3px 5px; background-repeat: no-repeat; margin: .5em 0; padding: 6px 6px 6px 25px; color: #345395; font-size: 11px; font-weight: bold; line-height: 1.3em; }
45
-
46
- .pmpro_success {background-color: #CFEECA; background-image: url(../images/icon_success.gif); color: #208A1B; }
47
- .pmpro_error {background-color: #F9D6CB; background-image: url(../images/icon_error.gif); color: #E36154; }
48
- .pmpro_alert {background-color: #FFF6CC; background-image: url(../images/icon_alert.gif); color: #CF8516; }
49
-
50
- .pmpro_message a {color: #345395; }
51
- .pmpro_success a {color: #208A1B; }
52
- .pmpro_error a {color: #E36154; }
53
- .pmpro_alert a {color: #CF8516; }
54
-
55
- /* highlighted trs */
56
- tr.pmpro_message {background-image: none;}
57
- tr.pmpro_success {background-image: none;}
58
- tr.pmpro_error {background-image: none;}
59
- tr.pmpro_alert {background-image: none;}
60
-
61
- /* discount levels */
62
- .pmpro_discount_levels {border: 1px solid #CCC;}
63
- .pmpro_discount_levels div {padding: 5px; border: 1px solid #CCC;}
64
- .pmpro_discount_levels div div {margin-top: 5px; background: #F5F5F5;}
65
-
66
- /* pagination */
67
- div.pmpro_pagination {padding: 3px; margin: 5px 0px 5px 0px; font-size: 10px; float: right; }
68
- div.pmpro_pagination a {padding: 2px 5px 2px 5px; margin: 1px; border: 1px solid #666; text-decoration: none; /* no underline */ color: #666; background: #EEE; }
69
- div.pmpro_pagination a:hover, div.pmpro_pagination a:active {background: #FFF; }
70
- div.pmpro_pagination span.current {border: 1px solid #FFF; color: #FFF; background: #666; padding: 2px 5px 2px 5px; margin: 1px; font-weight: bold; }
71
- div.pmpro_pagination span.disabled {padding: 2px 5px 2px 5px; margin: 2px; border: 1px solid #BBB; color: #BBB; background: #EFEFEF;}
72
-
73
- p.pmpro_meta_notice {font-size: .8em; padding-top: 5px; border-top: 1px solid #CCC;}
74
-
75
- /* add ons */
76
- .pmpro_admin .widgets-holder-wrap {clear: both; margin-top: 20px; padding: 0 8px; }
77
- .pmpro_admin .widgets-holder-wrap .widget {float: left; width: 32%; margin: 0 1% 1% 0; position: relative; }
78
- .pmpro_admin .widgets-holder-wrap p.description {padding: 0; }
79
- .pmpro_admin .widgets-holder-wrap .widget-top {height: auto; cursor: default; }
80
- .pmpro_admin .widgets-holder-wrap .widget-inside {display: block; height: 130px; overflow: hidden; }
81
- .pmpro_admin .widgets-holder-wrap .widget-inside p {height: 80px; overflow: hidden; }
82
- .pmpro_admin #pmpro-gists.widgets-holder-wrap .widget-inside, .pmpro_admin #pmpro-gists.widgets-holder-wrap .widget-inside p {height: auto; }
83
- .pmpro_admin .widgets-holder-wrap .widget-title { }
84
- .pmpro_admin .widgets-holder-wrap .widget-title h4 { }
85
- .pmpro_admin .widgets-holder-wrap .widget-title .status-label {display: block; float: left; margin: 0 5px 0 0; width: 10px;
86
- height: 10px; overflow: hidden; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; border: 1px solid #DFDFDF; text-indent: -9999em; }
87
- .pmpro_admin .widgets-holder-wrap .disabled .widget-title .status-label {background: #F00; }
88
- .pmpro_admin .widgets-holder-wrap .enabled .widget-title .status-label {background: #0C0; }
89
-
90
- .pmpro_admin .widgets-holder-wrap .widget-title .version {position: absolute; top: 13px; right: 10px; }
91
- .pmpro_admin .widgets-holder-wrap .widget-inside .addon-thumb {width: 100px; height: 100px; float: right; margin: 10px 0 0 10px; border: 1px solid #DFDFDF; background: #FFF; padding: 2px;}
92
-
93
- /*@media (min-width: 1200px) {
94
- .auto-fold .pmpro_admin .widgets-holder-wrap .widget-inside, .auto-fold .pmpro_admin .widgets-holder-wrap .widget-inside p {height: auto; }
95
- }
96
- */
97
- @media (max-width:900px) {
98
- .auto-fold .pmpro_admin .widgets-holder-wrap .widget {float: none; width: 100%; }
99
- .auto-fold .pmpro_admin .widgets-holder-wrap .widget-inside, .auto-fold .pmpro_admin .widgets-holder-wrap .widget-inside p {height: auto; }
100
- }
101
-
102
- /* misc */
103
- .pmpro_lite {color: #AAA;}
104
- .pmpro_pad20 {padding: 20px !important;}
105
- .pmpro_red {color: #CC0000;}
106
- .pmpro_green {color: #00AA00;}
107
- .ssp_description #description {width: 100%;}
108
- .top0em {margin-top: 0;}
109
- h2.nav-tab-wrapper {margin-bottom: 1em; }
110
-
111
- /* reports */
112
- .pmpro_reports-holder { }
113
- .pmpro_clickable {cursor: pointer;}
 
 
 
 
114
  .js .postbox.pmpro_clickable h3 {cursor: pointer;}
1
+ /* icon */
2
+ #wp-admin-bar-paid-memberships-pro .ab-item .ab-icon:before {
3
+ font-family: "dashicons";
4
+ content: "\f307";
5
+ }
6
+ .pmpro_admin tr td .dashicons {padding-top: 5px; }
7
+
8
+ /* header/etc */
9
+ .pmpro_admin {background: url(../images/Paid-Memberships-Pro_watermark.png) bottom right no-repeat !important; padding: 1em 0 70px 0; }
10
+
11
+ .pmpro_admin .pmpro_banner h2 {float: left; }
12
+ .pmpro_admin .pmpro_banner .pmpro_meta {float: left; margin: 26px 0 0 0; font-size: 12px; }
13
+ .pmpro_admin .pmpro_banner .pmpro_meta .pmpro_tag-blue {margin: 0 0 0 5px; }
14
+ .pmpro_admin .pmpro_banner .pmpro_logo {float: left; margin: 0 1em 0 0; width: 350px; height: 75px; }
15
+ .pmpro_admin .pmpro_banner ul.pmpro_menu {clear: both; border: 1px solid #CCC; border-radius: 5px; -moz-border-radius: 5px; background: #FFF; }
16
+ .pmpro_admin .pmpro_banner ul.pmpro_menu li {display: inline-block; margin: 10px 0; padding: 0px 10px; border-right: 1px solid #CCC; }
17
+ .pmpro_admin .pmpro_banner ul.pmpro_menu li a, .pmpro_admin .pmpro_banner ul.pmpro_menu li a:link {color: #1e0741; text-decoration: none; }
18
+ .pmpro_admin .pmpro_banner ul.pmpro_menu li a:hover {text-decoration: underline; color: #412f5b; }
19
+
20
+ .pmpro_admin .pmpro_tag-grey {display: inline-block; font-size: 11px; font-weight: bold; position: relative; padding: 2px 5px; border: 1px solid #CCC; background: whiteSmoke; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; }
21
+ .pmpro_admin .pmpro_tag-blue {display: inline-block; font-size: 11px; font-weight: bold; position: relative; padding: 2px 5px; border: 1px solid #2997c8; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; background: #2997c8; color: #FFF; text-decoration: none; }
22
+ .pmpro_admin a.pmpro_tag-blue:hover {background: #77a02e; border: 1px solid #77a02e; }
23
+
24
+ .pmpro_admin .topborder {border-top: 1px solid #CCC; margin-top: 1em; padding-top: 1em; }
25
+ .pmpro_admin #editorcontainer #description {width: 100%; height: 180px; }
26
+ .pmpro_admin .widefat {margin-top: 1em; }
27
+
28
+ /* checkboxes */
29
+ .checkbox_box {width: 300px; background: #FFFFFF; border: 1px solid #CCC;}
30
+ .checkbox_box div {border-bottom: 1px solid #CCC; padding: 3px;}
31
+ .checkbox_box .clickable {cursor: pointer;}
32
+ .checkbox_box .clickable:hover {background: #FFC;}
33
+
34
+ /* levels */
35
+ tr.pmpro_gray td {color: #AAA;}
36
+ tr td.level_name a {font-size: 115%; font-weight: bold; }
37
+ .membership-levels tr {background: #fff;}
38
+ .membership-levels tr.alternate {background: #f9f9f9;}
39
+ .membership-levels tr.ui-sortable-helper {border: 1px solid #2997C8;}
40
+ tr.testclass {border: 3px solid #2997C8; background: #2997C8;}
41
+
42
+ /* settings */
43
+ tr.pmpro_settings_divider td {padding: 5px; margin: 0; color: #555; border-top: 1px solid #CCC; border-bottom: 1px solid #CCC;}
44
+ tr.pmpro_settings_divider td:before {content: "- ";}
45
+ tr.pmpro_settings_divider td:after {content: " -";}
46
+
47
+ /* messages */
48
+ .pmpro_message {background-color: #D5E4F7; background-image: url(../images/icon_information.gif); background-position: 3px 5px; background-repeat: no-repeat; margin: .5em 0; padding: 6px 6px 6px 25px; color: #345395; font-size: 11px; font-weight: bold; line-height: 1.3em; }
49
+
50
+ .pmpro_success {background-color: #CFEECA; background-image: url(../images/icon_success.gif); color: #208A1B; }
51
+ .pmpro_error {background-color: #F9D6CB; background-image: url(../images/icon_error.gif); color: #E36154; }
52
+ .pmpro_alert {background-color: #FFF6CC; background-image: url(../images/icon_alert.gif); color: #CF8516; }
53
+
54
+ .pmpro_message a {color: #345395; }
55
+ .pmpro_success a {color: #208A1B; }
56
+ .pmpro_error a {color: #E36154; }
57
+ .pmpro_alert a {color: #CF8516; }
58
+
59
+ /* highlighted trs */
60
+ tr.pmpro_message {background-image: none;}
61
+ tr.pmpro_success {background-image: none;}
62
+ tr.pmpro_error {background-image: none;}
63
+ tr.pmpro_alert {background-image: none;}
64
+
65
+ /* discount levels */
66
+ .pmpro_discount_levels {border: 1px solid #CCC;}
67
+ .pmpro_discount_levels div {padding: 5px; border: 1px solid #CCC;}
68
+ .pmpro_discount_levels div div {margin-top: 5px; background: #F5F5F5;}
69
+
70
+ /* pagination */
71
+ div.pmpro_pagination {padding: 3px; margin: 5px 0px 5px 0px; font-size: 10px; float: right; }
72
+ div.pmpro_pagination a {padding: 2px 5px 2px 5px; margin: 1px; border: 1px solid #666; text-decoration: none; /* no underline */ color: #666; background: #EEE; }
73
+ div.pmpro_pagination a:hover, div.pmpro_pagination a:active {background: #FFF; }
74
+ div.pmpro_pagination span.current {border: 1px solid #FFF; color: #FFF; background: #666; padding: 2px 5px 2px 5px; margin: 1px; font-weight: bold; }
75
+ div.pmpro_pagination span.disabled {padding: 2px 5px 2px 5px; margin: 2px; border: 1px solid #BBB; color: #BBB; background: #EFEFEF;}
76
+
77
+ p.pmpro_meta_notice {font-size: .8em; padding-top: 5px; border-top: 1px solid #CCC;}
78
+
79
+ /* add ons */
80
+ .pmpro_admin .widgets-holder-wrap {clear: both; margin-top: 20px; padding: 0 8px; }
81
+ .pmpro_admin .widgets-holder-wrap .widget {float: left; width: 32%; margin: 0 1% 1% 0; position: relative; }
82
+ .pmpro_admin .widgets-holder-wrap p.description {padding: 0; }
83
+ .pmpro_admin .widgets-holder-wrap .widget-top {height: auto; cursor: default; }
84
+ .pmpro_admin .widgets-holder-wrap .widget-inside {display: block; height: 130px; overflow: hidden; }
85
+ .pmpro_admin .widgets-holder-wrap .widget-inside p {height: 80px; overflow: hidden; }
86
+ .pmpro_admin #pmpro-gists.widgets-holder-wrap .widget-inside, .pmpro_admin #pmpro-gists.widgets-holder-wrap .widget-inside p {height: auto; }
87
+ .pmpro_admin .widgets-holder-wrap .widget-title { }
88
+ .pmpro_admin .widgets-holder-wrap .widget-title h4 { }
89
+ .pmpro_admin .widgets-holder-wrap .widget-title .status-label {display: block; float: left; margin: 0 5px 0 0; width: 10px;
90
+ height: 10px; overflow: hidden; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; border: 1px solid #DFDFDF; text-indent: -9999em; }
91
+ .pmpro_admin .widgets-holder-wrap .disabled .widget-title .status-label {background: #F00; }
92
+ .pmpro_admin .widgets-holder-wrap .enabled .widget-title .status-label {background: #0C0; }
93
+
94
+ .pmpro_admin .widgets-holder-wrap .widget-title .version {position: absolute; top: 13px; right: 10px; }
95
+ .pmpro_admin .widgets-holder-wrap .widget-inside .addon-thumb {width: 100px; height: 100px; float: right; margin: 10px 0 0 10px; border: 1px solid #DFDFDF; background: #FFF; padding: 2px;}
96
+
97
+ /*@media (min-width: 1200px) {
98
+ .auto-fold .pmpro_admin .widgets-holder-wrap .widget-inside, .auto-fold .pmpro_admin .widgets-holder-wrap .widget-inside p {height: auto; }
99
+ }
100
+ */
101
+ @media (max-width:900px) {
102
+ .auto-fold .pmpro_admin .widgets-holder-wrap .widget {float: none; width: 100%; }
103
+ .auto-fold .pmpro_admin .widgets-holder-wrap .widget-inside, .auto-fold .pmpro_admin .widgets-holder-wrap .widget-inside p {height: auto; }
104
+ }
105
+
106
+ /* misc */
107
+ .pmpro_lite {color: #AAA;}
108
+ .pmpro_pad20 {padding: 20px !important;}
109
+ .pmpro_red {color: #CC0000;}
110
+ .pmpro_green {color: #00AA00;}
111
+ .ssp_description #description {width: 100%;}
112
+ .top0em {margin-top: 0;}
113
+ h2.nav-tab-wrapper {margin-bottom: 1em; }
114
+
115
+ /* reports */
116
+ .pmpro_reports-holder { }
117
+ .pmpro_clickable {cursor: pointer;}
118
  .js .postbox.pmpro_clickable h3 {cursor: pointer;}
css/frontend.css CHANGED
@@ -1,177 +1,177 @@
1
- /*---------------------------------------
2
- Buttons
3
- ---------------------------------------*/
4
- .pmpro_btn, .pmpro_btn:link, .pmpro_content_message a, .pmpro_content_message a:link {
5
- display: inline-block;
6
- background-color: #EFEFEF;
7
- background-image: none;
8
- border: 1px solid #D6D6D6;
9
- -webkit-border-radius: 4px;
10
- -moz-border-radius: 4px;
11
- border-radius: 4px;
12
- padding: 6px 12px;
13
- margin: 0;
14
- color: #444;
15
- font-size: 12px;
16
- font-weight: 700;
17
- text-transform: none;
18
- text-decoration: none;
19
- text-align: center;
20
- white-space: nowrap;
21
- vertical-align: middle;
22
- cursor: pointer;
23
- -webkit-user-select: none;
24
- -moz-user-select: none;
25
- -ms-user-select: none;
26
- -o-user-select: none;
27
- user-select: none;
28
- }
29
-
30
- .pmpro_btn:focus, .pmpro_content_message a:focus {
31
- outline: thin dotted;
32
- outline: 5px auto -webkit-focus-ring-color;
33
- outline-offset: -2px;
34
- }
35
-
36
- .pmpro_btn:hover, .pmpro_btn:focus, .pmpro_content_message a:focus, .pmpro_content_message a:hover {
37
- color: #000;
38
- background-color: #FAFAFA;
39
- text-decoration: none;
40
- }
41
-
42
- .pmpro_btn:active,
43
- .pmpro_btn.active {
44
- background-image: none;
45
- outline: 0;
46
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
47
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
48
- }
49
-
50
- .pmpro_btn.disabled,
51
- .pmpro_btn[disabled],
52
- fieldset[disabled] .pmpro_btn {
53
- pointer-events: none;
54
- cursor: not-allowed;
55
- opacity: 0.65;
56
- filter: alpha(opacity=65);
57
- -webkit-box-shadow: none;
58
- box-shadow: none;
59
- }
60
-
61
- .pmpro_btn.pmpro_cancel, .pmpro_btn.pmpro_cancel:link {background: none; border: none; margin: 0 0 0 10px; }
62
- /*---------------------------------------
63
- Forms
64
- ---------------------------------------*/
65
- form.pmpro_form div {clear: left; margin: .5em 0 1em 0; }
66
- form.pmpro_form label {float: left; margin: 3px 10px 0 0; width: 120px; font-weight: bold; text-align: right; }
67
- form.pmpro_form label.pmpro_normal {float: none; margin: 0 0 0 0; width: auto; font-weight: normal; text-align: auto;}
68
- .pmpro_clickable {cursor: pointer;}
69
- form.pmpro_form .likelabel {font-weight: bold; }
70
- form.pmpro_form .input, form.pmpro_form textarea, .input, form.pmpro_form select {padding: 3px; border: 1px solid #AAA; margin: 0 3px 0 0; }
71
- form.pmpro_form textarea {font-family: Arial, Helvetica, sans-serif; font-size: 12px; }
72
- form.pmpro_form select {margin: 2px 0 0 0 ; font-size: 12px;}
73
- form.pmpro_form .lite {color: #666; }
74
- form.pmpro_form .leftmar {margin: 8px 0 0 130px; }
75
-
76
- form.pmpro_form .pmpro_captcha {margin: 0 0 0 130px !important; }
77
- form.pmpro_form .pmpro_captcha div {clear: none; margin: 0; }
78
- form.pmpro_form .pmpro_submit {margin-left: 130px; }
79
- form.pmpro_form .pmpro_submit span {float: left; }
80
- form.pmpro_form #pmpro_processing_message {margin: 5px 0 0 10px; font-style: italic; color: #999; }
81
-
82
- /*--------------------------------------------------
83
- Messages - Success, Error, Alert
84
- ----------------------------------------------------*/
85
- .pmpro_message {background-color: #d9edf7; margin: .5em 0; padding: 10px 15px; color: #31708f; font-size: 14px; font-weight: 400; line-height: 1.5em; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; border: 1px solid #bce8f1; }
86
-
87
- .pmpro_success {background-color: #dff0d8; color: #3c763d; border-color: #d6e9c6; }
88
- .pmpro_error {background-color: #f2dede; color: #a94442; border-color: #ebccd1; }
89
- .pmpro_alert {background-color: #fcf8e3; color: #8a6d3b; border-color: #faebcc;}
90
-
91
- .pmpro_content_message a {margin: 5px 5px 0 0; }
92
-
93
- .pmpro_message a {color: #245269; text-decoration: underline; }
94
- .pmpro_success a {color: #2b542c; }
95
- .pmpro_error a {color: #843534; }
96
- .pmpro_alert a {color: #66512c; }
97
-
98
- input.pmpro_error {background-image: none;}
99
- select.pmpro_error {background-image: none;}
100
-
101
- /*---------------------------------------
102
- Membership Checkout
103
- ---------------------------------------*/
104
- .pmpro_checkout thead th {font-weight: bold; color: #444; padding: 10px; }
105
- .pmpro_checkout tbody td {padding: 10px; }
106
- .pmpro_checkout tr.odd td {background: rgba(125,125,125,.1); }
107
- .pmpro_checkout tr.selected td {background: #FFC; }
108
- .pmpro_checkout tr.active td {background: #FFC; }
109
- .pmpro_checkout .name {font-weight: bold; }
110
- .pmpro_checkout ul {margin: 5px 0 0 20px; padding: 0; font-size: .8em; color: #444; }
111
-
112
- .pmpro_checkout tfoot td {padding: 10px; color: #444; }
113
- .pmpro_checkout .topfoot td {border-top: 2px solid #CCC;}
114
- .pmpro_checkout .total td {border-top: 1px solid #CCC; font-size: 1.2em; font-weight: bold; padding-bottom: 30px;}
115
- .pmpro_checkout tfoot .entercode td {background: #EEE; }
116
-
117
- .pmpro_checkout td.rtbdr {border-right: 1px solid #CCC; }
118
-
119
- .pmpro_checkout select {font-size: 11px; }
120
-
121
- .pmpro_thead-msg {display: block; float: right; width: auto; font-style: italic; font-weight: normal; text-align: right; white-space: nowrap; }
122
-
123
- .pmpro_ordersummary {float: right; }
124
-
125
- #pmpro_license { background: #FFF; padding: 5px; border: 1px solid #CCC; height: 200px; margin: 3px; color: #666; overflow: auto; }
126
-
127
- .pmpro_sslseal {float: right; clear: none !important; margin: 0 !important; }
128
-
129
- a.pmpro_radio {text-decoration: none; color: #000;}
130
-
131
- /*---------------------------------------
132
- Membership Invoice
133
- ---------------------------------------*/
134
- .pmpro_invoice { }
135
-
136
-
137
- /*---------------------------------------
138
- Membership Account
139
- ---------------------------------------*/
140
- #pmpro_account .pmpro_box {border-top: 1px solid #CCC; padding: 1em 0; margin: 1em 0; }
141
- #pmpro_account .pmpro_box h3 {margin: 0; padding: 0; border: none; background: none; }
142
- #pmpro_account .pmpro_box p {margin: .5em 0 0 0; padding: 0; }
143
- #pmpro_account .pmpro_box ul {margin-bottom: 0; }
144
-
145
- #pmpro_account #pmpro_account-membership { }
146
- #pmpro_account #pmpro_account-profile { }
147
- #pmpro_account #pmpro_account-billing { }
148
- #pmpro_account #pmpro_account-invoices { }
149
- #pmpro_account #pmpro_account-links { }
150
-
151
- .pmpro_actionlinks {font-size: .8em; margin: .25em 0 0 0; }
152
- .pmpro_actionlinks a {display: inline-block; padding: 0 5px 0 0; margin: 0; text-decoration: none; }
153
- .pmpro_actionlinks a:last-child {padding: 0; }
154
- .pmpro_hidden {display: none;}
155
- li.pmpro_more {list-style-type: none; text-align: center; margin-left: -20px; padding-left: 0;}
156
-
157
- /*---------------------------------------
158
- Membership Levels
159
- ---------------------------------------*/
160
- #pmpro_levels_table {background: #FFF; }
161
- #pmpro_levels_table .pmpro_btn {display: block; }
162
-
163
- /*---------------------------------------
164
- Misc
165
- ---------------------------------------*/
166
- .pmpro_a-right {float: right; width: auto; text-align: right; text-decoration: underline; font-size: 11px; }
167
- .pmpro_a-print {float: right; width: auto; text-decoration: none; color: #345395; background: url(../images/printer.gif) top left no-repeat; padding: 0px 0px 2px 20px; font-size: 11px; line-height: 16px; cursor: pointer; }
168
-
169
- .pmpro_red {color: #CC0000; }
170
- .pmpro_grey {color: #999; }
171
-
172
- .top1em {margin-top: 1em;}
173
- .bot1em {margin-bottom: 1em;}
174
- .bot0em {margin-bottom: 0em;}
175
- .clear {clear: both; }
176
-
177
- .pmpro_small {font-size: .8em;}
1
+ /*---------------------------------------
2
+ Buttons
3
+ ---------------------------------------*/
4
+ .pmpro_btn, .pmpro_btn:link, .pmpro_content_message a, .pmpro_content_message a:link {
5
+ display: inline-block;
6
+ background-color: #EFEFEF;
7
+ background-image: none;
8
+ border: 1px solid #D6D6D6;
9
+ -webkit-border-radius: 4px;
10
+ -moz-border-radius: 4px;
11
+ border-radius: 4px;
12
+ padding: 6px 12px;
13
+ margin: 0;
14
+ color: #444;
15
+ font-size: 12px;
16
+ font-weight: 700;
17
+ text-transform: none;
18
+ text-decoration: none;
19
+ text-align: center;
20
+ white-space: nowrap;
21
+ vertical-align: middle;
22
+ cursor: pointer;
23
+ -webkit-user-select: none;
24
+ -moz-user-select: none;
25
+ -ms-user-select: none;
26
+ -o-user-select: none;
27
+ user-select: none;
28
+ }
29
+
30
+ .pmpro_btn:focus, .pmpro_content_message a:focus {
31
+ outline: thin dotted;
32
+ outline: 5px auto -webkit-focus-ring-color;
33
+ outline-offset: -2px;
34
+ }
35
+
36
+ .pmpro_btn:hover, .pmpro_btn:focus, .pmpro_content_message a:focus, .pmpro_content_message a:hover {
37
+ color: #000;
38
+ background-color: #FAFAFA;
39
+ text-decoration: none;
40
+ }
41
+
42
+ .pmpro_btn:active,
43
+ .pmpro_btn.active {
44
+ background-image: none;
45
+ outline: 0;
46
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
47
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
48
+ }
49
+
50
+ .pmpro_btn.disabled,
51
+ .pmpro_btn[disabled],
52
+ fieldset[disabled] .pmpro_btn {
53
+ pointer-events: none;
54
+ cursor: not-allowed;
55
+ opacity: 0.65;
56
+ filter: alpha(opacity=65);
57
+ -webkit-box-shadow: none;
58
+ box-shadow: none;
59
+ }
60
+
61
+ .pmpro_btn.pmpro_cancel, .pmpro_btn.pmpro_cancel:link {background: none; border: none; margin: 0 0 0 10px; }
62
+ /*---------------------------------------
63
+ Forms
64
+ ---------------------------------------*/
65
+ form.pmpro_form div {clear: left; margin: .5em 0 1em 0; }
66
+ form.pmpro_form label {float: left; margin: 3px 10px 0 0; width: 120px; font-weight: bold; text-align: right; }
67
+ form.pmpro_form label.pmpro_normal {float: none; margin: 0 0 0 0; width: auto; font-weight: normal; text-align: auto;}
68
+ .pmpro_clickable {cursor: pointer;}
69
+ form.pmpro_form .likelabel {font-weight: bold; }
70
+ form.pmpro_form .input, form.pmpro_form textarea, .input, form.pmpro_form select {padding: 3px; border: 1px solid #AAA; margin: 0 3px 0 0; }
71
+ form.pmpro_form textarea {font-family: Arial, Helvetica, sans-serif; font-size: 12px; }
72
+ form.pmpro_form select {margin: 2px 0 0 0 ; font-size: 12px;}
73
+ form.pmpro_form .lite {color: #666; }
74
+ form.pmpro_form .leftmar {margin: 8px 0 0 130px; }
75
+
76
+ form.pmpro_form .pmpro_captcha {margin: 0 0 0 130px !important; }
77
+ form.pmpro_form .pmpro_captcha div {clear: none; margin: 0; }
78
+ form.pmpro_form .pmpro_submit {margin-left: 130px; }
79
+ form.pmpro_form .pmpro_submit span {float: left; }
80
+ form.pmpro_form #pmpro_processing_message {margin: 5px 0 0 10px; font-style: italic; color: #999; }
81
+
82
+ /*--------------------------------------------------
83
+ Messages - Success, Error, Alert
84
+ ----------------------------------------------------*/
85
+ .pmpro_message {background-color: #d9edf7; margin: .5em 0; padding: 10px 15px; color: #31708f; font-size: 14px; font-weight: 400; line-height: 1.5em; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; border: 1px solid #bce8f1; }
86
+
87
+ .pmpro_success {background-color: #dff0d8; color: #3c763d; border-color: #d6e9c6; }
88
+ .pmpro_error {background-color: #f2dede; color: #a94442; border-color: #ebccd1; }
89
+ .pmpro_alert {background-color: #fcf8e3; color: #8a6d3b; border-color: #faebcc;}
90
+
91
+ .pmpro_content_message a {margin: 5px 5px 0 0; }
92
+
93
+ .pmpro_message a {color: #245269; text-decoration: underline; }
94
+ .pmpro_success a {color: #2b542c; }
95
+ .pmpro_error a {color: #843534; }
96
+ .pmpro_alert a {color: #66512c; }
97
+
98
+ input.pmpro_error {background-image: none;}
99
+ select.pmpro_error {background-image: none;}
100
+
101
+ /*---------------------------------------
102
+ Membership Checkout
103
+ ---------------------------------------*/
104
+ .pmpro_checkout thead th {font-weight: bold; color: #444; padding: 10px; }
105
+ .pmpro_checkout tbody td {padding: 10px; }
106
+ .pmpro_checkout tr.odd td {background: rgba(125,125,125,.1); }
107
+ .pmpro_checkout tr.selected td {background: #FFC; }
108
+ .pmpro_checkout tr.active td {background: #FFC; }
109
+ .pmpro_checkout .name {font-weight: bold; }
110
+ .pmpro_checkout ul {margin: 5px 0 0 20px; padding: 0; font-size: .8em; color: #444; }
111
+
112
+ .pmpro_checkout tfoot td {padding: 10px; color: #444; }
113
+ .pmpro_checkout .topfoot td {border-top: 2px solid #CCC;}
114
+ .pmpro_checkout .total td {border-top: 1px solid #CCC; font-size: 1.2em; font-weight: bold; padding-bottom: 30px;}
115
+ .pmpro_checkout tfoot .entercode td {background: #EEE; }
116
+
117
+ .pmpro_checkout td.rtbdr {border-right: 1px solid #CCC; }
118
+
119
+ .pmpro_checkout select {font-size: 11px; }
120
+
121
+ .pmpro_thead-msg {display: block; float: right; width: auto; font-style: italic; font-weight: normal; text-align: right; white-space: nowrap; }
122
+
123
+ .pmpro_ordersummary {float: right; }
124
+
125
+ #pmpro_license { background: #FFF; padding: 5px; border: 1px solid #CCC; height: 200px; margin: 3px; color: #666; overflow: auto; }
126
+
127
+ .pmpro_sslseal {float: right; clear: none !important; margin: 0 !important; }
128
+
129
+ a.pmpro_radio {text-decoration: none; color: #000;}
130
+
131
+ /*---------------------------------------
132
+ Membership Invoice
133
+ ---------------------------------------*/
134
+ .pmpro_invoice { }
135
+
136
+
137
+ /*---------------------------------------
138
+ Membership Account
139
+ ---------------------------------------*/
140
+ #pmpro_account .pmpro_box {border-top: 1px solid #CCC; padding: 1em 0; margin: 1em 0; }
141
+ #pmpro_account .pmpro_box h3 {margin: 0; padding: 0; border: none; background: none; }
142
+ #pmpro_account .pmpro_box p {margin: .5em 0 0 0; padding: 0; }
143
+ #pmpro_account .pmpro_box ul {margin-bottom: 0; }
144
+
145
+ #pmpro_account #pmpro_account-membership { }
146
+ #pmpro_account #pmpro_account-profile { }
147
+ #pmpro_account #pmpro_account-billing { }
148
+ #pmpro_account #pmpro_account-invoices { }
149
+ #pmpro_account #pmpro_account-links { }
150
+
151
+ .pmpro_actionlinks {font-size: .8em; margin: .25em 0 0 0; }
152
+ .pmpro_actionlinks a {display: inline-block; padding: 0 5px 0 0; margin: 0; text-decoration: none; }
153
+ .pmpro_actionlinks a:last-child {padding: 0; }
154
+ .pmpro_hidden {display: none;}
155
+ li.pmpro_more {list-style-type: none; text-align: center; margin-left: -20px; padding-left: 0;}
156
+
157
+ /*---------------------------------------
158
+ Membership Levels
159
+ ---------------------------------------*/
160
+ #pmpro_levels_table {background: #FFF; }
161
+ #pmpro_levels_table .pmpro_btn {display: block; }
162
+
163
+ /*---------------------------------------
164
+ Misc
165
+ ---------------------------------------*/
166
+ .pmpro_a-right {float: right; width: auto; text-align: right; text-decoration: underline; font-size: 11px; }
167
+ .pmpro_a-print {float: right; width: auto; text-decoration: none; color: #345395; background: url(../images/printer.gif) top left no-repeat; padding: 0px 0px 2px 20px; font-size: 11px; line-height: 16px; cursor: pointer; }
168
+
169
+ .pmpro_red {color: #CC0000; }
170
+ .pmpro_grey {color: #999; }
171
+
172
+ .top1em {margin-top: 1em;}
173
+ .bot1em {margin-bottom: 1em;}
174
+ .bot0em {margin-bottom: 0em;}
175
+ .clear {clear: both; }
176
+
177
+ .pmpro_small {font-size: .8em;}
css/print.css CHANGED
@@ -1,5 +1,5 @@
1
  @media print {
2
-
3
- .pmpro_a-print {display: none; position: absolute; left: -9999px; }
4
-
5
  }
1
  @media print {
2
+
3
+ .pmpro_a-print {display: none; position: absolute; left: -9999px; }
4
+
5
  }
email/billing.html CHANGED
@@ -1,12 +1,12 @@
1
  <p>Your billing information at !!sitename!! has been changed.</p>
2
 
3
  <p>Account: !!display_name!! (!!user_email!!)</p>
4
- <p>
5
  Billing Information:<br />
6
  !!billing_address!!
7
  </p>
8
-
9
- <p>
10
  !!cardtype!!: !!accountnumber!!<br />
11
  Expires: !!expirationmonth!!/!!expirationyear!!
12
  </p>
1
  <p>Your billing information at !!sitename!! has been changed.</p>
2
 
3
  <p>Account: !!display_name!! (!!user_email!!)</p>
4
+ <p>
5
  Billing Information:<br />
6
  !!billing_address!!
7
  </p>
8
+
9
+ <p>
10
  !!cardtype!!: !!accountnumber!!<br />
11
  Expires: !!expirationmonth!!/!!expirationyear!!
12
  </p>
email/billing_admin.html CHANGED
@@ -1,15 +1,15 @@
1
  <p>The billing information for !!display_name!! at !!sitename!! has been changed.</p>
2
 
3
  <p>Account: !!display_name!! (!!user_email!!)</p>
4
- <p>
5
  Billing Information:<br />
6
  !!billing_name!!<br />
7
- !!billing_street!!<br />
8
  !!billing_city!!, !!billing_state!! !!billing_zip!! !!billing_country!!
9
  !!billing_phone!!
10
  </p>
11
-
12
- <p>
13
  !!cardtype!!: !!accountnumber!!<br />
14
  Expires: !!expirationmonth!!/!!expirationyear!!
15
  </p>
1
  <p>The billing information for !!display_name!! at !!sitename!! has been changed.</p>
2
 
3
  <p>Account: !!display_name!! (!!user_email!!)</p>
4
+ <p>
5
  Billing Information:<br />
6
  !!billing_name!!<br />
7
+ !!billing_street!!<br />
8
  !!billing_city!!, !!billing_state!! !!billing_zip!! !!billing_country!!
9
  !!billing_phone!!
10
  </p>
11
+
12
+ <p>
13
  !!cardtype!!: !!accountnumber!!<br />
14
  Expires: !!expirationmonth!!/!!expirationyear!!
15
  </p>
email/billing_failure.html CHANGED
@@ -4,8 +4,8 @@
4
  <p>The most recent account information we have on file is:</p>
5
 
6
  <p>!!billing_address!!</p>
7
-
8
- <p>
9
  !!cardtype!!: !!accountnumber!!<br />
10
  Expires: !!expirationmonth!!/!!expirationyear!!
11
  </p>
4
  <p>The most recent account information we have on file is:</p>
5
 
6
  <p>!!billing_address!!</p>
7
+
8
+ <p>
9
  !!cardtype!!: !!accountnumber!!<br />
10
  Expires: !!expirationmonth!!/!!expirationyear!!
11
  </p>
email/billing_failure_admin.html CHANGED
@@ -1,11 +1,11 @@
1
- <p>Payment Failure</p>
2
-
3
- <p>Account: !!display_name!! (!!user_email!!)</p>
4
- <p>The most recent account information we have on file is:</p>
5
-
6
- <p>!!billing_address!!</p>
7
-
8
- <p>
9
- !!cardtype!!: !!accountnumber!!<br />
10
- Expires: !!expirationmonth!!/!!expirationyear!!
11
  </p>
1
+ <p>Payment Failure</p>
2
+
3
+ <p>Account: !!display_name!! (!!user_email!!)</p>
4
+ <p>The most recent account information we have on file is:</p>
5
+
6
+ <p>!!billing_address!!</p>
7
+
8
+ <p>
9
+ !!cardtype!!: !!accountnumber!!<br />
10
+ Expires: !!expirationmonth!!/!!expirationyear!!
11
  </p>
email/cancel_admin.html CHANGED
@@ -4,5 +4,5 @@
4
  <p>Membership Level: !!membership_level_name!!</p>
5
  <p>Start Date: !!startdate!!</p>
6
  <p>Cancellation Date: !!enddate!!</p>
7
-
8
  <p>Log in to your WordPress admin here: !!login_link!!</p>
4
  <p>Membership Level: !!membership_level_name!!</p>
5
  <p>Start Date: !!startdate!!</p>
6
  <p>Cancellation Date: !!enddate!!</p>
7
+
8
  <p>Log in to your WordPress admin here: !!login_link!!</p>
email/checkout_freetrial.html CHANGED
@@ -10,8 +10,8 @@
10
  Billing Information on File:<br />
11
  !!billing_address!!
12
  </p>
13
-
14
- <p>
15
  !!cardtype!!: !!accountnumber!!<br />
16
  Expires: !!expirationmonth!!/!!expirationyear!!
17
  </p>
10
  Billing Information on File:<br />
11
  !!billing_address!!
12
  </p>
13
+
14
+ <p>
15
  !!cardtype!!: !!accountnumber!!<br />
16
  Expires: !!expirationmonth!!/!!expirationyear!!
17
  </p>
email/checkout_freetrial_admin.html CHANGED
@@ -10,8 +10,8 @@
10
  Billing Information on File:<br />
11
  !!billing_address!!
12
  </p>
13
-
14
- <p>
15
  !!cardtype!!: !!accountnumber!!<br />
16
  Expires: !!expirationmonth!!/!!expirationyear!!
17
  </p>
10
  Billing Information on File:<br />
11
  !!billing_address!!
12
  </p>
13
+
14
+ <p>
15
  !!cardtype!!: !!accountnumber!!<br />
16
  Expires: !!expirationmonth!!/!!expirationyear!!
17
  </p>
email/checkout_paid.html CHANGED
@@ -14,8 +14,8 @@
14
  Billing Information:<br />
15
  !!billing_address!!
16
  </p>
17
-
18
- <p>
19
  !!cardtype!!: !!accountnumber!!<br />
20
  Expires: !!expirationmonth!!/!!expirationyear!!
21
  </p>
14
  Billing Information:<br />
15
  !!billing_address!!
16
  </p>
17
+
18
+ <p>
19
  !!cardtype!!: !!accountnumber!!<br />
20
  Expires: !!expirationmonth!!/!!expirationyear!!
21
  </p>
email/checkout_paid_admin.html CHANGED
@@ -14,8 +14,8 @@
14
  Billing Information:<br />
15
  !!billing_address!!
16
  </p>
17
-
18
- <p>
19
  !!cardtype!!: !!accountnumber!!<br />
20
  Expires: !!expirationmonth!!/!!expirationyear!!
21
  </p>
14
  Billing Information:<br />
15
  !!billing_address!!
16
  </p>
17
+
18
+ <p>
19
  !!cardtype!!: !!accountnumber!!<br />
20
  Expires: !!expirationmonth!!/!!expirationyear!!
21
  </p>
email/checkout_trial.html CHANGED
@@ -14,8 +14,8 @@
14
  Billing Information:<br />
15
  !!billing_address!!
16
  </p>
17
-
18
- <p>
19
  !!cardtype!!: !!accountnumber!!<br />
20
  Expires: !!expirationmonth!!/!!expirationyear!!
21
  </p>
14
  Billing Information:<br />
15
  !!billing_address!!
16
  </p>
17
+
18
+ <p>
19
  !!cardtype!!: !!accountnumber!!<br />
20
  Expires: !!expirationmonth!!/!!expirationyear!!
21
  </p>
email/checkout_trial_admin.html CHANGED
@@ -14,8 +14,8 @@
14
  Billing Information:<br />
15
  !!billing_address!!
16
  </p>
17
-
18
- <p>
19
  !!cardtype!!: !!accountnumber!!<br />
20
  Expires: !!expirationmonth!!/!!expirationyear!!
21
  </p>
14
  Billing Information:<br />
15
  !!billing_address!!
16
  </p>
17
+
18
+ <p>
19
  !!cardtype!!: !!accountnumber!!<br />
20
  Expires: !!expirationmonth!!/!!expirationyear!!
21
  </p>
email/credit_card_expiring.html CHANGED
@@ -1,13 +1,13 @@
1
- <p>The payment method used for your membership at !!sitename!! will expire soon. <strong>Please click the following link to log in and update your billing information to avoid account suspension. !!login_link!!</strong></p>
2
-
3
- <p>Account: !!display_name!! (!!user_email!!)</p>
4
- <p>The most recent account information we have on file is:</p>
5
-
6
- <p>!!billing_name!!</br />
7
- !!billing_address!!
8
- </p>
9
-
10
- <p>
11
- !!cardtype!!: !!accountnumber!!<br />
12
- Expires: !!expirationmonth!!/!!expirationyear!!
13
  </p>
1
+ <p>The payment method used for your membership at !!sitename!! will expire soon. <strong>Please click the following link to log in and update your billing information to avoid account suspension. !!login_link!!</strong></p>
2
+
3
+ <p>Account: !!display_name!! (!!user_email!!)</p>
4
+ <p>The most recent account information we have on file is:</p>
5
+
6
+ <p>!!billing_name!!</br />
7
+ !!billing_address!!
8
+ </p>
9
+
10
+ <p>
11
+ !!cardtype!!: !!accountnumber!!<br />
12
+ Expires: !!expirationmonth!!/!!expirationyear!!
13
  </p>
email/invoice.html CHANGED
@@ -9,8 +9,8 @@
9
  Billing Information:<br />
10
  !!billing_address!!
11
  </p>
12
-
13
- <p>
14
  !!cardtype!!: !!accountnumber!!<br />
15
  Expires: !!expirationmonth!!/!!expirationyear!!
16
  </p>
9
  Billing Information:<br />
10
  !!billing_address!!
11
  </p>
12
+
13
+ <p>
14
  !!cardtype!!: !!accountnumber!!<br />
15
  Expires: !!expirationmonth!!/!!expirationyear!!
16
  </p>
email/membership_expired.html CHANGED
@@ -1,7 +1,7 @@
1
- <p>Your membership at !!sitename!! has ended.</p>
2
-
3
- <p>Thank you for your support.</p>
4
-
5
- <p>View our current membership offerings here: !!levels_link!!</p>
6
-
7
  <p>Log in to manage your account here: !!login_link!!</p>
1
+ <p>Your membership at !!sitename!! has ended.</p>
2
+
3
+ <p>Thank you for your support.</p>
4
+
5
+ <p>View our current membership offerings here: !!levels_link!!</p>
6
+
7
  <p>Log in to manage your account here: !!login_link!!</p>
email/membership_expiring.html CHANGED
@@ -1,6 +1,6 @@
1
- <p>Thank you for your membership to !!sitename!!. This is just a reminder that your membership will end on !!enddate!!.</p>
2
-
3
- <p>Account: !!display_name!! (!!user_email!!)</p>
4
- <p>Membership Level: !!membership_level_name!!</p>
5
-
6
  <p>Log in to your membership account here: !!login_link!!</p>
1
+ <p>Thank you for your membership to !!sitename!!. This is just a reminder that your membership will end on !!enddate!!.</p>
2
+
3
+ <p>Account: !!display_name!! (!!user_email!!)</p>
4
+ <p>Membership Level: !!membership_level_name!!</p>
5
+
6
  <p>Log in to your membership account here: !!login_link!!</p>
includes/adminpages.php CHANGED
@@ -1,268 +1,272 @@
1
- <?php
2
- /*
3
- Get array of PMPro Capabilities
4
- */
5
- function pmpro_getPMProCaps()
6
- {
7
- $pmpro_caps = array(
8
- //pmpro_memberships_menu //this controls viewing the menu itself
9
- 'pmpro_membershiplevels',
10
- 'pmpro_pagesettings',
11
- 'pmpro_paymentsettings',
12
- 'pmpro_emailsettings',
13
- 'pmpro_advancedsettings',
14
- 'pmpro_addons',
15
- 'pmpro_memberslist',
16
- 'pmpro_reports',
17
- 'pmpro_orders',
18
- 'pmpro_discountcodes'
19
- );
20
-
21
- return $pmpro_caps;
22
- }
23
-
24
- /*
25
- Dashboard Menu
26
- */
27
- function pmpro_add_pages()
28
- {
29
- global $wpdb;
30
-
31
- //array of all caps in the menu
32
- $pmpro_caps = pmpro_getPMProCaps();
33
-
34
- //the top level menu links to the first page they have access to
35
- foreach($pmpro_caps as $cap)
36
- {
37
- if(current_user_can($cap))
38
- {
39
- $top_menu_cap = $cap;
40
- break;
41
- }
42
- }
43
-
44
- if(empty($top_menu_cap))
45
- return;
46
-
47
- add_menu_page(__('Memberships', 'pmpro'), __('Memberships', 'pmpro'), 'pmpro_memberships_menu', 'pmpro-membershiplevels', $top_menu_cap, 'dashicons-groups');
48
- add_submenu_page('pmpro-membershiplevels', __('Page Settings', 'pmpro'), __('Page Settings', 'pmpro'), 'pmpro_pagesettings', 'pmpro-pagesettings', 'pmpro_pagesettings');
49
- add_submenu_page('pmpro-membershiplevels', __('Payment Settings', 'pmpro'), __('Payment Settings', 'pmpro'), 'pmpro_paymentsettings', 'pmpro-paymentsettings', 'pmpro_paymentsettings');
50
- add_submenu_page('pmpro-membershiplevels', __('Email Settings', 'pmpro'), __('Email Settings', 'pmpro'), 'pmpro_emailsettings', 'pmpro-emailsettings', 'pmpro_emailsettings');
51
- add_submenu_page('pmpro-membershiplevels', __('Advanced Settings', 'pmpro'), __('Advanced Settings', 'pmpro'), 'pmpro_advancedsettings', 'pmpro-advancedsettings', 'pmpro_advancedsettings');
52
- add_submenu_page('pmpro-membershiplevels', __('Add Ons', 'pmpro'), __('Add Ons', 'pmpro'), 'pmpro_addons', 'pmpro-addons', 'pmpro_addons');
53
- add_submenu_page('pmpro-membershiplevels', __('Members List', 'pmpro'), __('Members List', 'pmpro'), 'pmpro_memberslist', 'pmpro-memberslist', 'pmpro_memberslist');
54
- add_submenu_page('pmpro-membershiplevels', __('Reports', 'pmpro'), __('Reports', 'pmpro'), 'pmpro_reports', 'pmpro-reports', 'pmpro_reports');
55
- add_submenu_page('pmpro-membershiplevels', __('Orders', 'pmpro'), __('Orders', 'pmpro'), 'pmpro_orders', 'pmpro-orders', 'pmpro_orders');
56
- add_submenu_page('pmpro-membershiplevels', __('Discount Codes', 'pmpro'), __('Discount Codes', 'pmpro'), 'pmpro_discountcodes', 'pmpro-discountcodes', 'pmpro_discountcodes');
57
-
58
- //rename the automatically added Memberships submenu item
59
- global $submenu;
60
- if(!empty($submenu['pmpro-membershiplevels']))
61
- {
62
- if(current_user_can("pmpro_membershiplevels"))
63
- {
64
- $submenu['pmpro-membershiplevels'][0][0] = __( 'Membership Levels', 'pmpro' );
65
- $submenu['pmpro-membershiplevels'][0][3] = __( 'Membership Levels', 'pmpro' );
66
- }
67
- else
68
- {
69
- unset($submenu['pmpro-membershiplevels']);
70
- }
71
- }
72
- }
73
- add_action('admin_menu', 'pmpro_add_pages');
74
-
75
- /*
76
- Admin Bar
77
- */
78
- function pmpro_admin_bar_menu() {
79
- global $wp_admin_bar;
80
-
81
- //view menu at all?
82
- if ( !current_user_can('pmpro_memberships_menu') || !is_admin_bar_showing() )
83
- return;
84
-
85
- //array of all caps in the menu
86
- $pmpro_caps = pmpro_getPMProCaps();
87
-
88
- //the top level menu links to the first page they have access to
89
- foreach($pmpro_caps as $cap)
90
- {
91
- if(current_user_can($cap))
92
- {
93
- $top_menu_page = str_replace("_", "-", $cap);
94
- break;
95
- }
96
- }
97
-
98
- $wp_admin_bar->add_menu( array(
99
- 'id' => 'paid-memberships-pro',
100
- 'title' => __( '<span class="ab-icon"></span>Memberships', 'pmpro'),
101
- 'href' => get_admin_url(NULL, '/admin.php?page=' . $top_menu_page) ) );
102
-
103
- if(current_user_can('pmpro_membershiplevels'))
104
- $wp_admin_bar->add_menu( array(
105
- 'id' => 'pmpro-membership-levels',
106
- 'parent' => 'paid-memberships-pro',
107
- 'title' => __( 'Membership Levels', 'pmpro'),
108
- 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-membershiplevels') ) );
109
-
110
- if(current_user_can('pmpro_pagesettings'))
111
- $wp_admin_bar->add_menu( array(
112
- 'id' => 'pmpro-page-settings',
113
- 'parent' => 'paid-memberships-pro',
114
- 'title' => __( 'Page Settings', 'pmpro'),
115
- 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-pagesettings') ) );
116
-
117
- if(current_user_can('pmpro_paymentsettings'))
118
- $wp_admin_bar->add_menu( array(
119
- 'id' => 'pmpro-payment-settings',
120
- 'parent' => 'paid-memberships-pro',
121
- 'title' => __( 'Payment Settings', 'pmpro'),
122
- 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-paymentsettings') ) );
123
-
124
- if(current_user_can('pmpro_emailsettings'))
125
- $wp_admin_bar->add_menu( array(
126
- 'id' => 'pmpro-email-settings',
127
- 'parent' => 'paid-memberships-pro',
128
- 'title' => __( 'Email Settings', 'pmpro'),
129
- 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-emailsettings') ) );
130
-
131
- if(current_user_can('pmpro_advancedsettings'))
132
- $wp_admin_bar->add_menu( array(
133
- 'id' => 'pmpro-advanced-settings',
134
- 'parent' => 'paid-memberships-pro',
135
- 'title' => __( 'Advanced Settings', 'pmpro'),
136
- 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-advancedsettings') ) );
137
-
138
- if(current_user_can('pmpro_addons'))
139
- $wp_admin_bar->add_menu( array(
140
- 'id' => 'pmpro-addons',
141
- 'parent' => 'paid-memberships-pro',
142
- 'title' => __( 'Add Ons', 'pmpro'),
143
- 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-addons') ) );
144
-
145
- if(current_user_can('pmpro_memberslist'))
146
- $wp_admin_bar->add_menu( array(
147
- 'id' => 'pmpro-members-list',
148
- 'parent' => 'paid-memberships-pro',
149
- 'title' => __( 'Members List', 'pmpro'),
150
- 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-memberslist') ) );
151
-
152
- if(current_user_can('pmpro_reports'))
153
- $wp_admin_bar->add_menu( array(
154
- 'id' => 'pmpro-reports',
155
- 'parent' => 'paid-memberships-pro',
156
- 'title' => __( 'Reports', 'pmpro'),
157
- 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-reports') ) );
158
-
159
- if(current_user_can('pmpro_orders'))
160
- $wp_admin_bar->add_menu( array(
161
- 'id' => 'pmpro-orders',
162
- 'parent' => 'paid-memberships-pro',
163
- 'title' => __( 'Orders', 'pmpro'),
164
- 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-orders') ) );
165
-
166
- if(current_user_can('pmpro_discountcodes'))
167
- $wp_admin_bar->add_menu( array(
168
- 'id' => 'pmpro-discount-codes',
169
- 'parent' => 'paid-memberships-pro',
170
- 'title' => __( 'Discount Codes', 'pmpro'),
171
- 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-discountcodes') ) );
172
- }
173
- add_action('admin_bar_menu', 'pmpro_admin_bar_menu', 1000);
174
-
175
- /*
176
- Functions to load pages from adminpages directory
177
- */
178
- function pmpro_reports()
179
- {
180
- require_once(PMPRO_DIR . "/adminpages/reports.php");
181
- }
182
-
183
- function pmpro_memberslist()
184
- {
185
- require_once(PMPRO_DIR . "/adminpages/memberslist.php");
186
- }
187
-
188
- function pmpro_discountcodes()
189
- {
190
- require_once(PMPRO_DIR . "/adminpages/discountcodes.php");
191
- }
192
-
193
- function pmpro_membershiplevels()
194
- {
195
- require_once(PMPRO_DIR . "/adminpages/membershiplevels.php");
196
- }
197
-
198
- function pmpro_pagesettings()
199
- {
200
- require_once(PMPRO_DIR . "/adminpages/pagesettings.php");
201
- }
202
-
203
- function pmpro_paymentsettings()
204
- {
205
- require_once(PMPRO_DIR . "/adminpages/paymentsettings.php");
206
- }
207
-
208
- function pmpro_emailsettings()
209
- {
210
- require_once(PMPRO_DIR . "/adminpages/emailsettings.php");
211
- }
212
-
213
- function pmpro_advancedsettings()
214
- {
215
- require_once(PMPRO_DIR . "/adminpages/advancedsettings.php");
216
- }
217
-
218
- function pmpro_addons()
219
- {
220
- require_once(PMPRO_DIR . "/adminpages/addons.php");
221
- }
222
-
223
- function pmpro_orders()
224
- {
225
- require_once(PMPRO_DIR . "/adminpages/orders.php");
226
- }
227
-
228
-
229
- /*
230
- Function to add links to the plugin action links
231
- */
232
- function pmpro_add_action_links($links) {
233
-
234
- //array of all caps in the menu
235
- $pmpro_caps = pmpro_getPMProCaps();
236
-
237
- //the top level menu links to the first page they have access to
238
- foreach($pmpro_caps as $cap)
239
- {
240
- if(current_user_can($cap))
241
- {
242
- $top_menu_page = str_replace("_", "-", $cap);
243
- break;
244
- }
245
- }
246
-
247
- $new_links = array(
248
- '<a href="' . get_admin_url(NULL, 'admin.php?page=' . $top_menu_page) . '">Settings</a>',
249
- );
250
- return array_merge($new_links, $links);
251
- }
252
- add_filter('plugin_action_links_' . plugin_basename(PMPRO_DIR . "/paid-memberships-pro.php"), 'pmpro_add_action_links');
253
-
254
- /*
255
- Function to add links to the plugin row meta
256
- */
257
- function pmpro_plugin_row_meta($links, $file) {
258
- if(strpos($file, 'paid-memberships-pro.php') !== false)
259
- {
260
- $new_links = array(
261
- '<a href="' . esc_url( apply_filters( 'pmpro_docs_url', 'http://paidmembershipspro.com/documentation/' ) ) . '" title="' . esc_attr( __( 'View PMPro Documentation', 'pmpro' ) ) . '">' . __( 'Docs', 'pmpro' ) . '</a>',
262
- '<a href="' . esc_url( apply_filters( 'pmpro_support_url', 'http://paidmembershipspro.com/support/' ) ) . '" title="' . esc_attr( __( 'Visit Customer Support Forum', 'pmpro' ) ) . '">' . __( 'Support', 'pmpro' ) . '</a>',
263
- );
264
- $links = array_merge($links, $new_links);
265
- }
266
- return $links;
267
- }
268
- add_filter('plugin_row_meta', 'pmpro_plugin_row_meta', 10, 2);
 
 
 
 
1
+ <?php
2
+ /*
3
+ Get array of PMPro Capabilities
4
+ */
5
+ function pmpro_getPMProCaps()
6
+ {
7
+ $pmpro_caps = array(
8
+ //pmpro_memberships_menu //this controls viewing the menu itself
9
+ 'pmpro_membershiplevels',
10
+ 'pmpro_pagesettings',
11
+ 'pmpro_paymentsettings',
12
+ 'pmpro_emailsettings',
13
+ 'pmpro_advancedsettings',
14
+ 'pmpro_addons',
15
+ 'pmpro_memberslist',
16
+ 'pmpro_reports',
17
+ 'pmpro_orders',
18
+ 'pmpro_discountcodes'
19
+ );
20
+
21
+ return $pmpro_caps;
22
+ }
23
+
24
+ /*
25
+ Dashboard Menu
26
+ */
27
+ function pmpro_add_pages()
28
+ {
29
+ global $wpdb;
30
+
31
+ //array of all caps in the menu
32
+ $pmpro_caps = pmpro_getPMProCaps();
33
+
34
+ //the top level menu links to the first page they have access to
35
+ foreach($pmpro_caps as $cap)
36
+ {
37
+ if(current_user_can($cap))
38
+ {
39
+ $top_menu_cap = $cap;
40
+ break;
41
+ }
42
+ }
43
+
44
+ if(empty($top_menu_cap))
45
+ return;
46
+
47
+ add_menu_page(__('Memberships', 'pmpro'), __('Memberships', 'pmpro'), 'pmpro_memberships_menu', 'pmpro-membershiplevels', $top_menu_cap, 'dashicons-groups');
48
+ add_submenu_page('pmpro-membershiplevels', __('Page Settings', 'pmpro'), __('Page Settings', 'pmpro'), 'pmpro_pagesettings', 'pmpro-pagesettings', 'pmpro_pagesettings');
49
+ add_submenu_page('pmpro-membershiplevels', __('Payment Settings', 'pmpro'), __('Payment Settings', 'pmpro'), 'pmpro_paymentsettings', 'pmpro-paymentsettings', 'pmpro_paymentsettings');
50
+ add_submenu_page('pmpro-membershiplevels', __('Email Settings', 'pmpro'), __('Email Settings', 'pmpro'), 'pmpro_emailsettings', 'pmpro-emailsettings', 'pmpro_emailsettings');
51
+ add_submenu_page('pmpro-membershiplevels', __('Advanced Settings', 'pmpro'), __('Advanced Settings', 'pmpro'), 'pmpro_advancedsettings', 'pmpro-advancedsettings', 'pmpro_advancedsettings');
52
+ add_submenu_page('pmpro-membershiplevels', __('Add Ons', 'pmpro'), __('Add Ons', 'pmpro'), 'pmpro_addons', 'pmpro-addons', 'pmpro_addons');
53
+ add_submenu_page('pmpro-membershiplevels', __('Members List', 'pmpro'), __('Members List', 'pmpro'), 'pmpro_memberslist', 'pmpro-memberslist', 'pmpro_memberslist');
54
+ add_submenu_page('pmpro-membershiplevels', __('Reports', 'pmpro'), __('Reports', 'pmpro'), 'pmpro_reports', 'pmpro-reports', 'pmpro_reports');
55
+ add_submenu_page('pmpro-membershiplevels', __('Orders', 'pmpro'), __('Orders', 'pmpro'), 'pmpro_orders', 'pmpro-orders', 'pmpro_orders');
56
+ add_submenu_page('pmpro-membershiplevels', __('Discount Codes', 'pmpro'), __('Discount Codes', 'pmpro'), 'pmpro_discountcodes', 'pmpro-discountcodes', 'pmpro_discountcodes');
57
+
58
+ //rename the automatically added Memberships submenu item
59
+ global $submenu;
60
+ if(!empty($submenu['pmpro-membershiplevels']))
61
+ {
62
+ if(current_user_can("pmpro_membershiplevels"))
63
+ {
64
+ $submenu['pmpro-membershiplevels'][0][0] = __( 'Membership Levels', 'pmpro' );
65
+ $submenu['pmpro-membershiplevels'][0][3] = __( 'Membership Levels', 'pmpro' );
66
+ }
67
+ elseif(current_user_can($top_menu_cap))
68
+ {
69
+ unset($submenu['pmpro-membershiplevels'][0]);
70
+ }
71
+ else
72
+ {
73
+ unset($submenu['pmpro-membershiplevels']);
74
+ }
75
+ }
76
+ }
77
+ add_action('admin_menu', 'pmpro_add_pages');
78
+
79
+ /*
80
+ Admin Bar
81
+ */
82
+ function pmpro_admin_bar_menu() {
83
+ global $wp_admin_bar;
84
+
85
+ //view menu at all?
86
+ if ( !current_user_can('pmpro_memberships_menu') || !is_admin_bar_showing() )
87
+ return;
88
+
89
+ //array of all caps in the menu
90
+ $pmpro_caps = pmpro_getPMProCaps();
91
+
92
+ //the top level menu links to the first page they have access to
93
+ foreach($pmpro_caps as $cap)
94
+ {
95
+ if(current_user_can($cap))
96
+ {
97
+ $top_menu_page = str_replace("_", "-", $cap);
98
+ break;
99
+ }
100
+ }
101
+
102
+ $wp_admin_bar->add_menu( array(
103
+ 'id' => 'paid-memberships-pro',
104
+ 'title' => __( '<span class="ab-icon"></span>Memberships', 'pmpro'),
105
+ 'href' => get_admin_url(NULL, '/admin.php?page=' . $top_menu_page) ) );
106
+
107
+ if(current_user_can('pmpro_membershiplevels'))
108
+ $wp_admin_bar->add_menu( array(
109
+ 'id' => 'pmpro-membership-levels',
110
+ 'parent' => 'paid-memberships-pro',
111
+ 'title' => __( 'Membership Levels', 'pmpro'),
112
+ 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-membershiplevels') ) );
113
+
114
+ if(current_user_can('pmpro_pagesettings'))
115
+ $wp_admin_bar->add_menu( array(
116
+ 'id' => 'pmpro-page-settings',
117
+ 'parent' => 'paid-memberships-pro',
118
+ 'title' => __( 'Page Settings', 'pmpro'),
119
+ 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-pagesettings') ) );
120
+
121
+ if(current_user_can('pmpro_paymentsettings'))
122
+ $wp_admin_bar->add_menu( array(
123
+ 'id' => 'pmpro-payment-settings',
124
+ 'parent' => 'paid-memberships-pro',
125
+ 'title' => __( 'Payment Settings', 'pmpro'),
126
+ 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-paymentsettings') ) );
127
+
128
+ if(current_user_can('pmpro_emailsettings'))
129
+ $wp_admin_bar->add_menu( array(
130
+ 'id' => 'pmpro-email-settings',
131
+ 'parent' => 'paid-memberships-pro',
132
+ 'title' => __( 'Email Settings', 'pmpro'),
133
+ 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-emailsettings') ) );
134
+
135
+ if(current_user_can('pmpro_advancedsettings'))
136
+ $wp_admin_bar->add_menu( array(
137
+ 'id' => 'pmpro-advanced-settings',
138
+ 'parent' => 'paid-memberships-pro',
139
+ 'title' => __( 'Advanced Settings', 'pmpro'),
140
+ 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-advancedsettings') ) );
141
+
142
+ if(current_user_can('pmpro_addons'))
143
+ $wp_admin_bar->add_menu( array(
144
+ 'id' => 'pmpro-addons',
145
+ 'parent' => 'paid-memberships-pro',
146
+ 'title' => __( 'Add Ons', 'pmpro'),
147
+ 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-addons') ) );
148
+
149
+ if(current_user_can('pmpro_memberslist'))
150
+ $wp_admin_bar->add_menu( array(
151
+ 'id' => 'pmpro-members-list',
152
+ 'parent' => 'paid-memberships-pro',
153
+ 'title' => __( 'Members List', 'pmpro'),
154
+ 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-memberslist') ) );
155
+
156
+ if(current_user_can('pmpro_reports'))
157
+ $wp_admin_bar->add_menu( array(
158
+ 'id' => 'pmpro-reports',
159
+ 'parent' => 'paid-memberships-pro',
160
+ 'title' => __( 'Reports', 'pmpro'),
161
+ 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-reports') ) );
162
+
163
+ if(current_user_can('pmpro_orders'))
164
+ $wp_admin_bar->add_menu( array(
165
+ 'id' => 'pmpro-orders',
166
+ 'parent' => 'paid-memberships-pro',
167
+ 'title' => __( 'Orders', 'pmpro'),
168
+ 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-orders') ) );
169
+
170
+ if(current_user_can('pmpro_discountcodes'))
171
+ $wp_admin_bar->add_menu( array(
172
+ 'id' => 'pmpro-discount-codes',
173
+ 'parent' => 'paid-memberships-pro',
174
+ 'title' => __( 'Discount Codes', 'pmpro'),
175
+ 'href' => get_admin_url(NULL, '/admin.php?page=pmpro-discountcodes') ) );
176
+ }
177
+ add_action('admin_bar_menu', 'pmpro_admin_bar_menu', 1000);
178
+
179
+ /*
180
+ Functions to load pages from adminpages directory
181
+ */
182
+ function pmpro_reports()
183
+ {
184
+ require_once(PMPRO_DIR . "/adminpages/reports.php");
185
+ }
186
+
187
+ function pmpro_memberslist()
188
+ {
189
+ require_once(PMPRO_DIR . "/adminpages/memberslist.php");
190
+ }
191
+
192
+ function pmpro_discountcodes()
193
+ {
194
+ require_once(PMPRO_DIR . "/adminpages/discountcodes.php");
195
+ }
196
+
197
+ function pmpro_membershiplevels()
198
+ {
199
+ require_once(PMPRO_DIR . "/adminpages/membershiplevels.php");
200
+ }
201
+
202
+ function pmpro_pagesettings()
203
+ {
204
+ require_once(PMPRO_DIR . "/adminpages/pagesettings.php");
205
+ }
206
+
207
+ function pmpro_paymentsettings()
208
+ {
209
+ require_once(PMPRO_DIR . "/adminpages/paymentsettings.php");
210
+ }
211
+
212
+ function pmpro_emailsettings()
213
+ {
214
+ require_once(PMPRO_DIR . "/adminpages/emailsettings.php");
215
+ }
216
+
217
+ function pmpro_advancedsettings()
218
+ {
219
+ require_once(PMPRO_DIR . "/adminpages/advancedsettings.php");
220
+ }
221
+
222
+ function pmpro_addons()
223
+ {
224
+ require_once(PMPRO_DIR . "/adminpages/addons.php");
225
+ }
226
+
227
+ function pmpro_orders()
228
+ {
229
+ require_once(PMPRO_DIR . "/adminpages/orders.php");
230
+ }
231
+
232
+
233
+ /*
234
+ Function to add links to the plugin action links
235
+ */
236
+ function pmpro_add_action_links($links) {
237
+
238
+ //array of all caps in the menu
239
+ $pmpro_caps = pmpro_getPMProCaps();
240
+
241
+ //the top level menu links to the first page they have access to
242
+ foreach($pmpro_caps as $cap)
243
+ {
244
+ if(current_user_can($cap))
245
+ {
246
+ $top_menu_page = str_replace("_", "-", $cap);
247
+ break;
248
+ }
249
+ }
250
+
251
+ $new_links = array(
252
+ '<a href="' . get_admin_url(NULL, 'admin.php?page=' . $top_menu_page) . '">Settings</a>',
253
+ );
254
+ return array_merge($new_links, $links);
255
+ }
256
+ add_filter('plugin_action_links_' . plugin_basename(PMPRO_DIR . "/paid-memberships-pro.php"), 'pmpro_add_action_links');
257
+
258
+ /*
259
+ Function to add links to the plugin row meta
260
+ */
261
+ function pmpro_plugin_row_meta($links, $file) {
262
+ if(strpos($file, 'paid-memberships-pro.php') !== false)
263
+ {
264
+ $new_links = array(
265
+ '<a href="' . esc_url( apply_filters( 'pmpro_docs_url', 'http://paidmembershipspro.com/documentation/' ) ) . '" title="' . esc_attr( __( 'View PMPro Documentation', 'pmpro' ) ) . '">' . __( 'Docs', 'pmpro' ) . '</a>',
266
+ '<a href="' . esc_url( apply_filters( 'pmpro_support_url', 'http://paidmembershipspro.com/support/' ) ) . '" title="' . esc_attr( __( 'Visit Customer Support Forum', 'pmpro' ) ) . '">' . __( 'Support', 'pmpro' ) . '</a>',
267
+ );
268
+ $links = array_merge($links, $new_links);
269
+ }
270
+ return $links;
271
+ }
272
+ add_filter('plugin_row_meta', 'pmpro_plugin_row_meta', 10, 2);
includes/cleanup.php CHANGED
@@ -1,40 +1,40 @@
1
- <?php
2
- /*
3
- Clean things up when deletes happen, etc. (This stuff needs a better home.)
4
- */
5
- //deleting a user? remove their account info.
6
- function pmpro_delete_user($user_id = NULL)
7
- {
8
- global $wpdb;
9
-
10
- //changing their membership level to 0 will cancel any subscription and remove their membership level entry
11
- //we don't remove the orders because it would affect reporting
12
- if(pmpro_changeMembershipLevel(0, $user_id))
13
- {
14
- //okay
15
- }
16
- else
17
- {
18
- //okay, guessing they didn't have a level
19
- }
20
- }
21
- add_action('delete_user', 'pmpro_delete_user');
22
- add_action('wpmu_delete_user', 'pmpro_delete_user');
23
-
24
- //deleting a category? remove any level associations
25
- function pmpro_delete_category($cat_id = NULL)
26
- {
27
- global $wpdb;
28
- $sqlQuery = "DELETE FROM $wpdb->pmpro_memberships_categories WHERE category_id = '" . $cat_id . "'";
29
- $wpdb->query($sqlQuery);
30
- }
31
- add_action('delete_category', 'pmpro_delete_category');
32
-
33
- //deleting a post? remove any level associations
34
- function pmpro_delete_post($post_id = NULL)
35
- {
36
- global $wpdb;
37
- $sqlQuery = "DELETE FROM $wpdb->pmpro_memberships_pages WHERE page_id = '" . $post_id . "'";
38
- $wpdb->query($sqlQuery);
39
- }
40
  add_action('delete_post', 'pmpro_delete_post');
1
+ <?php
2
+ /*
3
+ Clean things up when deletes happen, etc. (This stuff needs a better home.)
4
+ */
5
+ //deleting a user? remove their account info.
6
+ function pmpro_delete_user($user_id = NULL)
7
+ {
8
+ global $wpdb;
9
+
10
+ //changing their membership level to 0 will cancel any subscription and remove their membership level entry
11
+ //we don't remove the orders because it would affect reporting
12
+ if(pmpro_changeMembershipLevel(0, $user_id))
13
+ {
14
+ //okay
15
+ }
16
+ else
17
+ {
18
+ //okay, guessing they didn't have a level
19
+ }
20
+ }
21
+ add_action('delete_user', 'pmpro_delete_user');
22
+ add_action('wpmu_delete_user', 'pmpro_delete_user');
23
+
24
+ //deleting a category? remove any level associations
25
+ function pmpro_delete_category($cat_id = NULL)
26
+ {
27
+ global $wpdb;
28
+ $sqlQuery = "DELETE FROM $wpdb->pmpro_memberships_categories WHERE category_id = '" . $cat_id . "'";
29
+ $wpdb->query($sqlQuery);
30
+ }
31
+ add_action('delete_category', 'pmpro_delete_category');
32
+
33
+ //deleting a post? remove any level associations
34
+ function pmpro_delete_post($post_id = NULL)
35
+ {
36
+ global $wpdb;
37
+ $sqlQuery = "DELETE FROM $wpdb->pmpro_memberships_pages WHERE page_id = '" . $post_id . "'";
38
+ $wpdb->query($sqlQuery);
39
+ }
40
  add_action('delete_post', 'pmpro_delete_post');
includes/content.php CHANGED
@@ -1,458 +1,461 @@
1
- <?php
2
- /*
3
- Functions to detect member content and protect it.
4
- */
5
- function pmpro_has_membership_access($post_id = NULL, $user_id = NULL, $return_membership_levels = false)
6
- {
7
- global $post, $wpdb, $current_user;
8
- //use globals if no values supplied
9
- if(!$post_id && !empty($post))
10
- $post_id = $post->ID;
11
- if(!$user_id)
12
- $user_id = $current_user->ID;
13
-
14
- //no post, return true (changed from false in version 1.7.2)
15
- if(!$post_id)
16
- return true;
17
-
18
- //if no post or current_user object, set them up
19
- if(!empty($post->ID) && $post_id == $post->ID)
20
- $mypost = $post;
21
- else
22
- $mypost = get_post($post_id);
23
-
24
- if($user_id == $current_user->ID)
25
- $myuser = $current_user;
26
- else
27
- $myuser = get_userdata($user_id);
28
-
29
- //for these post types, we want to check the parent
30
- if($mypost->post_type == "attachment" || $mypost->post_type == "revision")
31
- {
32
- $mypost = get_post($mypost->post_parent);
33
- }
34
-
35
- if($mypost->post_type == "post")
36
- {
37
- $post_categories = wp_get_post_categories($mypost->ID);
38
-
39
- if(!$post_categories)
40
- {
41
- //just check for entries in the memberships_pages table
42
- $sqlQuery = "SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . $mypost->ID . "'";
43
- }
44
- else
45
- {
46
- //are any of the post categories associated with membership levels? also check the memberships_pages table
47
- $sqlQuery = "(SELECT m.id, m.name FROM $wpdb->pmpro_memberships_categories mc LEFT JOIN $wpdb->pmpro_membership_levels m ON mc.membership_id = m.id WHERE mc.category_id IN(" . implode(",", $post_categories) . ") AND m.id IS NOT NULL) UNION (SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . $mypost->ID . "')";
48
- }
49
- }
50
- else
51
- {
52
- //are any membership levels associated with this page?
53
- $sqlQuery = "SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . $mypost->ID . "'";
54
- }
55
-
56
-
57
- $post_membership_levels = $wpdb->get_results($sqlQuery);
58
-
59
- $post_membership_levels_ids = array();
60
- $post_membership_levels_names = array();
61
-
62
- if(!$post_membership_levels)
63
- {
64
- $hasaccess = true;
65
- }
66
- else
67
- {
68
- //we need to see if the user has access
69
- foreach($post_membership_levels as $level)
70
- {
71
- $post_membership_levels_ids[] = $level->id;
72
- $post_membership_levels_names[] = $level->name;
73
- }
74
-
75
- //levels found. check if this is in a feed or if the current user is in at least one of those membership levels
76
- if(is_feed())
77
- {
78
- //always block restricted feeds
79
- $hasaccess = false;
80
- }
81
- elseif(!empty($myuser->ID))
82
- {
83
- $myuser->membership_level = pmpro_getMembershipLevelForUser($myuser->ID);
84
- if(!empty($myuser->membership_level->ID) && in_array($myuser->membership_level->ID, $post_membership_levels_ids))
85
- {
86
- //the users membership id is one that will grant access
87
- $hasaccess = true;
88
- }
89
- else
90
- {
91
- //user isn't a member of a level with access
92
- $hasaccess = false;
93
- }
94
- }
95
- else
96
- {
97
- //user is not logged in and this content requires membership
98
- $hasaccess = false;
99
- }
100
- }
101
-
102
- /*
103
- Filters
104
- The generic filter is run first. Then if there is a filter for this post type, that is run.
105
- */
106
- //general filter for all posts
107
- $hasaccess = apply_filters("pmpro_has_membership_access_filter", $hasaccess, $mypost, $myuser, $post_membership_levels);
108
- //filter for this post type
109
- if(has_filter("pmpro_has_membership_access_filter_" . $mypost->post_type))
110
- $hasaccess = apply_filters("pmpro_has_membership_access_filter_" . $mypost->post_type, $hasaccess, $mypost, $myuser, $post_membership_levels);
111
-
112
- //return
113
- if($return_membership_levels)
114
- return array($hasaccess, $post_membership_levels_ids, $post_membership_levels_names);
115
- else
116
- return $hasaccess;
117
- }
118
-
119
- function pmpro_search_filter($query)
120
- {
121
- global $current_user, $wpdb, $pmpro_pages;
122
-
123
- //hide pmpro pages from search results
124
- if(!$query->is_admin && $query->is_search && empty($query->query['post_parent']))
125
- {
126
- if(empty($query->query_vars['post_parent'])) //avoiding post_parent queries for now
127
- $query->set('post__not_in', $pmpro_pages );
128
-
129
- $query->set('post__not_in', $pmpro_pages ); // id of page or post
130
- }
131
-
132
- //hide member pages from non-members (make sure they aren't hidden from members)
133
- if(!$query->is_admin &&
134
- !$query->is_singular &&
135
- empty($query->query['post_parent']) &&
136
- (
137
- empty($query->query_vars['post_type']) ||
138
- in_array($query->query_vars['post_type'], apply_filters('pmpro_search_filter_post_types', array("page", "post")))
139
- )
140
- )
141
- {
142
- //get page ids that are in my levels
143
- $levels = pmpro_getMembershipLevelsForUser($current_user->ID);
144
- $my_pages = array();
145
-
146
- if($levels) {
147
- foreach($levels as $key => $level) {
148
- //get restricted posts for level
149
- $sql = "SELECT page_id FROM $wpdb->pmpro_memberships_pages WHERE membership_id=" . $current_user->membership_level->ID;
150
- $member_pages = $wpdb->get_col($sql);
151
- $my_pages = array_unique(array_merge($my_pages, $member_pages));
152
- }
153
- }
154
-
155
- //get hidden page ids
156
- if(!empty($my_pages))
157
- $sql = "SELECT page_id FROM $wpdb->pmpro_memberships_pages WHERE page_id NOT IN(" . implode(',', $my_pages) . ")";
158
- else
159
- $sql = "SELECT page_id FROM $wpdb->pmpro_memberships_pages";
160
- $hidden_page_ids = array_values(array_unique($wpdb->get_col($sql)));
161
-
162
- if($hidden_page_ids)
163
- {
164
- if(empty($query->query_vars['post_parent'])) //avoiding post_parent queries for now
165
- $query->set('post__not_in', $hidden_page_ids);
166
- }
167
-
168
- //get categories that are filtered by level, but not my level
169
- global $pmpro_my_cats;
170
- $pmpro_my_cats = array();
171
-
172
- if($levels) {
173
- foreach($levels as $key => $level) {
174
- $member_cats = pmpro_getMembershipCategories($level->id);
175
- $pmpro_my_cats = array_unique(array_merge($pmpro_my_cats, $member_cats));
176
- }
177
- }
178
-
179
- //get hidden cats
180
- if(!empty($pmpro_my_cats))
181
- $sql = "SELECT category_id FROM $wpdb->pmpro_memberships_categories WHERE category_id NOT IN(" . implode(',', $pmpro_my_cats) . ")";
182
- else
183
- $sql = "SELECT category_id FROM $wpdb->pmpro_memberships_categories";
184
-
185
- $hidden_cat_ids = array_values(array_unique($wpdb->get_col($sql)));
186
-
187
- //make this work
188
- if($hidden_cat_ids)
189
- {
190
- $query->set('category__not_in', $hidden_cat_ids);
191
-
192
- //filter so posts in this member's categories are allowed
193
- add_action('posts_where', 'pmpro_posts_where_unhide_cats');
194
- }
195
- }
196
-
197
- return $query;
198
- }
199
- $filterqueries = pmpro_getOption("filterqueries");
200
- if(!empty($filterqueries))
201
- add_filter( 'pre_get_posts', 'pmpro_search_filter' );
202
-
203
- /*
204
- * Find taxonomy filters and make sure member categories are not hidden from members.
205
- * @since 1.7.15
206
- */
207
- function pmpro_posts_where_unhide_cats($where)
208
- {
209
- global $pmpro_my_cats, $wpdb;
210
-
211
- //if we have member cats, make sure they are allowed in taxonomy queries
212
- if(!empty($where) && !empty($pmpro_my_cats))
213
- {
214
- $pattern = "/$wpdb->posts.ID NOT IN \(\s*SELECT object_id\s*FROM dev_term_relationships\s*WHERE term_taxonomy_id IN \((.*)\)\s*\)/";
215
- $replacement = $wpdb->posts . '.ID NOT IN (
216
- SELECT tr1.object_id
217
- FROM ' . $wpdb->term_relationships . ' tr1
218
- LEFT JOIN ' . $wpdb->term_relationships . ' tr2 ON tr1.object_id = tr2.object_id AND tr2.term_taxonomy_id IN(' . implode($pmpro_my_cats) . ')
219
- WHERE tr1.term_taxonomy_id IN(${1}) AND tr2.term_taxonomy_id IS NULL ) ';
220
- $where = preg_replace($pattern, $replacement, $where);
221
- }
222
-
223
- //remove filter for next query
224
- remove_action('posts_where', 'pmpro_posts_where_unhide_cats');
225
-
226
- return $where;
227
- }
228
-
229
- function pmpro_membership_content_filter($content, $skipcheck = false)
230
- {
231
- global $post, $current_user;
232
-
233
- if(!$skipcheck)
234
- {
235
- $hasaccess = pmpro_has_membership_access(NULL, NULL, true);
236
- if(is_array($hasaccess))
237
- {
238
- //returned an array to give us the membership level values
239
- $post_membership_levels_ids = $hasaccess[1];
240
- $post_membership_levels_names = $hasaccess[2];
241
- $hasaccess = $hasaccess[0];
242
- }
243
- }
244
-
245
- if($hasaccess)
246
- {
247
- //all good, return content
248
- return $content;
249
- }
250
- else
251
- {
252
- //if show excerpts is set, return just the excerpt
253
- if(pmpro_getOption("showexcerpts"))
254
- {
255
- //show excerpt
256
- global $post;
257
- if($post->post_excerpt)
258
- {
259
- //defined exerpt
260
- $content = wpautop($post->post_excerpt);
261
- }
262
- elseif(strpos($content, "<span id=\"more-" . $post->ID . "\"></span>") !== false)
263
- {
264
- //more tag
265
- $pos = strpos($content, "<span id=\"more-" . $post->ID . "\"></span>");
266
- $content = wpautop(substr($content, 0, $pos));
267
- }
268
- elseif(strpos($content, 'class="more-link">') !== false)
269
- {
270
- //more link
271
- $content = preg_replace("/\<a.*class\=\"more\-link\".*\>.*\<\/a\>/", "", $content);
272
- }
273
- else
274
- {
275
- //auto generated excerpt. pulled from wp_trim_excerpt
276
- $content = strip_shortcodes( $content );
277
- $content = str_replace(']]>', ']]&gt;', $content);
278
- $content = strip_tags($content);
279
- $excerpt_length = apply_filters('excerpt_length', 55);
280
- $words = preg_split("/[\n\r\t ]+/", $content, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
281
- if ( count($words) > $excerpt_length ) {
282
- array_pop($words);
283
- $content = implode(' ', $words);
284
- $content = $content . "... ";
285
- } else {
286
- $content = implode(' ', $words) . "... ";
287
- }
288
-
289
- $content = wpautop($content);
290
- }
291
- }
292
- else
293
- {
294
- //else hide everything
295
- $content = "";
296
- }
297
-
298
- if(empty($post_membership_levels_ids))
299
- $post_membership_levels_ids = array();
300
-
301
- if(empty($post_membership_levels_names))
302
- $post_membership_levels_names = array();
303
-
304
- //hide levels which don't allow signups by default
305
- if(!apply_filters("pmpro_membership_content_filter_disallowed_levels", false, $post_membership_levels_ids, $post_membership_levels_names))
306
- {
307
- foreach($post_membership_levels_ids as $key=>$id)
308
- {
309
- //does this level allow registrations?
310
- $level_obj = pmpro_getLevel($id);
311
- if(!$level_obj->allow_signups)
312
- {
313
- unset($post_membership_levels_ids[$key]);
314
- unset($post_membership_levels_names[$key]);
315
- }
316
- }
317
- }
318
-
319
- $pmpro_content_message_pre = '<div class="pmpro_content_message">';
320
- $pmpro_content_message_post = '</div>';
321
-
322
- $sr_search = array("!!levels!!", "!!referrer!!");
323
- $sr_replace = array(pmpro_implodeToEnglish($post_membership_levels_names), $_SERVER['REQUEST_URI']);
324
-
325
- //get the correct message to show at the bottom
326
- if(is_feed())
327
- {
328
- $newcontent = apply_filters("pmpro_rss_text_filter", stripslashes(pmpro_getOption("rsstext")));
329
- $content .= $pmpro_content_message_pre . str_replace($sr_search, $sr_replace, $newcontent) . $pmpro_content_message_post;
330
- }
331
- elseif($current_user->ID)
332
- {
333
- //not a member
334
- $newcontent = apply_filters("pmpro_non_member_text_filter", stripslashes(pmpro_getOption("nonmembertext")));
335
- $content .= $pmpro_content_message_pre . str_replace($sr_search, $sr_replace, $newcontent) . $pmpro_content_message_post;
336
- }
337
- else
338
- {
339
- //not logged in!
340
- $newcontent = apply_filters("pmpro_not_logged_in_text_filter", stripslashes(pmpro_getOption("notloggedintext")));
341
- $content .= $pmpro_content_message_pre . str_replace($sr_search, $sr_replace, $newcontent) . $pmpro_content_message_post;
342
- }
343
- }
344
-
345
- return $content;
346
- }
347
- add_filter('the_content', 'pmpro_membership_content_filter', 5);
348
- add_filter('the_content_rss', 'pmpro_membership_content_filter', 5);
349
- add_filter('comment_text_rss', 'pmpro_membership_content_filter', 5);
350
-
351
- /*
352
- If the_excerpt is called, we want to disable the_content filters so the PMPro messages aren't added to the content before AND after the ecerpt.
353
- */
354
- function pmpro_membership_excerpt_filter($content, $skipcheck = false)
355
- {
356
- remove_filter('the_content', 'pmpro_membership_content_filter', 5);
357
- $content = pmpro_membership_content_filter($content, $skipcheck);
358
- add_filter('the_content', 'pmpro_membership_content_filter', 5);
359
-
360
- return $content;
361
- }
362
- function pmpro_membership_get_excerpt_filter_start($content, $skipcheck = false)
363
- {
364
- remove_filter('the_content', 'pmpro_membership_content_filter', 5);
365
- return $content;
366
- }
367
- function pmpro_membership_get_excerpt_filter_end($content, $skipcheck = false)
368
- {
369
- add_filter('the_content', 'pmpro_membership_content_filter', 5);
370
- return $content;
371
- }
372
- add_filter('the_excerpt', 'pmpro_membership_excerpt_filter', 15);
373
- add_filter('get_the_excerpt', 'pmpro_membership_get_excerpt_filter_start', 1);
374
- add_filter('get_the_excerpt', 'pmpro_membership_get_excerpt_filter_end', 100);
375
-
376
- function pmpro_comments_filter($comments, $post_id = NULL)
377
- {
378
- global $post, $wpdb, $current_user;
379
- if(!$post_id)
380
- $post_id = $post->ID;
381
-
382
- if(!$comments)
383
- return $comments; //if they are closed anyway, we don't need to check
384
-
385
- global $post, $current_user;
386
-
387
- $hasaccess = pmpro_has_membership_access(NULL, NULL, true);
388
- if(is_array($hasaccess))
389
- {
390
- //returned an array to give us the membership level values
391
- $post_membership_levels_ids = $hasaccess[1];
392
- $post_membership_levels_names = $hasaccess[2];
393
- $hasaccess = $hasaccess[0];
394
- }
395
-
396
- if($hasaccess)
397
- {
398
- //all good, return content
399
- return $comments;
400
- }
401
- else
402
- {
403
- if(!$post_membership_levels_ids)
404
- $post_membership_levels_ids = array();
405
-
406
- if(!$post_membership_levels_names)
407
- $post_membership_levels_names = array();
408
-
409
- //get the correct message
410
- if(is_feed())
411
- {
412
- if(is_array($comments))
413
- return array();
414
- else
415
- return false;
416
- }
417
- elseif($current_user->ID)
418
- {
419
- //not a member
420
- if(is_array($comments))
421
- return array();
422
- else
423
- return false;
424
- }
425
- else
426
- {
427
- //not logged in!
428
- if(is_array($comments))
429
- return array();
430
- else
431
- return false;
432
- }
433
- }
434
-
435
- return $comments;
436
- }
437
- add_filter("comments_array", "pmpro_comments_filter");
438
- add_filter("comments_open", "pmpro_comments_filter");
439
-
440
- //keep non-members from getting to certain pages (attachments, etc)
441
- function pmpro_hide_pages_redirect()
442
- {
443
- global $post;
444
-
445
- if(!is_admin() && !empty($post->ID))
446
- {
447
- if($post->post_type == "attachment")
448
- {
449
- //check if the user has access to the parent
450
- if(!pmpro_has_membership_access($post->ID))
451
- {
452
- wp_redirect(pmpro_url("levels"));
453
- exit;
454
- }
455
- }
456
- }
457
- }
458
- add_action('wp', 'pmpro_hide_pages_redirect');
1
+ <?php
2
+ /*
3
+ Functions to detect member content and protect it.
4
+ */
5
+ function pmpro_has_membership_access($post_id = NULL, $user_id = NULL, $return_membership_levels = false)
6
+ {
7
+ global $post, $wpdb, $current_user;
8
+ //use globals if no values supplied
9
+ if(!$post_id && !empty($post))
10
+ $post_id = $post->ID;
11
+ if(!$user_id)
12
+ $user_id = $current_user->ID;
13
+
14
+ //no post, return true (changed from false in version 1.7.2)
15
+ if(!$post_id)
16
+ return true;
17
+
18
+ //if no post or current_user object, set them up
19
+ if(!empty($post->ID) && $post_id == $post->ID)
20
+ $mypost = $post;
21
+ else
22
+ $mypost = get_post($post_id);
23
+
24
+ if($user_id == $current_user->ID)
25
+ $myuser = $current_user;
26
+ else
27
+ $myuser = get_userdata($user_id);
28
+
29
+ //for these post types, we want to check the parent
30
+ if($mypost->post_type == "attachment" || $mypost->post_type == "revision")
31
+ {
32
+ $mypost = get_post($mypost->post_parent);
33
+ }
34
+
35
+ // Allow plugins and themes to find the protected post
36
+ $mypost = apply_filters( 'pmpro_membership_access_post', $mypost, $myuser );
37
+
38
+ if($mypost->post_type == "post")
39
+ {
40
+ $post_categories = wp_get_post_categories($mypost->ID);
41
+
42
+ if(!$post_categories)
43
+ {
44
+ //just check for entries in the memberships_pages table
45
+ $sqlQuery = "SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . $mypost->ID . "'";
46
+ }
47
+ else
48
+ {
49
+ //are any of the post categories associated with membership levels? also check the memberships_pages table
50
+ $sqlQuery = "(SELECT m.id, m.name FROM $wpdb->pmpro_memberships_categories mc LEFT JOIN $wpdb->pmpro_membership_levels m ON mc.membership_id = m.id WHERE mc.category_id IN(" . implode(",", $post_categories) . ") AND m.id IS NOT NULL) UNION (SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . $mypost->ID . "')";
51
+ }
52
+ }
53
+ else
54
+ {
55
+ //are any membership levels associated with this page?
56
+ $sqlQuery = "SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . $mypost->ID . "'";
57
+ }
58
+
59
+
60
+ $post_membership_levels = $wpdb->get_results($sqlQuery);
61
+
62
+ $post_membership_levels_ids = array();
63
+ $post_membership_levels_names = array();
64
+
65
+ if(!$post_membership_levels)
66
+ {
67
+ $hasaccess = true;
68
+ }
69
+ else
70
+ {
71
+ //we need to see if the user has access
72
+ foreach($post_membership_levels as $level)
73
+ {
74
+ $post_membership_levels_ids[] = $level->id;
75
+ $post_membership_levels_names[] = $level->name;
76
+ }
77
+
78
+ //levels found. check if this is in a feed or if the current user is in at least one of those membership levels
79
+ if(is_feed())
80
+ {
81
+ //always block restricted feeds
82
+ $hasaccess = false;
83
+ }
84
+ elseif(!empty($myuser->ID))
85
+ {
86
+ $myuser->membership_level = pmpro_getMembershipLevelForUser($myuser->ID);
87
+ if(!empty($myuser->membership_level->ID) && in_array($myuser->membership_level->ID, $post_membership_levels_ids))
88
+ {
89
+ //the users membership id is one that will grant access
90
+ $hasaccess = true;
91
+ }
92
+ else
93
+ {
94
+ //user isn't a member of a level with access
95
+ $hasaccess = false;
96
+ }
97
+ }
98
+ else
99
+ {
100
+ //user is not logged in and this content requires membership
101
+ $hasaccess = false;
102
+ }
103
+ }
104
+
105
+ /*
106
+ Filters
107
+ The generic filter is run first. Then if there is a filter for this post type, that is run.
108
+ */
109
+ //general filter for all posts
110
+ $hasaccess = apply_filters("pmpro_has_membership_access_filter", $hasaccess, $mypost, $myuser, $post_membership_levels);
111
+ //filter for this post type
112
+ if(has_filter("pmpro_has_membership_access_filter_" . $mypost->post_type))
113
+ $hasaccess = apply_filters("pmpro_has_membership_access_filter_" . $mypost->post_type, $hasaccess, $mypost, $myuser, $post_membership_levels);
114
+
115
+ //return
116
+ if($return_membership_levels)
117
+ return array($hasaccess, $post_membership_levels_ids, $post_membership_levels_names);
118
+ else
119
+ return $hasaccess;
120
+ }
121
+
122
+ function pmpro_search_filter($query)
123
+ {
124
+ global $current_user, $wpdb, $pmpro_pages;
125
+
126
+ //hide pmpro pages from search results
127
+ if(!$query->is_admin && $query->is_search && empty($query->query['post_parent']))
128
+ {
129
+ if(empty($query->query_vars['post_parent'])) //avoiding post_parent queries for now
130
+ $query->set('post__not_in', $pmpro_pages );
131
+
132
+ $query->set('post__not_in', $pmpro_pages ); // id of page or post
133
+ }
134
+
135
+ //hide member pages from non-members (make sure they aren't hidden from members)
136
+ if(!$query->is_admin &&
137
+ !$query->is_singular &&
138
+ empty($query->query['post_parent']) &&
139
+ (
140
+ empty($query->query_vars['post_type']) ||
141
+ in_array($query->query_vars['post_type'], apply_filters('pmpro_search_filter_post_types', array("page", "post")))
142
+ )
143
+ )
144
+ {
145
+ //get page ids that are in my levels
146
+ $levels = pmpro_getMembershipLevelsForUser($current_user->ID);
147
+ $my_pages = array();
148
+
149
+ if($levels) {
150
+ foreach($levels as $key => $level) {
151
+ //get restricted posts for level
152
+ $sql = "SELECT page_id FROM $wpdb->pmpro_memberships_pages WHERE membership_id=" . $current_user->membership_level->ID;
153
+ $member_pages = $wpdb->get_col($sql);
154
+ $my_pages = array_unique(array_merge($my_pages, $member_pages));
155
+ }
156
+ }
157
+
158
+ //get hidden page ids
159
+ if(!empty($my_pages))
160
+ $sql = "SELECT page_id FROM $wpdb->pmpro_memberships_pages WHERE page_id NOT IN(" . implode(',', $my_pages) . ")";
161
+ else
162
+ $sql = "SELECT page_id FROM $wpdb->pmpro_memberships_pages";
163
+ $hidden_page_ids = array_values(array_unique($wpdb->get_col($sql)));
164
+
165
+ if($hidden_page_ids)
166
+ {
167
+ if(empty($query->query_vars['post_parent'])) //avoiding post_parent queries for now
168
+ $query->set('post__not_in', $hidden_page_ids);
169
+ }
170
+
171
+ //get categories that are filtered by level, but not my level
172
+ global $pmpro_my_cats;
173
+ $pmpro_my_cats = array();
174
+
175
+ if($levels) {
176
+ foreach($levels as $key => $level) {
177
+ $member_cats = pmpro_getMembershipCategories($level->id);
178
+ $pmpro_my_cats = array_unique(array_merge($pmpro_my_cats, $member_cats));
179
+ }
180
+ }
181
+
182
+ //get hidden cats
183
+ if(!empty($pmpro_my_cats))
184
+ $sql = "SELECT category_id FROM $wpdb->pmpro_memberships_categories WHERE category_id NOT IN(" . implode(',', $pmpro_my_cats) . ")";
185
+ else
186
+ $sql = "SELECT category_id FROM $wpdb->pmpro_memberships_categories";
187
+
188
+ $hidden_cat_ids = array_values(array_unique($wpdb->get_col($sql)));
189
+
190
+ //make this work
191
+ if($hidden_cat_ids)
192
+ {
193
+ $query->set('category__not_in', $hidden_cat_ids);
194
+
195
+ //filter so posts in this member's categories are allowed
196
+ add_action('posts_where', 'pmpro_posts_where_unhide_cats');
197
+ }
198
+ }
199
+
200
+ return $query;
201
+ }
202
+ $filterqueries = pmpro_getOption("filterqueries");
203
+ if(!empty($filterqueries))
204
+ add_filter( 'pre_get_posts', 'pmpro_search_filter' );
205
+
206
+ /*
207
+ * Find taxonomy filters and make sure member categories are not hidden from members.
208
+ * @since 1.7.15
209
+ */
210
+ function pmpro_posts_where_unhide_cats($where)
211
+ {
212
+ global $pmpro_my_cats, $wpdb;
213
+
214
+ //if we have member cats, make sure they are allowed in taxonomy queries
215
+ if(!empty($where) && !empty($pmpro_my_cats))
216
+ {
217
+ $pattern = "/$wpdb->posts.ID NOT IN \(\s*SELECT object_id\s*FROM dev_term_relationships\s*WHERE term_taxonomy_id IN \((.*)\)\s*\)/";
218
+ $replacement = $wpdb->posts . '.ID NOT IN (
219
+ SELECT tr1.object_id
220
+ FROM ' . $wpdb->term_relationships . ' tr1
221
+ LEFT JOIN ' . $wpdb->term_relationships . ' tr2 ON tr1.object_id = tr2.object_id AND tr2.term_taxonomy_id IN(' . implode($pmpro_my_cats) . ')
222
+ WHERE tr1.term_taxonomy_id IN(${1}) AND tr2.term_taxonomy_id IS NULL ) ';
223
+ $where = preg_replace($pattern, $replacement, $where);
224
+ }
225
+
226
+ //remove filter for next query
227
+ remove_action('posts_where', 'pmpro_posts_where_unhide_cats');
228
+
229
+ return $where;
230
+ }
231
+
232
+ function pmpro_membership_content_filter($content, $skipcheck = false)
233
+ {
234
+ global $post, $current_user;
235
+
236
+ if(!$skipcheck)
237
+ {
238
+ $hasaccess = pmpro_has_membership_access(NULL, NULL, true);
239
+ if(is_array($hasaccess))
240
+ {
241
+ //returned an array to give us the membership level values
242
+ $post_membership_levels_ids = $hasaccess[1];
243
+ $post_membership_levels_names = $hasaccess[2];
244
+ $hasaccess = $hasaccess[0];
245
+ }
246
+ }
247
+
248
+ if($hasaccess)
249
+ {
250
+ //all good, return content
251
+ return $content;
252
+ }
253
+ else
254
+ {
255
+ //if show excerpts is set, return just the excerpt
256
+ if(pmpro_getOption("showexcerpts"))
257
+ {
258
+ //show excerpt
259
+ global $post;
260
+ if($post->post_excerpt)
261
+ {
262
+ //defined exerpt
263
+ $content = wpautop($post->post_excerpt);
264
+ }
265
+ elseif(strpos($content, "<span id=\"more-" . $post->ID . "\"></span>") !== false)
266
+ {
267
+ //more tag
268
+ $pos = strpos($content, "<span id=\"more-" . $post->ID . "\"></span>");
269
+ $content = wpautop(substr($content, 0, $pos));
270
+ }
271
+ elseif(strpos($content, 'class="more-link">') !== false)
272
+ {
273
+ //more link
274
+ $content = preg_replace("/\<a.*class\=\"more\-link\".*\>.*\<\/a\>/", "", $content);
275
+ }
276
+ else
277
+ {
278
+ //auto generated excerpt. pulled from wp_trim_excerpt
279
+ $content = strip_shortcodes( $content );
280
+ $content = str_replace(']]>', ']]&gt;', $content);
281
+ $content = strip_tags($content);
282
+ $excerpt_length = apply_filters('excerpt_length', 55);
283
+ $words = preg_split("/[\n\r\t ]+/", $content, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
284
+ if ( count($words) > $excerpt_length ) {
285
+ array_pop($words);
286
+ $content = implode(' ', $words);
287
+ $content = $content . "... ";
288
+ } else {
289
+ $content = implode(' ', $words) . "... ";
290
+ }
291
+
292
+ $content = wpautop($content);
293
+ }
294
+ }
295
+ else
296
+ {
297
+ //else hide everything
298
+ $content = "";
299
+ }
300
+
301
+ if(empty($post_membership_levels_ids))
302
+ $post_membership_levels_ids = array();
303
+
304
+ if(empty($post_membership_levels_names))
305
+ $post_membership_levels_names = array();
306
+
307
+ //hide levels which don't allow signups by default
308
+ if(!apply_filters("pmpro_membership_content_filter_disallowed_levels", false, $post_membership_levels_ids, $post_membership_levels_names))
309
+ {
310
+ foreach($post_membership_levels_ids as $key=>$id)
311
+ {
312
+ //does this level allow registrations?
313
+ $level_obj = pmpro_getLevel($id);
314
+ if(!$level_obj->allow_signups)
315
+ {
316
+ unset($post_membership_levels_ids[$key]);
317
+ unset($post_membership_levels_names[$key]);
318
+ }
319
+ }
320
+ }
321
+
322
+ $pmpro_content_message_pre = '<div class="pmpro_content_message">';
323
+ $pmpro_content_message_post = '</div>';
324
+
325
+ $sr_search = array("!!levels!!", "!!referrer!!");
326
+ $sr_replace = array(pmpro_implodeToEnglish($post_membership_levels_names), $_SERVER['REQUEST_URI']);
327
+
328
+ //get the correct message to show at the bottom
329
+ if(is_feed())
330
+ {
331
+ $newcontent = apply_filters("pmpro_rss_text_filter", stripslashes(pmpro_getOption("rsstext")));
332
+ $content .= $pmpro_content_message_pre . str_replace($sr_search, $sr_replace, $newcontent) . $pmpro_content_message_post;
333
+ }
334
+ elseif($current_user->ID)
335
+ {
336
+ //not a member
337
+ $newcontent = apply_filters("pmpro_non_member_text_filter", stripslashes(pmpro_getOption("nonmembertext")));
338
+ $content .= $pmpro_content_message_pre . str_replace($sr_search, $sr_replace, $newcontent) . $pmpro_content_message_post;
339
+ }
340
+ else
341
+ {
342
+ //not logged in!
343
+ $newcontent = apply_filters("pmpro_not_logged_in_text_filter", stripslashes(pmpro_getOption("notloggedintext")));
344
+ $content .= $pmpro_content_message_pre . str_replace($sr_search, $sr_replace, $newcontent) . $pmpro_content_message_post;
345
+ }
346
+ }
347
+
348
+ return $content;
349
+ }
350
+ add_filter('the_content', 'pmpro_membership_content_filter', 5);
351
+ add_filter('the_content_rss', 'pmpro_membership_content_filter', 5);
352
+ add_filter('comment_text_rss', 'pmpro_membership_content_filter', 5);
353
+
354
+ /*
355
+ If the_excerpt is called, we want to disable the_content filters so the PMPro messages aren't added to the content before AND after the ecerpt.
356
+ */
357
+ function pmpro_membership_exce