Easy Digital Downloads - Version 2.3.8

Version Description

Download this release

Release Info

Developer cklosows
Plugin Icon 128x128 Easy Digital Downloads
Version 2.3.8
Comparing to
See all releases

Code changes from version 2.0.1 to 2.3.8

Files changed (133) hide show
  1. assets/css/chosen-sprite@2x.png +0 -0
  2. assets/css/edd-admin.css +91 -14
  3. assets/css/edd-admin.min.css +1 -1
  4. assets/images/chosen-sprite@2x.png +0 -0
  5. assets/images/edd-peeking.png +0 -0
  6. assets/images/screenshots/22-logs.png +0 -0
  7. assets/images/screenshots/22-purchased-downloads.png +0 -0
  8. assets/images/screenshots/22-purchased-downloads2.png +0 -0
  9. assets/images/screenshots/22-quantity.png +0 -0
  10. assets/images/screenshots/customer-ui.png +0 -0
  11. assets/images/screenshots/edit-download.png +0 -0
  12. assets/images/screenshots/email-template-21.png +0 -0
  13. assets/js/admin-scripts.js +317 -69
  14. assets/js/admin-scripts.min.js +1 -1
  15. assets/js/edd-ajax.js +317 -274
  16. assets/js/edd-ajax.min.js +1 -1
  17. assets/js/edd-checkout-global.js +52 -15
  18. assets/js/edd-checkout-global.min.js +1 -1
  19. assets/js/jquery.creditCardValidator.js +0 -10
  20. assets/sample-products-import.xml +3 -3
  21. easy-digital-downloads.php +54 -8
  22. includes/EDD_SL_Plugin_Updater.php +326 -165
  23. includes/actions.php +1 -1
  24. includes/admin/add-ons.php +46 -10
  25. includes/admin/admin-actions.php +1 -1
  26. includes/admin/admin-footer.php +3 -3
  27. includes/admin/admin-notices.php +25 -4
  28. includes/admin/admin-pages.php +32 -23
  29. includes/admin/class-api-keys-table.php +8 -6
  30. includes/admin/class-edd-heartbeat.php +42 -29
  31. includes/admin/class-edd-notices.php +195 -0
  32. includes/admin/customers/class-customer-table.php +302 -0
  33. includes/admin/customers/customer-actions.php +373 -0
  34. includes/admin/customers/customer-functions.php +57 -0
  35. includes/admin/customers/customers.php +531 -0
  36. includes/admin/dashboard-widgets.php +53 -6
  37. includes/admin/discounts/add-discount.php +16 -3
  38. includes/admin/discounts/class-discount-codes-table.php +19 -16
  39. includes/admin/discounts/contextual-help.php +1 -1
  40. includes/admin/discounts/discount-actions.php +107 -32
  41. includes/admin/discounts/discount-codes.php +1 -3
  42. includes/admin/discounts/edit-discount.php +20 -6
  43. includes/admin/downloads/contextual-help.php +9 -3
  44. includes/admin/downloads/dashboard-columns.php +75 -9
  45. includes/admin/downloads/metabox.php +87 -60
  46. includes/admin/export-functions.php +1 -1
  47. includes/admin/payments/actions.php +265 -54
  48. includes/admin/payments/class-payments-table.php +8 -9
  49. includes/admin/payments/contextual-help.php +1 -1
  50. includes/admin/payments/payments-history.php +2 -4
  51. includes/admin/payments/view-order-details.php +313 -239
  52. includes/admin/plugins.php +11 -3
  53. includes/admin/reporting/class-api-requests-logs-list-table.php +7 -11
  54. includes/admin/reporting/class-customer-reports-table.php +64 -42
  55. includes/admin/reporting/class-download-reports-table.php +3 -6
  56. includes/admin/reporting/class-edd-graph.php +6 -6
  57. includes/admin/reporting/class-export-customers.php +12 -10
  58. includes/admin/reporting/class-export-download-history.php +2 -2
  59. includes/admin/reporting/class-export-earnings.php +2 -2
  60. includes/admin/reporting/class-export-payments.php +17 -14
  61. includes/admin/reporting/class-export.php +8 -9
  62. includes/admin/reporting/class-file-downloads-logs-list-table.php +39 -23
  63. includes/admin/reporting/class-gateway-error-logs-list-table.php +3 -4
  64. includes/admin/reporting/class-gateways-reports-table.php +3 -6
  65. includes/admin/reporting/class-sales-logs-list-table.php +18 -18
  66. includes/admin/reporting/contextual-help.php +1 -1
  67. includes/admin/reporting/graphing.php +201 -101
  68. includes/admin/reporting/logs.php +21 -1
  69. includes/admin/reporting/pdf-reports.php +96 -94
  70. includes/admin/reporting/reports.php +83 -68
  71. includes/admin/settings/contextual-help.php +1 -1
  72. includes/admin/settings/display-settings.php +2 -5
  73. includes/admin/settings/register-settings.php +277 -63
  74. includes/admin/settings/settings.php +0 -75
  75. includes/admin/thickbox.php +1 -1
  76. includes/admin/tools.php +136 -24
  77. includes/admin/tracking.php +8 -11
  78. includes/admin/upgrades/upgrade-functions.php +561 -10
  79. includes/admin/upgrades/upgrades.php +23 -7
  80. includes/admin/upload-functions.php +1 -1
  81. includes/admin/welcome.php +108 -49
  82. includes/ajax-functions.php +203 -22
  83. includes/cart/actions.php +2 -2
  84. includes/cart/functions.php +177 -163
  85. includes/cart/template.php +28 -12
  86. includes/checkout/functions.php +109 -37
  87. includes/checkout/template.php +109 -68
  88. includes/class-edd-api.php +239 -148
  89. includes/class-edd-cache-helper.php +49 -11
  90. includes/class-edd-cli.php +652 -0
  91. includes/class-edd-cron.php +1 -1
  92. includes/class-edd-customer.php +638 -0
  93. includes/class-edd-db-customers.php +572 -0
  94. includes/class-edd-db.php +221 -0
  95. includes/class-edd-download.php +803 -0
  96. includes/class-edd-fees.php +77 -12
  97. includes/class-edd-html-elements.php +171 -57
  98. includes/class-edd-license-handler.php +122 -23
  99. includes/class-edd-logging.php +13 -12
  100. includes/class-edd-roles.php +20 -6
  101. includes/class-edd-session.php +96 -21
  102. includes/class-edd-stats.php +19 -22
  103. includes/country-functions.php +752 -29
  104. includes/deprecated-functions.php +196 -2
  105. includes/discount-functions.php +125 -44
  106. includes/download-functions.php +352 -283
  107. includes/emails/actions.php +13 -3
  108. includes/emails/class-edd-email-tags.php +854 -0
  109. includes/emails/class-edd-emails.php +348 -0
  110. includes/emails/email-tags.php +1 -1
  111. includes/emails/functions.php +85 -108
  112. includes/emails/template.php +49 -159
  113. includes/error-tracking.php +4 -4
  114. includes/formatting.php +19 -35
  115. includes/gateways/actions.php +1 -1
  116. includes/gateways/functions.php +15 -13
  117. includes/gateways/manual.php +7 -3
  118. includes/gateways/paypal-standard.php +202 -68
  119. includes/install.php +32 -5
  120. includes/libraries/array2xml.php +4 -0
  121. includes/libraries/browser.php +1024 -1003
  122. includes/libraries/class-recursive-arrayaccess.php +4 -1
  123. includes/libraries/class-wp-session.php +3 -0
  124. includes/libraries/fpdf/edd_pdf.php +3 -0
  125. includes/libraries/fpdf/fpdf.php +4 -1
  126. includes/libraries/wp-session.php +7 -0
  127. includes/login-register.php +4 -6
  128. includes/mime-types.php +1 -1
  129. includes/misc-functions.php +109 -40
  130. includes/payments/actions.php +116 -38
  131. includes/payments/class-payment-stats.php +4 -2
  132. includes/payments/class-payments-query.php +40 -36
  133. includes/payments/functions.php +339 -88
assets/css/chosen-sprite@2x.png ADDED
Binary file
assets/css/edd-admin.css CHANGED
@@ -3,7 +3,7 @@
3
  *
4
  * @package EDD
5
  * @subpackage Admin CSS
6
- * @copyright Copyright (c) 2014, Pippin Williamson
7
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
8
  */
9
 
@@ -15,12 +15,19 @@ a.edd-delete:hover { color: #f00; }
15
 
16
  /* =Add Ons Styles
17
  -------------------------------------------------------------- */
 
 
18
  #edd-add-ons h2 { margin: 0 0 15px; }
19
- #edd-add-ons .edd-extension { float: left; margin: 0 15px 15px 0; background: #f0f0f0; border: 1px solid #ccc; width: 320px; padding: 8px; height: 315px; position: relative; }
 
20
  #edd-add-ons .edd-extension h3 { margin: 0 0 8px; font-size: 13px; }
21
- #edd-add-ons .edd-extension .button-secondary { position: absolute; bottom: 8px; left: 8px; }
22
  #edd-add-ons .edd-browse-all { clear:both; width:100%; }
23
  #edd-add-ons .edd-extension .third-party { display: none; }
 
 
 
 
24
 
25
  /* Discount Code Styles
26
  -------------------------------------------------------------- */
@@ -37,7 +44,6 @@ a.edd-delete:hover { color: #f00; }
37
  background-image: -o-linear-gradient(bottom, #f5f5f5, #fafafa);
38
  background-image: linear-gradient(to top, #f5f5f5, #fafafa);
39
  border-color: #dfdfdf;
40
- //position: relative;
41
  overflow: auto;
42
  margin: 8px 0;
43
  padding: 12px;
@@ -59,6 +65,8 @@ tr.status-refunded td { background: #cecece; border-top-color: #ccc; }
59
  @media handheld, only screen and (max-width: 640px) {
60
  .wp-list-table.downloads th { width: auto!important;}
61
  }
 
 
62
 
63
  /* Metabox Styles
64
  -------------------------------------------------------------- */
@@ -68,6 +76,7 @@ tr.status-refunded td { background: #cecece; border-top-color: #ccc; }
68
  #postbox-container-1 .edd_files_name_label { width: 80px; }
69
  #postbox-container-1 .edd_files_url_label { width: 80px; }
70
  .edd_add_repeatable { display: inline-block; }
 
71
  #downloadinformation .edd_meta_table_wrap table input,
72
  #downloadinformation .edd_meta_table_wrap table select,
73
  #downloadinformation .edd_meta_table_wrap table textarea { margin: 4px 0; width: 100%; }
@@ -82,6 +91,7 @@ textarea#edd-payment-note { width: 100%; height: 4em; margin: 0; }
82
  .edd-price-field { width: 80px; }
83
  .edd_repeatable_upload_wrapper .pricing select, .edd_repeatable_product_wrapper .edd-select { min-width: 100%; }
84
  #edd_product_notes_field { width: 98%; margin: 0; height: 4em; }
 
85
 
86
  /* Payment Details
87
  -------------------------------------------------------------- */
@@ -92,8 +102,8 @@ textarea#edd-payment-note { width: 100%; height: 4em; margin: 0; }
92
  .edd-payment-fees .fee-label { font-weight: normal; color: #666; }
93
  .edd-admin-box .right { float: right; }
94
  .rtl .edd-admin-box .right { float: left; margin-left: 10px; }
95
- #edd-order-totals .inside,
96
- #edd-order-update .inside { margin: 0; padding: 0; }
97
  #edd-order-update input.edd_datepicker { width: 180px; }
98
  #edd-order-update input[type="number"].edd-payment-time-hour,
99
  #edd-order-update input[type="number"].edd-payment-time-min { width: 50px; }
@@ -106,14 +116,16 @@ textarea#edd-payment-note { width: 100%; height: 4em; margin: 0; }
106
  #edd-customer-details .order-data-address input,
107
  #edd-edit-order-form .column input,
108
  #edd-customer-details .order-data-column p.data input { clear: both; display: block; }
 
109
  .edd-order-data input.small-text { margin: 0; }
110
- #edd-order-update span.label { display: inline-block; width: 50px; }
 
111
  .edd-order-update-box .button-primary { margin-right: 0; }
112
  #edd-edit-order-form .column .description { padding-right: 10px; }
113
  #edd-edit-order-form .column,
114
  #edd-purchased-files .row > ul > li,
115
- #edd-purchased-files .inside > ul > li { display: inline-block; position: relative; vertical-align: top; }
116
- #edd-purchased-files li.actions { text-align: right; }
117
  #edd-purchased-files ul li.remove { text-align: right; }
118
  #edd-purchased-files .row { padding: 12px; border-bottom: 1px solid #eee; }
119
  #edd-purchased-files ul { font-size: 0; }
@@ -125,7 +137,8 @@ textarea#edd-payment-note { width: 100%; height: 4em; margin: 0; }
125
  .edd_repeatable_upload_wrapper .pricing select, .edd_repeatable_product_wrapper .edd-select,
126
  #edd_products .edd-select { min-width: 100%; max-width: 200px; }
127
  .edd_repeatable_product_wrapper td { overflow: visible; }
128
- @media screen and ( max-width: 782px ) {
 
129
  .order-data-column input[type="email"] {
130
  padding: 6px 10px;
131
  }
@@ -155,7 +168,7 @@ textarea#edd-payment-note { width: 100%; height: 4em; margin: 0; }
155
  }
156
  #edd-edit-order-form .columns-4 .column, #edd-purchased-files.columns-4 .row > ul > li,
157
  #edd-purchased-files.columns-4 .inside > ul > li {
158
- width: 23%; margin-right: 2%;
159
  }
160
  #edd-edit-order-form .columns-3 .column:nth-child(2n+1),
161
  #edd-edit-order-form .columns-4 .column:nth-child(3n+1),
@@ -177,7 +190,7 @@ textarea#edd-payment-note { width: 100%; height: 4em; margin: 0; }
177
  @media screen and ( max-width: 1284px ) {
178
  #edd-edit-order-form .column strong {
179
  display:block;
180
- }
181
  }
182
 
183
  /** Stats */
@@ -242,14 +255,17 @@ td.edd_order_price { text-align: right; }
242
  /* General styles
243
  -------------------------------------------------------------- */
244
  .edd-select-chosen { width: 300px; }
245
-
246
  .chosen-container-multi .chosen-choices{ -webkit-border-radius: 3px; border-radius: 3px; border-color: #dfdfdf; background-image:none; }
247
  .chosen-container-multi .chosen-choices input{ margin:2px; height:27px!important; border-color: #dfdfdf; }
248
  .chosen-container .chosen-drop { border-color: #aaa; -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); }
 
 
249
  .chosen-container-active .chosen-choices { -webkit-border-top-left-radius: 3px; border-top-left-radius: 3px; -webkit-border-top-right-radius: 3px; border-top-right-radius: 3px; -webkit-border-bottom-left-radius: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; border-color: #aaa; -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); }
 
250
  .download_page_edd-tools .tablenav .actions { overflow: visible; }
251
  .edd_user_search_wrap { position: relative; overflow: visible; }
252
  .edd_user_search_results { position: absolute; left: 0; top: 27px; }
 
253
  .edd_user_search_results ul { padding: 10px 10px 4px; margin: 0; background: #f0f0f0; border: 1px solid #DFDFDF; width: 300px; max-height: 200px; overflow-y: scroll; }
254
 
255
  /* Global Graph Styles
@@ -259,4 +275,65 @@ td.edd_order_price { text-align: right; }
259
 
260
  /* API Table Styles
261
  -------------------------------------------------------------- */
262
- .download_page_edd-tools .apikeys .column-user { width: 192px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  *
4
  * @package EDD
5
  * @subpackage Admin CSS
6
+ * @copyright Copyright (c) 2015, Pippin Williamson
7
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
8
  */
9
 
15
 
16
  /* =Add Ons Styles
17
  -------------------------------------------------------------- */
18
+ .edd-tab-span { float: right; bottom: 15px; position: relative; }
19
+ .edd-add-ons-footer { padding-top: 10px; }
20
  #edd-add-ons h2 { margin: 0 0 15px; }
21
+ #edd-add-ons h2 .button-primary { position: absolute; }
22
+ #edd-add-ons .edd-extension { float: left; margin: 0 15px 15px 0; background: #fff; border: 1px solid #ccc; width: 320px; padding: 14px; height: 315px; position: relative; }
23
  #edd-add-ons .edd-extension h3 { margin: 0 0 8px; font-size: 13px; }
24
+ #edd-add-ons .edd-extension .button-secondary { position: absolute; bottom: 14px; left: 14px; }
25
  #edd-add-ons .edd-browse-all { clear:both; width:100%; }
26
  #edd-add-ons .edd-extension .third-party { display: none; }
27
+ #edd-add-ons .edd-starter-package { border-color: #62a9d7; background-color: #85c0e5; color: #fff; }
28
+ #edd-add-ons .edd-starter-package h3 { color: #fff; }
29
+ #edd-add-ons .edd-extension .wp-post-image { width: 100%; height: auto; }
30
+
31
 
32
  /* Discount Code Styles
33
  -------------------------------------------------------------- */
44
  background-image: -o-linear-gradient(bottom, #f5f5f5, #fafafa);
45
  background-image: linear-gradient(to top, #f5f5f5, #fafafa);
46
  border-color: #dfdfdf;
 
47
  overflow: auto;
48
  margin: 8px 0;
49
  padding: 12px;
65
  @media handheld, only screen and (max-width: 640px) {
66
  .wp-list-table.downloads th { width: auto!important;}
67
  }
68
+ .download_page_edd-payment-history .ui-dialog .ui-dialog-titlebar-close span { margin-left: -8px; margin-top: -8px; }
69
+ #edd-download-link-textarea { width: 100%; }
70
 
71
  /* Metabox Styles
72
  -------------------------------------------------------------- */
76
  #postbox-container-1 .edd_files_name_label { width: 80px; }
77
  #postbox-container-1 .edd_files_url_label { width: 80px; }
78
  .edd_add_repeatable { display: inline-block; }
79
+ .edd_repeatable_row td { vertical-align: middle }
80
  #downloadinformation .edd_meta_table_wrap table input,
81
  #downloadinformation .edd_meta_table_wrap table select,
82
  #downloadinformation .edd_meta_table_wrap table textarea { margin: 4px 0; width: 100%; }
91
  .edd-price-field { width: 80px; }
92
  .edd_repeatable_upload_wrapper .pricing select, .edd_repeatable_product_wrapper .edd-select { min-width: 100%; }
93
  #edd_product_notes_field { width: 98%; margin: 0; height: 4em; }
94
+ .edd_repeatable_default_wrapper { text-align: center; width: 25px; }
95
 
96
  /* Payment Details
97
  -------------------------------------------------------------- */
102
  .edd-payment-fees .fee-label { font-weight: normal; color: #666; }
103
  .edd-admin-box .right { float: right; }
104
  .rtl .edd-admin-box .right { float: left; margin-left: 10px; }
105
+ #edd-order-update .inside,
106
+ #edd-order-details .inside { margin: 0; padding: 0; }
107
  #edd-order-update input.edd_datepicker { width: 180px; }
108
  #edd-order-update input[type="number"].edd-payment-time-hour,
109
  #edd-order-update input[type="number"].edd-payment-time-min { width: 50px; }
116
  #edd-customer-details .order-data-address input,
117
  #edd-edit-order-form .column input,
118
  #edd-customer-details .order-data-column p.data input { clear: both; display: block; }
119
+ #edd-customer-details .actions { float: right; }
120
  .edd-order-data input.small-text { margin: 0; }
121
+ .edd-order-data input.med-text { margin: 0; width: 100px; }
122
+ #edd-order-update span.label { display: inline; width: 50px; }
123
  .edd-order-update-box .button-primary { margin-right: 0; }
124
  #edd-edit-order-form .column .description { padding-right: 10px; }
125
  #edd-edit-order-form .column,
126
  #edd-purchased-files .row > ul > li,
127
+ #edd-purchased-files .inside > ul > li { display: inline-block; position: relative; vertical-align: bottom; margin-right: 5%; line-height:30px; }
128
+ #edd-purchased-files li.actions { text-align: right; min-width: 200px; }
129
  #edd-purchased-files ul li.remove { text-align: right; }
130
  #edd-purchased-files .row { padding: 12px; border-bottom: 1px solid #eee; }
131
  #edd-purchased-files ul { font-size: 0; }
137
  .edd_repeatable_upload_wrapper .pricing select, .edd_repeatable_product_wrapper .edd-select,
138
  #edd_products .edd-select { min-width: 100%; max-width: 200px; }
139
  .edd_repeatable_product_wrapper td { overflow: visible; }
140
+
141
+ @media screen and ( max-width: 782px ) {
142
  .order-data-column input[type="email"] {
143
  padding: 6px 10px;
144
  }
168
  }
169
  #edd-edit-order-form .columns-4 .column, #edd-purchased-files.columns-4 .row > ul > li,
170
  #edd-purchased-files.columns-4 .inside > ul > li {
171
+ width: 22%; margin-right: 2%;
172
  }
173
  #edd-edit-order-form .columns-3 .column:nth-child(2n+1),
174
  #edd-edit-order-form .columns-4 .column:nth-child(3n+1),
190
  @media screen and ( max-width: 1284px ) {
191
  #edd-edit-order-form .column strong {
192
  display:block;
193
+ }
194
  }
195
 
196
  /** Stats */
255
  /* General styles
256
  -------------------------------------------------------------- */
257
  .edd-select-chosen { width: 300px; }
 
258
  .chosen-container-multi .chosen-choices{ -webkit-border-radius: 3px; border-radius: 3px; border-color: #dfdfdf; background-image:none; }
259
  .chosen-container-multi .chosen-choices input{ margin:2px; height:27px!important; border-color: #dfdfdf; }
260
  .chosen-container .chosen-drop { border-color: #aaa; -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); }
261
+ .chosen-container .search-field { float: none!important; }
262
+ .chosen-container .search-field input { width: 90%!important; }
263
  .chosen-container-active .chosen-choices { -webkit-border-top-left-radius: 3px; border-top-left-radius: 3px; -webkit-border-top-right-radius: 3px; border-top-right-radius: 3px; -webkit-border-bottom-left-radius: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; border-color: #aaa; -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); }
264
+
265
  .download_page_edd-tools .tablenav .actions { overflow: visible; }
266
  .edd_user_search_wrap { position: relative; overflow: visible; }
267
  .edd_user_search_results { position: absolute; left: 0; top: 27px; }
268
+ .edd_user_search_results a.edd-ajax-user-cancel { position: absolute; right: 6px; top: 2px; }
269
  .edd_user_search_results ul { padding: 10px 10px 4px; margin: 0; background: #f0f0f0; border: 1px solid #DFDFDF; width: 300px; max-height: 200px; overflow-y: scroll; }
270
 
271
  /* Global Graph Styles
275
 
276
  /* API Table Styles
277
  -------------------------------------------------------------- */
278
+ .download_page_edd-tools .apikeys .column-user { width: 192px; }
279
+
280
+ /* Customer Styles
281
+ -------------------------------------------------------------- */
282
+ #customer-tab-wrapper { margin-left: -1px; z-index: 1; text-align: center; display: inline-block; }
283
+ #customer-tab-wrapper-list li { background-color: #fff; width: 32px; height: 32px; }
284
+ #customer-tab-wrapper-list .inactive { background-color: #fff; color: #eee; border-left: 1px solid #e5e5e5; }
285
+ #customer-tab-wrapper-list .active { border-width: 1px 1px 1px 0; border-style: solid; border-color: #e5e5e5; }
286
+ #customer-tab-wrapper-list :not(:last-child) { margin-bottom: 3px; }
287
+ #customer-tab-wrapper-list .dashicons { font-size: 24px; line-height: 32px; }
288
+ #edd-customer-card-wrapper .left { float: left; }
289
+ #edd-customer-card-wrapper .right { float: right; }
290
+ #edd-customer-card-wrapper input { font-weight: normal; }
291
+ #edd-customer-card-wrapper {
292
+ display: inline-block;
293
+ margin-left: -1px;
294
+ z-index: 2;
295
+ width: 700px;
296
+ background-color: #FFF;
297
+ min-height: 200px;
298
+ border: 1px solid #e5e5e5;
299
+ webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.04);
300
+ box-shadow: 0 1px 1px rgba(0,0,0,0.04);
301
+ }
302
+ #edd-customer-card-wrapper .customer-section { border-bottom: 1px solid #eee; margin-bottom: 10px; }
303
+ #edd-customer-card-wrapper .customer-section table { margin-bottom: 20px; }
304
+ #edd-customer-card-wrapper > div { padding: 0px 20px; }
305
+ #edd-customer-card-wrapper > div:first-child { padding-top: 20px; }
306
+ #edd-customer-card-wrapper > div:last-child { padding-bottom: 20px; border: none; }
307
+ #edd-customer-card-wrapper .avatar-wrap { padding-right: 10px; text-align: center; }
308
+ #edd-customer-card-wrapper .customer-id { font-size: 24px; font-weight: 600; }
309
+ #edd-customer-card-wrapper .customer-main-wrapper input { width: 200px; }
310
+ #edd-customer-card-wrapper .customer-address-wrapper { max-width: 33%; margin-right: 25px; width: 202px; }
311
+ #edd-customer-card-wrapper .customer-address-wrapper select { width: 200px;}
312
+ #edd-customer-card-wrapper .customer-info { margin-top: 5px; min-height: 185px; margin-bottom: 10px; }
313
+ #edd-customer-card-wrapper .info-wrapper { min-height: 125px; }
314
+ #edd-customer-card-wrapper a.delete { text-decoration: none; color: #ff0000; margin-right: 5px; }
315
+ .customer-info .customer-name { font-size: 24px; font-weight: 600; }
316
+ .customer-edit-link a, .disconnect-user a { font-size: 12px; font-weight: normal; text-decoration: none; }
317
+ #customer-edit-actions { text-align: center; margin-bottom: 20px; line-height: 28px; }
318
+ #customer-edit-actions .button-secondary { margin-right: 10px; }
319
+ #edd-customer-card-wrapper .info-item { line-height: 16px; display: block; padding-bottom: 5px; }
320
+ #edd-customer-card-wrapper .edit-item { display: none; }
321
+ #edd-customer-card-wrapper .edd_user_search_results { left: 1px; top: 16px;}
322
+ #edd-customer-card-wrapper .edd_user_search_results ul { width: 200px }
323
+ #customer-stats-wrapper { margin: 0 auto; text-align: center; min-height: 30px; }
324
+ #customer-stats-wrapper li { width: 50%; float: left; line-height: 22px; font-size: 14px; }
325
+ #customer-stats-wrapper a { text-decoration: none; }
326
+ #customer-stats-wrapper .dashicons { color: #888; }
327
+ #customer-tables-wrapper table { width: 100%; text-align: center; }
328
+ #customer-tables-wrapper th { text-align: center; }
329
+ #customer-tables-wrapper .downloads tr > th:first-child, #customer-tables-wrapper .downloads tr > td:first-child { text-align: left; }
330
+ #customer-tables-wrapper .downloads tr > td:only-child { text-align: center; }
331
+ #customer-notes-wrapper { min-height: 50px; }
332
+ .customer-notes-header span, .customer-notes-header img { font-weight: 600; line-height: 30px; vertical-align: middle; }
333
+ .customer-note-input { width: 100%; margin-bottom: 5px; }
334
+ #edd-customer-notes div:nth-of-type(even) { background-color: #fcfcfc; }
335
+ .customer-note-wrapper { border-bottom: 1px solid #f9f9f9; min-height: 38px; padding: 7px 0 7px 7px; }
336
+ .customer-note-wrapper span { display: block; }
337
+ .note-content-wrap { padding-top: 7px; }
338
+ .delete-customer { text-align: center; }
339
+
assets/css/edd-admin.min.css CHANGED
@@ -1 +1 @@
1
- .edd-hidden{display:none}.edd-clearfix:after{display:block;visibility:hidden;content:".";text-indent:-9999px;height:0}.edd-wrap a{text-decoration:none}a.edd-delete{color:#a00}a.edd-delete:hover{color:red}#edd-add-ons h2{margin:0 0 15px}#edd-add-ons .edd-extension{float:left;margin:0 15px 15px 0;background:#f0f0f0;border:1px solid #ccc;width:320px;padding:8px;height:315px;position:relative}#edd-add-ons .edd-extension h3{margin:0 0 8px;font-size:13px}#edd-add-ons .edd-extension .button-secondary{position:absolute;bottom:8px;left:8px}#edd-add-ons .edd-browse-all{clear:both;width:100%}#edd-add-ons .edd-extension .third-party{display:none}#edd-products{height:100px;min-width:200px}#edd-add-discount input[type=checkbox],#edd-edit-discount input[type=checkbox]{width:15px}#edd-payment-filters{clear:both;background:#f5f5f5;background-image:-webkit-gradient(linear,left bottom,left top,from(#f5f5f5),to(#fafafa));background-image:-webkit-linear-gradient(bottom,#f5f5f5,#fafafa);background-image:-moz-linear-gradient(bottom,#f5f5f5,#fafafa);background-image:-o-linear-gradient(bottom,#f5f5f5,#fafafa);background-image:linear-gradient(to top,#f5f5f5,#fafafa);border-color:#dfdfdf;//position:relative;overflow:auto;margin:8px 0;padding:12px;border-width:1px;border-style:solid;border-radius:3px;font-size:13px;line-height:2.1em}#edd-payments-filter ul.subsubsub{margin-bottom:8px}#edd-payment-filters p{color:#777}tr.status-refunded td{background:#cecece;border-top-color:#ccc}.wp-list-table.downloads th#ID{width:80px}.wp-list-table.downloads th#details{width:130px}.wp-list-table.downloads th#date{width:140px}.wp-list-table.downloads th#user{width:130px}.edd-mobile-link{line-height:32px;vertical-align:middle}.edd-mobile-link img{max-width:80%;height:auto;float:left}@media handheld,only screen and (max-width:640px){.wp-list-table.downloads th{width:auto!important}}.edd_files_name_label{width:225px;float:left}.edd_files_url_label{width:220px;float:left}#postbox-container-1 .edd_files_name_label,#postbox-container-1 .edd_files_url_label{width:80px}.edd_add_repeatable{display:inline-block}#downloadinformation .edd_meta_table_wrap table input,#downloadinformation .edd_meta_table_wrap table select,#downloadinformation .edd_meta_table_wrap table textarea{margin:4px 0;width:100%}#downloadinformation .edd_meta_table_wrap table .submit input{width:auto}.edd_repeatable_upload_wrapper .edd_repeatable_upload_field_container{position:relative}.edd_upload_file{position:absolute;top:3px;right:7px;padding:2px 8px;display:block;background:#fff}.edd_upload_field{padding-right:8em}.edd_remove_repeatable{margin:8px 0 0;cursor:pointer;width:10px;height:10px;display:inline-block;text-indent:-9999px;overflow:hidden}.edd_remove_repeatable:active,.edd_remove_repeatable:hover{background-position:-10px 0!important}.edd_draghandle{display:block;width:20px;height:20px;background:url(../images/edd-cross-hair.png);cursor:move;margin:4px 0 0}textarea#edd-payment-note{width:100%;height:4em;margin:0}#edd_product_notes_field{width:98%;margin:0;height:4em}.edd-admin-box .label{font-weight:600}.edd-admin-box-inside{margin:0;padding:3px 12px;clear:both;border-bottom:1px solid #eee}.rtl .edd-admin-box-inside{padding:5px 10px 5px 0}.edd-admin-box-inside .strong{font-weight:600}.edd-payment-fees .fee-label{font-weight:400;color:#666}.edd-admin-box .right{float:right}.rtl .edd-admin-box .right{float:left;margin-left:10px}#edd-order-totals .inside,#edd-order-update .inside{margin:0;padding:0}#edd-order-update input.edd_datepicker{width:180px}#edd-order-update input[type=number].edd-payment-time-hour,#edd-order-update input[type=number].edd-payment-time-min{width:50px}.edd-admin-box-inside:last-child{border-bottom:0}#edd-edit-order-form .data-payment-key{word-break:break-all}.edd-order-update-box #major-publishing-actions .button-secondary{margin-right:10px}#edd-purchased-files .edd-select-chosen{width:196px}#edd-customer-details .order-data-address input,#edd-customer-details .order-data-column p.data input,#edd-edit-order-form .column input,#edd-order-address-country-wrap select,#edd-purchased-files ul{clear:both;display:block}.edd-order-data input.small-text{margin:0}#edd-order-update span.label{display:inline-block;width:50px}.edd-order-update-box .button-primary{margin-right:0}#edd-edit-order-form .column .description{padding-right:10px}#edd-edit-order-form .column,#edd-purchased-files .inside>ul>li,#edd-purchased-files .row>ul>li{display:inline-block;position:relative;vertical-align:top}#edd-purchased-files li.actions,#edd-purchased-files ul li.remove{text-align:right}#edd-purchased-files .row{padding:12px;border-bottom:1px solid #eee}#edd-purchased-files ul{font-size:0}#edd-purchased-files ul li{font-size:13px}#edd-order-data .data span{color:#666;font-weight:600}#edd-purchased-files .inside{padding:12px}#edd-order-recalc-total{float:right}.edd-price-field{width:80px}#edd_products .edd-select,.edd_repeatable_product_wrapper .edd-select,.edd_repeatable_upload_wrapper .pricing select{min-width:100%;max-width:200px}.edd_repeatable_product_wrapper td{overflow:visible}@media screen and (max-width:782px){.order-data-column input[type=email]{padding:6px 10px}}@media screen and (min-width:851px){#edd-purchased-files .inside li.actions{text-align:right}}@media screen and (max-width:1024px){#edd-edit-order-form .column{width:49%}}@media screen and (max-width:1280px) and (min-width:1279px){#edd-purchased-files .inside li.actions{width:35%}#edd-edit-order-form .column{width:32%}}@media screen and (min-width:1280px){#edd-edit-order-form .column,#edd-purchased-files.columns-3 .inside>ul>li,#edd-purchased-files.columns-3 .row>ul>li{width:32%;margin-right:3%}#edd-edit-order-form .columns-4 .column,#edd-purchased-files.columns-4 .inside>ul>li,#edd-purchased-files.columns-4 .row>ul>li{width:23%;margin-right:2%}#edd-edit-order-form .column:nth-child(2n+1),#edd-edit-order-form .columns-3 .column:nth-child(2n+1),#edd-edit-order-form .columns-4 .column:nth-child(3n+1){margin-right:0}#edd-purchased-files.columns-4 li.download{width:33%}#edd-purchased-files.columns-3 .inside>ul>li.price,#edd-purchased-files.columns-3 .row>ul>li.price,#edd-purchased-files.columns-4 li.price{width:14%}#edd-purchased-files.columns-4 li.actions{width:25%;margin-top:0;margin-right:0}}@media screen and (max-width:1284px){#edd-edit-order-form .column strong{display:block}}#edd_product_stats .label{width:70px;display:inline-block}#edd_product_stats hr{border-style:solid;border-width:1px;border-color:#ccc #fff #fff #ccc}.edd_dashboard_widget table thead td{border-bottom:1px solid #ececec;color:#777}.edd_dashboard_widget .table_left{float:left;width:45%}.edd_dashboard_widget .table_right{float:right;width:45%}.edd_dashboard_widget .inside{font-size:12px}.edd_dashboard_widget td{padding:3px 0}.edd_dashboard_widget .b{font-size:14px;font-family:Georgia,"Times New Roman","Bitstream Charter",Times,serif;padding-right:6px;width:auto}.edd_dashboard_widget .t{font-size:12px;padding-right:12px;padding-top:6px;color:#777;width:100%}.edd_dashboard_widget .label_heading{margin:0 0 8px 12px;display:block;font-size:12px;font-family:Helvetica,Arial,sans-serif;color:#8f8f8f;font-weight:400;padding-top:10px;border-top:1px solid #ececec}.edd_dashboard_widget .edd_dashboard_widget_subheading{margin:1em 0 0;border-top:1px solid #ececec;padding-top:10px;color:#8f8f8f;font-size:14px}.edd_dashboard_widget .edd_dashboard_widget_subheading+.table{margin:8px 0 0}.edd_dashboard_widget .edd_price_label{background:#00769c;padding:2px 4px;border-radius:3px;color:#fff;margin-right:2px;font-size:10px}.edd_dashboard_widget table{width:100%;margin-left:0;margin-bottom:1em}td.edd_order_label{width:80%}td.edd_order_price{text-align:right}@media handheld,only screen and (max-width:1000px){.edd_dashboard_widget .edd-recent-email{display:none}}#edd-dashboard-widgets-wrap .postbox h3{cursor:default}#edd-date-range-options,#edd-graphs-date-options{float:left}#edd-date-range-options span{float:left;margin-right:6px;height:24px;line-height:24px}#edd_tax_rates{margin:1em 0 0}#edd_tax_rates .edd_tax_country *,#edd_tax_rates .edd_tax_state *{max-width:100%}#edd_tax_rates .edd_tax_country,#edd_tax_rates .edd_tax_state{width:180px}#edd_tax_rates .edd_tax_rate{width:80px}#edd_tax_rates th{padding:15px 10px}.post-type-download .fixed .column-name{width:27%}.post-type-download .fixed .column-description{width:30%}.post-type-download .fixed .column-slug{width:23%}.post-type-download .fixed .column-posts{text-align:left;width:17%}#system-info-textarea{width:800px;height:400px;font-family:Menlo,Monaco,monospace;background:0 0;white-space:pre;overflow:auto;display:block}#TB_window #edd-add-download:active,#TB_window #edd-add-download:focus,#TB_window #edd-add-download:hover{color:#fff}.edd-select-chosen{width:300px}.chosen-container-multi .chosen-choices{-webkit-border-radius:3px;border-radius:3px;border-color:#dfdfdf;background-image:none}.chosen-container-multi .chosen-choices input{margin:2px;height:27px!important;border-color:#dfdfdf}.chosen-container .chosen-drop{border-color:#aaa;-webkit-box-shadow:1px 1px 2px rgba(0,0,0,.1);box-shadow:1px 1px 2px rgba(0,0,0,.1)}.chosen-container-active .chosen-choices{-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;border-bottom-right-radius:0;border-color:#aaa;-webkit-box-shadow:1px 1px 2px rgba(0,0,0,.1);box-shadow:1px 1px 2px rgba(0,0,0,.1)}.download_page_edd-tools .tablenav .actions{overflow:visible}.edd_user_search_wrap{position:relative;overflow:visible}.edd_user_search_results{position:absolute;left:0;top:27px}.edd_user_search_results ul{padding:10px 10px 4px;margin:0;background:#f0f0f0;border:1px solid #DFDFDF;width:300px;max-height:200px;overflow-y:scroll}.edd-graph .y1Axis{color:#edc240!important}.edd-graph .y2Axis{color:#afd8f8!important}.download_page_edd-tools .apikeys .column-user{width:192px}
1
+ .edd-hidden{display:none}.edd-clearfix:after{display:block;visibility:hidden;content:".";text-indent:-9999px;height:0}.edd-wrap a{text-decoration:none}a.edd-delete{color:#a00}a.edd-delete:hover{color:red}.edd-tab-span{float:right;bottom:15px;position:relative}.edd-add-ons-footer{padding-top:10px}#edd-add-ons h2{margin:0 0 15px}#edd-add-ons h2 .button-primary{position:absolute}#edd-add-ons .edd-extension{float:left;margin:0 15px 15px 0;background:#fff;border:1px solid #ccc;width:320px;padding:14px;height:315px;position:relative}#edd-add-ons .edd-extension h3{margin:0 0 8px;font-size:13px}#edd-add-ons .edd-extension .button-secondary{position:absolute;bottom:14px;left:14px}#edd-add-ons .edd-browse-all{clear:both;width:100%}#edd-add-ons .edd-extension .third-party{display:none}#edd-add-ons .edd-starter-package{border-color:#62a9d7;background-color:#85c0e5;color:#fff}#edd-add-ons .edd-starter-package h3{color:#fff}#edd-add-ons .edd-extension .wp-post-image{width:100%;height:auto}#edd-products{height:100px;min-width:200px}#edd-add-discount input[type=checkbox],#edd-edit-discount input[type=checkbox]{width:15px}#edd-payment-filters{clear:both;background:#f5f5f5;background-image:-webkit-gradient(linear,left bottom,left top,from(#f5f5f5),to(#fafafa));background-image:-webkit-linear-gradient(bottom,#f5f5f5,#fafafa);background-image:-moz-linear-gradient(bottom,#f5f5f5,#fafafa);background-image:-o-linear-gradient(bottom,#f5f5f5,#fafafa);background-image:linear-gradient(to top,#f5f5f5,#fafafa);border-color:#dfdfdf;overflow:auto;margin:8px 0;padding:12px;border-width:1px;border-style:solid;border-radius:3px;font-size:13px;line-height:2.1em}#edd-payments-filter ul.subsubsub{margin-bottom:8px}#edd-payment-filters p{color:#777}tr.status-refunded td{background:#cecece;border-top-color:#ccc}.wp-list-table.downloads th#ID{width:80px}.wp-list-table.downloads th#details{width:130px}.wp-list-table.downloads th#date{width:140px}.wp-list-table.downloads th#user{width:130px}.edd-mobile-link{line-height:32px;vertical-align:middle}.edd-mobile-link img{max-width:80%;height:auto;float:left}@media handheld,only screen and (max-width:640px){.wp-list-table.downloads th{width:auto!important}}.download_page_edd-payment-history .ui-dialog .ui-dialog-titlebar-close span{margin-left:-8px;margin-top:-8px}#edd-download-link-textarea{width:100%}.edd_files_name_label{width:225px;float:left}.edd_files_url_label{width:220px;float:left}#postbox-container-1 .edd_files_name_label,#postbox-container-1 .edd_files_url_label{width:80px}.edd_add_repeatable{display:inline-block}.edd_repeatable_row td{vertical-align:middle}#downloadinformation .edd_meta_table_wrap table input,#downloadinformation .edd_meta_table_wrap table select,#downloadinformation .edd_meta_table_wrap table textarea{margin:4px 0;width:100%}#downloadinformation .edd_meta_table_wrap table .submit input{width:auto}.edd_repeatable_upload_wrapper .edd_repeatable_upload_field_container{position:relative}.edd_upload_file{position:absolute;top:3px;right:7px;padding:2px 8px;display:block;background:#fff}.edd_upload_field{padding-right:8em}.edd_remove_repeatable{margin:8px 0 0;cursor:pointer;width:10px;height:10px;display:inline-block;text-indent:-9999px;overflow:hidden}.edd_remove_repeatable:active,.edd_remove_repeatable:hover{background-position:-10px 0!important}.edd_draghandle{display:block;width:20px;height:20px;background:url(../images/edd-cross-hair.png);cursor:move;margin:4px 0 0}textarea#edd-payment-note{width:100%;height:4em;margin:0}#edd_product_notes_field{width:98%;margin:0;height:4em}.edd_repeatable_default_wrapper{text-align:center;width:25px}.edd-admin-box .label{font-weight:600}.edd-admin-box-inside{margin:0;padding:3px 12px;clear:both;border-bottom:1px solid #eee}.rtl .edd-admin-box-inside{padding:5px 10px 5px 0}.edd-admin-box-inside .strong{font-weight:600}.edd-payment-fees .fee-label{font-weight:400;color:#666}.edd-admin-box .right{float:right}.rtl .edd-admin-box .right{float:left;margin-left:10px}#edd-order-details .inside,#edd-order-update .inside{margin:0;padding:0}#edd-order-update input.edd_datepicker{width:180px}#edd-order-update input[type=number].edd-payment-time-hour,#edd-order-update input[type=number].edd-payment-time-min{width:50px}.edd-admin-box-inside:last-child{border-bottom:0}#edd-edit-order-form .data-payment-key{word-break:break-all}.edd-order-update-box #major-publishing-actions .button-secondary{margin-right:10px}#edd-purchased-files .edd-select-chosen{width:196px}#edd-customer-details .order-data-address input,#edd-customer-details .order-data-column p.data input,#edd-edit-order-form .column input,#edd-order-address-country-wrap select,#edd-purchased-files ul{clear:both;display:block}#edd-customer-details .actions{float:right}.edd-order-data input.small-text{margin:0}.edd-order-data input.med-text{margin:0;width:100px}#edd-order-update span.label{display:inline;width:50px}.edd-order-update-box .button-primary{margin-right:0}#edd-edit-order-form .column .description{padding-right:10px}#edd-edit-order-form .column,#edd-purchased-files .inside>ul>li,#edd-purchased-files .row>ul>li{display:inline-block;position:relative;vertical-align:bottom;margin-right:5%;line-height:30px}#edd-purchased-files li.actions{text-align:right;min-width:200px}#edd-purchased-files ul li.remove{text-align:right}#edd-purchased-files .row{padding:12px;border-bottom:1px solid #eee}#edd-purchased-files ul{font-size:0}#edd-purchased-files ul li{font-size:13px}#edd-order-data .data span{color:#666;font-weight:600}#edd-purchased-files .inside{padding:12px}#edd-order-recalc-total{float:right}.edd-price-field{width:80px}#edd_products .edd-select,.edd_repeatable_product_wrapper .edd-select,.edd_repeatable_upload_wrapper .pricing select{min-width:100%;max-width:200px}.edd_repeatable_product_wrapper td{overflow:visible}@media screen and (max-width:782px){.order-data-column input[type=email]{padding:6px 10px}}@media screen and (min-width:851px){#edd-purchased-files .inside li.actions{text-align:right}}@media screen and (max-width:1024px){#edd-edit-order-form .column{width:49%}}@media screen and (max-width:1280px) and (min-width:1279px){#edd-purchased-files .inside li.actions{width:35%}#edd-edit-order-form .column{width:32%}}@media screen and (min-width:1280px){#edd-edit-order-form .column,#edd-purchased-files.columns-3 .inside>ul>li,#edd-purchased-files.columns-3 .row>ul>li{width:32%;margin-right:3%}#edd-edit-order-form .columns-4 .column,#edd-purchased-files.columns-4 .inside>ul>li,#edd-purchased-files.columns-4 .row>ul>li{width:22%;margin-right:2%}#edd-edit-order-form .column:nth-child(2n+1),#edd-edit-order-form .columns-3 .column:nth-child(2n+1),#edd-edit-order-form .columns-4 .column:nth-child(3n+1){margin-right:0}#edd-purchased-files.columns-4 li.download{width:33%}#edd-purchased-files.columns-3 .inside>ul>li.price,#edd-purchased-files.columns-3 .row>ul>li.price,#edd-purchased-files.columns-4 li.price{width:14%}#edd-purchased-files.columns-4 li.actions{width:25%;margin-top:0;margin-right:0}}@media screen and (max-width:1284px){#edd-edit-order-form .column strong{display:block}}#edd_product_stats .label{width:70px;display:inline-block}#edd_product_stats hr{border-style:solid;border-width:1px;border-color:#ccc #fff #fff #ccc}.edd_dashboard_widget table thead td{border-bottom:1px solid #ececec;color:#777}.edd_dashboard_widget .table_left{float:left;width:45%}.edd_dashboard_widget .table_right{float:right;width:45%}.edd_dashboard_widget .inside{font-size:12px}.edd_dashboard_widget td{padding:3px 0}.edd_dashboard_widget .b{font-size:14px;font-family:Georgia,"Times New Roman","Bitstream Charter",Times,serif;padding-right:6px;width:auto}.edd_dashboard_widget .t{font-size:12px;padding-right:12px;padding-top:6px;color:#777;width:100%}.edd_dashboard_widget .label_heading{margin:0 0 8px 12px;display:block;font-size:12px;font-family:Helvetica,Arial,sans-serif;color:#8f8f8f;font-weight:400;padding-top:10px;border-top:1px solid #ececec}.edd_dashboard_widget .edd_dashboard_widget_subheading{margin:1em 0 0;border-top:1px solid #ececec;padding-top:10px;color:#8f8f8f;font-size:14px}.edd_dashboard_widget .edd_dashboard_widget_subheading+.table{margin:8px 0 0}.edd_dashboard_widget .edd_price_label{background:#00769c;padding:2px 4px;border-radius:3px;color:#fff;margin-right:2px;font-size:10px}.edd_dashboard_widget table{width:100%;margin-left:0;margin-bottom:1em}td.edd_order_label{width:80%}td.edd_order_price{text-align:right}@media handheld,only screen and (max-width:1000px){.edd_dashboard_widget .edd-recent-email{display:none}}#edd-dashboard-widgets-wrap .postbox h3{cursor:default}#edd-date-range-options,#edd-graphs-date-options{float:left}#edd-date-range-options span{float:left;margin-right:6px;height:24px;line-height:24px}#edd_tax_rates{margin:1em 0 0}#edd_tax_rates .edd_tax_country *,#edd_tax_rates .edd_tax_state *{max-width:100%}#edd_tax_rates .edd_tax_country,#edd_tax_rates .edd_tax_state{width:180px}#edd_tax_rates .edd_tax_rate{width:80px}#edd_tax_rates th{padding:15px 10px}.post-type-download .fixed .column-name{width:27%}.post-type-download .fixed .column-description{width:30%}.post-type-download .fixed .column-slug{width:23%}.post-type-download .fixed .column-posts{text-align:left;width:17%}#system-info-textarea{width:800px;height:400px;font-family:Menlo,Monaco,monospace;background:0 0;white-space:pre;overflow:auto;display:block}#TB_window #edd-add-download:active,#TB_window #edd-add-download:focus,#TB_window #edd-add-download:hover{color:#fff}.edd-select-chosen{width:300px}.chosen-container-multi .chosen-choices{-webkit-border-radius:3px;border-radius:3px;border-color:#dfdfdf;background-image:none}.chosen-container-multi .chosen-choices input{margin:2px;height:27px!important;border-color:#dfdfdf}.chosen-container .chosen-drop{border-color:#aaa;-webkit-box-shadow:1px 1px 2px rgba(0,0,0,.1);box-shadow:1px 1px 2px rgba(0,0,0,.1)}.chosen-container .search-field{float:none!important}.chosen-container .search-field input{width:90%!important}.chosen-container-active .chosen-choices{-webkit-border-top-left-radius:3px;border-radius:3px 3px 0 0;-webkit-border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;border-color:#aaa;-webkit-box-shadow:1px 1px 2px rgba(0,0,0,.1);box-shadow:1px 1px 2px rgba(0,0,0,.1)}.download_page_edd-tools .tablenav .actions{overflow:visible}.edd_user_search_wrap{position:relative;overflow:visible}.edd_user_search_results{position:absolute;left:0;top:27px}.edd_user_search_results a.edd-ajax-user-cancel{position:absolute;right:6px;top:2px}.edd_user_search_results ul{padding:10px 10px 4px;margin:0;background:#f0f0f0;border:1px solid #DFDFDF;width:300px;max-height:200px;overflow-y:scroll}.edd-graph .y1Axis{color:#edc240!important}.edd-graph .y2Axis{color:#afd8f8!important}.download_page_edd-tools .apikeys .column-user{width:192px}#customer-tab-wrapper{margin-left:-1px;z-index:1;text-align:center;display:inline-block}#customer-tab-wrapper-list li{background-color:#fff;width:32px;height:32px}#customer-tab-wrapper-list .inactive{background-color:#fff;color:#eee;border-left:1px solid #e5e5e5}#customer-tab-wrapper-list .active{border-width:1px 1px 1px 0;border-style:solid;border-color:#e5e5e5}#customer-tab-wrapper-list :not(:last-child){margin-bottom:3px}#customer-tab-wrapper-list .dashicons{font-size:24px;line-height:32px}#edd-customer-card-wrapper .left{float:left}#edd-customer-card-wrapper .right{float:right}#edd-customer-card-wrapper input{font-weight:400}#edd-customer-card-wrapper{display:inline-block;margin-left:-1px;z-index:2;width:700px;background-color:#FFF;min-height:200px;border:1px solid #e5e5e5;webkit-box-shadow:0 1px 1px rgba(0,0,0,.04);box-shadow:0 1px 1px rgba(0,0,0,.04)}#edd-customer-card-wrapper .customer-section{border-bottom:1px solid #eee;margin-bottom:10px}#edd-customer-card-wrapper .customer-section table{margin-bottom:20px}#edd-customer-card-wrapper>div{padding:0 20px}#edd-customer-card-wrapper>div:first-child{padding-top:20px}#edd-customer-card-wrapper>div:last-child{padding-bottom:20px;border:none}#edd-customer-card-wrapper .avatar-wrap{padding-right:10px;text-align:center}#edd-customer-card-wrapper .customer-id{font-size:24px;font-weight:600}#edd-customer-card-wrapper .customer-main-wrapper input{width:200px}#edd-customer-card-wrapper .customer-address-wrapper{max-width:33%;margin-right:25px;width:202px}#edd-customer-card-wrapper .customer-address-wrapper select{width:200px}#edd-customer-card-wrapper .customer-info{margin-top:5px;min-height:185px;margin-bottom:10px}#edd-customer-card-wrapper .info-wrapper{min-height:125px}#edd-customer-card-wrapper a.delete{text-decoration:none;color:red;margin-right:5px}.customer-info .customer-name{font-size:24px;font-weight:600}.customer-edit-link a,.disconnect-user a{font-size:12px;font-weight:400;text-decoration:none}#customer-edit-actions{text-align:center;margin-bottom:20px;line-height:28px}#customer-edit-actions .button-secondary{margin-right:10px}#edd-customer-card-wrapper .info-item{line-height:16px;display:block;padding-bottom:5px}#edd-customer-card-wrapper .edit-item{display:none}#edd-customer-card-wrapper .edd_user_search_results{left:1px;top:16px}#edd-customer-card-wrapper .edd_user_search_results ul{width:200px}#customer-stats-wrapper{margin:0 auto;text-align:center;min-height:30px}#customer-stats-wrapper li{width:50%;float:left;line-height:22px;font-size:14px}#customer-stats-wrapper a{text-decoration:none}#customer-stats-wrapper .dashicons{color:#888}#customer-tables-wrapper table{width:100%;text-align:center}#customer-tables-wrapper th{text-align:center}#customer-tables-wrapper .downloads tr>td:first-child,#customer-tables-wrapper .downloads tr>th:first-child{text-align:left}#customer-tables-wrapper .downloads tr>td:only-child{text-align:center}#customer-notes-wrapper{min-height:50px}.customer-notes-header img,.customer-notes-header span{font-weight:600;line-height:30px;vertical-align:middle}.customer-note-input{width:100%;margin-bottom:5px}#edd-customer-notes div:nth-of-type(even){background-color:#fcfcfc}.customer-note-wrapper{border-bottom:1px solid #f9f9f9;min-height:38px;padding:7px 0 7px 7px}.customer-note-wrapper span{display:block}.note-content-wrap{padding-top:7px}.delete-customer{text-align:center}
assets/images/chosen-sprite@2x.png ADDED
Binary file
assets/images/edd-peeking.png ADDED
Binary file
assets/images/screenshots/22-logs.png ADDED
Binary file
assets/images/screenshots/22-purchased-downloads.png ADDED
Binary file
assets/images/screenshots/22-purchased-downloads2.png ADDED
Binary file
assets/images/screenshots/22-quantity.png ADDED
Binary file
assets/images/screenshots/customer-ui.png ADDED
Binary file
assets/images/screenshots/edit-download.png CHANGED
Binary file
assets/images/screenshots/email-template-21.png ADDED
Binary file
assets/js/admin-scripts.js CHANGED
@@ -15,6 +15,16 @@ jQuery(document).ready(function ($) {
15
  },
16
  clone_repeatable : function(row) {
17
 
 
 
 
 
 
 
 
 
 
 
18
  clone = row.clone();
19
 
20
  /** manually update any select box values */
@@ -22,19 +32,26 @@ jQuery(document).ready(function ($) {
22
  $( this ).val( row.find( 'select[name="' + $( this ).attr( 'name' ) + '"]' ).val() );
23
  });
24
 
25
- var count = row.parent().find( 'tr' ).length - 1;
26
-
27
  clone.removeClass( 'edd_add_blank' );
28
 
29
- clone.find( 'td input, td select' ).val( '' );
30
- clone.find( 'input, select' ).each(function() {
31
- var name = $( this ).attr( 'name' );
 
32
 
33
- name = name.replace( /\[(\d+)\]/, '[' + parseInt( count ) + ']');
34
 
35
  $( this ).attr( 'name', name ).attr( 'id', name );
36
  });
37
 
 
 
 
 
 
 
 
 
38
  return clone;
39
  },
40
 
@@ -44,30 +61,24 @@ jQuery(document).ready(function ($) {
44
  var button = $( this ),
45
  row = button.parent().parent().prev( 'tr' ),
46
  clone = EDD_Download_Configuration.clone_repeatable(row);
47
- clone.insertAfter( row );
48
  });
49
  },
50
 
51
  move : function() {
52
- /*
53
- * Disabled until we can work out a way to solve the issues raised here: https://github.com/easydigitaldownloads/Easy-Digital-Downloads/issues/1066
54
- if( ! $('.edd_repeatable_table').length )
55
- return;
56
 
57
  $(".edd_repeatable_table tbody").sortable({
58
  handle: '.edd_draghandle', items: '.edd_repeatable_row', opacity: 0.6, cursor: 'move', axis: 'y', update: function() {
59
  var count = 0;
60
  $(this).find( 'tr' ).each(function() {
61
- $(this).find( 'input, select' ).each(function() {
62
- var name = $( this ).attr( 'name' );
63
- name = name.replace( /\[(\d+)\]/, '[' + count + ']');
64
- $( this ).attr( 'name', name ).attr( 'id', name );
65
  });
66
  count++;
67
  });
68
  }
69
  });
70
- */
71
  },
72
 
73
  remove : function() {
@@ -80,7 +91,7 @@ jQuery(document).ready(function ($) {
80
  repeatable = 'tr.edd_repeatable_' + type + 's';
81
 
82
  /** remove from price condition */
83
- $( '.edd_repeatable_condition_field option[value=' + row.index() + ']' ).remove();
84
 
85
  if( count > 1 ) {
86
  $( 'input, select', row ).val( '' );
@@ -91,7 +102,7 @@ jQuery(document).ready(function ($) {
91
  alert( edd_vars.one_price_min );
92
  break;
93
  case 'file' :
94
- alert( edd_vars.one_file_min );
95
  break;
96
  default:
97
  alert( edd_vars.one_field_min );
@@ -100,13 +111,13 @@ jQuery(document).ready(function ($) {
100
  }
101
 
102
  /* re-index after deleting */
103
- $(repeatable).each( function( rowIndex ) {
104
- $(this).find( 'input, select' ).each(function() {
105
- var name = $( this ).attr( 'name' );
106
- name = name.replace( /\[(\d+)\]/, '[' + rowIndex+ ']');
107
- $( this ).attr( 'name', name ).attr( 'id', name );
108
- });
109
- });
110
  });
111
  },
112
 
@@ -191,9 +202,9 @@ jQuery(document).ready(function ($) {
191
  file_frame = wp.media.frames.file_frame = wp.media( {
192
  frame: 'post',
193
  state: 'insert',
194
- title: button.data( 'uploader_title' ),
195
  button: {
196
- text: button.data( 'uploader_button_text' )
197
  },
198
  multiple: $( this ).data( 'multiple' ) == '0' ? false : true // Set to true to allow multiple files to be selected
199
  } );
@@ -255,7 +266,7 @@ jQuery(document).ready(function ($) {
255
  updatePrices: function() {
256
  $( '#edd_price_fields' ).on( 'keyup', '.edd_variable_prices_name', function() {
257
 
258
- var key = $( this ).parents( 'tr' ).index(),
259
  name = $( this ).val(),
260
  field_option = $( '.edd_repeatable_condition_field option[value=' + key + ']' );
261
 
@@ -294,6 +305,7 @@ jQuery(document).ready(function ($) {
294
  this.edit_address();
295
  this.remove_download();
296
  this.add_download();
 
297
  this.recalculate_total();
298
  this.variable_prices_check();
299
  this.add_note();
@@ -331,7 +343,27 @@ jQuery(document).ready(function ($) {
331
  // Remove a download from a purchase
332
  $('#edd-purchased-files').on('click', '.edd-order-remove-download', function() {
333
  if( confirm( edd_vars.delete_payment_download ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  $(this).parent().parent().parent().remove();
 
335
  // Flag the Downloads section as changed
336
  $('#edd-payment-downloads-changed').val(1);
337
  $('.edd-order-payment-recalc-totals').show();
@@ -341,6 +373,22 @@ jQuery(document).ready(function ($) {
341
 
342
  },
343
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
 
345
  add_download : function() {
346
 
@@ -350,20 +398,38 @@ jQuery(document).ready(function ($) {
350
  e.preventDefault();
351
 
352
  var download_id = $('#edd_order_download_select').val();
353
- var download_title = $('.chosen-single span').text();
 
354
  var amount = $('#edd-order-download-amount').val();
355
  var price_id = $('.edd_price_options_select option:selected').val();
356
  var price_name = $('.edd_price_options_select option:selected').text();
357
- var quantity = $('#edd-order-download-quantity').val();
358
 
359
  if( download_id < 1 ) {
360
  return false;
361
  }
362
 
363
  if( ! amount ) {
364
- amount = '0.00';
 
 
 
 
 
 
365
  }
366
 
 
 
 
 
 
 
 
 
 
 
 
 
367
  var formatted_amount = amount + edd_vars.currency_sign;
368
  if ( 'before' === edd_vars.currency_pos ) {
369
  formatted_amount = edd_vars.currency_sign + amount;
@@ -378,12 +444,14 @@ jQuery(document).ready(function ($) {
378
 
379
  clone.find( '.download span' ).html( '<a href="post.php?post=' + download_id + '&action=edit"></a>' );
380
  clone.find( '.download span a' ).text( download_title );
381
- clone.find( '.price' ).text( formatted_amount );
382
- clone.find( '.quantity span' ).text( quantity );
 
383
  clone.find( 'input.edd-payment-details-download-id' ).val( download_id );
384
  clone.find( 'input.edd-payment-details-download-price-id' ).val( price_id );
385
  clone.find( 'input.edd-payment-details-download-amount' ).val( amount );
386
  clone.find( 'input.edd-payment-details-download-quantity' ).val( quantity );
 
387
 
388
  // Replace the name / id attributes
389
  clone.find( 'input' ).each(function() {
@@ -398,7 +466,7 @@ jQuery(document).ready(function ($) {
398
  $('#edd-payment-downloads-changed').val(1);
399
 
400
  $(clone).insertAfter( '#edd-purchased-files div.row:last' );
401
- $('.edd-order-payment-recalc-totals').show();
402
 
403
  });
404
  },
@@ -411,12 +479,7 @@ jQuery(document).ready(function ($) {
411
  var total = 0;
412
  if( $('#edd-purchased-files .row .edd-payment-details-download-amount').length ) {
413
  $('#edd-purchased-files .row .edd-payment-details-download-amount').each(function() {
414
- var quantity = $(this).next().val();
415
- if( quantity ) {
416
- total += ( parseFloat( $(this).val() ) * parseInt( quantity ) );
417
- } else {
418
- total += parseFloat( $(this).val() );
419
- }
420
  });
421
  }
422
  if( $('.edd-payment-fees').length ) {
@@ -553,15 +616,16 @@ jQuery(document).ready(function ($) {
553
  download_id : $this.data('download-id'),
554
  price_id : $this.data('price-id')
555
  };
556
-
557
  $.ajax({
558
  type: "POST",
559
  data: postData,
560
  url: ajaxurl,
561
  success: function (link) {
562
-
563
- alert( edd_vars.copy_download_link_text + "\n\n" + link );
564
-
 
565
  return false;
566
  }
567
  }).fail(function (data) {
@@ -608,7 +672,7 @@ jQuery(document).ready(function ($) {
608
  } else {
609
 
610
  $('#edd-discount-product-conditions').hide();
611
-
612
  }
613
 
614
  });
@@ -857,8 +921,18 @@ jQuery(document).ready(function ($) {
857
 
858
  // Remove tax row
859
  $('body').on('click', '#edd_tax_rates .edd_remove_tax_rate', function() {
860
- if( confirm( edd_vars.delete_tax_rate ) )
861
- $(this).closest('tr').remove();
 
 
 
 
 
 
 
 
 
 
862
  return false;
863
  });
864
 
@@ -931,8 +1005,8 @@ jQuery(document).ready(function ($) {
931
  });
932
 
933
 
934
- // Bulk edit save
935
- $( 'body' ).on( 'click', '#bulk_edit', function() {
936
 
937
  // define the bulk edit row
938
  var $bulk_row = $( '#bulk-edit' );
@@ -958,27 +1032,37 @@ jQuery(document).ready(function ($) {
958
 
959
  });
960
 
961
- // Setup Chosen menus
962
- $('.edd-select-chosen').chosen({
963
- inherit_select_classes: true,
964
- placeholder_text_single: edd_vars.one_option,
965
- placeholder_text_multiple: edd_vars.one_or_more_option,
966
- });
 
 
 
 
 
967
 
968
  // Variables for setting up the typing timer
969
  var typingTimer; // Timer identifier
970
  var doneTypingInterval = 342; // Time in ms, Slow - 521ms, Moderate - 342ms, Fast - 300ms
971
 
972
- // Replace options with search results
973
  $('.edd-select.chosen-container .chosen-search input, .edd-select.chosen-container .search-field input').keyup(function(e) {
974
 
975
  var val = $(this).val(), container = $(this).closest( '.edd-select-chosen' );
976
  var menu_id = container.attr('id').replace( '_chosen', '' );
977
  var lastKey = e.which;
 
 
 
 
 
978
 
979
  // Don't fire if short or is a modifier key (shift, ctrl, apple command key, or arrow keys)
980
  if(
981
- val.length <= 3 ||
982
  (
983
  e.which == 16 ||
984
  e.which == 13 ||
@@ -992,7 +1076,6 @@ jQuery(document).ready(function ($) {
992
  ) {
993
  return;
994
  }
995
-
996
  clearTimeout(typingTimer);
997
  typingTimer = setTimeout(
998
  function(){
@@ -1000,8 +1083,9 @@ jQuery(document).ready(function ($) {
1000
  type: 'GET',
1001
  url: ajaxurl,
1002
  data: {
1003
- action: 'edd_download_search',
1004
  s: val,
 
1005
  },
1006
  dataType: "json",
1007
  beforeSend: function(){
@@ -1010,9 +1094,9 @@ jQuery(document).ready(function ($) {
1010
  success: function( data ) {
1011
 
1012
  // Remove all options but those that are selected
1013
- $('#' + menu_id + ' option:not(:selected)').remove();
1014
  $.each( data, function( key, item ) {
1015
- // Add any option that doesn't already exist
1016
  if( ! $('#' + menu_id + ' option[value="' + item.id + '"]').length ) {
1017
  $('#' + menu_id).prepend( '<option value="' + item.id + '">' + item.name + '</option>' );
1018
  }
@@ -1023,11 +1107,11 @@ jQuery(document).ready(function ($) {
1023
  }
1024
  }).fail(function (response) {
1025
  if ( window.console && window.console.log ) {
1026
- console.log( data );
1027
  }
1028
  }).done(function (response) {
1029
 
1030
- });
1031
  },
1032
  doneTypingInterval
1033
  );
@@ -1061,15 +1145,152 @@ jQuery(document).ready(function ($) {
1061
  };
1062
  EDD_Tools.init();
1063
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1064
  // Ajax user search
1065
  $('.edd-ajax-user-search').keyup(function() {
1066
  var user_search = $(this).val();
 
 
 
 
 
 
1067
  $('.edd-ajax').show();
1068
  data = {
1069
  action: 'edd_search_users',
1070
- user_name: user_search
 
1071
  };
1072
-
1073
  document.body.style.cursor = 'wait';
1074
 
1075
  $.ajax({
@@ -1080,17 +1301,44 @@ jQuery(document).ready(function ($) {
1080
  success: function (search_response) {
1081
 
1082
  $('.edd-ajax').hide();
1083
- $('.edd_user_search_results').html('');
1084
- $(search_response.results).appendTo('.edd_user_search_results');
 
1085
  document.body.style.cursor = 'default';
1086
  }
1087
  });
1088
  });
1089
- $('body').on('click.eddSelectUser', '.edd_user_search_results a', function(e) {
 
1090
  e.preventDefault();
1091
  var login = $(this).data('login');
1092
  $('.edd-ajax-user-search').val(login);
1093
- $('.edd_user_search_results').html('');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1094
  });
1095
 
1096
  });
15
  },
16
  clone_repeatable : function(row) {
17
 
18
+ // Retrieve the highest current key
19
+ var key = highest = 1;
20
+ row.parent().find( 'tr.edd_repeatable_row' ).each(function() {
21
+ var current = $(this).data( 'key' );
22
+ if( parseInt( current ) > highest ) {
23
+ highest = current;
24
+ }
25
+ });
26
+ key = highest += 1;
27
+
28
  clone = row.clone();
29
 
30
  /** manually update any select box values */
32
  $( this ).val( row.find( 'select[name="' + $( this ).attr( 'name' ) + '"]' ).val() );
33
  });
34
 
 
 
35
  clone.removeClass( 'edd_add_blank' );
36
 
37
+ clone.data( 'key', key );
38
+ clone.find( 'td input, td select, textarea' ).val( '' );
39
+ clone.find( 'input, select, textarea' ).each(function() {
40
+ var name = $( this ).attr( 'name' );
41
 
42
+ name = name.replace( /\[(\d+)\]/, '[' + parseInt( key ) + ']');
43
 
44
  $( this ).attr( 'name', name ).attr( 'id', name );
45
  });
46
 
47
+ clone.find( 'span.edd_price_id' ).each(function() {
48
+ $( this ).text( parseInt( key ) );
49
+ });
50
+
51
+ clone.find( '.edd_repeatable_default_input' ).each( function() {
52
+ $( this ).val( parseInt( key ) ).removeAttr('checked');
53
+ })
54
+
55
  return clone;
56
  },
57
 
61
  var button = $( this ),
62
  row = button.parent().parent().prev( 'tr' ),
63
  clone = EDD_Download_Configuration.clone_repeatable(row);
64
+ clone.insertAfter( row ).find('input, textarea, select').filter(':visible').eq(0).focus();
65
  });
66
  },
67
 
68
  move : function() {
 
 
 
 
69
 
70
  $(".edd_repeatable_table tbody").sortable({
71
  handle: '.edd_draghandle', items: '.edd_repeatable_row', opacity: 0.6, cursor: 'move', axis: 'y', update: function() {
72
  var count = 0;
73
  $(this).find( 'tr' ).each(function() {
74
+ $(this).find( 'input.edd_repeatable_index' ).each(function() {
75
+ $( this ).val( count );
 
 
76
  });
77
  count++;
78
  });
79
  }
80
  });
81
+
82
  },
83
 
84
  remove : function() {
91
  repeatable = 'tr.edd_repeatable_' + type + 's';
92
 
93
  /** remove from price condition */
94
+ $( '.edd_repeatable_condition_field option[value=' + row.index() + ']' ).remove();
95
 
96
  if( count > 1 ) {
97
  $( 'input, select', row ).val( '' );
102
  alert( edd_vars.one_price_min );
103
  break;
104
  case 'file' :
105
+ $( 'input, select', row ).val( '' );
106
  break;
107
  default:
108
  alert( edd_vars.one_field_min );
111
  }
112
 
113
  /* re-index after deleting */
114
+ $(repeatable).each( function( rowIndex ) {
115
+ $(this).find( 'input, select' ).each(function() {
116
+ var name = $( this ).attr( 'name' );
117
+ name = name.replace( /\[(\d+)\]/, '[' + rowIndex+ ']');
118
+ $( this ).attr( 'name', name ).attr( 'id', name );
119
+ });
120
+ });
121
  });
122
  },
123
 
202
  file_frame = wp.media.frames.file_frame = wp.media( {
203
  frame: 'post',
204
  state: 'insert',
205
+ title: button.data( 'uploader-title' ),
206
  button: {
207
+ text: button.data( 'uploader-button-text' )
208
  },
209
  multiple: $( this ).data( 'multiple' ) == '0' ? false : true // Set to true to allow multiple files to be selected
210
  } );
266
  updatePrices: function() {
267
  $( '#edd_price_fields' ).on( 'keyup', '.edd_variable_prices_name', function() {
268
 
269
+ var key = $( this ).parents( 'tr' ).data( 'key' ),
270
  name = $( this ).val(),
271
  field_option = $( '.edd_repeatable_condition_field option[value=' + key + ']' );
272
 
305
  this.edit_address();
306
  this.remove_download();
307
  this.add_download();
308
+ this.new_customer();
309
  this.recalculate_total();
310
  this.variable_prices_check();
311
  this.add_note();
343
  // Remove a download from a purchase
344
  $('#edd-purchased-files').on('click', '.edd-order-remove-download', function() {
345
  if( confirm( edd_vars.delete_payment_download ) ) {
346
+ var key = $(this).data('key');
347
+
348
+ var purchase_id = $('.edd-payment-id').val();
349
+ var download_id = $('input[name="edd-payment-details-downloads['+key+'][id]"]').val();
350
+ var price_id = $('input[name="edd-payment-details-downloads['+key+'][price_id]"]').val();
351
+ var quantity = $('input[name="edd-payment-details-downloads['+key+'][quantity]"]').val();
352
+ var amount = $('input[name="edd-payment-details-downloads['+key+'][amount]"]').val();
353
+
354
+ var currently_removed = $('input[name="edd-payment-removed"]').val();
355
+ currently_removed = $.parseJSON(currently_removed);
356
+ if ( currently_removed.length < 1 ) {
357
+ currently_removed = {};
358
+ }
359
+
360
+ var removed_item = [ { 'id': download_id, 'price_id': price_id, 'quantity': quantity, 'amount': amount } ];
361
+ currently_removed[key] = removed_item
362
+
363
+ $('input[name="edd-payment-removed"]').val(JSON.stringify(currently_removed));
364
+
365
  $(this).parent().parent().parent().remove();
366
+
367
  // Flag the Downloads section as changed
368
  $('#edd-payment-downloads-changed').val(1);
369
  $('.edd-order-payment-recalc-totals').show();
373
 
374
  },
375
 
376
+ new_customer : function() {
377
+
378
+ $('#edd-customer-details').on('click', '.edd-payment-new-customer, .edd-payment-new-customer-cancel', function(e) {
379
+ e.preventDefault();
380
+ $('.customer-info').toggle();
381
+ $('.new-customer').toggle();
382
+
383
+ if ($('.new-customer').is(":visible")) {
384
+ $('#edd-new-customer').val(1);
385
+ } else {
386
+ $('#edd-new-customer').val(0);
387
+ }
388
+
389
+ });
390
+
391
+ },
392
 
393
  add_download : function() {
394
 
398
  e.preventDefault();
399
 
400
  var download_id = $('#edd_order_download_select').val();
401
+ var download_title = $('#edd_order_download_select').find(':selected').text();
402
+ var quantity = $('#edd-order-download-quantity').val();
403
  var amount = $('#edd-order-download-amount').val();
404
  var price_id = $('.edd_price_options_select option:selected').val();
405
  var price_name = $('.edd_price_options_select option:selected').text();
 
406
 
407
  if( download_id < 1 ) {
408
  return false;
409
  }
410
 
411
  if( ! amount ) {
412
+ amount = 0;
413
+ }
414
+
415
+ amount = parseFloat( amount );
416
+ if ( isNaN( amount ) ) {
417
+ alert( edd_vars.numeric_item_price );
418
+ return false;
419
  }
420
 
421
+ if ( edd_vars.quantities_enabled === '1' ) {
422
+ if ( !isNaN( parseInt( quantity ) ) ) {
423
+ amount = amount * quantity;
424
+ } else {
425
+ alert( edd_vars.numeric_quantity );
426
+ return false;
427
+ }
428
+ }
429
+
430
+
431
+ amount = amount.toFixed( edd_vars.currency_decimals );
432
+
433
  var formatted_amount = amount + edd_vars.currency_sign;
434
  if ( 'before' === edd_vars.currency_pos ) {
435
  formatted_amount = edd_vars.currency_sign + amount;
444
 
445
  clone.find( '.download span' ).html( '<a href="post.php?post=' + download_id + '&action=edit"></a>' );
446
  clone.find( '.download span a' ).text( download_title );
447
+ clone.find( '.price-text' ).text( formatted_amount );
448
+ clone.find( '.item-quantity' ).text( quantity );
449
+ clone.find( '.item-price' ).text( edd_vars.currency_sign + ( amount / quantity ).toFixed( edd_vars.currency_decimals ) );
450
  clone.find( 'input.edd-payment-details-download-id' ).val( download_id );
451
  clone.find( 'input.edd-payment-details-download-price-id' ).val( price_id );
452
  clone.find( 'input.edd-payment-details-download-amount' ).val( amount );
453
  clone.find( 'input.edd-payment-details-download-quantity' ).val( quantity );
454
+ clone.find( 'input.edd-payment-details-download-has-log').val(0);
455
 
456
  // Replace the name / id attributes
457
  clone.find( 'input' ).each(function() {
466
  $('#edd-payment-downloads-changed').val(1);
467
 
468
  $(clone).insertAfter( '#edd-purchased-files div.row:last' );
469
+ $( '.edd-order-payment-recalc-totals' ).show();
470
 
471
  });
472
  },
479
  var total = 0;
480
  if( $('#edd-purchased-files .row .edd-payment-details-download-amount').length ) {
481
  $('#edd-purchased-files .row .edd-payment-details-download-amount').each(function() {
482
+ total += parseFloat( $(this).val() );
 
 
 
 
 
483
  });
484
  }
485
  if( $('.edd-payment-fees').length ) {
616
  download_id : $this.data('download-id'),
617
  price_id : $this.data('price-id')
618
  };
619
+
620
  $.ajax({
621
  type: "POST",
622
  data: postData,
623
  url: ajaxurl,
624
  success: function (link) {
625
+ $( "#edd-download-link" ).dialog({
626
+ width: 400
627
+ }).html( '<textarea rows="10" cols="40" id="edd-download-link-textarea">' + link + '</textarea>' );
628
+ $( "#edd-download-link-textarea" ).focus().select();
629
  return false;
630
  }
631
  }).fail(function (data) {
672
  } else {
673
 
674
  $('#edd-discount-product-conditions').hide();
675
+
676
  }
677
 
678
  });
921
 
922
  // Remove tax row
923
  $('body').on('click', '#edd_tax_rates .edd_remove_tax_rate', function() {
924
+ if( confirm( edd_vars.delete_tax_rate ) ) {
925
+ var count = $('#edd_tax_rates tr:visible').length;
926
+
927
+ if( count === 2 ) {
928
+ $('#edd_tax_rates select').val('');
929
+ $('#edd_tax_rates input[type="text"]').val('');
930
+ $('#edd_tax_rates input[type="number"]').val('');
931
+ $('#edd_tax_rates input[type="checkbox"]').attr('checked', false);
932
+ } else {
933
+ $(this).closest('tr').remove();
934
+ }
935
+ }
936
  return false;
937
  });
938
 
1005
  });
1006
 
1007
 
1008
+ // Bulk edit save
1009
+ $( 'body' ).on( 'click', '#bulk_edit', function() {
1010
 
1011
  // define the bulk edit row
1012
  var $bulk_row = $( '#bulk-edit' );
1032
 
1033
  });
1034
 
1035
+ // Setup Chosen menus
1036
+ $('.edd-select-chosen').chosen({
1037
+ inherit_select_classes: true,
1038
+ placeholder_text_single: edd_vars.one_option,
1039
+ placeholder_text_multiple: edd_vars.one_or_more_option,
1040
+ });
1041
+
1042
+ // Add placeholders for Chosen input fields
1043
+ $( '.chosen-choices' ).on( 'click', function () {
1044
+ $(this).children('li').children('input').attr( 'placeholder', edd_vars.type_to_search );
1045
+ });
1046
 
1047
  // Variables for setting up the typing timer
1048
  var typingTimer; // Timer identifier
1049
  var doneTypingInterval = 342; // Time in ms, Slow - 521ms, Moderate - 342ms, Fast - 300ms
1050
 
1051
+ // Replace options with search results
1052
  $('.edd-select.chosen-container .chosen-search input, .edd-select.chosen-container .search-field input').keyup(function(e) {
1053
 
1054
  var val = $(this).val(), container = $(this).closest( '.edd-select-chosen' );
1055
  var menu_id = container.attr('id').replace( '_chosen', '' );
1056
  var lastKey = e.which;
1057
+ var search_type = 'edd_download_search';
1058
+
1059
+ if( container.attr( 'id' ).indexOf( "customer" ) >= 0 ) {
1060
+ search_type = 'edd_customer_search';
1061
+ }
1062
 
1063
  // Don't fire if short or is a modifier key (shift, ctrl, apple command key, or arrow keys)
1064
  if(
1065
+ ( val.length <= 3 && 'edd_download_search' == search_type ) ||
1066
  (
1067
  e.which == 16 ||
1068
  e.which == 13 ||
1076
  ) {
1077
  return;
1078
  }
 
1079
  clearTimeout(typingTimer);
1080
  typingTimer = setTimeout(
1081
  function(){
1083
  type: 'GET',
1084
  url: ajaxurl,
1085
  data: {
1086
+ action: search_type,
1087
  s: val,
1088
+ current_id: edd_vars.post_id,
1089
  },
1090
  dataType: "json",
1091
  beforeSend: function(){
1094
  success: function( data ) {
1095
 
1096
  // Remove all options but those that are selected
1097
+ $('#' + menu_id + ' option:not(:selected)').remove();
1098
  $.each( data, function( key, item ) {
1099
+ // Add any option that doesn't already exist
1100
  if( ! $('#' + menu_id + ' option[value="' + item.id + '"]').length ) {
1101
  $('#' + menu_id).prepend( '<option value="' + item.id + '">' + item.name + '</option>' );
1102
  }
1107
  }
1108
  }).fail(function (response) {
1109
  if ( window.console && window.console.log ) {
1110
+ console.log( response );
1111
  }
1112
  }).done(function (response) {
1113
 
1114
+ });
1115
  },
1116
  doneTypingInterval
1117
  );
1145
  };
1146
  EDD_Tools.init();
1147
 
1148
+ /**
1149
+ * Customer management screen JS
1150
+ */
1151
+ var EDD_Customer = {
1152
+
1153
+ init : function() {
1154
+ this.edit_customer();
1155
+ this.user_search();
1156
+ this.remove_user();
1157
+ this.cancel_edit();
1158
+ this.change_country();
1159
+ this.add_note();
1160
+ this.delete_checked();
1161
+ },
1162
+ edit_customer: function() {
1163
+ $( 'body' ).on( 'click', '#edit-customer', function( e ) {
1164
+ e.preventDefault();
1165
+ $( '#edd-customer-card-wrapper .editable' ).hide();
1166
+ $( '#edd-customer-card-wrapper .edit-item' ).fadeIn().css( 'display', 'block' );
1167
+ });
1168
+ },
1169
+ user_search: function() {
1170
+ // Upon selecting a user from the dropdown, we need to update the User ID
1171
+ $('body').on('click.eddSelectUser', '.edd_user_search_results a', function( e ) {
1172
+ e.preventDefault();
1173
+ var user_id = $(this).data('userid');
1174
+ $('input[name="customerinfo[user_id]"]').val(user_id);
1175
+ });
1176
+ },
1177
+ remove_user: function() {
1178
+ $( 'body' ).on( 'click', '#disconnect-customer', function( e ) {
1179
+ e.preventDefault();
1180
+ var customer_id = $('input[name="customerinfo[id]"]').val();
1181
+
1182
+ var postData = {
1183
+ edd_action: 'disconnect-userid',
1184
+ customer_id: customer_id,
1185
+ _wpnonce: $( '#edit-customer-info #_wpnonce' ).val()
1186
+ };
1187
+
1188
+ $.post(ajaxurl, postData, function( response ) {
1189
+
1190
+ window.location.href=window.location.href;
1191
+
1192
+ }, 'json');
1193
+
1194
+ });
1195
+ },
1196
+ cancel_edit: function() {
1197
+ $( 'body' ).on( 'click', '#edd-edit-customer-cancel', function( e ) {
1198
+ e.preventDefault();
1199
+ $( '#edd-customer-card-wrapper .edit-item' ).hide();
1200
+ $( '#edd-customer-card-wrapper .editable' ).show();
1201
+ $( '.edd_user_search_results' ).html('');
1202
+ });
1203
+ },
1204
+ change_country: function() {
1205
+ $('select[name="customerinfo[country]"]').change(function() {
1206
+ var $this = $(this);
1207
+ data = {
1208
+ action: 'edd_get_shop_states',
1209
+ country: $this.val(),
1210
+ field_name: 'customerinfo[state]'
1211
+ };
1212
+ $.post(ajaxurl, data, function (response) {
1213
+ if( 'nostates' == response ) {
1214
+ $(':input[name="customerinfo[state]"]').replaceWith( '<input type="text" name="' + data.field_name + '" value="" class="edd-edit-toggles medium-text"/>' );
1215
+ } else {
1216
+ $(':input[name="customerinfo[state]"]').replaceWith( response );
1217
+ }
1218
+ });
1219
+
1220
+ return false;
1221
+ });
1222
+ },
1223
+ add_note : function() {
1224
+ $( 'body' ).on( 'click', '#add-customer-note', function( e ) {
1225
+ e.preventDefault();
1226
+ var postData = {
1227
+ edd_action : 'add-customer-note',
1228
+ customer_id : $( '#customer-id' ).val(),
1229
+ customer_note : $( '#customer-note' ).val(),
1230
+ add_customer_note_nonce: $( '#add_customer_note_nonce' ).val()
1231
+ };
1232
+
1233
+ if( postData.customer_note ) {
1234
+
1235
+ $.ajax({
1236
+ type: "POST",
1237
+ data: postData,
1238
+ url: ajaxurl,
1239
+ success: function ( response ) {
1240
+ $( '#edd-customer-notes' ).prepend( response );
1241
+ $( '.edd-no-customer-notes' ).hide();
1242
+ $( '#customer-note' ).val( '' );
1243
+ }
1244
+ }).fail( function ( data ) {
1245
+ if ( window.console && window.console.log ) {
1246
+ console.log( data );
1247
+ }
1248
+ });
1249
+
1250
+ } else {
1251
+ var border_color = $( '#customer-note' ).css( 'border-color' );
1252
+ $( '#customer-note' ).css( 'border-color', 'red' );
1253
+ setTimeout( function() {
1254
+ $( '#customer-note' ).css( 'border-color', border_color );
1255
+ }, 500 );
1256
+ }
1257
+ });
1258
+ },
1259
+ delete_checked: function() {
1260
+ $( '#edd-customer-delete-confirm' ).change( function() {
1261
+ var records_input = $('#edd-customer-delete-records');
1262
+ var submit_button = $('#edd-delete-customer');
1263
+
1264
+ if ( $(this).prop('checked') ) {
1265
+ records_input.attr('disabled', false);
1266
+ submit_button.attr('disabled', false);
1267
+ } else {
1268
+ records_input.attr('disabled', true);
1269
+ records_input.prop('checked', false);
1270
+ submit_button.attr('disabled', true);
1271
+ }
1272
+ });
1273
+ }
1274
+
1275
+ };
1276
+ EDD_Customer.init();
1277
+
1278
  // Ajax user search
1279
  $('.edd-ajax-user-search').keyup(function() {
1280
  var user_search = $(this).val();
1281
+ var exclude = '';
1282
+
1283
+ if ( $(this).data('exclude') ) {
1284
+ exclude = $(this).data('exclude');
1285
+ }
1286
+
1287
  $('.edd-ajax').show();
1288
  data = {
1289
  action: 'edd_search_users',
1290
+ user_name: user_search,
1291
+ exclude: exclude
1292
  };
1293
+
1294
  document.body.style.cursor = 'wait';
1295
 
1296
  $.ajax({
1301
  success: function (search_response) {
1302
 
1303
  $('.edd-ajax').hide();
1304
+ $('.edd_user_search_results').removeClass('hidden');
1305
+ $('.edd_user_search_results span').html('');
1306
+ $(search_response.results).appendTo('.edd_user_search_results span');
1307
  document.body.style.cursor = 'default';
1308
  }
1309
  });
1310
  });
1311
+
1312
+ $('body').on('click.eddSelectUser', '.edd_user_search_results span a', function(e) {
1313
  e.preventDefault();
1314
  var login = $(this).data('login');
1315
  $('.edd-ajax-user-search').val(login);
1316
+ $('.edd_user_search_results').addClass('hidden');
1317
+ $('.edd_user_search_results span').html('');
1318
+ });
1319
+
1320
+ $('body').on('click.eddCancelUserSearch', '.edd_user_search_results a.edd-ajax-user-cancel', function(e) {
1321
+ e.preventDefault();
1322
+ $('.edd-ajax-user-search').val('');
1323
+ $('.edd_user_search_results').addClass('hidden');
1324
+ $('.edd_user_search_results span').html('');
1325
+ });
1326
+
1327
+ $.ajax({
1328
+ type: "GET",
1329
+ data: {
1330
+ action: 'edd_load_dashboard_widget'
1331
+ },
1332
+ url: ajaxurl,
1333
+ success: function (response) {
1334
+ $('#edd_dashboard_sales .inside').html( response );
1335
+ }
1336
+ });
1337
+
1338
+ $(document).on('keydown', '.customer-note-input', function(e) {
1339
+ if(e.keyCode == 13 && (e.metaKey || e.ctrlKey)) {
1340
+ $('#add-customer-note').click();
1341
+ }
1342
  });
1343
 
1344
  });
assets/js/admin-scripts.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(e){var t={init:function(){this.add();this.move();this.remove();this.type();this.prices();this.files();this.updatePrices()},clone_repeatable:function(t){clone=t.clone();clone.find("select").each(function(){e(this).val(t.find('select[name="'+e(this).attr("name")+'"]').val())});var n=t.parent().find("tr").length-1;clone.removeClass("edd_add_blank");clone.find("td input, td select").val("");clone.find("input, select").each(function(){var t=e(this).attr("name");t=t.replace(/\[(\d+)\]/,"["+parseInt(n)+"]");e(this).attr("name",t).attr("id",t)});return clone},add:function(){e("body").on("click",".submit .edd_add_repeatable",function(n){n.preventDefault();var r=e(this),i=r.parent().parent().prev("tr"),s=t.clone_repeatable(i);s.insertAfter(i)})},move:function(){},remove:function(){e("body").on("click",".edd_remove_repeatable",function(t){t.preventDefault();var n=e(this).parent().parent("tr"),r=n.parent().find("tr").length-1,i=e(this).data("type"),s="tr.edd_repeatable_"+i+"s";e(".edd_repeatable_condition_field option[value="+n.index()+"]").remove();if(r>1){e("input, select",n).val("");n.fadeOut("fast").remove()}else{switch(i){case"price":alert(edd_vars.one_price_min);break;case"file":alert(edd_vars.one_file_min);break;default:alert(edd_vars.one_field_min);break}}e(s).each(function(t){e(this).find("input, select").each(function(){var n=e(this).attr("name");n=n.replace(/\[(\d+)\]/,"["+t+"]");e(this).attr("name",n).attr("id",n)})})})},type:function(){e("body").on("change","#_edd_product_type",function(t){if("bundle"===e(this).val()){e("#edd_products").show();e("#edd_download_files").hide();e("#edd_download_limit_wrap").hide()}else{e("#edd_products").hide();e("#edd_download_files").show();e("#edd_download_limit_wrap").show()}})},prices:function(){e("body").on("change","#edd_variable_pricing",function(t){e(".edd_pricing_fields,.edd_repeatable_table .pricing").toggle()})},files:function(){if(typeof wp==="undefined"||"1"!==edd_vars.new_media_ui){if(e(".edd_upload_file_button").length>0){window.formfield="";e("body").on("click",".edd_upload_file_button",function(t){t.preventDefault();window.formfield=e(this).parent().prev();window.tbframe_interval=setInterval(function(){jQuery("#TB_iframeContent").contents().find(".savesend .button").val(edd_vars.use_this_file).end().find("#insert-gallery, .wp-post-thumbnail").hide()},2e3);if(edd_vars.post_id!=null){var n="post_id="+edd_vars.post_id+"&"}tb_show(edd_vars.add_new_download,"media-upload.php?"+n+"TB_iframe=true")});window.edd_send_to_editor=window.send_to_editor;window.send_to_editor=function(t){if(window.formfield){imgurl=e("a","<div>"+t+"</div>").attr("href");window.formfield.val(imgurl);window.clearInterval(window.tbframe_interval);tb_remove()}else{window.edd_send_to_editor(t)}window.send_to_editor=window.edd_send_to_editor;window.formfield="";window.imagefield=false}}}else{var n;window.formfield="";e("body").on("click",".edd_upload_file_button",function(r){r.preventDefault();var i=e(this);window.formfield=e(this).closest(".edd_repeatable_upload_wrapper");if(n){n.open();return}n=wp.media.frames.file_frame=wp.media({frame:"post",state:"insert",title:i.data("uploader_title"),button:{text:i.data("uploader_button_text")},multiple:e(this).data("multiple")=="0"?false:true});n.on("menu:render:default",function(e){var t={};e.unset("library-separator");e.unset("gallery");e.unset("featured-image");e.unset("embed");e.set(t)});n.on("insert",function(){var e=n.state().get("selection");e.each(function(e,n){e=e.toJSON();if(0===n){window.formfield.find(".edd_repeatable_attachment_id_field").val(e.id);window.formfield.find(".edd_repeatable_upload_field").val(e.url);window.formfield.find(".edd_repeatable_name_field").val(e.title)}else{var r=window.formfield,i=t.clone_repeatable(r);i.find(".edd_repeatable_attachment_id_field").val(e.id);i.find(".edd_repeatable_upload_field").val(e.url);if(e.title.length>0){i.find(".edd_repeatable_name_field").val(e.title)}else{i.find(".edd_repeatable_name_field").val(e.filename)}i.insertAfter(r)}})});n.open()});var n;window.formfield=""}},updatePrices:function(){e("#edd_price_fields").on("keyup",".edd_variable_prices_name",function(){var t=e(this).parents("tr").index(),n=e(this).val(),r=e(".edd_repeatable_condition_field option[value="+t+"]");if(r.length>0){r.text(n)}else{e(".edd_repeatable_condition_field").append(e("<option></option>").attr("value",t).text(n))}})}};t.init();if(e(".edd_datepicker").length>0){var n="mm/dd/yy";e(".edd_datepicker").datepicker({dateFormat:n})}var r={init:function(){this.edit_address();this.remove_download();this.add_download();this.recalculate_total();this.variable_prices_check();this.add_note();this.remove_note();this.resend_receipt();this.copy_download_link()},edit_address:function(){e('select[name="edd-payment-address[0][country]"]').change(function(){var t=e(this);data={action:"edd_get_shop_states",country:t.val(),field_name:"edd-payment-address[0][state]"};e.post(ajaxurl,data,function(t){if("nostates"==t){e("#edd-order-address-state-wrap select, #edd-order-address-state-wrap input").replaceWith('<input type="text" name="edd-payment-address[0][state]" value="" class="edd-edit-toggles medium-text"/>')}else{e("#edd-order-address-state-wrap select, #edd-order-address-state-wrap input").replaceWith(t)}});return false})},remove_download:function(){e("#edd-purchased-files").on("click",".edd-order-remove-download",function(){if(confirm(edd_vars.delete_payment_download)){e(this).parent().parent().parent().remove();e("#edd-payment-downloads-changed").val(1);e(".edd-order-payment-recalc-totals").show()}return false})},add_download:function(){e("#edd-purchased-files").on("click","#edd-order-add-download",function(t){t.preventDefault();var n=e("#edd_order_download_select").val();var r=e(".chosen-single span").text();var i=e("#edd-order-download-amount").val();var s=e(".edd_price_options_select option:selected").val();var o=e(".edd_price_options_select option:selected").text();var u=e("#edd-order-download-quantity").val();if(n<1){return false}if(!i){i="0.00"}var a=i+edd_vars.currency_sign;if("before"===edd_vars.currency_pos){a=edd_vars.currency_sign+i}if(o){r=r+" - "+o}var f=e("#edd-purchased-files div.row").length;var l=e("#edd-purchased-files div.row:last").clone();l.find(".download span").html('<a href="post.php?post='+n+'&action=edit"></a>');l.find(".download span a").text(r);l.find(".price").text(a);l.find(".quantity span").text(u);l.find("input.edd-payment-details-download-id").val(n);l.find("input.edd-payment-details-download-price-id").val(s);l.find("input.edd-payment-details-download-amount").val(i);l.find("input.edd-payment-details-download-quantity").val(u);l.find("input").each(function(){var t=e(this).attr("name");t=t.replace(/\[(\d+)\]/,"["+parseInt(f)+"]");e(this).attr("name",t).attr("id",t)});e("#edd-payment-downloads-changed").val(1);e(l).insertAfter("#edd-purchased-files div.row:last");e(".edd-order-payment-recalc-totals").show()})},recalculate_total:function(){e("#edd-order-recalc-total").on("click",function(t){t.preventDefault();var n=0;if(e("#edd-purchased-files .row .edd-payment-details-download-amount").length){e("#edd-purchased-files .row .edd-payment-details-download-amount").each(function(){var t=e(this).next().val();if(t){n+=parseFloat(e(this).val())*parseInt(t)}else{n+=parseFloat(e(this).val())}})}if(e(".edd-payment-fees").length){e(".edd-payment-fees span.fee-amount").each(function(){n+=parseFloat(e(this).data("fee"))})}e("input[name=edd-payment-total]").val(n)})},variable_prices_check:function(){e("#edd-purchased-files").on("change","select#edd_order_download_select",function(){var t=e(this),n=t.val();if(parseInt(n)>0){var r={action:"edd_check_for_download_price_variations",download_id:n};e.ajax({type:"POST",data:r,url:ajaxurl,success:function(n){e(".edd_price_options_select").remove();e(n).insertAfter(t.next())}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}})}})},add_note:function(){e("#edd-add-payment-note").on("click",function(t){t.preventDefault();var n={action:"edd_insert_payment_note",payment_id:e(this).data("payment-id"),note:e("#edd-payment-note").val()};if(n.note){e.ajax({type:"POST",data:n,url:ajaxurl,success:function(t){e("#edd-payment-notes-inner").append(t);e(".edd-no-payment-notes").hide();e("#edd-payment-note").val("")}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}})}else{var r=e("#edd-payment-note").css("border-color");e("#edd-payment-note").css("border-color","red");setTimeout(function(){e("#edd-payment-note").css("border-color",r)},500)}})},remove_note:function(){e("body").on("click",".edd-delete-payment-note",function(t){t.preventDefault();if(confirm(edd_vars.delete_payment_note)){var n={action:"edd_delete_payment_note",payment_id:e(this).data("payment-id"),note_id:e(this).data("note-id")};e.ajax({type:"POST",data:n,url:ajaxurl,success:function(t){e("#edd-payment-note-"+n.note_id).remove();if(!e(".edd-payment-note").length){e(".edd-no-payment-notes").show()}return false}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}});return true}})},resend_receipt:function(){e("body").on("click","#edd-resend-receipt",function(e){return confirm(edd_vars.resend_receipt)})},copy_download_link:function(){e("body").on("click",".edd-copy-download-link",function(t){t.preventDefault();var n=e(this);var r={action:"edd_get_file_download_link",payment_id:e('input[name="edd_payment_id"]').val(),download_id:n.data("download-id"),price_id:n.data("price-id")};e.ajax({type:"POST",data:r,url:ajaxurl,success:function(e){alert(edd_vars.copy_download_link_text+"\n\n"+e);return false}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}})})}};r.init();var i={init:function(){this.type_select();this.product_requirements()},type_select:function(){e("#edd-edit-discount #edd-type, #edd-add-discount #edd-type").change(function(){e(".edd-amount-description").toggle()})},product_requirements:function(){e("#products").change(function(){if(e(this).val()){e("#edd-discount-product-conditions").show()}else{e("#edd-discount-product-conditions").hide()}})}};i.init();var s={init:function(){this.date_options();this.customers_export()},date_options:function(){e("#edd-graphs-date-options").change(function(){var t=e(this);if("other"===t.val()){e("#edd-date-range-options").show()}else{e("#edd-date-range-options").hide()}})},customers_export:function(){e("#edd_customer_export_download").change(function(){var t=e(this),n=e("option:selected",t).val();if("0"===t.val()){e("#edd_customer_export_option").show()}else{e("#edd_customer_export_option").hide()}if(parseInt(n)!=0){var r={action:"edd_check_for_download_price_variations",download_id:n};e.post(ajaxurl,r,function(n){e(".edd_price_options_select").remove();t.after(n)})}else{e(".edd_price_options_select").remove()}})}};s.init();var o={init:function(){this.general();this.taxes();this.emails();this.misc()},general:function(){if(e(".edd-color-picker").length){e(".edd-color-picker").wpColorPicker()}if(typeof wp==="undefined"||"1"!==edd_vars.new_media_ui){if(e(".edd_settings_upload_button").length>0){window.formfield="";e("body").on("click",".edd_settings_upload_button",function(t){t.preventDefault();window.formfield=e(this).parent().prev();window.tbframe_interval=setInterval(function(){jQuery("#TB_iframeContent").contents().find(".savesend .button").val(edd_vars.use_this_file).end().find("#insert-gallery, .wp-post-thumbnail").hide()},2e3);tb_show(edd_vars.add_new_download,"media-upload.php?TB_iframe=true")});window.edd_send_to_editor=window.send_to_editor;window.send_to_editor=function(t){if(window.formfield){imgurl=e("a","<div>"+t+"</div>").attr("href");window.formfield.val(imgurl);window.clearInterval(window.tbframe_interval);tb_remove()}else{window.edd_send_to_editor(t)}window.send_to_editor=window.edd_send_to_editor;window.formfield="";window.imagefield=false}}}else{var t;window.formfield="";e("body").on("click",".edd_settings_upload_button",function(n){n.preventDefault();var r=e(this);window.formfield=e(this).parent().prev();if(t){t.open();return}t=wp.media.frames.file_frame=wp.media({frame:"post",state:"insert",title:r.data("uploader_title"),button:{text:r.data("uploader_button_text")},multiple:false});t.on("menu:render:default",function(e){var t={};e.unset("library-separator");e.unset("gallery");e.unset("featured-image");e.unset("embed");e.set(t)});t.on("insert",function(){var e=t.state().get("selection");e.each(function(e,t){e=e.toJSON();window.formfield.val(e.url)})});t.open()});var t;window.formfield=""}},taxes:function(){if(e("select.edd-no-states").length){e("select.edd-no-states").closest("tr").hide()}e('select[name="edd_settings[base_country]"]').change(function(){var t=e(this),n=t.closest("tr");data={action:"edd_get_shop_states",country:e(this).val(),field_name:"edd_settings[base_state]"};e.post(ajaxurl,data,function(e){if("nostates"==e){n.next().hide()}else{n.next().show();n.next().find("select").replaceWith(e)}});return false});e("body").on("change","#edd_tax_rates select.edd-tax-country",function(){var t=e(this);data={action:"edd_get_shop_states",country:e(this).val(),field_name:t.attr("name").replace("country","state")};e.post(ajaxurl,data,function(e){if("nostates"==e){var n='<input type="text" name="'+data.field_name+'" value=""/>';t.parent().next().find("select").replaceWith(n)}else{t.parent().next().find("input,select").show();t.parent().next().find("input,select").replaceWith(e)}});return false});e("#edd_add_tax_rate").on("click",function(){var t=e("#edd_tax_rates tr:last");var n=t.clone();var r=t.parent().find("tr").length;n.find("td input").val("");n.find("input, select").each(function(){var t=e(this).attr("name");t=t.replace(/\[(\d+)\]/,"["+parseInt(r)+"]");e(this).attr("name",t).attr("id",t)});n.insertAfter(t);return false});e("body").on("click","#edd_tax_rates .edd_remove_tax_rate",function(){if(confirm(edd_vars.delete_tax_rate))e(this).closest("tr").remove();return false})},emails:function(){if(e("#email-preview-wrap").length){var t=e("#email-preview");e("#open-email-preview").colorbox({inline:true,href:t,width:"80%",height:"auto"})}},misc:function(){if(e('select[name="edd_settings[download_method]"]:selected').val()!="direct"){e('select[name="edd_settings[download_method]"]').parent().parent().next().hide();e('select[name="edd_settings[download_method]"]').parent().parent().next().find("input").attr("checked",false)}e('select[name="edd_settings[download_method]"]').on("change",function(){var t=e(this).parent().parent().next();if(e(this).val()=="direct"){t.hide()}else{t.show();t.find("input").attr("checked",false)}})}};o.init();e(".download_page_edd-payment-history .row-actions .delete a").on("click",function(){if(confirm(edd_vars.delete_payment)){return true}return false});e("#the-list").on("click",".editinline",function(){inlineEditPost.revert();var t=e(this).closest("tr").attr("id");t=t.replace("post-","");var n=e("#post-"+t);var r=n.find(".column-price .downloadprice-"+t).val();if(r!=e("#post-"+t+".column-price .downloadprice-"+t).val()){e(".regprice","#edd-download-data").val(r).attr("disabled",false)}else{e(".regprice","#edd-download-data").val(edd_vars.quick_edit_warning).attr("disabled","disabled")}});e("body").on("click","#bulk_edit",function(){var t=e("#bulk-edit");var n=new Array;t.find("#bulk-titles").children().each(function(){n.push(e(this).attr("id").replace(/^(ttle)/i,""))});var r=e('#edd-download-data input[name="_edd_regprice"]').val();var i={action:"edd_save_bulk_edit",edd_bulk_nonce:n,post_ids:n,price:r};e.post(ajaxurl,i)});e(".edd-select-chosen").chosen({inherit_select_classes:true,placeholder_text_single:edd_vars.one_option,placeholder_text_multiple:edd_vars.one_or_more_option});var u;var a=342;e(".edd-select.chosen-container .chosen-search input, .edd-select.chosen-container .search-field input").keyup(function(t){var n=e(this).val(),r=e(this).closest(".edd-select-chosen");var i=r.attr("id").replace("_chosen","");var s=t.which;if(n.length<=3||t.which==16||t.which==13||t.which==91||t.which==17||t.which==37||t.which==38||t.which==39||t.which==40){return}clearTimeout(u);u=setTimeout(function(){e.ajax({type:"GET",url:ajaxurl,data:{action:"edd_download_search",s:n},dataType:"json",beforeSend:function(){e("ul.chosen-results").empty()},success:function(t){e("#"+i+" option:not(:selected)").remove();e.each(t,function(t,n){if(!e("#"+i+' option[value="'+n.id+'"]').length){e("#"+i).prepend('<option value="'+n.id+'">'+n.name+"</option>")}});e(".edd-select-chosen").trigger("chosen:updated");e("#"+i).next().find("input").val(n)}}).fail(function(e){if(window.console&&window.console.log){console.log(data)}}).done(function(e){})},a)});e("#post").on("click",".edd-thickbox",function(){e(".edd-select-chosen","#choose-download").css("width","100%")});var f={init:function(){this.revoke_api_key();this.regenerate_api_key()},revoke_api_key:function(){e("body").on("click",".edd-revoke-api-key",function(e){return confirm(edd_vars.revoke_api_key)})},regenerate_api_key:function(){e("body").on("click",".edd-regenerate-api-key",function(e){return confirm(edd_vars.regenerate_api_key)})}};f.init();e(".edd-ajax-user-search").keyup(function(){var t=e(this).val();e(".edd-ajax").show();data={action:"edd_search_users",user_name:t};document.body.style.cursor="wait";e.ajax({type:"POST",data:data,dataType:"json",url:ajaxurl,success:function(t){e(".edd-ajax").hide();e(".edd_user_search_results").html("");e(t.results).appendTo(".edd_user_search_results");document.body.style.cursor="default"}})});e("body").on("click.eddSelectUser",".edd_user_search_results a",function(t){t.preventDefault();var n=e(this).data("login");e(".edd-ajax-user-search").val(n);e(".edd_user_search_results").html("")})})
1
+ jQuery(document).ready(function(e){var t={init:function(){this.add(),this.move(),this.remove(),this.type(),this.prices(),this.files(),this.updatePrices()},clone_repeatable:function(t){var d=highest=1;return t.parent().find("tr.edd_repeatable_row").each(function(){var t=e(this).data("key");parseInt(t)>highest&&(highest=t)}),d=highest+=1,clone=t.clone(),clone.find("select").each(function(){e(this).val(t.find('select[name="'+e(this).attr("name")+'"]').val())}),clone.removeClass("edd_add_blank"),clone.data("key",d),clone.find("td input, td select, textarea").val(""),clone.find("input, select, textarea").each(function(){var t=e(this).attr("name");t=t.replace(/\[(\d+)\]/,"["+parseInt(d)+"]"),e(this).attr("name",t).attr("id",t)}),clone.find("span.edd_price_id").each(function(){e(this).text(parseInt(d))}),clone.find(".edd_repeatable_default_input").each(function(){e(this).val(parseInt(d)).removeAttr("checked")}),clone},add:function(){e("body").on("click",".submit .edd_add_repeatable",function(d){d.preventDefault();var n=e(this),a=n.parent().parent().prev("tr"),o=t.clone_repeatable(a);o.insertAfter(a).find("input, textarea, select").filter(":visible").eq(0).focus()})},move:function(){e(".edd_repeatable_table tbody").sortable({handle:".edd_draghandle",items:".edd_repeatable_row",opacity:.6,cursor:"move",axis:"y",update:function(){var t=0;e(this).find("tr").each(function(){e(this).find("input.edd_repeatable_index").each(function(){e(this).val(t)}),t++})}})},remove:function(){e("body").on("click",".edd_remove_repeatable",function(t){t.preventDefault();var d=e(this).parent().parent("tr"),n=d.parent().find("tr").length-1,a=e(this).data("type"),o="tr.edd_repeatable_"+a+"s";if(e(".edd_repeatable_condition_field option[value="+d.index()+"]").remove(),n>1)e("input, select",d).val(""),d.fadeOut("fast").remove();else switch(a){case"price":alert(edd_vars.one_price_min);break;case"file":e("input, select",d).val("");break;default:alert(edd_vars.one_field_min)}e(o).each(function(t){e(this).find("input, select").each(function(){var d=e(this).attr("name");d=d.replace(/\[(\d+)\]/,"["+t+"]"),e(this).attr("name",d).attr("id",d)})})})},type:function(){e("body").on("change","#_edd_product_type",function(){"bundle"===e(this).val()?(e("#edd_products").show(),e("#edd_download_files").hide(),e("#edd_download_limit_wrap").hide()):(e("#edd_products").hide(),e("#edd_download_files").show(),e("#edd_download_limit_wrap").show())})},prices:function(){e("body").on("change","#edd_variable_pricing",function(){e(".edd_pricing_fields,.edd_repeatable_table .pricing").toggle()})},files:function(){if("undefined"==typeof wp||"1"!==edd_vars.new_media_ui)e(".edd_upload_file_button").length>0&&(window.formfield="",e("body").on("click",".edd_upload_file_button",function(t){if(t.preventDefault(),window.formfield=e(this).parent().prev(),window.tbframe_interval=setInterval(function(){jQuery("#TB_iframeContent").contents().find(".savesend .button").val(edd_vars.use_this_file).end().find("#insert-gallery, .wp-post-thumbnail").hide()},2e3),null!=edd_vars.post_id)var d="post_id="+edd_vars.post_id+"&";tb_show(edd_vars.add_new_download,"media-upload.php?"+d+"TB_iframe=true")}),window.edd_send_to_editor=window.send_to_editor,window.send_to_editor=function(t){window.formfield?(imgurl=e("a","<div>"+t+"</div>").attr("href"),window.formfield.val(imgurl),window.clearInterval(window.tbframe_interval),tb_remove()):window.edd_send_to_editor(t),window.send_to_editor=window.edd_send_to_editor,window.formfield="",window.imagefield=!1});else{var d;window.formfield="",e("body").on("click",".edd_upload_file_button",function(n){n.preventDefault();var a=e(this);return window.formfield=e(this).closest(".edd_repeatable_upload_wrapper"),d?void d.open():(d=wp.media.frames.file_frame=wp.media({frame:"post",state:"insert",title:a.data("uploader-title"),button:{text:a.data("uploader-button-text")},multiple:"0"==e(this).data("multiple")?!1:!0}),d.on("menu:render:default",function(e){var t={};e.unset("library-separator"),e.unset("gallery"),e.unset("featured-image"),e.unset("embed"),e.set(t)}),d.on("insert",function(){var e=d.state().get("selection");e.each(function(e,d){if(e=e.toJSON(),0===d)window.formfield.find(".edd_repeatable_attachment_id_field").val(e.id),window.formfield.find(".edd_repeatable_upload_field").val(e.url),window.formfield.find(".edd_repeatable_name_field").val(e.title);else{var n=window.formfield,a=t.clone_repeatable(n);a.find(".edd_repeatable_attachment_id_field").val(e.id),a.find(".edd_repeatable_upload_field").val(e.url),a.find(".edd_repeatable_name_field").val(e.title.length>0?e.title:e.filename),a.insertAfter(n)}})}),void d.open())});var d;window.formfield=""}},updatePrices:function(){e("#edd_price_fields").on("keyup",".edd_variable_prices_name",function(){var t=e(this).parents("tr").data("key"),d=e(this).val(),n=e(".edd_repeatable_condition_field option[value="+t+"]");n.length>0?n.text(d):e(".edd_repeatable_condition_field").append(e("<option></option>").attr("value",t).text(d))})}};if(t.init(),e(".edd_datepicker").length>0){var d="mm/dd/yy";e(".edd_datepicker").datepicker({dateFormat:d})}var n={init:function(){this.edit_address(),this.remove_download(),this.add_download(),this.new_customer(),this.recalculate_total(),this.variable_prices_check(),this.add_note(),this.remove_note(),this.resend_receipt(),this.copy_download_link()},edit_address:function(){e('select[name="edd-payment-address[0][country]"]').change(function(){var t=e(this);return data={action:"edd_get_shop_states",country:t.val(),field_name:"edd-payment-address[0][state]"},e.post(ajaxurl,data,function(t){e("#edd-order-address-state-wrap select, #edd-order-address-state-wrap input").replaceWith("nostates"==t?'<input type="text" name="edd-payment-address[0][state]" value="" class="edd-edit-toggles medium-text"/>':t)}),!1})},remove_download:function(){e("#edd-purchased-files").on("click",".edd-order-remove-download",function(){if(confirm(edd_vars.delete_payment_download)){var t=e(this).data("key"),d=(e(".edd-payment-id").val(),e('input[name="edd-payment-details-downloads['+t+'][id]"]').val()),n=e('input[name="edd-payment-details-downloads['+t+'][price_id]"]').val(),a=e('input[name="edd-payment-details-downloads['+t+'][quantity]"]').val(),o=e('input[name="edd-payment-details-downloads['+t+'][amount]"]').val(),i=e('input[name="edd-payment-removed"]').val();i=e.parseJSON(i),i.length<1&&(i={});var r=[{id:d,price_id:n,quantity:a,amount:o}];i[t]=r,e('input[name="edd-payment-removed"]').val(JSON.stringify(i)),e(this).parent().parent().parent().remove(),e("#edd-payment-downloads-changed").val(1),e(".edd-order-payment-recalc-totals").show()}return!1})},new_customer:function(){e("#edd-customer-details").on("click",".edd-payment-new-customer, .edd-payment-new-customer-cancel",function(t){t.preventDefault(),e(".customer-info").toggle(),e(".new-customer").toggle(),e("#edd-new-customer").val(e(".new-customer").is(":visible")?1:0)})},add_download:function(){e("#edd-purchased-files").on("click","#edd-order-add-download",function(t){t.preventDefault();var d=e("#edd_order_download_select").val(),n=e("#edd_order_download_select").find(":selected").text(),a=e("#edd-order-download-quantity").val(),o=e("#edd-order-download-amount").val(),i=e(".edd_price_options_select option:selected").val(),r=e(".edd_price_options_select option:selected").text();if(1>d)return!1;if(o||(o=0),o=parseFloat(o),isNaN(o))return alert(edd_vars.numeric_item_price),!1;if("1"===edd_vars.quantities_enabled){if(isNaN(parseInt(a)))return alert(edd_vars.numeric_quantity),!1;o*=a}o=o.toFixed(edd_vars.currency_decimals);var s=o+edd_vars.currency_sign;"before"===edd_vars.currency_pos&&(s=edd_vars.currency_sign+o),r&&(n=n+" - "+r);var c=e("#edd-purchased-files div.row").length,l=e("#edd-purchased-files div.row:last").clone();l.find(".download span").html('<a href="post.php?post='+d+'&action=edit"></a>'),l.find(".download span a").text(n),l.find(".price-text").text(s),l.find(".item-quantity").text(a),l.find(".item-price").text(edd_vars.currency_sign+(o/a).toFixed(edd_vars.currency_decimals)),l.find("input.edd-payment-details-download-id").val(d),l.find("input.edd-payment-details-download-price-id").val(i),l.find("input.edd-payment-details-download-amount").val(o),l.find("input.edd-payment-details-download-quantity").val(a),l.find("input.edd-payment-details-download-has-log").val(0),l.find("input").each(function(){var t=e(this).attr("name");t=t.replace(/\[(\d+)\]/,"["+parseInt(c)+"]"),e(this).attr("name",t).attr("id",t)}),e("#edd-payment-downloads-changed").val(1),e(l).insertAfter("#edd-purchased-files div.row:last"),e(".edd-order-payment-recalc-totals").show()})},recalculate_total:function(){e("#edd-order-recalc-total").on("click",function(t){t.preventDefault();var d=0;e("#edd-purchased-files .row .edd-payment-details-download-amount").length&&e("#edd-purchased-files .row .edd-payment-details-download-amount").each(function(){d+=parseFloat(e(this).val())}),e(".edd-payment-fees").length&&e(".edd-payment-fees span.fee-amount").each(function(){d+=parseFloat(e(this).data("fee"))}),e("input[name=edd-payment-total]").val(d)})},variable_prices_check:function(){e("#edd-purchased-files").on("change","select#edd_order_download_select",function(){var t=e(this),d=t.val();if(parseInt(d)>0){var n={action:"edd_check_for_download_price_variations",download_id:d};e.ajax({type:"POST",data:n,url:ajaxurl,success:function(d){e(".edd_price_options_select").remove(),e(d).insertAfter(t.next())}}).fail(function(e){window.console&&window.console.log&&console.log(e)})}})},add_note:function(){e("#edd-add-payment-note").on("click",function(t){t.preventDefault();var d={action:"edd_insert_payment_note",payment_id:e(this).data("payment-id"),note:e("#edd-payment-note").val()};if(d.note)e.ajax({type:"POST",data:d,url:ajaxurl,success:function(t){e("#edd-payment-notes-inner").append(t),e(".edd-no-payment-notes").hide(),e("#edd-payment-note").val("")}}).fail(function(e){window.console&&window.console.log&&console.log(e)});else{var n=e("#edd-payment-note").css("border-color");e("#edd-payment-note").css("border-color","red"),setTimeout(function(){e("#edd-payment-note").css("border-color",n)},500)}})},remove_note:function(){e("body").on("click",".edd-delete-payment-note",function(t){if(t.preventDefault(),confirm(edd_vars.delete_payment_note)){var d={action:"edd_delete_payment_note",payment_id:e(this).data("payment-id"),note_id:e(this).data("note-id")};return e.ajax({type:"POST",data:d,url:ajaxurl,success:function(){return e("#edd-payment-note-"+d.note_id).remove(),e(".edd-payment-note").length||e(".edd-no-payment-notes").show(),!1}}).fail(function(e){window.console&&window.console.log&&console.log(e)}),!0}})},resend_receipt:function(){e("body").on("click","#edd-resend-receipt",function(){return confirm(edd_vars.resend_receipt)})},copy_download_link:function(){e("body").on("click",".edd-copy-download-link",function(t){t.preventDefault();var d=e(this),n={action:"edd_get_file_download_link",payment_id:e('input[name="edd_payment_id"]').val(),download_id:d.data("download-id"),price_id:d.data("price-id")};e.ajax({type:"POST",data:n,url:ajaxurl,success:function(t){return e("#edd-download-link").dialog({width:400}).html('<textarea rows="10" cols="40" id="edd-download-link-textarea">'+t+"</textarea>"),e("#edd-download-link-textarea").focus().select(),!1}}).fail(function(e){window.console&&window.console.log&&console.log(e)})})}};n.init();var a={init:function(){this.type_select(),this.product_requirements()},type_select:function(){e("#edd-edit-discount #edd-type, #edd-add-discount #edd-type").change(function(){e(".edd-amount-description").toggle()})},product_requirements:function(){e("#products").change(function(){e(this).val()?e("#edd-discount-product-conditions").show():e("#edd-discount-product-conditions").hide()})}};a.init();var o={init:function(){this.date_options(),this.customers_export()},date_options:function(){e("#edd-graphs-date-options").change(function(){var t=e(this);"other"===t.val()?e("#edd-date-range-options").show():e("#edd-date-range-options").hide()})},customers_export:function(){e("#edd_customer_export_download").change(function(){var t=e(this),d=e("option:selected",t).val();if("0"===t.val()?e("#edd_customer_export_option").show():e("#edd_customer_export_option").hide(),0!=parseInt(d)){var n={action:"edd_check_for_download_price_variations",download_id:d};e.post(ajaxurl,n,function(d){e(".edd_price_options_select").remove(),t.after(d)})}else e(".edd_price_options_select").remove()})}};o.init();var i={init:function(){this.general(),this.taxes(),this.emails(),this.misc()},general:function(){if(e(".edd-color-picker").length&&e(".edd-color-picker").wpColorPicker(),"undefined"==typeof wp||"1"!==edd_vars.new_media_ui)e(".edd_settings_upload_button").length>0&&(window.formfield="",e("body").on("click",".edd_settings_upload_button",function(t){t.preventDefault(),window.formfield=e(this).parent().prev(),window.tbframe_interval=setInterval(function(){jQuery("#TB_iframeContent").contents().find(".savesend .button").val(edd_vars.use_this_file).end().find("#insert-gallery, .wp-post-thumbnail").hide()},2e3),tb_show(edd_vars.add_new_download,"media-upload.php?TB_iframe=true")}),window.edd_send_to_editor=window.send_to_editor,window.send_to_editor=function(t){window.formfield?(imgurl=e("a","<div>"+t+"</div>").attr("href"),window.formfield.val(imgurl),window.clearInterval(window.tbframe_interval),tb_remove()):window.edd_send_to_editor(t),window.send_to_editor=window.edd_send_to_editor,window.formfield="",window.imagefield=!1});else{var t;window.formfield="",e("body").on("click",".edd_settings_upload_button",function(d){d.preventDefault();var n=e(this);return window.formfield=e(this).parent().prev(),t?void t.open():(t=wp.media.frames.file_frame=wp.media({frame:"post",state:"insert",title:n.data("uploader_title"),button:{text:n.data("uploader_button_text")},multiple:!1}),t.on("menu:render:default",function(e){var t={};e.unset("library-separator"),e.unset("gallery"),e.unset("featured-image"),e.unset("embed"),e.set(t)}),t.on("insert",function(){var e=t.state().get("selection");e.each(function(e){e=e.toJSON(),window.formfield.val(e.url)})}),void t.open())});var t;window.formfield=""}},taxes:function(){e("select.edd-no-states").length&&e("select.edd-no-states").closest("tr").hide(),e('select[name="edd_settings[base_country]"]').change(function(){var t=e(this),d=t.closest("tr");return data={action:"edd_get_shop_states",country:e(this).val(),field_name:"edd_settings[base_state]"},e.post(ajaxurl,data,function(e){"nostates"==e?d.next().hide():(d.next().show(),d.next().find("select").replaceWith(e))}),!1}),e("body").on("change","#edd_tax_rates select.edd-tax-country",function(){var t=e(this);return data={action:"edd_get_shop_states",country:e(this).val(),field_name:t.attr("name").replace("country","state")},e.post(ajaxurl,data,function(e){if("nostates"==e){var d='<input type="text" name="'+data.field_name+'" value=""/>';t.parent().next().find("select").replaceWith(d)}else t.parent().next().find("input,select").show(),t.parent().next().find("input,select").replaceWith(e)}),!1}),e("#edd_add_tax_rate").on("click",function(){var t=e("#edd_tax_rates tr:last"),d=t.clone(),n=t.parent().find("tr").length;return d.find("td input").val(""),d.find("input, select").each(function(){var t=e(this).attr("name");t=t.replace(/\[(\d+)\]/,"["+parseInt(n)+"]"),e(this).attr("name",t).attr("id",t)}),d.insertAfter(t),!1}),e("body").on("click","#edd_tax_rates .edd_remove_tax_rate",function(){if(confirm(edd_vars.delete_tax_rate)){var t=e("#edd_tax_rates tr:visible").length;2===t?(e("#edd_tax_rates select").val(""),e('#edd_tax_rates input[type="text"]').val(""),e('#edd_tax_rates input[type="number"]').val(""),e('#edd_tax_rates input[type="checkbox"]').attr("checked",!1)):e(this).closest("tr").remove()}return!1})},emails:function(){if(e("#email-preview-wrap").length){var t=e("#email-preview");e("#open-email-preview").colorbox({inline:!0,href:t,width:"80%",height:"auto"})}},misc:function(){"direct"!=e('select[name="edd_settings[download_method]"]:selected').val()&&(e('select[name="edd_settings[download_method]"]').parent().parent().next().hide(),e('select[name="edd_settings[download_method]"]').parent().parent().next().find("input").attr("checked",!1)),e('select[name="edd_settings[download_method]"]').on("change",function(){var t=e(this).parent().parent().next();"direct"==e(this).val()?t.hide():(t.show(),t.find("input").attr("checked",!1))})}};i.init(),e(".download_page_edd-payment-history .row-actions .delete a").on("click",function(){return confirm(edd_vars.delete_payment)?!0:!1}),e("#the-list").on("click",".editinline",function(){inlineEditPost.revert();var t=e(this).closest("tr").attr("id");t=t.replace("post-","");var d=e("#post-"+t),n=d.find(".column-price .downloadprice-"+t).val();n!=e("#post-"+t+".column-price .downloadprice-"+t).val()?e(".regprice","#edd-download-data").val(n).attr("disabled",!1):e(".regprice","#edd-download-data").val(edd_vars.quick_edit_warning).attr("disabled","disabled")}),e("body").on("click","#bulk_edit",function(){var t=e("#bulk-edit"),d=new Array;t.find("#bulk-titles").children().each(function(){d.push(e(this).attr("id").replace(/^(ttle)/i,""))});var n=e('#edd-download-data input[name="_edd_regprice"]').val(),a={action:"edd_save_bulk_edit",edd_bulk_nonce:d,post_ids:d,price:n};e.post(ajaxurl,a)}),e(".edd-select-chosen").chosen({inherit_select_classes:!0,placeholder_text_single:edd_vars.one_option,placeholder_text_multiple:edd_vars.one_or_more_option}),e(".chosen-choices").on("click",function(){e(this).children("li").children("input").attr("placeholder",edd_vars.type_to_search)});var r,s=342;e(".edd-select.chosen-container .chosen-search input, .edd-select.chosen-container .search-field input").keyup(function(t){var d=e(this).val(),n=e(this).closest(".edd-select-chosen"),a=n.attr("id").replace("_chosen",""),o=(t.which,"edd_download_search");n.attr("id").indexOf("customer")>=0&&(o="edd_customer_search"),d.length<=3&&"edd_download_search"==o||16==t.which||13==t.which||91==t.which||17==t.which||37==t.which||38==t.which||39==t.which||40==t.which||(clearTimeout(r),r=setTimeout(function(){e.ajax({type:"GET",url:ajaxurl,data:{action:o,s:d,current_id:edd_vars.post_id},dataType:"json",beforeSend:function(){e("ul.chosen-results").empty()},success:function(t){e("#"+a+" option:not(:selected)").remove(),e.each(t,function(t,d){e("#"+a+' option[value="'+d.id+'"]').length||e("#"+a).prepend('<option value="'+d.id+'">'+d.name+"</option>")}),e(".edd-select-chosen").trigger("chosen:updated"),e("#"+a).next().find("input").val(d)}}).fail(function(e){window.console&&window.console.log&&console.log(e)}).done(function(){})},s))}),e("#post").on("click",".edd-thickbox",function(){e(".edd-select-chosen","#choose-download").css("width","100%")});var c={init:function(){this.revoke_api_key(),this.regenerate_api_key()},revoke_api_key:function(){e("body").on("click",".edd-revoke-api-key",function(){return confirm(edd_vars.revoke_api_key)})},regenerate_api_key:function(){e("body").on("click",".edd-regenerate-api-key",function(){return confirm(edd_vars.regenerate_api_key)})}};c.init();var l={init:function(){this.edit_customer(),this.user_search(),this.remove_user(),this.cancel_edit(),this.change_country(),this.add_note(),this.delete_checked()},edit_customer:function(){e("body").on("click","#edit-customer",function(t){t.preventDefault(),e("#edd-customer-card-wrapper .editable").hide(),e("#edd-customer-card-wrapper .edit-item").fadeIn().css("display","block")})},user_search:function(){e("body").on("click.eddSelectUser",".edd_user_search_results a",function(t){t.preventDefault();var d=e(this).data("userid");e('input[name="customerinfo[user_id]"]').val(d)})},remove_user:function(){e("body").on("click","#disconnect-customer",function(t){t.preventDefault();var d=e('input[name="customerinfo[id]"]').val(),n={edd_action:"disconnect-userid",customer_id:d,_wpnonce:e("#edit-customer-info #_wpnonce").val()};e.post(ajaxurl,n,function(){window.location.href=window.location.href},"json")})},cancel_edit:function(){e("body").on("click","#edd-edit-customer-cancel",function(t){t.preventDefault(),e("#edd-customer-card-wrapper .edit-item").hide(),e("#edd-customer-card-wrapper .editable").show(),e(".edd_user_search_results").html("")})},change_country:function(){e('select[name="customerinfo[country]"]').change(function(){var t=e(this);return data={action:"edd_get_shop_states",country:t.val(),field_name:"customerinfo[state]"},e.post(ajaxurl,data,function(t){e(':input[name="customerinfo[state]"]').replaceWith("nostates"==t?'<input type="text" name="'+data.field_name+'" value="" class="edd-edit-toggles medium-text"/>':t)}),!1})},add_note:function(){e("body").on("click","#add-customer-note",function(t){t.preventDefault();var d={edd_action:"add-customer-note",customer_id:e("#customer-id").val(),customer_note:e("#customer-note").val(),add_customer_note_nonce:e("#add_customer_note_nonce").val()};if(d.customer_note)e.ajax({type:"POST",data:d,url:ajaxurl,success:function(t){e("#edd-customer-notes").prepend(t),e(".edd-no-customer-notes").hide(),e("#customer-note").val("")}}).fail(function(e){window.console&&window.console.log&&console.log(e)});else{var n=e("#customer-note").css("border-color");e("#customer-note").css("border-color","red"),setTimeout(function(){e("#customer-note").css("border-color",n)},500)}})},delete_checked:function(){e("#edd-customer-delete-confirm").change(function(){var t=e("#edd-customer-delete-records"),d=e("#edd-delete-customer");e(this).prop("checked")?(t.attr("disabled",!1),d.attr("disabled",!1)):(t.attr("disabled",!0),t.prop("checked",!1),d.attr("disabled",!0))})}};l.init(),e(".edd-ajax-user-search").keyup(function(){var t=e(this).val(),d="";e(this).data("exclude")&&(d=e(this).data("exclude")),e(".edd-ajax").show(),data={action:"edd_search_users",user_name:t,exclude:d},document.body.style.cursor="wait",e.ajax({type:"POST",data:data,dataType:"json",url:ajaxurl,success:function(t){e(".edd-ajax").hide(),e(".edd_user_search_results").removeClass("hidden"),e(".edd_user_search_results span").html(""),e(t.results).appendTo(".edd_user_search_results span"),document.body.style.cursor="default"}})}),e("body").on("click.eddSelectUser",".edd_user_search_results span a",function(t){t.preventDefault();var d=e(this).data("login");e(".edd-ajax-user-search").val(d),e(".edd_user_search_results").addClass("hidden"),e(".edd_user_search_results span").html("")}),e("body").on("click.eddCancelUserSearch",".edd_user_search_results a.edd-ajax-user-cancel",function(t){t.preventDefault(),e(".edd-ajax-user-search").val(""),e(".edd_user_search_results").addClass("hidden"),e(".edd_user_search_results span").html("")}),e.ajax({type:"GET",data:{action:"edd_load_dashboard_widget"},url:ajaxurl,success:function(t){e("#edd_dashboard_sales .inside").html(t)}}),e(document).on("keydown",".customer-note-input",function(t){13==t.keyCode&&(t.metaKey||t.ctrlKey)&&e("#add-customer-note").click()})});
assets/js/edd-ajax.js CHANGED
@@ -1,314 +1,357 @@
1
  var edd_scripts;
2
  jQuery(document).ready(function ($) {
3
 
4
- // Hide unneeded elements. These are things that are required in case JS breaks or isn't present
5
- $('.edd-no-js').hide();
6
- $('a.edd-add-to-cart').addClass('edd-has-js');
7
-
8
- // Send Remove from Cart requests
9
- $('body').on('click.eddRemoveFromCart', '.edd-remove-from-cart', function (event) {
10
- var $this = $(this),
11
- item = $this.data('cart-item'),
12
- action = $this.data('action'),
13
- id = $this.data('download-id'),
14
- data = {
15
- action: action,
16
- cart_item: item
17
- };
18
-
19
- $.ajax({
20
- type: "POST",
21
- data: data,
22
- dataType: "json",
23
- url: edd_scripts.ajaxurl,
24
- success: function (response) {
25
- if (response.removed) {
26
- if ( parseInt( edd_scripts.position_in_cart, 10 ) === parseInt( item, 10 ) ) {
27
- window.location = window.location;
28
- return false;
29
- }
30
-
31
- // Remove the selected cart item
32
- $('.edd-cart').find("[data-cart-item='" + item + "']").parent().remove();
33
-
34
- // Check to see if the purchase form for this download is present on this page
35
- if( $( '#edd_purchase_' + id ).length ) {
36
- $( '#edd_purchase_' + id + ' .edd_go_to_checkout' ).hide();
37
- $( '#edd_purchase_' + id + ' a.edd-add-to-cart' ).show().removeAttr('data-edd-loading');
38
- }
39
-
40
- $('span.edd-cart-quantity').each(function() {
41
- var quantity = parseInt( $(this).text(), 10 ) - 1;
42
- if( quantity < 1 ) {
43
- quantity = 0;
44
- }
45
- $(this).text( quantity );
46
- $('body').trigger('edd_quantity_updated', [ quantity ]);
47
- });
48
-
49
- $('.cart_item.edd_subtotal span').html( response.subtotal );
50
-
51
- if(!$('.edd-cart-item').length) {
52
- $('.cart_item.edd_subtotal,.edd-cart-number-of-items,.cart_item.edd_checkout').hide();
53
- $('.edd-cart').append('<li class="cart_item empty">' + edd_scripts.empty_cart_message + '</li>');
54
- }
55
-
56
- $('body').trigger('edd_cart_item_removed', [ response ]);
57
- }
58
- }
59
- }).fail(function (response) {
60
- if ( window.console && window.console.log ) {
61
- console.log( response );
62
- }
63
- }).done(function (response) {
64
-
65
- });
66
-
67
- return false;
68
- });
69
-
70
- // Send Add to Cart request
71
- $('body').on('click.eddAddToCart', '.edd-add-to-cart', function (e) {
72
-
73
- e.preventDefault();
74
-
75
- var $this = $(this), form = $this.closest('form');
76
-
77
- if( 'straight_to_gateway' == form.find('.edd_action_input').val() ) {
78
- form.submit();
79
- return true; // Submit the form
80
- }
81
-
82
- var $spinner = $this.find('.edd-loading');
83
- var container = $this.closest('div');
84
-
85
- var spinnerWidth = $spinner.width(),
86
- spinnerHeight = $spinner.height();
87
-
88
- // Show the spinner
89
- $this.attr('data-edd-loading', '');
90
-
91
- $spinner.css({
92
- 'margin-left': spinnerWidth / -2,
93
- 'margin-top' : spinnerHeight / -2
94
- });
95
-
96
- var form = $this.parents('form').last();
97
- var download = $this.data('download-id');
98
- var variable_price = $this.data('variable-price');
99
- var price_mode = $this.data('price-mode');
100
- var item_price_ids = [];
101
-
102
- if( variable_price == 'yes' ) {
103
-
104
- if( ! $('.edd_price_option_' + download + ':checked', form).length ) {
105
- // hide the spinner
106
- $this.removeAttr( 'data-edd-loading' );
107
- alert( edd_scripts.select_option );
108
- return;
109
- }
110
-
111
- $('.edd_price_option_' + download + ':checked', form).each(function( index ) {
112
- item_price_ids[ index ] = $(this).val();
113
- });
114
-
115
- } else {
116
- item_price_ids[0] = download;
117
- }
118
-
119
- var action = $this.data('action');
120
- var data = {
121
- action: action,
122
- download_id: download,
123
- price_ids : item_price_ids,
124
- post_data: $(form).serialize()
125
- };
126
-
127
- $.ajax({
128
- type: "POST",
129
- data: data,
130
- dataType: "json",
131
- url: edd_scripts.ajaxurl,
132
- success: function (response) {
133
-
134
- if( edd_scripts.redirect_to_checkout == '1' ) {
135
-
136
- window.location = edd_scripts.checkout_page;
137
-
138
- } else {
139
-
140
- // Add the new item to the cart widget
141
- if ($('.cart_item.empty').length) {
142
- $(response.cart_item).insertBefore('.cart_item.edd_subtotal');
143
- $('.cart_item.edd_checkout,.cart_item.edd_subtotal').show();
144
- $('.cart_item.empty').remove();
145
- } else {
146
- $(response.cart_item).insertBefore('.cart_item.edd_subtotal');
147
- }
148
-
149
- $('.cart_item.edd_subtotal span').html( response.subtotal );
150
-
151
- // Update the cart quantity
152
- $('span.edd-cart-quantity').each(function() {
153
- var quantity = parseInt($(this).text(), 10) + 1;
154
- $(this).text(quantity);
155
- $('body').trigger('edd_quantity_updated', [ quantity ]);
156
- });
157
-
158
- // Show the "number of items in cart" message
159
- if ( $('.edd-cart-number-of-items').css('display') == 'none') {
160
- $('.edd-cart-number-of-items').show('slow');
161
- }
162
-
163
- if( variable_price == 'no' || price_mode != 'multi' ) {
164
- // Switch purchase to checkout if a single price item or variable priced with radio buttons
165
- $('a.edd-add-to-cart', container).toggle();
166
- $('.edd_go_to_checkout', container).css('display', 'inline-block');
167
- }
168
-
169
- if ( price_mode == 'multi' ) {
170
- // remove spinner for multi
171
- $this.removeAttr( 'data-edd-loading' );
172
- }
173
-
174
- // Update all buttons for same download
175
- if( $( '.edd_download_purchase_form' ).length ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  var parent_form = $('.edd_download_purchase_form *[data-download-id="' + download + '"]').parents('form');
177
  $( 'a.edd-add-to-cart', parent_form ).hide();
178
- $( '.edd_go_to_checkout', parent_form ).show().removeAttr( 'data-edd-loading' );
179
- }
 
 
 
 
 
 
 
 
 
 
 
180
 
181
- if( response != 'incart' ) {
182
- // Show the added message
183
- $('.edd-cart-added-alert', container).fadeIn();
184
- setTimeout(function () {
185
- $('.edd-cart-added-alert', container).fadeOut();
186
- }, 3000);
187
- }
188
 
189
- $('body').trigger('edd_cart_item_added', [ response ]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
- }
192
- }
193
- }).fail(function (response) {
194
- if ( window.console && window.console.log ) {
195
- console.log( response );
196
- }
197
- }).done(function (response) {
 
198
 
199
- });
 
200
 
201
- return false;
202
- });
203
 
204
- // Show the login form on the checkout page
205
- $('#edd_checkout_form_wrap').on('click', '.edd_checkout_register_login', function () {
206
- var $this = $(this),
207
- data = {
208
- action: $this.data('action')
209
- };
210
- // Show the ajax loader
211
- $('.edd-cart-ajax').show();
212
 
213
- $.post(edd_scripts.ajaxurl, data, function (checkout_response) {
214
- $('#edd_checkout_login_register').html(edd_scripts.loading);
215
- $('#edd_checkout_login_register').html(checkout_response);
216
- // Hide the ajax loader
217
- $('.edd-cart-ajax').hide();
218
- });
219
- return false;
220
- });
221
 
222
- // Process the login form via ajax
223
- $(document).on('click', '#edd_purchase_form #edd_login_fields input[type=submit]', function(e) {
224
 
225
- e.preventDefault();
 
 
 
 
 
226
 
227
- var complete_purchase_val = $(this).val();
228
 
229
- $(this).val(edd_global_vars.purchase_loading);
 
 
 
 
 
 
 
 
 
230
 
231
- $(this).after('<span class="edd-cart-ajax"><i class="edd-icon-spinner edd-icon-spin"></i></span>');
232
 
233
- var data = {
234
- action : 'edd_process_checkout_login',
235
- edd_ajax : 1,
236
- edd_user_login : $('#edd_login_fields #edd_user_login').val(),
237
- edd_user_pass : $('#edd_login_fields #edd_user_pass').val()
238
- };
239
 
240
- $.post(edd_global_vars.ajaxurl, data, function(data) {
241
 
242
- if ( $.trim(data) == 'success' ) {
243
- $('.edd_errors').remove();
244
- window.location = edd_scripts.checkout_page;
245
- } else {
246
- $('#edd_login_fields input[type=submit]').val(complete_purchase_val);
247
- $('.edd-cart-ajax').remove();
248
- $('.edd_errors').remove();
249
- $('#edd-user-login-submit').before(data);
250
- }
251
- });
252
 
253
- });
254
 
255
- // Load the fields for the selected payment method
256
- $('select#edd-gateway, input.edd-gateway').change( function (e) {
257
 
258
- var payment_mode = $('#edd-gateway option:selected, input.edd-gateway:checked').val();
 
 
 
 
 
259
 
260
- if( payment_mode == '0' )
261
- return false;
262
 
263
- edd_load_gateway( payment_mode );
264
 
265
- return false;
266
- });
 
267
 
268
- // Auto load first payment gateway
269
- if( edd_scripts.is_checkout == '1' && $('select#edd-gateway, input.edd-gateway').length ) {
270
- setTimeout( function() {
271
- edd_load_gateway( edd_scripts.default_gateway );
272
- }, 200);
273
- }
274
 
275
- $(document).on('click', '#edd_purchase_form #edd_purchase_submit input[type=submit]', function(e) {
276
 
277
- e.preventDefault();
278
 
279
- var complete_purchase_val = $(this).val();
280
 
281
- $(this).val(edd_global_vars.purchase_loading);
 
 
 
 
 
 
 
 
 
 
282
 
283
- $(this).after('<span class="edd-cart-ajax"><i class="edd-icon-spinner edd-icon-spin"></i></span>');
284
-
285
- $.post(edd_global_vars.ajaxurl, $('#edd_purchase_form').serialize() + '&action=edd_process_checkout&edd_ajax=true', function(data) {
286
- if ( $.trim(data) == 'success' ) {
287
- $('.edd_errors').remove();
288
- $('#edd_purchase_form').submit();
289
- } else {
290
- $('#edd_purchase_form input[type=submit]').val(complete_purchase_val);
291
- $('.edd-cart-ajax').remove();
292
- $('.edd_errors').remove();
293
- $('#edd_purchase_submit').before(data);
294
- }
295
- });
296
-
297
- });
298
 
299
  });
300
 
301
  function edd_load_gateway( payment_mode ) {
302
 
303
- // Show the ajax loader
304
- jQuery('.edd-cart-ajax').show();
305
- jQuery('#edd_purchase_form_wrap').html('<img src="' + edd_scripts.ajax_loader + '"/>');
306
 
307
- jQuery.post(edd_scripts.ajaxurl + '?payment-mode=' + payment_mode, { action: 'edd_load_gateway', edd_payment_mode: payment_mode },
308
- function(response){
309
- jQuery('#edd_purchase_form_wrap').html(response);
310
- jQuery('.edd-no-js').hide();
311
- }
312
- );
313
 
314
  }
1
  var edd_scripts;
2
  jQuery(document).ready(function ($) {
3
 
4
+ // Hide unneeded elements. These are things that are required in case JS breaks or isn't present
5
+ $('.edd-no-js').hide();
6
+ $('a.edd-add-to-cart').addClass('edd-has-js');
7
+
8
+ // Send Remove from Cart requests
9
+ $('body').on('click.eddRemoveFromCart', '.edd-remove-from-cart', function (event) {
10
+ var $this = $(this),
11
+ item = $this.data('cart-item'),
12
+ action = $this.data('action'),
13
+ id = $this.data('download-id'),
14
+ data = {
15
+ action: action,
16
+ cart_item: item
17
+ };
18
+
19
+ $.ajax({
20
+ type: "POST",
21
+ data: data,
22
+ dataType: "json",
23
+ url: edd_scripts.ajaxurl,
24
+ xhrFields: {
25
+ withCredentials: true
26
+ },
27
+ success: function (response) {
28
+ if (response.removed) {
29
+ if ( parseInt( edd_scripts.position_in_cart, 10 ) === parseInt( item, 10 ) ) {
30
+ window.location = window.location;
31
+ return false;
32
+ }
33
+
34
+ // Remove the selected cart item
35
+ $('.edd-cart').find("[data-cart-item='" + item + "']").parent().parent().remove();
36
+
37
+ //Reset the data-cart-item attributes to match their new values in the EDD session cart array
38
+ var cart_item_counter = 0;
39
+ $('.edd-cart').find("[data-cart-item]").each(function(){
40
+ $(this).attr('data-cart-item', cart_item_counter);
41
+ cart_item_counter = cart_item_counter + 1;
42
+ });
43
+
44
+ // Check to see if the purchase form for this download is present on this page
45
+ if( $( '#edd_purchase_' + id ).length ) {
46
+ $( '#edd_purchase_' + id + ' .edd_go_to_checkout' ).hide();
47
+ $( '#edd_purchase_' + id + ' a.edd-add-to-cart' ).show().removeAttr('data-edd-loading');
48
+ if ( edd_scripts.quantities_enabled == '1' ) {
49
+ $( '#edd_purchase_' + id + ' .edd_download_quantity_wrapper' ).show();
50
+ }
51
+ }
52
+
53
+ $('span.edd-cart-quantity').text( response.cart_quantity );
54
+ $('body').trigger('edd_quantity_updated', [ response.cart_quantity ]);
55
+
56
+ $('.cart_item.edd_subtotal span').html( response.subtotal );
57
+
58
+ if( response.cart_quantity == 0 ) {
59
+ $('.cart_item.edd_subtotal,.edd-cart-number-of-items,.cart_item.edd_checkout').hide();
60
+ $('.edd-cart').append('<li class="cart_item empty">' + edd_scripts.empty_cart_message + '</li>');
61
+ }
62
+
63
+ $('body').trigger('edd_cart_item_removed', [ response ]);
64
+ }
65
+ }
66
+ }).fail(function (response) {
67
+ if ( window.console && window.console.log ) {
68
+ console.log( response );
69
+ }
70
+ }).done(function (response) {
71
+
72
+ });
73
+
74
+ return false;
75
+ });
76
+
77
+ // Send Add to Cart request
78
+ $('body').on('click.eddAddToCart', '.edd-add-to-cart', function (e) {
79
+
80
+ e.preventDefault();
81
+
82
+ var $this = $(this), form = $this.closest('form');
83
+
84
+ var $spinner = $this.find('.edd-loading');
85
+ var container = $this.closest('div');
86
+
87
+ var spinnerWidth = $spinner.width(),
88
+ spinnerHeight = $spinner.height();
89
+
90
+ // Show the spinner
91
+ $this.attr('data-edd-loading', '');
92
+
93
+ $spinner.css({
94
+ 'margin-left': spinnerWidth / -2,
95
+ 'margin-top' : spinnerHeight / -2
96
+ });
97
+
98
+ var form = $this.parents('form').last();
99
+ var download = $this.data('download-id');
100
+ var variable_price = $this.data('variable-price');
101
+ var price_mode = $this.data('price-mode');
102
+ var item_price_ids = [];
103
+ var free_items = true;
104
+
105
+ if( variable_price == 'yes' ) {
106
+
107
+ if ( form.find('.edd_price_option_' + download).is('input:hidden') ) {
108
+ item_price_ids[0] = $('.edd_price_option_' + download, form).val();
109
+ } else {
110
+ if( ! form.find('.edd_price_option_' + download + ':checked', form).length ) {
111
+ // hide the spinner
112
+ $this.removeAttr( 'data-edd-loading' );
113
+ alert( edd_scripts.select_option );
114
+ return;
115
+ }
116
+
117
+ form.find('.edd_price_option_' + download + ':checked', form).each(function( index ) {
118
+ item_price_ids[ index ] = $(this).val();
119
+
120
+ // If we're still only at free items, check if this one is free also
121
+ if ( true === free_items ) {
122
+ var item_price = $(this).data('price');
123
+ if ( item_price && item_price > 0 ) {
124
+ // We now have a paid item, we can't use add_to_cart
125
+ free_items = false;
126
+ }
127
+ }
128
+
129
+ });
130
+ }
131
+
132
+ } else {
133
+ item_price_ids[0] = download;
134
+ if ( $this.data('price') && $this.data('price') > 0 ) {
135
+ free_items = false;
136
+ }
137
+ }
138
+
139
+ // If we've got nothing but free items being added, change to add_to_cart
140
+ if ( free_items ) {
141
+ form.find('.edd_action_input').val('add_to_cart');
142
+ }
143
+
144
+ if( 'straight_to_gateway' == form.find('.edd_action_input').val() ) {
145
+ form.submit();
146
+ return true; // Submit the form
147
+ }
148
+
149
+ var action = $this.data('action');
150
+ var data = {
151
+ action: action,
152
+ download_id: download,
153
+ price_ids : item_price_ids,
154
+ post_data: $(form).serialize()
155
+ };
156
+
157
+ $.ajax({
158
+ type: "POST",
159
+ data: data,
160
+ dataType: "json",
161
+ url: edd_scripts.ajaxurl,
162
+ xhrFields: {
163
+ withCredentials: true
164
+ },
165
+ success: function (response) {
166
+
167
+ if( edd_scripts.redirect_to_checkout == '1' ) {
168
+
169
+ window.location = edd_scripts.checkout_page;
170
+
171
+ } else {
172
+
173
+ // Add the new item to the cart widget
174
+ if ($('.cart_item.empty').length) {
175
+ $(response.cart_item).insertBefore('.cart_item.edd_subtotal');
176
+ $('.cart_item.edd_checkout,.cart_item.edd_subtotal').show();
177
+ $('.cart_item.empty').remove();
178
+ } else {
179
+ $(response.cart_item).insertBefore('.cart_item.edd_subtotal');
180
+ }
181
+
182
+ $('.cart_item.edd_subtotal span').html( response.subtotal );
183
+
184
+ // Update the cart quantity
185
+ var items_added = $( '.edd-cart-item-title', response.cart_item ).length;
186
+
187
+ $('span.edd-cart-quantity').each(function() {
188
+ $(this).text(response.cart_quantity);
189
+ $('body').trigger('edd_quantity_updated', [ response.cart_quantity ]);
190
+ });
191
+
192
+ // Show the "number of items in cart" message
193
+ if ( $('.edd-cart-number-of-items').css('display') == 'none') {
194
+ $('.edd-cart-number-of-items').show('slow');
195
+ }
196
+
197
+ if( variable_price == 'no' || price_mode != 'multi' ) {
198
+ // Switch purchase to checkout if a single price item or variable priced with radio buttons
199
+ $('a.edd-add-to-cart', container).toggle();
200
+ $('.edd_go_to_checkout', container).css('display', 'inline-block');
201
+ }
202
+
203
+ if ( price_mode == 'multi' ) {
204
+ // remove spinner for multi
205
+ $this.removeAttr( 'data-edd-loading' );
206
+ }
207
+
208
+ // Update all buttons for same download
209
+ if( $( '.edd_download_purchase_form' ).length && ( variable_price == 'no' || ! form.find('.edd_price_option_' + download).is('input:hidden') ) ) {
210
  var parent_form = $('.edd_download_purchase_form *[data-download-id="' + download + '"]').parents('form');
211
  $( 'a.edd-add-to-cart', parent_form ).hide();
212
+ if( price_mode != 'multi' ) {
213
+ parent_form.find('.edd_download_quantity_wrapper').slideUp();
214
+ }
215
+ $( '.edd_go_to_checkout', parent_form ).show().removeAttr( 'data-edd-loading' );
216
+ }
217
+
218
+ if( response != 'incart' ) {
219
+ // Show the added message
220
+ $('.edd-cart-added-alert', container).fadeIn();
221
+ setTimeout(function () {
222
+ $('.edd-cart-added-alert', container).fadeOut();
223
+ }, 3000);
224
+ }
225
 
226
+ $('body').trigger('edd_cart_item_added', [ response ]);
 
 
 
 
 
 
227
 
228
+ }
229
+ }
230
+ }).fail(function (response) {
231
+ if ( window.console && window.console.log ) {
232
+ console.log( response );
233
+ }
234
+ }).done(function (response) {
235
+
236
+ });
237
+
238
+ return false;
239
+ });
240
+
241
+ // Show the login form on the checkout page
242
+ $('#edd_checkout_form_wrap').on('click', '.edd_checkout_register_login', function () {
243
+ var $this = $(this),
244
+ data = {
245
+ action: $this.data('action')
246
+ };
247
+ // Show the ajax loader
248
+ $('.edd-cart-ajax').show();
249
 
250
+ $.post(edd_scripts.ajaxurl, data, function (checkout_response) {
251
+ $('#edd_checkout_login_register').html(edd_scripts.loading);
252
+ $('#edd_checkout_login_register').html(checkout_response);
253
+ // Hide the ajax loader
254
+ $('.edd-cart-ajax').hide();
255
+ });
256
+ return false;
257
+ });
258
 
259
+ // Process the login form via ajax
260
+ $(document).on('click', '#edd_purchase_form #edd_login_fields input[type=submit]', function(e) {
261
 
262
+ e.preventDefault();
 
263
 
264
+ var complete_purchase_val = $(this).val();
 
 
 
 
 
 
 
265
 
266
+ $(this).val(edd_global_vars.purchase_loading);
 
 
 
 
 
 
 
267
 
268
+ $(this).after('<span class="edd-cart-ajax"><i class="edd-icon-spinner edd-icon-spin"></i></span>');
 
269
 
270
+ var data = {
271
+ action : 'edd_process_checkout_login',
272
+ edd_ajax : 1,
273
+ edd_user_login : $('#edd_login_fields #edd_user_login').val(),
274
+ edd_user_pass : $('#edd_login_fields #edd_user_pass').val()
275
+ };
276
 
277
+ $.post(edd_global_vars.ajaxurl, data, function(data) {
278
 
279
+ if ( $.trim(data) == 'success' ) {
280
+ $('.edd_errors').remove();
281
+ window.location = edd_scripts.checkout_page;
282
+ } else {
283
+ $('#edd_login_fields input[type=submit]').val(complete_purchase_val);
284
+ $('.edd-cart-ajax').remove();
285
+ $('.edd_errors').remove();
286
+ $('#edd-user-login-submit').before(data);
287
+ }
288
+ });
289
 
290
+ });
291
 
292
+ // Load the fields for the selected payment method
293
+ $('select#edd-gateway, input.edd-gateway').change( function (e) {
 
 
 
 
294
 
295
+ var payment_mode = $('#edd-gateway option:selected, input.edd-gateway:checked').val();
296
 
297
+ if( payment_mode == '0' )
298
+ return false;
 
 
 
 
 
 
 
 
299
 
300
+ edd_load_gateway( payment_mode );
301
 
302
+ return false;
303
+ });
304
 
305
+ // Auto load first payment gateway
306
+ if( edd_scripts.is_checkout == '1' && $('select#edd-gateway, input.edd-gateway').length ) {
307
+ setTimeout( function() {
308
+ edd_load_gateway( edd_scripts.default_gateway );
309
+ }, 200);
310
+ }
311
 
312
+ $(document).on('click', '#edd_purchase_form #edd_purchase_submit input[type=submit]', function(e) {
 
313
 
314
+ var eddPurchaseform = document.getElementById('edd_purchase_form');
315
 
316
+ if( typeof eddPurchaseform.checkValidity === "function" && false === eddPurchaseform.checkValidity() ) {
317
+ return;
318
+ }
319
 
320
+ e.preventDefault();
 
 
 
 
 
321
 
322
+ var complete_purchase_val = $(this).val();
323
 
324
+ $(this).val(edd_global_vars.purchase_loading);
325
 
326
+ $(this).after('<span class="edd-cart-ajax"><i class="edd-icon-spinner edd-icon-spin"></i></span>');
327
 
328
+ $.post(edd_global_vars.ajaxurl, $('#edd_purchase_form').serialize() + '&action=edd_process_checkout&edd_ajax=true', function(data) {
329
+ if ( $.trim(data) == 'success' ) {
330
+ $('.edd_errors').remove();
331
+ $(eddPurchaseform).submit();
332
+ } else {
333
+ $('#edd-purchase-button').val(complete_purchase_val);
334
+ $('.edd-cart-ajax').remove();
335
+ $('.edd_errors').remove();
336
+ $('#edd_purchase_submit').before(data);
337
+ }
338
+ });
339
 
340
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
 
342
  });
343
 
344
  function edd_load_gateway( payment_mode ) {
345
 
346
+ // Show the ajax loader
347
+ jQuery('.edd-cart-ajax').show();
348
+ jQuery('#edd_purchase_form_wrap').html('<img src="' + edd_scripts.ajax_loader + '"/>');
349
 
350
+ jQuery.post(edd_scripts.ajaxurl + '?payment-mode=' + payment_mode, { action: 'edd_load_gateway', edd_payment_mode: payment_mode },
351
+ function(response){
352
+ jQuery('#edd_purchase_form_wrap').html(response);
353
+ jQuery('.edd-no-js').hide();
354
+ }
355
+ );
356
 
357
  }
assets/js/edd-ajax.min.js CHANGED
@@ -1 +1 @@
1
- function edd_load_gateway(e){jQuery(".edd-cart-ajax").show();jQuery("#edd_purchase_form_wrap").html('<img src="'+edd_scripts.ajax_loader+'"/>');jQuery.post(edd_scripts.ajaxurl+"?payment-mode="+e,{action:"edd_load_gateway",edd_payment_mode:e},function(e){jQuery("#edd_purchase_form_wrap").html(e);jQuery(".edd-no-js").hide()})}var edd_scripts;jQuery(document).ready(function(e){e(".edd-no-js").hide();e("a.edd-add-to-cart").addClass("edd-has-js");e("body").on("click.eddRemoveFromCart",".edd-remove-from-cart",function(t){var n=e(this),r=n.data("cart-item"),i=n.data("action"),s=n.data("download-id"),o={action:i,cart_item:r};e.ajax({type:"POST",data:o,dataType:"json",url:edd_scripts.ajaxurl,success:function(t){if(t.removed){if(parseInt(edd_scripts.position_in_cart,10)===parseInt(r,10)){window.location=window.location;return false}e(".edd-cart").find("[data-cart-item='"+r+"']").parent().remove();if(e("#edd_purchase_"+s).length){e("#edd_purchase_"+s+" .edd_go_to_checkout").hide();e("#edd_purchase_"+s+" a.edd-add-to-cart").show().removeAttr("data-edd-loading")}e("span.edd-cart-quantity").each(function(){var t=parseInt(e(this).text(),10)-1;if(t<1){t=0}e(this).text(t);e("body").trigger("edd_quantity_updated",[t])});e(".cart_item.edd_subtotal span").html(t.subtotal);if(!e(".edd-cart-item").length){e(".cart_item.edd_subtotal,.edd-cart-number-of-items,.cart_item.edd_checkout").hide();e(".edd-cart").append('<li class="cart_item empty">'+edd_scripts.empty_cart_message+"</li>")}e("body").trigger("edd_cart_item_removed",[t])}}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}}).done(function(e){});return false});e("body").on("click.eddAddToCart",".edd-add-to-cart",function(t){t.preventDefault();var n=e(this),r=n.closest("form");if("straight_to_gateway"==r.find(".edd_action_input").val()){r.submit();return true}var i=n.find(".edd-loading");var s=n.closest("div");var o=i.width(),u=i.height();n.attr("data-edd-loading","");i.css({"margin-left":o/-2,"margin-top":u/-2});var r=n.parents("form").last();var a=n.data("download-id");var f=n.data("variable-price");var l=n.data("price-mode");var c=[];if(f=="yes"){if(!e(".edd_price_option_"+a+":checked",r).length){n.removeAttr("data-edd-loading");alert(edd_scripts.select_option);return}e(".edd_price_option_"+a+":checked",r).each(function(t){c[t]=e(this).val()})}else{c[0]=a}var h=n.data("action");var p={action:h,download_id:a,price_ids:c,post_data:e(r).serialize()};e.ajax({type:"POST",data:p,dataType:"json",url:edd_scripts.ajaxurl,success:function(t){if(edd_scripts.redirect_to_checkout=="1"){window.location=edd_scripts.checkout_page}else{if(e(".cart_item.empty").length){e(t.cart_item).insertBefore(".cart_item.edd_subtotal");e(".cart_item.edd_checkout,.cart_item.edd_subtotal").show();e(".cart_item.empty").remove()}else{e(t.cart_item).insertBefore(".cart_item.edd_subtotal")}e(".cart_item.edd_subtotal span").html(t.subtotal);e("span.edd-cart-quantity").each(function(){var t=parseInt(e(this).text(),10)+1;e(this).text(t);e("body").trigger("edd_quantity_updated",[t])});if(e(".edd-cart-number-of-items").css("display")=="none"){e(".edd-cart-number-of-items").show("slow")}if(f=="no"||l!="multi"){e("a.edd-add-to-cart",s).toggle();e(".edd_go_to_checkout",s).css("display","inline-block")}if(l=="multi"){n.removeAttr("data-edd-loading")}if(e(".edd_download_purchase_form").length){var r=e('.edd_download_purchase_form *[data-download-id="'+a+'"]').parents("form");e("a.edd-add-to-cart",r).hide();e(".edd_go_to_checkout",r).show().removeAttr("data-edd-loading")}if(t!="incart"){e(".edd-cart-added-alert",s).fadeIn();setTimeout(function(){e(".edd-cart-added-alert",s).fadeOut()},3e3)}e("body").trigger("edd_cart_item_added",[t])}}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}}).done(function(e){});return false});e("#edd_checkout_form_wrap").on("click",".edd_checkout_register_login",function(){var t=e(this),n={action:t.data("action")};e(".edd-cart-ajax").show();e.post(edd_scripts.ajaxurl,n,function(t){e("#edd_checkout_login_register").html(edd_scripts.loading);e("#edd_checkout_login_register").html(t);e(".edd-cart-ajax").hide()});return false});e(document).on("click","#edd_purchase_form #edd_login_fields input[type=submit]",function(t){t.preventDefault();var n=e(this).val();e(this).val(edd_global_vars.purchase_loading);e(this).after('<span class="edd-cart-ajax"><i class="edd-icon-spinner edd-icon-spin"></i></span>');var r={action:"edd_process_checkout_login",edd_ajax:1,edd_user_login:e("#edd_login_fields #edd_user_login").val(),edd_user_pass:e("#edd_login_fields #edd_user_pass").val()};e.post(edd_global_vars.ajaxurl,r,function(t){if(e.trim(t)=="success"){e(".edd_errors").remove();window.location=edd_scripts.checkout_page}else{e("#edd_login_fields input[type=submit]").val(n);e(".edd-cart-ajax").remove();e(".edd_errors").remove();e("#edd-user-login-submit").before(t)}})});e("select#edd-gateway, input.edd-gateway").change(function(t){var n=e("#edd-gateway option:selected, input.edd-gateway:checked").val();if(n=="0")return false;edd_load_gateway(n);return false});if(edd_scripts.is_checkout=="1"&&e("select#edd-gateway, input.edd-gateway").length){setTimeout(function(){edd_load_gateway(edd_scripts.default_gateway)},200)}e(document).on("click","#edd_purchase_form #edd_purchase_submit input[type=submit]",function(t){t.preventDefault();var n=e(this).val();e(this).val(edd_global_vars.purchase_loading);e(this).after('<span class="edd-cart-ajax"><i class="edd-icon-spinner edd-icon-spin"></i></span>');e.post(edd_global_vars.ajaxurl,e("#edd_purchase_form").serialize()+"&action=edd_process_checkout&edd_ajax=true",function(t){if(e.trim(t)=="success"){e(".edd_errors").remove();e("#edd_purchase_form").submit()}else{e("#edd_purchase_form input[type=submit]").val(n);e(".edd-cart-ajax").remove();e(".edd_errors").remove();e("#edd_purchase_submit").before(t)}})})})
1
+ function edd_load_gateway(e){jQuery(".edd-cart-ajax").show(),jQuery("#edd_purchase_form_wrap").html('<img src="'+edd_scripts.ajax_loader+'"/>'),jQuery.post(edd_scripts.ajaxurl+"?payment-mode="+e,{action:"edd_load_gateway",edd_payment_mode:e},function(e){jQuery("#edd_purchase_form_wrap").html(e),jQuery(".edd-no-js").hide()})}var edd_scripts;jQuery(document).ready(function(e){e(".edd-no-js").hide(),e("a.edd-add-to-cart").addClass("edd-has-js"),e("body").on("click.eddRemoveFromCart",".edd-remove-from-cart",function(){var d=e(this),t=d.data("cart-item"),a=d.data("action"),i=d.data("download-id"),o={action:a,cart_item:t};return e.ajax({type:"POST",data:o,dataType:"json",url:edd_scripts.ajaxurl,xhrFields:{withCredentials:!0},success:function(d){if(d.removed){if(parseInt(edd_scripts.position_in_cart,10)===parseInt(t,10))return window.location=window.location,!1;e(".edd-cart").find("[data-cart-item='"+t+"']").parent().remove();var a=0;e(".edd-cart").find("[data-cart-item]").each(function(){e(this).attr("data-cart-item",a),a+=1}),e("#edd_purchase_"+i).length&&(e("#edd_purchase_"+i+" .edd_go_to_checkout").hide(),e("#edd_purchase_"+i+" a.edd-add-to-cart").show().removeAttr("data-edd-loading"),"1"==edd_scripts.quantities_enabled&&e("#edd_purchase_"+i+" .edd_download_quantity_wrapper").show()),e("span.edd-cart-quantity").text(d.cart_quantity),e("body").trigger("edd_quantity_updated",[d.cart_quantity]),e(".cart_item.edd_subtotal span").html(d.subtotal),0==d.cart_quantity&&(e(".cart_item.edd_subtotal,.edd-cart-number-of-items,.cart_item.edd_checkout").hide(),e(".edd-cart").append('<li class="cart_item empty">'+edd_scripts.empty_cart_message+"</li>")),e("body").trigger("edd_cart_item_removed",[d])}}}).fail(function(e){window.console&&window.console.log&&console.log(e)}).done(function(){}),!1}),e("body").on("click.eddAddToCart",".edd-add-to-cart",function(d){d.preventDefault();var t=e(this),a=t.closest("form"),i=t.find(".edd-loading"),o=t.closest("div"),r=i.width(),c=i.height();t.attr("data-edd-loading",""),i.css({"margin-left":r/-2,"margin-top":c/-2});var a=t.parents("form").last(),n=t.data("download-id"),s=t.data("variable-price"),_=t.data("price-mode"),l=[],u=!0;if("yes"==s)if(a.find(".edd_price_option_"+n).is("input:hidden"))l[0]=e(".edd_price_option_"+n,a).val();else{if(!a.find(".edd_price_option_"+n+":checked",a).length)return t.removeAttr("data-edd-loading"),void alert(edd_scripts.select_option);a.find(".edd_price_option_"+n+":checked",a).each(function(d){if(l[d]=e(this).val(),!0===u){var t=e(this).data("price");t&&t>0&&(u=!1)}})}else l[0]=n,t.data("price")&&t.data("price")>0&&(u=!1);if(u&&a.find(".edd_action_input").val("add_to_cart"),"straight_to_gateway"==a.find(".edd_action_input").val())return a.submit(),!0;var p=t.data("action"),m={action:p,download_id:n,price_ids:l,post_data:e(a).serialize()};return e.ajax({type:"POST",data:m,dataType:"json",url:edd_scripts.ajaxurl,xhrFields:{withCredentials:!0},success:function(d){if("1"==edd_scripts.redirect_to_checkout)window.location=edd_scripts.checkout_page;else{e(".cart_item.empty").length?(e(d.cart_item).insertBefore(".cart_item.edd_subtotal"),e(".cart_item.edd_checkout,.cart_item.edd_subtotal").show(),e(".cart_item.empty").remove()):e(d.cart_item).insertBefore(".cart_item.edd_subtotal"),e(".cart_item.edd_subtotal span").html(d.subtotal);{e(".edd-cart-item-title",d.cart_item).length}if(e("span.edd-cart-quantity").each(function(){e(this).text(d.cart_quantity),e("body").trigger("edd_quantity_updated",[d.cart_quantity])}),"none"==e(".edd-cart-number-of-items").css("display")&&e(".edd-cart-number-of-items").show("slow"),("no"==s||"multi"!=_)&&(e("a.edd-add-to-cart",o).toggle(),e(".edd_go_to_checkout",o).css("display","inline-block")),"multi"==_&&t.removeAttr("data-edd-loading"),e(".edd_download_purchase_form").length&&("no"==s||!a.find(".edd_price_option_"+n).is("input:hidden"))){var i=e('.edd_download_purchase_form *[data-download-id="'+n+'"]').parents("form");e("a.edd-add-to-cart",i).hide(),"multi"!=_&&i.find(".edd_download_quantity_wrapper").slideUp(),e(".edd_go_to_checkout",i).show().removeAttr("data-edd-loading")}"incart"!=d&&(e(".edd-cart-added-alert",o).fadeIn(),setTimeout(function(){e(".edd-cart-added-alert",o).fadeOut()},3e3)),e("body").trigger("edd_cart_item_added",[d])}}}).fail(function(e){window.console&&window.console.log&&console.log(e)}).done(function(){}),!1}),e("#edd_checkout_form_wrap").on("click",".edd_checkout_register_login",function(){var d=e(this),t={action:d.data("action")};return e(".edd-cart-ajax").show(),e.post(edd_scripts.ajaxurl,t,function(d){e("#edd_checkout_login_register").html(edd_scripts.loading),e("#edd_checkout_login_register").html(d),e(".edd-cart-ajax").hide()}),!1}),e(document).on("click","#edd_purchase_form #edd_login_fields input[type=submit]",function(d){d.preventDefault();var t=e(this).val();e(this).val(edd_global_vars.purchase_loading),e(this).after('<span class="edd-cart-ajax"><i class="edd-icon-spinner edd-icon-spin"></i></span>');var a={action:"edd_process_checkout_login",edd_ajax:1,edd_user_login:e("#edd_login_fields #edd_user_login").val(),edd_user_pass:e("#edd_login_fields #edd_user_pass").val()};e.post(edd_global_vars.ajaxurl,a,function(d){"success"==e.trim(d)?(e(".edd_errors").remove(),window.location=edd_scripts.checkout_page):(e("#edd_login_fields input[type=submit]").val(t),e(".edd-cart-ajax").remove(),e(".edd_errors").remove(),e("#edd-user-login-submit").before(d))})}),e("select#edd-gateway, input.edd-gateway").change(function(){var d=e("#edd-gateway option:selected, input.edd-gateway:checked").val();return"0"==d?!1:(edd_load_gateway(d),!1)}),"1"==edd_scripts.is_checkout&&e("select#edd-gateway, input.edd-gateway").length&&setTimeout(function(){edd_load_gateway(edd_scripts.default_gateway)},200),e(document).on("click","#edd_purchase_form #edd_purchase_submit input[type=submit]",function(d){var t=document.getElementById("edd_purchase_form");if("function"!=typeof t.checkValidity||!1!==t.checkValidity()){d.preventDefault();var a=e(this).val();e(this).val(edd_global_vars.purchase_loading),e(this).after('<span class="edd-cart-ajax"><i class="edd-icon-spinner edd-icon-spin"></i></span>'),e.post(edd_global_vars.ajaxurl,e("#edd_purchase_form").serialize()+"&action=edd_process_checkout&edd_ajax=true",function(d){"success"==e.trim(d)?(e(".edd_errors").remove(),e(t).submit()):(e("#edd-purchase-button").val(a),e(".edd-cart-ajax").remove(),e(".edd_errors").remove(),e("#edd_purchase_submit").before(d))})}})});
assets/js/edd-checkout-global.js CHANGED
@@ -1,5 +1,6 @@
1
  jQuery(document).ready(function($) {
2
  var $body = $('body'),
 
3
  $edd_cart_amount = $('.edd_cart_amount');
4
 
5
  // Update state/province field on checkout page
@@ -18,13 +19,16 @@ jQuery(document).ready(function($) {
18
  type: "POST",
19
  data: postData,
20
  url: edd_global_vars.ajaxurl,
 
 
 
21
  success: function (response) {
22
- if( 'nostates' == response ) {
23
- var text_field = '<input type="text" name="card_state" class="cart-state edd-input required" value=""/>';
24
- $this.parent().next().find('input,select').replaceWith( text_field );
25
- } else {
26
- $this.parent().next().find('input,select').replaceWith( response );
27
- }
28
  $('body').trigger('edd_cart_billing_address_updated', [ response ]);
29
  }
30
  }).fail(function (data) {
@@ -62,8 +66,11 @@ jQuery(document).ready(function($) {
62
  data: postData,
63
  dataType: "json",
64
  url: edd_global_vars.ajaxurl,
 
 
 
65
  success: function (tax_response) {
66
- $('#edd_checkout_cart').replaceWith(tax_response.html);
67
  $('.edd_cart_amount').html(tax_response.total);
68
  var tax_data = new Object();
69
  tax_data.postdata = postData;
@@ -79,7 +86,7 @@ jQuery(document).ready(function($) {
79
 
80
  /* Credit card verification */
81
 
82
- $body.on('keyup', '.edd-do-validate .card-number', function() {
83
  edd_validate_card( $(this) );
84
  });
85
 
@@ -140,7 +147,8 @@ jQuery(document).ready(function($) {
140
 
141
  var postData = {
142
  action: 'edd_apply_discount',
143
- code: discount_code
 
144
  };
145
 
146
  $('#edd-discount-error-wrap').html('').hide();
@@ -151,6 +159,9 @@ jQuery(document).ready(function($) {
151
  data: postData,
152
  dataType: "json",
153
  url: edd_global_vars.ajaxurl,
 
 
 
154
  success: function (discount_response) {
155
  if( discount_response ) {
156
  if (discount_response.msg == 'valid') {
@@ -171,7 +182,6 @@ jQuery(document).ready(function($) {
171
  } else {
172
 
173
  $('#edd_cc_fields,#edd_cc_address').slideDown();
174
- $('input[name="edd-gateway"]').val( 'manual' );
175
 
176
  }
177
 
@@ -206,6 +216,13 @@ jQuery(document).ready(function($) {
206
  }
207
  });
208
 
 
 
 
 
 
 
 
209
  // Remove a discount
210
  $body.on('click', '.edd_discount_remove', function (event) {
211
 
@@ -219,6 +236,9 @@ jQuery(document).ready(function($) {
219
  data: postData,
220
  dataType: "json",
221
  url: edd_global_vars.ajaxurl,
 
 
 
222
  success: function (discount_response) {
223
 
224
  $('.edd_cart_amount').each(function() {
@@ -251,10 +271,11 @@ jQuery(document).ready(function($) {
251
  return false;
252
  });
253
 
 
254
  $body.on('click', '.edd_discount_link', function(e) {
255
  e.preventDefault();
256
  $('.edd_discount_link').parent().hide();
257
- $('#edd-discount-code-wrap').show();
258
  });
259
 
260
  // Hide / show discount fields for browsers without javascript enabled
@@ -262,16 +283,19 @@ jQuery(document).ready(function($) {
262
  $body.find('#edd_show_discount').show();
263
 
264
  // Update the checkout when item quantities are updated
265
- $('#edd_checkout_cart').on('change', '.edd-item-quantity', function (event) {
266
 
267
  var $this = $(this),
268
  quantity = $this.val(),
269
- download_id = $this.closest('tr.edd_cart_item').data('download-id');
 
 
270
 
271
  var postData = {
272
  action: 'edd_update_quantity',
273
  quantity: quantity,
274
- download_id: download_id
 
275
  };
276
 
277
  //edd_discount_loader.show();
@@ -281,8 +305,21 @@ jQuery(document).ready(function($) {
281
  data: postData,
282
  dataType: "json",
283
  url: edd_global_vars.ajaxurl,
 
 
 
284
  success: function (response) {
285
- $('.edd_cart_amount').each(function() {
 
 
 
 
 
 
 
 
 
 
286
  $(this).text(response.total);
287
  $('body').trigger('edd_quantity_updated', [ response ]);
288
  });
1
  jQuery(document).ready(function($) {
2
  var $body = $('body'),
3
+ $form = $("#edd_purchase_form"),
4
  $edd_cart_amount = $('.edd_cart_amount');
5
 
6
  // Update state/province field on checkout page
19
  type: "POST",
20
  data: postData,
21
  url: edd_global_vars.ajaxurl,
22
+ xhrFields: {
23
+ withCredentials: true
24
+ },
25
  success: function (response) {
26
+ if( 'nostates' == response ) {
27
+ var text_field = '<input type="text" name="card_state" class="cart-state edd-input required" value=""/>';
28
+ $form.find('input[name="card_state"], select[name="card_state"]').replaceWith( text_field );
29
+ } else {
30
+ $form.find('input[name="card_state"], select[name="card_state"]').replaceWith( response );
31
+ }
32
  $('body').trigger('edd_cart_billing_address_updated', [ response ]);
33
  }
34
  }).fail(function (data) {
66
  data: postData,
67
  dataType: "json",
68
  url: edd_global_vars.ajaxurl,
69
+ xhrFields: {
70
+ withCredentials: true
71
+ },
72
  success: function (tax_response) {
73
+ $('#edd_checkout_cart_form').replaceWith(tax_response.html);
74
  $('.edd_cart_amount').html(tax_response.total);
75
  var tax_data = new Object();
76
  tax_data.postdata = postData;
86
 
87
  /* Credit card verification */
88
 
89
+ $body.on('keyup change', '.edd-do-validate .card-number', function() {
90
  edd_validate_card( $(this) );
91
  });
92
 
147
 
148
  var postData = {
149
  action: 'edd_apply_discount',
150
+ code: discount_code,
151
+ form: $( '#edd_purchase_form' ).serialize()
152
  };
153
 
154
  $('#edd-discount-error-wrap').html('').hide();
159
  data: postData,
160
  dataType: "json",
161
  url: edd_global_vars.ajaxurl,
162
+ xhrFields: {
163
+ withCredentials: true
164
+ },
165
  success: function (discount_response) {
166
  if( discount_response ) {
167
  if (discount_response.msg == 'valid') {
182
  } else {
183
 
184
  $('#edd_cc_fields,#edd_cc_address').slideDown();
 
185
 
186
  }
187
 
216
  }
217
  });
218
 
219
+ // Apply the discount when hitting Enter in the discount field instead
220
+ $checkout_form_wrap.on('keyup', '#edd-discount', function (event) {
221
+ if (event.keyCode == '13') {
222
+ $checkout_form_wrap.find('.edd-apply-discount').trigger('click');
223
+ }
224
+ });
225
+
226
  // Remove a discount
227
  $body.on('click', '.edd_discount_remove', function (event) {
228
 
236
  data: postData,
237
  dataType: "json",
238
  url: edd_global_vars.ajaxurl,
239
+ xhrFields: {
240
+ withCredentials: true
241
+ },
242
  success: function (discount_response) {
243
 
244
  $('.edd_cart_amount').each(function() {
271
  return false;
272
  });
273
 
274
+ // When discount link is clicked, hide the link, then show the discount input and set focus.
275
  $body.on('click', '.edd_discount_link', function(e) {
276
  e.preventDefault();
277
  $('.edd_discount_link').parent().hide();
278
+ $('#edd-discount-code-wrap').show().find('#edd-discount').focus();
279
  });
280
 
281
  // Hide / show discount fields for browsers without javascript enabled
283
  $body.find('#edd_show_discount').show();
284
 
285
  // Update the checkout when item quantities are updated
286
+ $(document).on('change', '.edd-item-quantity', function (event) {
287
 
288
  var $this = $(this),
289
  quantity = $this.val(),
290
+ key = $this.data('key'),
291
+ download_id = $this.closest('tr.edd_cart_item').data('download-id'),
292
+ options = $this.parent().find('input[name="edd-cart-download-' + key + '-options"]').val();
293
 
294
  var postData = {
295
  action: 'edd_update_quantity',
296
  quantity: quantity,
297
+ download_id: download_id,
298
+ options: options
299
  };
300
 
301
  //edd_discount_loader.show();
305
  data: postData,
306
  dataType: "json",
307
  url: edd_global_vars.ajaxurl,
308
+ xhrFields: {
309
+ withCredentials: true
310
+ },
311
  success: function (response) {
312
+
313
+ console.log( response );
314
+ $('.edd_cart_subtotal_amount').each(function() {
315
+ $(this).text(response.subtotal);
316
+ });
317
+
318
+ $('.edd_cart_tax_amount').each(function() {
319
+ $(this).text(response.taxes);
320
+ });
321
+
322
+ $('.edd_cart_amount').each(function() {
323
  $(this).text(response.total);
324
  $('body').trigger('edd_quantity_updated', [ response ]);
325
  });
assets/js/edd-checkout-global.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(e){function r(t){if("1"!=edd_global_vars.taxes_enabled)return;var n=e("#edd_cc_address");if(!t){t=n.find("#card_state").val()}var r={action:"edd_recalculate_taxes",billing_country:n.find("#billing_country").val(),state:t};e.ajax({type:"POST",data:r,dataType:"json",url:edd_global_vars.ajaxurl,success:function(t){e("#edd_checkout_cart").replaceWith(t.html);e(".edd_cart_amount").html(t.total);var n=new Object;n.postdata=r;n.response=t;e("body").trigger("edd_taxes_recalculated",[n])}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}})}function i(t){var n=t;n.validateCreditCard(function(t){var r=e(".card-type");if(t.card_type==null){r.removeClass().addClass("off card-type");n.removeClass("valid");n.addClass("error")}else{r.removeClass("off");r.addClass(t.card_type.name);if(t.length_valid&&t.luhn_valid){n.addClass("valid");n.removeClass("error")}else{n.removeClass("valid");n.addClass("error")}}})}var t=e("body"),n=e(".edd_cart_amount");t.on("change","#edd_cc_address input.card_state, #edd_cc_address select",function(){var t=e(this);if("card_state"!=t.attr("id")){var n={action:"edd_get_shop_states",country:t.val(),field_name:"card_state"};e.ajax({type:"POST",data:n,url:edd_global_vars.ajaxurl,success:function(n){if("nostates"==n){var r='<input type="text" name="card_state" class="cart-state edd-input required" value=""/>';t.parent().next().find("input,select").replaceWith(r)}else{t.parent().next().find("input,select").replaceWith(n)}e("body").trigger("edd_cart_billing_address_updated",[n])}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}}).done(function(e){r()})}else{r()}return false});t.on("keyup",".edd-do-validate .card-number",function(){i(e(this))});t.on("submit","#edd_payment_mode",function(){var t=e("#edd-gateway option:selected").val();if(t==0){alert(edd_global_vars.no_gateway);return false}});t.on("click","#edd_payment_mode_select input",function(){e("#edd_payment_mode_select label.edd-gateway-option-selected").removeClass("edd-gateway-option-selected");e("#edd_payment_mode_select input:checked").parent().addClass("edd-gateway-option-selected")});var s=n.text(),o=e("#edd_checkout_form_wrap");o.on("click",".edd-apply-discount",function(t){t.preventDefault();var n=e(this),i=e("#edd-discount").val(),s=e("#edd-discount-loader");if(i==""||i==edd_global_vars.enter_discount){return false}var u={action:"edd_apply_discount",code:i};e("#edd-discount-error-wrap").html("").hide();s.show();e.ajax({type:"POST",data:u,dataType:"json",url:edd_global_vars.ajaxurl,success:function(t){if(t){if(t.msg=="valid"){e(".edd_cart_discount").html(t.html);e(".edd_cart_discount_row").show();e(".edd_cart_amount").each(function(){e(this).text(t.total)});e("#edd-discount",o).val("");r();if("0.00"==t.total_plain){e("#edd_cc_fields,#edd_cc_address").slideUp();e('input[name="edd-gateway"]').val("manual")}else{e("#edd_cc_fields,#edd_cc_address").slideDown();e('input[name="edd-gateway"]').val("manual")}e("body").trigger("edd_discount_applied",[t])}else{e("#edd-discount-error-wrap").html('<span class="edd_error">'+t.msg+"</span>");e("#edd-discount-error-wrap").show();e("body").trigger("edd_discount_invalid",[t])}}else{if(window.console&&window.console.log){console.log(t)}e("body").trigger("edd_discount_failed",[t])}s.hide()}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}});return false});o.on("keypress","#edd-discount",function(e){if(e.keyCode=="13"){return false}});t.on("click",".edd_discount_remove",function(t){var n=e(this),i={action:"edd_remove_discount",code:n.data("code")};e.ajax({type:"POST",data:i,dataType:"json",url:edd_global_vars.ajaxurl,success:function(t){e(".edd_cart_amount").each(function(){if(edd_global_vars.currency_sign+"0.00"==e(this).text()||"0.00"+edd_global_vars.currency_sign==e(this).text()){window.location.reload()}e(this).text(t.total)});e(".edd_cart_discount").html(t.html);if(!t.discounts){e(".edd_cart_discount_row").hide()}r();e("#edd_cc_fields,#edd_cc_address").slideDown();e("body").trigger("edd_discount_removed",[t])}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}});return false});t.on("click",".edd_discount_link",function(t){t.preventDefault();e(".edd_discount_link").parent().hide();e("#edd-discount-code-wrap").show()});t.find("#edd-discount-code-wrap").hide();t.find("#edd_show_discount").show();e("#edd_checkout_cart").on("change",".edd-item-quantity",function(t){var n=e(this),r=n.val(),i=n.closest("tr.edd_cart_item").data("download-id");var s={action:"edd_update_quantity",quantity:r,download_id:i};e.ajax({type:"POST",data:s,dataType:"json",url:edd_global_vars.ajaxurl,success:function(t){e(".edd_cart_amount").each(function(){e(this).text(t.total);e("body").trigger("edd_quantity_updated",[t])})}}).fail(function(e){if(window.console&&window.console.log){console.log(e)}});return false})})
1
+ jQuery(document).ready(function(e){function d(d){if("1"==edd_global_vars.taxes_enabled){var t=e("#edd_cc_address");d||(d=t.find("#card_state").val());var a={action:"edd_recalculate_taxes",billing_country:t.find("#billing_country").val(),state:d};e.ajax({type:"POST",data:a,dataType:"json",url:edd_global_vars.ajaxurl,xhrFields:{withCredentials:!0},success:function(d){e("#edd_checkout_cart_form").replaceWith(d.html),e(".edd_cart_amount").html(d.total);var t=new Object;t.postdata=a,t.response=d,e("body").trigger("edd_taxes_recalculated",[t])}}).fail(function(e){window.console&&window.console.log&&console.log(e)})}}function t(d){var t=d;t.validateCreditCard(function(d){var a=e(".card-type");null==d.card_type?(a.removeClass().addClass("off card-type"),t.removeClass("valid"),t.addClass("error")):(a.removeClass("off"),a.addClass(d.card_type.name),d.length_valid&&d.luhn_valid?(t.addClass("valid"),t.removeClass("error")):(t.removeClass("valid"),t.addClass("error")))})}var a=e("body"),o=e("#edd_purchase_form"),n=e(".edd_cart_amount");a.on("change","#edd_cc_address input.card_state, #edd_cc_address select",function(){var t=e(this);if("card_state"!=t.attr("id")){var a={action:"edd_get_shop_states",country:t.val(),field_name:"card_state"};e.ajax({type:"POST",data:a,url:edd_global_vars.ajaxurl,xhrFields:{withCredentials:!0},success:function(d){if("nostates"==d){var t='<input type="text" name="card_state" class="cart-state edd-input required" value=""/>';o.find('input[name="card_state"], select[name="card_state"]').replaceWith(t)}else o.find('input[name="card_state"], select[name="card_state"]').replaceWith(d);e("body").trigger("edd_cart_billing_address_updated",[d])}}).fail(function(e){window.console&&window.console.log&&console.log(e)}).done(function(){d()})}else d();return!1}),a.on("keyup change",".edd-do-validate .card-number",function(){t(e(this))}),a.on("submit","#edd_payment_mode",function(){var d=e("#edd-gateway option:selected").val();return 0==d?(alert(edd_global_vars.no_gateway),!1):void 0}),a.on("click","#edd_payment_mode_select input",function(){e("#edd_payment_mode_select label.edd-gateway-option-selected").removeClass("edd-gateway-option-selected"),e("#edd_payment_mode_select input:checked").parent().addClass("edd-gateway-option-selected")});var s=(n.text(),e("#edd_checkout_form_wrap"));s.on("click",".edd-apply-discount",function(t){t.preventDefault();var a=(e(this),e("#edd-discount").val()),o=e("#edd-discount-loader");if(""==a||a==edd_global_vars.enter_discount)return!1;var n={action:"edd_apply_discount",code:a,form:e("#edd_purchase_form").serialize()};return e("#edd-discount-error-wrap").html("").hide(),o.show(),e.ajax({type:"POST",data:n,dataType:"json",url:edd_global_vars.ajaxurl,xhrFields:{withCredentials:!0},success:function(t){t?"valid"==t.msg?(e(".edd_cart_discount").html(t.html),e(".edd_cart_discount_row").show(),e(".edd_cart_amount").each(function(){e(this).text(t.total)}),e("#edd-discount",s).val(""),d(),"0.00"==t.total_plain?(e("#edd_cc_fields,#edd_cc_address").slideUp(),e('input[name="edd-gateway"]').val("manual")):e("#edd_cc_fields,#edd_cc_address").slideDown(),e("body").trigger("edd_discount_applied",[t])):(e("#edd-discount-error-wrap").html('<span class="edd_error">'+t.msg+"</span>"),e("#edd-discount-error-wrap").show(),e("body").trigger("edd_discount_invalid",[t])):(window.console&&window.console.log&&console.log(t),e("body").trigger("edd_discount_failed",[t])),o.hide()}}).fail(function(e){window.console&&window.console.log&&console.log(e)}),!1}),s.on("keypress","#edd-discount",function(e){return"13"==e.keyCode?!1:void 0}),s.on("keyup","#edd-discount",function(e){"13"==e.keyCode&&s.find(".edd-apply-discount").trigger("click")}),a.on("click",".edd_discount_remove",function(){var t=e(this),a={action:"edd_remove_discount",code:t.data("code")};return e.ajax({type:"POST",data:a,dataType:"json",url:edd_global_vars.ajaxurl,xhrFields:{withCredentials:!0},success:function(t){e(".edd_cart_amount").each(function(){(edd_global_vars.currency_sign+"0.00"==e(this).text()||"0.00"+edd_global_vars.currency_sign==e(this).text())&&window.location.reload(),e(this).text(t.total)}),e(".edd_cart_discount").html(t.html),t.discounts||e(".edd_cart_discount_row").hide(),d(),e("#edd_cc_fields,#edd_cc_address").slideDown(),e("body").trigger("edd_discount_removed",[t])}}).fail(function(e){window.console&&window.console.log&&console.log(e)}),!1}),a.on("click",".edd_discount_link",function(d){d.preventDefault(),e(".edd_discount_link").parent().hide(),e("#edd-discount-code-wrap").show().find("#edd-discount").focus()}),a.find("#edd-discount-code-wrap").hide(),a.find("#edd_show_discount").show(),e(document).on("change",".edd-item-quantity",function(){var d=e(this),t=d.val(),a=d.data("key"),o=d.closest("tr.edd_cart_item").data("download-id"),n=d.parent().find('input[name="edd-cart-download-'+a+'-options"]').val(),s={action:"edd_update_quantity",quantity:t,download_id:o,options:n};return e.ajax({type:"POST",data:s,dataType:"json",url:edd_global_vars.ajaxurl,xhrFields:{withCredentials:!0},success:function(d){console.log(d),e(".edd_cart_subtotal_amount").each(function(){e(this).text(d.subtotal)}),e(".edd_cart_tax_amount").each(function(){e(this).text(d.taxes)}),e(".edd_cart_amount").each(function(){e(this).text(d.total),e("body").trigger("edd_quantity_updated",[d])})}}).fail(function(e){window.console&&window.console.log&&console.log(e)}),!1})});
assets/js/jquery.creditCardValidator.js CHANGED
@@ -4,16 +4,6 @@
4
  jQuery Credit Card Validator
5
 
6
  Copyright 2012 Pawel Decowski
7
-
8
- This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
9
- Unported License. To view a copy of this license, visit:
10
-
11
- http://creativecommons.org/licenses/by-sa/3.0/
12
-
13
- or send a letter to:
14
-
15
- Creative Commons, 444 Castro Street, Suite 900,
16
- Mountain View, California, 94041, USA.
17
  */
18
 
19
 
4
  jQuery Credit Card Validator
5
 
6
  Copyright 2012 Pawel Decowski
 
 
 
 
 
 
 
 
 
 
7
  */
8
 
9
 
assets/sample-products-import.xml CHANGED
@@ -18,11 +18,11 @@
18
 
19
  <!-- generator="WordPress/3.5.1" created="2013-01-25 17:58" -->
20
  <rss version="2.0"
21
- xmlns:excerpt="http://wordpress.org/export/1.2/excerpt/"
22
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
23
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
24
  xmlns:dc="http://purl.org/dc/elements/1.1/"
25
- xmlns:wp="http://wordpress.org/export/1.2/"
26
  >
27
 
28
  <channel>
@@ -49,7 +49,7 @@
49
  <wp:term><wp:term_id>8</wp:term_id><wp:term_taxonomy>download_tag</wp:term_taxonomy><wp:term_slug>tag4</wp:term_slug><wp:term_parent></wp:term_parent><wp:term_name><![CDATA[Tag4]]></wp:term_name></wp:term>
50
  <wp:term><wp:term_id>6</wp:term_id><wp:term_taxonomy>nav_menu</wp:term_taxonomy><wp:term_slug>main-nav</wp:term_slug><wp:term_name><![CDATA[Main Nav]]></wp:term_name></wp:term>
51
 
52
- <generator>http://wordpress.org/?v=3.5.1</generator>
53
 
54
  <item>
55
  <title>A Sample Digital Download</title>
18
 
19
  <!-- generator="WordPress/3.5.1" created="2013-01-25 17:58" -->
20
  <rss version="2.0"
21
+ xmlns:excerpt="https://wordpress.org/export/1.2/excerpt/"
22
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
23
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
24
  xmlns:dc="http://purl.org/dc/elements/1.1/"
25
+ xmlns:wp="https://wordpress.org/export/1.2/"
26
  >
27
 
28
  <channel>
49
  <wp:term><wp:term_id>8</wp:term_id><wp:term_taxonomy>download_tag</wp:term_taxonomy><wp:term_slug>tag4</wp:term_slug><wp:term_parent></wp:term_parent><wp:term_name><![CDATA[Tag4]]></wp:term_name></wp:term>
50
  <wp:term><wp:term_id>6</wp:term_id><wp:term_taxonomy>nav_menu</wp:term_taxonomy><wp:term_slug>main-nav</wp:term_slug><wp:term_name><![CDATA[Main Nav]]></wp:term_name></wp:term>
51
 
52
+ <generator>https://wordpress.org/?v=3.5.1</generator>
53
 
54
  <item>
55
  <title>A Sample Digital Download</title>
easy-digital-downloads.php CHANGED
@@ -5,7 +5,7 @@
5
  * Description: Serve Digital Downloads Through WordPress
6
  * Author: Pippin Williamson
7
  * Author URI: http://pippinsplugins.com
8
- * Version: 2.0.1
9
  * Text Domain: edd
10
  * Domain Path: languages
11
  *
@@ -25,7 +25,7 @@
25
  * @package EDD
26
  * @category Core
27
  * @author Pippin Williamson
28
- * @version 2.0.1
29
  */
30
 
31
  // Exit if accessed directly
@@ -47,6 +47,14 @@ final class Easy_Digital_Downloads {
47
  */
48
  private static $instance;
49
 
 
 
 
 
 
 
 
 
50
  /**
51
  * EDD Cart Fees Object
52
  *
@@ -82,6 +90,14 @@ final class Easy_Digital_Downloads {
82
  */
83
  public $html;
84
 
 
 
 
 
 
 
 
 
85
  /**
86
  * EDD Email Template Tags Object
87
  *
@@ -90,6 +106,14 @@ final class Easy_Digital_Downloads {
90
  */
91
  public $email_tags;
92
 
 
 
 
 
 
 
 
 
93
  /**
94
  * Main Easy_Digital_Downloads Instance
95
  *
@@ -109,14 +133,18 @@ final class Easy_Digital_Downloads {
109
  if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Easy_Digital_Downloads ) ) {
110
  self::$instance = new Easy_Digital_Downloads;
111
  self::$instance->setup_constants();
 
 
 
112
  self::$instance->includes();
113
- self::$instance->load_textdomain();
114
  self::$instance->roles = new EDD_Roles();
115
  self::$instance->fees = new EDD_Fees();
116
  self::$instance->api = new EDD_API();
117
  self::$instance->session = new EDD_Session();
118
  self::$instance->html = new EDD_HTML_Elements();
 
119
  self::$instance->email_tags = new EDD_Email_Template_Tags();
 
120
  }
121
  return self::$instance;
122
  }
@@ -156,10 +184,10 @@ final class Easy_Digital_Downloads {
156
  * @return void
157
  */
158
  private function setup_constants() {
159
-
160
  // Plugin version
161
  if ( ! defined( 'EDD_VERSION' ) ) {
162
- define( 'EDD_VERSION', '2.0.1' );
163
  }
164
 
165
  // Plugin Folder Path
@@ -176,6 +204,11 @@ final class Easy_Digital_Downloads {
176
  if ( ! defined( 'EDD_PLUGIN_FILE' ) ) {
177
  define( 'EDD_PLUGIN_FILE', __FILE__ );
178
  }
 
 
 
 
 
179
  }
180
 
181
  /**
@@ -192,7 +225,9 @@ final class Easy_Digital_Downloads {
192
  $edd_options = edd_get_settings();
193
 
194
  require_once EDD_PLUGIN_DIR . 'includes/actions.php';
195
- require_once EDD_PLUGIN_DIR . 'includes/deprecated-functions.php';
 
 
196
  require_once EDD_PLUGIN_DIR . 'includes/ajax-functions.php';
197
  require_once EDD_PLUGIN_DIR . 'includes/template-functions.php';
198
  require_once EDD_PLUGIN_DIR . 'includes/checkout/template.php';
@@ -201,7 +236,14 @@ final class Easy_Digital_Downloads {
201
  require_once EDD_PLUGIN_DIR . 'includes/cart/template.php';
202
  require_once EDD_PLUGIN_DIR . 'includes/cart/actions.php';
203
  require_once EDD_PLUGIN_DIR . 'includes/class-edd-api.php';
 
 
 
 
204
  require_once EDD_PLUGIN_DIR . 'includes/class-edd-cache-helper.php';
 
 
 
205
  require_once EDD_PLUGIN_DIR . 'includes/class-edd-cron.php';
206
  require_once EDD_PLUGIN_DIR . 'includes/class-edd-fees.php';
207
  require_once EDD_PLUGIN_DIR . 'includes/class-edd-html-elements.php';
@@ -228,10 +270,11 @@ final class Easy_Digital_Downloads {
228
  require_once EDD_PLUGIN_DIR . 'includes/scripts.php';
229
  require_once EDD_PLUGIN_DIR . 'includes/post-types.php';
230
  require_once EDD_PLUGIN_DIR . 'includes/plugin-compatibility.php';
 
 
231
  require_once EDD_PLUGIN_DIR . 'includes/emails/functions.php';
232
  require_once EDD_PLUGIN_DIR . 'includes/emails/template.php';
233
  require_once EDD_PLUGIN_DIR . 'includes/emails/actions.php';
234
- require_once EDD_PLUGIN_DIR . 'includes/emails/email-tags.php';
235
  require_once EDD_PLUGIN_DIR . 'includes/error-tracking.php';
236
  require_once EDD_PLUGIN_DIR . 'includes/user-functions.php';
237
  require_once EDD_PLUGIN_DIR . 'includes/query-filters.php';
@@ -244,13 +287,16 @@ final class Easy_Digital_Downloads {
244
  require_once EDD_PLUGIN_DIR . 'includes/admin/add-ons.php';
245
  require_once EDD_PLUGIN_DIR . 'includes/admin/admin-footer.php';
246
  require_once EDD_PLUGIN_DIR . 'includes/admin/admin-actions.php';
247
- require_once EDD_PLUGIN_DIR . 'includes/admin/admin-notices.php';
248
  require_once EDD_PLUGIN_DIR . 'includes/admin/admin-pages.php';
249
  require_once EDD_PLUGIN_DIR . 'includes/admin/dashboard-widgets.php';
250
  require_once EDD_PLUGIN_DIR . 'includes/admin/export-functions.php';
251
  require_once EDD_PLUGIN_DIR . 'includes/admin/thickbox.php';
252
  require_once EDD_PLUGIN_DIR . 'includes/admin/upload-functions.php';
253
  require_once EDD_PLUGIN_DIR . 'includes/admin/downloads/dashboard-columns.php';
 
 
 
254
  require_once EDD_PLUGIN_DIR . 'includes/admin/downloads/metabox.php';
255
  require_once EDD_PLUGIN_DIR . 'includes/admin/downloads/contextual-help.php';
256
  require_once EDD_PLUGIN_DIR . 'includes/admin/discounts/contextual-help.php';
5
  * Description: Serve Digital Downloads Through WordPress
6
  * Author: Pippin Williamson
7
  * Author URI: http://pippinsplugins.com
8
+ * Version: 2.3.8
9
  * Text Domain: edd
10
  * Domain Path: languages
11
  *
25
  * @package EDD
26
  * @category Core
27
  * @author Pippin Williamson
28
+ * @version 2.3.8
29
  */
30
 
31
  // Exit if accessed directly
47
  */
48
  private static $instance;
49
 
50
+ /**
51
+ * EDD Roles Object
52
+ *
53
+ * @var object
54
+ * @since 1.5
55
+ */
56
+ public $roles;
57
+
58
  /**
59
  * EDD Cart Fees Object
60
  *
90
  */
91
  public $html;
92
 
93
+ /**
94
+ * EDD Emails Object
95
+ *
96
+ * @var object
97
+ * @since 2.1
98
+ */
99
+ public $emails;
100
+
101
  /**
102
  * EDD Email Template Tags Object
103
  *
106
  */
107
  public $email_tags;
108
 
109
+ /**
110
+ * EDD Customers DB Object
111
+ *
112
+ * @var object
113
+ * @since 2.1
114
+ */
115
+ public $customers;
116
+
117
  /**
118
  * Main Easy_Digital_Downloads Instance
119
  *
133
  if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Easy_Digital_Downloads ) ) {
134
  self::$instance = new Easy_Digital_Downloads;
135
  self::$instance->setup_constants();
136
+
137
+ add_action( 'plugins_loaded', array( self::$instance, 'load_textdomain' ) );
138
+
139
  self::$instance->includes();
 
140
  self::$instance->roles = new EDD_Roles();
141
  self::$instance->fees = new EDD_Fees();
142
  self::$instance->api = new EDD_API();
143
  self::$instance->session = new EDD_Session();
144
  self::$instance->html = new EDD_HTML_Elements();
145
+ self::$instance->emails = new EDD_Emails();
146
  self::$instance->email_tags = new EDD_Email_Template_Tags();
147
+ self::$instance->customers = new EDD_DB_Customers();
148
  }
149
  return self::$instance;
150
  }
184
  * @return void
185
  */
186
  private function setup_constants() {
187
+
188
  // Plugin version
189
  if ( ! defined( 'EDD_VERSION' ) ) {
190
+ define( 'EDD_VERSION', '2.3.8' );
191
  }
192
 
193
  // Plugin Folder Path
204
  if ( ! defined( 'EDD_PLUGIN_FILE' ) ) {
205
  define( 'EDD_PLUGIN_FILE', __FILE__ );
206
  }
207
+
208
+ // Make sure CAL_GREGORIAN is defined
209
+ if ( ! defined( 'CAL_GREGORIAN' ) ) {
210
+ define( 'CAL_GREGORIAN', 1 );
211
+ }
212
  }
213
 
214
  /**
225
  $edd_options = edd_get_settings();
226
 
227
  require_once EDD_PLUGIN_DIR . 'includes/actions.php';
228
+ if( file_exists( EDD_PLUGIN_DIR . 'includes/deprecated-functions.php' ) ) {
229
+ require_once EDD_PLUGIN_DIR . 'includes/deprecated-functions.php';
230
+ }
231
  require_once EDD_PLUGIN_DIR . 'includes/ajax-functions.php';
232
  require_once EDD_PLUGIN_DIR . 'includes/template-functions.php';
233
  require_once EDD_PLUGIN_DIR . 'includes/checkout/template.php';
236
  require_once EDD_PLUGIN_DIR . 'includes/cart/template.php';
237
  require_once EDD_PLUGIN_DIR . 'includes/cart/actions.php';
238
  require_once EDD_PLUGIN_DIR . 'includes/class-edd-api.php';
239
+ require_once EDD_PLUGIN_DIR . 'includes/class-edd-db.php';
240
+ require_once EDD_PLUGIN_DIR . 'includes/class-edd-db-customers.php';
241
+ require_once EDD_PLUGIN_DIR . 'includes/class-edd-customer.php';
242
+ require_once EDD_PLUGIN_DIR . 'includes/class-edd-download.php';
243
  require_once EDD_PLUGIN_DIR . 'includes/class-edd-cache-helper.php';
244
+ if ( defined( 'WP_CLI' ) && WP_CLI ) {
245
+ require_once EDD_PLUGIN_DIR . 'includes/class-edd-cli.php';
246
+ }
247
  require_once EDD_PLUGIN_DIR . 'includes/class-edd-cron.php';
248
  require_once EDD_PLUGIN_DIR . 'includes/class-edd-fees.php';
249
  require_once EDD_PLUGIN_DIR . 'includes/class-edd-html-elements.php';
270
  require_once EDD_PLUGIN_DIR . 'includes/scripts.php';
271
  require_once EDD_PLUGIN_DIR . 'includes/post-types.php';
272
  require_once EDD_PLUGIN_DIR . 'includes/plugin-compatibility.php';
273
+ require_once EDD_PLUGIN_DIR . 'includes/emails/class-edd-emails.php';
274
+ require_once EDD_PLUGIN_DIR . 'includes/emails/class-edd-email-tags.php';
275
  require_once EDD_PLUGIN_DIR . 'includes/emails/functions.php';
276
  require_once EDD_PLUGIN_DIR . 'includes/emails/template.php';
277
  require_once EDD_PLUGIN_DIR . 'includes/emails/actions.php';
 
278
  require_once EDD_PLUGIN_DIR . 'includes/error-tracking.php';
279
  require_once EDD_PLUGIN_DIR . 'includes/user-functions.php';
280
  require_once EDD_PLUGIN_DIR . 'includes/query-filters.php';
287
  require_once EDD_PLUGIN_DIR . 'includes/admin/add-ons.php';
288
  require_once EDD_PLUGIN_DIR . 'includes/admin/admin-footer.php';
289
  require_once EDD_PLUGIN_DIR . 'includes/admin/admin-actions.php';
290
+ require_once EDD_PLUGIN_DIR . 'includes/admin/class-edd-notices.php';
291
  require_once EDD_PLUGIN_DIR . 'includes/admin/admin-pages.php';
292
  require_once EDD_PLUGIN_DIR . 'includes/admin/dashboard-widgets.php';
293
  require_once EDD_PLUGIN_DIR . 'includes/admin/export-functions.php';
294
  require_once EDD_PLUGIN_DIR . 'includes/admin/thickbox.php';
295
  require_once EDD_PLUGIN_DIR . 'includes/admin/upload-functions.php';
296
  require_once EDD_PLUGIN_DIR . 'includes/admin/downloads/dashboard-columns.php';
297
+ require_once EDD_PLUGIN_DIR . 'includes/admin/customers/customers.php';
298
+ require_once EDD_PLUGIN_DIR . 'includes/admin/customers/customer-functions.php';
299
+ require_once EDD_PLUGIN_DIR . 'includes/admin/customers/customer-actions.php';
300
  require_once EDD_PLUGIN_DIR . 'includes/admin/downloads/metabox.php';
301
  require_once EDD_PLUGIN_DIR . 'includes/admin/downloads/contextual-help.php';
302
  require_once EDD_PLUGIN_DIR . 'includes/admin/discounts/contextual-help.php';
includes/EDD_SL_Plugin_Updater.php CHANGED
@@ -3,175 +3,336 @@
3
  // uncomment this line for testing
4
  //set_site_transient( 'update_plugins', null );
5
 
 
 
 
6
  /**
7
  * Allows plugins to use their own update API.
8
  *
9
  * @author Pippin Williamson
10
- * @version 1.2
11
  */
12
  class EDD_SL_Plugin_Updater {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
- private $api_url = '';
15
- private $api_data = array();
16
- private $name = '';
17
- private $slug = '';
18
- private $do_check = false;
19
-
20
- /**
21
- * Class constructor.
22
- *
23
- * @uses plugin_basename()
24
- * @uses hook()
25
- *
26
- * @param string $_api_url The URL pointing to the custom API endpoint.
27
- * @param string $_plugin_file Path to the plugin file.
28
- * @param array $_api_data Optional data to send with API calls.
29
- * @return EDD_SL_Plugin_Updater
30
- */
31
- function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
32
- $this->api_url = trailingslashit( $_api_url );
33
- $this->api_data = urlencode_deep( $_api_data );
34
- $this->name = plugin_basename( $_plugin_file );
35
- $this->slug = basename( $_plugin_file, '.php');
36
- $this->version = $_api_data['version'];
37
-
38
- // Set up hooks.
39
- $this->hook();
40
- }
41
-
42
- /**
43
- * Set up Wordpress filters to hook into WP's update process.
44
- *
45
- * @uses add_filter()
46
- *
47
- * @return void
48
- */
49
- private function hook() {
50
- add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'pre_set_site_transient_update_plugins_filter' ) );
51
- add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
52
- add_filter( 'http_request_args', array( $this, 'http_request_args' ), 10, 2 );
53
- }
54
-
55
- /**
56
- * Check for Updates at the defined API endpoint and modify the update array.
57
- *
58
- * This function dives into the update api just when WordPress creates its update array,
59
- * then adds a custom API call and injects the custom plugin data retrieved from the API.
60
- * It is reassembled from parts of the native WordPress plugin update code.
61
- * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
62
- *
63
- * @uses api_request()
64
- *
65
- * @param array $_transient_data Update array build by WordPress.
66
- * @return array Modified update array with custom plugin data.
67
- */
68
- function pre_set_site_transient_update_plugins_filter( $_transient_data ) {
69
- if( empty( $_transient_data ) || ! $this->do_check ) {
70
-
71
- // This ensures that the custom API request only runs on the second time that WP fires the update check
72
- $this->do_check = true;
73
-
74
- return $_transient_data;
75
- }
76
-
77
- $to_send = array( 'slug' => $this->slug );
78
-
79
- $api_response = $this->api_request( 'plugin_latest_version', $to_send );
80
-
81
- if( false !== $api_response && is_object( $api_response ) && isset( $api_response->new_version ) ) {
82
-
83
- if( version_compare( $this->version, $api_response->new_version, '<' ) ) {
84
- $_transient_data->response[$this->name] = $api_response;
85
- }
86
- }
87
- return $_transient_data;
88
- }
89
-
90
-
91
- /**
92
- * Updates information on the "View version x.x details" page with custom data.
93
- *
94
- * @uses api_request()
95
- *
96
- * @param mixed $_data
97
- * @param string $_action
98
- * @param object $_args
99
- * @return object $_data
100
- */
101
- function plugins_api_filter( $_data, $_action = '', $_args = null ) {
102
- if ( ( $_action != 'plugin_information' ) || !isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
103
- return $_data;
104
- }
105
-
106
- $to_send = array( 'slug' => $this->slug );
107
-
108
- $api_response = $this->api_request( 'plugin_information', $to_send );
109
- if ( false !== $api_response ) {
110
- $_data = $api_response;
111
- }
112
- return $_data;
113
- }
114
-
115
-
116
- /**
117
- * Disable SSL verification in order to prevent download update failures
118
- *
119
- * @param array $args
120
- * @param string $url
121
- * @return object $array
122
- */
123
- function http_request_args( $args, $url ) {
124
- // If it is an https request and we are performing a package download, disable ssl verification
125
- if( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
126
- $args['sslverify'] = false;
127
- }
128
- return $args;
129
- }
130
-
131
- /**
132
- * Calls the API and, if successfull, returns the object delivered by the API.
133
- *
134
- * @uses get_bloginfo()
135
- * @uses wp_remote_post()
136
- * @uses is_wp_error()
137
- *
138
- * @param string $_action The requested action.
139
- * @param array $_data Parameters for the API action.
140
- * @return false|object
141
- */
142
- private function api_request( $_action, $_data ) {
143
- $data = array_merge( $this->api_data, $_data );
144
-
145
- if( $data['slug'] != $this->slug ) {
146
- return false;
147
- }
148
-
149
- if( empty( $data['license'] ) ) {
150
- return false;
151
- }
152
-
153
- if( $this->api_url == home_url() ) {
154
- return false; // Don't allow a plugin to ping itself
155
- }
156
-
157
- $api_params = array(
158
- 'edd_action' => 'get_version',
159
- 'license' => $data['license'],
160
- 'name' => $data['item_name'],
161
- 'slug' => $this->slug,
162
- 'author' => $data['author'],
163
- 'url' => home_url()
164
- );
165
- $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
166
-
167
- if ( ! is_wp_error( $request ) ) {
168
- $request = json_decode( wp_remote_retrieve_body( $request ) );
169
- if( $request && isset( $request->sections ) ) {
170
- $request->sections = maybe_unserialize( $request->sections );
171
- }
172
- return $request;
173
- } else {
174
- return false;
175
- }
176
- }
177
- }
3
  // uncomment this line for testing
4
  //set_site_transient( 'update_plugins', null );
5
 
6
+ // Exit if accessed directly
7
+ if ( ! defined( 'ABSPATH' ) ) exit;
8
+
9
  /**
10
  * Allows plugins to use their own update API.
11
  *
12
  * @author Pippin Williamson
13
+ * @version 1.6
14
  */
15
  class EDD_SL_Plugin_Updater {
16
+ private $api_url = '';
17
+ private $api_data = array();
18
+ private $name = '';
19
+ private $slug = '';
20
+ private $version = '';
21
+
22
+ /**
23
+ * Class constructor.
24
+ *
25
+ * @uses plugin_basename()
26
+ * @uses hook()
27
+ *
28
+ * @param string $_api_url The URL pointing to the custom API endpoint.
29
+ * @param string $_plugin_file Path to the plugin file.
30
+ * @param array $_api_data Optional data to send with API calls.
31
+ */
32
+ function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
33
+ $this->api_url = trailingslashit( $_api_url );
34
+ $this->api_data = $_api_data;
35
+ $this->name = plugin_basename( $_plugin_file );
36
+ $this->slug = basename( $_plugin_file, '.php' );
37
+ $this->version = $_api_data['version'];
38
+
39
+ // Set up hooks.
40
+ $this->init();
41
+ add_action( 'admin_init', array( $this, 'show_changelog' ) );
42
+ }
43
+
44
+ /**
45
+ * Set up WordPress filters to hook into WP's update process.
46
+ *
47
+ * @uses add_filter()
48
+ *
49
+ * @return void
50
+ */
51
+ public function init() {
52
+
53
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
54
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
55
+
56
+ add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
57
+ }
58
+
59
+ /**
60
+ * Check for Updates at the defined API endpoint and modify the update array.
61
+ *
62
+ * This function dives into the update API just when WordPress creates its update array,
63
+ * then adds a custom API call and injects the custom plugin data retrieved from the API.
64
+ * It is reassembled from parts of the native WordPress plugin update code.
65
+ * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
66
+ *
67
+ * @uses api_request()
68
+ *
69
+ * @param array $_transient_data Update array build by WordPress.
70
+ * @return array Modified update array with custom plugin data.
71
+ */
72
+ function check_update( $_transient_data ) {
73
+
74
+ global $pagenow;
75
+
76
+ if( ! is_object( $_transient_data ) ) {
77
+ $_transient_data = new stdClass;
78
+ }
79
+
80
+ if( 'plugins.php' == $pagenow && is_multisite() ) {
81
+ return $_transient_data;
82
+ }
83
+
84
+ if ( empty( $_transient_data->response ) || empty( $_transient_data->response[ $this->name ] ) ) {
85
+
86
+ $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
87
+
88
+ if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
89
+
90
+ if( version_compare( $this->version, $version_info->new_version, '<' ) ) {
91
+
92
+ $_transient_data->response[ $this->name ] = $version_info;
93
+
94
+ }
95
+
96
+ $_transient_data->last_checked = time();
97
+ $_transient_data->checked[ $this->name ] = $this->version;
98
+
99
+ }
100
+
101
+ }
102
+
103
+ return $_transient_data;
104
+ }
105
+
106
+ /**
107
+ * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
108
+ *
109
+ * @param string $file
110
+ * @param array $plugin
111
+ */
112
+ public function show_update_notification( $file, $plugin ) {
113
+
114
+ if( ! current_user_can( 'update_plugins' ) ) {
115
+ return;
116
+ }
117
+
118
+ if( ! is_multisite() ) {
119
+ return;
120
+ }
121
+
122
+ if ( $this->name != $file ) {
123
+ return;
124
+ }
125
+
126
+ // Remove our filter on the site transient
127
+ remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
128
+
129
+ $update_cache = get_site_transient( 'update_plugins' );
130
+
131
+ if ( ! is_object( $update_cache ) || empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
132
+
133
+ $cache_key = md5( 'edd_plugin_' .sanitize_key( $this->name ) . '_version_info' );
134
+ $version_info = get_transient( $cache_key );
135
+
136
+ if( false === $version_info ) {
137
+
138
+ $version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
139
+
140
+ set_transient( $cache_key, $version_info, 3600 );
141
+ }
142
+
143
+
144
+ if( ! is_object( $version_info ) ) {
145
+ return;
146
+ }
147
+
148
+ if( version_compare( $this->version, $version_info->new_version, '<' ) ) {
149
+
150
+ $update_cache->response[ $this->name ] = $version_info;
151
+
152
+ }
153
+
154
+ $update_cache->last_checked = time();
155
+ $update_cache->checked[ $this->name ] = $this->version;
156
+
157
+ set_site_transient( 'update_plugins', $update_cache );
158
+
159
+ } else {
160
+
161
+ $version_info = $update_cache->response[ $this->name ];
162
+
163
+ }
164
+
165
+ // Restore our filter
166
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
167
+
168
+ if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) {
169
+
170
+ // build a plugin list row, with update notification
171
+ $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
172
+ echo '<tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';
173
+
174
+ $changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911' );
175
+
176
+ if ( empty( $version_info->download_link ) ) {
177
+ printf(
178
+ __( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a>.', 'edd' ),
179
+ esc_html( $version_info->name ),
180
+ esc_url( $changelog_link ),
181
+ esc_html( $version_info->new_version )
182
+ );
183
+ } else {
184
+ printf(
185
+ __( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a> or <a href="%4$s">update now</a>.', 'edd' ),
186
+ esc_html( $version_info->name ),
187
+ esc_url( $changelog_link ),
188
+ esc_html( $version_info->new_version ),
189
+ esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) )
190
+ );
191
+ }
192
+
193
+ echo '</div></td></tr>';
194
+ }
195
+ }
196
+
197
+
198
+ /**
199
+ * Updates information on the "View version x.x details" page with custom data.
200
+ *
201
+ * @uses api_request()
202
+ *
203
+ * @param mixed $_data
204
+ * @param string $_action
205
+ * @param object $_args
206
+ * @return object $_data
207
+ */
208
+ function plugins_api_filter( $_data, $_action = '', $_args = null ) {
209
+
210
+
211
+ if ( $_action != 'plugin_information' ) {
212
+
213
+ return $_data;
214
+
215
+ }
216
+
217
+ if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
218
+
219
+ return $_data;
220
+
221
+ }
222
+
223
+ $to_send = array(
224
+ 'slug' => $this->slug,
225
+ 'is_ssl' => is_ssl(),
226
+ 'fields' => array(
227
+ 'banners' => false, // These will be supported soon hopefully
228
+ 'reviews' => false
229
+ )
230
+ );
231
+
232
+ $api_response = $this->api_request( 'plugin_information', $to_send );
233
+
234
+ if ( false !== $api_response ) {
235
+ $_data = $api_response;
236
+ }
237
+
238
+ return $_data;
239
+ }
240
+
241
+
242
+ /**
243
+ * Disable SSL verification in order to prevent download update failures
244
+ *
245
+ * @param array $args
246
+ * @param string $url
247
+ * @return object $array
248
+ */
249
+ function http_request_args( $args, $url ) {
250
+ // If it is an https request and we are performing a package download, disable ssl verification
251
+ if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
252
+ $args['sslverify'] = false;
253
+ }
254
+ return $args;
255
+ }
256
+
257
+ /**
258
+ * Calls the API and, if successfull, returns the object delivered by the API.
259
+ *
260
+ * @uses get_bloginfo()
261
+ * @uses wp_remote_post()
262
+ * @uses is_wp_error()
263
+ *
264
+ * @param string $_action The requested action.
265
+ * @param array $_data Parameters for the API action.
266
+ * @return false|object
267
+ */
268
+ private function api_request( $_action, $_data ) {
269
+
270
+ global $wp_version;
271
+
272
+ $data = array_merge( $this->api_data, $_data );
273
+
274
+ if ( $data['slug'] != $this->slug )
275
+ return;
276
+
277
+ if ( empty( $data['license'] ) )
278
+ return;
279
+
280
+ if( $this->api_url == home_url() ) {
281
+ return false; // Don't allow a plugin to ping itself
282
+ }
283
+
284
+ $api_params = array(
285
+ 'edd_action' => 'get_version',
286
+ 'license' => $data['license'],
287
+ 'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
288
+ 'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
289
+ 'slug' => $data['slug'],
290
+ 'author' => $data['author'],
291
+ 'url' => home_url()
292
+ );
293
+
294
+ $request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
295
+
296
+ if ( ! is_wp_error( $request ) ) {
297
+ $request = json_decode( wp_remote_retrieve_body( $request ) );
298
+ }
299
+
300
+ if ( $request && isset( $request->sections ) ) {
301
+ $request->sections = maybe_unserialize( $request->sections );
302
+ } else {
303
+ $request = false;
304
+ }
305
+
306
+ return $request;
307
+ }
308
+
309
+ public function show_changelog() {
310
+
311
+
312
+ if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
313
+ return;
314
+ }
315
+
316
+ if( empty( $_REQUEST['plugin'] ) ) {
317
+ return;
318
+ }
319
+
320
+ if( empty( $_REQUEST['slug'] ) ) {
321
+ return;
322
+ }
323
+
324
+ if( ! current_user_can( 'update_plugins' ) ) {
325
+ wp_die( __( 'You do not have permission to install plugin updates', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
326
+ }
327
+
328
+ $response = $this->api_request( 'plugin_latest_version', array( 'slug' => $_REQUEST['slug'] ) );
329
+
330
+ if( $response && isset( $response->sections['changelog'] ) ) {
331
+ echo '<div style="background:#fff;padding:10px;">' . $response->sections['changelog'] . '</div>';
332
+ }
333
+
334
+
335
+ exit;
336
+ }
337
 
338
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/actions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0.8.1
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0.8.1
10
  */
includes/admin/add-ons.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Add-ons
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -36,14 +36,43 @@ add_action( 'admin_menu', 'edd_add_ons_init');
36
  * @return void
37
  */
38
  function edd_add_ons_page() {
 
 
 
39
  ob_start(); ?>
40
  <div class="wrap" id="edd-add-ons">
41
  <h2>
42
- <?php _e( 'Add Ons for Easy Digital Downloads', 'edd' ); ?>
43
- &nbsp;&mdash;&nbsp;<a href="http://easydigitaldownloads.com/extensions/?utm_source=plugin-addons-page&utm_medium=plugin&ytm_campaign=EDD%20Addons%20Page&utm_content=All%20Extensions" class="button-primary" title="<?php _e( 'Browse All Extensions', 'edd' ); ?>" target="_blank"><?php _e( 'Browse All Extensions', 'edd' ); ?></a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  </h2>
45
- <p><?php _e( 'These add-ons extend the functionality of Easy Digital Downloads.', 'edd' ); ?></p>
46
- <?php echo edd_add_ons_get_feed(); ?>
 
 
 
 
 
47
  </div>
48
  <?php
49
  echo ob_get_clean();
@@ -57,17 +86,24 @@ function edd_add_ons_page() {
57
  * @since 1.0
58
  * @return void
59
  */
60
- function edd_add_ons_get_feed() {
61
- if ( false === ( $cache = get_transient( 'easydigitaldownloads_add_ons_feed' ) ) ) {
62
- $feed = wp_remote_get( 'https://easydigitaldownloads.com/?feed=addons', array( 'sslverify' => false ) );
 
 
 
 
 
 
63
  if ( ! is_wp_error( $feed ) ) {
64
  if ( isset( $feed['body'] ) && strlen( $feed['body'] ) > 0 ) {
65
  $cache = wp_remote_retrieve_body( $feed );
66
- set_transient( 'easydigitaldownloads_add_ons_feed', $cache, 3600 );
67
  }
68
  } else {
69
  $cache = '<div class="error"><p>' . __( 'There was an error retrieving the extensions list from the server. Please try again later.', 'edd' ) . '</div>';
70
  }
71
  }
 
72
  return $cache;
73
- }
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Add-ons
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
36
  * @return void
37
  */
38
  function edd_add_ons_page() {
39
+ $add_ons_tabs = apply_filters( 'edd_add_ons_tabs', array( 'popular' => 'Popular', 'new' => 'New') );
40
+ $active_tab = isset( $_GET['tab'] ) && array_key_exists( $_GET['tab'], $add_ons_tabs ) ? $_GET['tab'] : 'popular';
41
+
42
  ob_start(); ?>
43
  <div class="wrap" id="edd-add-ons">
44
  <h2>
45
+ <?php _e( 'Extensions for Easy Digital Downloads', 'edd' ); ?>
46
+ <span>
47
+ &nbsp;&nbsp;<a href="http://easydigitaldownloads.com/extensions/?utm_source=plugin-addons-page&utm_medium=plugin&ytm_campaign=EDD%20Addons%20Page&utm_content=All%20Extensions" class="button-primary" title="<?php _e( 'Browse All Extensions', 'edd' ); ?>" target="_blank"><?php _e( 'Browse All Extensions', 'edd' ); ?></a>
48
+ </span>
49
+ </h2>
50
+ <p><?php _e( 'These extensions <em><strong>add functionality</strong></em> to your Easy Digital Downloads powered store.', 'edd' ); ?></p>
51
+ <h2 class="nav-tab-wrapper">
52
+ <?php
53
+ foreach( $add_ons_tabs as $tab_id => $tab_name ) {
54
+
55
+ $tab_url = add_query_arg( array(
56
+ 'settings-updated' => false,
57
+ 'tab' => $tab_id
58
+ ) );
59
+
60
+ $active = $active_tab == $tab_id ? ' nav-tab-active' : '';
61
+
62
+ echo '<a href="' . esc_url( $tab_url ) . '" title="' . esc_attr( $tab_name ) . '" class="nav-tab' . $active . '">';
63
+ echo esc_html( $tab_name );
64
+ echo '</a>';
65
+ }
66
+ ?>
67
+ <span class="edd-tab-span"><img src="<?php echo EDD_PLUGIN_URL; ?>assets/images/edd-peeking.png" /></span>
68
  </h2>
69
+ <div id="tab_container">
70
+ <?php echo edd_add_ons_get_feed( $active_tab ); ?>
71
+ <div class="clear"></div>
72
+ <div class="edd-add-ons-footer">
73
+ <a href="http://easydigitaldownloads.com/extensions/?utm_source=plugin-addons-page&utm_medium=plugin&ytm_campaign=EDD%20Addons%20Page&utm_content=All%20Extensions" class="button-primary" title="<?php _e( 'Browse All Extensions', 'edd' ); ?>" target="_blank"><?php _e( 'Browse All Extensions', 'edd' ); ?></a>
74
+ </div>
75
+ </div><!-- #tab_container-->
76
  </div>
77
  <?php
78
  echo ob_get_clean();
86
  * @since 1.0
87
  * @return void
88
  */
89
+ function edd_add_ons_get_feed( $tab = 'popular' ) {
90
+ if ( false === ( $cache = get_transient( 'easydigitaldownloads_add_ons_feed_' . $tab ) ) ) {
91
+ $url = 'https://easydigitaldownloads.com/?feed=addons';
92
+ if ( 'popular' !== $tab ) {
93
+ $url = add_query_arg( array( 'display' => $tab ), $url );
94
+ }
95
+
96
+ $feed = wp_remote_get( esc_url_raw( $url ), array( 'sslverify' => false ) );
97
+
98
  if ( ! is_wp_error( $feed ) ) {
99
  if ( isset( $feed['body'] ) && strlen( $feed['body'] ) > 0 ) {
100
  $cache = wp_remote_retrieve_body( $feed );
101
+ set_transient( 'easydigitaldownloads_add_ons_feed_' . $tab, $cache, 3600 );
102
  }
103
  } else {
104
  $cache = '<div class="error"><p>' . __( 'There was an error retrieving the extensions list from the server. Please try again later.', 'edd' ) . '</div>';
105
  }
106
  }
107
+
108
  return $cache;
109
+ }
includes/admin/admin-actions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Actions
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Actions
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
includes/admin/admin-footer.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Footer
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -26,7 +26,7 @@ function edd_admin_rate_us( $footer_text ) {
26
  if ( $typenow == 'download' ) {
27
  $rate_text = sprintf( __( 'Thank you for using <a href="%1$s" target="_blank">Easy Digital Downloads</a>! Please <a href="%2$s" target="_blank">rate us</a> on <a href="%2$s" target="_blank">WordPress.org</a>', 'edd' ),
28
  'https://easydigitaldownloads.com',
29
- 'http://wordpress.org/support/view/plugin-reviews/easy-digital-downloads?filter=5#postform'
30
  );
31
 
32
  return str_replace( '</span>', '', $footer_text ) . ' | ' . $rate_text . '</span>';
@@ -34,4 +34,4 @@ function edd_admin_rate_us( $footer_text ) {
34
  return $footer_text;
35
  }
36
  }
37
- add_filter( 'admin_footer_text', 'edd_admin_rate_us' );
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Footer
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
26
  if ( $typenow == 'download' ) {
27
  $rate_text = sprintf( __( 'Thank you for using <a href="%1$s" target="_blank">Easy Digital Downloads</a>! Please <a href="%2$s" target="_blank">rate us</a> on <a href="%2$s" target="_blank">WordPress.org</a>', 'edd' ),
28
  'https://easydigitaldownloads.com',
29
+ 'https://wordpress.org/support/view/plugin-reviews/easy-digital-downloads?filter=5#postform'
30
  );
31
 
32
  return str_replace( '</span>', '', $footer_text ) . ' | ' . $rate_text . '</span>';
34
  return $footer_text;
35
  }
36
  }
37
+ add_filter( 'admin_footer_text', 'edd_admin_rate_us' );
includes/admin/admin-notices.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Notices
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -30,6 +30,10 @@ function edd_admin_messages() {
30
  add_settings_error( 'edd-notices', 'edd-discount-add-fail', __( 'There was a problem adding your discount code, please try again.', 'edd' ), 'error' );
31
  }
32
 
 
 
 
 
33
  if ( isset( $_GET['edd-message'] ) && 'discount_updated' == $_GET['edd-message'] && current_user_can( 'manage_shop_discounts' ) ) {
34
  add_settings_error( 'edd-notices', 'edd-discount-updated', __( 'Discount code updated.', 'edd' ), 'updated' );
35
  }
@@ -77,8 +81,8 @@ function edd_admin_messages() {
77
  add_settings_error( 'edd-notices', 'edd-api-key-generated', __( 'API keys successfully generated.', 'edd' ), 'updated' );
78
  }
79
 
80
- if ( isset( $_GET['edd-message'] ) && 'api-key-exists' == $_GET['edd-message'] && current_user_can( 'manage_shop_settings' ) ) {
81
- add_settings_error( 'edd-notices', 'edd-api-key-exists', __( 'The specified user already has API keys.', 'edd' ), 'error' );
82
  }
83
 
84
  if ( isset( $_GET['edd-message'] ) && 'api-key-regenerated' == $_GET['edd-message'] && current_user_can( 'manage_shop_settings' ) ) {
@@ -89,7 +93,7 @@ function edd_admin_messages() {
89
  add_settings_error( 'edd-notices', 'edd-api-key-revoked', __( 'API keys successfully revoked.', 'edd' ), 'updated' );
90
  }
91
 
92
- if( ! edd_htaccess_exists() && ! get_user_meta( get_current_user_id(), '_edd_htaccess_missing_dismissed', true ) ) {
93
  if( ! stristr( $_SERVER['SERVER_SOFTWARE'], 'apache' ) )
94
  return; // Bail if we aren't using Apache... nginx doesn't use htaccess!
95
 
@@ -101,6 +105,19 @@ function edd_admin_messages() {
101
  echo '</div>';
102
  }
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  settings_errors( 'edd-notices' );
105
  }
106
  add_action( 'admin_notices', 'edd_admin_messages' );
@@ -124,6 +141,10 @@ function edd_admin_addons_notices() {
124
  */
125
  function edd_dismiss_notices() {
126
 
 
 
 
 
127
  $notice = isset( $_GET['edd_notice'] ) ? $_GET['edd_notice'] : false;
128
 
129
  if( ! $notice )
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Notices
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
30
  add_settings_error( 'edd-notices', 'edd-discount-add-fail', __( 'There was a problem adding your discount code, please try again.', 'edd' ), 'error' );
31
  }
32
 
33
+ if ( isset( $_GET['edd-message'] ) && 'discount_exists' == $_GET['edd-message'] && current_user_can( 'manage_shop_discounts' ) ) {
34
+ add_settings_error( 'edd-notices', 'edd-discount-exists', __( 'A discount with that code already exists, please use a different code.', 'edd' ), 'error' );
35
+ }
36
+
37
  if ( isset( $_GET['edd-message'] ) && 'discount_updated' == $_GET['edd-message'] && current_user_can( 'manage_shop_discounts' ) ) {
38
  add_settings_error( 'edd-notices', 'edd-discount-updated', __( 'Discount code updated.', 'edd' ), 'updated' );
39
  }
81
  add_settings_error( 'edd-notices', 'edd-api-key-generated', __( 'API keys successfully generated.', 'edd' ), 'updated' );
82
  }
83
 
84
+ if ( isset( $_GET['edd-message'] ) && 'api-key-failed' == $_GET['edd-message'] && current_user_can( 'manage_shop_settings' ) ) {
85
+ add_settings_error( 'edd-notices', 'edd-api-key-failed', __( 'The specified user already has API keys or the specified user does not exist..', 'edd' ), 'error' );
86
  }
87
 
88
  if ( isset( $_GET['edd-message'] ) && 'api-key-regenerated' == $_GET['edd-message'] && current_user_can( 'manage_shop_settings' ) ) {
93
  add_settings_error( 'edd-notices', 'edd-api-key-revoked', __( 'API keys successfully revoked.', 'edd' ), 'updated' );
94
  }
95
 
96
+ if( ! edd_htaccess_exists() && ! get_user_meta( get_current_user_id(), '_edd_htaccess_missing_dismissed', true ) && current_user_can( 'manage_shop_settings' ) ) {
97
  if( ! stristr( $_SERVER['SERVER_SOFTWARE'], 'apache' ) )
98
  return; // Bail if we aren't using Apache... nginx doesn't use htaccess!
99
 
105
  echo '</div>';
106
  }
107
 
108
+ if( ! get_user_meta( get_current_user_id(), '_edd_admin_ajax_inaccessible_dismissed', true ) && current_user_can( 'manage_shop_settings' ) && false !== get_transient( '_edd_ajax_works' ) ) {
109
+
110
+ if( ! edd_test_ajax_works() ) {
111
+
112
+ echo '<div class="error">';
113
+ echo '<p>' . __( 'Your site appears to be blocking the WordPress ajax interface. This may causes issues with your store.', 'edd' ) . '</p>';
114
+ echo '<p>' . sprintf( __( 'Please see <a href="%s" target="_blank">this reference</a> for possible solutions.', 'edd' ), 'https://easydigitaldownloads.com/docs/admin-ajax-blocked' ) . '</p>';
115
+ echo '<p><a href="' . add_query_arg( array( 'edd_action' => 'dismiss_notices', 'edd_notice' => 'admin_ajax_inaccessible' ) ) . '">' . __( 'Dismiss Notice', 'edd' ) . '</a></p>';
116
+ echo '</div>';
117
+
118
+ }
119
+ }
120
+
121
  settings_errors( 'edd-notices' );
122
  }
123
  add_action( 'admin_notices', 'edd_admin_messages' );
141
  */
142
  function edd_dismiss_notices() {
143
 
144
+ if( ! is_user_logged_in() ) {
145
+ return;
146
+ }
147
+
148
  $notice = isset( $_GET['edd_notice'] ) ? $_GET['edd_notice'] : false;
149
 
150
  if( ! $notice )
includes/admin/admin-pages.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Pages
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -19,6 +19,7 @@ if ( ! defined( 'ABSPATH' ) ) exit;
19
  * @since 1.0
20
  * @global $edd_discounts_page
21
  * @global $edd_payments_page
 
22
  * @global $edd_settings_page
23
  * @global $edd_reports_page
24
  * @global $edd_add_ons_page
@@ -27,46 +28,54 @@ if ( ! defined( 'ABSPATH' ) ) exit;
27
  * @return void
28
  */
29
  function edd_add_options_link() {
30
- global $edd_discounts_page, $edd_payments_page, $edd_settings_page, $edd_reports_page, $edd_add_ons_page, $edd_settings_export, $edd_upgrades_screen, $edd_tools_page;
31
 
32
  $edd_payment = get_post_type_object( 'edd_payment' );
33
 
34
  $edd_payments_page = add_submenu_page( 'edit.php?post_type=download', $edd_payment->labels->name, $edd_payment->labels->menu_name, 'edit_shop_payments', 'edd-payment-history', 'edd_payment_history_page' );
 
35
  $edd_discounts_page = add_submenu_page( 'edit.php?post_type=download', __( 'Discount Codes', 'edd' ), __( 'Discount Codes', 'edd' ), 'manage_shop_discounts', 'edd-discounts', 'edd_discounts_page' );
36
- $edd_reports_page = add_submenu_page( 'edit.php?post_type=download', __( 'Earnings and Sales Reports', 'edd' ), __( 'Reports', 'edd' ), 'view_shop_reports', 'edd-reports', 'edd_reports_page' );
37
- $edd_settings_page = add_submenu_page( 'edit.php?post_type=download', __( 'Easy Digital Download Settings', 'edd' ), __( 'Settings', 'edd' ), 'manage_shop_settings', 'edd-settings', 'edd_options_page' );
38
  $edd_tools_page = add_submenu_page( 'edit.php?post_type=download', __( 'Easy Digital Download Info and Tools', 'edd' ), __( 'Tools', 'edd' ), 'install_plugins', 'edd-tools', 'edd_tools_page' );
39
- $edd_add_ons_page = add_submenu_page( 'edit.php?post_type=download', __( 'Easy Digital Download Add Ons', 'edd' ), __( 'Add Ons', 'edd' ), 'install_plugins', 'edd-addons', 'edd_add_ons_page' );
40
- $edd_upgrades_screen = add_submenu_page( null, __( 'EDD Upgrades', 'edd' ), __( 'EDD Upgrades', 'edd' ), 'install_plugins', 'edd-upgrades', 'edd_upgrades_screen' );
 
41
  }
42
  add_action( 'admin_menu', 'edd_add_options_link', 10 );
43
 
44
  /**
45
  * Determines whether the current admin page is an EDD admin page.
46
- *
47
- * Only works after the `wp_loaded` hook, & most effective
48
  * starting on `admin_menu` hook.
49
- *
50
  * @since 1.9.6
51
  * @return bool True if EDD admin page.
52
  */
53
  function edd_is_admin_page() {
54
 
55
- if ( ! is_admin() || ! did_action( 'wp_loaded' ) ) {
56
- return false;
57
- }
58
-
59
- global $pagenow, $typenow, $edd_discounts_page, $edd_payments_page, $edd_settings_page, $edd_reports_page, $edd_system_info_page, $edd_add_ons_page, $edd_settings_export, $edd_upgrades_screen;
60
 
61
  if ( 'download' == $typenow || 'index.php' == $pagenow || 'post-new.php' == $pagenow || 'post.php' == $pagenow ) {
62
- return true;
63
- }
64
-
65
- $edd_admin_pages = apply_filters( 'edd_admin_pages', array( $edd_discounts_page, $edd_payments_page, $edd_settings_page, $edd_reports_page, $edd_system_info_page, $edd_add_ons_page, $edd_settings_export, $edd_upgrades_screen, ) );
66
-
67
- if ( in_array( $pagenow, $edd_admin_pages ) ) {
68
- return true;
69
- } else {
70
- return false;
 
 
 
 
71
  }
 
 
72
  }
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Pages
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
19
  * @since 1.0
20
  * @global $edd_discounts_page
21
  * @global $edd_payments_page
22
+ * @global $edd_customers_page
23
  * @global $edd_settings_page
24
  * @global $edd_reports_page
25
  * @global $edd_add_ons_page
28
  * @return void
29
  */
30
  function edd_add_options_link() {
31
+ global $edd_discounts_page, $edd_payments_page, $edd_settings_page, $edd_reports_page, $edd_add_ons_page, $edd_settings_export, $edd_upgrades_screen, $edd_tools_page, $edd_customers_page;
32
 
33
  $edd_payment = get_post_type_object( 'edd_payment' );
34
 
35
  $edd_payments_page = add_submenu_page( 'edit.php?post_type=download', $edd_payment->labels->name, $edd_payment->labels->menu_name, 'edit_shop_payments', 'edd-payment-history', 'edd_payment_history_page' );
36
+ $edd_customers_page = add_submenu_page( 'edit.php?post_type=download', __( 'Customers', 'edd' ), __( 'Customers', 'edd' ), 'view_shop_reports', 'edd-customers', 'edd_customers_page' );
37
  $edd_discounts_page = add_submenu_page( 'edit.php?post_type=download', __( 'Discount Codes', 'edd' ), __( 'Discount Codes', 'edd' ), 'manage_shop_discounts', 'edd-discounts', 'edd_discounts_page' );
38
+ $edd_reports_page = add_submenu_page( 'edit.php?post_type=download', __( 'Earnings and Sales Reports', 'edd' ), __( 'Reports', 'edd' ), 'view_shop_reports', 'edd-reports', 'edd_reports_page' );
39
+ $edd_settings_page = add_submenu_page( 'edit.php?post_type=download', __( 'Easy Digital Download Settings', 'edd' ), __( 'Settings', 'edd' ), 'manage_shop_settings', 'edd-settings', 'edd_options_page' );
40
  $edd_tools_page = add_submenu_page( 'edit.php?post_type=download', __( 'Easy Digital Download Info and Tools', 'edd' ), __( 'Tools', 'edd' ), 'install_plugins', 'edd-tools', 'edd_tools_page' );
41
+ $edd_add_ons_page = add_submenu_page( 'edit.php?post_type=download', __( 'Easy Digital Download Extensions', 'edd' ), __( 'Extensions', 'edd' ), 'install_plugins', 'edd-addons', 'edd_add_ons_page' );
42
+ $edd_upgrades_screen = add_submenu_page( null, __( 'EDD Upgrades', 'edd' ), __( 'EDD Upgrades', 'edd' ), 'manage_shop_settings', 'edd-upgrades', 'edd_upgrades_screen' );
43
+
44
  }
45
  add_action( 'admin_menu', 'edd_add_options_link', 10 );
46
 
47
  /**
48
  * Determines whether the current admin page is an EDD admin page.
49
+ *
50
+ * Only works after the `wp_loaded` hook, & most effective
51
  * starting on `admin_menu` hook.
52
+ *
53
  * @since 1.9.6
54
  * @return bool True if EDD admin page.
55
  */
56
  function edd_is_admin_page() {
57
 
58
+ global $pagenow, $typenow, $edd_discounts_page, $edd_payments_page, $edd_settings_page,
59
+ $edd_reports_page, $edd_system_info_page, $edd_add_ons_page, $edd_settings_export, $edd_upgrades_screen;
60
+
61
+ $ret = false;
62
+ $admin_pages = apply_filters( 'edd_admin_pages', array( $edd_discounts_page, $edd_payments_page, $edd_settings_page, $edd_reports_page, $edd_system_info_page, $edd_add_ons_page, $edd_settings_export ) );
63
 
64
  if ( 'download' == $typenow || 'index.php' == $pagenow || 'post-new.php' == $pagenow || 'post.php' == $pagenow ) {
65
+
66
+ $ret = true;
67
+
68
+ if( isset( $_GET['page'] ) && 'edd-upgrades' == $_GET['page'] ) {
69
+
70
+ $ret = false;
71
+
72
+ }
73
+
74
+ } elseif ( in_array( $pagenow, $admin_pages ) ) {
75
+
76
+ $ret = true;
77
+
78
  }
79
+
80
+ return (bool) apply_filters( 'edd_is_admin_page', $ret );
81
  }
includes/admin/class-api-keys-table.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Tools/APIKeys
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 2.0
10
  */
@@ -80,6 +80,9 @@ class EDD_API_Keys_Table extends WP_List_Table {
80
  * @return void
81
  */
82
  public function column_user( $item ) {
 
 
 
83
  if( apply_filters( 'edd_api_log_requests', true ) ) {
84
  $actions['view'] = sprintf(
85
  '<a href="%s">%s</a>',
@@ -90,12 +93,12 @@ class EDD_API_Keys_Table extends WP_List_Table {
90
 
91
  $actions['reissue'] = sprintf(
92
  '<a href="%s" class="edd-regenerate-api-key">%s</a>',
93
- esc_url( add_query_arg( array( 'user_id' => $item['id'], 'edd_action' => 'process_api_key', 'edd_api_process' => 'regenerate' ) ) ),
94
  __( 'Reissue', 'edd' )
95
  );
96
  $actions['revoke'] = sprintf(
97
  '<a href="%s" class="edd-revoke-api-key edd-delete">%s</a>',
98
- esc_url( add_query_arg( array( 'user_id' => $item['id'], 'edd_action' => 'process_api_key', 'edd_api_process' => 'revoke' ) ) ),
99
  __( 'Revoke', 'edd' )
100
  );
101
 
@@ -129,7 +132,7 @@ class EDD_API_Keys_Table extends WP_List_Table {
129
  * @since 1.5
130
  * @return void
131
  */
132
- function bulk_actions() {
133
  // These aren't really bulk actions but this outputs the markup in the right place
134
  static $edd_api_is_bottom;
135
 
@@ -140,6 +143,7 @@ class EDD_API_Keys_Table extends WP_List_Table {
140
  <form method="post" action="<?php echo admin_url( 'edit.php?post_type=download&page=edd-tools&tab=api_keys' ); ?>">
141
  <input type="hidden" name="edd_action" value="process_api_key" />
142
  <input type="hidden" name="edd_api_process" value="generate" />
 
143
  <?php echo EDD()->html->ajax_user_search(); ?>
144
  <?php submit_button( __( 'Generate New API Keys', 'edd' ), 'secondary', 'submit', false ); ?>
145
  </form>
@@ -224,8 +228,6 @@ class EDD_API_Keys_Table extends WP_List_Table {
224
 
225
  $data = $this->query();
226
 
227
- $current_page = $this->get_pagenum();
228
-
229
  $total_items = $this->total_items();
230
 
231
  $this->items = $data;
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Tools/APIKeys
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 2.0
10
  */
80
  * @return void
81
  */
82
  public function column_user( $item ) {
83
+
84
+ $actions = array();
85
+
86
  if( apply_filters( 'edd_api_log_requests', true ) ) {
87
  $actions['view'] = sprintf(
88
  '<a href="%s">%s</a>',
93
 
94
  $actions['reissue'] = sprintf(
95
  '<a href="%s" class="edd-regenerate-api-key">%s</a>',
96
+ esc_url( wp_nonce_url( add_query_arg( array( 'user_id' => $item['id'], 'edd_action' => 'process_api_key', 'edd_api_process' => 'regenerate' ) ), 'edd-api-nonce' ) ),
97
  __( 'Reissue', 'edd' )
98
  );
99
  $actions['revoke'] = sprintf(
100
  '<a href="%s" class="edd-revoke-api-key edd-delete">%s</a>',
101
+ esc_url( wp_nonce_url( add_query_arg( array( 'user_id' => $item['id'], 'edd_action' => 'process_api_key', 'edd_api_process' => 'revoke' ) ), 'edd-api-nonce' ) ),
102
  __( 'Revoke', 'edd' )
103
  );
104
 
132
  * @since 1.5
133
  * @return void
134
  */
135
+ function bulk_actions( $which = '' ) {
136
  // These aren't really bulk actions but this outputs the markup in the right place
137
  static $edd_api_is_bottom;
138
 
143
  <form method="post" action="<?php echo admin_url( 'edit.php?post_type=download&page=edd-tools&tab=api_keys' ); ?>">
144
  <input type="hidden" name="edd_action" value="process_api_key" />
145
  <input type="hidden" name="edd_api_process" value="generate" />
146
+ <?php wp_nonce_field( 'edd-api-nonce' ); ?>
147
  <?php echo EDD()->html->ajax_user_search(); ?>
148
  <?php submit_button( __( 'Generate New API Keys', 'edd' ), 'secondary', 'submit', false ); ?>
149
  </form>
228
 
229
  $data = $this->query();
230
 
 
 
231
  $total_items = $this->total_items();
232
 
233
  $this->items = $data;
includes/admin/class-edd-heartbeat.php CHANGED
@@ -4,11 +4,13 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin
7
- * @copyright Copyright (c) 2012, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8
10
  */
11
 
 
 
12
 
13
  /**
14
  * EDD_Heartbeart Class
@@ -110,34 +112,45 @@ class EDD_Heartbeat {
110
  ?>
111
  <script>
112
  (function($){
113
-
114
- // Hook into the heartbeat-send
115
- $(document).on('heartbeat-send', function(e, data) {
116
- data['edd_heartbeat'] = 'dashboard_summary';
117
- });
118
-
119
- // Listen for the custom event "heartbeat-tick" on $(document).
120
- $(document).on( 'heartbeat-tick', function(e, data) {
121
-
122
- // Only proceed if our EDD data is present
123
- if ( ! data['edd-total-payments'] )
124
- return;
125
- console.log('tick');
126
- // Update sale count and bold it to provide a highlight
127
- $('.edd_dashboard_widget .table_totals .b.b-earnings').text( data['edd-total-earnings'] ).css( 'font-weight', 'bold' );
128
- $('.edd_dashboard_widget .table_totals .b.b-sales').text( data['edd-total-payments'] ).css( 'font-weight', 'bold' );
129
- $('.edd_dashboard_widget .table_today .b.b-earnings').text( data['edd-earnings-today'] ).css( 'font-weight', 'bold' );
130
- $('.edd_dashboard_widget .table_today .b.b-sales').text( data['edd-payments-today'] ).css( 'font-weight', 'bold' );
131
- $('.edd_dashboard_widget .table_current_month .b-earnings').text( data['edd-earnings-month'] ).css( 'font-weight', 'bold' );
132
- $('.edd_dashboard_widget .table_current_month .b-sales').text( data['edd-payments-month'] ).css( 'font-weight', 'bold' );
133
-
134
- // Return font-weight to normal after 2 seconds
135
- setTimeout(function(){
136
- $('.edd_dashboard_widget .b.b-sales,.edd_dashboard_widget .b.b-earnings').css( 'font-weight', 'normal' );
137
- $('.edd_dashboard_widget .table_current_month .b.b-earnings,.edd_dashboard_widget .table_current_month .b.b-sales').css( 'font-weight', 'normal' );
138
- }, 2000);
139
-
140
- });
 
 
 
 
 
 
 
 
 
 
 
141
  }(jQuery));
142
  </script>
143
  <?php
4
  *
5
  * @package EDD
6
  * @subpackage Admin
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
 
15
  /**
16
  * EDD_Heartbeart Class
112
  ?>
113
  <script>
114
  (function($){
115
+ // Hook into the heartbeat-send
116
+ $(document).on('heartbeat-send', function(e, data) {
117
+ data['edd_heartbeat'] = 'dashboard_summary';
118
+ });
119
+
120
+ // Listen for the custom event "heartbeat-tick" on $(document).
121
+ $(document).on( 'heartbeat-tick', function(e, data) {
122
+
123
+ // Only proceed if our EDD data is present
124
+ if ( ! data['edd-total-payments'] )
125
+ return;
126
+
127
+ <?php if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) : ?>
128
+ console.log('tick');
129
+ <?php endif; ?>
130
+
131
+ // Update sale count and bold it to provide a highlight
132
+ edd_dashboard_heartbeat_update( '.edd_dashboard_widget .table_totals .b.b-earnings', data['edd-total-earnings'] );
133
+ edd_dashboard_heartbeat_update( '.edd_dashboard_widget .table_totals .b.b-sales', data['edd-total-payments'] );
134
+ edd_dashboard_heartbeat_update( '.edd_dashboard_widget .table_today .b.b-earnings', data['edd-earnings-today'] );
135
+ edd_dashboard_heartbeat_update( '.edd_dashboard_widget .table_today .b.b-sales', data['edd-payments-today'] );
136
+ edd_dashboard_heartbeat_update( '.edd_dashboard_widget .table_current_month .b-earnings', data['edd-earnings-month'] );
137
+ edd_dashboard_heartbeat_update( '.edd_dashboard_widget .table_current_month .b-sales', data['edd-payments-month'] );
138
+
139
+ // Return font-weight to normal after 2 seconds
140
+ setTimeout(function(){
141
+ $('.edd_dashboard_widget .b.b-sales,.edd_dashboard_widget .b.b-earnings').css( 'font-weight', 'normal' );
142
+ $('.edd_dashboard_widget .table_current_month .b.b-earnings,.edd_dashboard_widget .table_current_month .b.b-sales').css( 'font-weight', 'normal' );
143
+ }, 2000);
144
+
145
+ });
146
+
147
+ function edd_dashboard_heartbeat_update( selector, new_value ) {
148
+ var current_value = $(selector).text();
149
+ $(selector).text( new_value );
150
+ if ( current_value !== new_value ) {
151
+ $(selector).css( 'font-weight', 'bold' );
152
+ }
153
+ }
154
  }(jQuery));
155
  </script>
156
  <?php
includes/admin/class-edd-notices.php ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Admin Notices Class
4
+ *
5
+ * @package EDD
6
+ * @subpackage Admin/Notices
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
+ * @since 2.3
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
+
15
+ /**
16
+ * EDD_Notices Class
17
+ *
18
+ * @since 2.3
19
+ */
20
+ class EDD_Notices {
21
+
22
+ /**
23
+ * Get things started
24
+ *
25
+ * @since 2.3
26
+ */
27
+ public function __construct() {
28
+ add_action( 'admin_notices', array( $this, 'show_notices' ) );
29
+ add_action( 'edd_dismiss_notices', array( $this, 'dismiss_notices' ) );
30
+ }
31
+
32
+ /**
33
+ * Show relevant notices
34
+ *
35
+ * @since 2.3
36
+ */
37
+ public function show_notices() {
38
+ $notices = array(
39
+ 'updated' => array(),
40
+ 'error' => array()
41
+ );
42
+
43
+ // Global (non-action-based) messages
44
+ if ( edd_get_option( 'purchase_page', '' ) == '' || 'trash' == get_post_status( edd_get_option( 'purchase_page', '' ) ) && current_user_can( 'edit_pages' ) && ! get_user_meta( get_current_user_id(), '_edd_set_checkout_dismissed' ) ) {
45
+ echo '<div class="error">';
46
+ echo '<p>' . sprintf( __( 'No checkout page has been configured. Visit <a href="%s">Settings</a> to set one.', 'edd' ), admin_url( 'edit.php?post_type=download&page=edd-settings' ) ) . '</p>';
47
+ echo '<p><a href="' . add_query_arg( array( 'edd_action' => 'dismiss_notices', 'edd_notice' => 'set_checkout' ) ) . '">' . __( 'Dismiss Notice', 'edd' ) . '</a></p>';
48
+ echo '</div>';
49
+ }
50
+
51
+ if ( isset( $_GET['page'] ) && 'edd-payment-history' == $_GET['page'] && current_user_can( 'view_shop_reports' ) && edd_is_test_mode() ) {
52
+ $notices['updated']['edd-payment-history-test-mode'] = sprintf( __( 'Note: Test Mode is enabled, only test payments are shown below. <a href="%s">Settings</a>.', 'edd' ), admin_url( 'edit.php?post_type=download&page=edd-settings' ) );
53
+ }
54
+
55
+ if( stristr( $_SERVER['SERVER_SOFTWARE'], 'nginx' ) && ! get_user_meta( get_current_user_id(), '_edd_nginx_redirect_dismissed', true ) && current_user_can( 'manage_shop_settings' ) ) {
56
+
57
+ echo '<div class="error">';
58
+ echo '<p>' . sprintf( __( 'The download files in <strong>%s</strong> are not currently protected due to your site running on NGINX.', 'edd' ), edd_get_upload_dir() ) . '</p>';
59
+ echo '<p>' . __( 'To protect them, you must add a redirect rule as explained in <a href="http://docs.easydigitaldownloads.com/article/682-protected-download-files-on-nginx">this guide</a>.', 'edd' ) . '</p>';
60
+ echo '<p>' . __( 'If you have already added the redirect rule, you may safely dismiss this notice', 'edd' ) . '</p>';
61
+ echo '<p><a href="' . add_query_arg( array( 'edd_action' => 'dismiss_notices', 'edd_notice' => 'nginx_redirect' ) ) . '">' . __( 'Dismiss Notice', 'edd' ) . '</a></p>';
62
+ echo '</div>';
63
+
64
+ }
65
+
66
+ if( ! edd_htaccess_exists() && ! get_user_meta( get_current_user_id(), '_edd_htaccess_missing_dismissed', true ) && current_user_can( 'manage_shop_settings' ) ) {
67
+ if( ! stristr( $_SERVER['SERVER_SOFTWARE'], 'apache' ) )
68
+ return; // Bail if we aren't using Apache... nginx doesn't use htaccess!
69
+
70
+ echo '<div class="error">';
71
+ echo '<p>' . sprintf( __( 'The Easy Digital Downloads .htaccess file is missing from <strong>%s</strong>!', 'edd' ), edd_get_upload_dir() ) . '</p>';
72
+ echo '<p>' . sprintf( __( 'First, please resave the Misc settings tab a few times. If this warning continues to appear, create a file called ".htaccess" in the <strong>%s</strong> directory, and copy the following into it:', 'edd' ), edd_get_upload_dir() ) . '</p>';
73
+ echo '<p><pre>' . edd_get_htaccess_rules() . '</pre>';
74
+ echo '<p><a href="' . add_query_arg( array( 'edd_action' => 'dismiss_notices', 'edd_notice' => 'htaccess_missing' ) ) . '">' . __( 'Dismiss Notice', 'edd' ) . '</a></p>';
75
+ echo '</div>';
76
+ }
77
+
78
+ if( ! edd_test_ajax_works() && ! get_user_meta( get_current_user_id(), '_edd_admin_ajax_inaccessible_dismissed', true ) && current_user_can( 'manage_shop_settings' ) ) {
79
+ echo '<div class="error">';
80
+ echo '<p>' . __( 'Your site appears to be blocking the WordPress ajax interface. This may causes issues with your store.', 'edd' ) . '</p>';
81
+ echo '<p>' . sprintf( __( 'Please see <a href="%s" target="_blank">this reference</a> for possible solutions.', 'edd' ), 'https://easydigitaldownloads.com/docs/admin-ajax-blocked' ) . '</p>';
82
+ echo '<p><a href="' . add_query_arg( array( 'edd_action' => 'dismiss_notices', 'edd_notice' => 'admin_ajax_inaccessible' ) ) . '">' . __( 'Dismiss Notice', 'edd' ) . '</a></p>';
83
+ echo '</div>';
84
+ }
85
+
86
+ if ( isset( $_GET['edd-message'] ) ) {
87
+ // Shop discounts errors
88
+ if( current_user_can( 'manage_shop_discounts' ) ) {
89
+ switch( $_GET['edd-message'] ) {
90
+ case 'discount_added' :
91
+ $notices['updated']['edd-discount-added'] = __( 'Discount code added.', 'edd' );
92
+ break;
93
+ case 'discount_add_failed' :
94
+ $notices['error']['edd-discount-add-fail'] = __( 'There was a problem adding your discount code, please try again.', 'edd' );
95
+ break;
96
+ case 'discount_exists' :
97
+ $notices['error']['edd-discount-exists'] = __( 'A discount with that code already exists, please use a different code.', 'edd' );
98
+ break;
99
+ case 'discount_updated' :
100
+ $notices['updated']['edd-discount-updated'] = __( 'Discount code updated.', 'edd' );
101
+ break;
102
+ case 'discount_update_failed' :
103
+ $notices['error']['edd-discount-updated-fail'] = __( 'There was a problem updating your discount code, please try again.', 'edd' );
104
+ break;
105
+ }
106
+ }
107
+
108
+ // Shop reports errors
109
+ if( current_user_can( 'view_shop_reports' ) ) {
110
+ switch( $_GET['edd-message'] ) {
111
+ case 'payment_deleted' :
112
+ $notices['updated']['edd-payment-deleted'] = __( 'The payment has been deleted.', 'edd' );
113
+ break;
114
+ case 'email_sent' :
115
+ $notices['updated']['edd-payment-sent'] = __( 'The purchase receipt has been resent.', 'edd' );
116
+ break;
117
+ case 'payment-note-deleted' :
118
+ $notices['updated']['edd-payment-note-deleted'] = __( 'The payment note has been deleted.', 'edd' );
119
+ break;
120
+ }
121
+ }
122
+
123
+ // Shop settings errors
124
+ if( current_user_can( 'manage_shop_settings' ) ) {
125
+ switch( $_GET['edd-message'] ) {
126
+ case 'settings-imported' :
127
+ $notices['updated']['edd-settings-imported'] = __( 'The settings have been imported.', 'edd' );
128
+ break;
129
+ case 'api-key-generated' :
130
+ $notices['updated']['edd-api-key-generated'] = __( 'API keys successfully generated.', 'edd' );
131
+ break;
132
+ case 'api-key-exists' :
133
+ $notices['error']['edd-api-key-exists'] = __( 'The specified user already has API keys.', 'edd' );
134
+ break;
135
+ case 'api-key-regenerated' :
136
+ $notices['updated']['edd-api-key-regenerated'] = __( 'API keys successfully regenerated.', 'edd' );
137
+ break;
138
+ case 'api-key-revoked' :
139
+ $notices['updated']['edd-api-key-revoked'] = __( 'API keys successfully revoked.', 'edd' );
140
+ break;
141
+ }
142
+ }
143
+
144
+ // Shop payments errors
145
+ if( current_user_can( 'edit_shop_payments' ) ) {
146
+ switch( $_GET['edd-message'] ) {
147
+ case 'note-added' :
148
+ $notices['updated']['edd-note-added'] = __( 'The payment note has been added successfully.', 'edd' );
149
+ break;
150
+ case 'payment-updated' :
151
+ $notices['updated']['edd-payment-updated'] = __( 'The payment has been successfully updated.', 'edd' );
152
+ break;
153
+ }
154
+ }
155
+
156
+ // Customer Notices
157
+ if ( current_user_can( 'edit_shop_payments' ) ) {
158
+ switch( $_GET['edd-message'] ) {
159
+ case 'customer-deleted' :
160
+ $notices['updated']['edd-customer-deleted'] = __( 'Customer successfully deleted', 'edd' );
161
+ break;
162
+ }
163
+ }
164
+ }
165
+
166
+ if ( count( $notices['updated'] ) > 0 ) {
167
+ foreach( $notices['updated'] as $notice => $message ) {
168
+ add_settings_error( 'edd-notices', $notice, $message, 'updated' );
169
+ }
170
+ }
171
+
172
+ if ( count( $notices['error'] ) > 0 ) {
173
+ foreach( $notices['error'] as $notice => $message ) {
174
+ add_settings_error( 'edd-notices', $notice, $message, 'error' );
175
+ }
176
+ }
177
+
178
+ settings_errors( 'edd-notices' );
179
+ }
180
+
181
+ /**
182
+ * Dismiss admin notices when Dismiss links are clicked
183
+ *
184
+ * @since 2.3
185
+ * @return void
186
+ */
187
+ function dismiss_notices() {
188
+ if( isset( $_GET['edd_notice'] ) ) {
189
+ update_user_meta( get_current_user_id(), '_edd_' . $_GET['edd_notice'] . '_dismissed', 1 );
190
+ wp_redirect( remove_query_arg( array( 'edd_action', 'edd_notice' ) ) );
191
+ exit;
192
+ }
193
+ }
194
+ }
195
+ new EDD_Notices;
includes/admin/customers/class-customer-table.php ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Customer Reports Table Class
4
+ *
5
+ * @package EDD
6
+ * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
+ * @since 1.5
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
+
15
+ // Load WP_List_Table if not loaded
16
+ if ( ! class_exists( 'WP_List_Table' ) ) {
17
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
18
+ }
19
+
20
+ /**
21
+ * EDD_Customer_Reports_Table Class
22
+ *
23
+ * Renders the Customer Reports table
24
+ *
25
+ * @since 1.5
26
+ */
27
+ class EDD_Customer_Reports_Table extends WP_List_Table {
28
+
29
+ /**
30
+ * Number of items per page
31
+ *
32
+ * @var int
33
+ * @since 1.5
34
+ */
35
+ public $per_page = 30;
36
+
37
+ /**
38
+ * Number of customers found
39
+ *
40
+ * @var int
41
+ * @since 1.7
42
+ */
43
+ public $count = 0;
44
+
45
+ /**
46
+ * Total customers
47
+ *
48
+ * @var int
49
+ * @since 1.95
50
+ */
51
+ public $total = 0;
52
+
53
+ /**
54
+ * Get things started
55
+ *
56
+ * @since 1.5
57
+ * @see WP_List_Table::__construct()
58
+ */
59
+ public function __construct() {
60
+ global $status, $page;
61
+
62
+ // Set parent defaults
63
+ parent::__construct( array(
64
+ 'singular' => __( 'Customer', 'edd' ), // Singular name of the listed records
65
+ 'plural' => __( 'Customers', 'edd' ), // Plural name of the listed records
66
+ 'ajax' => false // Does this table support ajax?
67
+ ) );
68
+
69
+ }
70
+
71
+ /**
72
+ * Show the search field
73
+ *
74
+ * @since 1.7
75
+ * @access public
76
+ *
77
+ * @param string $text Label for the search box
78
+ * @param string $input_id ID of the search box
79
+ *
80
+ * @return void
81
+ */
82
+ public function search_box( $text, $input_id ) {
83
+ $input_id = $input_id . '-search-input';
84
+
85
+ if ( ! empty( $_REQUEST['orderby'] ) )
86
+ echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
87
+ if ( ! empty( $_REQUEST['order'] ) )
88
+ echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
89
+ ?>
90
+ <p class="search-box">
91
+ <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
92
+ <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>" />
93
+ <?php submit_button( $text, 'button', false, false, array('ID' => 'search-submit') ); ?>
94
+ </p>
95
+ <?php
96
+ }
97
+
98
+ /**
99
+ * This function renders most of the columns in the list table.
100
+ *
101
+ * @access public
102
+ * @since 1.5
103
+ *
104
+ * @param array $item Contains all the data of the customers
105
+ * @param string $column_name The name of the column
106
+ *
107
+ * @return string Column Name
108
+ */
109
+ public function column_default( $item, $column_name ) {
110
+ switch ( $column_name ) {
111
+
112
+ case 'num_purchases' :
113
+ $value = '<a href="' .
114
+ admin_url( '/edit.php?post_type=download&page=edd-payment-history&user=' . urlencode( $item['email'] )
115
+ ) . '">' . esc_html( $item['num_purchases'] ) . '</a>';
116
+ break;
117
+
118
+ case 'amount_spent' :
119
+ $value = edd_currency_filter( edd_format_amount( $item[ $column_name ] ) );
120
+ break;
121
+
122
+ case 'date_created' :
123
+ $value = date_i18n( get_option( 'date_format' ), strtotime( $item['date_created'] ) );
124
+ break;
125
+
126
+ default:
127
+ $value = isset( $item[ $column_name ] ) ? $item[ $column_name ] : null;
128
+ break;
129
+ }
130
+ return apply_filters( 'edd_report_column_' . $column_name, $value, $item['id'] );
131
+ }
132
+
133
+ public function column_name( $item ) {
134
+ $name = '#' . $item['id'] . ' ';
135
+ $name .= ! empty( $item['name'] ) ? $item['name'] : '<em>' . __( 'Unnamed Customer', 'edd') . '</em>';
136
+ $user = ! empty( $item['user_id'] ) ? $item['user_id'] : $item['email'];
137
+ $view_url = admin_url( 'edit.php?post_type=download&page=edd-customers&view=overview&id=' . $item['id'] );
138
+ $actions = array(
139
+ 'view' => sprintf( __( '<a href="%s">View</a>', 'edd' ), $view_url ),
140
+ 'logs' => sprintf( __( '<a href="%s">Download log</a>', 'edd' ), admin_url( '/edit.php?post_type=download&page=edd-reports&tab=logs&user=' . urlencode( $user ) ) ),
141
+ 'delete' => sprintf( __( '<a href="%s">Delete</a>', 'edd' ), admin_url( 'edit.php?post_type=download&page=edd-customers&view=delete&id=' . $item['id'] ) )
142
+ );
143
+
144
+ return '<a href="' . esc_url( $view_url ) . '">' . $name . '</a>' . $this->row_actions( $actions );
145
+ }
146
+
147
+ /**
148
+ * Retrieve the table columns
149
+ *
150
+ * @access public
151
+ * @since 1.5
152
+ * @return array $columns Array of all the list table columns
153
+ */
154
+ public function get_columns() {
155
+ $columns = array(
156
+ 'name' => __( 'Name', 'edd' ),
157
+ 'email' => __( 'Email', 'edd' ),
158
+ 'num_purchases' => __( 'Purchases', 'edd' ),
159
+ 'amount_spent' => __( 'Total Spent', 'edd' ),
160
+ 'date_created' => __( 'Date Created', 'edd' )
161
+ );
162
+
163
+ return apply_filters( 'edd_report_customer_columns', $columns );
164
+
165
+ }
166
+
167
+ /**
168
+ * Get the sortable columns
169
+ *
170
+ * @access public
171
+ * @since 2.1
172
+ * @return array Array of all the sortable columns
173
+ */
174
+ public function get_sortable_columns() {
175
+ return array(
176
+ 'date_created' => array( 'date_created', true ),
177
+ 'name' => array( 'name', true ),
178
+ 'num_purchases' => array( 'purchase_count', false ),
179
+ 'amount_spent' => array( 'purchase_value', false ),
180
+ );
181
+ }
182
+
183
+ /**
184
+ * Outputs the reporting views
185
+ *
186
+ * @access public
187
+ * @since 1.5
188
+ * @return void
189
+ */
190
+ public function bulk_actions( $which = '' ) {
191
+ // These aren't really bulk actions but this outputs the markup in the right place
192
+ }
193
+
194
+ /**
195
+ * Retrieve the current page number
196
+ *
197
+ * @access public
198
+ * @since 1.5
199
+ * @return int Current page number
200
+ */
201
+ public function get_paged() {
202
+ return isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1;
203
+ }
204
+
205
+ /**
206
+ * Retrieves the search query string
207
+ *
208
+ * @access public
209
+ * @since 1.7
210
+ * @return mixed string If search is present, false otherwise
211
+ */
212
+ public function get_search() {
213
+ return ! empty( $_GET['s'] ) ? urldecode( trim( $_GET['s'] ) ) : false;
214
+ }
215
+
216
+ /**
217
+ * Build all the reports data
218
+ *
219
+ * @access public
220
+ * @since 1.5
221
+ * @global object $wpdb Used to query the database using the WordPress
222
+ * Database API
223
+ * @return array $reports_data All the data for customer reports
224
+ */
225
+ public function reports_data() {
226
+ global $wpdb;
227
+
228
+ $data = array();
229
+ $paged = $this->get_paged();
230
+ $offset = $this->per_page * ( $paged - 1 );
231
+ $search = $this->get_search();
232
+ $order = isset( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'DESC';
233
+ $orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'id';
234
+
235
+ $args = array(
236
+ 'number' => $this->per_page,
237
+ 'offset' => $offset,
238
+ 'order' => $order,
239
+ 'orderby' => $orderby
240
+ );
241
+
242
+ if( is_email( $search ) ) {
243
+ $args['email'] = $search;
244
+ } elseif( is_numeric( $search ) ) {
245
+ $args['id'] = $search;
246
+ } else {
247
+ $args['name'] = $search;
248
+ }
249
+
250
+ $customers = EDD()->customers->get_customers( $args );
251
+
252
+ if ( $customers ) {
253
+
254
+ foreach ( $customers as $customer ) {
255
+
256
+ $user_id = ! empty( $customer->user_id ) ? intval( $customer->user_id ) : 0;
257
+
258
+ $data[] = array(
259
+ 'id' => $customer->id,
260
+ 'user_id' => $user_id,
261
+ 'name' => $customer->name,
262
+ 'email' => $customer->email,
263
+ 'num_purchases' => $customer->purchase_count,
264
+ 'amount_spent' => $customer->purchase_value,
265
+ 'date_created' => $customer->date_created,
266
+ );
267
+ }
268
+ }
269
+
270
+ return $data;
271
+ }
272
+
273
+ /**
274
+ * Setup the final data for the table
275
+ *
276
+ * @access public
277
+ * @since 1.5
278
+ * @uses EDD_Customer_Reports_Table::get_columns()
279
+ * @uses WP_List_Table::get_sortable_columns()
280
+ * @uses EDD_Customer_Reports_Table::get_pagenum()
281
+ * @uses EDD_Customer_Reports_Table::get_total_customers()
282
+ * @return void
283
+ */
284
+ public function prepare_items() {
285
+
286
+ $columns = $this->get_columns();
287
+ $hidden = array(); // No hidden columns
288
+ $sortable = $this->get_sortable_columns();
289
+
290
+ $this->_column_headers = array( $columns, $hidden, $sortable );
291
+
292
+ $this->items = $this->reports_data();
293
+
294
+ $this->total = edd_count_total_customers();
295
+
296
+ $this->set_pagination_args( array(
297
+ 'total_items' => $this->total,
298
+ 'per_page' => $this->per_page,
299
+ 'total_pages' => ceil( $this->total / $this->per_page )
300
+ ) );
301
+ }
302
+ }
includes/admin/customers/customer-actions.php ADDED
@@ -0,0 +1,373 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+
6
+ /**
7
+ * Processes a custom edit
8
+ *
9
+ * @since 2.3
10
+ * @param array $args The $_POST array being passeed
11
+ * @return array $output Response messages
12
+ */
13
+ function edd_edit_customer( $args ) {
14
+ $customer_edit_role = apply_filters( 'edd_edit_customers_role', 'edit_shop_payments' );
15
+
16
+ if ( ! is_admin() || ! current_user_can( $customer_edit_role ) ) {
17
+ wp_die( __( 'You do not have permission to edit this customer.', 'edd' ) );
18
+ }
19
+
20
+ if ( empty( $args ) ) {
21
+ return;
22
+ }
23
+
24
+ $customer_info = $args['customerinfo'];
25
+ $customer_id = (int)$args['customerinfo']['id'];
26
+ $nonce = $args['_wpnonce'];
27
+
28
+ if ( ! wp_verify_nonce( $nonce, 'edit-customer' ) ) {
29
+ wp_die( __( 'Cheatin\' eh?!', 'edd' ) );
30
+ }
31
+
32
+ $customer = new EDD_Customer( $customer_id );
33
+ if ( empty( $customer->id ) ) {
34
+ return false;
35
+ }
36
+
37
+ $defaults = array(
38
+ 'name' => '',
39
+ 'email' => '',
40
+ 'user_id' => 0
41
+ );
42
+
43
+ $customer_info = wp_parse_args( $customer_info, $defaults );
44
+
45
+ if ( ! is_email( $customer_info['email'] ) ) {
46
+ edd_set_error( 'edd-invalid-email', __( 'Please enter a valid email address.', 'edd' ) );
47
+ }
48
+
49
+ if ( (int) $customer_info['user_id'] != (int) $customer->user_id ) {
50
+
51
+ // Make sure we don't already have this user attached to a customer
52
+ if ( ! empty( $customer_info['user_id'] ) && false !== EDD()->customers->get_customer_by( 'user_id', $customer_info['user_id'] ) ) {
53
+ edd_set_error( 'edd-invalid-customer-user_id', sprintf( __( 'The User ID %d is already associated with a different customer.', 'edd' ), $customer_info['user_id'] ) );
54
+ }
55
+
56
+ // Make sure it's actually a user
57
+ $user = get_user_by( 'id', $customer_info['user_id'] );
58
+ if ( ! empty( $customer_info['user_id'] ) && false === $user ) {
59
+ edd_set_error( 'edd-invalid-user_id', sprintf( __( 'The User ID %d does not exist. Please assign an existing user.', 'edd' ), $customer_info['user_id'] ) );
60
+ }
61
+
62
+ }
63
+
64
+ // Record this for later
65
+ $previous_user_id = $customer->user_id;
66
+
67
+ if ( edd_get_errors() ) {
68
+ return;
69
+ }
70
+
71
+ // Setup the customer address, if present
72
+ $address = array();
73
+ if ( intval( $customer_info['user_id'] ) > 0 ) {
74
+
75
+ $current_address = get_user_meta( $customer_info['user_id'], '_edd_user_address', true );
76
+
77
+ if ( false === $current_address ) {
78
+ $address['line1'] = isset( $customer_info['line1'] ) ? $customer_info['line1'] : '';
79
+ $address['line2'] = isset( $customer_info['line2'] ) ? $customer_info['line2'] : '';
80
+ $address['city'] = isset( $customer_info['city'] ) ? $customer_info['city'] : '';
81
+ $address['country'] = isset( $customer_info['country'] ) ? $customer_info['country'] : '';
82
+ $address['zip'] = isset( $customer_info['zip'] ) ? $customer_info['zip'] : '';
83
+ $address['state'] = isset( $customer_info['state'] ) ? $customer_info['state'] : '';
84
+ } else {
85
+ $current_address = wp_parse_args( $current_address, array( 'line1', 'line2', 'city', 'zip', 'state', 'country' ) );
86
+ $address['line1'] = isset( $customer_info['line1'] ) ? $customer_info['line1'] : $current_address['line1'] ;
87
+ $address['line2'] = isset( $customer_info['line2'] ) ? $customer_info['line2'] : $current_address['line2'] ;
88
+ $address['city'] = isset( $customer_info['city'] ) ? $customer_info['city'] : $current_address['city'] ;
89
+ $address['country'] = isset( $customer_info['country'] ) ? $customer_info['country'] : $current_address['country'];
90
+ $address['zip'] = isset( $customer_info['zip'] ) ? $customer_info['zip'] : $current_address['zip'] ;
91
+ $address['state'] = isset( $customer_info['state'] ) ? $customer_info['state'] : $current_address['state'] ;
92
+ }
93
+
94
+ }
95
+
96
+ // Sanitize the inputs
97
+ $customer_data = array();
98
+ $customer_data['name'] = $customer_info['name'];
99
+ $customer_data['email'] = $customer_info['email'];
100
+ $customer_data['user_id'] = $customer_info['user_id'];
101
+
102
+ $customer_data = apply_filters( 'edd_edit_customer_info', $customer_data, $customer_id );
103
+ $address = apply_filters( 'edd_edit_customer_address', $address, $customer_id );
104
+
105
+ $customer_data = array_map( 'sanitize_text_field', $customer_data );
106
+ $address = array_map( 'sanitize_text_field', $address );
107
+
108
+ do_action( 'edd_pre_edit_customer', $customer_id, $customer_data, $address );
109
+
110
+ $output = array();
111
+ $previous_email = $customer->email;
112
+
113
+ if ( $customer->update( $customer_data ) ) {
114
+
115
+ if ( ! empty( $customer->user_id ) && $customer->user_id > 0 ) {
116
+ update_user_meta( $customer->user_id, '_edd_user_address', $address );
117
+ }
118
+
119
+ // Update some payment meta if we need to
120
+ $payments_array = explode( ',', $customer->payment_ids );
121
+
122
+ if ( $customer->email != $previous_email ) {
123
+ foreach ( $payments_array as $payment_id ) {
124
+ edd_update_payment_meta( $payment_id, 'email', $customer->email );
125
+ }
126
+ }
127
+
128
+ if ( $customer->user_id != $previous_user_id ) {
129
+ foreach ( $payments_array as $payment_id ) {
130
+ edd_update_payment_meta( $payment_id, '_edd_payment_user_id', $customer->user_id );
131
+ }
132
+ }
133
+
134
+ $output['success'] = true;
135
+ $customer_data = array_merge( $customer_data, $address );
136
+ $output['customer_info'] = $customer_data;
137
+
138
+ } else {
139
+
140
+ $output['success'] = false;
141
+
142
+ }
143
+
144
+ do_action( 'edd_post_edit_customer', $customer_id, $customer_data );
145
+
146
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
147
+ header( 'Content-Type: application/json' );
148
+ echo json_encode( $output );
149
+ wp_die();
150
+ }
151
+
152
+ return $output;
153
+
154
+ }
155
+ add_action( 'edd_edit-customer', 'edd_edit_customer', 10, 1 );
156
+
157
+ /**
158
+ * Save a customer note being added
159
+ *
160
+ * @since 2.3
161
+ * @param array $args The $_POST array being passeed
162
+ * @return int The Note ID that was saved, or 0 if nothing was saved
163
+ */
164
+ function edd_customer_save_note( $args ) {
165
+
166
+ $customer_view_role = apply_filters( 'edd_view_customers_role', 'view_shop_reports' );
167
+
168
+ if ( ! is_admin() || ! current_user_can( $customer_view_role ) ) {
169
+ wp_die( __( 'You do not have permission to edit this customer.', 'edd' ) );
170
+ }
171
+
172
+ if ( empty( $args ) ) {
173
+ return;
174
+ }
175
+
176
+ $customer_note = trim( sanitize_text_field( $args['customer_note'] ) );
177
+ $customer_id = (int)$args['customer_id'];
178
+ $nonce = $args['add_customer_note_nonce'];
179
+
180
+ if ( ! wp_verify_nonce( $nonce, 'add-customer-note' ) ) {
181
+ wp_die( __( 'Cheatin\' eh?!', 'edd' ) );
182
+ }
183
+
184
+ if ( empty( $customer_note ) ) {
185
+ edd_set_error( 'empty-customer-note', __( 'A note is required', 'edd' ) );
186
+ }
187
+
188
+ if ( edd_get_errors() ) {
189
+ return;
190
+ }
191
+
192
+ $customer = new EDD_Customer( $customer_id );
193
+ $new_note = $customer->add_note( $customer_note );
194
+
195
+ do_action( 'edd_pre_insert_customer_note', $customer_id, $new_note );
196
+
197
+ if ( ! empty( $new_note ) && ! empty( $customer->id ) ) {
198
+
199
+ ob_start();
200
+ ?>
201
+ <div class="customer-note-wrapper dashboard-comment-wrap comment-item">
202
+ <span class="note-content-wrap">
203
+ <?php echo stripslashes( $new_note ); ?>
204
+ </span>
205
+ </div>
206
+ <?php
207
+ $output = ob_get_contents();
208
+ ob_end_clean();
209
+
210
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
211
+ echo $output;
212
+ exit;
213
+ }
214
+
215
+ return $new_note;
216
+
217
+ }
218
+
219
+ return false;
220
+
221
+ }
222
+ add_action( 'edd_add-customer-note', 'edd_customer_save_note', 10, 1 );
223
+
224
+ /**
225
+ * Delete a customer
226
+ *
227
+ * @since 2.3
228
+ * @param array $args The $_POST array being passeed
229
+ * @return int Wether it was a successful deletion
230
+ */
231
+ function edd_customer_delete( $args ) {
232
+
233
+ $customer_edit_role = apply_filters( 'edd_edit_customers_role', 'edit_shop_payments' );
234
+
235
+ if ( ! is_admin() || ! current_user_can( $customer_edit_role ) ) {
236
+ wp_die( __( 'You do not have permission to delete this customer.', 'edd' ) );
237
+ }
238
+
239
+ if ( empty( $args ) ) {
240
+ return;
241
+ }
242
+
243
+ $customer_id = (int)$args['customer_id'];
244
+ $confirm = ! empty( $args['edd-customer-delete-confirm'] ) ? true : false;
245
+ $remove_data = ! empty( $args['edd-customer-delete-records'] ) ? true : false;
246
+ $nonce = $args['_wpnonce'];
247
+
248
+ if ( ! wp_verify_nonce( $nonce, 'delete-customer' ) ) {
249
+ wp_die( __( 'Cheatin\' eh?!', 'edd' ) );
250
+ }
251
+
252
+ if ( ! $confirm ) {
253
+ edd_set_error( 'customer-delete-no-confirm', __( 'Please confirm you want to delete this customer', 'edd' ) );
254
+ }
255
+
256
+ if ( edd_get_errors() ) {
257
+ wp_redirect( admin_url( 'edit.php?post_type=download&page=edd-customers&view=overview&id=' . $customer_id ) );
258
+ exit;
259
+ }
260
+
261
+ $customer = new EDD_Customer( $customer_id );
262
+
263
+ do_action( 'edd_pre_delete_customer', $customer_id, $confirm, $remove_data );
264
+
265
+ $success = false;
266
+
267
+ if ( $customer->id > 0 ) {
268
+
269
+ $payments_array = explode( ',', $customer->payment_ids );
270
+ $success = EDD()->customers->delete( $customer->id );
271
+
272
+ if ( $success ) {
273
+
274
+ if ( $remove_data ) {
275
+
276
+ // Remove all payments, logs, etc
277
+ foreach ( $payments_array as $payment_id ) {
278
+ edd_delete_purchase( $payment_id, false, true );
279
+ }
280
+
281
+ } else {
282
+
283
+ // Just set the payments to customer_id of 0
284
+ foreach ( $payments_array as $payment_id ) {
285
+ edd_update_payment_meta( $payment_id, '_edd_payment_customer_id', 0 );
286
+ }
287
+
288
+ }
289
+
290
+ $redirect = admin_url( 'edit.php?post_type=download&page=edd-customers&edd-message=customer-deleted' );
291
+
292
+ } else {
293
+
294
+ edd_set_error( 'edd-customer-delete-failed', __( 'Error deleting customer', 'edd' ) );
295
+ $redirect = admin_url( 'edit.php?post_type=download&page=edd-customers&view=delete&id=' . $customer_id );
296
+
297
+ }
298
+
299
+ } else {
300
+
301
+ edd_set_error( 'edd-customer-delete-invalid-id', __( 'Invalid Customer ID', 'edd' ) );
302
+ $redirect = admin_url( 'edit.php?post_type=download&page=edd-customers' );
303
+
304
+ }
305
+
306
+ wp_redirect( $redirect );
307
+ exit;
308
+
309
+ }
310
+ add_action( 'edd_delete-customer', 'edd_customer_delete', 10, 1 );
311
+
312
+ /**
313
+ * Disconnect a user ID from a customer
314
+ *
315
+ * @since 2.3
316
+ * @param array $args Array of arguements
317
+ * @return bool If the disconnect was sucessful
318
+ */
319
+ function edd_disconnect_customer_user_id( $args ) {
320
+
321
+ $customer_edit_role = apply_filters( 'edd_edit_customers_role', 'edit_shop_payments' );
322
+
323
+ if ( ! is_admin() || ! current_user_can( $customer_edit_role ) ) {
324
+ wp_die( __( 'You do not have permission to edit this customer.', 'edd' ) );
325
+ }
326
+
327
+ if ( empty( $args ) ) {
328
+ return;
329
+ }
330
+
331
+ $customer_id = (int)$args['customer_id'];
332
+ $nonce = $args['_wpnonce'];
333
+
334
+ if ( ! wp_verify_nonce( $nonce, 'edit-customer' ) ) {
335
+ wp_die( __( 'Cheatin\' eh?!', 'edd' ) );
336
+ }
337
+
338
+ $customer = new EDD_Customer( $customer_id );
339
+ if ( empty( $customer->id ) ) {
340
+ return false;
341
+ }
342
+
343
+ do_action( 'edd_pre_customer_disconnect_user_id', $customer_id, $customer->user_id );
344
+
345
+ $customer_args = array( 'user_id' => 0 );
346
+
347
+ if ( $customer->update( $customer_args ) ) {
348
+ global $wpdb;
349
+
350
+ if ( ! empty( $customer->payment_ids ) ) {
351
+ $wpdb->query( "UPDATE $wpdb->postmeta SET meta_value = 0 WHERE meta_key = '_edd_payment_user_id' AND post_id IN ( $customer->payment_ids )" );
352
+ }
353
+
354
+ $output['success'] = true;
355
+
356
+ } else {
357
+
358
+ $output['success'] = false;
359
+ edd_set_error( 'edd-disconnect-user-fail', __( 'Failed to disconnect user from customer', 'edd' ) );
360
+ }
361
+
362
+ do_action( 'edd_post_customer_disconnect_user_id', $customer_id );
363
+
364
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
365
+ header( 'Content-Type: application/json' );
366
+ echo json_encode( $output );
367
+ wp_die();
368
+ }
369
+
370
+ return $output;
371
+
372
+ }
373
+ add_action( 'edd_disconnect-userid', 'edd_disconnect_customer_user_id', 10, 1 );
includes/admin/customers/customer-functions.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+
6
+ /**
7
+ * Register a view for the single customer view
8
+ *
9
+ * @since 2.3
10
+ * @param array $views An array of existing views
11
+ * @return array The altered list of views
12
+ */
13
+ function edd_register_default_customer_views( $views ) {
14
+
15
+ $default_views = array(
16
+ 'overview' => 'edd_customers_view',
17
+ 'delete' => 'edd_customers_delete_view',
18
+ 'notes' => 'edd_customer_notes_view'
19
+ );
20
+
21
+ return array_merge( $views, $default_views );
22
+
23
+ }
24
+ add_filter( 'edd_customer_views', 'edd_register_default_customer_views', 1, 1 );
25
+
26
+ /**
27
+ * Register a tab for the single customer view
28
+ *
29
+ * @since 2.3
30
+ * @param array $tabs An array of existing tabs
31
+ * @return array The altered list of tabs
32
+ */
33
+ function edd_register_default_customer_tabs( $tabs ) {
34
+
35
+ $default_tabs = array(
36
+ 'overview' => array( 'dashicon' => 'dashicons-admin-users', 'title' => __( 'Customer Profile', 'edd' ) ),
37
+ 'notes' => array( 'dashicon' => 'dashicons-admin-comments', 'title' => __( 'Customer Notes', 'edd' ) )
38
+ );
39
+
40
+ return array_merge( $tabs, $default_tabs );
41
+ }
42
+ add_filter( 'edd_customer_tabs', 'edd_register_default_customer_tabs', 1, 1 );
43
+
44
+ /**
45
+ * Register the Delete icon as late as possible so it's at the bottom
46
+ *
47
+ * @since 2.3.1
48
+ * @param array $tabs An array of existing tabs
49
+ * @return array The altered list of tabs, with 'delete' at the bottom
50
+ */
51
+ function edd_register_delete_customer_tab( $tabs ) {
52
+
53
+ $tabs['delete'] = array( 'dashicon' => 'dashicons-trash', 'title' => __( 'Delete Customer', 'edd' ) );
54
+
55
+ return $tabs;
56
+ }
57
+ add_filter( 'edd_customer_tabs', 'edd_register_delete_customer_tab', PHP_INT_MAX, 1 );
includes/admin/customers/customers.php ADDED
@@ -0,0 +1,531 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+
6
+ /**
7
+ * Customers Page
8
+ *
9
+ * Renders the customers page contents.
10
+ *
11
+ * @since 2.3
12
+ * @return void
13
+ */
14
+ function edd_customers_page() {
15
+ $default_views = edd_customer_views();
16
+ $requested_view = isset( $_GET['view'] ) ? sanitize_text_field( $_GET['view'] ) : 'customers';
17
+ if ( array_key_exists( $requested_view, $default_views ) && function_exists( $default_views[$requested_view] ) ) {
18
+ edd_render_customer_view( $requested_view, $default_views );
19
+ } else {
20
+ edd_customers_list();
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Register the views for customer management
26
+ *
27
+ * @since 2.3
28
+ * @return array Array of views and their callbacks
29
+ */
30
+ function edd_customer_views() {
31
+
32
+ $views = array();
33
+ return apply_filters( 'edd_customer_views', $views );
34
+
35
+ }
36
+
37
+ /**
38
+ * Register the tabs for customer management
39
+ *
40
+ * @since 2.3
41
+ * @return array Array of tabs for the customer
42
+ */
43
+ function edd_customer_tabs() {
44
+
45
+ $tabs = array();
46
+ return apply_filters( 'edd_customer_tabs', $tabs );
47
+
48
+ }
49
+
50
+ /**
51
+ * List table of customers
52
+ *
53
+ * @since 2.3
54
+ * @return void
55
+ */
56
+ function edd_customers_list() {
57
+ include( dirname( __FILE__ ) . '/class-customer-table.php' );
58
+
59
+ $customers_table = new EDD_Customer_Reports_Table();
60
+ $customers_table->prepare_items();
61
+ ?>
62
+ <div class="wrap">
63
+ <h2><?php _e( 'Customers', 'edd' ); ?></h2>
64
+ <?php do_action( 'edd_customers_table_top' ); ?>
65
+ <form id="edd-customers-filter" method="get" action="<?php echo admin_url( 'edit.php?post_type=download&page=edd-customers' ); ?>">
66
+ <?php
67
+ $customers_table->search_box( __( 'Search Customers', 'edd' ), 'edd-customers' );
68
+ $customers_table->display();
69
+ ?>
70
+ <input type="hidden" name="post_type" value="download" />
71
+ <input type="hidden" name="page" value="edd-customers" />
72
+ <input type="hidden" name="view" value="customers" />
73
+ </form>
74
+ <?php do_action( 'edd_customers_table_bottom' ); ?>
75
+ </div>
76
+ <?php
77
+ }
78
+
79
+ /**
80
+ * Renders the customer view wrapper
81
+ *
82
+ * @since 2.3
83
+ * @param string $view The View being requested
84
+ * @param array $callbacks The Registered views and their callback functions
85
+ * @return void
86
+ */
87
+ function edd_render_customer_view( $view, $callbacks ) {
88
+
89
+ $render = true;
90
+
91
+ $customer_view_role = apply_filters( 'edd_view_customers_role', 'view_shop_reports' );
92
+
93
+ if ( ! current_user_can( $customer_view_role ) ) {
94
+ edd_set_error( 'edd-no-access', __( 'You are not permitted to view this data.', 'edd' ) );
95
+ $render = false;
96
+ }
97
+
98
+ if ( ! isset( $_GET['id'] ) || ! is_numeric( $_GET['id'] ) ) {
99
+ edd_set_error( 'edd-invalid_customer', __( 'Invalid Customer ID Provided.', 'edd' ) );
100
+ $render = false;
101
+ }
102
+
103
+ $customer_id = (int)$_GET['id'];
104
+ $customer = new EDD_Customer( $customer_id );
105
+
106
+ if ( empty( $customer->id ) ) {
107
+ edd_set_error( 'edd-invalid_customer', __( 'Invalid Customer ID Provided.', 'edd' ) );
108
+ $render = false;
109
+ }
110
+
111
+ $customer_tabs = edd_customer_tabs();
112
+ ?>
113
+
114
+ <div class='wrap'>
115
+ <h2><?php _e( 'Customer Details', 'edd' );?></h2>
116
+ <?php if ( edd_get_errors() ) :?>
117
+ <div class="error settings-error">
118
+ <?php edd_print_errors(); ?>
119
+ </div>
120
+ <?php endif; ?>
121
+
122
+ <?php if ( $customer && $render ) : ?>
123
+
124
+ <div id="customer-tab-wrapper">
125
+ <ul id="customer-tab-wrapper-list">
126
+ <?php foreach ( $customer_tabs as $key => $tab ) : ?>
127
+ <?php $active = $key === $view ? true : false; ?>
128
+ <?php $class = $active ? 'active' : 'inactive'; ?>
129
+
130
+ <?php if ( ! $active ) : ?>
131
+ <a title="<?php echo esc_attr( $tab['title'] ); ?>" aria-label="<?php echo esc_attr( $tab['title'] ); ?>" href="<?php echo esc_url( admin_url( 'edit.php?post_type=download&page=edd-customers&view=' . $key . '&id=' . $customer->id ) ); ?>">
132
+ <?php endif; ?>
133
+
134
+ <li class="<?php echo sanitize_html_class( $class ); ?>"><span class="dashicons <?php echo sanitize_html_class( $tab['dashicon'] ); ?>"></span></li>
135
+
136
+ <?php if ( ! $active ) : ?>
137
+ </a>
138
+ <?php endif; ?>
139
+
140
+ <?php endforeach; ?>
141
+ </ul>
142
+ </div>
143
+
144
+ <div id="edd-customer-card-wrapper" style="float: left">
145
+ <?php $callbacks[$view]( $customer ) ?>
146
+ </div>
147
+
148
+ <?php endif; ?>
149
+
150
+ </div>
151
+ <?php
152
+
153
+ }
154
+
155
+
156
+ /**
157
+ * View a customer
158
+ *
159
+ * @since 2.3
160
+ * @param $customer The Customer object being displayed
161
+ * @return void
162
+ */
163
+ function edd_customers_view( $customer ) {
164
+
165
+ $customer_edit_role = apply_filters( 'edd_edit_customers_role', 'edit_shop_payments' );
166
+
167
+ ?>
168
+
169
+ <?php do_action( 'edd_customer_card_top', $customer ); ?>
170
+
171
+ <div class="info-wrapper customer-section">
172
+
173
+ <form id="edit-customer-info" method="post" action="<?php echo admin_url( 'edit.php?post_type=download&page=edd-customers&view=overview&id=' . $customer->id ); ?>">
174
+
175
+ <div class="customer-info">
176
+
177
+ <div class="avatar-wrap left" id="customer-avatar">
178
+ <?php echo get_avatar( $customer->email ); ?><br />
179
+ <?php if ( current_user_can( $customer_edit_role ) ): ?>
180
+ <span class="info-item editable customer-edit-link"><a title="<?php _e( 'Edit Customer', 'edd' ); ?>" href="#" id="edit-customer"><?php _e( 'Edit Customer', 'edd' ); ?></a></span>
181
+ <?php endif; ?>
182
+ </div>
183
+
184
+ <div class="customer-id right">
185
+ #<?php echo $customer->id; ?>
186
+ </div>
187
+
188
+ <div class="customer-address-wrapper right">
189
+ <?php if ( isset( $customer->user_id ) && $customer->user_id > 0 ) : ?>
190
+
191
+ <?php
192
+ $address = get_user_meta( $customer->user_id, '_edd_user_address', true );
193
+ $defaults = array(
194
+ 'line1' => '',
195
+ 'line2' => '',
196
+ 'city' => '',
197
+ 'state' => '',
198
+ 'country' => '',
199
+ 'zip' => ''
200
+ );
201
+
202
+ $address = wp_parse_args( $address, $defaults );
203
+ ?>
204
+
205
+ <?php if ( ! empty( $address ) ) : ?>
206
+ <strong><?php _e( 'Customer Address', 'edd' ); ?></strong>
207
+ <span class="customer-address info-item editable">
208
+ <span class="info-item" data-key="line1"><?php echo $address['line1']; ?></span>
209
+ <span class="info-item" data-key="line2"><?php echo $address['line2']; ?></span>
210
+ <span class="info-item" data-key="city"><?php echo $address['city']; ?></span>
211
+ <span class="info-item" data-key="state"><?php echo $address['state']; ?></span>
212
+ <span class="info-item" data-key="country"><?php echo $address['country']; ?></span>
213
+ <span class="info-item" data-key="zip"><?php echo $address['zip']; ?></span>
214
+ </span>
215
+ <?php endif; ?>
216
+ <span class="customer-address info-item edit-item">
217
+ <input class="info-item" type="text" data-key="line1" name="customerinfo[line1]" placeholder="<?php _e( 'Address 1', 'edd' ); ?>" value="<?php echo $address['line1']; ?>" />
218
+ <input class="info-item" type="text" data-key="line2" name="customerinfo[line2]" placeholder="<?php _e( 'Address 2', 'edd' ); ?>" value="<?php echo $address['line2']; ?>" />
219
+ <input class="info-item" type="text" data-key="city" name="customerinfo[city]" placeholder="<?php _e( 'City', 'edd' ); ?>" value="<?php echo $address['city']; ?>" />
220
+ <select data-key="country" name="customerinfo[country]" id="billing_country" class="billing_country edd-select edit-item">
221
+ <?php
222
+
223
+ $selected_country = $address['country'];
224
+
225
+ $countries = edd_get_country_list();
226
+ foreach( $countries as $country_code => $country ) {
227
+ echo '<option value="' . esc_attr( $country_code ) . '"' . selected( $country_code, $selected_country, false ) . '>' . $country . '</option>';
228
+ }
229
+ ?>
230
+ </select>
231
+ <?php
232
+ $selected_state = edd_get_shop_state();
233
+ $states = edd_get_shop_states( $selected_country );
234
+
235
+ $selected_state = isset( $address['state'] ) ? $address['state'] : $selected_state;
236
+
237
+ if( ! empty( $states ) ) : ?>
238
+ <select data-key="state" name="customerinfo[state]" id="card_state" class="card_state edd-select info-item">
239
+ <?php
240
+ foreach( $states as $state_code => $state ) {
241
+ echo '<option value="' . $state_code . '"' . selected( $state_code, $selected_state, false ) . '>' . $state . '</option>';
242
+ }
243
+ ?>
244
+ </select>
245
+ <?php else : ?>
246
+ <input type="text" size="6" data-key="state" name="customerinfo[state]" id="card_state" class="card_state edd-input info-item" placeholder="<?php _e( 'State / Province', 'edd' ); ?>"/>
247
+ <?php endif; ?>
248
+ <input class="info-item" type="text" data-key="zip" name="customerinfo[zip]" placeholder="<?php _e( 'Postal', 'edd' ); ?>" value="<?php echo $address['zip']; ?>" />
249
+ </span>
250
+ <?php endif; ?>
251
+ </div>
252
+
253
+ <div class="customer-main-wrapper left">
254
+
255
+ <span class="customer-name info-item edit-item"><input size="15" data-key="name" name="customerinfo[name]" type="text" value="<?php echo $customer->name; ?>" placeholder="<?php _e( 'Customer Name', 'edd' ); ?>" /></span>
256
+ <span class="customer-name info-item editable"><span data-key="name"><?php echo $customer->name; ?></span></span>
257
+ <span class="customer-name info-item edit-item"><input size="20" data-key="email" name="customerinfo[email]" type="text" value="<?php echo $customer->email; ?>" placeholder="<?php _e( 'Customer Email', 'edd' ); ?>" /></span>
258
+ <span class="customer-email info-item editable" data-key="email"><?php echo $customer->email; ?></span>
259
+ <span class="customer-since info-item">
260
+ <?php _e( 'Customer since', 'edd' ); ?>
261
+ <?php echo date_i18n( get_option( 'date_format' ), strtotime( $customer->date_created ) ) ?>
262
+ </span>
263
+ <span class="customer-user-id info-item edit-item">
264
+ <?php
265
+
266
+ $user_id = $customer->user_id > 0 ? $customer->user_id : '';
267
+ $data_atts = array( 'key' => 'user_login', 'exclude' => $user_id );
268
+ $user_args = array(
269
+ 'name' => 'customerinfo[user_login]',
270
+ 'class' => 'edd-user-dropdown',
271
+ 'data' => $data_atts,
272
+ );
273
+
274
+ if( ! empty( $user_id ) ) {
275
+ $userdata = get_userdata( $user_id );
276
+ $user_args['value'] = $userdata->user_login;
277
+ }
278
+
279
+ echo EDD()->html->ajax_user_search( $user_args );
280
+ ?>
281
+ <input type="hidden" name="customerinfo[user_id]" data-key="user_id" value="<?php echo $customer->user_id; ?>" />
282
+ </span>
283
+
284
+ <span class="customer-user-id info-item editable">
285
+ <?php _e( 'User ID', 'edd' ); ?>:&nbsp;
286
+ <?php if( intval( $customer->user_id ) > 0 ) : ?>
287
+ <span data-key="user_id"><?php echo $customer->user_id; ?></span>
288
+ <?php else : ?>
289
+ <span data-key="user_id"><?php _e( 'none', 'edd' ); ?></span>
290
+ <?php endif; ?>
291
+ <?php if ( current_user_can( $customer_edit_role ) && intval( $customer->user_id ) > 0 ) : ?>
292
+ <span class="disconnect-user"> - <a id="disconnect-customer" href="#disconnect" title="<?php _e( 'Disconnects the current user ID from this customer record', 'edd' ); ?>"><?php _e( 'Disconnect User', 'edd' ); ?></a></span>
293
+ <?php endif; ?>
294
+ </span>
295
+
296
+ </div>
297
+
298
+ </div>
299
+
300
+ <span id="customer-edit-actions" class="edit-item">
301
+ <input type="hidden" data-key="id" name="customerinfo[id]" value="<?php echo $customer->id; ?>" />
302
+ <?php wp_nonce_field( 'edit-customer', '_wpnonce', false, true ); ?>
303
+ <input type="hidden" name="edd_action" value="edit-customer" />
304
+ <input type="submit" id="edd-edit-customer-save" class="button-secondary" value="<?php _e( 'Update Customer', 'edd' ); ?>" />
305
+ <a id="edd-edit-customer-cancel" href="" class="delete"><?php _e( 'Cancel', 'edd' ); ?></a>
306
+ </span>
307
+
308
+ </form>
309
+ </div>
310
+
311
+ <?php do_action( 'edd_customer_before_stats', $customer ); ?>
312
+
313
+ <div id="customer-stats-wrapper" class="customer-section">
314
+ <ul>
315
+ <li>
316
+ <a title="<?php _e( 'View All Purchases', 'edd' ); ?>" href="<?php echo admin_url( 'edit.php?post_type=download&page=edd-payment-history&user=' . urlencode( $customer->email ) ); ?>">
317
+ <span class="dashicons dashicons-cart"></span>
318
+ <?php printf( _n( '%d Completed Sale', '%d Completed Sales', $customer->purchase_count, 'edd' ), $customer->purchase_count ); ?>
319
+ </a>
320
+ </li>
321
+ <li>
322
+ <span class="dashicons dashicons-chart-area"></span>
323
+ <?php echo edd_currency_filter( edd_format_amount( $customer->purchase_value ) ); ?> <?php _e( 'Lifetime Value', 'edd' ); ?>
324
+ </li>
325
+ <?php do_action( 'edd_customer_stats_list', $customer ); ?>
326
+ </ul>
327
+ </div>
328
+
329
+ <?php do_action( 'edd_customer_before_tables_wrapper', $customer ); ?>
330
+
331
+ <div id="customer-tables-wrapper" class="customer-section">
332
+
333
+ <?php do_action( 'edd_customer_before_tables', $customer ); ?>
334
+
335
+ <h3><?php _e( 'Recent Payments', 'edd' ); ?></h3>
336
+ <?php
337
+ $payment_ids = explode( ',', $customer->payment_ids );
338
+ $payments = edd_get_payments( array( 'post__in' => $payment_ids ) );
339
+ $payments = array_slice( $payments, 0, 10 );
340
+ ?>
341
+ <table class="wp-list-table widefat striped payments">
342
+ <thead>
343
+ <tr>
344
+ <th><?php _e( 'ID', 'edd' ); ?></th>
345
+ <th><?php _e( 'Amount', 'edd' ); ?></th>
346
+ <th><?php _e( 'Date', 'edd' ); ?></th>
347
+ <th><?php _e( 'Status', 'edd' ); ?></th>
348
+ <th><?php _e( 'Actions', 'edd' ); ?></th>
349
+ </tr>
350
+ </thead>
351
+ <tbody>
352
+ <?php if ( ! empty( $payments ) ) : ?>
353
+ <?php foreach ( $payments as $payment ) : ?>
354
+ <tr>
355
+ <td><?php echo $payment->ID; ?></td>
356
+ <td><?php echo edd_payment_amount( $payment->ID ); ?></td>
357
+ <td><?php echo date_i18n( get_option( 'date_format' ), strtotime( $payment->post_date ) ); ?></td>
358
+ <td><?php echo edd_get_payment_status( $payment, true ); ?></td>
359
+ <td>
360
+ <a title="<?php _e( 'View Details for Payment', 'edd' ); echo ' ' . $payment->ID; ?>" href="<?php echo admin_url( 'edit.php?post_type=download&page=edd-payment-history&view=view-order-details&id=' . $payment->ID ); ?>">
361
+ <?php _e( 'View Details', 'edd' ); ?>
362
+ </a>
363
+ <?php do_action( 'edd_customer_recent_purcahses_actions', $customer, $payment ); ?>
364
+ </td>
365
+ </tr>
366
+ <?php endforeach; ?>
367
+ <?php else: ?>
368
+ <tr><td colspan="5"><?php _e( 'No Payments Found', 'edd' ); ?></td></tr>
369
+ <?php endif; ?>
370
+ </tbody>
371
+ </table>
372
+
373
+ <h3><?php printf( __( 'Purchased %s', 'edd' ), edd_get_label_plural() ); ?></h3>
374
+ <?php
375
+ $downloads = edd_get_users_purchased_products( $customer->email );
376
+ ?>
377
+ <table class="wp-list-table widefat striped downloads">
378
+ <thead>
379
+ <tr>
380
+ <th><?php echo edd_get_label_singular(); ?></th>
381
+ <th width="120px"><?php _e( 'Actions', 'edd' ); ?></th>
382
+ </tr>
383
+ </thead>
384
+ <tbody>
385
+ <?php if ( ! empty( $downloads ) ) : ?>
386
+ <?php foreach ( $downloads as $download ) : ?>
387
+ <tr>
388
+ <td><?php echo $download->post_title; ?></td>
389
+ <td>
390
+ <a title="<?php echo esc_attr( sprintf( __( 'View %s', 'edd' ), $download->post_title ) ); ?>" href="<?php echo esc_url( admin_url( 'post.php?action=edit&post=' . $download->ID ) ); ?>">
391
+ <?php printf( __( 'View %s', 'edd' ), edd_get_label_singular() ); ?>
392
+ </a>
393
+ </td>
394
+ </tr>
395
+ <?php endforeach; ?>
396
+ <?php else: ?>
397
+ <tr><td colspan="2"><?php printf( __( 'No %s Found', 'edd' ), edd_get_label_plural() ); ?></td></tr>
398
+ <?php endif; ?>
399
+ </tbody>
400
+ </table>
401
+
402
+ <?php do_action( 'edd_customer_after_tables', $customer ); ?>
403
+
404
+ </div>
405
+
406
+ <?php do_action( 'edd_customer_card_bottom', $customer ); ?>
407
+
408
+ <?php
409
+ }
410
+
411
+ /**
412
+ * View the notes of a customer
413
+ *
414
+ * @since 2.3
415
+ * @param $customer The Customer being displayed
416
+ * @return void
417
+ */
418
+ function edd_customer_notes_view( $customer ) {
419
+
420
+ $paged = isset( $_GET['paged'] ) && is_numeric( $_GET['paged'] ) ? $_GET['paged'] : 1;
421
+ $paged = absint( $paged );
422
+ $note_count = $customer->get_notes_count();
423
+ $per_page = apply_filters( 'edd_customer_notes_per_page', 20 );
424
+ $total_pages = ceil( $note_count / $per_page );
425
+
426
+ $customer_notes = $customer->get_notes( $per_page, $paged );
427
+ ?>
428
+
429
+ <div id="customer-notes-wrapper">
430
+ <div class="customer-notes-header">
431
+ <?php echo get_avatar( $customer->email, 30 ); ?> <span><?php echo $customer->name; ?></span>
432
+ </div>
433
+ <h3><?php _e( 'Notes', 'edd' ); ?></h3>
434
+
435
+ <?php if ( 1 == $paged ) : ?>
436
+ <div style="display: block; margin-bottom: 35px;">
437
+ <form id="edd-add-customer-note" method="post" action="<?php echo admin_url( 'edit.php?post_type=download&page=edd-customers&view=notes&id=' . $customer->id ); ?>">
438
+ <textarea id="customer-note" name="customer_note" class="customer-note-input" rows="10"></textarea>
439
+ <br />
440
+ <input type="hidden" id="customer-id" name="customer_id" value="<?php echo $customer->id; ?>" />
441
+ <input type="hidden" name="edd_action" value="add-customer-note" />
442
+ <?php wp_nonce_field( 'add-customer-note', 'add_customer_note_nonce', true, true ); ?>
443
+ <input id="add-customer-note" class="right button-primary" type="submit" value="Add Note" />
444
+ </form>
445
+ </div>
446
+ <?php endif; ?>
447
+
448
+ <?php
449
+ $pagination_args = array(
450
+ 'base' => '%_%',
451
+ 'format' => '?paged=%#%',
452
+ 'total' => $total_pages,
453
+ 'current' => $paged,
454
+ 'show_all' => true
455
+ );
456
+
457
+ echo paginate_links( $pagination_args );
458
+ ?>
459
+
460
+ <div id="edd-customer-notes">
461
+ <?php if ( count( $customer_notes ) > 0 ) : ?>
462
+ <?php foreach( $customer_notes as $key => $note ) : ?>
463
+ <div class="customer-note-wrapper dashboard-comment-wrap comment-item">
464
+ <span class="note-content-wrap">
465
+ <?php echo stripslashes( $note ); ?>
466
+ </span>
467
+ </div>
468
+ <?php endforeach; ?>
469
+ <?php else: ?>
470
+ <div class="edd-no-customer-notes">
471
+ <?php _e( 'No Customer Notes', 'edd' ); ?>
472
+ </div>
473
+ <?php endif; ?>
474
+ </div>
475
+
476
+ <?php echo paginate_links( $pagination_args ); ?>
477
+
478
+ </div>
479
+
480
+ <?php
481
+ }
482
+
483
+ function edd_customers_delete_view( $customer ) {
484
+ $customer_edit_role = apply_filters( 'edd_edit_customers_role', 'edit_shop_payments' );
485
+
486
+ ?>
487
+
488
+ <?php do_action( 'edd_customer_delete_top', $customer ); ?>
489
+
490
+ <div class="info-wrapper customer-section">
491
+
492
+ <form id="delete-customer" method="post" action="<?php echo admin_url( 'edit.php?post_type=download&page=edd-customers&view=delete&id=' . $customer->id ); ?>">
493
+
494
+ <div class="customer-notes-header">
495
+ <?php echo get_avatar( $customer->email, 30 ); ?> <span><?php echo $customer->name; ?></span>
496
+ </div>
497
+
498
+
499
+ <div class="customer-info delete-customer">
500
+
501
+ <span class="delete-customer-options">
502
+ <p>
503
+ <?php echo EDD()->html->checkbox( array( 'name' => 'edd-customer-delete-confirm' ) ); ?>
504
+ <label for="edd-customer-delete-confirm"><?php _e( 'Are you sure you want to delete this customer?', 'edd' ); ?></label>
505
+ </p>
506
+
507
+ <p>
508
+ <?php echo EDD()->html->checkbox( array( 'name' => 'edd-customer-delete-records', 'options' => array( 'disabled' => true ) ) ); ?>
509
+ <label for="edd-customer-delete-records"><?php _e( 'Delete all associated payments and records?', 'edd' ); ?></label>
510
+ </p>
511
+
512
+ <?php do_action( 'edd_customer_delete_inputs', $customer ); ?>
513
+ </span>
514
+
515
+ <span id="customer-edit-actions">
516
+ <input type="hidden" name="customer_id" value="<?php echo $customer->id; ?>" />
517
+ <?php wp_nonce_field( 'delete-customer', '_wpnonce', false, true ); ?>
518
+ <input type="hidden" name="edd_action" value="delete-customer" />
519
+ <input type="submit" disabled="disabled" id="edd-delete-customer" class="button-primary" value="<?php _e( 'Delete Customer', 'edd' ); ?>" />
520
+ <a id="edd-delete-customer-cancel" href="<?php echo admin_url( 'edit.php?post_type=download&page=edd-customers&view=overview&id=' . $customer->id ); ?>" class="delete"><?php _e( 'Cancel', 'edd' ); ?></a>
521
+ </span>
522
+
523
+ </div>
524
+
525
+ </form>
526
+ </div>
527
+
528
+ <?php
529
+
530
+ do_action( 'edd_customer_delete_bottom', $customer );
531
+ }
includes/admin/dashboard-widgets.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Dashboard
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -37,7 +37,22 @@ add_action('wp_dashboard_setup', 'edd_register_dashboard_widgets', 10 );
37
  * @since 1.2.2
38
  * @return void
39
  */
40
- function edd_dashboard_sales_widget() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  $stats = new EDD_Payment_Stats; ?>
42
  <div class="edd_dashboard_widget">
43
  <div class="table table_left table_current_month">
@@ -95,7 +110,7 @@ function edd_dashboard_sales_widget() {
95
  <tr>
96
  <td class="t sales"><?php _e( 'Earnings', 'edd' ); ?></td>
97
  <td class="last b b-earnings">
98
- <?php $earnings_today = $stats->get_earnings( 0, 'today', false, array( 'publish', 'revoked' ) ); ?>
99
  <?php echo edd_currency_filter( edd_format_amount( $earnings_today ) ); ?>
100
  </td>
101
  </tr>
@@ -161,12 +176,14 @@ function edd_dashboard_sales_widget() {
161
  </a>
162
  <?php if ( $payment->user_info['id'] > 0 ) {
163
  $user = get_user_by( 'id', $payment->user_info['id'] );
164
- echo "(" . $user->data->user_login . ")";
 
 
165
  } ?>
166
  </td>
167
  <td class="edd_order_price">
168
  <a href="<?php echo add_query_arg( 'id', $payment->ID, admin_url( 'edit.php?post_type=download&page=edd-payment-history&view=view-order-details' ) ); ?>" title="<?php printf( __( 'Purchase Details for Payment #%s', 'edd' ), $payment->ID ); ?> ">
169
- <span class="edd_price_label"><?php echo edd_currency_filter( edd_format_amount( $payment->total ) ); ?></span>
170
  </a>
171
  </td>
172
  </tr>
@@ -178,4 +195,34 @@ function edd_dashboard_sales_widget() {
178
  <?php } // End if ?>
179
  </div>
180
  <?php
181
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Dashboard
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
37
  * @since 1.2.2
38
  * @return void
39
  */
40
+ function edd_dashboard_sales_widget( ) {
41
+ echo '<p><img src=" ' . esc_attr( set_url_scheme( EDD_PLUGIN_URL . 'assets/images/loading.gif', 'relative' ) ) . '"/></p>';
42
+ }
43
+
44
+ /**
45
+ * Loads the dashboard sales widget via ajax
46
+ *
47
+ * @since 2.1
48
+ * @return void
49
+ */
50
+ function edd_load_dashboard_sales_widget( ) {
51
+
52
+ if ( ! current_user_can( apply_filters( 'edd_dashboard_stats_cap', 'view_shop_reports' ) ) ) {
53
+ die();
54
+ }
55
+
56
  $stats = new EDD_Payment_Stats; ?>
57
  <div class="edd_dashboard_widget">
58
  <div class="table table_left table_current_month">
110
  <tr>
111
  <td class="t sales"><?php _e( 'Earnings', 'edd' ); ?></td>
112
  <td class="last b b-earnings">
113
+ <?php $earnings_today = $stats->get_earnings( 0, 'today', false ); ?>
114
  <?php echo edd_currency_filter( edd_format_amount( $earnings_today ) ); ?>
115
  </td>
116
  </tr>
176
  </a>
177
  <?php if ( $payment->user_info['id'] > 0 ) {
178
  $user = get_user_by( 'id', $payment->user_info['id'] );
179
+ if ( $user ) {
180
+ echo "(" . $user->data->user_login . ")";
181
+ }
182
  } ?>
183
  </td>
184
  <td class="edd_order_price">
185
  <a href="<?php echo add_query_arg( 'id', $payment->ID, admin_url( 'edit.php?post_type=download&page=edd-payment-history&view=view-order-details' ) ); ?>" title="<?php printf( __( 'Purchase Details for Payment #%s', 'edd' ), $payment->ID ); ?> ">
186
+ <span class="edd_price_label"><?php echo edd_currency_filter( edd_format_amount( $payment->total ), edd_get_payment_currency_code( $payment->ID ) ); ?></span>
187
  </a>
188
  </td>
189
  </tr>
195
  <?php } // End if ?>
196
  </div>
197
  <?php
198
+ die();
199
+ }
200
+ add_action( 'wp_ajax_edd_load_dashboard_widget', 'edd_load_dashboard_sales_widget' );
201
+
202
+ /**
203
+ * Add download count to At a glance widget
204
+ *
205
+ * @author Daniel J Griffiths
206
+ * @since 2.1
207
+ * @return void
208
+ */
209
+ function edd_dashboard_at_a_glance_widget( $items ) {
210
+ $num_posts = wp_count_posts( 'download' );
211
+
212
+ if ( $num_posts && $num_posts->publish ) {
213
+ $text = _n( '%s ' . edd_get_label_singular(), '%s ' . edd_get_label_plural(), $num_posts->publish, 'edd' );
214
+
215
+ $text = sprintf( $text, number_format_i18n( $num_posts->publish ) );
216
+
217
+ if ( current_user_can( 'edit_products' ) ) {
218
+ $text = sprintf( '<a class="download-count" href="edit.php?post_type=download">%1$s</a>', $text );
219
+ } else {
220
+ $text = sprintf( '<span class="download-count">%1$s</span>', $text );
221
+ }
222
+
223
+ $items[] = $text;
224
+ }
225
+
226
+ return $items;
227
+ }
228
+ add_filter( 'dashboard_glance_items', 'edd_dashboard_at_a_glance_widget', 1 );
includes/admin/discounts/add-discount.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -18,6 +18,7 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
18
  <?php do_action( 'edd_add_discount_form_top' ); ?>
19
  <table class="form-table">
20
  <tbody>
 
21
  <tr>
22
  <th scope="row" valign="top">
23
  <label for="edd-name"><?php _e( 'Name', 'edd' ); ?></label>
@@ -27,6 +28,7 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
27
  <p class="description"><?php _e( 'The name of this discount', 'edd' ); ?></p>
28
  </td>
29
  </tr>
 
30
  <tr>
31
  <th scope="row" valign="top">
32
  <label for="edd-code"><?php _e( 'Code', 'edd' ); ?></label>
@@ -36,6 +38,7 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
36
  <p class="description"><?php _e( 'Enter a code for this discount, such as 10PERCENT', 'edd' ); ?></p>
37
  </td>
38
  </tr>
 
39
  <tr>
40
  <th scope="row" valign="top">
41
  <label for="edd-type"><?php _e( 'Type', 'edd' ); ?></label>
@@ -48,6 +51,7 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
48
  <p class="description"><?php _e( 'The kind of discount to apply for this discount.', 'edd' ); ?></p>
49
  </td>
50
  </tr>
 
51
  <tr>
52
  <th scope="row" valign="top">
53
  <label for="edd-amount"><?php _e( 'Amount', 'edd' ); ?></label>
@@ -58,6 +62,7 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
58
  <p class="description edd-amount-description"><?php _e( 'Enter the discount percentage. 10 = 10%', 'edd' ); ?></p>
59
  </td>
60
  </tr>
 
61
  <tr>
62
  <th scope="row" valign="top">
63
  <label for="edd-products"><?php printf( __( '%s Requirements', 'edd' ), edd_get_label_singular() ); ?></label>
@@ -68,7 +73,8 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
68
  'name' => 'products[]',
69
  'id' => 'products',
70
  'multiple' => true,
71
- 'chosen' => true
 
72
  ) ); ?><br/>
73
  </p>
74
  <div id="edd-discount-product-conditions" style="display:none;">
@@ -92,6 +98,7 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
92
  <p class="description"><?php printf( __( 'Select %s relevant to this discount.', 'edd' ), edd_get_label_plural() ); ?></p>
93
  </td>
94
  </tr>
 
95
  <tr>
96
  <th scope="row" valign="top">
97
  <label for="edd-excluded-products"><?php printf( __( 'Excluded %s', 'edd' ), edd_get_label_plural() ); ?></label>
@@ -102,11 +109,13 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
102
  'id' => 'excluded-products',
103
  'selected' => array(),
104
  'multiple' => true,
105
- 'chosen' => true
 
106
  ) ); ?><br/>
107
  <p class="description"><?php printf( __( '%s that this discount code cannot be applied to.', 'edd' ), edd_get_label_plural() ); ?></p>
108
  </td>
109
  </tr>
 
110
  <tr>
111
  <th scope="row" valign="top">
112
  <label for="edd-start"><?php _e( 'Start date', 'edd' ); ?></label>
@@ -116,6 +125,7 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
116
  <p class="description"><?php _e( 'Enter the start date for this discount code in the format of mm/dd/yyyy. For no start date, leave blank. If entered, the discount can only be used after or on this date.', 'edd' ); ?></p>
117
  </td>
118
  </tr>
 
119
  <tr>
120
  <th scope="row" valign="top">
121
  <label for="edd-expiration"><?php _e( 'Expiration date', 'edd' ); ?></label>
@@ -125,6 +135,7 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
125
  <p class="description"><?php _e( 'Enter the expiration date for this discount code in the format of mm/dd/yyyy. For no expiration, leave blank', 'edd' ); ?></p>
126
  </td>
127
  </tr>
 
128
  <tr>
129
  <th scope="row" valign="top">
130
  <label for="edd-min-cart-amount"><?php _e( 'Minimum Amount', 'edd' ); ?></label>
@@ -134,6 +145,7 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
134
  <p class="description"><?php _e( 'The minimum amount that must be purchased before this discount can be used. Leave blank for no minimum.', 'edd' ); ?></p>
135
  </td>
136
  </tr>
 
137
  <tr>
138
  <th scope="row" valign="top">
139
  <label for="edd-max-uses"><?php _e( 'Max Uses', 'edd' ); ?></label>
@@ -143,6 +155,7 @@ $downloads = get_posts( array( 'post_type' => 'download', 'nopaging' => true ) )
143
  <p class="description"><?php _e( 'The maximum number of times this discount can be used. Leave blank for unlimited.', 'edd' ); ?></p>
144
  </td>
145
  </tr>
 
146
  <tr>
147
  <th scope="row" valign="top">
148
  <label for="edd-use-once"><?php _e( 'Use Once Per Customer', 'edd' ); ?></label>
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
18
  <?php do_action( 'edd_add_discount_form_top' ); ?>
19
  <table class="form-table">
20
  <tbody>
21
+ <?php do_action( 'edd_add_discount_form_before_name' ); ?>
22
  <tr>
23
  <th scope="row" valign="top">
24
  <label for="edd-name"><?php _e( 'Name', 'edd' ); ?></label>
28
  <p class="description"><?php _e( 'The name of this discount', 'edd' ); ?></p>
29
  </td>
30
  </tr>
31
+ <?php do_action( 'edd_add_discount_form_before_code' ); ?>
32
  <tr>
33
  <th scope="row" valign="top">
34
  <label for="edd-code"><?php _e( 'Code', 'edd' ); ?></label>
38
  <p class="description"><?php _e( 'Enter a code for this discount, such as 10PERCENT', 'edd' ); ?></p>
39
  </td>
40
  </tr>
41
+ <?php do_action( 'edd_add_discount_form_before_type' ); ?>
42
  <tr>
43
  <th scope="row" valign="top">
44
  <label for="edd-type"><?php _e( 'Type', 'edd' ); ?></label>
51
  <p class="description"><?php _e( 'The kind of discount to apply for this discount.', 'edd' ); ?></p>
52
  </td>
53
  </tr>
54
+ <?php do_action( 'edd_add_discount_form_before_amount' ); ?>
55
  <tr>
56
  <th scope="row" valign="top">
57
  <label for="edd-amount"><?php _e( 'Amount', 'edd' ); ?></label>
62
  <p class="description edd-amount-description"><?php _e( 'Enter the discount percentage. 10 = 10%', 'edd' ); ?></p>
63
  </td>
64
  </tr>
65
+ <?php do_action( 'edd_add_discount_form_before_products' ); ?>
66
  <tr>
67
  <th scope="row" valign="top">
68
  <label for="edd-products"><?php printf( __( '%s Requirements', 'edd' ), edd_get_label_singular() ); ?></label>
73
  'name' => 'products[]',
74
  'id' => 'products',
75
  'multiple' => true,
76
+ 'chosen' => true,
77
+ 'placeholder' => sprintf( __( 'Select one or more %s', 'edd' ), edd_get_label_plural() )
78
  ) ); ?><br/>
79
  </p>
80
  <div id="edd-discount-product-conditions" style="display:none;">
98
  <p class="description"><?php printf( __( 'Select %s relevant to this discount.', 'edd' ), edd_get_label_plural() ); ?></p>
99
  </td>
100
  </tr>
101
+ <?php do_action( 'edd_add_discount_form_before_excluded_products' ); ?>
102
  <tr>
103
  <th scope="row" valign="top">
104
  <label for="edd-excluded-products"><?php printf( __( 'Excluded %s', 'edd' ), edd_get_label_plural() ); ?></label>
109
  'id' => 'excluded-products',
110
  'selected' => array(),
111
  'multiple' => true,
112
+ 'chosen' => true,
113
+ 'placeholder' => sprintf( __( 'Select one or more %s', 'edd' ), edd_get_label_plural() )
114
  ) ); ?><br/>
115
  <p class="description"><?php printf( __( '%s that this discount code cannot be applied to.', 'edd' ), edd_get_label_plural() ); ?></p>
116
  </td>
117
  </tr>
118
+ <?php do_action( 'edd_add_discount_form_before_start' ); ?>
119
  <tr>
120
  <th scope="row" valign="top">
121
  <label for="edd-start"><?php _e( 'Start date', 'edd' ); ?></label>
125
  <p class="description"><?php _e( 'Enter the start date for this discount code in the format of mm/dd/yyyy. For no start date, leave blank. If entered, the discount can only be used after or on this date.', 'edd' ); ?></p>
126
  </td>
127
  </tr>
128
+ <?php do_action( 'edd_add_discount_form_before_expiration' ); ?>
129
  <tr>
130
  <th scope="row" valign="top">
131
  <label for="edd-expiration"><?php _e( 'Expiration date', 'edd' ); ?></label>
135
  <p class="description"><?php _e( 'Enter the expiration date for this discount code in the format of mm/dd/yyyy. For no expiration, leave blank', 'edd' ); ?></p>
136
  </td>
137
  </tr>
138
+ <?php do_action( 'edd_add_discount_form_before_min_cart_amount' ); ?>
139
  <tr>
140
  <th scope="row" valign="top">
141
  <label for="edd-min-cart-amount"><?php _e( 'Minimum Amount', 'edd' ); ?></label>
145
  <p class="description"><?php _e( 'The minimum amount that must be purchased before this discount can be used. Leave blank for no minimum.', 'edd' ); ?></p>
146
  </td>
147
  </tr>
148
+ <?php do_action( 'edd_add_discount_form_before_max_uses' ); ?>
149
  <tr>
150
  <th scope="row" valign="top">
151
  <label for="edd-max-uses"><?php _e( 'Max Uses', 'edd' ); ?></label>
155
  <p class="description"><?php _e( 'The maximum number of times this discount can be used. Leave blank for unlimited.', 'edd' ); ?></p>
156
  </td>
157
  </tr>
158
+ <?php do_action( 'edd_add_discount_form_before_use_once' ); ?>
159
  <tr>
160
  <th scope="row" valign="top">
161
  <label for="edd-use-once"><?php _e( 'Use Once Per Customer', 'edd' ); ?></label>
includes/admin/discounts/class-discount-codes-table.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
@@ -70,9 +70,9 @@ class EDD_Discount_Codes_Table extends WP_List_Table {
70
  global $status, $page;
71
 
72
  parent::__construct( array(
73
- 'singular' => edd_get_label_singular(), // Singular name of the listed records
74
- 'plural' => edd_get_label_plural(), // Plural name of the listed records
75
- 'ajax' => false // Does this table support ajax?
76
  ) );
77
 
78
  $this->get_discount_code_counts();
@@ -180,10 +180,7 @@ class EDD_Discount_Codes_Table extends WP_List_Table {
180
  * @return string Column Name
181
  */
182
  function column_default( $item, $column_name ) {
183
- switch( $column_name ){
184
- default:
185
- return $item[ $column_name ];
186
- }
187
  }
188
 
189
  /**
@@ -196,18 +193,17 @@ class EDD_Discount_Codes_Table extends WP_List_Table {
196
  */
197
  function column_name( $item ) {
198
  $discount = get_post( $item['ID'] );
199
- $base = admin_url( 'edit.php?post_type=download&page=edd-discounts&edd-action=edit_discount&discount=' . $item['ID'] );
200
  $row_actions = array();
201
 
202
  $row_actions['edit'] = '<a href="' . add_query_arg( array( 'edd-action' => 'edit_discount', 'discount' => $discount->ID ) ) . '">' . __( 'Edit', 'edd' ) . '</a>';
203
 
204
  if( strtolower( $item['status'] ) == 'active' ) {
205
- $row_actions['deactivate'] = '<a href="' . add_query_arg( array( 'edd-action' => 'deactivate_discount', 'discount' => $discount->ID ) ) . '">' . __( 'Deactivate', 'edd' ) . '</a>';
206
  } elseif( strtolower( $item['status'] ) == 'inactive' ) {
207
- $row_actions['activate'] = '<a href="' . add_query_arg( array( 'edd-action' => 'activate_discount', 'discount' => $discount->ID ) ) . '">' . __( 'Activate', 'edd' ) . '</a>';
208
  }
209
 
210
- $row_actions['delete'] = '<a href="' . wp_nonce_url( add_query_arg( array( 'edd-action' => 'delete_discount', 'discount' => $discount->ID ) ), 'edd_discount_nonce' ) . '">' . __( 'Delete', 'edd' ) . '</a>';
211
 
212
  $row_actions = apply_filters( 'edd_discount_row_actions', $row_actions, $discount );
213
 
@@ -289,11 +285,21 @@ class EDD_Discount_Codes_Table extends WP_List_Table {
289
  * @return void
290
  */
291
  public function process_bulk_action() {
 
 
 
 
 
 
 
 
 
292
  $ids = isset( $_GET['discount'] ) ? $_GET['discount'] : false;
293
 
294
  if ( ! is_array( $ids ) )
295
  $ids = array( $ids );
296
 
 
297
  foreach ( $ids as $id ) {
298
  if ( 'delete' === $this->current_action() ) {
299
  edd_remove_discount( $id );
@@ -336,11 +342,9 @@ class EDD_Discount_Codes_Table extends WP_List_Table {
336
 
337
  $orderby = isset( $_GET['orderby'] ) ? $_GET['orderby'] : 'ID';
338
  $order = isset( $_GET['order'] ) ? $_GET['order'] : 'DESC';
339
- $order_inverse = $order == 'DESC' ? 'ASC' : 'DESC';
340
  $status = isset( $_GET['status'] ) ? $_GET['status'] : array( 'active', 'inactive' );
341
  $meta_key = isset( $_GET['meta_key'] ) ? $_GET['meta_key'] : null;
342
  $search = isset( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : null;
343
- $order_class = strtolower( $order_inverse );
344
 
345
  $discounts = edd_get_discounts( array(
346
  'posts_per_page' => $per_page,
@@ -425,8 +429,6 @@ class EDD_Discount_Codes_Table extends WP_List_Table {
425
 
426
  $data = $this->discount_codes_data();
427
 
428
- $current_page = $this->get_pagenum();
429
-
430
  $status = isset( $_GET['status'] ) ? $_GET['status'] : 'any';
431
 
432
  switch( $status ) {
@@ -437,6 +439,7 @@ class EDD_Discount_Codes_Table extends WP_List_Table {
437
  $total_items = $this->inactive_count;
438
  break;
439
  case 'any':
 
440
  $total_items = $this->total_count;
441
  break;
442
  }
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
70
  global $status, $page;
71
 
72
  parent::__construct( array(
73
+ 'singular' => 'discount', // Singular name of the listed records
74
+ 'plural' => 'discounts', // Plural name of the listed records
75
+ 'ajax' => false // Does this table support ajax?
76
  ) );
77
 
78
  $this->get_discount_code_counts();
180
  * @return string Column Name
181
  */
182
  function column_default( $item, $column_name ) {
183
+ return $item[ $column_name ];
 
 
 
184
  }
185
 
186
  /**
193
  */
194
  function column_name( $item ) {
195
  $discount = get_post( $item['ID'] );
 
196
  $row_actions = array();
197
 
198
  $row_actions['edit'] = '<a href="' . add_query_arg( array( 'edd-action' => 'edit_discount', 'discount' => $discount->ID ) ) . '">' . __( 'Edit', 'edd' ) . '</a>';
199
 
200
  if( strtolower( $item['status'] ) == 'active' ) {
201
+ $row_actions['deactivate'] = '<a href="' . esc_url( wp_nonce_url( add_query_arg( array( 'edd-action' => 'deactivate_discount', 'discount' => $discount->ID ) ), 'edd_discount_nonce' ) ) . '">' . __( 'Deactivate', 'edd' ) . '</a>';
202
  } elseif( strtolower( $item['status'] ) == 'inactive' ) {
203
+ $row_actions['activate'] = '<a href="' . esc_url( wp_nonce_url( add_query_arg( array( 'edd-action' => 'activate_discount', 'discount' => $discount->ID ) ), 'edd_discount_nonce' ) ) . '">' . __( 'Activate', 'edd' ) . '</a>';
204
  }
205
 
206
+ $row_actions['delete'] = '<a href="' . esc_url( wp_nonce_url( add_query_arg( array( 'edd-action' => 'delete_discount', 'discount' => $discount->ID ) ), 'edd_discount_nonce' ) ) . '">' . __( 'Delete', 'edd' ) . '</a>';
207
 
208
  $row_actions = apply_filters( 'edd_discount_row_actions', $row_actions, $discount );
209
 
285
  * @return void
286
  */
287
  public function process_bulk_action() {
288
+
289
+ if( empty( $_REQUEST['_wpnonce'] ) ) {
290
+ return;
291
+ }
292
+
293
+ if( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'bulk-discounts' ) ) {
294
+ return;
295
+ }
296
+
297
  $ids = isset( $_GET['discount'] ) ? $_GET['discount'] : false;
298
 
299
  if ( ! is_array( $ids ) )
300
  $ids = array( $ids );
301
 
302
+
303
  foreach ( $ids as $id ) {
304
  if ( 'delete' === $this->current_action() ) {
305
  edd_remove_discount( $id );
342
 
343
  $orderby = isset( $_GET['orderby'] ) ? $_GET['orderby'] : 'ID';
344
  $order = isset( $_GET['order'] ) ? $_GET['order'] : 'DESC';
 
345
  $status = isset( $_GET['status'] ) ? $_GET['status'] : array( 'active', 'inactive' );
346
  $meta_key = isset( $_GET['meta_key'] ) ? $_GET['meta_key'] : null;
347
  $search = isset( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : null;
 
348
 
349
  $discounts = edd_get_discounts( array(
350
  'posts_per_page' => $per_page,
429
 
430
  $data = $this->discount_codes_data();
431
 
 
 
432
  $status = isset( $_GET['status'] ) ? $_GET['status'] : 'any';
433
 
434
  switch( $status ) {
439
  $total_items = $this->inactive_count;
440
  break;
441
  case 'any':
442
+ default:
443
  $total_items = $this->total_count;
444
  break;
445
  }
includes/admin/discounts/contextual-help.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.2.3
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.2.3
10
  */
includes/admin/discounts/discount-actions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0.8.1
10
  */
@@ -21,27 +21,57 @@ if ( ! defined( 'ABSPATH' ) ) exit;
21
  * @return void
22
  */
23
  function edd_add_discount( $data ) {
24
- if ( isset( $data['edd-discount-nonce'] ) && wp_verify_nonce( $data['edd-discount-nonce'], 'edd_discount_nonce' ) ) {
25
- // Setup the discount code details
26
- $posted = array();
27
-
28
- foreach ( $data as $key => $value ) {
29
- if ( $key != 'edd-discount-nonce' && $key != 'edd-action' && $key != 'edd-redirect' ) {
30
- if ( is_string( $value ) || is_int( $value ) )
31
- $posted[ $key ] = strip_tags( addslashes( $value ) );
32
- elseif ( is_array( $value ) )
33
- $posted[ $key ] = array_map( 'absint', $value );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  }
35
  }
36
 
 
 
 
 
 
37
  // Set the discount code's default status to active
38
  $posted['status'] = 'active';
 
39
  if ( edd_store_discount( $posted ) ) {
 
40
  wp_redirect( add_query_arg( 'edd-message', 'discount_added', $data['edd-redirect'] ) ); edd_die();
 
41
  } else {
 
42
  wp_redirect( add_query_arg( 'edd-message', 'discount_add_failed', $data['edd-redirect'] ) ); edd_die();
43
- }
 
 
 
 
 
 
44
  }
 
45
  }
46
  add_action( 'edd_add_discount', 'edd_add_discount' );
47
 
@@ -53,28 +83,49 @@ add_action( 'edd_add_discount', 'edd_add_discount' );
53
  * @return void
54
  */
55
  function edd_edit_discount( $data ) {
56
- if ( isset( $data['edd-discount-nonce'] ) && wp_verify_nonce( $data['edd-discount-nonce'], 'edd_discount_nonce' ) ) {
57
- // Setup the discount code details
58
- $discount = array();
59
-
60
- foreach ( $data as $key => $value ) {
61
- if ( $key != 'edd-discount-nonce' && $key != 'edd-action' && $key != 'discount-id' && $key != 'edd-redirect' ) {
62
- if ( is_string( $value ) || is_int( $value ) )
63
- $discount[ $key ] = strip_tags( addslashes( $value ) );
64
- elseif ( is_array( $value ) )
65
- $discount[ $key ] = array_map( 'absint', $value );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
 
67
  }
68
 
69
- $old_discount = edd_get_discount_by( 'code', $data['code'] );
70
- $discount['uses'] = edd_get_discount_uses( $old_discount->ID );
 
 
 
 
 
 
 
 
 
 
71
 
72
- if ( edd_store_discount( $discount, $data['discount-id'] ) ) {
73
- wp_redirect( add_query_arg( 'edd-message', 'discount_updated', $data['edd-redirect'] ) ); edd_die();
74
- } else {
75
- wp_redirect( add_query_arg( 'edd-message', 'discount_update_failed', $data['edd-redirect'] ) ); edd_die();
76
- }
77
  }
 
78
  }
79
  add_action( 'edd_edit_discount', 'edd_edit_discount' );
80
 
@@ -88,8 +139,14 @@ add_action( 'edd_edit_discount', 'edd_edit_discount' );
88
  * @return void
89
  */
90
  function edd_delete_discount( $data ) {
91
- if ( ! isset( $data['_wpnonce'] ) || ! wp_verify_nonce( $data['_wpnonce'], 'edd_discount_nonce' ) )
92
- wp_die( __( 'Trying to cheat or something?', 'edd' ), __( 'Error', 'edd' ) );
 
 
 
 
 
 
93
 
94
  $discount_id = $data['discount'];
95
  edd_remove_discount( $discount_id );
@@ -107,6 +164,15 @@ add_action( 'edd_delete_discount', 'edd_delete_discount' );
107
  * @return void
108
  */
109
  function edd_activate_discount( $data ) {
 
 
 
 
 
 
 
 
 
110
  $id = absint( $data['discount'] );
111
  edd_update_discount_status( $id, 'active' );
112
  }
@@ -122,7 +188,16 @@ add_action( 'edd_activate_discount', 'edd_activate_discount' );
122
  * @uses edd_update_discount_status()
123
  * @return void
124
  */
125
- function edd_deactivate_discount( $data) {
 
 
 
 
 
 
 
 
 
126
  $id = absint( $data['discount'] );
127
  edd_update_discount_status( $id, 'inactive' );
128
  }
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0.8.1
10
  */
21
  * @return void
22
  */
23
  function edd_add_discount( $data ) {
24
+
25
+ if ( ! isset( $data['edd-discount-nonce'] ) || ! wp_verify_nonce( $data['edd-discount-nonce'], 'edd_discount_nonce' ) ) {
26
+ return;
27
+ }
28
+
29
+ if( ! current_user_can( 'manage_shop_discounts' ) ) {
30
+ wp_die( __( 'You do not have permission to create discount codes', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
31
+ }
32
+
33
+ // Setup the discount code details
34
+ $posted = array();
35
+
36
+ foreach ( $data as $key => $value ) {
37
+
38
+ if ( $key != 'edd-discount-nonce' && $key != 'edd-action' && $key != 'edd-redirect' ) {
39
+
40
+ if ( is_string( $value ) || is_int( $value ) ) {
41
+
42
+ $posted[ $key ] = strip_tags( addslashes( $value ) );
43
+
44
+ } elseif ( is_array( $value ) ) {
45
+
46
+ $posted[ $key ] = array_map( 'absint', $value );
47
+
48
  }
49
  }
50
 
51
+ }
52
+
53
+ // Ensure this discount doesn't already exist
54
+ if ( ! edd_get_discount_by_code( $posted['code'] ) ) {
55
+
56
  // Set the discount code's default status to active
57
  $posted['status'] = 'active';
58
+
59
  if ( edd_store_discount( $posted ) ) {
60
+
61
  wp_redirect( add_query_arg( 'edd-message', 'discount_added', $data['edd-redirect'] ) ); edd_die();
62
+
63
  } else {
64
+
65
  wp_redirect( add_query_arg( 'edd-message', 'discount_add_failed', $data['edd-redirect'] ) ); edd_die();
66
+
67
+ }
68
+
69
+ } else {
70
+
71
+ wp_redirect( add_query_arg( 'edd-message', 'discount_exists', $data['edd-redirect'] ) ); edd_die();
72
+
73
  }
74
+
75
  }
76
  add_action( 'edd_add_discount', 'edd_add_discount' );
77
 
83
  * @return void
84
  */
85
  function edd_edit_discount( $data ) {
86
+
87
+ if ( ! isset( $data['edd-discount-nonce'] ) || ! wp_verify_nonce( $data['edd-discount-nonce'], 'edd_discount_nonce' ) ) {
88
+ return;
89
+ }
90
+
91
+ if( ! current_user_can( 'manage_shop_discounts' ) ) {
92
+ wp_die( __( 'You do not have permission to edit discount codes', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
93
+ }
94
+
95
+ // Setup the discount code details
96
+ $discount = array();
97
+
98
+ foreach ( $data as $key => $value ) {
99
+
100
+ if ( $key != 'edd-discount-nonce' && $key != 'edd-action' && $key != 'discount-id' && $key != 'edd-redirect' ) {
101
+
102
+ if ( is_string( $value ) || is_int( $value ) ) {
103
+
104
+ $discount[ $key ] = strip_tags( addslashes( $value ) );
105
+
106
+ } elseif ( is_array( $value ) ) {
107
+
108
+ $discount[ $key ] = array_map( 'absint', $value );
109
+
110
  }
111
+
112
  }
113
 
114
+ }
115
+
116
+ $old_discount = edd_get_discount_by( 'code', $data['code'] );
117
+ $discount['uses'] = edd_get_discount_uses( $old_discount->ID );
118
+
119
+ if ( edd_store_discount( $discount, $data['discount-id'] ) ) {
120
+
121
+ wp_redirect( add_query_arg( 'edd-message', 'discount_updated', $data['edd-redirect'] ) ); edd_die();
122
+
123
+ } else {
124
+
125
+ wp_redirect( add_query_arg( 'edd-message', 'discount_update_failed', $data['edd-redirect'] ) ); edd_die();
126
 
 
 
 
 
 
127
  }
128
+
129
  }
130
  add_action( 'edd_edit_discount', 'edd_edit_discount' );
131
 
139
  * @return void
140
  */
141
  function edd_delete_discount( $data ) {
142
+
143
+ if ( ! isset( $data['_wpnonce'] ) || ! wp_verify_nonce( $data['_wpnonce'], 'edd_discount_nonce' ) ) {
144
+ wp_die( __( 'Trying to cheat or something?', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
145
+ }
146
+
147
+ if( ! current_user_can( 'manage_shop_discounts' ) ) {
148
+ wp_die( __( 'You do not have permission to delete discount codes', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
149
+ }
150
 
151
  $discount_id = $data['discount'];
152
  edd_remove_discount( $discount_id );
164
  * @return void
165
  */
166
  function edd_activate_discount( $data ) {
167
+
168
+ if ( ! isset( $data['_wpnonce'] ) || ! wp_verify_nonce( $data['_wpnonce'], 'edd_discount_nonce' ) ) {
169
+ wp_die( __( 'Trying to cheat or something?', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
170
+ }
171
+
172
+ if( ! current_user_can( 'manage_shop_discounts' ) ) {
173
+ wp_die( __( 'You do not have permission to edit discount codes', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
174
+ }
175
+
176
  $id = absint( $data['discount'] );
177
  edd_update_discount_status( $id, 'active' );
178
  }
188
  * @uses edd_update_discount_status()
189
  * @return void
190
  */
191
+ function edd_deactivate_discount( $data ) {
192
+
193
+ if ( ! isset( $data['_wpnonce'] ) || ! wp_verify_nonce( $data['_wpnonce'], 'edd_discount_nonce' ) ) {
194
+ wp_die( __( 'Trying to cheat or something?', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
195
+ }
196
+
197
+ if( ! current_user_can( 'manage_shop_discounts' ) ) {
198
+ wp_die( __( 'You do not have permission to create discount codes', 'edd' ), array( 'response' => 403 ) );
199
+ }
200
+
201
  $id = absint( $data['discount'] );
202
  edd_update_discount_status( $id, 'inactive' );
203
  }
includes/admin/discounts/discount-codes.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -20,8 +20,6 @@ if ( ! defined( 'ABSPATH' ) ) exit;
20
  * @return void
21
  */
22
  function edd_discounts_page() {
23
- global $edd_options;
24
-
25
  if ( isset( $_GET['edd-action'] ) && $_GET['edd-action'] == 'edit_discount' ) {
26
  require_once EDD_PLUGIN_DIR . 'includes/admin/discounts/edit-discount.php';
27
  } elseif ( isset( $_GET['edd-action'] ) && $_GET['edd-action'] == 'add_discount' ) {
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
20
  * @return void
21
  */
22
  function edd_discounts_page() {
 
 
23
  if ( isset( $_GET['edd-action'] ) && $_GET['edd-action'] == 'edit_discount' ) {
24
  require_once EDD_PLUGIN_DIR . 'includes/admin/discounts/edit-discount.php';
25
  } elseif ( isset( $_GET['edd-action'] ) && $_GET['edd-action'] == 'add_discount' ) {
includes/admin/discounts/edit-discount.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -13,7 +13,7 @@
13
  if ( ! defined( 'ABSPATH' ) ) exit;
14
 
15
  if ( ! isset( $_GET['discount'] ) || ! is_numeric( $_GET['discount'] ) ) {
16
- wp_die( __( 'Something went wrong.', 'edd' ), __( 'Error', 'edd' ) );
17
  }
18
 
19
  $discount_id = absint( $_GET['discount'] );
@@ -22,8 +22,8 @@ $product_reqs = edd_get_discount_product_reqs( $discount_id );
22
  $excluded_products = edd_get_discount_excluded_products( $discount_id );
23
  $condition = edd_get_discount_product_condition( $discount_id );
24
  $single_use = edd_discount_is_single_use( $discount_id );
25
- $flat_display = edd_get_discount_type( $discount_id ) == 'percentage' ? '' : ' style="display:none;"';
26
- $percent_display = edd_get_discount_type( $discount_id ) == 'percentage' ? ' style="display:none;"' : '';
27
  $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
28
  ?>
29
  <h2><?php _e( 'Edit Discount', 'edd' ); ?> - <a href="<?php echo admin_url( 'edit.php?post_type=download&page=edd-discounts' ); ?>" class="button-secondary"><?php _e( 'Go Back', 'edd' ); ?></a></h2>
@@ -31,6 +31,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
31
  <?php do_action( 'edd_edit_discount_form_top', $discount_id, $discount ); ?>
32
  <table class="form-table">
33
  <tbody>
 
34
  <tr>
35
  <th scope="row" valign="top">
36
  <label for="edd-name"><?php _e( 'Name', 'edd' ); ?></label>
@@ -40,6 +41,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
40
  <p class="description"><?php _e( 'The name of this discount', 'edd' ); ?></p>
41
  </td>
42
  </tr>
 
43
  <tr>
44
  <th scope="row" valign="top">
45
  <label for="edd-code"><?php _e( 'Code', 'edd' ); ?></label>
@@ -49,6 +51,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
49
  <p class="description"><?php _e( 'Enter a code for this discount, such as 10PERCENT', 'edd' ); ?></p>
50
  </td>
51
  </tr>
 
52
  <tr>
53
  <th scope="row" valign="top">
54
  <label for="edd-type"><?php _e( 'Type', 'edd' ); ?></label>
@@ -61,6 +64,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
61
  <p class="description"><?php _e( 'The kind of discount to apply for this discount.', 'edd' ); ?></p>
62
  </td>
63
  </tr>
 
64
  <tr>
65
  <th scope="row" valign="top">
66
  <label for="edd-amount"><?php _e( 'Amount', 'edd' ); ?></label>
@@ -71,6 +75,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
71
  <p class="description edd-amount-description"<?php echo $percent_display; ?>><?php _e( 'Enter the discount percentage. 10 = 10%', 'edd' ); ?></p>
72
  </td>
73
  </tr>
 
74
  <tr>
75
  <th scope="row" valign="top">
76
  <label for="edd-products"><?php printf( __( '%s Requirements', 'edd' ), edd_get_label_singular() ); ?></label>
@@ -82,7 +87,8 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
82
  'id' => 'products',
83
  'selected' => $product_reqs,
84
  'multiple' => true,
85
- 'chosen' => true
 
86
  ) ); ?><br/>
87
  </p>
88
  <div id="edd-discount-product-conditions"<?php echo $condition_display; ?>>
@@ -106,6 +112,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
106
  <p class="description"><?php printf( __( 'Select %s relevant to this discount.', 'edd' ), edd_get_label_plural() ); ?></p>
107
  </td>
108
  </tr>
 
109
  <tr>
110
  <th scope="row" valign="top">
111
  <label for="edd-excluded-products"><?php printf( __( 'Excluded %s', 'edd' ), edd_get_label_plural() ); ?></label>
@@ -116,11 +123,13 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
116
  'id' => 'excluded-products',
117
  'selected' => $excluded_products,
118
  'multiple' => true,
119
- 'chosen' => true
 
120
  ) ); ?><br/>
121
  <p class="description"><?php printf( __( '%s that this discount code cannot be applied to.', 'edd' ), edd_get_label_plural() ); ?></p>
122
  </td>
123
  </tr>
 
124
  <tr>
125
  <th scope="row" valign="top">
126
  <label for="edd-start"><?php _e( 'Start date', 'edd' ); ?></label>
@@ -130,6 +139,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
130
  <p class="description"><?php _e( 'Enter the start date for this discount code in the format of mm/dd/yyyy. For no start date, leave blank. If entered, the discount can only be used after or on this date.', 'edd' ); ?></p>
131
  </td>
132
  </tr>
 
133
  <tr>
134
  <th scope="row" valign="top">
135
  <label for="edd-expiration"><?php _e( 'Expiration date', 'edd' ); ?></label>
@@ -139,6 +149,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
139
  <p class="description"><?php _e( 'Enter the expiration date for this discount code in the format of mm/dd/yyyy. For no expiration, leave blank', 'edd' ); ?></p>
140
  </td>
141
  </tr>
 
142
  <tr>
143
  <th scope="row" valign="top">
144
  <label for="edd-max-uses"><?php _e( 'Max Uses', 'edd' ); ?></label>
@@ -148,6 +159,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
148
  <p class="description"><?php _e( 'The maximum number of times this discount can be used. Leave blank for unlimited.', 'edd' ); ?></p>
149
  </td>
150
  </tr>
 
151
  <tr>
152
  <th scope="row" valign="top">
153
  <label for="edd-min-cart-amount"><?php _e( 'Minimum Amount', 'edd' ); ?></label>
@@ -157,6 +169,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
157
  <p class="description"><?php _e( 'The minimum amount that must be purchased before this discount can be used. Leave blank for no minimum.', 'edd' ); ?></p>
158
  </td>
159
  </tr>
 
160
  <tr>
161
  <th scope="row" valign="top">
162
  <label for="edd-status"><?php _e( 'Status', 'edd' ); ?></label>
@@ -169,6 +182,7 @@ $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
169
  <p class="description"><?php _e( 'The status of this discount code.', 'edd' ); ?></p>
170
  </td>
171
  </tr>
 
172
  <tr>
173
  <th scope="row" valign="top">
174
  <label for="edd-use-once"><?php _e( 'Use Once Per Customer', 'edd' ); ?></label>
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Discounts
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
13
  if ( ! defined( 'ABSPATH' ) ) exit;
14
 
15
  if ( ! isset( $_GET['discount'] ) || ! is_numeric( $_GET['discount'] ) ) {
16
+ wp_die( __( 'Something went wrong.', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 400 ) );
17
  }
18
 
19
  $discount_id = absint( $_GET['discount'] );
22
  $excluded_products = edd_get_discount_excluded_products( $discount_id );
23
  $condition = edd_get_discount_product_condition( $discount_id );
24
  $single_use = edd_discount_is_single_use( $discount_id );
25
+ $flat_display = edd_get_discount_type( $discount_id ) == 'flat' ? '' : ' style="display:none;"';
26
+ $percent_display = edd_get_discount_type( $discount_id ) == 'percent' ? '' : ' style="display:none;"';
27
  $condition_display = empty( $product_reqs ) ? ' style="display:none;"' : '';
28
  ?>
29
  <h2><?php _e( 'Edit Discount', 'edd' ); ?> - <a href="<?php echo admin_url( 'edit.php?post_type=download&page=edd-discounts' ); ?>" class="button-secondary"><?php _e( 'Go Back', 'edd' ); ?></a></h2>
31
  <?php do_action( 'edd_edit_discount_form_top', $discount_id, $discount ); ?>
32
  <table class="form-table">
33
  <tbody>
34
+ <?php do_action( 'edd_edit_discount_form_before_name', $discount_id, $discount ); ?>
35
  <tr>
36
  <th scope="row" valign="top">
37
  <label for="edd-name"><?php _e( 'Name', 'edd' ); ?></label>
41
  <p class="description"><?php _e( 'The name of this discount', 'edd' ); ?></p>
42
  </td>
43
  </tr>
44
+ <?php do_action( 'edd_edit_discount_form_before_code', $discount_id, $discount ); ?>
45
  <tr>
46
  <th scope="row" valign="top">
47
  <label for="edd-code"><?php _e( 'Code', 'edd' ); ?></label>
51
  <p class="description"><?php _e( 'Enter a code for this discount, such as 10PERCENT', 'edd' ); ?></p>
52
  </td>
53
  </tr>
54
+ <?php do_action( 'edd_edit_discount_form_before_type', $discount_id, $discount ); ?>
55
  <tr>
56
  <th scope="row" valign="top">
57
  <label for="edd-type"><?php _e( 'Type', 'edd' ); ?></label>
64
  <p class="description"><?php _e( 'The kind of discount to apply for this discount.', 'edd' ); ?></p>
65
  </td>
66
  </tr>
67
+ <?php do_action( 'edd_edit_discount_form_before_amount', $discount_id, $discount ); ?>
68
  <tr>
69
  <th scope="row" valign="top">
70
  <label for="edd-amount"><?php _e( 'Amount', 'edd' ); ?></label>
75
  <p class="description edd-amount-description"<?php echo $percent_display; ?>><?php _e( 'Enter the discount percentage. 10 = 10%', 'edd' ); ?></p>
76
  </td>
77
  </tr>
78
+ <?php do_action( 'edd_edit_discount_form_before_products', $discount_id, $discount ); ?>
79
  <tr>
80
  <th scope="row" valign="top">
81
  <label for="edd-products"><?php printf( __( '%s Requirements', 'edd' ), edd_get_label_singular() ); ?></label>
87
  'id' => 'products',
88
  'selected' => $product_reqs,
89
  'multiple' => true,
90
+ 'chosen' => true,
91
+ 'placeholder' => sprintf( __( 'Select one or more %s', 'edd' ), edd_get_label_plural() )
92
  ) ); ?><br/>
93
  </p>
94
  <div id="edd-discount-product-conditions"<?php echo $condition_display; ?>>
112
  <p class="description"><?php printf( __( 'Select %s relevant to this discount.', 'edd' ), edd_get_label_plural() ); ?></p>
113
  </td>
114
  </tr>
115
+ <?php do_action( 'edd_edit_discount_form_before_excluded_products', $discount_id, $discount ); ?>
116
  <tr>
117
  <th scope="row" valign="top">
118
  <label for="edd-excluded-products"><?php printf( __( 'Excluded %s', 'edd' ), edd_get_label_plural() ); ?></label>
123
  'id' => 'excluded-products',
124
  'selected' => $excluded_products,
125
  'multiple' => true,
126
+ 'chosen' => true,
127
+ 'placeholder' => sprintf( __( 'Select one or more %s', 'edd' ), edd_get_label_plural() )
128
  ) ); ?><br/>
129
  <p class="description"><?php printf( __( '%s that this discount code cannot be applied to.', 'edd' ), edd_get_label_plural() ); ?></p>
130
  </td>
131
  </tr>
132
+ <?php do_action( 'edd_edit_discount_form_before_start', $discount_id, $discount ); ?>
133
  <tr>
134
  <th scope="row" valign="top">
135
  <label for="edd-start"><?php _e( 'Start date', 'edd' ); ?></label>
139
  <p class="description"><?php _e( 'Enter the start date for this discount code in the format of mm/dd/yyyy. For no start date, leave blank. If entered, the discount can only be used after or on this date.', 'edd' ); ?></p>
140
  </td>
141
  </tr>
142
+ <?php do_action( 'edd_edit_discount_form_before_expiration', $discount_id, $discount ); ?>
143
  <tr>
144
  <th scope="row" valign="top">
145
  <label for="edd-expiration"><?php _e( 'Expiration date', 'edd' ); ?></label>
149
  <p class="description"><?php _e( 'Enter the expiration date for this discount code in the format of mm/dd/yyyy. For no expiration, leave blank', 'edd' ); ?></p>
150
  </td>
151
  </tr>
152
+ <?php do_action( 'edd_edit_discount_form_before_max_uses', $discount_id, $discount ); ?>
153
  <tr>
154
  <th scope="row" valign="top">
155
  <label for="edd-max-uses"><?php _e( 'Max Uses', 'edd' ); ?></label>
159
  <p class="description"><?php _e( 'The maximum number of times this discount can be used. Leave blank for unlimited.', 'edd' ); ?></p>
160
  </td>
161
  </tr>
162
+ <?php do_action( 'edd_edit_discount_form_before_min_cart_amount', $discount_id, $discount ); ?>
163
  <tr>
164
  <th scope="row" valign="top">
165
  <label for="edd-min-cart-amount"><?php _e( 'Minimum Amount', 'edd' ); ?></label>
169
  <p class="description"><?php _e( 'The minimum amount that must be purchased before this discount can be used. Leave blank for no minimum.', 'edd' ); ?></p>
170
  </td>
171
  </tr>
172
+ <?php do_action( 'edd_edit_discount_form_before_status', $discount_id, $discount ); ?>
173
  <tr>
174
  <th scope="row" valign="top">
175
  <label for="edd-status"><?php _e( 'Status', 'edd' ); ?></label>
182
  <p class="description"><?php _e( 'The status of this discount code.', 'edd' ); ?></p>
183
  </td>
184
  </tr>
185
+ <?php do_action( 'edd_edit_discount_form_before_use_once', $discount_id, $discount ); ?>
186
  <tr>
187
  <th scope="row" valign="top">
188
  <label for="edd-use-once"><?php _e( 'Use Once Per Customer', 'edd' ); ?></label>
includes/admin/downloads/contextual-help.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Downloads
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.2.3
10
  */
@@ -90,9 +90,15 @@ function edd_downloads_contextual_help() {
90
  <li><strong>color</strong> - <em>' . implode( '</em> | <em>', $colors ) . '</em></li>
91
  <li><strong>class</strong> - ' . __( 'One or more custom CSS classes you want applied to the button.', 'edd' ) . '</li>
92
  </ul>' .
93
- '<p>' . sprintf( __( 'For more information, see <a href="%s">using Shortcodes</a> on the WordPress.org Codex or <a href="%s">Easy Digital Downloads Documentation</a>', 'edd' ), 'http://codex.wordpress.org/Shortcode', 'https://easydigitaldownloads.com/docs/display-purchase-buttons-purchase_link/' ) . '</p>'
94
  ) );
95
-
 
 
 
 
 
 
96
  do_action( 'edd_downloads_contextual_help', $screen );
97
  }
98
  add_action( 'load-post.php', 'edd_downloads_contextual_help' );
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Downloads
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.2.3
10
  */
90
  <li><strong>color</strong> - <em>' . implode( '</em> | <em>', $colors ) . '</em></li>
91
  <li><strong>class</strong> - ' . __( 'One or more custom CSS classes you want applied to the button.', 'edd' ) . '</li>
92
  </ul>' .
93
+ '<p>' . sprintf( __( 'For more information, see <a href="%s">using Shortcodes</a> on the WordPress.org Codex or <a href="%s">Easy Digital Downloads Documentation</a>', 'edd' ), 'https://codex.wordpress.org/Shortcode', 'https://easydigitaldownloads.com/docs/display-purchase-buttons-purchase_link/' ) . '</p>'
94
  ) );
95
+
96
+ /**
97
+ * Fires off in the EDD Downloads Contextual Help Screen
98
+ *
99
+ * @since 1.2.3
100
+ * @param object $screen The current admin screen
101
+ */
102
  do_action( 'edd_downloads_contextual_help', $screen );
103
  }
104
  add_action( 'load-post.php', 'edd_downloads_contextual_help' );
includes/admin/downloads/dashboard-columns.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Downloads
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -49,12 +49,10 @@ add_filter( 'manage_edit-download_columns', 'edd_download_columns' );
49
  */
50
  function edd_render_download_columns( $column_name, $post_id ) {
51
  if ( get_post_type( $post_id ) == 'download' ) {
52
- global $edd_options;
53
-
54
- $style = isset( $edd_options['button_style'] ) ? $edd_options['button_style'] : 'button';
55
- $color = isset( $edd_options['checkout_color'] ) ? $edd_options['checkout_color'] : 'blue';
56
- $color = ( $color == 'inherit' ) ? '' : $color;
57
- $purchase_text = ! empty( $edd_options['add_to_cart_text'] ) ? $edd_options['add_to_cart_text'] : __( 'Purchase', 'edd' );
58
 
59
  switch ( $column_name ) {
60
  case 'download_category':
@@ -73,7 +71,7 @@ function edd_render_download_columns( $column_name, $post_id ) {
73
  break;
74
  case 'sales':
75
  if ( current_user_can( 'view_product_stats', $post_id ) ) {
76
- echo '<a href="' . esc_url( admin_url( 'edit.php?post_type=download&page=edd-reports&tab=logs&download=' . $post_id ) ) . '">';
77
  echo edd_get_download_sales_stats( $post_id );
78
  echo '</a>';
79
  } else {
@@ -160,6 +158,38 @@ function edd_sort_downloads( $vars ) {
160
  return $vars;
161
  }
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  /**
164
  * Download Load
165
  *
@@ -170,6 +200,7 @@ function edd_sort_downloads( $vars ) {
170
  */
171
  function edd_download_load() {
172
  add_filter( 'request', 'edd_sort_downloads' );
 
173
  }
174
  add_action( 'load-edit.php', 'edd_download_load', 9999 );
175
 
@@ -207,11 +238,40 @@ function edd_add_download_filters() {
207
  }
208
  echo "</select>";
209
  }
 
 
 
 
 
 
 
210
  }
211
 
212
  }
213
  add_action( 'restrict_manage_posts', 'edd_add_download_filters', 100 );
214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  /**
216
  * Adds price field to Quick Edit options
217
  *
@@ -265,11 +325,17 @@ add_action( 'save_post', 'edd_price_save_quick_edit' );
265
  * @return void
266
  */
267
  function edd_save_bulk_edit() {
268
- $post_ids = ( isset( $_POST[ 'post_ids' ] ) && ! empty( $_POST[ 'post_ids' ] ) ) ? $_POST[ 'post_ids' ] : array();
 
269
 
270
  if ( ! empty( $post_ids ) && is_array( $post_ids ) ) {
271
  $price = isset( $_POST['price'] ) ? strip_tags( stripslashes( $_POST['price'] ) ) : 0;
272
  foreach ( $post_ids as $post_id ) {
 
 
 
 
 
273
  if ( ! empty( $price ) ) {
274
  update_post_meta( $post_id, 'edd_price', edd_sanitize_amount( $price ) );
275
  }
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Downloads
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
49
  */
50
  function edd_render_download_columns( $column_name, $post_id ) {
51
  if ( get_post_type( $post_id ) == 'download' ) {
52
+ $style = edd_get_option( 'button_style', 'button' );
53
+ $color = edd_get_option( 'checkout_color', 'blue' );
54
+ $color = ( $color == 'inherit' ) ? '' : $color;
55
+ $purchase_text = edd_get_option( 'add_to_cart_text', __( 'Purchase', 'edd' ) );
 
 
56
 
57
  switch ( $column_name ) {
58
  case 'download_category':
71
  break;
72
  case 'sales':
73
  if ( current_user_can( 'view_product_stats', $post_id ) ) {
74
+ echo '<a href="' . esc_url( admin_url( 'edit.php?post_type=download&page=edd-reports&tab=logs&view=sales&download=' . $post_id ) ) . '">';
75
  echo edd_get_download_sales_stats( $post_id );
76
  echo '</a>';
77
  } else {
158
  return $vars;
159
  }
160
 
161
+ /**
162
+ * Sets restrictions on author of Downloads List Table
163
+ *
164
+ * @since 2.2
165
+ * @param array $vars Array of all sort varialbes
166
+ * @return array Array of all sort variables
167
+ */
168
+ function edd_filter_downloads( $vars ) {
169
+ if ( isset( $vars['post_type'] ) && 'download' == $vars['post_type'] ) {
170
+
171
+ // If an author ID was passed, use it
172
+ if ( isset( $_REQUEST['author'] ) && ! current_user_can( 'view_shop_reports' ) ) {
173
+
174
+ $author_id = $_REQUEST['author'];
175
+ if ( (int) $author_id !== get_current_user_id() ) {
176
+ // Tried to view the products of another person, sorry
177
+ wp_die( __( 'You do not have permission to view this data.', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
178
+ }
179
+ $vars = array_merge(
180
+ $vars,
181
+ array(
182
+ 'author' => get_current_user_id()
183
+ )
184
+ );
185
+
186
+ }
187
+
188
+ }
189
+
190
+ return $vars;
191
+ }
192
+
193
  /**
194
  * Download Load
195
  *
200
  */
201
  function edd_download_load() {
202
  add_filter( 'request', 'edd_sort_downloads' );
203
+ add_filter( 'request', 'edd_filter_downloads' );
204
  }
205
  add_action( 'load-edit.php', 'edd_download_load', 9999 );
206
 
238
  }
239
  echo "</select>";
240
  }
241
+
242
+ if ( isset( $_REQUEST['all_posts'] ) && '1' === $_REQUEST['all_posts'] ) {
243
+ echo '<input type="hidden" name="all_posts" value="1" />';
244
+ } else if ( ! current_user_can( 'view_shop_reports' ) ) {
245
+ $author_id = get_current_user_id();
246
+ echo '<input type="hidden" name="author" value="' . esc_attr( $author_id ) . '" />';
247
+ }
248
  }
249
 
250
  }
251
  add_action( 'restrict_manage_posts', 'edd_add_download_filters', 100 );
252
 
253
+ /**
254
+ * Remove Download Month Filter
255
+ *
256
+ * Removes the drop down filter for downloads by date.
257
+ *
258
+ * @author Daniel J Griffiths
259
+ * @since 2.1
260
+ * @param array $dates The preset array of dates
261
+ * @global $typenow The post type we are viewing
262
+ * @return array Empty array disables the dropdown
263
+ */
264
+ function edd_remove_month_filter( $dates ) {
265
+ global $typenow;
266
+
267
+ if ( $typenow == 'download' ) {
268
+ $dates = array();
269
+ }
270
+
271
+ return $dates;
272
+ }
273
+ add_filter( 'months_dropdown_results', 'edd_remove_month_filter', 99 );
274
+
275
  /**
276
  * Adds price field to Quick Edit options
277
  *
325
  * @return void
326
  */
327
  function edd_save_bulk_edit() {
328
+
329
+ $post_ids = ( isset( $_POST['post_ids'] ) && ! empty( $_POST['post_ids'] ) ) ? $_POST['post_ids'] : array();
330
 
331
  if ( ! empty( $post_ids ) && is_array( $post_ids ) ) {
332
  $price = isset( $_POST['price'] ) ? strip_tags( stripslashes( $_POST['price'] ) ) : 0;
333
  foreach ( $post_ids as $post_id ) {
334
+
335
+ if( ! current_user_can( 'edit_post', $post_id ) ) {
336
+ continue;
337
+ }
338
+
339
  if ( ! empty( $price ) ) {
340
  update_post_meta( $post_id, 'edd_price', edd_sanitize_amount( $price ) );
341
  }
includes/admin/downloads/metabox.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Downloads
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -68,7 +68,8 @@ function edd_download_metabox_fields() {
68
  '_edd_hide_purchase_link',
69
  '_edd_download_tax_exclusive',
70
  '_edd_button_behavior',
71
- 'edd_product_notes'
 
72
  );
73
 
74
  if ( current_user_can( 'manage_shop_settings' ) ) {
@@ -132,6 +133,11 @@ function edd_download_meta_box_save( $post_id, $post ) {
132
  }
133
  }
134
 
 
 
 
 
 
135
  } else {
136
 
137
  if ( ! empty( $_POST[ $field ] ) ) {
@@ -161,7 +167,7 @@ add_action( 'save_post', 'edd_download_meta_box_save', 10, 2 );
161
  *
162
  * @since 1.3.2
163
  * @param string $price Price before sanitization
164
- * @return float $price Sanitized price
165
  */
166
  function edd_sanitize_price_save( $price ) {
167
  return edd_sanitize_amount( $price );
@@ -179,11 +185,14 @@ add_filter( 'edd_metabox_save_edd_price', 'edd_sanitize_price_save' );
179
  */
180
  function edd_sanitize_variable_prices_save( $prices ) {
181
 
182
- global $post;
183
-
184
  foreach( $prices as $id => $price ) {
185
 
186
- if( empty( $price['amount'] ) ) {
 
 
 
 
 
187
 
188
  $price['amount'] = 0;
189
 
@@ -193,8 +202,7 @@ function edd_sanitize_variable_prices_save( $prices ) {
193
 
194
  }
195
 
196
- // Make sure all prices are rekeyed starting at 0
197
- return array_values( $prices );
198
  }
199
  add_filter( 'edd_metabox_save_edd_variable_prices', 'edd_sanitize_variable_prices_save' );
200
 
@@ -236,12 +244,12 @@ function edd_sanitize_files_save( $files ) {
236
  // Clean up filenames to ensure whitespaces are stripped
237
  foreach( $files as $id => $file ) {
238
 
239
- if( ! empty( $files[ $id ][ 'file' ] ) ) {
240
- $files[ $id ][ 'file' ] = trim( $file[ 'file' ] );
241
  }
242
 
243
- if( ! empty( $files[ $id ][ 'name' ] ) ) {
244
- $files[ $id ][ 'name' ] = trim( $file[ 'name' ] );
245
  }
246
  }
247
 
@@ -285,7 +293,7 @@ add_filter( 'edd_metabox_save_edd_download_files', 'edd_metabox_save_check_blank
285
  * @return void
286
  */
287
  function edd_render_download_meta_box() {
288
- global $post, $edd_options;
289
 
290
  /*
291
  * Output the price fields
@@ -311,7 +319,7 @@ function edd_render_download_meta_box() {
311
  * @return void
312
  */
313
  function edd_render_files_meta_box() {
314
- global $post, $edd_options;
315
 
316
  /*
317
  * Output the files fields
@@ -327,7 +335,7 @@ function edd_render_files_meta_box() {
327
  * @return void
328
  */
329
  function edd_render_settings_meta_box() {
330
- global $post, $edd_options;
331
 
332
  /*
333
  * Output the files fields
@@ -352,15 +360,14 @@ function edd_render_settings_meta_box() {
352
  * @param $post_id
353
  */
354
  function edd_render_price_field( $post_id ) {
355
- global $edd_options;
356
-
357
- $price = edd_get_download_price( $post_id );
358
- $variable_pricing = edd_has_variable_prices( $post_id );
359
- $prices = edd_get_variable_prices( $post_id );
360
  $single_option_mode = edd_single_price_option_mode( $post_id );
361
 
362
- $price_display = $variable_pricing ? ' style="display:none;"' : '';
363
- $variable_display = $variable_pricing ? '' : ' style="display:none;"';
 
364
  ?>
365
  <p>
366
  <strong><?php echo apply_filters( 'edd_price_options_heading', __( 'Pricing Options:', 'edd' ) ); ?></strong>
@@ -382,7 +389,7 @@ function edd_render_price_field( $post_id ) {
382
  );
383
  ?>
384
 
385
- <?php if ( ! isset( $edd_options['currency_position'] ) || $edd_options['currency_position'] == 'before' ) : ?>
386
  <?php echo edd_currency_filter( '' ); ?>
387
  <?php echo EDD()->html->text( $price_args ); ?>
388
  <?php else : ?>
@@ -405,11 +412,11 @@ function edd_render_price_field( $post_id ) {
405
  <table class="widefat edd_repeatable_table" width="100%" cellpadding="0" cellspacing="0">
406
  <thead>
407
  <tr>
408
- <!--drag handle column. Disabled until we can work out a way to solve the issues raised here: https://github.com/easydigitaldownloads/Easy-Digital-Downloads/issues/1066
409
  <th style="width: 20px"></th>
410
- -->
411
  <th><?php _e( 'Option Name', 'edd' ); ?></th>
412
  <th style="width: 100px"><?php _e( 'Price', 'edd' ); ?></th>
 
 
413
  <?php do_action( 'edd_download_price_table_head', $post_id ); ?>
414
  <th style="width: 2%"></th>
415
  </tr>
@@ -417,21 +424,22 @@ function edd_render_price_field( $post_id ) {
417
  <tbody>
418
  <?php
419
  if ( ! empty( $prices ) ) :
 
420
  foreach ( $prices as $key => $value ) :
421
- $name = isset( $value['name'] ) ? $value['name'] : '';
422
  $amount = isset( $value['amount'] ) ? $value['amount'] : '';
423
-
424
  $args = apply_filters( 'edd_price_row_args', compact( 'name', 'amount' ), $value );
425
- ?>
426
- <tr class="edd_variable_prices_wrapper edd_repeatable_row">
427
- <?php do_action( 'edd_render_price_row', $key, $args, $post_id ); ?>
428
- </tr>
429
- <?php
430
  endforeach;
431
  else :
432
  ?>
433
- <tr class="edd_variable_prices_wrapper edd_repeatable_row">
434
- <?php do_action( 'edd_render_price_row', 0, array(), $post_id ); ?>
435
  </tr>
436
  <?php endif; ?>
437
 
@@ -460,28 +468,26 @@ add_action( 'edd_meta_box_price_fields', 'edd_render_price_field', 10 );
460
  * @param array $args
461
  * @param $post_id
462
  */
463
- function edd_render_price_row( $key, $args = array(), $post_id ) {
464
- global $edd_options;
465
-
466
  $defaults = array(
467
  'name' => null,
468
  'amount' => null
469
  );
470
 
471
  $args = wp_parse_args( $args, $defaults );
472
- extract( $args, EXTR_SKIP );
 
 
 
473
  ?>
474
- <!--
475
- Disabled until we can work out a way to solve the issues raised here: https://github.com/easydigitaldownloads/Easy-Digital-Downloads/issues/1066
476
  <td>
477
  <span class="edd_draghandle"></span>
 
478
  </td>
479
- -->
480
-
481
  <td>
482
  <?php echo EDD()->html->text( array(
483
  'name' => 'edd_variable_prices[' . $key . '][name]',
484
- 'value' => esc_attr( $name ),
485
  'placeholder' => __( 'Option Name', 'edd' ),
486
  'class' => 'edd_variable_prices_name large-text'
487
  ) ); ?>
@@ -491,13 +497,13 @@ function edd_render_price_row( $key, $args = array(), $post_id ) {
491
  <?php
492
  $price_args = array(
493
  'name' => 'edd_variable_prices[' . $key . '][amount]',
494
- 'value' => $amount,
495
  'placeholder' => '9.99',
496
  'class' => 'edd-price-field'
497
  );
498
  ?>
499
 
500
- <?php if( ! isset( $edd_options['currency_position'] ) || $edd_options['currency_position'] == 'before' ) : ?>
501
  <span><?php echo edd_currency_filter( '' ); ?></span>
502
  <?php echo EDD()->html->text( $price_args ); ?>
503
  <?php else : ?>
@@ -505,6 +511,11 @@ function edd_render_price_row( $key, $args = array(), $post_id ) {
505
  <?php echo edd_currency_filter( '' ); ?>
506
  <?php endif; ?>
507
  </td>
 
 
 
 
 
508
 
509
  <?php do_action( 'edd_download_price_table_row', $post_id, $key, $args ); ?>
510
 
@@ -513,7 +524,7 @@ function edd_render_price_row( $key, $args = array(), $post_id ) {
513
  </td>
514
  <?php
515
  }
516
- add_action( 'edd_render_price_row', 'edd_render_price_row', 10, 3 );
517
 
518
  /**
519
  * Product type options
@@ -574,7 +585,8 @@ function edd_render_products_field( $post_id ) {
574
  'id' => 'edd_bundled_products',
575
  'selected' => $products,
576
  'multiple' => true,
577
- 'chosen' => true
 
578
  ) );
579
  ?>
580
  </td>
@@ -606,6 +618,7 @@ function edd_render_files_field( $post_id = 0 ) {
606
  $variable_pricing = edd_has_variable_prices( $post_id );
607
  $display = $type == 'bundle' ? ' style="display:none;"' : '';
608
  $variable_display = $variable_pricing ? '' : 'display:none;';
 
609
  ?>
610
  <div id="edd_download_files"<?php echo $display; ?>>
611
  <p>
@@ -639,7 +652,7 @@ function edd_render_files_field( $post_id = 0 ) {
639
 
640
  $args = apply_filters( 'edd_file_row_args', compact( 'name', 'file', 'condition', 'attachment_id' ), $value );
641
  ?>
642
- <tr class="edd_repeatable_upload_wrapper edd_repeatable_row">
643
  <?php do_action( 'edd_render_file_row', $key, $args, $post_id ); ?>
644
  </tr>
645
  <?php
@@ -718,7 +731,7 @@ function edd_render_file_row( $key = '', $args = array(), $post_id ) {
718
  ) ); ?>
719
 
720
  <span class="edd_upload_file">
721
- <a href="#" data-uploader_title="" data-uploader_button_text="<?php _e( 'Insert', 'edd' ); ?>" class="edd_upload_file_button" onclick="return false;"><?php _e( 'Upload a File', 'edd' ); ?></a>
722
  </span>
723
  </div>
724
  </td>
@@ -729,7 +742,7 @@ function edd_render_file_row( $key = '', $args = array(), $post_id ) {
729
 
730
  if ( $prices ) {
731
  foreach ( $prices as $price_key => $price ) {
732
- $options[ $price_key ] = $prices[ $price_key ][ 'name' ];
733
  }
734
  }
735
 
@@ -752,6 +765,29 @@ function edd_render_file_row( $key = '', $args = array(), $post_id ) {
752
  }
753
  add_action( 'edd_render_file_row', 'edd_render_file_row', 10, 3 );
754
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
755
 
756
  /**
757
  * File Download Limit Row
@@ -764,8 +800,6 @@ add_action( 'edd_render_file_row', 'edd_render_file_row', 10, 3 );
764
  * @return void
765
  */
766
  function edd_render_download_limit_row( $post_id ) {
767
- global $edd_options;
768
-
769
  if( ! current_user_can( 'manage_shop_settings' ) )
770
  return;
771
 
@@ -797,8 +831,6 @@ add_action( 'edd_meta_box_settings_fields', 'edd_render_download_limit_row', 20
797
  * @return void
798
  */
799
  function edd_render_dowwn_tax_options( $post_id = 0 ) {
800
- global $edd_options;
801
-
802
  if( ! current_user_can( 'manage_shop_settings' ) || ! edd_use_taxes() )
803
  return;
804
 
@@ -824,8 +856,6 @@ add_action( 'edd_meta_box_settings_fields', 'edd_render_dowwn_tax_options', 30 )
824
  * @return void
825
  */
826
  function edd_render_accounting_options( $post_id ) {
827
- global $edd_options;
828
-
829
  if( ! edd_use_skus() ) {
830
  return;
831
  }
@@ -900,11 +930,10 @@ add_action( 'edd_meta_box_settings_fields', 'edd_render_disable_button', 30 );
900
  *
901
  * @since 1.2.1
902
  * @global array $post Contains all the download data
903
- * @global array $edd_options Contains all the options set for EDD
904
  * @return void
905
  */
906
  function edd_render_product_notes_meta_box() {
907
- global $post, $edd_options;
908
 
909
  do_action( 'edd_product_notes_meta_box_fields', $post->ID );
910
  }
@@ -917,8 +946,6 @@ function edd_render_product_notes_meta_box() {
917
  * @return void
918
  */
919
  function edd_render_product_notes_field( $post_id ) {
920
- global $edd_options;
921
-
922
  $product_notes = edd_get_product_notes( $post_id );
923
  ?>
924
  <textarea rows="1" cols="40" class="large-texarea" name="edd_product_notes" id="edd_product_notes_field"><?php echo esc_textarea( $product_notes ); ?></textarea>
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Downloads
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
68
  '_edd_hide_purchase_link',
69
  '_edd_download_tax_exclusive',
70
  '_edd_button_behavior',
71
+ 'edd_product_notes',
72
+ '_edd_default_price_id'
73
  );
74
 
75
  if ( current_user_can( 'manage_shop_settings' ) ) {
133
  }
134
  }
135
 
136
+ } elseif ( '_edd_default_price_id' == $field && edd_has_variable_prices( $post_id ) ) {
137
+
138
+ $new_default_price_id = ! empty( $_POST[$field] ) && is_numeric( $_POST[$field] ) ? (int)$_POST[$field] : 1;
139
+ update_post_meta( $post_id, $field, $new_default_price_id );
140
+
141
  } else {
142
 
143
  if ( ! empty( $_POST[ $field ] ) ) {
167
  *
168
  * @since 1.3.2
169
  * @param string $price Price before sanitization
170
+ * @return string $price Sanitized price
171
  */
172
  function edd_sanitize_price_save( $price ) {
173
  return edd_sanitize_amount( $price );
185
  */
186
  function edd_sanitize_variable_prices_save( $prices ) {
187
 
 
 
188
  foreach( $prices as $id => $price ) {
189
 
190
+ if( empty( $price['amount'] ) && empty( $price['name'] ) ) {
191
+
192
+ unset( $prices[ $id ] );
193
+ continue;
194
+
195
+ } elseif( empty( $price['amount'] ) ) {
196
 
197
  $price['amount'] = 0;
198
 
202
 
203
  }
204
 
205
+ return $prices;
 
206
  }
207
  add_filter( 'edd_metabox_save_edd_variable_prices', 'edd_sanitize_variable_prices_save' );
208
 
244
  // Clean up filenames to ensure whitespaces are stripped
245
  foreach( $files as $id => $file ) {
246
 
247
+ if( ! empty( $files[ $id ]['file'] ) ) {
248
+ $files[ $id ]['file'] = trim( $file['file'] );
249
  }
250
 
251
+ if( ! empty( $files[ $id ]['name'] ) ) {
252
+ $files[ $id ]['name'] = trim( $file['name'] );
253
  }
254
  }
255
 
293
  * @return void
294
  */
295
  function edd_render_download_meta_box() {
296
+ global $post;
297
 
298
  /*
299
  * Output the price fields
319
  * @return void
320
  */
321
  function edd_render_files_meta_box() {
322
+ global $post;
323
 
324
  /*
325
  * Output the files fields
335
  * @return void
336
  */
337
  function edd_render_settings_meta_box() {
338
+ global $post;
339
 
340
  /*
341
  * Output the files fields
360
  * @param $post_id
361
  */
362
  function edd_render_price_field( $post_id ) {
363
+ $price = edd_get_download_price( $post_id );
364
+ $variable_pricing = edd_has_variable_prices( $post_id );
365
+ $prices = edd_get_variable_prices( $post_id );
 
 
366
  $single_option_mode = edd_single_price_option_mode( $post_id );
367
 
368
+ $price_display = $variable_pricing ? ' style="display:none;"' : '';
369
+ $variable_display = $variable_pricing ? '' : ' style="display:none;"';
370
+ $currency_position = edd_get_option( 'currency_position', 'before' );
371
  ?>
372
  <p>
373
  <strong><?php echo apply_filters( 'edd_price_options_heading', __( 'Pricing Options:', 'edd' ) ); ?></strong>
389
  );
390
  ?>
391
 
392
+ <?php if ( $currency_position == 'before' ) : ?>
393
  <?php echo edd_currency_filter( '' ); ?>
394
  <?php echo EDD()->html->text( $price_args ); ?>
395
  <?php else : ?>
412
  <table class="widefat edd_repeatable_table" width="100%" cellpadding="0" cellspacing="0">
413
  <thead>
414
  <tr>
 
415
  <th style="width: 20px"></th>
 
416
  <th><?php _e( 'Option Name', 'edd' ); ?></th>
417
  <th style="width: 100px"><?php _e( 'Price', 'edd' ); ?></th>
418
+ <th class="edd_repeatable_default"><?php _e( 'Default', 'edd' ); ?></th>
419
+ <th style="width: 15px"><?php _e( 'ID', 'edd' ); ?></th>
420
  <?php do_action( 'edd_download_price_table_head', $post_id ); ?>
421
  <th style="width: 2%"></th>
422
  </tr>
424
  <tbody>
425
  <?php
426
  if ( ! empty( $prices ) ) :
427
+
428
  foreach ( $prices as $key => $value ) :
429
+ $name = isset( $value['name'] ) ? $value['name'] : '';
430
  $amount = isset( $value['amount'] ) ? $value['amount'] : '';
431
+ $index = isset( $value['index'] ) ? $value['index'] : $key;
432
  $args = apply_filters( 'edd_price_row_args', compact( 'name', 'amount' ), $value );
433
+ ?>
434
+ <tr class="edd_variable_prices_wrapper edd_repeatable_row" data-key="<?php echo esc_attr( $key ); ?>">
435
+ <?php do_action( 'edd_render_price_row', $key, $args, $post_id, $index ); ?>
436
+ </tr>
437
+ <?php
438
  endforeach;
439
  else :
440
  ?>
441
+ <tr class="edd_variable_prices_wrapper edd_repeatable_row" data-key="1">
442
+ <?php do_action( 'edd_render_price_row', 1, array(), $post_id, 1 ); ?>
443
  </tr>
444
  <?php endif; ?>
445
 
468
  * @param array $args
469
  * @param $post_id
470
  */
471
+ function edd_render_price_row( $key, $args = array(), $post_id, $index ) {
 
 
472
  $defaults = array(
473
  'name' => null,
474
  'amount' => null
475
  );
476
 
477
  $args = wp_parse_args( $args, $defaults );
478
+
479
+ $default_price_id = edd_get_default_variable_price( $post_id );
480
+ $currency_position = edd_get_option( 'currency_position', 'before' );
481
+
482
  ?>
 
 
483
  <td>
484
  <span class="edd_draghandle"></span>
485
+ <input type="hidden" name="edd_variable_prices[<?php echo $key; ?>][index]" class="edd_repeatable_index" value="<?php echo $index; ?>"/>
486
  </td>
 
 
487
  <td>
488
  <?php echo EDD()->html->text( array(
489
  'name' => 'edd_variable_prices[' . $key . '][name]',
490
+ 'value' => esc_attr( $args['name'] ),
491
  'placeholder' => __( 'Option Name', 'edd' ),
492
  'class' => 'edd_variable_prices_name large-text'
493
  ) ); ?>
497
  <?php
498
  $price_args = array(
499
  'name' => 'edd_variable_prices[' . $key . '][amount]',
500
+ 'value' => $args['amount'],
501
  'placeholder' => '9.99',
502
  'class' => 'edd-price-field'
503
  );
504
  ?>
505
 
506
+ <?php if( $currency_position == 'before' ) : ?>
507
  <span><?php echo edd_currency_filter( '' ); ?></span>
508
  <?php echo EDD()->html->text( $price_args ); ?>
509
  <?php else : ?>
511
  <?php echo edd_currency_filter( '' ); ?>
512
  <?php endif; ?>
513
  </td>
514
+ <td class="edd_repeatable_default_wrapper">
515
+ <input type="radio" <?php checked( $default_price_id, $key, true ); ?> class="edd_repeatable_default_input" name="_edd_default_price_id" value="<?php echo $key; ?>" />
516
+ <td>
517
+ <span class="edd_price_id"><?php echo $key; ?></span>
518
+ </td>
519
 
520
  <?php do_action( 'edd_download_price_table_row', $post_id, $key, $args ); ?>
521
 
524
  </td>
525
  <?php
526
  }
527
+ add_action( 'edd_render_price_row', 'edd_render_price_row', 10, 4 );
528
 
529
  /**
530
  * Product type options
585
  'id' => 'edd_bundled_products',
586
  'selected' => $products,
587
  'multiple' => true,
588
+ 'chosen' => true,
589
+ 'bundles' => false
590
  ) );
591
  ?>
592
  </td>
618
  $variable_pricing = edd_has_variable_prices( $post_id );
619
  $display = $type == 'bundle' ? ' style="display:none;"' : '';
620
  $variable_display = $variable_pricing ? '' : 'display:none;';
621
+
622
  ?>
623
  <div id="edd_download_files"<?php echo $display; ?>>
624
  <p>
652
 
653
  $args = apply_filters( 'edd_file_row_args', compact( 'name', 'file', 'condition', 'attachment_id' ), $value );
654
  ?>
655
+ <tr class="edd_repeatable_upload_wrapper edd_repeatable_row" data-key="<?php echo esc_attr( $key ); ?>">
656
  <?php do_action( 'edd_render_file_row', $key, $args, $post_id ); ?>
657
  </tr>
658
  <?php
731
  ) ); ?>
732
 
733
  <span class="edd_upload_file">
734
+ <a href="#" data-uploader-title="<?php _e( 'Insert File', 'edd' ); ?>" data-uploader-button-text="<?php _e( 'Insert', 'edd' ); ?>" class="edd_upload_file_button" onclick="return false;"><?php _e( 'Upload a File', 'edd' ); ?></a>
735
  </span>
736
  </div>
737
  </td>
742
 
743
  if ( $prices ) {
744
  foreach ( $prices as $price_key => $price ) {
745
+ $options[ $price_key ] = $prices[ $price_key ]['name'];
746
  }
747
  }
748
 
765
  }
766
  add_action( 'edd_render_file_row', 'edd_render_file_row', 10, 3 );
767
 
768
+ /**
769
+ * Alter the Add to post button in the media manager for downloads
770
+ *
771
+ * @since 2.2
772
+ * @param array $strings Array of default strings for media manager
773
+ * @return array The altered array of strings for media manager
774
+ */
775
+ function edd_download_media_strings( $strings ) {
776
+ global $post;
777
+
778
+ if ( ! $post || $post->post_type !== 'download' ) {
779
+ return $strings;
780
+ }
781
+
782
+ $downloads_object = get_post_type_object( 'download' );
783
+ $labels = $downloads_object->labels;
784
+
785
+ $strings['insertIntoPost'] = sprintf( __( 'Insert into %s', 'edd' ), strtolower( $labels->singular_name ) );
786
+
787
+ return $strings;
788
+ }
789
+ add_filter( 'media_view_strings', 'edd_download_media_strings', 10, 1 );
790
+
791
 
792
  /**
793
  * File Download Limit Row
800
  * @return void
801
  */
802
  function edd_render_download_limit_row( $post_id ) {
 
 
803
  if( ! current_user_can( 'manage_shop_settings' ) )
804
  return;
805
 
831
  * @return void
832
  */
833
  function edd_render_dowwn_tax_options( $post_id = 0 ) {
 
 
834
  if( ! current_user_can( 'manage_shop_settings' ) || ! edd_use_taxes() )
835
  return;
836
 
856
  * @return void
857
  */
858
  function edd_render_accounting_options( $post_id ) {
 
 
859
  if( ! edd_use_skus() ) {
860
  return;
861
  }
930
  *
931
  * @since 1.2.1
932
  * @global array $post Contains all the download data
 
933
  * @return void
934
  */
935
  function edd_render_product_notes_meta_box() {
936
+ global $post;
937
 
938
  do_action( 'edd_product_notes_meta_box_fields', $post->ID );
939
  }
946
  * @return void
947
  */
948
  function edd_render_product_notes_field( $post_id ) {
 
 
949
  $product_notes = edd_get_product_notes( $post_id );
950
  ?>
951
  <textarea rows="1" cols="40" class="large-texarea" name="edd_product_notes" id="edd_product_notes_field"><?php echo esc_textarea( $product_notes ); ?></textarea>
includes/admin/export-functions.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Export
9
- * @copyright Copyright (c) 2014, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  */
12
 
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Export
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  */
12
 
includes/admin/payments/actions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Payments
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.9
10
  */
@@ -21,43 +21,50 @@ if ( ! defined( 'ABSPATH' ) ) exit;
21
  */
22
  function edd_update_payment_details( $data ) {
23
 
24
- if( ! current_user_can( 'edit_shop_payment', $data['edd_payment_id' ] ) ) {
25
- wp_die( __( 'You do not have permission to edit this payment record', 'edd' ), __( 'Error', 'edd' ) );
26
  }
27
 
28
  check_admin_referer( 'edd_update_payment_details_nonce' );
29
-
30
  // Retrieve the payment ID
31
  $payment_id = absint( $data['edd_payment_id'] );
32
 
33
  // Retrieve existing payment meta
34
- $meta = edd_get_payment_meta( $payment_id );
35
- $user_info = edd_get_payment_meta_user_info( $payment_id );
36
-
37
- $status = $data['edd-payment-status'];
38
- $unlimited = isset( $data['edd-unlimited-downloads'] ) ? '1' : '';
39
- $user_id = intval( $data['edd-payment-user-id'] );
40
- $date = sanitize_text_field( $data['edd-payment-date'] );
41
- $hour = sanitize_text_field( $data['edd-payment-time-hour'] );
42
- $minute = sanitize_text_field( $data['edd-payment-time-min'] );
43
- $email = sanitize_text_field( $data['edd-payment-user-email'] );
44
- $names = sanitize_text_field( $data['edd-payment-user-name'] );
45
- $address = array_map( 'trim', $data['edd-payment-address'][0] );
46
-
47
- $total = edd_sanitize_amount( $_POST['edd-payment-total'] );
48
- $tax = isset( $_POST['edd-payment-tax'] ) ? edd_sanitize_amount( $_POST['edd-payment-tax'] ) : 0;
49
-
50
- // Setup date from input values
51
- $date = date( 'Y-m-d', strtotime( $date ) ) . ' ' . $hour . ':' . $minute . ':00';
52
 
53
- // Setup first and last name from input values
54
- $names = explode( ' ', $names );
55
- $first_name = ! empty( $names[0] ) ? $names[0] : '';
56
- if( ! empty( $names[1] ) ) {
57
- unset( $names[0] );
58
- $last_name = implode( ' ', $names );
 
59
  }
60
 
 
 
 
 
 
 
 
 
 
 
61
  // Setup purchased Downloads and price options
62
  $updated_downloads = isset( $_POST['edd-payment-details-downloads'] ) ? $_POST['edd-payment-details-downloads'] : false;
63
  if( $updated_downloads && ! empty( $_POST['edd-payment-downloads-changed'] ) ) {
@@ -66,10 +73,16 @@ function edd_update_payment_details( $data ) {
66
  $cart_details = array();
67
  $i = 0;
68
  foreach( $updated_downloads as $download ) {
 
 
 
 
 
69
  $item = array();
70
  $item['id'] = absint( $download['id'] );
71
- $item['quantity'] = absint( $download['quantity'] );
72
  $price_id = (int) $download['price_id'];
 
73
 
74
  if( $price_id !== false && edd_has_variable_prices( $item['id'] ) ) {
75
  $item['options'] = array(
@@ -81,23 +94,185 @@ function edd_update_payment_details( $data ) {
81
  $cart_item = array();
82
  $cart_item['item_number'] = $item;
83
 
 
 
84
  $cart_details[$i] = array(
85
  'name' => get_the_title( $download['id'] ),
86
  'id' => $download['id'],
87
  'item_number' => $item,
88
  'price' => $download['amount'],
 
 
89
  'quantity' => $download['quantity'],
 
 
90
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  $i++;
92
  }
93
 
94
  $meta['downloads'] = $downloads;
95
  $meta['cart_details'] = $cart_details;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  }
97
 
98
  // Set new meta values
99
- $user_info['id'] = $user_id;
100
- $user_info['email'] = $email;
101
  $user_info['first_name'] = $first_name;
102
  $user_info['last_name'] = $last_name;
103
  $user_info['address'] = $address;
@@ -107,28 +282,38 @@ function edd_update_payment_details( $data ) {
107
  // Check for payment notes
108
  if ( ! empty( $data['edd-payment-note'] ) ) {
109
 
110
- $note = wp_kses( $data['edd-payment-note'], array() );
111
- $note_id = edd_insert_payment_note( $payment_id, $note );
112
 
113
  }
114
 
115
- do_action( 'edd_update_edited_purchase', $payment_id );
116
-
117
- // Update main payment record
118
- wp_update_post( array(
119
- 'ID' => $payment_id,
120
- 'post_date' => $date
121
- ) );
122
-
123
  // Set new status
124
  edd_update_payment_status( $payment_id, $status );
125
 
126
- update_post_meta( $payment_id, '_edd_payment_user_id', $user_id );
127
- update_post_meta( $payment_id, '_edd_payment_user_email', $email );
128
- update_post_meta( $payment_id, '_edd_payment_meta', $meta );
129
- update_post_meta( $payment_id, '_edd_payment_total', $total );
130
- update_post_meta( $payment_id, '_edd_payment_downloads', $total );
131
- update_post_meta( $payment_id, '_edd_payment_unlimited_downloads', $unlimited );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
  do_action( 'edd_updated_edited_purchase', $payment_id );
134
 
@@ -137,11 +322,38 @@ function edd_update_payment_details( $data ) {
137
  }
138
  add_action( 'edd_update_payment_details', 'edd_update_payment_details' );
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  function edd_ajax_store_payment_note() {
141
 
142
  $payment_id = absint( $_POST['payment_id'] );
143
  $note = wp_kses( $_POST['note'], array() );
144
 
 
 
 
 
145
  if( empty( $payment_id ) )
146
  die( '-1' );
147
 
@@ -165,8 +377,8 @@ function edd_trigger_payment_note_deletion( $data ) {
165
  if( ! wp_verify_nonce( $data['_wpnonce'], 'edd_delete_payment_note_' . $data['note_id'] ) )
166
  return;
167
 
168
- if( ! current_user_can( 'edit_shop_payment', $data['payment_id' ] ) ) {
169
- wp_die( __( 'You do not have permission to edit this payment record', 'edd' ), __( 'Error', 'edd' ) );
170
  }
171
 
172
  $edit_order_url = admin_url( 'edit.php?post_type=download&page=edd-payment-history&view=view-order-details&edd-message=payment-note-deleted&id=' . absint( $data['payment_id'] ) );
@@ -181,13 +393,12 @@ add_action( 'edd_delete_payment_note', 'edd_trigger_payment_note_deletion' );
181
  * Delete a payment note deletion with ajax
182
  *
183
  * @since 1.6
184
- * @param array $data Arguments passed
185
  * @return void
186
  */
187
  function edd_ajax_delete_payment_note() {
188
 
189
- if( ! current_user_can( 'edit_shop_payment', $_POST['payment_id' ] ) ) {
190
- wp_die( __( 'You do not have permission to edit this payment record', 'edd' ), __( 'Error', 'edd' ) );
191
  }
192
 
193
  if( edd_delete_payment_note( $_POST['note_id'], $_POST['payment_id'] ) ) {
@@ -245,6 +456,6 @@ function edd_ajax_generate_file_download_link() {
245
  }
246
 
247
  die( $file_urls );
248
-
249
  }
250
- add_action( 'wp_ajax_edd_get_file_download_link', 'edd_ajax_generate_file_download_link' );
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Payments
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.9
10
  */
21
  */
22
  function edd_update_payment_details( $data ) {
23
 
24
+ if( ! current_user_can( 'edit_shop_payments', $data['edd_payment_id'] ) ) {
25
+ wp_die( __( 'You do not have permission to edit this payment record', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
26
  }
27
 
28
  check_admin_referer( 'edd_update_payment_details_nonce' );
29
+
30
  // Retrieve the payment ID
31
  $payment_id = absint( $data['edd_payment_id'] );
32
 
33
  // Retrieve existing payment meta
34
+ $meta = edd_get_payment_meta( $payment_id );
35
+ $user_info = edd_get_payment_meta_user_info( $payment_id );
36
+
37
+ $status = $data['edd-payment-status'];
38
+ $unlimited = isset( $data['edd-unlimited-downloads'] ) ? '1' : '';
39
+ $date = sanitize_text_field( $data['edd-payment-date'] );
40
+ $hour = sanitize_text_field( $data['edd-payment-time-hour'] );
41
+
42
+ // Restrict to our high and low
43
+ if ( $hour > 23 ) {
44
+ $hour = 23;
45
+ } elseif ( $hour < 0 ) {
46
+ $hour = 00;
47
+ }
 
 
 
 
48
 
49
+ $minute = sanitize_text_field( $data['edd-payment-time-min'] );
50
+
51
+ // Restrict to our high and low
52
+ if ( $minute > 59 ) {
53
+ $minute = 59;
54
+ } elseif ( $minute < 0 ) {
55
+ $minute = 00;
56
  }
57
 
58
+ $address = array_map( 'trim', $data['edd-payment-address'][0] );
59
+
60
+ $curr_total = edd_sanitize_amount( edd_get_payment_amount( $payment_id ) );
61
+ $new_total = edd_sanitize_amount( $_POST['edd-payment-total'] );
62
+ $tax = isset( $_POST['edd-payment-tax'] ) ? edd_sanitize_amount( $_POST['edd-payment-tax'] ) : 0;
63
+ $date = date( 'Y-m-d', strtotime( $date ) ) . ' ' . $hour . ':' . $minute . ':00';
64
+
65
+ $curr_customer_id = sanitize_text_field( $data['edd-current-customer'] );
66
+ $new_customer_id = sanitize_text_field( $data['customer-id'] );
67
+
68
  // Setup purchased Downloads and price options
69
  $updated_downloads = isset( $_POST['edd-payment-details-downloads'] ) ? $_POST['edd-payment-details-downloads'] : false;
70
  if( $updated_downloads && ! empty( $_POST['edd-payment-downloads-changed'] ) ) {
73
  $cart_details = array();
74
  $i = 0;
75
  foreach( $updated_downloads as $download ) {
76
+
77
+ if( empty( $download['amount'] ) ) {
78
+ $download['amount'] = '0.00';
79
+ }
80
+
81
  $item = array();
82
  $item['id'] = absint( $download['id'] );
83
+ $item['quantity'] = absint( $download['quantity'] ) > 0 ? absint( $download['quantity'] ) : 1;
84
  $price_id = (int) $download['price_id'];
85
+ $has_log = absint( $download['has_log'] );
86
 
87
  if( $price_id !== false && edd_has_variable_prices( $item['id'] ) ) {
88
  $item['options'] = array(
94
  $cart_item = array();
95
  $cart_item['item_number'] = $item;
96
 
97
+ $item_price = round( $download['amount'] / $item['quantity'], edd_currency_decimal_filter() );
98
+
99
  $cart_details[$i] = array(
100
  'name' => get_the_title( $download['id'] ),
101
  'id' => $download['id'],
102
  'item_number' => $item,
103
  'price' => $download['amount'],
104
+ 'item_price' => $item_price,
105
+ 'subtotal' => $download['amount'],
106
  'quantity' => $download['quantity'],
107
+ 'discount' => 0,
108
+ 'tax' => 0,
109
  );
110
+
111
+ // If this item doesn't have a log yet, add one for each quantity count
112
+ if ( empty( $has_log ) ) {
113
+
114
+ $log_date = date( 'Y-m-d G:i:s', current_time( 'timestamp', true ) );
115
+ $price_id = $price_id !== false ? $price_id : 0;
116
+
117
+ $y = 0;
118
+
119
+ while ( $y < $download['quantity'] ) {
120
+
121
+ edd_record_sale_in_log( $download['id'], $payment_id, $price_id, $log_date );
122
+ $y++;
123
+
124
+ }
125
+
126
+ edd_increase_purchase_count( $download['id'], $download['quantity'] );
127
+ edd_increase_earnings( $download['id'], $download['amount'] );
128
+
129
+
130
+ }
131
+
132
  $i++;
133
  }
134
 
135
  $meta['downloads'] = $downloads;
136
  $meta['cart_details'] = $cart_details;
137
+
138
+ $deleted_downloads = json_decode( stripcslashes( $data['edd-payment-removed'] ), true );
139
+
140
+ foreach ( $deleted_downloads as $deleted_download ) {
141
+ $deleted_download = $deleted_download[0];
142
+
143
+ if ( empty ( $deleted_download['id'] ) ) {
144
+ continue;
145
+ }
146
+
147
+ $price_id = empty( $deleted_download['price_id'] ) ? 0 : (int) $deleted_download['price_id'];
148
+
149
+ $log_args = array(
150
+ 'post_type' => 'edd_log',
151
+ 'post_parent' => $deleted_download['id'],
152
+ 'numberposts' => $deleted_download['quantity'],
153
+ 'meta_query' => array(
154
+ array(
155
+ 'key' => '_edd_log_payment_id',
156
+ 'value' => $payment_id,
157
+ 'compare' => '=',
158
+ ),
159
+ array(
160
+ 'key' => '_edd_log_price_id',
161
+ 'value' => $price_id,
162
+ 'compare' => '='
163
+ )
164
+ )
165
+ );
166
+
167
+ $found_logs = get_posts( $log_args );
168
+ foreach ( $found_logs as $log ) {
169
+ wp_delete_post( $log->ID, true );
170
+ }
171
+
172
+ edd_decrease_purchase_count( $deleted_download['id'], $deleted_download['quantity'] );
173
+ edd_decrease_earnings( $deleted_download['id'], $deleted_download['amount'] );
174
+
175
+ }
176
+
177
+
178
+ }
179
+
180
+ do_action( 'edd_update_edited_purchase', $payment_id );
181
+
182
+ // Update main payment record
183
+ $updated = wp_update_post( array(
184
+ 'ID' => $payment_id,
185
+ 'post_date' => $date
186
+ ) );
187
+
188
+ if ( 0 === $updated ) {
189
+ wp_die( __( 'Error Updating Payment', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 400 ) );
190
+ }
191
+
192
+ $customer_changed = false;
193
+
194
+ if ( isset( $data['edd-new-customer'] ) && $data['edd-new-customer'] == '1' ) {
195
+
196
+ $email = isset( $data['edd-new-customer-email'] ) ? sanitize_text_field( $data['edd-new-customer-email'] ) : '';
197
+ $names = isset( $data['edd-new-customer-name'] ) ? sanitize_text_field( $data['edd-new-customer-name'] ) : '';
198
+
199
+ if ( empty( $email ) || empty( $names ) ) {
200
+ wp_die( __( 'New Customers require a name and email address', 'edd' ) );
201
+ }
202
+
203
+ $customer = new EDD_Customer( $email );
204
+ if ( empty( $customer->id ) ) {
205
+ $customer_data = array( 'name' => $names, 'email' => $email );
206
+ $user_id = email_exists( $email );
207
+ if ( false !== $user_id ) {
208
+ $customer_data['user_id'] = $user_id;
209
+ }
210
+
211
+ if ( ! $customer->create( $customer_data ) ) {
212
+ // Failed to crete the new customer, assume the previous customer
213
+ $customer_changed = false;
214
+ $customer = new EDD_Customer( $curr_customer_id );
215
+ edd_set_error( 'edd-payment-new-customer-fail', __( 'Error creating new customer', 'edd' ) );
216
+ }
217
+ }
218
+
219
+ $new_customer_id = $customer->id;
220
+
221
+ $previous_customer = new EDD_Customer( $curr_customer_id );
222
+
223
+ $customer_changed = true;
224
+
225
+ } elseif ( $curr_customer_id !== $new_customer_id ) {
226
+
227
+ $customer = new EDD_Customer( $new_customer_id );
228
+ $email = $customer->email;
229
+ $names = $customer->name;
230
+
231
+ $previous_customer = new EDD_Customer( $curr_customer_id );
232
+
233
+ $customer_changed = true;
234
+
235
+ } else {
236
+
237
+ $customer = new EDD_Customer( $curr_customer_id );
238
+ $email = $customer->email;
239
+ $names = $customer->name;
240
+
241
+ }
242
+
243
+
244
+
245
+ // Setup first and last name from input values
246
+ $names = explode( ' ', $names );
247
+ $first_name = ! empty( $names[0] ) ? $names[0] : '';
248
+ $last_name = '';
249
+ if( ! empty( $names[1] ) ) {
250
+ unset( $names[0] );
251
+ $last_name = implode( ' ', $names );
252
+ }
253
+
254
+ if ( $customer_changed ) {
255
+
256
+ // Remove the stats and payment from the previous customer and attach it to the new customer
257
+ $previous_customer->remove_payment( $payment_id, false );
258
+ $customer->attach_payment( $payment_id, false );
259
+
260
+ // If purchase was completed and not ever refunded, adjust stats of customers
261
+ if( 'revoked' == $status || 'publish' == $status ) {
262
+
263
+ $previous_customer->decrease_purchase_count();
264
+ $previous_customer->decrease_value( $new_total );
265
+
266
+ $customer->increase_purchase_count();
267
+ $customer->increase_value( $new_total );
268
+ }
269
+
270
+ update_post_meta( $payment_id, '_edd_payment_customer_id', $customer->id );
271
  }
272
 
273
  // Set new meta values
274
+ $user_info['id'] = $customer->user_id;
275
+ $user_info['email'] = $customer->email;
276
  $user_info['first_name'] = $first_name;
277
  $user_info['last_name'] = $last_name;
278
  $user_info['address'] = $address;
282
  // Check for payment notes
283
  if ( ! empty( $data['edd-payment-note'] ) ) {
284
 
285
+ $note = wp_kses( $data['edd-payment-note'], array() );
286
+ edd_insert_payment_note( $payment_id, $note );
287
 
288
  }
289
 
 
 
 
 
 
 
 
 
290
  // Set new status
291
  edd_update_payment_status( $payment_id, $status );
292
 
293
+ edd_update_payment_meta( $payment_id, '_edd_payment_user_id', $customer->user_id );
294
+ edd_update_payment_meta( $payment_id, '_edd_payment_user_email', $customer->email );
295
+ edd_update_payment_meta( $payment_id, '_edd_payment_meta', $meta );
296
+ edd_update_payment_meta( $payment_id, '_edd_payment_total', $new_total );
297
+
298
+ // Adjust total store earnings if the payment total has been changed
299
+ if ( $new_total !== $curr_total && ( 'publish' == $status || 'revoked' == $status ) ) {
300
+
301
+ if ( $new_total > $curr_total ) {
302
+ // Increase if our new total is higher
303
+ $difference = $new_total - $curr_total;
304
+ edd_increase_total_earnings( $difference );
305
+
306
+ } elseif ( $curr_total > $new_total ) {
307
+ // Decrease if our new total is lower
308
+ $difference = $curr_total - $new_total;
309
+ edd_decrease_total_earnings( $difference );
310
+
311
+ }
312
+
313
+ }
314
+
315
+ edd_update_payment_meta( $payment_id, '_edd_payment_downloads', $new_total );
316
+ edd_update_payment_meta( $payment_id, '_edd_payment_unlimited_downloads', $unlimited );
317
 
318
  do_action( 'edd_updated_edited_purchase', $payment_id );
319
 
322
  }
323
  add_action( 'edd_update_payment_details', 'edd_update_payment_details' );
324
 
325
+ /**
326
+ * Trigger a Purchase Deletion
327
+ *
328
+ * @since 1.3.4
329
+ * @param $data Arguments passed
330
+ * @return void
331
+ */
332
+ function edd_trigger_purchase_delete( $data ) {
333
+ if ( wp_verify_nonce( $data['_wpnonce'], 'edd_payment_nonce' ) ) {
334
+
335
+ $payment_id = absint( $data['purchase_id'] );
336
+
337
+ if( ! current_user_can( 'edit_shop_payments', $payment_id ) ) {
338
+ wp_die( __( 'You do not have permission to edit this payment record', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
339
+ }
340
+
341
+ edd_delete_purchase( $payment_id );
342
+ wp_redirect( admin_url( '/edit.php?post_type=download&page=edd-payment-history&edd-message=payment_deleted' ) );
343
+ edd_die();
344
+ }
345
+ }
346
+ add_action( 'edd_delete_payment', 'edd_trigger_purchase_delete' );
347
+
348
  function edd_ajax_store_payment_note() {
349
 
350
  $payment_id = absint( $_POST['payment_id'] );
351
  $note = wp_kses( $_POST['note'], array() );
352
 
353
+ if( ! current_user_can( 'edit_shop_payments', $payment_id ) ) {
354
+ wp_die( __( 'You do not have permission to edit this payment record', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
355
+ }
356
+
357
  if( empty( $payment_id ) )
358
  die( '-1' );
359
 
377
  if( ! wp_verify_nonce( $data['_wpnonce'], 'edd_delete_payment_note_' . $data['note_id'] ) )
378
  return;
379
 
380
+ if( ! current_user_can( 'edit_shop_payments', $data['payment_id'] ) ) {
381
+ wp_die( __( 'You do not have permission to edit this payment record', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
382
  }
383
 
384
  $edit_order_url = admin_url( 'edit.php?post_type=download&page=edd-payment-history&view=view-order-details&edd-message=payment-note-deleted&id=' . absint( $data['payment_id'] ) );
393
  * Delete a payment note deletion with ajax
394
  *
395
  * @since 1.6
 
396
  * @return void
397
  */
398
  function edd_ajax_delete_payment_note() {
399
 
400
+ if( ! current_user_can( 'edit_shop_payments', $_POST['payment_id'] ) ) {
401
+ wp_die( __( 'You do not have permission to edit this payment record', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
402
  }
403
 
404
  if( edd_delete_payment_note( $_POST['note_id'], $_POST['payment_id'] ) ) {
456
  }
457
 
458
  die( $file_urls );
459
+
460
  }
461
+ add_action( 'wp_ajax_edd_get_file_download_link', 'edd_ajax_generate_file_download_link' );
includes/admin/payments/class-payments-table.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Payments
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
@@ -252,7 +252,7 @@ class EDD_Payment_History_Table extends WP_List_Table {
252
  * @access public
253
  * @since 1.4
254
  *
255
- * @param array $item Contains all the data of the discount code
256
  * @param string $column_name The name of the column
257
  *
258
  * @return string Column Name
@@ -261,7 +261,7 @@ class EDD_Payment_History_Table extends WP_List_Table {
261
  switch ( $column_name ) {
262
  case 'amount' :
263
  $amount = ! empty( $payment->total ) ? $payment->total : 0;
264
- $value = edd_currency_filter( edd_format_amount( $amount ) );
265
  break;
266
  case 'date' :
267
  $date = strtotime( $payment->date );
@@ -500,17 +500,12 @@ class EDD_Payment_History_Table extends WP_List_Table {
500
  * @return array $payment_data Array of all the data for the payments
501
  */
502
  public function payments_data() {
503
- $payments_data = array();
504
-
505
- $page = isset( $_GET['paged'] ) ? $_GET['paged'] : 1;
506
 
507
  $per_page = $this->per_page;
508
  $orderby = isset( $_GET['orderby'] ) ? urldecode( $_GET['orderby'] ) : 'ID';
509
  $order = isset( $_GET['order'] ) ? $_GET['order'] : 'DESC';
510
- $order_inverse = $order == 'DESC' ? 'ASC' : 'DESC';
511
- $order_class = strtolower( $order_inverse );
512
  $user = isset( $_GET['user'] ) ? $_GET['user'] : null;
513
- $status = isset( $_GET['status'] ) ? $_GET['status'] : 'any';
514
  $meta_key = isset( $_GET['meta_key'] ) ? $_GET['meta_key'] : null;
515
  $year = isset( $_GET['year'] ) ? $_GET['year'] : null;
516
  $month = isset( $_GET['m'] ) ? $_GET['m'] : null;
@@ -519,6 +514,10 @@ class EDD_Payment_History_Table extends WP_List_Table {
519
  $start_date = isset( $_GET['start-date'] ) ? sanitize_text_field( $_GET['start-date'] ) : null;
520
  $end_date = isset( $_GET['end-date'] ) ? sanitize_text_field( $_GET['end-date'] ) : $start_date;
521
 
 
 
 
 
522
  $args = array(
523
  'output' => 'payments',
524
  'number' => $per_page,
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Payments
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
252
  * @access public
253
  * @since 1.4
254
  *
255
+ * @param array $payment Contains all the data of the payment
256
  * @param string $column_name The name of the column
257
  *
258
  * @return string Column Name
261
  switch ( $column_name ) {
262
  case 'amount' :
263
  $amount = ! empty( $payment->total ) ? $payment->total : 0;
264
+ $value = edd_currency_filter( edd_format_amount( $amount ), edd_get_payment_currency_code( $payment->ID ) );
265
  break;
266
  case 'date' :
267
  $date = strtotime( $payment->date );
500
  * @return array $payment_data Array of all the data for the payments
501
  */
502
  public function payments_data() {
 
 
 
503
 
504
  $per_page = $this->per_page;
505
  $orderby = isset( $_GET['orderby'] ) ? urldecode( $_GET['orderby'] ) : 'ID';
506
  $order = isset( $_GET['order'] ) ? $_GET['order'] : 'DESC';
 
 
507
  $user = isset( $_GET['user'] ) ? $_GET['user'] : null;
508
+ $status = isset( $_GET['status'] ) ? $_GET['status'] : edd_get_payment_status_keys();
509
  $meta_key = isset( $_GET['meta_key'] ) ? $_GET['meta_key'] : null;
510
  $year = isset( $_GET['year'] ) ? $_GET['year'] : null;
511
  $month = isset( $_GET['m'] ) ? $_GET['m'] : null;
514
  $start_date = isset( $_GET['start-date'] ) ? sanitize_text_field( $_GET['start-date'] ) : null;
515
  $end_date = isset( $_GET['end-date'] ) ? sanitize_text_field( $_GET['end-date'] ) : $start_date;
516
 
517
+ if( ! empty( $search ) ) {
518
+ $status = 'any'; // Force all payment statuses when searching
519
+ }
520
+
521
  $args = array(
522
  'output' => 'payments',
523
  'number' => $per_page,
includes/admin/payments/contextual-help.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Payments
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Payments
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
includes/admin/payments/payments-history.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Payments
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -22,8 +22,6 @@ if ( ! defined( 'ABSPATH' ) ) exit;
22
  * @return void
23
  */
24
  function edd_payment_history_page() {
25
- global $edd_options;
26
-
27
  $edd_payment = get_post_type_object( 'edd_payment' );
28
 
29
  if ( isset( $_GET['view'] ) && 'view-order-details' == $_GET['view'] ) {
@@ -61,7 +59,7 @@ function edd_payment_history_page() {
61
  function edd_payment_history_mobile_link() {
62
  ?>
63
  <p class="edd-mobile-link">
64
- <a href="https://easydigitaldownloads.com/extension/ios-sales-earnings-tracker/" target="_blank">
65
  <img src="<?php echo EDD_PLUGIN_URL . 'assets/images/icons/iphone.png'; ?>"/>
66
  <?php _e( 'Get the EDD Sales / Earnings tracker for iOS', 'edd' ); ?>
67
  </a>
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Payments
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
22
  * @return void
23
  */
24
  function edd_payment_history_page() {
 
 
25
  $edd_payment = get_post_type_object( 'edd_payment' );
26
 
27
  if ( isset( $_GET['view'] ) && 'view-order-details' == $_GET['view'] ) {
59
  function edd_payment_history_mobile_link() {
60
  ?>
61
  <p class="edd-mobile-link">
62
+ <a href="https://easydigitaldownloads.com/extensions/ios-sales-earnings-tracker/" target="_blank">
63
  <img src="<?php echo EDD_PLUGIN_URL . 'assets/images/icons/iphone.png'; ?>"/>
64
  <?php _e( 'Get the EDD Sales / Earnings tracker for iOS', 'edd' ); ?>
65
  </a>
includes/admin/payments/view-order-details.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Payments
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.6
10
  */
@@ -29,16 +29,20 @@ $item = get_post( $payment_id );
29
 
30
  // Sanity check... fail if purchase ID is invalid
31
  if ( !is_object( $item ) || $item->post_type != 'edd_payment' ) {
32
- wp_die( __( 'The specified ID does not belong to a payment. Please try again', 'edd' ), __( 'Error', 'edd' ) );
33
  }
34
 
35
- $payment_meta = edd_get_payment_meta( $payment_id );
36
- $cart_items = edd_get_payment_meta_cart_details( $payment_id );
37
- $user_id = edd_get_payment_user_id( $payment_id );
38
- $payment_date = strtotime( $item->post_date );
39
- $unlimited = edd_payment_has_unlimited_downloads( $payment_id );
40
- $user_info = edd_get_payment_meta_user_info( $payment_id );
41
- $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array( 'line1' => '', 'line2' => '', 'city' => '', 'country' => '', 'state' => '', 'zip' => '' );
 
 
 
 
42
  ?>
43
  <div class="wrap edd-wrap">
44
  <h2><?php printf( __( 'Payment %s', 'edd' ), $number ); ?></h2>
@@ -50,29 +54,55 @@ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array
50
  <div id="post-body" class="metabox-holder columns-2">
51
  <div id="postbox-container-1" class="postbox-container">
52
  <div id="side-sortables" class="meta-box-sortables ui-sortable">
 
53
  <?php do_action( 'edd_view_order_details_sidebar_before', $payment_id ); ?>
54
-
55
- <div id="edd-order-totals" class="postbox">
 
 
56
  <h3 class="hndle">
57
- <span><?php _e( 'Payment Totals', 'edd' ); ?></span>
58
  </h3>
59
  <div class="inside">
60
- <div class="edd-order-totals-box edd-admin-box">
 
61
  <?php do_action( 'edd_view_order_details_totals_before', $payment_id ); ?>
62
- <div class="edd-order-discount edd-admin-box-inside">
 
63
  <p>
64
- <span class="label"><?php _e( 'Discount Code', 'edd' ); ?>:</span>&nbsp;
65
- <span class="right"><?php if ( isset( $user_info['discount'] ) && $user_info['discount'] !== 'none' ) { echo '<code>' . $user_info['discount'] . '</code>'; } else { _e( 'None', 'edd' ); } ?></span>
 
 
 
 
66
  </p>
67
  </div>
68
- <?php if ( edd_use_taxes() ) : ?>
69
- <div class="edd-order-taxes edd-admin-box-inside">
70
  <p>
71
- <span class="label"><?php _e( 'Tax', 'edd' ); ?>:</span>&nbsp;
72
- <input name="edd-payment-tax" type="number" step="0.01" class="small-text right " value="<?php echo esc_attr( edd_get_payment_tax( $payment_id ) ); ?>"/>
73
  </p>
74
  </div>
75
- <?php endif; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  <?php
77
  $fees = edd_get_payment_fees( $payment_id );
78
  if ( ! empty( $fees ) ) : ?>
@@ -80,86 +110,102 @@ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array
80
  <p class="strong"><?php _e( 'Fees', 'edd' ); ?>:</p>
81
  <ul class="edd-payment-fees">
82
  <?php foreach( $fees as $fee ) : ?>
83
- <li><span class="fee-label"><?php echo $fee['label'] . ':</span> ' . '<span class="right fee-amount" data-fee="' . esc_attr( $fee['amount'] ) . '">' . edd_currency_filter( $fee['amount'] ); ?></span></li>
84
  <?php endforeach; ?>
85
  </ul>
86
  </div>
87
  <?php endif; ?>
 
 
 
 
 
 
 
 
 
 
88
  <div class="edd-order-payment edd-admin-box-inside">
89
  <p>
90
  <span class="label"><?php _e( 'Total Price', 'edd' ); ?>:</span>&nbsp;
91
- <input name="edd-payment-total" type="number" step="0.01" class="small-text right" value="<?php echo esc_attr( edd_get_payment_amount( $payment_id ) ); ?>"/>
92
  </p>
93
  </div>
 
94
  <div class="edd-order-payment-recalc-totals edd-admin-box-inside" style="display:none">
95
  <p>
96
  <span class="label"><?php _e( 'Recalculate Totals', 'edd' ); ?>:</span>&nbsp;
97
  <a href="" id="edd-order-recalc-total" class="button button-secondary right"><?php _e( 'Recalculate', 'edd' ); ?></a>
98
  </p>
99
  </div>
 
100
  <?php do_action( 'edd_view_order_details_totals_after', $payment_id ); ?>
101
- </div><!-- /.edd-order-totals-box -->
 
 
102
  </div><!-- /.inside -->
103
- </div><!-- /#edd-order-totals -->
104
-
105
- <div id="edd-order-update" class="postbox edd-order-data">
106
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  <h3 class="hndle">
108
- <span><?php _e( 'Update Payment', 'edd' ); ?></span>
109
  </h3>
110
  <div class="inside">
111
  <div class="edd-admin-box">
112
-
113
- <div class="edd-admin-box-inside">
114
-
115
- <?php
116
- $gateway = edd_get_payment_gateway( $payment_id );
117
- if ( $gateway ) { ?>
118
- <p>
119
- <strong><?php _e( 'Gateway:', 'edd' ); ?></strong>&nbsp;
120
- <span><?php echo edd_get_gateway_admin_label( $gateway ); ?></span>
121
- </p>
122
- <?php } ?>
123
-
 
 
 
124
  <p>
125
- <strong><?php _e( 'Key:', 'edd' ); ?></strong>&nbsp;
126
  <span><?php echo edd_get_payment_key( $payment_id ); ?></span>
127
  </p>
128
-
129
- <p>
130
- <strong><?php _e( 'IP:', 'edd' ); ?></strong>&nbsp;
131
- <span><?php esc_attr_e( edd_get_payment_user_ip( $payment_id )); ?></span>
132
- </p>
133
-
134
  </div>
135
-
136
- <div class="edd-admin-box-inside">
137
- <p>
138
- <span class="label"><?php _e( 'Status:', 'edd' ); ?></span>&nbsp;
139
- <select name="edd-payment-status" class="medium-text">
140
- <?php foreach( edd_get_payment_statuses() as $key => $status ) : ?>
141
- <option value="<?php esc_attr_e( $key ); ?>"<?php selected( edd_get_payment_status( $item, true ), $status ); ?>><?php esc_html_e( $status ); ?></option>
142
- <?php endforeach; ?>
143
- </select>
144
- </p>
145
- </div>
146
-
147
- <div class="edd-admin-box-inside">
148
  <p>
149
- <span class="label"><?php _e( 'Date:', 'edd' ); ?></span>&nbsp;
150
- <input type="text" name="edd-payment-date" value="<?php esc_attr_e( date( 'm/d/Y', $payment_date ) ); ?>" class="medium-text edd_datepicker"/>
151
  </p>
152
  </div>
153
-
154
- <div class="edd-admin-box-inside">
 
155
  <p>
156
- <span class="label"><?php _e( 'Time:', 'edd' ); ?></span>&nbsp;
157
- <input type="number" step="1" max="24" name="edd-payment-time-hour" value="<?php esc_attr_e( date_i18n( 'H', $payment_date ) ); ?>" class="small-text edd-payment-time-hour"/>&nbsp;:&nbsp;
158
- <input type="number" step="1" max="59" name="edd-payment-time-min" value="<?php esc_attr_e( date( 'i', $payment_date ) ); ?>" class="small-text edd-payment-time-min"/>
159
  </p>
160
  </div>
161
-
162
- <div class="edd-admin-box-inside">
 
163
  <p>
164
  <span class="label" title="<?php _e( 'Grants the customer unlimited file downloads for this purchase, regardless of other limits set.', 'edd' ); ?>"><i data-code="f316" class="dashicons dashicons-download"></i></span>&nbsp;
165
  <input type="checkbox" name="edd-unlimited-downloads" id="edd_unlimited_downloads" value="1"<?php checked( true, $unlimited, true ); ?>/>
@@ -167,174 +213,63 @@ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array
167
  </p>
168
  </div>
169
 
170
- <?php do_action( 'edd_view_order_details_update_inner', $payment_id ); ?>
171
-
172
  </div><!-- /.column-container -->
173
-
174
  </div><!-- /.inside -->
175
-
176
- <div class="edd-order-update-box edd-admin-box">
177
- <?php do_action( 'edd_view_order_details_update_before', $payment_id ); ?>
178
- <div id="major-publishing-actions">
179
- <div id="publishing-action">
180
- <input type="submit" class="button button-primary right" value="<?php esc_attr_e( 'Save Payment', 'edd' ); ?>"/>
181
- <?php if( edd_is_payment_complete( $payment_id ) ) : ?>
182
- <a href="<?php echo add_query_arg( array( 'edd-action' => 'email_links', 'purchase_id' => $payment_id ) ); ?>" id="edd-resend-receipt" class="button-secondary right"><?php _e( 'Resend Receipt', 'edd' ); ?></a>
183
- <?php endif; ?>
184
- </div>
185
- <div class="clear"></div>
186
- </div>
187
- <?php do_action( 'edd_view_order_details_update_after', $payment_id ); ?>
188
- </div><!-- /.edd-order-update-box -->
189
-
190
  </div><!-- /#edd-order-data -->
191
 
192
  <div id="edd-order-logs" class="postbox edd-order-logs">
193
-
194
  <h3 class="hndle">
195
  <span><?php _e( 'Logs', 'edd' ); ?></span>
196
  </h3>
197
  <div class="inside">
198
  <div class="edd-admin-box">
199
-
200
  <div class="edd-admin-box-inside">
201
 
202
- <p><a href="<?php echo admin_url( '/edit.php?post_type=download&page=edd-reports&tab=logs&payment=' . $payment_id ); ?>"><?php _e( 'View file download log for purchase', 'edd' ); ?></a></p>
203
-
 
 
 
 
 
 
 
 
 
204
  </div>
205
 
206
  <?php do_action( 'edd_view_order_details_logs_inner', $payment_id ); ?>
207
-
208
  </div><!-- /.column-container -->
209
-
210
  </div><!-- /.inside -->
211
 
212
-
213
  </div><!-- /#edd-order-logs -->
214
-
215
  <?php do_action( 'edd_view_order_details_sidebar_after', $payment_id ); ?>
216
  </div><!-- /#side-sortables -->
217
  </div><!-- /#postbox-container-1 -->
218
-
219
  <div id="postbox-container-2" class="postbox-container">
220
  <div id="normal-sortables" class="meta-box-sortables ui-sortable">
221
-
222
  <?php do_action( 'edd_view_order_details_main_before', $payment_id ); ?>
223
-
224
- <div id="edd-customer-details" class="postbox">
225
- <h3 class="hndle">
226
- <span><?php _e( 'Customer Details', 'edd' ); ?></span>
227
- </h3>
228
- <div class="inside edd-clearfix">
229
-
230
- <div class="column-container">
231
- <div class="column">
232
- <strong><?php _e( 'Name:', 'edd' ); ?></strong>&nbsp;
233
- <input type="text" name="edd-payment-user-name" value="<?php esc_attr_e( $user_info['first_name'] . ' ' . $user_info['last_name'] ); ?>" class="medium-text"/>
234
- </div>
235
- <div class="column">
236
- <strong><?php _e( 'Email:', 'edd' ); ?></strong>&nbsp;
237
- <input type="email" name="edd-payment-user-email" value="<?php esc_attr_e( edd_get_payment_user_email( $payment_id ) ); ?>" class="medium-text"/>
238
- </div>
239
- <div class="column">
240
- <strong><?php _e( 'User ID:', 'edd' ); ?></strong>&nbsp;
241
- <input type="number" step="1" min="-1" name="edd-payment-user-id" value="<?php esc_attr_e( $user_id ); ?>" class="small-text"/>
242
- </div>
243
- </div>
244
-
245
- <?php
246
- // The edd_payment_personal_details_list hook is left here for backwards compatibility
247
- do_action( 'edd_payment_personal_details_list', $payment_meta, $user_info );
248
- do_action( 'edd_payment_view_details', $payment_id );
249
- ?>
250
-
251
- </div><!-- /.inside -->
252
- </div><!-- /#edd-customer-details -->
253
-
254
- <?php do_action( 'edd_view_order_details_billing_before', $payment_id ); ?>
255
-
256
- <div id="edd-billing-details" class="postbox">
257
- <h3 class="hndle">
258
- <span><?php _e( 'Billing Address', 'edd' ); ?></span>
259
- </h3>
260
- <div class="inside edd-clearfix">
261
-
262
- <div id="edd-order-address">
263
-
264
- <div class="order-data-address">
265
- <div class="data column-container">
266
- <div class="column">
267
- <p>
268
- <strong class="order-data-address-line"><?php _e( 'Street Address Line 1:', 'edd' ); ?></strong><br/>
269
- <input type="text" name="edd-payment-address[0][line1]" value="<?php esc_attr_e( $address['line1'] ); ?>" class="medium-text" />
270
- </p>
271
- <p>
272
- <strong class="order-data-address-line"><?php _e( 'Street Address Line 2:', 'edd' ); ?></strong><br/>
273
- <input type="text" name="edd-payment-address[0][line2]" value="<?php esc_attr_e( $address['line2'] ); ?>" class="medium-text" />
274
- </p>
275
-
276
- </div>
277
- <div class="column">
278
- <p>
279
- <strong class="order-data-address-line"><?php echo _x( 'City:', 'Address City', 'edd' ); ?></strong><br/>
280
- <input type="text" name="edd-payment-address[0][city]" value="<?php esc_attr_e( $address['city'] ); ?>" class="medium-text"/>
281
-
282
- </p>
283
- <p>
284
- <strong class="order-data-address-line"><?php echo _x( 'Zip / Postal Code:', 'Zip / Postal code of address', 'edd' ); ?></strong><br/>
285
- <input type="text" name="edd-payment-address[0][zip]" value="<?php esc_attr_e( $address['zip'] ); ?>" class="medium-text"/>
286
-
287
- </p>
288
- </div>
289
- <div class="column">
290
- <p id="edd-order-address-country-wrap">
291
- <strong class="order-data-address-line"><?php echo _x( 'Country:', 'Address country', 'edd' ); ?></strong><br/>
292
- <?php
293
- echo EDD()->html->select( array(
294
- 'options' => edd_get_country_list(),
295
- 'name' => 'edd-payment-address[0][country]',
296
- 'selected' => $address['country'],
297
- 'show_option_all' => false,
298
- 'show_option_none' => false
299
- ) );
300
- ?>
301
- </p>
302
- <p id="edd-order-address-state-wrap">
303
- <strong class="order-data-address-line"><?php echo _x( 'State / Province:', 'State / province of address', 'edd' ); ?></strong><br/>
304
- <?php
305
- $states = edd_get_shop_states( $address['country'] );
306
- if( ! empty( $states ) ) {
307
- echo EDD()->html->select( array(
308
- 'options' => $states,
309
- 'name' => 'edd-payment-address[0][state]',
310
- 'selected' => $address['state'],
311
- 'show_option_all' => false,
312
- 'show_option_none' => false
313
- ) );
314
- } else { ?>
315
- <input type="text" name="edd-payment-address[0][state]" value="<?php esc_attr_e( $address['state'] ); ?>" class="medium-text"/>
316
- <?php
317
- } ?>
318
- </p>
319
- </div>
320
- </div>
321
- </div>
322
- </div><!-- /#edd-order-address -->
323
-
324
- <?php do_action( 'edd_payment_billing_details', $payment_id ); ?>
325
-
326
- </div><!-- /.inside -->
327
- </div><!-- /#edd-billing-details -->
328
-
329
- <?php do_action( 'edd_view_order_details_billing_after', $payment_id ); ?>
330
-
331
  <?php $column_count = edd_item_quantities_enabled() ? 'columns-4' : 'columns-3'; ?>
332
  <div id="edd-purchased-files" class="postbox <?php echo $column_count; ?>">
333
  <h3 class="hndle">
334
  <span><?php printf( __( 'Purchased %s', 'edd' ), edd_get_label_plural() ); ?></span>
335
  </h3>
336
-
337
- <?php if ( $cart_items ) :
 
338
  $i = 0;
339
  foreach ( $cart_items as $key => $cart_item ) : ?>
340
  <div class="row">
@@ -343,15 +278,17 @@ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array
343
  // Item ID is checked if isset due to the near-1.0 cart data
344
  $item_id = isset( $cart_item['id'] ) ? $cart_item['id'] : $cart_item;
345
  $price = isset( $cart_item['price'] ) ? $cart_item['price'] : false;
 
346
  $price_id = isset( $cart_item['item_number']['options']['price_id'] ) ? $cart_item['item_number']['options']['price_id'] : null;
347
  $quantity = isset( $cart_item['quantity'] ) && $cart_item['quantity'] > 0 ? $cart_item['quantity'] : 1;
348
-
349
- if( ! $price ) {
 
350
  // This function is only used on payments with near 1.0 cart data structure
351
  $price = edd_get_download_final_price( $item_id, $user_info, null );
352
  }
353
  ?>
354
-
355
  <li class="download">
356
  <span>
357
  <a href="<?php echo admin_url( 'post.php?post=' . $item_id . '&action=edit' ); ?>">
@@ -371,22 +308,27 @@ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array
371
  <input type="hidden" name="edd-payment-details-downloads[<?php echo $key; ?>][price_id]" class="edd-payment-details-download-price-id" value="<?php echo esc_attr( $price_id ); ?>"/>
372
  <input type="hidden" name="edd-payment-details-downloads[<?php echo $key; ?>][amount]" class="edd-payment-details-download-amount" value="<?php echo esc_attr( $price ); ?>"/>
373
  <input type="hidden" name="edd-payment-details-downloads[<?php echo $key; ?>][quantity]" class="edd-payment-details-download-quantity" value="<?php echo esc_attr( $quantity ); ?>"/>
374
-
375
  </li>
376
-
377
  <?php if( edd_item_quantities_enabled() ) : ?>
378
  <li class="quantity">
379
- <?php echo __( 'Quantity:', 'edd' ) . '&nbsp;<span>' . $quantity . '</span>'; ?>
 
380
  </li>
381
  <?php endif; ?>
382
-
383
  <li class="price">
384
- <?php echo edd_currency_filter( edd_format_amount( $price ) ); ?>
 
 
 
385
  </li>
386
-
387
  <li class="actions">
388
- <?php if( edd_get_download_files( $item_id, $price_id ) ) : ?>
389
- <a href="" class="edd-copy-download-link" data-download-id="<?php echo esc_attr( $item_id ); ?>" data-price-id="<?php echo esc_attr( $price_id ); ?>"><?php _e( 'Copy Download Link(s)', 'edd' ); ?></a> |
 
390
  <?php endif; ?>
391
  <a href="" class="edd-order-remove-download edd-delete" data-key="<?php echo esc_attr( $key ); ?>"><?php _e( 'Remove', 'edd' ); ?></a>
392
  </li>
@@ -398,41 +340,38 @@ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array
398
  <div class="inside">
399
  <ul>
400
  <li class="download">
401
- <input type="hidden" name="edd-payment-details-downloads[<?php echo $key; ?>][id]" class="edd-payment-details-download-id" value="<?php echo esc_attr( $item_id ); ?>"/>
402
- <input type="hidden" name="edd-payment-details-downloads[<?php echo $key; ?>][price_id]" class="edd-payment-details-download-price-id" value="<?php echo esc_attr( $price_id ); ?>"/>
403
- <input type="hidden" name="edd-payment-details-downloads[<?php echo $key; ?>][amount]" class="edd-payment-details-download-amount" value="<?php echo esc_attr( $price ); ?>"/>
404
- <input type="hidden" name="edd-payment-details-downloads[<?php echo $key; ?>][quantity]" class="edd-payment-details-download-quantity" value="<?php echo esc_attr( $quantity ); ?>"/>
405
  <?php echo EDD()->html->product_dropdown( array(
406
  'name' => 'edd-order-download-select',
407
  'id' => 'edd-order-download-select',
408
  'chosen' => true
409
  ) ); ?>
410
  </li>
411
-
412
  <?php if( edd_item_quantities_enabled() ) : ?>
413
  <li class="quantity">
414
  <span><?php _e( 'Quantity', 'edd' ); ?>:&nbsp;</span>
415
  <input type="number" id="edd-order-download-quantity" class="small-text" min="1" step="1" value="1" />
416
  </li>
417
  <?php endif; ?>
418
-
419
  <li class="price">
420
  <?php
421
  echo EDD()->html->text( array( 'name' => 'edd-order-download-amount',
422
- 'label' => __( 'Amount: ', 'edd' ),
423
- 'class' => 'small-text edd-order-download-price'
424
  ) );
425
  ?>
426
  </li>
427
-
428
  <li class="actions">
429
  <a href="" id="edd-order-add-download" class="button button-secondary"><?php printf( __( 'Add %s to Payment', 'edd' ), edd_get_label_singular() ); ?></a>
430
  </li>
431
-
432
  </ul>
433
-
434
- <input type="hidden" name="edd-payment-downloads-changed" id="edd-payment-downloads-changed" value=""/>
435
-
 
436
  </div><!-- /.inside -->
437
  <?php else : $key = 0; ?>
438
  <div class="row">
@@ -440,9 +379,142 @@ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array
440
  </div>
441
  <?php endif; ?>
442
  </div><!-- /#edd-purchased-files -->
443
-
444
  <?php do_action( 'edd_view_order_details_files_after', $payment_id ); ?>
445
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
446
  <div id="edd-payment-notes" class="postbox">
447
  <h3 class="hndle"><span><?php _e( 'Payment Notes', 'edd' ); ?></span></h3>
448
  <div class="inside">
@@ -452,9 +524,9 @@ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array
452
  if ( ! empty( $notes ) ) :
453
  $no_notes_display = ' style="display:none;"';
454
  foreach ( $notes as $note ) :
455
-
456
  echo edd_get_payment_note_html( $note, $payment_id );
457
-
458
  endforeach;
459
  else :
460
  $no_notes_display = '';
@@ -463,15 +535,15 @@ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array
463
  ?>
464
  </div>
465
  <textarea name="edd-payment-note" id="edd-payment-note" class="large-text"></textarea>
466
-
467
  <p>
468
  <button id="edd-add-payment-note" class="button button-secondary right" data-payment-id="<?php echo absint( $payment_id ); ?>"><?php _e( 'Add Note', 'edd' ); ?></button>
469
  </p>
470
-
471
  <div class="clear"></div>
472
  </div><!-- /.inside -->
473
  </div><!-- /#edd-payment-notes -->
474
-
475
  <?php do_action( 'edd_view_order_details_main_after', $payment_id ); ?>
476
  </div><!-- /#normal-sortables -->
477
  </div><!-- #postbox-container-2 -->
@@ -485,3 +557,5 @@ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array
485
  </form>
486
  <?php do_action( 'edd_view_order_details_after', $payment_id ); ?>
487
  </div><!-- /.wrap -->
 
 
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Payments
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.6
10
  */
29
 
30
  // Sanity check... fail if purchase ID is invalid
31
  if ( !is_object( $item ) || $item->post_type != 'edd_payment' ) {
32
+ wp_die( __( 'The specified ID does not belong to a payment. Please try again', 'edd' ), __( 'Error', 'edd' ) );
33
  }
34
 
35
+ $payment_meta = edd_get_payment_meta( $payment_id );
36
+ $transaction_id = esc_attr( edd_get_payment_transaction_id( $payment_id ) );
37
+ $cart_items = edd_get_payment_meta_cart_details( $payment_id );
38
+ $user_id = edd_get_payment_user_id( $payment_id );
39
+ $customer_id = edd_get_payment_customer_id( $payment_id );
40
+ $payment_date = strtotime( $item->post_date );
41
+ $unlimited = edd_payment_has_unlimited_downloads( $payment_id );
42
+ $user_info = edd_get_payment_meta_user_info( $payment_id );
43
+ $address = ! empty( $user_info['address'] ) ? $user_info['address'] : array( 'line1' => '', 'line2' => '', 'city' => '', 'country' => '', 'state' => '', 'zip' => '' );
44
+ $gateway = edd_get_payment_gateway( $payment_id );
45
+ $currency_code = edd_get_payment_currency_code( $payment_id );
46
  ?>
47
  <div class="wrap edd-wrap">
48
  <h2><?php printf( __( 'Payment %s', 'edd' ), $number ); ?></h2>
54
  <div id="post-body" class="metabox-holder columns-2">
55
  <div id="postbox-container-1" class="postbox-container">
56
  <div id="side-sortables" class="meta-box-sortables ui-sortable">
57
+
58
  <?php do_action( 'edd_view_order_details_sidebar_before', $payment_id ); ?>
59
+
60
+
61
+ <div id="edd-order-update" class="postbox edd-order-data">
62
+
63
  <h3 class="hndle">
64
+ <span><?php _e( 'Update Payment', 'edd' ); ?></span>
65
  </h3>
66
  <div class="inside">
67
+ <div class="edd-admin-box">
68
+
69
  <?php do_action( 'edd_view_order_details_totals_before', $payment_id ); ?>
70
+
71
+ <div class="edd-admin-box-inside">
72
  <p>
73
+ <span class="label"><?php _e( 'Status:', 'edd' ); ?></span>&nbsp;
74
+ <select name="edd-payment-status" class="medium-text">
75
+ <?php foreach( edd_get_payment_statuses() as $key => $status ) : ?>
76
+ <option value="<?php echo esc_attr( $key ); ?>"<?php selected( edd_get_payment_status( $item, true ), $status ); ?>><?php echo esc_html( $status ); ?></option>
77
+ <?php endforeach; ?>
78
+ </select>
79
  </p>
80
  </div>
81
+
82
+ <div class="edd-admin-box-inside">
83
  <p>
84
+ <span class="label"><?php _e( 'Date:', 'edd' ); ?></span>&nbsp;
85
+ <input type="text" name="edd-payment-date" value="<?php echo esc_attr( date( 'm/d/Y', $payment_date ) ); ?>" class="medium-text edd_datepicker"/>
86
  </p>
87
  </div>
88
+
89
+ <div class="edd-admin-box-inside">
90
+ <p>
91
+ <span class="label"><?php _e( 'Time:', 'edd' ); ?></span>&nbsp;
92
+ <input type="text" maxlength="2" name="edd-payment-time-hour" value="<?php echo esc_attr( date_i18n( 'H', $payment_date ) ); ?>" class="small-text edd-payment-time-hour"/>&nbsp;:&nbsp;
93
+ <input type="text" maxlength="2" name="edd-payment-time-min" value="<?php echo esc_attr( date( 'i', $payment_date ) ); ?>" class="small-text edd-payment-time-min"/>
94
+ </p>
95
+ </div>
96
+
97
+ <?php do_action( 'edd_view_order_details_update_inner', $payment_id ); ?>
98
+
99
+ <div class="edd-order-discount edd-admin-box-inside">
100
+ <p>
101
+ <span class="label"><?php _e( 'Discount Code', 'edd' ); ?>:</span>&nbsp;
102
+ <span><?php if ( isset( $user_info['discount'] ) && $user_info['discount'] !== 'none' ) { echo '<code>' . $user_info['discount'] . '</code>'; } else { _e( 'None', 'edd' ); } ?></span>
103
+ </p>
104
+ </div>
105
+
106
  <?php
107
  $fees = edd_get_payment_fees( $payment_id );
108
  if ( ! empty( $fees ) ) : ?>
110
  <p class="strong"><?php _e( 'Fees', 'edd' ); ?>:</p>
111
  <ul class="edd-payment-fees">
112
  <?php foreach( $fees as $fee ) : ?>
113
+ <li><span class="fee-label"><?php echo $fee['label'] . ':</span> ' . '<span class="fee-amount" data-fee="' . esc_attr( $fee['amount'] ) . '">' . edd_currency_filter( $fee['amount'], $currency_code ); ?></span></li>
114
  <?php endforeach; ?>
115
  </ul>
116
  </div>
117
  <?php endif; ?>
118
+
119
+ <?php if ( edd_use_taxes() ) : ?>
120
+ <div class="edd-order-taxes edd-admin-box-inside">
121
+ <p>
122
+ <span class="label"><?php _e( 'Tax', 'edd' ); ?>:</span>&nbsp;
123
+ <input name="edd-payment-tax" class="med-text" type="text" value="<?php echo esc_attr( edd_format_amount( edd_get_payment_tax( $payment_id ) ) ); ?>"/>
124
+ </p>
125
+ </div>
126
+ <?php endif; ?>
127
+
128
  <div class="edd-order-payment edd-admin-box-inside">
129
  <p>
130
  <span class="label"><?php _e( 'Total Price', 'edd' ); ?>:</span>&nbsp;
131
+ <?php echo edd_currency_symbol( $payment_meta['currency'] ); ?>&nbsp;<input name="edd-payment-total" type="text" class="med-text" value="<?php echo esc_attr( edd_format_amount( edd_get_payment_amount( $payment_id ) ) ); ?>"/>
132
  </p>
133
  </div>
134
+
135
  <div class="edd-order-payment-recalc-totals edd-admin-box-inside" style="display:none">
136
  <p>
137
  <span class="label"><?php _e( 'Recalculate Totals', 'edd' ); ?>:</span>&nbsp;
138
  <a href="" id="edd-order-recalc-total" class="button button-secondary right"><?php _e( 'Recalculate', 'edd' ); ?></a>
139
  </p>
140
  </div>
141
+
142
  <?php do_action( 'edd_view_order_details_totals_after', $payment_id ); ?>
143
+
144
+ </div><!-- /.edd-admin-box -->
145
+
146
  </div><!-- /.inside -->
147
+
148
+ <div class="edd-order-update-box edd-admin-box">
149
+ <?php do_action( 'edd_view_order_details_update_before', $payment_id ); ?>
150
+ <div id="major-publishing-actions">
151
+ <div id="publishing-action">
152
+ <input type="submit" class="button button-primary right" value="<?php esc_attr_e( 'Save Payment', 'edd' ); ?>"/>
153
+ <?php if( edd_is_payment_complete( $payment_id ) ) : ?>
154
+ <a href="<?php echo add_query_arg( array( 'edd-action' => 'email_links', 'purchase_id' => $payment_id ) ); ?>" id="edd-resend-receipt" class="button-secondary right"><?php _e( 'Resend Receipt', 'edd' ); ?></a>
155
+ <?php endif; ?>
156
+ </div>
157
+ <div class="clear"></div>
158
+ </div>
159
+ <?php do_action( 'edd_view_order_details_update_after', $payment_id ); ?>
160
+ </div><!-- /.edd-order-update-box -->
161
+
162
+ </div><!-- /#edd-order-data -->
163
+
164
+ <div id="edd-order-details" class="postbox edd-order-data">
165
+
166
  <h3 class="hndle">
167
+ <span><?php _e( 'Payment Meta', 'edd' ); ?></span>
168
  </h3>
169
  <div class="inside">
170
  <div class="edd-admin-box">
171
+
172
+ <?php do_action( 'edd_view_order_details_payment_meta_before', $payment_id ); ?>
173
+
174
+ <?php
175
+ $gateway = edd_get_payment_gateway( $payment_id );
176
+ if ( $gateway ) : ?>
177
+ <div class="edd-order-gateway edd-admin-box-inside">
178
+ <p>
179
+ <span class="label"><?php _e( 'Gateway:', 'edd' ); ?></span>&nbsp;
180
+ <?php echo edd_get_gateway_admin_label( $gateway ); ?>
181
+ </p>
182
+ </div>
183
+ <?php endif; ?>
184
+
185
+ <div class="edd-order-payment-key edd-admin-box-inside">
186
  <p>
187
+ <span class="label"><?php _e( 'Key:', 'edd' ); ?></span>&nbsp;
188
  <span><?php echo edd_get_payment_key( $payment_id ); ?></span>
189
  </p>
 
 
 
 
 
 
190
  </div>
191
+
192
+ <div class="edd-order-ip edd-admin-box-inside">
 
 
 
 
 
 
 
 
 
 
 
193
  <p>
194
+ <span class="label"><?php _e( 'IP:', 'edd' ); ?></span>&nbsp;
195
+ <span><?php echo esc_attr( edd_get_payment_user_ip( $payment_id )); ?></span>
196
  </p>
197
  </div>
198
+
199
+ <?php if ( $transaction_id ) : ?>
200
+ <div class="edd-order-tx-id edd-admin-box-inside">
201
  <p>
202
+ <span class="label"><?php _e( 'Transaction ID:', 'edd' ); ?></span>&nbsp;
203
+ <span><?php echo apply_filters( 'edd_payment_details_transaction_id-' . $gateway, $transaction_id, $payment_id ); ?></span>
 
204
  </p>
205
  </div>
206
+ <?php endif; ?>
207
+
208
+ <div class="edd-admin-box-inside edd-unlimited-downloads">
209
  <p>
210
  <span class="label" title="<?php _e( 'Grants the customer unlimited file downloads for this purchase, regardless of other limits set.', 'edd' ); ?>"><i data-code="f316" class="dashicons dashicons-download"></i></span>&nbsp;
211
  <input type="checkbox" name="edd-unlimited-downloads" id="edd_unlimited_downloads" value="1"<?php checked( true, $unlimited, true ); ?>/>
213
  </p>
214
  </div>
215
 
216
+ <?php do_action( 'edd_view_order_details_payment_meta_after', $payment_id ); ?>
217
+
218
  </div><!-- /.column-container -->
219
+
220
  </div><!-- /.inside -->
221
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  </div><!-- /#edd-order-data -->
223
 
224
  <div id="edd-order-logs" class="postbox edd-order-logs">
225
+
226
  <h3 class="hndle">
227
  <span><?php _e( 'Logs', 'edd' ); ?></span>
228
  </h3>
229
  <div class="inside">
230
  <div class="edd-admin-box">
231
+
232
  <div class="edd-admin-box-inside">
233
 
234
+ <p>
235
+ <a href="<?php echo admin_url( '/edit.php?post_type=download&page=edd-reports&tab=logs&payment=' . $payment_id ); ?>"><?php _e( 'View file download log for purchase', 'edd' ); ?></a>
236
+ </p>
237
+ <p>
238
+ <?php $download_log_url = admin_url( 'edit.php?post_type=download&page=edd-reports&tab=logs&user=' . $user_id ); ?>
239
+ <a href="<?php echo $download_log_url; ?>"><?php _e( 'View customer download log', 'edd' ); ?></a>
240
+ </p>
241
+ <p>
242
+ <?php $purchase_url = admin_url( 'edit.php?post_type=download&page=edd-payment-history&user=' . esc_attr( edd_get_payment_user_email( $payment_id ) ) ); ?>
243
+ <a href="<?php echo $purchase_url; ?>"><?php _e( 'View all purchases of customer', 'edd' ); ?></a>
244
+ </p>
245
  </div>
246
 
247
  <?php do_action( 'edd_view_order_details_logs_inner', $payment_id ); ?>
248
+
249
  </div><!-- /.column-container -->
250
+
251
  </div><!-- /.inside -->
252
 
253
+
254
  </div><!-- /#edd-order-logs -->
255
+
256
  <?php do_action( 'edd_view_order_details_sidebar_after', $payment_id ); ?>
257
  </div><!-- /#side-sortables -->
258
  </div><!-- /#postbox-container-1 -->
259
+
260
  <div id="postbox-container-2" class="postbox-container">
261
  <div id="normal-sortables" class="meta-box-sortables ui-sortable">
262
+
263
  <?php do_action( 'edd_view_order_details_main_before', $payment_id ); ?>
264
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  <?php $column_count = edd_item_quantities_enabled() ? 'columns-4' : 'columns-3'; ?>
266
  <div id="edd-purchased-files" class="postbox <?php echo $column_count; ?>">
267
  <h3 class="hndle">
268
  <span><?php printf( __( 'Purchased %s', 'edd' ), edd_get_label_plural() ); ?></span>
269
  </h3>
270
+
271
+ <?php if ( is_array( $cart_items ) ) :
272
+
273
  $i = 0;
274
  foreach ( $cart_items as $key => $cart_item ) : ?>
275
  <div class="row">
278
  // Item ID is checked if isset due to the near-1.0 cart data
279
  $item_id = isset( $cart_item['id'] ) ? $cart_item['id'] : $cart_item;
280
  $price = isset( $cart_item['price'] ) ? $cart_item['price'] : false;
281
+ $item_price = isset( $cart_item['item_price'] ) ? $cart_item['item_price'] : $price;
282
  $price_id = isset( $cart_item['item_number']['options']['price_id'] ) ? $cart_item['item_number']['options']['price_id'] : null;
283
  $quantity = isset( $cart_item['quantity'] ) && $cart_item['quantity'] > 0 ? $cart_item['quantity'] : 1;
284
+
285
+ if( false === $price ) {
286
+
287
  // This function is only used on payments with near 1.0 cart data structure
288
  $price = edd_get_download_final_price( $item_id, $user_info, null );
289
  }
290
  ?>
291
+
292
  <li class="download">
293
  <span>
294
  <a href="<?php echo admin_url( 'post.php?post=' . $item_id . '&action=edit' ); ?>">
308
  <input type="hidden" name="edd-payment-details-downloads[<?php echo $key; ?>][price_id]" class="edd-payment-details-download-price-id" value="<?php echo esc_attr( $price_id ); ?>"/>
309
  <input type="hidden" name="edd-payment-details-downloads[<?php echo $key; ?>][amount]" class="edd-payment-details-download-amount" value="<?php echo esc_attr( $price ); ?>"/>
310
  <input type="hidden" name="edd-payment-details-downloads[<?php echo $key; ?>][quantity]" class="edd-payment-details-download-quantity" value="<?php echo esc_attr( $quantity ); ?>"/>
311
+
312
  </li>
313
+
314
  <?php if( edd_item_quantities_enabled() ) : ?>
315
  <li class="quantity">
316
+ <span class="item-price"><?php echo edd_currency_filter( edd_format_amount( $item_price ) ); ?></span>
317
+ &nbsp;&times;&nbsp;<span class="item-quantity"><?php echo $quantity; ?></span>
318
  </li>
319
  <?php endif; ?>
320
+
321
  <li class="price">
322
+ <?php if ( edd_item_quantities_enabled() ) : ?>
323
+ <?php echo __( 'Total:', 'edd' ) . '&nbsp;'; ?>
324
+ <?php endif; ?>
325
+ <span class="price-text"><?php echo edd_currency_filter( edd_format_amount( $price ), $currency_code ); ?></span>
326
  </li>
327
+
328
  <li class="actions">
329
+ <input type="hidden" class="edd-payment-details-download-has-log" name="edd-payment-details-downloads[<?php echo $key; ?>][has_log]" value="1" />
330
+ <?php if( edd_get_download_files( $item_id, $price_id ) && edd_is_payment_complete( $payment_id ) ) : ?>
331
+ <a href="" class="edd-copy-download-link" data-download-id="<?php echo esc_attr( $item_id ); ?>" data-price-id="<?php echo esc_attr( $price_id ); ?>"><?php _e( 'Copy Download Link(s)', 'edd' ); ?></a> |
332
  <?php endif; ?>
333
  <a href="" class="edd-order-remove-download edd-delete" data-key="<?php echo esc_attr( $key ); ?>"><?php _e( 'Remove', 'edd' ); ?></a>
334
  </li>
340
  <div class="inside">
341
  <ul>
342
  <li class="download">
 
 
 
 
343
  <?php echo EDD()->html->product_dropdown( array(
344
  'name' => 'edd-order-download-select',
345
  'id' => 'edd-order-download-select',
346
  'chosen' => true
347
  ) ); ?>
348
  </li>
349
+
350
  <?php if( edd_item_quantities_enabled() ) : ?>
351
  <li class="quantity">
352
  <span><?php _e( 'Quantity', 'edd' ); ?>:&nbsp;</span>
353
  <input type="number" id="edd-order-download-quantity" class="small-text" min="1" step="1" value="1" />
354
  </li>
355
  <?php endif; ?>
356
+
357
  <li class="price">
358
  <?php
359
  echo EDD()->html->text( array( 'name' => 'edd-order-download-amount',
360
+ 'label' => __( 'Item Price: ', 'edd' ),
361
+ 'class' => 'small-text edd-order-download-price'
362
  ) );
363
  ?>
364
  </li>
365
+
366
  <li class="actions">
367
  <a href="" id="edd-order-add-download" class="button button-secondary"><?php printf( __( 'Add %s to Payment', 'edd' ), edd_get_label_singular() ); ?></a>
368
  </li>
369
+
370
  </ul>
371
+
372
+ <input type="hidden" name="edd-payment-downloads-changed" id="edd-payment-downloads-changed" value="" />
373
+ <input type="hidden" name="edd-payment-removed" id="edd-payment-removed" value="{}" />
374
+
375
  </div><!-- /.inside -->
376
  <?php else : $key = 0; ?>
377
  <div class="row">
379
  </div>
380
  <?php endif; ?>
381
  </div><!-- /#edd-purchased-files -->
382
+
383
  <?php do_action( 'edd_view_order_details_files_after', $payment_id ); ?>
384
+
385
+ <?php do_action( 'edd_view_order_details_billing_before', $payment_id ); ?>
386
+
387
+ <div id="edd-customer-details" class="postbox">
388
+ <h3 class="hndle">
389
+ <span><?php _e( 'Customer Details', 'edd' ); ?></span>
390
+ </h3>
391
+ <div class="inside edd-clearfix">
392
+
393
+ <?php $customer = new EDD_Customer( edd_get_payment_customer_id( $payment_id ) ); ?>
394
+
395
+ <div class="column-container customer-info">
396
+ <div class="column">
397
+ <?php echo EDD()->html->customer_dropdown( array( 'selected' => $customer->id, 'name' => 'customer-id' ) ); ?>
398
+ </div>
399
+ <div class="column">
400
+ <input type="hidden" name="edd-current-customer" value="<?php echo $customer->id; ?>" />
401
+ </div>
402
+ <div class="column">
403
+ <?php if( ! empty( $customer->id ) ) : ?>
404
+ <?php $customer_url = admin_url( 'edit.php?post_type=download&page=edd-customers&view=overview&id=' . $customer->id ); ?>
405
+ <a href="<?php echo $customer_url; ?>" title="<?php _e( 'View Customer Details', 'edd' ); ?>"><?php _e( 'View Customer Details', 'edd' ); ?></a>
406
+ &nbsp;|&nbsp;
407
+ <?php endif; ?>
408
+ <a href="#new" class="edd-payment-new-customer" title="<?php _e( 'New Customer', 'edd' ); ?>"><?php _e( 'New Customer', 'edd' ); ?></a>
409
+ </div>
410
+ </div>
411
+
412
+ <div class="column-container new-customer" style="display: none">
413
+ <div class="column">
414
+ <strong><?php _e( 'Name:', 'edd' ); ?></strong>&nbsp;
415
+ <input type="text" name="edd-new-customer-name" value="" class="medium-text"/>
416
+ </div>
417
+ <div class="column">
418
+ <strong><?php _e( 'Email:', 'edd' ); ?></strong>&nbsp;
419
+ <input type="email" name="edd-new-customer-email" value="" class="medium-text"/>
420
+ </div>
421
+ <div class="column">
422
+ <input type="hidden" id="edd-new-customer" name="edd-new-customer" value="0" />
423
+ <a href="#cancel" class="edd-payment-new-customer-cancel edd-delete"><?php _e( 'Cancel', 'edd' ); ?></a>
424
+ </div>
425
+ <div class="column">
426
+ <small><em>*<?php _e( 'Click "Save Payment" to create new customer', 'edd' ); ?></em></small>
427
+ </div>
428
+ </div>
429
+
430
+ <?php
431
+ // The edd_payment_personal_details_list hook is left here for backwards compatibility
432
+ do_action( 'edd_payment_personal_details_list', $payment_meta, $user_info );
433
+ do_action( 'edd_payment_view_details', $payment_id );
434
+ ?>
435
+
436
+ </div><!-- /.inside -->
437
+ </div><!-- /#edd-customer-details -->
438
+
439
+ <div id="edd-billing-details" class="postbox">
440
+ <h3 class="hndle">
441
+ <span><?php _e( 'Billing Address', 'edd' ); ?></span>
442
+ </h3>
443
+ <div class="inside edd-clearfix">
444
+
445
+ <div id="edd-order-address">
446
+
447
+ <div class="order-data-address">
448
+ <div class="data column-container">
449
+ <div class="column">
450
+ <p>
451
+ <strong class="order-data-address-line"><?php _e( 'Street Address Line 1:', 'edd' ); ?></strong><br/>
452
+ <input type="text" name="edd-payment-address[0][line1]" value="<?php echo esc_attr( $address['line1'] ); ?>" class="medium-text" />
453
+ </p>
454
+ <p>
455
+ <strong class="order-data-address-line"><?php _e( 'Street Address Line 2:', 'edd' ); ?></strong><br/>
456
+ <input type="text" name="edd-payment-address[0][line2]" value="<?php echo esc_attr( $address['line2'] ); ?>" class="medium-text" />
457
+ </p>
458
+
459
+ </div>
460
+ <div class="column">
461
+ <p>
462
+ <strong class="order-data-address-line"><?php echo _x( 'City:', 'Address City', 'edd' ); ?></strong><br/>
463
+ <input type="text" name="edd-payment-address[0][city]" value="<?php echo esc_attr( $address['city'] ); ?>" class="medium-text"/>
464
+
465
+ </p>
466
+ <p>
467
+ <strong class="order-data-address-line"><?php echo _x( 'Zip / Postal Code:', 'Zip / Postal code of address', 'edd' ); ?></strong><br/>
468
+ <input type="text" name="edd-payment-address[0][zip]" value="<?php echo esc_attr( $address['zip'] ); ?>" class="medium-text"/>
469
+
470
+ </p>
471
+ </div>
472
+ <div class="column">
473
+ <p id="edd-order-address-country-wrap">
474
+ <strong class="order-data-address-line"><?php echo _x( 'Country:', 'Address country', 'edd' ); ?></strong><br/>
475
+ <?php
476
+ echo EDD()->html->select( array(
477
+ 'options' => edd_get_country_list(),
478
+ 'name' => 'edd-payment-address[0][country]',
479
+ 'selected' => $address['country'],
480
+ 'show_option_all' => false,
481
+ 'show_option_none' => false,
482
+ 'chosen' => true,
483
+ 'placeholder' => __( 'Select a country', 'edd' )
484
+ ) );
485
+ ?>
486
+ </p>
487
+ <p id="edd-order-address-state-wrap">
488
+ <strong class="order-data-address-line"><?php echo _x( 'State / Province:', 'State / province of address', 'edd' ); ?></strong><br/>
489
+ <?php
490
+ $states = edd_get_shop_states( $address['country'] );
491
+ if( ! empty( $states ) ) {
492
+ echo EDD()->html->select( array(
493
+ 'options' => $states,
494
+ 'name' => 'edd-payment-address[0][state]',
495
+ 'selected' => $address['state'],
496
+ 'show_option_all' => false,
497
+ 'show_option_none' => false,
498
+ 'chosen' => true,
499
+ 'placeholder' => __( 'Select a state', 'edd' )
500
+ ) );
501
+ } else { ?>
502
+ <input type="text" name="edd-payment-address[0][state]" value="<?php echo esc_attr( $address['state'] ); ?>" class="medium-text"/>
503
+ <?php
504
+ } ?>
505
+ </p>
506
+ </div>
507
+ </div>
508
+ </div>
509
+ </div><!-- /#edd-order-address -->
510
+
511
+ <?php do_action( 'edd_payment_billing_details', $payment_id ); ?>
512
+
513
+ </div><!-- /.inside -->
514
+ </div><!-- /#edd-billing-details -->
515
+
516
+ <?php do_action( 'edd_view_order_details_billing_after', $payment_id ); ?>
517
+
518
  <div id="edd-payment-notes" class="postbox">
519
  <h3 class="hndle"><span><?php _e( 'Payment Notes', 'edd' ); ?></span></h3>
520
  <div class="inside">
524
  if ( ! empty( $notes ) ) :
525
  $no_notes_display = ' style="display:none;"';
526
  foreach ( $notes as $note ) :
527
+
528
  echo edd_get_payment_note_html( $note, $payment_id );
529
+
530
  endforeach;
531
  else :
532
  $no_notes_display = '';
535
  ?>
536
  </div>
537
  <textarea name="edd-payment-note" id="edd-payment-note" class="large-text"></textarea>
538
+
539
  <p>
540
  <button id="edd-add-payment-note" class="button button-secondary right" data-payment-id="<?php echo absint( $payment_id ); ?>"><?php _e( 'Add Note', 'edd' ); ?></button>
541
  </p>
542
+
543
  <div class="clear"></div>
544
  </div><!-- /.inside -->
545
  </div><!-- /#edd-payment-notes -->
546
+
547
  <?php do_action( 'edd_view_order_details_main_after', $payment_id ); ?>
548
  </div><!-- /#normal-sortables -->
549
  </div><!-- #postbox-container-2 -->
557
  </form>
558
  <?php do_action( 'edd_view_order_details_after', $payment_id ); ?>
559
  </div><!-- /.wrap -->
560
+
561
+ <div id="edd-download-link" title="<?php _e( 'Copy Download Link(s)', 'edd' ); ?>"></div>
includes/admin/plugins.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Plugins
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8
10
  */
@@ -46,13 +46,21 @@ function edd_plugin_row_meta( $input, $file ) {
46
  if ( $file != 'easy-digital-downloads/easy-digital-downloads.php' )
47
  return $input;
48
 
 
 
 
 
 
 
 
 
49
  $links = array(
50
  '<a href="' . admin_url( 'index.php?page=edd-getting-started' ) . '">' . esc_html__( 'Getting Started', 'edd' ) . '</a>',
51
- '<a href="https://easydigitaldownloads.com/extensions/">' . esc_html__( 'Add Ons', 'edd' ) . '</a>',
52
  );
53
 
54
  $input = array_merge( $input, $links );
55
 
56
  return $input;
57
  }
58
- add_filter( 'plugin_row_meta', 'edd_plugin_row_meta', 10, 2 );
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Plugins
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8
10
  */
46
  if ( $file != 'easy-digital-downloads/easy-digital-downloads.php' )
47
  return $input;
48
 
49
+ $edd_link = esc_url( add_query_arg( array(
50
+ 'utm_source' => 'admin-plugins-page',
51
+ 'utm_medium' => 'plugin',
52
+ 'utm_campaign' => 'EDDPluginsPage',
53
+ 'utm_content' => 'plugin-page-link'
54
+ ), 'https://easydigitaldownloads.com/extensions/' )
55
+ );
56
+
57
  $links = array(
58
  '<a href="' . admin_url( 'index.php?page=edd-getting-started' ) . '">' . esc_html__( 'Getting Started', 'edd' ) . '</a>',
59
+ '<a href="' . $edd_link . '">' . esc_html__( 'Extensions', 'edd' ) . '</a>',
60
  );
61
 
62
  $input = array_merge( $input, $links );
63
 
64
  return $input;
65
  }
66
+ add_filter( 'plugin_row_meta', 'edd_plugin_row_meta', 10, 2 );
includes/admin/reporting/class-api-requests-logs-list-table.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.5
10
  */
@@ -101,16 +101,13 @@ class EDD_API_Request_Log_Table extends WP_List_Table {
101
  * @access public
102
  * @since 1.5
103
  *
104
- * @param array $item Contains all the data of the discount code
105
  * @param string $column_name The name of the column
106
  *
107
  * @return string Column Name
108
  */
109
  public function column_default( $item, $column_name ) {
110
- switch( $column_name ){
111
- default:
112
- return $item[ $column_name ];
113
- }
114
  }
115
 
116
  /**
@@ -151,7 +148,7 @@ class EDD_API_Request_Log_Table extends WP_List_Table {
151
  *
152
  * @access public
153
  * @since 1.5
154
- * @return mixed String if search is present, false otherwise
155
  */
156
  public function get_search() {
157
  return ! empty( $_GET['s'] ) ? urldecode( trim( $_GET['s'] ) ) : false;
@@ -231,7 +228,7 @@ class EDD_API_Request_Log_Table extends WP_List_Table {
231
  * @since 1.5
232
  * @return void
233
  */
234
- function bulk_actions() {
235
  // These aren't really bulk actions but this outputs the markup in the right place
236
  edd_log_views();
237
  }
@@ -250,7 +247,7 @@ class EDD_API_Request_Log_Table extends WP_List_Table {
250
  $logs_data = array();
251
  $paged = $this->get_paged();
252
  $log_query = array(
253
- 'log_type' => 'api_requests',
254
  'paged' => $paged,
255
  'meta_query' => $this->get_meta_query()
256
  );
@@ -291,7 +288,6 @@ class EDD_API_Request_Log_Table extends WP_List_Table {
291
  $hidden = array(); // No hidden columns
292
  $sortable = $this->get_sortable_columns();
293
  $this->_column_headers = array( $columns, $hidden, $sortable );
294
- $current_page = $this->get_pagenum();
295
  $this->items = $this->get_logs();
296
  $total_items = $edd_logs->get_log_count( 0, 'api_requests' );
297
 
@@ -302,4 +298,4 @@ class EDD_API_Request_Log_Table extends WP_List_Table {
302
  )
303
  );
304
  }
305
- }
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.5
10
  */
101
  * @access public
102
  * @since 1.5
103
  *
104
+ * @param array $item Contains all the data of the api request
105
  * @param string $column_name The name of the column
106
  *
107
  * @return string Column Name
108
  */
109
  public function column_default( $item, $column_name ) {
110
+ return $item[ $column_name ];
 
 
 
111
  }
112
 
113
  /**
148
  *
149
  * @access public
150
  * @since 1.5
151
+ * @return string|false String if search is present, false otherwise
152
  */
153
  public function get_search() {
154
  return ! empty( $_GET['s'] ) ? urldecode( trim( $_GET['s'] ) ) : false;
228
  * @since 1.5
229
  * @return void
230
  */
231
+ function bulk_actions( $which='' ) {
232
  // These aren't really bulk actions but this outputs the markup in the right place
233
  edd_log_views();
234
  }
247
  $logs_data = array();
248
  $paged = $this->get_paged();
249
  $log_query = array(
250
+ 'log_type' => 'api_request',
251
  'paged' => $paged,
252
  'meta_query' => $this->get_meta_query()
253
  );
288
  $hidden = array(); // No hidden columns
289
  $sortable = $this->get_sortable_columns();
290
  $this->_column_headers = array( $columns, $hidden, $sortable );
 
291
  $this->items = $this->get_logs();
292
  $total_items = $edd_logs->get_log_count( 0, 'api_requests' );
293
 
298
  )
299
  );
300
  }
301
+ }
includes/admin/reporting/class-customer-reports-table.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.5
10
  */
@@ -108,21 +108,26 @@ class EDD_Customer_Reports_Table extends WP_List_Table {
108
  */
109
  public function column_default( $item, $column_name ) {
110
  switch ( $column_name ) {
111
- case 'name' :
112
- return '<a href="' .
113
- admin_url( '/edit.php?post_type=download&page=edd-payment-history&user=' . urlencode( $item['email'] )
114
- ) . '">' . esc_html( $item[ $column_name ] ) . '</a>';
 
 
115
 
116
  case 'amount_spent' :
117
- return edd_currency_filter( edd_format_amount( $item[ $column_name ] ) );
 
118
 
119
  case 'file_downloads' :
120
- return '<a href="' . admin_url( '/edit.php?post_type=download&page=edd-reports&tab=logs&user=' . urlencode( ! empty( $item['ID'] ) ? $item['ID'] : $item['email'] ) ) . '" target="_blank">' . __( 'View download log', 'edd' ) . '</a>';
121
-
 
122
  default:
123
  $value = isset( $item[ $column_name ] ) ? $item[ $column_name ] : null;
124
- return apply_filters( 'edd_report_column_' . $column_name, $value, $item['ID'] );
125
  }
 
126
  }
127
 
128
  /**
@@ -135,6 +140,7 @@ class EDD_Customer_Reports_Table extends WP_List_Table {
135
  public function get_columns() {
136
  $columns = array(
137
  'name' => __( 'Name', 'edd' ),
 
138
  'email' => __( 'Email', 'edd' ),
139
  'num_purchases' => __( 'Purchases', 'edd' ),
140
  'amount_spent' => __( 'Total Spent', 'edd' ),
@@ -142,6 +148,23 @@ class EDD_Customer_Reports_Table extends WP_List_Table {
142
  );
143
 
144
  return apply_filters( 'edd_report_customer_columns', $columns );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  }
146
 
147
  /**
@@ -151,7 +174,7 @@ class EDD_Customer_Reports_Table extends WP_List_Table {
151
  * @since 1.5
152
  * @return void
153
  */
154
- public function bulk_actions() {
155
  // These aren't really bulk actions but this outputs the markup in the right place
156
  edd_report_views();
157
  }
@@ -190,41 +213,43 @@ class EDD_Customer_Reports_Table extends WP_List_Table {
190
  public function reports_data() {
191
  global $wpdb;
192
 
193
- $data = array();
194
- $paged = $this->get_paged();
195
- $offset = $this->per_page * ( $paged - 1 );
196
- $search = $this->get_search();
197
- $where = "WHERE meta_key = '_edd_payment_user_email'";
 
 
 
 
 
 
 
 
198
 
199
- if ( $search ) {
200
- $where .= " AND meta_value LIKE '%$search%'";
 
 
201
  }
202
 
203
- $customers = $wpdb->get_col( "SELECT DISTINCT meta_value FROM $wpdb->postmeta $where ORDER BY meta_id DESC LIMIT $this->per_page OFFSET $offset" );
204
 
205
  if ( $customers ) {
206
 
207
  $this->count = count( $customers );
208
 
209
- foreach ( $customers as $customer_email ) {
210
- $wp_user = get_user_by( 'email', $customer_email );
211
-
212
- $user_id = $wp_user ? $wp_user->ID : 0;
213
 
214
- if( $wp_user ) {
215
- $user = $user_id;
216
- } else {
217
- $user = $customer_email;
218
- }
219
-
220
- $stats = edd_get_purchase_stats_by_user( $user );
221
 
222
  $data[] = array(
223
- 'ID' => $user_id,
224
- 'name' => $wp_user ? $wp_user->display_name : __( 'Guest', 'edd' ),
225
- 'email' => $customer_email,
226
- 'num_purchases' => $stats['purchases'],
227
- 'amount_spent' => $stats['total_spent']
 
228
  );
229
  }
230
  }
@@ -244,24 +269,21 @@ class EDD_Customer_Reports_Table extends WP_List_Table {
244
  * @return void
245
  */
246
  public function prepare_items() {
247
- $columns = $this->get_columns();
248
-
249
- $hidden = array(); // No hidden columns
250
 
 
 
251
  $sortable = $this->get_sortable_columns();
252
 
253
  $this->_column_headers = array( $columns, $hidden, $sortable );
254
 
255
- $current_page = $this->get_pagenum();
256
-
257
  $this->items = $this->reports_data();
258
 
259
  $this->total = edd_count_total_customers();
260
 
261
  $this->set_pagination_args( array(
262
- 'total_items' => $this->count, // WE have to calculate the total number of items
263
- 'per_page' => $this->per_page, // WE have to determine how many items to show on a page
264
- 'total_pages' => ceil( $this->total / $this->per_page ) // WE have to calculate the total number of pages
265
  ) );
266
  }
267
  }
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.5
10
  */
108
  */
109
  public function column_default( $item, $column_name ) {
110
  switch ( $column_name ) {
111
+
112
+ case 'num_purchases' :
113
+ $value = '<a href="' .
114
+ admin_url( '/edit.php?post_type=download&page=edd-payment-history&user=' . urlencode( $item['email'] )
115
+ ) . '">' . esc_html( $item['num_purchases'] ) . '</a>';
116
+ break;
117
 
118
  case 'amount_spent' :
119
+ $value = edd_currency_filter( edd_format_amount( $item[ $column_name ] ) );
120
+ break;
121
 
122
  case 'file_downloads' :
123
+ $user = ! empty( $item['user_id'] ) ? $item['user_id'] : $item['email'];
124
+ $value = '<a href="' . esc_url( admin_url( '/edit.php?post_type=download&page=edd-reports&tab=logs&user=' . urlencode( $user ) ) ) . '">' . __( 'View download log', 'edd' ) . '</a>';
125
+ break;
126
  default:
127
  $value = isset( $item[ $column_name ] ) ? $item[ $column_name ] : null;
128
+ break;
129
  }
130
+ return apply_filters( 'edd_report_column_' . $column_name, $value, $item['id'] );
131
  }
132
 
133
  /**
140
  public function get_columns() {
141
  $columns = array(
142
  'name' => __( 'Name', 'edd' ),
143
+ 'id' => __( 'ID', 'edd' ),
144
  'email' => __( 'Email', 'edd' ),
145
  'num_purchases' => __( 'Purchases', 'edd' ),
146
  'amount_spent' => __( 'Total Spent', 'edd' ),
148
  );
149
 
150
  return apply_filters( 'edd_report_customer_columns', $columns );
151
+
152
+ }
153
+
154
+ /**
155
+ * Get the sortable columns
156
+ *
157
+ * @access public
158
+ * @since 2.1
159
+ * @return array Array of all the sortable columns
160
+ */
161
+ public function get_sortable_columns() {
162
+ return array(
163
+ 'id' => array( 'id', true ),
164
+ 'name' => array( 'name', true ),
165
+ 'num_purchases' => array( 'purchase_count', false ),
166
+ 'amount_spent' => array( 'purchase_value', false ),
167
+ );
168
  }
169
 
170
  /**
174
  * @since 1.5
175
  * @return void
176
  */
177
+ public function bulk_actions( $which = '' ) {
178
  // These aren't really bulk actions but this outputs the markup in the right place
179
  edd_report_views();
180
  }
213
  public function reports_data() {
214
  global $wpdb;
215
 
216
+ $data = array();
217
+ $paged = $this->get_paged();
218
+ $offset = $this->per_page * ( $paged - 1 );
219
+ $search = $this->get_search();
220
+ $order = isset( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'DESC';
221
+ $orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'id';
222
+
223
+ $args = array(
224
+ 'number' => $this->per_page,
225
+ 'offset' => $offset,
226
+ 'order' => $order,
227
+ 'orderby' => $orderby
228
+ );
229
 
230
+ if( is_email( $search ) ) {
231
+ $args['email'] = $search;
232
+ } elseif( is_numeric( $search ) ) {
233
+ $args['id'] = $search;
234
  }
235
 
236
+ $customers = EDD()->customers->get_customers( $args );
237
 
238
  if ( $customers ) {
239
 
240
  $this->count = count( $customers );
241
 
242
+ foreach ( $customers as $customer ) {
 
 
 
243
 
244
+ $user_id = ! empty( $customer->user_id ) ? absint( $customer->user_id ) : 0;
 
 
 
 
 
 
245
 
246
  $data[] = array(
247
+ 'id' => $customer->id,
248
+ 'user_id' => $user_id,
249
+ 'name' => $customer->name,
250
+ 'email' => $customer->email,
251
+ 'num_purchases' => $customer->purchase_count,
252
+ 'amount_spent' => $customer->purchase_value
253
  );
254
  }
255
  }
269
  * @return void
270
  */
271
  public function prepare_items() {
 
 
 
272
 
273
+ $columns = $this->get_columns();
274
+ $hidden = array(); // No hidden columns
275
  $sortable = $this->get_sortable_columns();
276
 
277
  $this->_column_headers = array( $columns, $hidden, $sortable );
278
 
 
 
279
  $this->items = $this->reports_data();
280
 
281
  $this->total = edd_count_total_customers();
282
 
283
  $this->set_pagination_args( array(
284
+ 'total_items' => $this->total,
285
+ 'per_page' => $this->per_page,
286
+ 'total_pages' => ceil( $this->total / $this->per_page )
287
  ) );
288
  }
289
  }
includes/admin/reporting/class-download-reports-table.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.5
10
  */
@@ -80,7 +80,7 @@ class EDD_Download_Reports_Table extends WP_List_Table {
80
  case 'average_earnings' :
81
  return edd_currency_filter( edd_format_amount( $item[ $column_name ] ) );
82
  case 'details' :
83
- return '<a href="' . admin_url( 'edit.php?post_type=download&page=edd-reports&view=downloads&download-id=' . $item[ 'ID' ] ) . '">' . __( 'View Detailed Report', 'edd' ) . '</a>';
84
  default:
85
  return $item[ $column_name ];
86
  }
@@ -168,7 +168,7 @@ class EDD_Download_Reports_Table extends WP_List_Table {
168
  * @since 1.5
169
  * @return void
170
  */
171
- public function bulk_actions() {
172
  // These aren't really bulk actions but this outputs the markup in the right place
173
  edd_report_views();
174
  }
@@ -182,7 +182,6 @@ class EDD_Download_Reports_Table extends WP_List_Table {
182
  * @return void
183
  */
184
  public function category_filter() {
185
- $current_view = isset( $_GET[ 'view' ] ) ? $_GET[ 'view' ] : 'earnings';
186
  if( get_terms( 'download_category' ) ) {
187
  echo EDD()->html->category_dropdown( 'category', $this->get_category() );
188
  }
@@ -295,8 +294,6 @@ class EDD_Download_Reports_Table extends WP_List_Table {
295
 
296
  $data = $this->reports_data();
297
 
298
- $current_page = $this->get_pagenum();
299
-
300
  $total_items = $this->get_total_downloads();
301
 
302
  $this->items = $data;
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.5
10
  */
80
  case 'average_earnings' :
81
  return edd_currency_filter( edd_format_amount( $item[ $column_name ] ) );
82
  case 'details' :
83
+ return '<a href="' . admin_url( 'edit.php?post_type=download&page=edd-reports&view=downloads&download-id=' . $item['ID'] ) . '">' . __( 'View Detailed Report', 'edd' ) . '</a>';
84
  default:
85
  return $item[ $column_name ];
86
  }
168
  * @since 1.5
169
  * @return void
170
  */
171
+ public function bulk_actions( $which = '' ) {
172
  // These aren't really bulk actions but this outputs the markup in the right place
173
  edd_report_views();
174
  }
182
  * @return void
183
  */
184
  public function category_filter() {
 
185
  if( get_terms( 'download_category' ) ) {
186
  echo EDD()->html->category_dropdown( 'category', $this->get_category() );
187
  }
294
 
295
  $data = $this->reports_data();
296
 
 
 
297
  $total_items = $this->get_total_downloads();
298
 
299
  $this->items = $data;
includes/admin/reporting/class-edd-graph.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
- * @copyright Copyright (c) 2012, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.9
12
  */
@@ -183,7 +183,7 @@ class EDD_Graph {
183
  lines: {
184
  show: <?php echo $this->options['lines'] ? 'true' : 'false'; ?>
185
  },
186
- <?php if( $this->options[ 'multiple_y_axes' ] ) : ?>
187
  yaxis: <?php echo $yaxis_count; ?>
188
  <?php endif; ?>
189
  },
@@ -194,10 +194,10 @@ class EDD_Graph {
194
  grid: {
195
  show: true,
196
  aboveData: false,
197
- color: "<?php echo $this->options[ 'color' ]; ?>",
198
- backgroundColor: "<?php echo $this->options[ 'bgcolor' ]; ?>",
199
- borderColor: "<?php echo $this->options[ 'bordercolor' ]; ?>",
200
- borderWidth: <?php echo absint( $this->options[ 'borderwidth' ] ); ?>,
201
  clickable: false,
202
  hoverable: true
203
  },
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.9
12
  */
183
  lines: {
184
  show: <?php echo $this->options['lines'] ? 'true' : 'false'; ?>
185
  },
186
+ <?php if( $this->options['multiple_y_axes'] ) : ?>
187
  yaxis: <?php echo $yaxis_count; ?>
188
  <?php endif; ?>
189
  },
194
  grid: {
195
  show: true,
196
  aboveData: false,
197
+ color: "<?php echo $this->options['color']; ?>",
198
+ backgroundColor: "<?php echo $this->options['bgcolor']; ?>",
199
+ borderColor: "<?php echo $this->options['bordercolor']; ?>",
200
+ borderWidth: <?php echo absint( $this->options['borderwidth'] ); ?>,
201
  clickable: false,
202
  hoverable: true
203
  },
includes/admin/reporting/class-export-customers.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
- * @copyright Copyright (c) 2014, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.4.4
12
  */
@@ -49,7 +49,7 @@ class EDD_Customers_Export extends EDD_Export {
49
 
50
  nocache_headers();
51
  header( 'Content-Type: text/csv; charset=utf-8' );
52
- header( 'Content-Disposition: attachment; filename=edd-export-' . $extra . $this->export_type . '-' . date( 'm-d-Y' ) . '.csv' );
53
  header( "Expires: 0" );
54
  }
55
 
@@ -137,25 +137,27 @@ class EDD_Customers_Export extends EDD_Export {
137
  );
138
  }
139
  }
 
140
  } else {
 
141
  // Export all customers
142
- $emails = $wpdb->get_col( "SELECT DISTINCT meta_value FROM $wpdb->postmeta WHERE meta_key = '_edd_payment_user_email' " );
143
 
144
  $i = 0;
145
 
146
- foreach ( $emails as $email ) {
147
 
148
  if( 'emails' != $_POST['edd_export_option'] ) {
149
- $wp_user = get_user_by( 'email', $email );
150
- $data[$i]['name'] = $wp_user ? $wp_user->display_name : __( 'Guest', 'edd' );
151
  }
152
 
153
- $data[$i]['email'] = $email;
154
 
155
  if( 'full' == $_POST['edd_export_option'] ) {
156
- $stats = edd_get_purchase_stats_by_user( $email );
157
- $data[$i]['purchases'] = $stats['purchases'];
158
- $data[$i]['amount'] = edd_format_amount( $stats['total_spent'] );
 
159
  }
160
  $i++;
161
  }
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.4.4
12
  */
49
 
50
  nocache_headers();
51
  header( 'Content-Type: text/csv; charset=utf-8' );
52
+ header( 'Content-Disposition: attachment; filename=' . apply_filters( 'edd_customers_export_filename', 'edd-export-' . $extra . $this->export_type . '-' . date( 'm-d-Y' ) ) . '.csv' );
53
  header( "Expires: 0" );
54
  }
55
 
137
  );
138
  }
139
  }
140
+
141
  } else {
142
+
143
  // Export all customers
144
+ $customers = EDD()->customers->get_customers( array( 'number' => -1 ) );
145
 
146
  $i = 0;
147
 
148
+ foreach ( $customers as $customer ) {
149
 
150
  if( 'emails' != $_POST['edd_export_option'] ) {
151
+ $data[$i]['name'] = $customer->name;
 
152
  }
153
 
154
+ $data[$i]['email'] = $customer->email;
155
 
156
  if( 'full' == $_POST['edd_export_option'] ) {
157
+
158
+ $data[$i]['purchases'] = $customer->purchase_count;
159
+ $data[$i]['amount'] = edd_format_amount( $customer->purchase_value );
160
+
161
  }
162
  $i++;
163
  }
includes/admin/reporting/class-export-download-history.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
- * @copyright Copyright (c) 2014, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.4.4
12
  */
@@ -47,7 +47,7 @@ class EDD_Download_History_Export extends EDD_Export {
47
 
48
  nocache_headers();
49
  header( 'Content-Type: text/csv; charset=utf-8' );
50
- header( 'Content-Disposition: attachment; filename=edd-export-' . $this->export_type . '-' . $month . '-' . $year . '.csv' );
51
  header( "Expires: 0" );
52
  }
53
 
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.4.4
12
  */
47
 
48
  nocache_headers();
49
  header( 'Content-Type: text/csv; charset=utf-8' );
50
+ header( 'Content-Disposition: attachment; filename=' . apply_filters( 'edd_download_history_export_filename', 'edd-export-' . $this->export_type . '-' . $month . '-' . $year ) . '.csv' );
51
  header( "Expires: 0" );
52
  }
53
 
includes/admin/reporting/class-export-earnings.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
- * @copyright Copyright (c) 2014, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 2.0
12
  */
@@ -44,7 +44,7 @@ class EDD_Earnings_Export extends EDD_Export {
44
 
45
  nocache_headers();
46
  header( 'Content-Type: text/csv; charset=utf-8' );
47
- header( 'Content-Disposition: attachment; filename=edd-export-' . $this->export_type . '-' . date( 'n' ) . '-' . date( 'Y' ) . '.csv' );
48
  header( "Expires: 0" );
49
 
50
  }
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 2.0
12
  */
44
 
45
  nocache_headers();
46
  header( 'Content-Type: text/csv; charset=utf-8' );
47
+ header( 'Content-Disposition: attachment; filename=' . apply_filters( 'edd_earnings_export_filename', 'edd-export-' . $this->export_type . '-' . date( 'n' ) . '-' . date( 'Y' ) ) . '.csv' );
48
  header( "Expires: 0" );
49
 
50
  }
includes/admin/reporting/class-export-payments.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
- * @copyright Copyright (c) 2014, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.4.4
12
  */
@@ -45,7 +45,7 @@ class EDD_Payments_Export extends EDD_Export {
45
 
46
  nocache_headers();
47
  header( 'Content-Type: text/csv; charset=utf-8' );
48
- header( 'Content-Disposition: attachment; filename=edd-export-' . $this->export_type . '-' . $month . '-' . $year . '.csv' );
49
  header( "Expires: 0" );
50
  }
51
 
@@ -57,10 +57,9 @@ class EDD_Payments_Export extends EDD_Export {
57
  * @return array $cols All the columns
58
  */
59
  public function csv_cols() {
60
- global $edd_options;
61
-
62
  $cols = array(
63
- 'id' => __( 'ID', 'edd' ),
 
64
  'email' => __( 'Email', 'edd' ),
65
  'first' => __( 'First Name', 'edd' ),
66
  'last' => __( 'Last Name', 'edd' ),
@@ -76,14 +75,19 @@ class EDD_Payments_Export extends EDD_Export {
76
  'tax' => __( 'Tax', 'edd' ) . ' (' . html_entity_decode( edd_currency_filter( '' ) ) . ')',
77
  'discount' => __( 'Discount Code', 'edd' ),
78
  'gateway' => __( 'Payment Method', 'edd' ),
 
79
  'key' => __( 'Purchase Key', 'edd' ),
80
  'date' => __( 'Date', 'edd' ),
81
  'user' => __( 'User', 'edd' ),
82
  'status' => __( 'Status', 'edd' )
83
  );
84
 
85
- if( ! edd_use_skus() )
86
  unset( $cols['skus'] );
 
 
 
 
87
 
88
  return $cols;
89
  }
@@ -98,7 +102,7 @@ class EDD_Payments_Export extends EDD_Export {
98
  * @return array $data The data for the CSV file
99
  */
100
  public function get_data() {
101
- global $wpdb, $edd_options;
102
 
103
  $data = array();
104
 
@@ -144,7 +148,7 @@ class EDD_Payments_Export extends EDD_Export {
144
  $price_options = $downloads[ $key ]['item_number']['options'];
145
 
146
  if ( isset( $price_options['price_id'] ) ) {
147
- $products .= edd_get_price_option_name( $id, $price_options['price_id'] ) . ' - ';
148
  }
149
  }
150
  $products .= html_entity_decode( edd_currency_filter( $price ) );
@@ -165,10 +169,11 @@ class EDD_Payments_Export extends EDD_Export {
165
  }
166
 
167
  $data[] = array(
168
- 'id' => edd_get_payment_number( $payment->ID ),
 
169
  'email' => $payment_meta['email'],
170
  'first' => $user_info['first_name'],
171
- 'last' => $user_info['last_name'],
172
  'address1' => isset( $user_info['address']['line1'] ) ? $user_info['address']['line1'] : '',
173
  'address2' => isset( $user_info['address']['line2'] ) ? $user_info['address']['line2'] : '',
174
  'city' => isset( $user_info['address']['city'] ) ? $user_info['address']['city'] : '',
@@ -178,18 +183,16 @@ class EDD_Payments_Export extends EDD_Export {
178
  'products' => $products,
179
  'skus' => $skus,
180
  'amount' => html_entity_decode( edd_format_amount( $total ) ),
181
- 'tax' => html_entity_decode( edd_get_payment_tax( $payment->ID, $payment_meta ) ),
182
  'discount' => isset( $user_info['discount'] ) && $user_info['discount'] != 'none' ? $user_info['discount'] : __( 'none', 'edd' ),
183
  'gateway' => edd_get_gateway_admin_label( get_post_meta( $payment->ID, '_edd_payment_gateway', true ) ),
 
184
  'key' => $payment_meta['key'],
185
  'date' => $payment->post_date,
186
  'user' => $user ? $user->display_name : __( 'guest', 'edd' ),
187
  'status' => edd_get_payment_status( $payment, true )
188
  );
189
 
190
- if( !edd_use_skus() ) {
191
- unset( $data['skus'] );
192
- }
193
  }
194
 
195
  $data = apply_filters( 'edd_export_get_data', $data );
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.4.4
12
  */
45
 
46
  nocache_headers();
47
  header( 'Content-Type: text/csv; charset=utf-8' );
48
+ header( 'Content-Disposition: attachment; filename=' . apply_filters( 'edd_payments_export_filename', 'edd-export-' . $this->export_type . '-' . $month . '-' . $year ) . '.csv' );
49
  header( "Expires: 0" );
50
  }
51
 
57
  * @return array $cols All the columns
58
  */
59
  public function csv_cols() {
 
 
60
  $cols = array(
61
+ 'id' => __( 'ID', 'edd' ), // unaltered payment ID (use for querying)
62
+ 'seq_id' => __( 'Payment Number', 'edd' ), // sequential payment ID
63
  'email' => __( 'Email', 'edd' ),
64
  'first' => __( 'First Name', 'edd' ),
65
  'last' => __( 'Last Name', 'edd' ),
75
  'tax' => __( 'Tax', 'edd' ) . ' (' . html_entity_decode( edd_currency_filter( '' ) ) . ')',
76
  'discount' => __( 'Discount Code', 'edd' ),
77
  'gateway' => __( 'Payment Method', 'edd' ),
78
+ 'trans_id' => __( 'Transaction ID', 'edd' ),
79
  'key' => __( 'Purchase Key', 'edd' ),
80
  'date' => __( 'Date', 'edd' ),
81
  'user' => __( 'User', 'edd' ),
82
  'status' => __( 'Status', 'edd' )
83
  );
84
 
85
+ if( ! edd_use_skus() ){
86
  unset( $cols['skus'] );
87
+ }
88
+ if ( ! edd_get_option( 'enable_sequential' ) ) {
89
+ unset( $cols['seq_id'] );
90
+ }
91
 
92
  return $cols;
93
  }
102
  * @return array $data The data for the CSV file
103
  */
104
  public function get_data() {
105
+ global $wpdb;
106
 
107
  $data = array();
108
 
148
  $price_options = $downloads[ $key ]['item_number']['options'];
149
 
150
  if ( isset( $price_options['price_id'] ) ) {
151
+ $products .= edd_get_price_option_name( $id, $price_options['price_id'], $payment->ID ) . ' - ';
152
  }
153
  }
154
  $products .= html_entity_decode( edd_currency_filter( $price ) );
169
  }
170
 
171
  $data[] = array(
172
+ 'id' => $payment->ID,
173
+ 'seq_id' => edd_get_payment_number( $payment->ID ),
174
  'email' => $payment_meta['email'],
175
  'first' => $user_info['first_name'],
176
+ 'last' => $user_info['last_name'],
177
  'address1' => isset( $user_info['address']['line1'] ) ? $user_info['address']['line1'] : '',
178
  'address2' => isset( $user_info['address']['line2'] ) ? $user_info['address']['line2'] : '',
179
  'city' => isset( $user_info['address']['city'] ) ? $user_info['address']['city'] : '',
183
  'products' => $products,
184
  'skus' => $skus,
185
  'amount' => html_entity_decode( edd_format_amount( $total ) ),
186
+ 'tax' => html_entity_decode( edd_format_amount( edd_get_payment_tax( $payment->ID, $payment_meta ) ) ),
187
  'discount' => isset( $user_info['discount'] ) && $user_info['discount'] != 'none' ? $user_info['discount'] : __( 'none', 'edd' ),
188
  'gateway' => edd_get_gateway_admin_label( get_post_meta( $payment->ID, '_edd_payment_gateway', true ) ),
189
+ 'trans_id' => edd_get_payment_transaction_id( $payment->ID ),
190
  'key' => $payment_meta['key'],
191
  'date' => $payment->post_date,
192
  'user' => $user ? $user->display_name : __( 'guest', 'edd' ),
193
  'status' => edd_get_payment_status( $payment, true )
194
  );
195
 
 
 
 
196
  }
197
 
198
  $data = apply_filters( 'edd_export_get_data', $data );
includes/admin/reporting/class-export.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
- * @copyright Copyright (c) 2014, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.4.4
12
  */
@@ -35,7 +35,7 @@ class EDD_Export {
35
  * @return bool Whether we can export or not
36
  */
37
  public function can_export() {
38
- return (bool) apply_filters( 'edd_export_capability', current_user_can( 'manage_options' ) );
39
  }
40
 
41
  /**
@@ -96,7 +96,7 @@ class EDD_Export {
96
  $cols = $this->get_csv_cols();
97
  $i = 1;
98
  foreach( $cols as $col_id => $column ) {
99
- echo '"' . $column . '"';
100
  echo $i == count( $cols ) ? '' : ',';
101
  $i++;
102
  }
@@ -147,11 +147,10 @@ class EDD_Export {
147
  foreach ( $row as $col_id => $column ) {
148
  // Make sure the column is valid
149
  if ( array_key_exists( $col_id, $cols ) ) {
150
- echo '"' . $column . '"';
151
- echo $i == count( $cols ) + 1 ? '' : ',';
 
152
  }
153
-
154
- $i++;
155
  }
156
  echo "\r\n";
157
  }
@@ -170,7 +169,7 @@ class EDD_Export {
170
  */
171
  public function export() {
172
  if ( ! $this->can_export() )
173
- wp_die( __( 'You do not have permission to export data.', 'edd' ), __( 'Error', 'edd' ) );
174
 
175
  // Set headers
176
  $this->headers();
@@ -183,4 +182,4 @@ class EDD_Export {
183
 
184
  edd_die();
185
  }
186
- }
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Reports
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.4.4
12
  */
35
  * @return bool Whether we can export or not
36
  */
37
  public function can_export() {
38
+ return (bool) apply_filters( 'edd_export_capability', current_user_can( 'export_shop_reports' ) );
39
  }
40
 
41
  /**
96
  $cols = $this->get_csv_cols();
97
  $i = 1;
98
  foreach( $cols as $col_id => $column ) {
99
+ echo '"' . addslashes( $column ) . '"';
100
  echo $i == count( $cols ) ? '' : ',';
101
  $i++;
102
  }
147
  foreach ( $row as $col_id => $column ) {
148
  // Make sure the column is valid
149
  if ( array_key_exists( $col_id, $cols ) ) {
150
+ echo '"' . addslashes( $column ) . '"';
151
+ echo $i == count( $cols ) ? '' : ',';
152
+ $i++;
153
  }
 
 
154
  }
155
  echo "\r\n";
156
  }
169
  */
170
  public function export() {
171
  if ( ! $this->can_export() )
172
+ wp_die( __( 'You do not have permission to export data.', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
173
 
174
  // Set headers
175
  $this->headers();
182
 
183
  edd_die();
184
  }
185
+ }
includes/admin/reporting/class-file-downloads-logs-list-table.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4.4
10
  */
@@ -25,7 +25,7 @@ if ( ! class_exists( 'WP_List_Table' ) ) {
25
  * @since 1.4
26
  */
27
  class EDD_File_Downloads_Log_Table extends WP_List_Table {
28
-
29
  /**
30
  * Number of items per page
31
  *
@@ -102,7 +102,7 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
102
  * @access public
103
  * @since 1.4
104
  *
105
- * @param array $item Contains all the data of the discount code
106
  * @param string $column_name The name of the column
107
  *
108
  * @return string Column Name
@@ -112,9 +112,9 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
112
  case 'download' :
113
  return '<a href="' . add_query_arg( 'download', $item[ $column_name ] ) . '" >' . get_the_title( $item[ $column_name ] ) . '</a>';
114
  case 'user_id' :
115
- return '<a href="' . add_query_arg( 'user', $item[ $column_name ] ) . '">' . $item[ 'user_name' ] . '</a>';
116
  case 'payment_id' :
117
- return '<a href="' . admin_url( 'edit.php?post_type=download&page=edd-payment-history&view=view-order-details&id=' . $item[ 'payment_id' ] ) . '">' . edd_get_payment_number( $item[ 'payment_id' ] ) . '</a>';
118
  default:
119
  return $item[ $column_name ];
120
  }
@@ -145,10 +145,20 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
145
  *
146
  * @access public
147
  * @since 1.4
148
- * @return mixed int If User ID, string If Email/Login
149
  */
150
  public function get_filtered_user() {
151
- return isset( $_GET['user'] ) ? absint( $_GET['user'] ) : false;
 
 
 
 
 
 
 
 
 
 
152
  }
153
 
154
  /**
@@ -178,10 +188,10 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
178
  *
179
  * @access public
180
  * @since 1.4
181
- * @return mixed string If search is present, false otherwise
182
  */
183
  public function get_search() {
184
- return ! empty( $_GET['s'] ) ? urldecode( trim( $_GET['s'] ) ) : false;
185
  }
186
 
187
  /**
@@ -200,10 +210,18 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
200
 
201
  if ( $user ) {
202
  // Show only logs from a specific user
203
- $meta_query[] = array(
204
- 'key' => '_edd_log_user_id',
205
- 'value' => $user
206
- );
 
 
 
 
 
 
 
 
207
  }
208
 
209
  if ( $payment ) {
@@ -216,7 +234,7 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
216
 
217
  $search = $this->get_search();
218
 
219
- if ( $search ) {
220
  if ( filter_var( $search, FILTER_VALIDATE_IP ) ) {
221
  // This is an IP address search
222
  $key = '_edd_log_ip';
@@ -289,7 +307,7 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
289
  * @since 1.4
290
  * @return void
291
  */
292
- public function bulk_actions() {
293
  // These aren't really bulk actions but this outputs the markup in the right place
294
  edd_log_views();
295
  }
@@ -355,11 +373,10 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
355
  if ( $logs ) {
356
  foreach ( $logs as $log ) {
357
 
358
-
359
  $meta = get_post_custom( $log->ID );
360
- $user_info = maybe_unserialize( $meta[ '_edd_log_user_info' ][0] );
361
- $payment_id = $meta[ '_edd_log_payment_id' ][0];
362
- $ip = $meta[ '_edd_log_ip' ][0];
363
  $user_id = isset( $user_info['id'] ) ? $user_info['id'] : false;
364
 
365
  if( ! array_key_exists( $log->post_parent, $this->queried_files ) ) {
@@ -369,7 +386,7 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
369
  $files = $this->queried_files[ $log->post_parent ];
370
  }
371
 
372
- $file_id = (int) $meta[ '_edd_log_file_id' ][0];
373
  $file_id = $file_id !== false ? $file_id : 0;
374
  $file_name = isset( $files[ $file_id ]['name'] ) ? $files[ $file_id ]['name'] : null;
375
 
@@ -378,8 +395,8 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
378
  'ID' => $log->ID,
379
  'download' => $log->post_parent,
380
  'payment_id'=> $payment_id,
381
- 'user_id' => $user_id ? $user_id : $user_info['email'],
382
- 'user_name' => $user_info['email'],
383
  'file' => $file_name,
384
  'ip' => $ip,
385
  'date' => $log->post_date
@@ -412,7 +429,6 @@ class EDD_File_Downloads_Log_Table extends WP_List_Table {
412
  $hidden = array(); // No hidden columns
413
  $sortable = $this->get_sortable_columns();
414
  $this->_column_headers = array( $columns, $hidden, $sortable );
415
- $current_page = $this->get_pagenum();
416
  $this->items = $this->get_logs();
417
  $total_items = $edd_logs->get_log_count( $this->get_filtered_download(), 'file_download', $this->get_meta_query() );
418
  $this->set_pagination_args( array(
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4.4
10
  */
25
  * @since 1.4
26
  */
27
  class EDD_File_Downloads_Log_Table extends WP_List_Table {
28
+
29
  /**
30
  * Number of items per page
31
  *
102
  * @access public
103
  * @since 1.4
104
  *
105
+ * @param array $item Contains all the data of the log item
106
  * @param string $column_name The name of the column
107
  *
108
  * @return string Column Name
112
  case 'download' :
113
  return '<a href="' . add_query_arg( 'download', $item[ $column_name ] ) . '" >' . get_the_title( $item[ $column_name ] ) . '</a>';
114
  case 'user_id' :
115
+ return $item[ $column_name ] ? '<a href="' . add_query_arg( 'user', $item[ $column_name ] ) . '">' . $item['user_name'] . '</a>' : $item['user_name'];
116
  case 'payment_id' :
117
+ return $item['payment_id'] !== false ? '<a href="' . admin_url( 'edit.php?post_type=download&page=edd-payment-history&view=view-order-details&id=' . $item['payment_id'] ) . '">' . edd_get_payment_number( $item['payment_id'] ) . '</a>' : '';
118
  default:
119
  return $item[ $column_name ];
120
  }
145
  *
146
  * @access public
147
  * @since 1.4
148
+ * @return mixed int If User ID, string If Email/Login, false if not present
149
  */
150
  public function get_filtered_user() {
151
+ $ret = false;
152
+
153
+ if( isset( $_GET['user'] ) ) {
154
+ if( is_numeric( $_GET['user'] ) ) {
155
+ $ret = absint( $_GET['user'] );
156
+ } else {
157
+ $ret = sanitize_text_field( $_GET['user'] );
158
+ }
159
+ }
160
+
161
+ return $ret;
162
  }
163
 
164
  /**
188
  *
189
  * @access public
190
  * @since 1.4
191
+ * @return String The search string
192
  */
193
  public function get_search() {
194
+ return ! empty( $_GET['s'] ) ? urldecode( trim( $_GET['s'] ) ) : '';
195
  }
196
 
197
  /**
210
 
211
  if ( $user ) {
212
  // Show only logs from a specific user
213
+ if( is_numeric( $user ) ) {
214
+ $meta_query[] = array(
215
+ 'key' => '_edd_log_user_id',
216
+ 'value' => $user
217
+ );
218
+ } else {
219
+ $meta_query[] = array(
220
+ 'key' => '_edd_log_user_info',
221
+ 'value' => $user,
222
+ 'compare' => 'LIKE'
223
+ );
224
+ }
225
  }
226
 
227
  if ( $payment ) {
234
 
235
  $search = $this->get_search();
236
 
237
+ if ( ! empty( $search ) ) {
238
  if ( filter_var( $search, FILTER_VALIDATE_IP ) ) {
239
  // This is an IP address search
240
  $key = '_edd_log_ip';
307
  * @since 1.4
308
  * @return void
309
  */
310
+ public function bulk_actions( $which = '' ) {
311
  // These aren't really bulk actions but this outputs the markup in the right place
312
  edd_log_views();
313
  }
373
  if ( $logs ) {
374
  foreach ( $logs as $log ) {
375
 
 
376
  $meta = get_post_custom( $log->ID );
377
+ $user_info = isset( $meta['_edd_log_user_info'] ) ? maybe_unserialize( $meta['_edd_log_user_info'][0] ) : array();
378
+ $payment_id = isset( $meta['_edd_log_payment_id'] ) ? $meta['_edd_log_payment_id'][0] : false;
379
+ $ip = $meta['_edd_log_ip'][0];
380
  $user_id = isset( $user_info['id'] ) ? $user_info['id'] : false;
381
 
382
  if( ! array_key_exists( $log->post_parent, $this->queried_files ) ) {
386
  $files = $this->queried_files[ $log->post_parent ];
387
  }
388
 
389
+ $file_id = (int) $meta['_edd_log_file_id'][0];
390
  $file_id = $file_id !== false ? $file_id : 0;
391
  $file_name = isset( $files[ $file_id ]['name'] ) ? $files[ $file_id ]['name'] : null;
392
 
395
  'ID' => $log->ID,
396
  'download' => $log->post_parent,
397
  'payment_id'=> $payment_id,
398
+ 'user_id' => $user_id ? $user_id : ( isset( $user_info['email'] ) ? $user_info['email'] : null ),
399
+ 'user_name' => isset( $user_info['email'] ) ? $user_info['email'] : ( isset( $user_info['name'] ) ? $user_info['name'] : '' ),
400
  'file' => $file_name,
401
  'ip' => $ip,
402
  'date' => $log->post_date
429
  $hidden = array(); // No hidden columns
430
  $sortable = $this->get_sortable_columns();
431
  $this->_column_headers = array( $columns, $hidden, $sortable );
 
432
  $this->items = $this->get_logs();
433
  $total_items = $edd_logs->get_log_count( $this->get_filtered_download(), 'file_download', $this->get_meta_query() );
434
  $this->set_pagination_args( array(
includes/admin/reporting/class-gateway-error-logs-list-table.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  */
10
 
@@ -56,7 +56,7 @@ class EDD_Gateway_Error_Log_Table extends WP_List_Table {
56
  * @access public
57
  * @since 1.4
58
  *
59
- * @param array $item Contains all the data of the discount code
60
  * @param string $column_name The name of the column
61
  *
62
  * @return string Column Name
@@ -143,7 +143,7 @@ class EDD_Gateway_Error_Log_Table extends WP_List_Table {
143
  * @since 1.4
144
  * @return void
145
  */
146
- public function bulk_actions() {
147
  // These aren't really bulk actions but this outputs the markup in the right place
148
  edd_log_views();
149
  }
@@ -207,7 +207,6 @@ class EDD_Gateway_Error_Log_Table extends WP_List_Table {
207
  $hidden = array(); // No hidden columns
208
  $sortable = $this->get_sortable_columns();
209
  $this->_column_headers = array( $columns, $hidden, $sortable );
210
- $current_page = $this->get_pagenum();
211
  $this->items = $this->get_logs();
212
  $total_items = $edd_logs->get_log_count( 0, 'gateway_error' );
213
 
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  */
10
 
56
  * @access public
57
  * @since 1.4
58
  *
59
+ * @param array $item Contains all the data of the log item
60
  * @param string $column_name The name of the column
61
  *
62
  * @return string Column Name
143
  * @since 1.4
144
  * @return void
145
  */
146
+ public function bulk_actions( $which = '' ) {
147
  // These aren't really bulk actions but this outputs the markup in the right place
148
  edd_log_views();
149
  }
207
  $hidden = array(); // No hidden columns
208
  $sortable = $this->get_sortable_columns();
209
  $this->_column_headers = array( $columns, $hidden, $sortable );
 
210
  $this->items = $this->get_logs();
211
  $total_items = $edd_logs->get_log_count( 0, 'gateway_error' );
212
 
includes/admin/reporting/class-gateways-reports-table.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.5
10
  */
@@ -63,10 +63,7 @@ class EDD_Gateawy_Reports_Table extends WP_List_Table {
63
  * @return string Column Name
64
  */
65
  public function column_default( $item, $column_name ) {
66
- switch( $column_name ){
67
- default:
68
- return $item[ $column_name ];
69
- }
70
  }
71
 
72
  /**
@@ -107,7 +104,7 @@ class EDD_Gateawy_Reports_Table extends WP_List_Table {
107
  * @since 1.5
108
  * @return void
109
  */
110
- public function bulk_actions() {
111
  // These aren't really bulk actions but this outputs the markup in the right place
112
  edd_report_views();
113
  }
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.5
10
  */
63
  * @return string Column Name
64
  */
65
  public function column_default( $item, $column_name ) {
66
+ return $item[ $column_name ];
 
 
 
67
  }
68
 
69
  /**
104
  * @since 1.5
105
  * @return void
106
  */
107
+ public function bulk_actions( $which = '' ) {
108
  // These aren't really bulk actions but this outputs the markup in the right place
109
  edd_report_views();
110
  }
includes/admin/reporting/class-sales-logs-list-table.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  */
10
 
@@ -57,7 +57,7 @@ class EDD_Sales_Log_Table extends WP_List_Table {
57
  * @access public
58
  * @since 1.4
59
  *
60
- * @param array $item Contains all the data of the discount code
61
  * @param string $column_name The name of the column
62
  *
63
  * @return string Column Name
@@ -70,13 +70,13 @@ class EDD_Sales_Log_Table extends WP_List_Table {
70
  case 'user_id' :
71
  return '<a href="' .
72
  admin_url( 'edit.php?post_type=download&page=edd-payment-history&user=' . urlencode( $item['user_id'] ) ) .
73
- '">' . $item[ 'user_name' ] . '</a>';
74
 
75
  case 'amount' :
76
  return edd_currency_filter( edd_format_amount( $item['amount'] ) );
77
 
78
  case 'payment_id' :
79
- return '<a href="' . admin_url( 'edit.php?post_type=download&page=edd-payment-history&view=view-order-details&id=' . $item[ 'payment_id' ] ) . '">' . edd_get_payment_number( $item[ 'payment_id' ] ) . '</a>';
80
 
81
  default:
82
  return $item[ $column_name ];
@@ -141,7 +141,7 @@ class EDD_Sales_Log_Table extends WP_List_Table {
141
  *
142
  * @access public
143
  * @since 1.4
144
- * @return mixed string If search is present, false otherwise
145
  */
146
  public function get_search() {
147
  return ! empty( $_GET['s'] ) ? urldecode( trim( $_GET['s'] ) ) : false;
@@ -226,7 +226,7 @@ class EDD_Sales_Log_Table extends WP_List_Table {
226
  * @since 1.4
227
  * @return void
228
  */
229
- function bulk_actions() {
230
  // These aren't really bulk actions but this outputs the markup in the right place
231
  edd_log_views();
232
  }
@@ -277,7 +277,6 @@ class EDD_Sales_Log_Table extends WP_List_Table {
277
  $logs_data = array();
278
  $paged = $this->get_paged();
279
  $download = empty( $_GET['s'] ) ? $this->get_filtered_download() : null;
280
- $user = $this-> get_filtered_user();
281
 
282
  $log_query = array(
283
  'post_parent' => $download,
@@ -299,20 +298,22 @@ class EDD_Sales_Log_Table extends WP_List_Table {
299
  $amount = 0;
300
  if ( is_array( $cart_items ) && is_array( $user_info ) ) {
301
  foreach ( $cart_items as $item ) {
302
- $price_override = isset( $item['price'] ) ? $item['price'] : null;
303
- if ( isset( $item['id'] ) && $item['id'] == $log->post_parent ) {
304
- $amount = edd_get_download_final_price( $item['id'], $user_info, $price_override );
 
305
  }
 
306
  }
307
 
308
  $logs_data[] = array(
309
- 'ID' => $log->ID,
310
- 'payment_id'=> $payment_id,
311
- 'download' => $log->post_parent,
312
- 'amount' => $amount,
313
- 'user_id' => $user_info['id'],
314
- 'user_name' => $user_info['first_name'] . ' ' . $user_info['last_name'],
315
- 'date' => get_post_field( 'post_date', $payment_id )
316
  );
317
  }
318
  endif;
@@ -342,7 +343,6 @@ class EDD_Sales_Log_Table extends WP_List_Table {
342
  $hidden = array();
343
  $sortable = $this->get_sortable_columns();
344
  $this->_column_headers = array( $columns, $hidden, $sortable );
345
- $current_page = $this->get_pagenum();
346
  $this->items = $this->get_logs();
347
  $total_items = $edd_logs->get_log_count( $this->get_filtered_download(), 'sale', $this->get_meta_query() );
348
 
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  */
10
 
57
  * @access public
58
  * @since 1.4
59
  *
60
+ * @param array $item Contains all the data of the log item
61
  * @param string $column_name The name of the column
62
  *
63
  * @return string Column Name
70
  case 'user_id' :
71
  return '<a href="' .
72
  admin_url( 'edit.php?post_type=download&page=edd-payment-history&user=' . urlencode( $item['user_id'] ) ) .
73
+ '">' . $item['user_name'] . '</a>';
74
 
75
  case 'amount' :
76
  return edd_currency_filter( edd_format_amount( $item['amount'] ) );
77
 
78
  case 'payment_id' :
79
+ return '<a href="' . admin_url( 'edit.php?post_type=download&page=edd-payment-history&view=view-order-details&id=' . $item['payment_id'] ) . '">' . edd_get_payment_number( $item['payment_id'] ) . '</a>';
80
 
81
  default:
82
  return $item[ $column_name ];
141
  *
142
  * @access public
143
  * @since 1.4
144
+ * @return string|false string If search is present, false otherwise
145
  */
146
  public function get_search() {
147
  return ! empty( $_GET['s'] ) ? urldecode( trim( $_GET['s'] ) ) : false;
226
  * @since 1.4
227
  * @return void
228
  */
229
+ function bulk_actions( $which = '' ) {
230
  // These aren't really bulk actions but this outputs the markup in the right place
231
  edd_log_views();
232
  }
277
  $logs_data = array();
278
  $paged = $this->get_paged();
279
  $download = empty( $_GET['s'] ) ? $this->get_filtered_download() : null;
 
280
 
281
  $log_query = array(
282
  'post_parent' => $download,
298
  $amount = 0;
299
  if ( is_array( $cart_items ) && is_array( $user_info ) ) {
300
  foreach ( $cart_items as $item ) {
301
+
302
+ if ( $item['id'] == $log->post_parent ) {
303
+ $amount = isset( $item['item_price'] ) ? $item['item_price'] : $item['price'];
304
+ break;
305
  }
306
+
307
  }
308
 
309
  $logs_data[] = array(
310
+ 'ID' => $log->ID,
311
+ 'payment_id' => $payment_id,
312
+ 'download' => $log->post_parent,
313
+ 'amount' => $amount,
314
+ 'user_id' => $user_info['id'],
315
+ 'user_name' => $user_info['first_name'] . ' ' . $user_info['last_name'],
316
+ 'date' => get_post_field( 'post_date', $payment_id )
317
  );
318
  }
319
  endif;
343
  $hidden = array();
344
  $sortable = $this->get_sortable_columns();
345
  $this->_column_headers = array( $columns, $hidden, $sortable );
 
346
  $this->items = $this->get_logs();
347
  $total_items = $edd_logs->get_log_count( $this->get_filtered_download(), 'sale', $this->get_meta_query() );
348
 
includes/admin/reporting/contextual-help.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
includes/admin/reporting/graphing.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -35,7 +35,7 @@ function edd_reports_graph() {
35
  $day_by_day = false;
36
  break;
37
  case 'other' :
38
- if( $dates['m_end'] - $dates['m_start'] >= 2 || $dates['year_end'] > $dates['year'] ) {
39
  $day_by_day = false;
40
  } else {
41
  $day_by_day = true;
@@ -47,7 +47,7 @@ function edd_reports_graph() {
47
  endswitch;
48
 
49
  $earnings_totals = 0.00; // Total earnings for time period shown
50
- $sales_totals = 0; // Total sales for time period shown
51
 
52
  $earnings_data = array();
53
  $sales_data = array();
@@ -55,19 +55,19 @@ function edd_reports_graph() {
55
  if( $dates['range'] == 'today' || $dates['range'] == 'yesterday' ) {
56
  // Hour by hour
57
  $hour = 1;
58
- $month = date( 'n', current_time( 'timestamp' ) );
59
  while ( $hour <= 23 ) :
60
 
61
  $sales = edd_get_sales_by_date( $dates['day'], $month, $dates['year'], $hour );
62
  $earnings = edd_get_earnings_by_date( $dates['day'], $month, $dates['year'], $hour );
63
-
64
  $sales_totals += $sales;
65
  $earnings_totals += $earnings;
66
-
67
  $date = mktime( $hour, 0, 0, $month, $dates['day'], $dates['year'] ) * 1000;
68
  $sales_data[] = array( $date, $sales );
69
  $earnings_data[] = array( $date, $earnings );
70
-
71
  $hour++;
72
  endwhile;
73
 
@@ -101,6 +101,9 @@ function edd_reports_graph() {
101
  } elseif( $y == $dates['year'] ) {
102
  $month_start = $dates['m_start'];
103
  $month_end = 12;
 
 
 
104
  } else {
105
  $month_start = 1;
106
  $month_end = 12;
@@ -108,10 +111,23 @@ function edd_reports_graph() {
108
 
109
  $i = $month_start;
110
  while ( $i <= $month_end ) :
 
111
  if ( $day_by_day ) :
112
- $num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
113
- $d = 1;
 
 
 
 
 
 
 
 
 
 
 
114
  while ( $d <= $num_of_days ) :
 
115
  $sales = edd_get_sales_by_date( $d, $i, $y );
116
  $sales_totals += $sales;
117
 
@@ -121,20 +137,36 @@ function edd_reports_graph() {
121
  $date = mktime( 0, 0, 0, $i, $d, $y ) * 1000;
122
  $sales_data[] = array( $date, $sales );
123
  $earnings_data[] = array( $date, $earnings );
124
- $d++;
 
125
  endwhile;
 
126
  else :
 
127
  $sales = edd_get_sales_by_date( null, $i, $y );
128
  $sales_totals += $sales;
129
 
130
  $earnings = edd_get_earnings_by_date( null, $i, $y );
131
  $earnings_totals += $earnings;
132
 
133
- $date = mktime( 0, 0, 0, $i, 1, $y ) * 1000;
 
 
 
 
 
 
 
 
 
 
134
  $sales_data[] = array( $date, $sales );
135
  $earnings_data[] = array( $date, $earnings );
 
136
  endif;
 
137
  $i++;
 
138
  endwhile;
139
 
140
  $y++;
@@ -147,12 +179,14 @@ function edd_reports_graph() {
147
  __( 'Sales', 'edd' ) => $sales_data
148
  );
149
 
 
 
150
  ?>
151
  <div id="edd-dashboard-widgets-wrap">
152
  <div class="metabox-holder" style="padding-top: 0;">
153
  <div class="postbox">
154
  <h3><span><?php _e('Earnings Over Time', 'edd'); ?></span></h3>
155
-
156
  <div class="inside">
157
  <?php
158
  edd_reports_graph_controls();
@@ -160,20 +194,32 @@ function edd_reports_graph() {
160
  $graph->set( 'x_mode', 'time' );
161
  $graph->set( 'multiple_y_axes', true );
162
  $graph->display();
163
-
164
- $estimated = edd_estimated_monthly_stats();
 
 
165
  ?>
166
-
167
  <p class="edd_graph_totals"><strong><?php _e( 'Total earnings for period shown: ', 'edd' ); echo edd_currency_filter( edd_format_amount( $earnings_totals ) ); ?></strong></p>
168
  <p class="edd_graph_totals"><strong><?php _e( 'Total sales for period shown: ', 'edd' ); echo edd_format_amount( $sales_totals, false ); ?></strong></p>
169
- <p class="edd_graph_totals"><strong><?php _e( 'Estimated monthly earnings: ', 'edd' ); echo edd_currency_filter( edd_format_amount( $estimated['earnings'] ) ); ?></strong></p>
170
- <p class="edd_graph_totals"><strong><?php _e( 'Estimated monthly sales: ', 'edd' ); echo edd_format_amount( $estimated['sales'], false ); ?></strong></p>
 
 
 
 
 
 
171
  </div>
172
  </div>
173
  </div>
174
  </div>
175
  <?php
176
- echo ob_get_clean();
 
 
 
 
177
  }
178
 
179
  /**
@@ -221,32 +267,33 @@ function edd_reports_graph_of_download( $download_id = 0 ) {
221
 
222
  $earnings_data = array();
223
  $sales_data = array();
224
- $stats = new EDD_Payment_Stats;
225
 
226
  if( $dates['range'] == 'today' || $dates['range'] == 'yesterday' ) {
 
227
  // Hour by hour
228
- $month = date( 'n', current_time( 'timestamp' ) );
229
  $hour = 1;
230
  $minute = 0;
231
  $second = 0;
232
  while ( $hour <= 23 ) :
233
-
234
  if( $hour == 23 ) {
235
  $minute = $second = 59;
236
  }
237
 
238
  $date = mktime( $hour, $minute, $second, $month, $dates['day'], $dates['year'] );
239
  $date_end = mktime( $hour + 1, $minute, $second, $month, $dates['day'], $dates['year'] );
240
-
241
  $sales = $stats->get_sales( $download_id, $date, $date_end );
242
  $sales_totals += $sales;
243
-
244
  $earnings = $stats->get_earnings( $download_id, $date, $date_end );
245
  $earnings_totals += $earnings;
246
-
247
  $sales_data[] = array( $date * 1000, $sales );
248
  $earnings_data[] = array( $date * 1000, $earnings );
249
-
250
  $hour++;
251
  endwhile;
252
 
@@ -257,15 +304,15 @@ function edd_reports_graph_of_download( $download_id = 0 ) {
257
  $day_end = $dates['day_end'];
258
  $month = $dates['m_start'];
259
  while ( $day <= $day_end ) :
260
-
261
  $date = mktime( 0, 0, 0, $month, $day, $dates['year'] );
262
  $date_end = mktime( 0, 0, 0, $month, $day + 1, $dates['year'] );
263
  $sales = $stats->get_sales( $download_id, $date, $date_end );
264
  $sales_totals += $sales;
265
-
266
  $earnings = $stats->get_earnings( $download_id, $date, $date_end );
267
  $earnings_totals += $earnings;
268
-
269
  $sales_data[] = array( $date * 1000, $sales );
270
  $earnings_data[] = array( $date * 1000, $earnings );
271
 
@@ -290,37 +337,56 @@ function edd_reports_graph_of_download( $download_id = 0 ) {
290
 
291
  $i = $month_start;
292
  while ( $i <= $month_end ) :
 
293
  if ( $day_by_day ) :
294
- $num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
295
- $d = 1;
 
 
 
 
 
 
 
 
 
 
296
  while ( $d <= $num_of_days ) :
 
297
  $date = mktime( 0, 0, 0, $i, $d, $y );
298
- $end_date = mktime( 0, 0, 0, $i, $d + 1, $y );
299
-
300
  $sales = $stats->get_sales( $download_id, $date, $end_date );
301
  $sales_totals += $sales;
302
-
303
  $earnings = $stats->get_earnings( $download_id, $date, $end_date );
304
  $earnings_totals += $earnings;
305
-
306
  $sales_data[] = array( $date * 1000, $sales );
307
  $earnings_data[] = array( $date * 1000, $earnings );
308
  $d++;
 
309
  endwhile;
 
310
  else :
311
- $date = mktime( 0, 0, 0, $i, 1, $y );
312
- $end_date = mktime( 0, 0, 0, $i + 1, 1, $y );
313
-
 
 
 
314
  $sales = $stats->get_sales( $download_id, $date, $end_date );
315
  $sales_totals += $sales;
316
-
317
  $earnings = $stats->get_earnings( $download_id, $date, $end_date );
318
  $earnings_totals += $earnings;
319
-
320
  $sales_data[] = array( $date * 1000, $sales );
321
  $earnings_data[] = array( $date * 1000, $earnings );
322
  endif;
 
323
  $i++;
 
324
  endwhile;
325
 
326
  $y++;
@@ -333,14 +399,14 @@ function edd_reports_graph_of_download( $download_id = 0 ) {
333
  __( 'Sales', 'edd' ) => $sales_data
334
  );
335
 
336
- ?>
337
  <div class="metabox-holder" style="padding-top: 0;">
338
  <div class="postbox">
339
  <h3><span><?php printf( __('Earnings Over Time for %s', 'edd' ), get_the_title( $download_id ) ); ?></span></h3>
340
 
341
  <div class="inside">
342
- <?php
343
- edd_reports_graph_controls();
344
  $graph = new EDD_Graph( $data );
345
  $graph->set( 'x_mode', 'time' );
346
  $graph->set( 'multiple_y_axes', true );
@@ -348,7 +414,7 @@ function edd_reports_graph_of_download( $download_id = 0 ) {
348
  ?>
349
  <p class="edd_graph_totals"><strong><?php _e( 'Total earnings for period shown: ', 'edd' ); echo edd_currency_filter( edd_format_amount( $earnings_totals ) ); ?></strong></p>
350
  <p class="edd_graph_totals"><strong><?php _e( 'Total sales for period shown: ', 'edd' ); echo $sales_totals; ?></strong></p>
351
- <p class="edd_graph_totals"><strong><?php printf( __( 'Average monthly earnings: %s', 'edd' ), edd_get_average_monthly_download_earnings( $download_id ) ); ?>
352
  <p class="edd_graph_totals"><strong><?php printf( __( 'Average monthly sales: %s', 'edd' ), number_format( edd_get_average_monthly_download_sales( $download_id ), 0 ) ); ?>
353
  </div>
354
  </div>
@@ -378,60 +444,69 @@ function edd_reports_graph_controls() {
378
  'other' => __( 'Custom', 'edd' )
379
  ) );
380
 
381
- $dates = edd_get_report_dates();
382
-
383
  $display = $dates['range'] == 'other' ? '' : 'style="display:none;"';
 
384
 
385
- $view = edd_get_reporting_view();
 
 
386
 
387
  ?>
388
  <form id="edd-graphs-filter" method="get">
389
  <div class="tablenav top">
390
  <div class="alignleft actions">
391
 
392
- <input type="hidden" name="post_type" value="download"/>
393
- <input type="hidden" name="page" value="edd-reports"/>
394
- <input type="hidden" name="view" value="<?php echo esc_attr( $view ); ?>"/>
395
 
396
- <?php if( isset( $_GET['download-id'] ) ) : ?>
397
- <input type="hidden" name="download-id" value="<?php echo absint( $_GET['download-id'] ); ?>"/>
398
- <?php endif; ?>
399
 
400
- <select id="edd-graphs-date-options" name="range">
401
- <?php
402
- foreach ( $date_options as $key => $option ) {
403
- echo '<option value="' . esc_attr( $key ) . '" ' . selected( $key, $dates['range'] ) . '>' . esc_html( $option ) . '</option>';
404
- }
405
- ?>
406
- </select>
407
-
408
- <div id="edd-date-range-options" <?php echo $display; ?>>
409
  <span><?php _e( 'From', 'edd' ); ?>&nbsp;</span>
410
- <select id="edd-graphs-month-start" name="m_start">
411
- <?php for ( $i = 1; $i <= 12; $i++ ) : ?>
412
- <option value="<?php echo absint( $i ); ?>" <?php selected( $i, $dates['m_start'] ); ?>><?php echo edd_month_num_to_name( $i ); ?></option>
413
- <?php endfor; ?>
414
- </select>
415
- <select id="edd-graphs-year" name="year">
416
- <?php for ( $i = 2007; $i <= date( 'Y' ); $i++ ) : ?>
417
- <option value="<?php echo absint( $i ); ?>" <?php selected( $i, $dates['year'] ); ?>><?php echo $i; ?></option>
418
- <?php endfor; ?>
419
- </select>
420
- <span><?php _e( 'To', 'edd' ); ?>&nbsp;</span>
421
- <select id="edd-graphs-month-start" name="m_end">
422
- <?php for ( $i = 1; $i <= 12; $i++ ) : ?>
423
- <option value="<?php echo absint( $i ); ?>" <?php selected( $i, $dates['m_end'] ); ?>><?php echo edd_month_num_to_name( $i ); ?></option>
424
- <?php endfor; ?>
425
- </select>
426
- <select id="edd-graphs-year" name="year_end">
427
- <?php for ( $i = 2007; $i <= date( 'Y' ); $i++ ) : ?>
428
- <option value="<?php echo absint( $i ); ?>" <?php selected( $i, $dates['year_end'] ); ?>><?php echo $i; ?></option>
429
- <?php endfor; ?>
430
- </select>
431
- </div>
432
-
433
- <input type="hidden" name="edd_action" value="filter_reports" />
434
- <input type="submit" class="button-secondary" value="<?php _e( 'Filter', 'edd' ); ?>"/>
 
 
 
 
 
 
 
 
 
 
435
  </div>
436
  </div>
437
  </form>
@@ -445,7 +520,7 @@ function edd_reports_graph_controls() {
445
  * selected date-range (if any)
446
  *
447
  * @since 1.3
448
- * @return void
449
  */
450
  function edd_get_report_dates() {
451
  $dates = array();
@@ -453,19 +528,23 @@ function edd_get_report_dates() {
453
  $current_time = current_time( 'timestamp' );
454
 
455
  $dates['range'] = isset( $_GET['range'] ) ? $_GET['range'] : 'this_month';
456
- $dates['day'] = isset( $_GET['day'] ) ? $_GET['day'] : null;
457
- $dates['m_start'] = isset( $_GET['m_start'] ) ? $_GET['m_start'] : 1;
458
- $dates['m_end'] = isset( $_GET['m_end'] ) ? $_GET['m_end'] : 12;
459
  $dates['year'] = isset( $_GET['year'] ) ? $_GET['year'] : date( 'Y' );
460
  $dates['year_end'] = isset( $_GET['year_end'] )? $_GET['year_end']: date( 'Y' );
461
-
 
 
 
 
462
  // Modify dates based on predefined ranges
463
  switch ( $dates['range'] ) :
464
 
465
  case 'this_month' :
466
- $dates['m_start'] = date( 'n', $current_time );
467
- $dates['m_end'] = date( 'n', $current_time );
468
- $dates['year'] = date( 'Y', $current_time );
 
 
 
469
  break;
470
 
471
  case 'last_month' :
@@ -479,6 +558,7 @@ function edd_get_report_dates() {
479
  $dates['m_end'] = date( 'n' ) - 1;
480
  $dates['year_end']= $dates['year'];
481
  }
 
482
  break;
483
 
484
  case 'today' :
@@ -489,13 +569,33 @@ function edd_get_report_dates() {
489
  break;
490
 
491
  case 'yesterday' :
492
- $month = date( 'n', $current_time ) == 1 ? 12 : date( 'n', $current_time );
493
- $days_in_month = cal_days_in_month( CAL_GREGORIAN, $month, date( 'Y' ) );
494
- $yesterday = date( 'd', $current_time ) == 1 ? $days_in_month : date( 'd', $current_time ) - 1;
495
- $dates['day'] = $yesterday;
496
- $dates['m_start'] = $month;
497
- $dates['m_end'] = $month;
498
- $dates['year'] = $month == 1 && date( 'd', $current_time ) == 1 ? date( 'Y', $current_time ) - 1 : date( 'Y', $current_time );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
499
  break;
500
 
501
  case 'this_week' :
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
35
  $day_by_day = false;
36
  break;
37
  case 'other' :
38
+ if( $dates['m_end'] - $dates['m_start'] >= 2 || $dates['year_end'] > $dates['year'] && ( $dates['m_start'] != '12' && $dates['m_end'] != '1' ) ) {
39
  $day_by_day = false;
40
  } else {
41
  $day_by_day = true;
47
  endswitch;
48
 
49
  $earnings_totals = 0.00; // Total earnings for time period shown
50
+ $sales_totals = 0; // Total sales for time period shown
51
 
52
  $earnings_data = array();
53
  $sales_data = array();
55
  if( $dates['range'] == 'today' || $dates['range'] == 'yesterday' ) {
56
  // Hour by hour
57
  $hour = 1;
58
+ $month = $dates['m_start'];
59
  while ( $hour <= 23 ) :
60
 
61
  $sales = edd_get_sales_by_date( $dates['day'], $month, $dates['year'], $hour );
62
  $earnings = edd_get_earnings_by_date( $dates['day'], $month, $dates['year'], $hour );
63
+
64
  $sales_totals += $sales;
65
  $earnings_totals += $earnings;
66
+
67
  $date = mktime( $hour, 0, 0, $month, $dates['day'], $dates['year'] ) * 1000;
68
  $sales_data[] = array( $date, $sales );
69
  $earnings_data[] = array( $date, $earnings );
70
+
71
  $hour++;
72
  endwhile;
73
 
101
  } elseif( $y == $dates['year'] ) {
102
  $month_start = $dates['m_start'];
103
  $month_end = 12;
104
+ } elseif ( $y == $dates['year_end'] ) {
105
+ $month_start = 1;
106
+ $month_end = $dates['m_end'];
107
  } else {
108
  $month_start = 1;
109
  $month_end = 12;
111
 
112
  $i = $month_start;
113
  while ( $i <= $month_end ) :
114
+
115
  if ( $day_by_day ) :
116
+
117
+ if( $i == $month_end ) {
118
+
119
+ $num_of_days = $dates['day_end'];
120
+
121
+ } else {
122
+
123
+ $num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
124
+
125
+ }
126
+
127
+ $d = $dates['day'];
128
+
129
  while ( $d <= $num_of_days ) :
130
+
131
  $sales = edd_get_sales_by_date( $d, $i, $y );
132
  $sales_totals += $sales;
133
 
137
  $date = mktime( 0, 0, 0, $i, $d, $y ) * 1000;
138
  $sales_data[] = array( $date, $sales );
139
  $earnings_data[] = array( $date, $earnings );
140
+ $d++;
141
+
142
  endwhile;
143
+
144
  else :
145
+
146
  $sales = edd_get_sales_by_date( null, $i, $y );
147
  $sales_totals += $sales;
148
 
149
  $earnings = edd_get_earnings_by_date( null, $i, $y );
150
  $earnings_totals += $earnings;
151
 
152
+ if( $i == $month_end ) {
153
+
154
+ $num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
155
+
156
+ } else {
157
+
158
+ $num_of_days = 1;
159
+
160
+ }
161
+
162
+ $date = mktime( 0, 0, 0, $i, $num_of_days, $y ) * 1000;
163
  $sales_data[] = array( $date, $sales );
164
  $earnings_data[] = array( $date, $earnings );
165
+
166
  endif;
167
+
168
  $i++;
169
+
170
  endwhile;
171
 
172
  $y++;
179
  __( 'Sales', 'edd' ) => $sales_data
180
  );
181
 
182
+ // start our own output buffer
183
+ ob_start();
184
  ?>
185
  <div id="edd-dashboard-widgets-wrap">
186
  <div class="metabox-holder" style="padding-top: 0;">
187
  <div class="postbox">
188
  <h3><span><?php _e('Earnings Over Time', 'edd'); ?></span></h3>
189
+
190
  <div class="inside">
191
  <?php
192
  edd_reports_graph_controls();
194
  $graph->set( 'x_mode', 'time' );
195
  $graph->set( 'multiple_y_axes', true );
196
  $graph->display();
197
+
198
+ if( 'this_month' == $dates['range'] ) {
199
+ $estimated = edd_estimated_monthly_stats();
200
+ }
201
  ?>
202
+
203
  <p class="edd_graph_totals"><strong><?php _e( 'Total earnings for period shown: ', 'edd' ); echo edd_currency_filter( edd_format_amount( $earnings_totals ) ); ?></strong></p>
204
  <p class="edd_graph_totals"><strong><?php _e( 'Total sales for period shown: ', 'edd' ); echo edd_format_amount( $sales_totals, false ); ?></strong></p>
205
+
206
+ <?php if( 'this_month' == $dates['range'] ) : ?>
207
+ <p class="edd_graph_totals"><strong><?php _e( 'Estimated monthly earnings: ', 'edd' ); echo edd_currency_filter( edd_format_amount( $estimated['earnings'] ) ); ?></strong></p>
208
+ <p class="edd_graph_totals"><strong><?php _e( 'Estimated monthly sales: ', 'edd' ); echo edd_format_amount( $estimated['sales'], false ); ?></strong></p>
209
+ <?php endif; ?>
210
+
211
+ <?php do_action( 'edd_reports_graph_additional_stats' ); ?>
212
+
213
  </div>
214
  </div>
215
  </div>
216
  </div>
217
  <?php
218
+ // get output buffer contents and end our own buffer
219
+ $output = ob_get_contents();
220
+ ob_end_clean();
221
+
222
+ echo $output;
223
  }
224
 
225
  /**
267
 
268
  $earnings_data = array();
269
  $sales_data = array();
270
+ $stats = new EDD_Payment_Stats;
271
 
272
  if( $dates['range'] == 'today' || $dates['range'] == 'yesterday' ) {
273
+
274
  // Hour by hour
275
+ $month = $dates['m_start'];
276
  $hour = 1;
277
  $minute = 0;
278
  $second = 0;
279
  while ( $hour <= 23 ) :
280
+
281
  if( $hour == 23 ) {
282
  $minute = $second = 59;
283
  }
284
 
285
  $date = mktime( $hour, $minute, $second, $month, $dates['day'], $dates['year'] );
286
  $date_end = mktime( $hour + 1, $minute, $second, $month, $dates['day'], $dates['year'] );
287
+
288
  $sales = $stats->get_sales( $download_id, $date, $date_end );
289
  $sales_totals += $sales;
290
+
291
  $earnings = $stats->get_earnings( $download_id, $date, $date_end );
292
  $earnings_totals += $earnings;
293
+
294
  $sales_data[] = array( $date * 1000, $sales );
295
  $earnings_data[] = array( $date * 1000, $earnings );
296
+
297
  $hour++;
298
  endwhile;
299
 
304
  $day_end = $dates['day_end'];
305
  $month = $dates['m_start'];
306
  while ( $day <= $day_end ) :
307
+
308
  $date = mktime( 0, 0, 0, $month, $day, $dates['year'] );
309
  $date_end = mktime( 0, 0, 0, $month, $day + 1, $dates['year'] );
310
  $sales = $stats->get_sales( $download_id, $date, $date_end );
311
  $sales_totals += $sales;
312
+
313
  $earnings = $stats->get_earnings( $download_id, $date, $date_end );
314
  $earnings_totals += $earnings;
315
+
316
  $sales_data[] = array( $date * 1000, $sales );
317
  $earnings_data[] = array( $date * 1000, $earnings );
318
 
337
 
338
  $i = $month_start;
339
  while ( $i <= $month_end ) :
340
+
341
  if ( $day_by_day ) :
342
+
343
+ if( $i == $month_end ) {
344
+
345
+ $num_of_days = $dates['day_end'];
346
+
347
+ } else {
348
+
349
+ $num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
350
+
351
+ }
352
+
353
+ $d = $dates['day'];
354
  while ( $d <= $num_of_days ) :
355
+
356
  $date = mktime( 0, 0, 0, $i, $d, $y );
357
+ $end_date = mktime( 23, 59, 59, $i, $d, $y );
358
+
359
  $sales = $stats->get_sales( $download_id, $date, $end_date );
360
  $sales_totals += $sales;
361
+
362
  $earnings = $stats->get_earnings( $download_id, $date, $end_date );
363
  $earnings_totals += $earnings;
364
+
365
  $sales_data[] = array( $date * 1000, $sales );
366
  $earnings_data[] = array( $date * 1000, $earnings );
367
  $d++;
368
+
369
  endwhile;
370
+
371
  else :
372
+
373
+ $num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
374
+
375
+ $date = mktime( 0, 0, 0, $i, 1, $y );
376
+ $end_date = mktime( 23, 59, 59, $i, $num_of_days, $y );
377
+
378
  $sales = $stats->get_sales( $download_id, $date, $end_date );
379
  $sales_totals += $sales;
380
+
381
  $earnings = $stats->get_earnings( $download_id, $date, $end_date );
382
  $earnings_totals += $earnings;
383
+
384
  $sales_data[] = array( $date * 1000, $sales );
385
  $earnings_data[] = array( $date * 1000, $earnings );
386
  endif;
387
+
388
  $i++;
389
+
390
  endwhile;
391
 
392
  $y++;
399
  __( 'Sales', 'edd' ) => $sales_data
400
  );
401
 
402
+ ?>
403
  <div class="metabox-holder" style="padding-top: 0;">
404
  <div class="postbox">
405
  <h3><span><?php printf( __('Earnings Over Time for %s', 'edd' ), get_the_title( $download_id ) ); ?></span></h3>
406
 
407
  <div class="inside">
408
+ <?php
409
+ edd_reports_graph_controls();
410
  $graph = new EDD_Graph( $data );
411
  $graph->set( 'x_mode', 'time' );
412
  $graph->set( 'multiple_y_axes', true );
414
  ?>
415
  <p class="edd_graph_totals"><strong><?php _e( 'Total earnings for period shown: ', 'edd' ); echo edd_currency_filter( edd_format_amount( $earnings_totals ) ); ?></strong></p>
416
  <p class="edd_graph_totals"><strong><?php _e( 'Total sales for period shown: ', 'edd' ); echo $sales_totals; ?></strong></p>
417
+ <p class="edd_graph_totals"><strong><?php printf( __( 'Average monthly earnings: %s', 'edd' ), edd_currency_filter( edd_format_amount( edd_get_average_monthly_download_earnings( $download_id ) ) ) ); ?>
418
  <p class="edd_graph_totals"><strong><?php printf( __( 'Average monthly sales: %s', 'edd' ), number_format( edd_get_average_monthly_download_sales( $download_id ), 0 ) ); ?>
419
  </div>
420
  </div>
444
  'other' => __( 'Custom', 'edd' )
445
  ) );
446
 
447
+ $dates = edd_get_report_dates();
 
448
  $display = $dates['range'] == 'other' ? '' : 'style="display:none;"';
449
+ $view = edd_get_reporting_view();
450
 
451
+ if( empty( $dates['day_end'] ) ) {
452
+ $dates['day_end'] = cal_days_in_month( CAL_GREGORIAN, date( 'n' ), date( 'Y' ) );
453
+ }
454
 
455
  ?>
456
  <form id="edd-graphs-filter" method="get">
457
  <div class="tablenav top">
458
  <div class="alignleft actions">
459
 
460
+ <input type="hidden" name="post_type" value="download"/>
461
+ <input type="hidden" name="page" value="edd-reports"/>
462
+ <input type="hidden" name="view" value="<?php echo esc_attr( $view ); ?>"/>
463
 
464
+ <?php if( isset( $_GET['download-id'] ) ) : ?>
465
+ <input type="hidden" name="download-id" value="<?php echo absint( $_GET['download-id'] ); ?>"/>
466
+ <?php endif; ?>
467
 
468
+ <select id="edd-graphs-date-options" name="range">
469
+ <?php foreach ( $date_options as $key => $option ) : ?>
470
+ <option value="<?php echo esc_attr( $key ); ?>"<?php selected( $key, $dates['range'] ); ?>><?php echo esc_html( $option ); ?></option>
471
+ <?php endforeach; ?>
472
+ </select>
473
+ <div id="edd-date-range-options" <?php echo $display; ?>>
 
 
 
474
  <span><?php _e( 'From', 'edd' ); ?>&nbsp;</span>
475
+ <select id="edd-graphs-month-start" name="m_start">
476
+ <?php for ( $i = 1; $i <= 12; $i++ ) : ?>
477
+ <option value="<?php echo absint( $i ); ?>" <?php selected( $i, $dates['m_start'] ); ?>><?php echo edd_month_num_to_name( $i ); ?></option>
478
+ <?php endfor; ?>
479
+ </select>
480
+ <select id="edd-graphs-day-start" name="day">
481
+ <?php for ( $i = 1; $i <= 31; $i++ ) : ?>
482
+ <option value="<?php echo absint( $i ); ?>" <?php selected( $i, $dates['day'] ); ?>><?php echo $i; ?></option>
483
+ <?php endfor; ?>
484
+ </select>
485
+ <select id="edd-graphs-year-start" name="year">
486
+ <?php for ( $i = 2007; $i <= date( 'Y' ); $i++ ) : ?>
487
+ <option value="<?php echo absint( $i ); ?>" <?php selected( $i, $dates['year'] ); ?>><?php echo $i; ?></option>
488
+ <?php endfor; ?>
489
+ </select>
490
+ <span><?php _e( 'To', 'edd' ); ?>&nbsp;</span>
491
+ <select id="edd-graphs-month-end" name="m_end">
492
+ <?php for ( $i = 1; $i <= 12; $i++ ) : ?>
493
+ <option value="<?php echo absint( $i ); ?>" <?php selected( $i, $dates['m_end'] ); ?>><?php echo edd_month_num_to_name( $i ); ?></option>
494
+ <?php endfor; ?>
495
+ </select>
496
+ <select id="edd-graphs-day-end" name="day_end">
497
+ <?php for ( $i = 1; $i <= 31; $i++ ) : ?>
498
+ <option value="<?php echo absint( $i ); ?>" <?php selected( $i, $dates['day_end'] ); ?>><?php echo $i; ?></option>
499
+ <?php endfor; ?>
500
+ </select>
501
+ <select id="edd-graphs-year-end" name="year_end">
502
+ <?php for ( $i = 2007; $i <= date( 'Y' ); $i++ ) : ?>
503
+ <option value="<?php echo absint( $i ); ?>" <?php selected( $i, $dates['year_end'] ); ?>><?php echo $i; ?></option>
504
+ <?php endfor; ?>
505
+ </select>
506
+ </div>
507
+
508
+ <input type="hidden" name="edd_action" value="filter_reports" />
509
+ <input type="submit" class="button-secondary" value="<?php _e( 'Filter', 'edd' ); ?>"/>
510
  </div>
511
  </div>
512
  </form>
520
  * selected date-range (if any)
521
  *
522
  * @since 1.3
523
+ * @return array
524
  */
525
  function edd_get_report_dates() {
526
  $dates = array();
528
  $current_time = current_time( 'timestamp' );
529
 
530
  $dates['range'] = isset( $_GET['range'] ) ? $_GET['range'] : 'this_month';
 
 
 
531
  $dates['year'] = isset( $_GET['year'] ) ? $_GET['year'] : date( 'Y' );
532
  $dates['year_end'] = isset( $_GET['year_end'] )? $_GET['year_end']: date( 'Y' );
533
+ $dates['m_start'] = isset( $_GET['m_start'] ) ? $_GET['m_start'] : 1;
534
+ $dates['m_end'] = isset( $_GET['m_end'] ) ? $_GET['m_end'] : 12;
535
+ $dates['day'] = isset( $_GET['day'] ) ? $_GET['day'] : 1;
536
+ $dates['day_end'] = isset( $_GET['day_end'] ) ? $_GET['day_end'] : cal_days_in_month( CAL_GREGORIAN, $dates['m_end'], $dates['year'] );
537
+
538
  // Modify dates based on predefined ranges
539
  switch ( $dates['range'] ) :
540
 
541
  case 'this_month' :
542
+ $dates['m_start'] = date( 'n', $current_time );
543
+ $dates['m_end'] = date( 'n', $current_time );
544
+ $dates['day'] = 1;
545
+ $dates['day_end'] = cal_days_in_month( CAL_GREGORIAN, $dates['m_end'], $dates['year'] );
546
+ $dates['year'] = date( 'Y' );
547
+ $dates['year_end'] = date( 'Y' );
548
  break;
549
 
550
  case 'last_month' :
558
  $dates['m_end'] = date( 'n' ) - 1;
559
  $dates['year_end']= $dates['year'];
560
  }
561
+ $dates['day_end'] = cal_days_in_month( CAL_GREGORIAN, $dates['m_end'], $dates['year'] );
562
  break;
563
 
564
  case 'today' :
569
  break;
570
 
571
  case 'yesterday' :
572
+
573
+ $year = date( 'Y', $current_time );
574
+ $month = date( 'n', $current_time );
575
+ $day = date( 'd', $current_time );
576
+
577
+ if ( $month == 1 && $day == 1 ) {
578
+
579
+ $year -= 1;
580
+ $month = 12;
581
+ $day = cal_days_in_month( CAL_GREGORIAN, $month, $year );
582
+
583
+ } elseif ( $month > 1 && $day == 1 ) {
584
+
585
+ $month -= 1;
586
+ $day = cal_days_in_month( CAL_GREGORIAN, $month, $year );
587
+
588
+ } else {
589
+
590
+ $day -= 1;
591
+
592
+ }
593
+
594
+ $dates['day'] = $day;
595
+ $dates['m_start'] = $month;
596
+ $dates['m_end'] = $month;
597
+ $dates['year'] = $year;
598
+ $dates['year_end'] = $year;
599
  break;
600
 
601
  case 'this_week' :
includes/admin/reporting/logs.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
@@ -21,6 +21,11 @@ if ( ! defined( 'ABSPATH' ) ) exit;
21
  * @return void
22
  */
23
  function edd_logs_view_sales() {
 
 
 
 
 
24
  include( dirname( __FILE__ ) . '/class-sales-logs-list-table.php' );
25
 
26
  $logs_table = new EDD_Sales_Log_Table();
@@ -40,6 +45,11 @@ add_action( 'edd_logs_view_sales', 'edd_logs_view_sales' );
40
  * @return void
41
  */
42
  function edd_logs_view_file_downloads() {
 
 
 
 
 
43
  include( dirname( __FILE__ ) . '/class-file-downloads-logs-list-table.php' );
44
 
45
  $logs_table = new EDD_File_Downloads_Log_Table();
@@ -71,6 +81,11 @@ add_action( 'edd_logs_view_file_downloads', 'edd_logs_view_file_downloads' );
71
  * @return void
72
  */
73
  function edd_logs_view_gateway_errors() {
 
 
 
 
 
74
  include( dirname( __FILE__ ) . '/class-gateway-error-logs-list-table.php' );
75
 
76
  $logs_table = new EDD_Gateway_Error_Log_Table();
@@ -90,6 +105,11 @@ add_action( 'edd_logs_view_gateway_errors', 'edd_logs_view_gateway_errors' );
90
  */
91
 
92
  function edd_logs_view_api_requests() {
 
 
 
 
 
93
  include( dirname( __FILE__ ) . '/class-api-requests-logs-list-table.php' );
94
 
95
  $logs_table = new EDD_API_Request_Log_Table();
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
21
  * @return void
22
  */
23
  function edd_logs_view_sales() {
24
+
25
+ if( ! current_user_can( 'view_shop_reports' ) ) {
26
+ return;
27
+ }
28
+
29
  include( dirname( __FILE__ ) . '/class-sales-logs-list-table.php' );
30
 
31
  $logs_table = new EDD_Sales_Log_Table();
45
  * @return void
46
  */
47
  function edd_logs_view_file_downloads() {
48
+
49
+ if( ! current_user_can( 'view_shop_reports' ) ) {
50
+ return;
51
+ }
52
+
53
  include( dirname( __FILE__ ) . '/class-file-downloads-logs-list-table.php' );
54
 
55
  $logs_table = new EDD_File_Downloads_Log_Table();
81
  * @return void
82
  */
83
  function edd_logs_view_gateway_errors() {
84
+
85
+ if( ! current_user_can( 'view_shop_reports' ) ) {
86
+ return;
87
+ }
88
+
89
  include( dirname( __FILE__ ) . '/class-gateway-error-logs-list-table.php' );
90
 
91
  $logs_table = new EDD_Gateway_Error_Log_Table();
105
  */
106
 
107
  function edd_logs_view_api_requests() {
108
+
109
+ if( ! current_user_can( 'view_shop_reports' ) ) {
110
+ return;
111
+ }
112
+
113
  include( dirname( __FILE__ ) . '/class-api-requests-logs-list-table.php' );
114
 
115
  $logs_table = new EDD_API_Request_Log_Table();
includes/admin/reporting/pdf-reports.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @author Sunny Ratilal
9
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
10
  * @since 1.1.4.0
@@ -24,118 +24,122 @@ if ( ! defined( 'ABSPATH' ) ) exit;
24
  * @author Sunny Ratilal
25
  */
26
  function edd_generate_pdf( $data ) {
27
- $edd_pdf_reports_nonce = $_GET['_wpnonce'];
28
 
29
- if ( wp_verify_nonce( $edd_pdf_reports_nonce, 'edd_generate_pdf' ) ) {
30
- require_once EDD_PLUGIN_DIR . '/includes/libraries/fpdf/fpdf.php';
31
- require_once EDD_PLUGIN_DIR . '/includes/libraries/fpdf/edd_pdf.php';
32
-
33
- $daterange = date_i18n( get_option( 'date_format' ), mktime( 0, 0, 0, 1, 1, date( 'Y' ) ) ) . ' ' . utf8_decode( __( 'to', 'edd' ) ) . ' ' . date_i18n( get_option( 'date_format' ) );
34
 
35
- $pdf = new edd_pdf();
36
- $pdf->AddPage( 'L', 'A4' );
 
37
 
38
- $pdf->SetTitle( utf8_decode( __( 'Sales and earnings reports for the current year for all products', 'edd') ) );
39
- $pdf->SetAuthor( utf8_decode( __( 'Easy Digital Downloads', 'edd' ) ) );
40
- $pdf->SetCreator( utf8_decode( __( 'Easy Digital Downloads', 'edd' ) ) );
41
 
42
- $pdf->Image( EDD_PLUGIN_URL . 'assets/images/edd-logo.png', 205, 10 );
43
 
44
- $pdf->SetMargins( 8, 8, 8 );
45
- $pdf->SetX( 8 );
46
 
47
- $pdf->SetFont( 'Helvetica', '', 16 );
48
- $pdf->SetTextColor( 50, 50, 50 );
49
- $pdf->Cell( 0, 3, utf8_decode( __( 'Sales and earnings reports for the current year for all products', 'edd' ) ), 0, 2, 'L', false );
50
 
51
- $pdf->SetFont( 'Helvetica', '', 13 );
52
- $pdf->Ln();
53
- $pdf->SetTextColor( 150, 150, 150 );
54
- $pdf->Cell( 0, 6, utf8_decode( __( 'Date Range: ', 'edd' ) ) . $daterange, 0, 2, 'L', false );
55
- $pdf->Ln();
56
- $pdf->SetTextColor( 50, 50, 50 );
57
- $pdf->SetFont( 'Helvetica', '', 14 );
58
- $pdf->Cell( 0, 10, utf8_decode( __( 'Table View', 'edd' ) ), 0, 2, 'L', false );
59
- $pdf->SetFont( 'Helvetica', '', 12 );
60
 
61
- $pdf->SetFillColor( 238, 238, 238 );
62
- $pdf->Cell( 70, 6, utf8_decode( __( 'Product Name', 'edd' ) ), 1, 0, 'L', true );
63
- $pdf->Cell( 30, 6, utf8_decode( __( 'Price', 'edd' ) ), 1, 0, 'L', true );
64
- $pdf->Cell( 50, 6, utf8_decode( __( 'Categories', 'edd' ) ), 1, 0, 'L', true );
65
- $pdf->Cell( 50, 6, utf8_decode( __( 'Tags', 'edd' ) ), 1, 0, 'L', true );
66
- $pdf->Cell( 45, 6, utf8_decode( __( 'Number of Sales', 'edd' ) ), 1, 0, 'L', true );
67
- $pdf->Cell( 35, 6, utf8_decode( __( 'Earnings to Date', 'edd' ) ), 1, 1, 'L', true );
68
 
69
- $year = date('Y');
70
- $downloads = get_posts( array( 'post_type' => 'download', 'year' => $year, 'posts_per_page' => -1 ) );
 
71
 
72
- if ( $downloads ):
73
- $pdf->SetWidths( array( 70, 30, 50, 50, 45, 35 ) );
 
 
 
 
 
 
 
74
 
75
- foreach ( $downloads as $download ):
76
- $pdf->SetFillColor( 255, 255, 255 );
 
 
 
 
 
77
 
78
- $title = utf8_decode( get_the_title( $download->ID ) );
 
79
 
80
- if ( edd_has_variable_prices( $download->ID ) ) {
 
81
 
82
- $prices = edd_get_variable_prices( $download->ID );
 
83
 
84
- $first = $prices[0]['amount'];
85
- $last = array_pop( $prices );
86
- $last = $last['amount'];
87
 
88
- if ( $first < $last ) {
89
- $min = $first;
90
- $max = $last;
91
- } else {
92
- $min = $last;
93
- $max = $first;
94
- }
95
 
96
- $price = html_entity_decode( edd_currency_filter( edd_format_amount( $min ) ) . ' - ' . edd_currency_filter( edd_format_amount( $max ) ) );
97
- } else {
98
- $price = html_entity_decode( edd_currency_filter( edd_get_download_price( $download->ID ) ) );
99
- }
100
 
101
- $categories = get_the_term_list( $download->ID, 'download_category', '', ', ', '' );
102
- $categories = $categories ? strip_tags( $categories ) : '';
 
103
 
104
- $tags = get_the_term_list( $download->ID, 'download_tag', '', ', ', '' );
105
- $tags = $tags ? strip_tags( $tags ) : '';
106
-
107
- $sales = edd_get_download_sales_stats( $download->ID );
108
- $link = get_permalink( $download->ID );
109
- $earnings = html_entity_decode ( edd_currency_filter( edd_get_download_earnings_stats( $download->ID ) ) );
110
-
111
- if( function_exists( 'iconv' ) ) {
112
- // Ensure characters like euro; are properly converted. See GithuB issue #472 and #1570
113
- $price = iconv('UTF-8', 'windows-1252', utf8_encode( $price ) );
114
- $earnings = iconv('UTF-8', 'windows-1252', utf8_encode( $earnings ) );
115
  }
116
 
117
- $pdf->Row( array( $title, $price, $categories, $tags, $sales, $earnings ) );
118
- endforeach;
119
- else:
120
- $pdf->SetWidths( array( 280 ) );
121
- $title = utf8_decode( sprintf( __( 'No %s found.', 'edd' ), edd_get_label_plural() ) );
122
- $pdf->Row( array( $title ) );
123
- endif;
124
-
125
- $pdf->Ln();
126
- $pdf->SetTextColor( 50, 50, 50 );
127
- $pdf->SetFont( 'Helvetica', '', 14 );
128
- $pdf->Cell( 0, 10, utf8_decode( __('Graph View', 'edd') ), 0, 2, 'L', false );
129
- $pdf->SetFont( 'Helvetica', '', 12 );
130
-
131
- $image = html_entity_decode( urldecode( edd_draw_chart_image() ) );
132
- $image = str_replace( ' ', '%20', $image );
133
-
134
- $pdf->SetX( 25 );
135
- $pdf->Image( $image .'&file=.png' );
136
- $pdf->Ln( 7 );
137
- $pdf->Output( 'edd-report-' . date_i18n('Y-m-d') . '.pdf', 'D' );
138
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  }
140
  add_action( 'edd_generate_pdf', 'edd_generate_pdf' );
141
 
@@ -181,9 +185,7 @@ function edd_draw_chart_image() {
181
  $i++;
182
  }
183
 
184
- $min_earnings = 0;
185
  $max_earnings = max( $earnings_array );
186
- $earnings_scale = round( $max_earnings, -1 );
187
 
188
  $data = new GoogleChartData( array(
189
  $earnings_array[0],
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @author Sunny Ratilal
9
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
10
  * @since 1.1.4.0
24
  * @author Sunny Ratilal
25
  */
26
  function edd_generate_pdf( $data ) {
 
27
 
28
+ if( ! current_user_can( 'view_shop_reports' ) ) {
29
+ wp_die( __( 'You do not have permission to generate PDF sales reports', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
30
+ }
 
 
31
 
32
+ if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'edd_generate_pdf' ) ) {
33
+ wp_die( __( 'Nonce verification failed', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
34
+ }
35
 
36
+ require_once EDD_PLUGIN_DIR . '/includes/libraries/fpdf/fpdf.php';
37
+ require_once EDD_PLUGIN_DIR . '/includes/libraries/fpdf/edd_pdf.php';
 
38
 
39
+ $daterange = date_i18n( get_option( 'date_format' ), mktime( 0, 0, 0, 1, 1, date( 'Y' ) ) ) . ' ' . utf8_decode( __( 'to', 'edd' ) ) . ' ' . date_i18n( get_option( 'date_format' ) );
40
 
41
+ $pdf = new edd_pdf();
42
+ $pdf->AddPage( 'L', 'A4' );
43
 
44
+ $pdf->SetTitle( utf8_decode( __( 'Sales and earnings reports for the current year for all products', 'edd') ) );
45
+ $pdf->SetAuthor( utf8_decode( __( 'Easy Digital Downloads', 'edd' ) ) );
46
+ $pdf->SetCreator( utf8_decode( __( 'Easy Digital Downloads', 'edd' ) ) );
47
 
48
+ $pdf->Image( EDD_PLUGIN_URL . 'assets/images/edd-logo.png', 205, 10 );
 
 
 
 
 
 
 
 
49
 
50
+ $pdf->SetMargins( 8, 8, 8 );
51
+ $pdf->SetX( 8 );
 
 
 
 
 
52
 
53
+ $pdf->SetFont( 'Helvetica', '', 16 );
54
+ $pdf->SetTextColor( 50, 50, 50 );
55
+ $pdf->Cell( 0, 3, utf8_decode( __( 'Sales and earnings reports for the current year for all products', 'edd' ) ), 0, 2, 'L', false );
56
 
57
+ $pdf->SetFont( 'Helvetica', '', 13 );
58
+ $pdf->Ln();
59
+ $pdf->SetTextColor( 150, 150, 150 );
60
+ $pdf->Cell( 0, 6, utf8_decode( __( 'Date Range: ', 'edd' ) ) . $daterange, 0, 2, 'L', false );
61
+ $pdf->Ln();
62
+ $pdf->SetTextColor( 50, 50, 50 );
63
+ $pdf->SetFont( 'Helvetica', '', 14 );
64
+ $pdf->Cell( 0, 10, utf8_decode( __( 'Table View', 'edd' ) ), 0, 2, 'L', false );
65
+ $pdf->SetFont( 'Helvetica', '', 12 );
66
 
67
+ $pdf->SetFillColor( 238, 238, 238 );
68
+ $pdf->Cell( 70, 6, utf8_decode( __( 'Product Name', 'edd' ) ), 1, 0, 'L', true );
69
+ $pdf->Cell( 30, 6, utf8_decode( __( 'Price', 'edd' ) ), 1, 0, 'L', true );
70
+ $pdf->Cell( 50, 6, utf8_decode( __( 'Categories', 'edd' ) ), 1, 0, 'L', true );
71
+ $pdf->Cell( 50, 6, utf8_decode( __( 'Tags', 'edd' ) ), 1, 0, 'L', true );
72
+ $pdf->Cell( 45, 6, utf8_decode( __( 'Number of Sales', 'edd' ) ), 1, 0, 'L', true );
73
+ $pdf->Cell( 35, 6, utf8_decode( __( 'Earnings to Date', 'edd' ) ), 1, 1, 'L', true );
74
 
75
+ $year = date('Y');
76
+ $downloads = get_posts( array( 'post_type' => 'download', 'year' => $year, 'posts_per_page' => -1 ) );
77
 
78
+ if ( $downloads ):
79
+ $pdf->SetWidths( array( 70, 30, 50, 50, 45, 35 ) );
80
 
81
+ foreach ( $downloads as $download ):
82
+ $pdf->SetFillColor( 255, 255, 255 );
83
 
84
+ $title = utf8_decode( get_the_title( $download->ID ) );
 
 
85
 
86
+ if ( edd_has_variable_prices( $download->ID ) ) {
 
 
 
 
 
 
87
 
88
+ $prices = edd_get_variable_prices( $download->ID );
 
 
 
89
 
90
+ $first = $prices[0]['amount'];
91
+ $last = array_pop( $prices );
92
+ $last = $last['amount'];
93
 
94
+ if ( $first < $last ) {
95
+ $min = $first;
96
+ $max = $last;
97
+ } else {
98
+ $min = $last;
99
+ $max = $first;
 
 
 
 
 
100
  }
101
 
102
+ $price = html_entity_decode( edd_currency_filter( edd_format_amount( $min ) ) . ' - ' . edd_currency_filter( edd_format_amount( $max ) ) );
103
+ } else {
104
+ $price = html_entity_decode( edd_currency_filter( edd_get_download_price( $download->ID ) ) );
105
+ }
106
+
107
+ $categories = get_the_term_list( $download->ID, 'download_category', '', ', ', '' );
108
+ $categories = $categories ? strip_tags( $categories ) : '';
109
+
110
+ $tags = get_the_term_list( $download->ID, 'download_tag', '', ', ', '' );
111
+ $tags = $tags ? strip_tags( $tags ) : '';
112
+
113
+ $sales = edd_get_download_sales_stats( $download->ID );
114
+ $earnings = html_entity_decode ( edd_currency_filter( edd_get_download_earnings_stats( $download->ID ) ) );
115
+
116
+ if( function_exists( 'iconv' ) ) {
117
+ // Ensure characters like euro; are properly converted. See GithuB issue #472 and #1570
118
+ $price = iconv('UTF-8', 'windows-1252', utf8_encode( $price ) );
119
+ $earnings = iconv('UTF-8', 'windows-1252', utf8_encode( $earnings ) );
120
+ }
121
+
122
+ $pdf->Row( array( $title, $price, $categories, $tags, $sales, $earnings ) );
123
+ endforeach;
124
+ else:
125
+ $pdf->SetWidths( array( 280 ) );
126
+ $title = utf8_decode( sprintf( __( 'No %s found.', 'edd' ), edd_get_label_plural() ) );
127
+ $pdf->Row( array( $title ) );
128
+ endif;
129
+
130
+ $pdf->Ln();
131
+ $pdf->SetTextColor( 50, 50, 50 );
132
+ $pdf->SetFont( 'Helvetica', '', 14 );
133
+ $pdf->Cell( 0, 10, utf8_decode( __('Graph View', 'edd') ), 0, 2, 'L', false );
134
+ $pdf->SetFont( 'Helvetica', '', 12 );
135
+
136
+ $image = html_entity_decode( urldecode( edd_draw_chart_image() ) );
137
+ $image = str_replace( ' ', '%20', $image );
138
+
139
+ $pdf->SetX( 25 );
140
+ $pdf->Image( $image .'&file=.png' );
141
+ $pdf->Ln( 7 );
142
+ $pdf->Output( apply_filters( 'edd_sales_earnings_pdf_export_filename', 'edd-report-' . date_i18n('Y-m-d') ) . '.pdf', 'D' );
143
  }
144
  add_action( 'edd_generate_pdf', 'edd_generate_pdf' );
145
 
185
  $i++;
186
  }
187
 
 
188
  $max_earnings = max( $earnings_array );
 
189
 
190
  $data = new GoogleChartData( array(
191
  $earnings_array[0],
includes/admin/reporting/reports.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -18,14 +18,11 @@ if ( ! defined( 'ABSPATH' ) ) exit;
18
  * Renders the reports page contents.
19
  *
20
  * @since 1.0
21
- * @global $edd_options Array of all the EDD Options
22
  * @return void
23
  */
24
  function edd_reports_page() {
25
- global $edd_options;
26
-
27
  $current_page = admin_url( 'edit.php?post_type=download&page=edd-reports' );
28
- $active_tab = isset( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'reports';
29
  ?>
30
  <div class="wrap">
31
  <h2 class="nav-tab-wrapper">
@@ -56,7 +53,6 @@ function edd_reports_default_views() {
56
  $views = array(
57
  'earnings' => __( 'Earnings', 'edd' ),
58
  'downloads' => edd_get_label_plural(),
59
- 'customers' => __( 'Customers', 'edd' ),
60
  'gateways' => __( 'Payment Methods', 'edd' ),
61
  'taxes' => __( 'Taxes', 'edd' )
62
  );
@@ -70,15 +66,15 @@ function edd_reports_default_views() {
70
  * Default Report Views
71
  *
72
  * Checks the $_GET['view'] parameter to ensure it exists within the default allowed views.
73
- *
74
  * @param string $default Default view to use.
75
- *
76
  * @since 1.9.6
77
  * @return string $view Report View
78
- *
79
  */
80
  function edd_get_reporting_view( $default = 'earnings' ) {
81
-
82
  if ( ! isset( $_GET['view'] ) || ! in_array( $_GET['view'], array_keys( edd_reports_default_views() ) ) ) {
83
  $view = $default;
84
  } else {
@@ -95,13 +91,19 @@ function edd_get_reporting_view( $default = 'earnings' ) {
95
  * @return void
96
  */
97
  function edd_reports_tab_reports() {
 
 
 
 
 
98
  $current_view = 'earnings';
99
  $views = edd_reports_default_views();
100
 
101
- if ( isset( $_GET[ 'view' ] ) && array_key_exists( $_GET[ 'view' ], $views ) )
102
- $current_view = $_GET[ 'view' ];
103
 
104
  do_action( 'edd_reports_view_' . $current_view );
 
105
  }
106
  add_action( 'edd_reports_tab_reports', 'edd_reports_tab_reports' );
107
 
@@ -112,8 +114,13 @@ add_action( 'edd_reports_tab_reports', 'edd_reports_tab_reports' );
112
  * @return void
113
  */
114
  function edd_report_views() {
 
 
 
 
 
115
  $views = edd_reports_default_views();
116
- $current_view = isset( $_GET[ 'view' ] ) ? $_GET[ 'view' ] : 'earnings';
117
  ?>
118
  <form id="edd-reports-filter" method="get">
119
  <select id="edd-reports-view" name="view">
@@ -142,7 +149,11 @@ function edd_report_views() {
142
  * @return void
143
  */
144
  function edd_reports_downloads_table() {
145
-
 
 
 
 
146
  if( isset( $_GET['download-id'] ) )
147
  return;
148
 
@@ -161,6 +172,11 @@ add_action( 'edd_reports_view_downloads', 'edd_reports_downloads_table' );
161
  * @return void
162
  */
163
  function edd_reports_download_details() {
 
 
 
 
 
164
  if( ! isset( $_GET['download-id'] ) )
165
  return;
166
  ?>
@@ -177,37 +193,6 @@ function edd_reports_download_details() {
177
  }
178
  add_action( 'edd_reports_view_downloads', 'edd_reports_download_details' );
179
 
180
- /**
181
- * Renders the Reports Customers Table
182
- *
183
- * @since 1.3
184
- * @uses EDD_Customer_Reports_Table::prepare_items()
185
- * @uses EDD_Customer_Reports_Table::display()
186
- * @return void
187
- */
188
- function edd_reports_customers_table() {
189
- include( dirname( __FILE__ ) . '/class-customer-reports-table.php' );
190
-
191
- $downloads_table = new EDD_Customer_Reports_Table();
192
- $downloads_table->prepare_items();
193
- ?>
194
- <div class="wrap">
195
- <?php do_action( 'edd_logs_file_downloads_top' ); ?>
196
- <form id="edd-customers-filter" method="get" action="<?php echo admin_url( 'edit.php?post_type=download&page=edd-reports&view=customers' ); ?>">
197
- <?php
198
- $downloads_table->search_box( __( 'Search', 'edd' ), 'edd-customers' );
199
- $downloads_table->display();
200
- ?>
201
- <input type="hidden" name="post_type" value="download" />
202
- <input type="hidden" name="page" value="edd-reports" />
203
- <input type="hidden" name="view" value="customers" />
204
- </form>
205
- <?php do_action( 'edd_logs_file_downloads_bottom' ); ?>
206
- </div>
207
- <?php
208
- }
209
- add_action( 'edd_reports_view_customers', 'edd_reports_customers_table' );
210
-
211
 
212
  /**
213
  * Renders the Gateways Table
@@ -218,6 +203,11 @@ add_action( 'edd_reports_view_customers', 'edd_reports_customers_table' );
218
  * @return void
219
  */
220
  function edd_reports_gateways_table() {
 
 
 
 
 
221
  include( dirname( __FILE__ ) . '/class-gateways-reports-table.php' );
222
 
223
  $downloads_table = new EDD_Gateawy_Reports_Table();
@@ -234,6 +224,10 @@ add_action( 'edd_reports_view_gateways', 'edd_reports_gateways_table' );
234
  * @return void
235
  */
236
  function edd_reports_earnings() {
 
 
 
 
237
  ?>
238
  <div class="tablenav top">
239
  <div class="alignleft actions"><?php edd_report_views(); ?></div>
@@ -250,6 +244,11 @@ add_action( 'edd_reports_view_earnings', 'edd_reports_earnings' );
250
  * @return void
251
  */
252
  function edd_reports_taxes() {
 
 
 
 
 
253
  $year = isset( $_GET['year'] ) ? absint( $_GET['year'] ) : date( 'Y' );
254
  ?>
255
  <div class="tablenav top">
@@ -287,23 +286,27 @@ add_action( 'edd_reports_view_taxes', 'edd_reports_taxes' );
287
  * @return void
288
  */
289
  function edd_reports_tab_export() {
 
 
 
 
290
  ?>
291
  <div id="edd-dashboard-widgets-wrap">
292
  <div class="metabox-holder">
293
  <div id="post-body">
294
  <div id="post-body-content">
295
-
296
  <?php do_action( 'edd_reports_tab_export_content_top' ); ?>
297
-
298
- <div class="postbox">
299
  <h3><span><?php _e( 'Export PDF of Sales and Earnings', 'edd' ); ?></span></h3>
300
  <div class="inside">
301
  <p><?php _e( 'Download a PDF of Sales and Earnings reports for all products for the current year.', 'edd' ); ?> <?php _e( 'Date range reports will be coming soon.', 'edd' ); ?></p>
302
  <p><a class="button" href="<?php echo wp_nonce_url( add_query_arg( array( 'edd-action' => 'generate_pdf' ) ), 'edd_generate_pdf' ); ?>"><?php _e( 'Generate PDF', 'edd' ); ?></a></p>
303
  </div><!-- .inside -->
304
  </div><!-- .postbox -->
305
-
306
- <div class="postbox">
307
  <h3><span><?php _e( 'Export Earnings and Sales Stats', 'edd' ); ?></span></h3>
308
  <div class="inside">
309
  <p><?php _e( 'Download a CSV of earnings and sales over time.', 'edd' ); ?></p>
@@ -321,7 +324,7 @@ function edd_reports_tab_export() {
321
  </div><!-- .inside -->
322
  </div><!-- .postbox -->
323
 
324
- <div class="postbox">
325
  <h3><span><?php _e('Export Payment History', 'edd'); ?></span></h3>
326
  <div class="inside">
327
  <p><?php _e( 'Download a CSV of all payments recorded.', 'edd' ); ?></p>
@@ -344,8 +347,8 @@ function edd_reports_tab_export() {
344
  </p>
345
  </div><!-- .inside -->
346
  </div><!-- .postbox -->
347
-
348
- <div class="postbox">
349
  <h3><span><?php _e('Export Customers in CSV', 'edd'); ?></span></h3>
350
  <div class="inside">
351
  <p><?php _e( 'Download a CSV of all customer emails. Optionally export only customers that have purchased a particular product. Note, if you have a large number of customers, exporting the purchase stats may fail.', 'edd' ); ?></p>
@@ -373,8 +376,8 @@ function edd_reports_tab_export() {
373
  </p>
374
  </div><!-- .inside -->
375
  </div><!-- .postbox -->
376
-
377
- <div class="postbox">
378
  <h3><span><?php _e('Export Download History in CSV', 'edd'); ?></span></h3>
379
  <div class="inside">
380
  <p><?php _e( 'Download a CSV of all file downloads for a specific month and year.', 'edd' ); ?></p>
@@ -388,9 +391,9 @@ function edd_reports_tab_export() {
388
  </p>
389
  </div><!-- .inside -->
390
  </div><!-- .postbox -->
391
-
392
  <?php do_action( 'edd_reports_tab_export_content_bottom' ); ?>
393
-
394
  </div><!-- .post-body-content -->
395
  </div><!-- .post-body -->
396
  </div><!-- .metabox-holder -->
@@ -406,13 +409,18 @@ add_action( 'edd_reports_tab_export', 'edd_reports_tab_export' );
406
  * @return void
407
  */
408
  function edd_reports_tab_logs() {
 
 
 
 
 
409
  require( EDD_PLUGIN_DIR . 'includes/admin/reporting/logs.php' );
410
 
411
  $current_view = 'file_downloads';
412
  $log_views = edd_log_default_views();
413
 
414
- if ( isset( $_GET[ 'view' ] ) && array_key_exists( $_GET[ 'view' ], $log_views ) )
415
- $current_view = $_GET[ 'view' ];
416
 
417
  do_action( 'edd_logs_view_' . $current_view );
418
  }
@@ -425,25 +433,32 @@ add_action( 'edd_reports_tab_logs', 'edd_reports_tab_logs' );
425
  * @return array
426
  */
427
  function edd_estimated_monthly_stats() {
 
428
  $estimated = get_transient( 'edd_estimated_monthly_stats' );
429
 
430
  if ( false === $estimated ) {
 
431
  $estimated = array(
432
  'earnings' => 0,
433
  'sales' => 0
434
  );
435
 
436
- $products = get_posts( array( 'post_type' => 'download', 'posts_per_page' => -1, 'fields' => 'ids' ) );
437
- if ( $products ) {
438
- foreach ( $products as $download ) {
439
- $estimated['earnings'] += edd_get_average_monthly_download_earnings( $download );
440
- $estimated['sales'] += number_format( edd_get_average_monthly_download_sales( $download ), 0 );
441
- }
442
- }
 
 
 
 
 
443
 
444
  // Cache for one day
445
- set_transient( 'edd_estimated_monthly_stats', serialize( $estimated ), 86400 );
446
  }
447
 
448
  return maybe_unserialize( $estimated );
449
- }
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Reports
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
18
  * Renders the reports page contents.
19
  *
20
  * @since 1.0
 
21
  * @return void
22
  */
23
  function edd_reports_page() {
 
 
24
  $current_page = admin_url( 'edit.php?post_type=download&page=edd-reports' );
25
+ $active_tab = isset( $_GET['tab'] ) ? $_GET['tab'] : 'reports';
26
  ?>
27
  <div class="wrap">
28
  <h2 class="nav-tab-wrapper">
53
  $views = array(
54
  'earnings' => __( 'Earnings', 'edd' ),
55
  'downloads' => edd_get_label_plural(),
 
56
  'gateways' => __( 'Payment Methods', 'edd' ),
57
  'taxes' => __( 'Taxes', 'edd' )
58
  );
66
  * Default Report Views
67
  *
68
  * Checks the $_GET['view'] parameter to ensure it exists within the default allowed views.
69
+ *
70
  * @param string $default Default view to use.
71
+ *
72
  * @since 1.9.6
73
  * @return string $view Report View
74
+ *
75
  */
76
  function edd_get_reporting_view( $default = 'earnings' ) {
77
+
78
  if ( ! isset( $_GET['view'] ) || ! in_array( $_GET['view'], array_keys( edd_reports_default_views() ) ) ) {
79
  $view = $default;
80
  } else {
91
  * @return void
92
  */
93
  function edd_reports_tab_reports() {
94
+
95
+ if( ! current_user_can( 'view_shop_reports' ) ) {
96
+ wp_die( __( 'You do not have permission to access this report', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
97
+ }
98
+
99
  $current_view = 'earnings';
100
  $views = edd_reports_default_views();
101
 
102
+ if ( isset( $_GET['view'] ) && array_key_exists( $_GET['view'], $views ) )
103
+ $current_view = $_GET['view'];
104
 
105
  do_action( 'edd_reports_view_' . $current_view );
106
+
107
  }
108
  add_action( 'edd_reports_tab_reports', 'edd_reports_tab_reports' );
109
 
114
  * @return void
115
  */
116
  function edd_report_views() {
117
+
118
+ if( ! current_user_can( 'view_shop_reports' ) ) {
119
+ return;
120
+ }
121
+
122
  $views = edd_reports_default_views();
123
+ $current_view = isset( $_GET['view'] ) ? $_GET['view'] : 'earnings';
124
  ?>
125
  <form id="edd-reports-filter" method="get">
126
  <select id="edd-reports-view" name="view">
149
  * @return void
150
  */
151
  function edd_reports_downloads_table() {
152
+
153
+ if( ! current_user_can( 'view_shop_reports' ) ) {
154
+ return;
155
+ }
156
+
157
  if( isset( $_GET['download-id'] ) )
158
  return;
159
 
172
  * @return void
173
  */
174
  function edd_reports_download_details() {
175
+
176
+ if( ! current_user_can( 'view_shop_reports' ) ) {
177
+ return;
178
+ }
179
+
180
  if( ! isset( $_GET['download-id'] ) )
181
  return;
182
  ?>
193
  }
194
  add_action( 'edd_reports_view_downloads', 'edd_reports_download_details' );
195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
  /**
198
  * Renders the Gateways Table
203
  * @return void
204
  */
205
  function edd_reports_gateways_table() {
206
+
207
+ if( ! current_user_can( 'view_shop_reports' ) ) {
208
+ return;
209
+ }
210
+
211
  include( dirname( __FILE__ ) . '/class-gateways-reports-table.php' );
212
 
213
  $downloads_table = new EDD_Gateawy_Reports_Table();
224
  * @return void
225
  */
226
  function edd_reports_earnings() {
227
+
228
+ if( ! current_user_can( 'view_shop_reports' ) ) {
229
+ return;
230
+ }
231
  ?>
232
  <div class="tablenav top">
233
  <div class="alignleft actions"><?php edd_report_views(); ?></div>
244
  * @return void
245
  */
246
  function edd_reports_taxes() {
247
+
248
+ if( ! current_user_can( 'view_shop_reports' ) ) {
249
+ return;
250
+ }
251
+
252
  $year = isset( $_GET['year'] ) ? absint( $_GET['year'] ) : date( 'Y' );
253
  ?>
254
  <div class="tablenav top">
286
  * @return void
287
  */
288
  function edd_reports_tab_export() {
289
+
290
+ if( ! current_user_can( 'view_shop_reports' ) ) {
291
+ return;
292
+ }
293
  ?>
294
  <div id="edd-dashboard-widgets-wrap">
295
  <div class="metabox-holder">
296
  <div id="post-body">
297
  <div id="post-body-content">
298
+
299
  <?php do_action( 'edd_reports_tab_export_content_top' ); ?>
300
+
301
+ <div class="postbox edd-export-pdf-sales-earnings">
302
  <h3><span><?php _e( 'Export PDF of Sales and Earnings', 'edd' ); ?></span></h3>
303
  <div class="inside">
304
  <p><?php _e( 'Download a PDF of Sales and Earnings reports for all products for the current year.', 'edd' ); ?> <?php _e( 'Date range reports will be coming soon.', 'edd' ); ?></p>
305
  <p><a class="button" href="<?php echo wp_nonce_url( add_query_arg( array( 'edd-action' => 'generate_pdf' ) ), 'edd_generate_pdf' ); ?>"><?php _e( 'Generate PDF', 'edd' ); ?></a></p>
306
  </div><!-- .inside -->
307
  </div><!-- .postbox -->
308
+
309
+ <div class="postbox edd-export-sales-earnings">
310
  <h3><span><?php _e( 'Export Earnings and Sales Stats', 'edd' ); ?></span></h3>
311
  <div class="inside">
312
  <p><?php _e( 'Download a CSV of earnings and sales over time.', 'edd' ); ?></p>
324
  </div><!-- .inside -->
325
  </div><!-- .postbox -->
326
 
327
+ <div class="postbox edd-export-payment-history">
328
  <h3><span><?php _e('Export Payment History', 'edd'); ?></span></h3>
329
  <div class="inside">
330
  <p><?php _e( 'Download a CSV of all payments recorded.', 'edd' ); ?></p>
347
  </p>
348
  </div><!-- .inside -->
349
  </div><!-- .postbox -->
350
+
351
+ <div class="postbox edd-export-customers">
352
  <h3><span><?php _e('Export Customers in CSV', 'edd'); ?></span></h3>
353
  <div class="inside">
354
  <p><?php _e( 'Download a CSV of all customer emails. Optionally export only customers that have purchased a particular product. Note, if you have a large number of customers, exporting the purchase stats may fail.', 'edd' ); ?></p>
376
  </p>
377
  </div><!-- .inside -->
378
  </div><!-- .postbox -->
379
+
380
+ <div class="postbox edd-export-download-history">
381
  <h3><span><?php _e('Export Download History in CSV', 'edd'); ?></span></h3>
382
  <div class="inside">
383
  <p><?php _e( 'Download a CSV of all file downloads for a specific month and year.', 'edd' ); ?></p>
391
  </p>
392
  </div><!-- .inside -->
393
  </div><!-- .postbox -->
394
+
395
  <?php do_action( 'edd_reports_tab_export_content_bottom' ); ?>
396
+
397
  </div><!-- .post-body-content -->
398
  </div><!-- .post-body -->
399
  </div><!-- .metabox-holder -->
409
  * @return void
410
  */
411
  function edd_reports_tab_logs() {
412
+
413
+ if( ! current_user_can( 'view_shop_reports' ) ) {
414
+ return;
415
+ }
416
+
417
  require( EDD_PLUGIN_DIR . 'includes/admin/reporting/logs.php' );
418
 
419
  $current_view = 'file_downloads';
420
  $log_views = edd_log_default_views();
421
 
422
+ if ( isset( $_GET['view'] ) && array_key_exists( $_GET['view'], $log_views ) )
423
+ $current_view = $_GET['view'];
424
 
425
  do_action( 'edd_logs_view_' . $current_view );
426
  }
433
  * @return array
434
  */
435
  function edd_estimated_monthly_stats() {
436
+
437
  $estimated = get_transient( 'edd_estimated_monthly_stats' );
438
 
439
  if ( false === $estimated ) {
440
+
441
  $estimated = array(
442
  'earnings' => 0,
443
  'sales' => 0
444
  );
445
 
446
+ $stats = new EDD_Payment_Stats;
447
+
448
+ $to_date_earnings = $stats->get_earnings( 0, 'this_month' );
449
+ $to_date_sales = $stats->get_sales( 0, 'this_month' );
450
+
451
+ $current_day = date( 'd', current_time( 'timestamp' ) );
452
+ $current_month = date( 'n', current_time( 'timestamp' ) );
453
+ $current_year = date( 'Y', current_time( 'timestamp' ) );
454
+ $days_in_month = cal_days_in_month( CAL_GREGORIAN, $current_month, $current_year );
455
+
456
+ $estimated['earnings'] = ( $to_date_earnings / $current_day ) * $days_in_month;
457
+ $estimated['sales'] = ( $to_date_sales / $current_day ) * $days_in_month;
458
 
459
  // Cache for one day
460
+ set_transient( 'edd_estimated_monthly_stats', $estimated, 86400 );
461
  }
462
 
463
  return maybe_unserialize( $estimated );
464
+ }
includes/admin/settings/contextual-help.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Settings
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Settings
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
includes/admin/settings/display-settings.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Settings
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -18,13 +18,10 @@ if ( ! defined( 'ABSPATH' ) ) exit;
18
  * Renders the options page contents.
19
  *
20
  * @since 1.0
21
- * @global $edd_options Array of all the EDD Options
22
  * @return void
23
  */
24
  function edd_options_page() {
25
- global $edd_options;
26
-
27
- $active_tab = isset( $_GET[ 'tab' ] ) && array_key_exists( $_GET['tab'], edd_get_settings_tabs() ) ? $_GET[ 'tab' ] : 'general';
28
 
29
  ob_start();
30
  ?>
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Settings
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
18
  * Renders the options page contents.
19
  *
20
  * @since 1.0
 
21
  * @return void
22
  */
23
  function edd_options_page() {
24
+ $active_tab = isset( $_GET['tab'] ) && array_key_exists( $_GET['tab'], edd_get_settings_tabs() ) ? $_GET['tab'] : 'general';
 
 
25
 
26
  ob_start();
27
  ?>
includes/admin/settings/register-settings.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Settings
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -28,6 +28,87 @@ function edd_get_option( $key = '', $default = false ) {
28
  return apply_filters( 'edd_get_option_' . $key, $value, $key, $default );
29
  }
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  /**
32
  * Get Settings
33
  *
@@ -93,13 +174,19 @@ function edd_register_settings() {
93
  'edd_settings_' . $tab,
94
  'edd_settings_' . $tab,
95
  array(
96
- 'id' => isset( $option['id'] ) ? $option['id'] : null,
97
- 'desc' => ! empty( $option['desc'] ) ? $option['desc'] : '',
98
- 'name' => isset( $option['name'] ) ? $option['name'] : null,
99
- 'section' => $tab,
100
- 'size' => isset( $option['size'] ) ? $option['size'] : null,
101
- 'options' => isset( $option['options'] ) ? $option['options'] : '',
102
- 'std' => isset( $option['std'] ) ? $option['std'] : ''
 
 
 
 
 
 
103
  )
104
  );
105
  }
@@ -139,28 +226,53 @@ function edd_get_registered_settings() {
139
  'name' => __( 'Checkout Page', 'edd' ),
140
  'desc' => __( 'This is the checkout page where buyers will complete their purchases. The [download_checkout] short code must be on this page.', 'edd' ),
141
  'type' => 'select',
142
- 'options' => edd_get_pages()
 
 
143
  ),
144
  'success_page' => array(
145
  'id' => 'success_page',
146
  'name' => __( 'Success Page', 'edd' ),
147
  'desc' => __( 'This is the page buyers are sent to after completing their purchases. The [edd_receipt] short code should be on this page.', 'edd' ),
148
  'type' => 'select',
149
- 'options' => edd_get_pages()
 
 
150
  ),
151
  'failure_page' => array(
152
  'id' => 'failure_page',
153
  'name' => __( 'Failed Transaction Page', 'edd' ),
154
  'desc' => __( 'This is the page buyers are sent to if their transaction is cancelled or fails', 'edd' ),
155
  'type' => 'select',
156
- 'options' => edd_get_pages()
 
 
157
  ),
158
  'purchase_history_page' => array(
159
  'id' => 'purchase_history_page',
160
  'name' => __( 'Purchase History Page', 'edd' ),
161
  'desc' => __( 'This page shows a complete purchase history for the current user, including download links', 'edd' ),
162
  'type' => 'select',
163
- 'options' => edd_get_pages()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  ),
165
  'currency_settings' => array(
166
  'id' => 'currency_settings',
@@ -173,7 +285,8 @@ function edd_get_registered_settings() {
173
  'name' => __( 'Currency', 'edd' ),
174
  'desc' => __( 'Choose your currency. Note that some payment gateways have currency restrictions.', 'edd' ),
175
  'type' => 'select',
176
- 'options' => edd_get_currencies()
 
177
  ),
178
  'currency_position' => array(
179
  'id' => 'currency_position',
@@ -254,7 +367,7 @@ function edd_get_registered_settings() {
254
  'id' => 'accepted_cards',
255
  'name' => __( 'Accepted Payment Method Icons', 'edd' ),
256
  'desc' => __( 'Display icons for the selected payment methods', 'edd' ) . '<br/>' . __( 'You will also need to configure your gateway settings if you are accepting credit cards', 'edd' ),
257
- 'type' => 'multicheck',
258
  'options' => apply_filters('edd_accepted_payment_icons', array(
259
  'mastercard' => 'Mastercard',
260
  'visa' => 'Visa',
@@ -302,6 +415,12 @@ function edd_get_registered_settings() {
302
  'type' => 'select',
303
  'options' => edd_get_email_templates()
304
  ),
 
 
 
 
 
 
305
  'email_settings' => array(
306
  'id' => 'email_settings',
307
  'name' => '',
@@ -411,26 +530,19 @@ function edd_get_registered_settings() {
411
  'desc' => __( 'Check this to enable taxes on purchases.', 'edd' ),
412
  'type' => 'checkbox',
413
  ),
 
 
 
 
 
 
414
  'tax_rate' => array(
415
  'id' => 'tax_rate',
416
- 'name' => __( 'Default Tax Rate', 'edd' ),
417
- 'desc' => __( 'Enter a percentage, such as 6.5. Customers not in a specific rate below will be charged this rate.', 'edd' ),
418
  'type' => 'text',
419
  'size' => 'small'
420
  ),
421
- 'base_country' => array(
422
- 'id' => 'base_country',
423
- 'name' => __( 'Base Country', 'edd' ),
424
- 'desc' => __( 'Where does your store operate from?', 'edd' ),
425
- 'type' => 'select',
426
- 'options' => edd_get_country_list()
427
- ),
428
- 'base_state' => array(
429
- 'id' => 'base_state',
430
- 'name' => __( 'Base State / Province', 'edd' ),
431
- 'desc' => __( 'What state / province does your store operate from?', 'edd' ),
432
- 'type' => 'shop_states'
433
- ),
434
  'prices_include_tax' => array(
435
  'id' => 'prices_include_tax',
436
  'name' => __( 'Prices entered with tax', 'edd' ),
@@ -458,18 +570,6 @@ function edd_get_registered_settings() {
458
  'yes' => __( 'Including tax', 'edd' ),
459
  'no' => __( 'Excluding tax', 'edd' )
460
  )
461
- ),
462
- 'taxes_after_discounts' => array(
463
- 'id' => 'taxes_after_discounts',
464
- 'name' => __( 'Calculate Tax After Discounts?', 'edd' ),
465
- 'desc' => __( 'Check this if you would like taxes calculated after discounts. By default taxes are calculated before discounts are applied.', 'edd' ),
466
- 'type' => 'checkbox'
467
- ),
468
- 'tax_rates' => array(
469
- 'id' => 'tax_rates',
470
- 'name' => '<strong>' . __( 'Additional Tax Rates', 'edd' ) . '</strong>',
471
- 'desc' => __( 'Specify additional tax rates for other regions.', 'edd' ),
472
- 'type' => 'tax_rates'
473
  )
474
  )
475
  ),
@@ -524,7 +624,7 @@ function edd_get_registered_settings() {
524
  'item_quantities' => array(
525
  'id' => 'item_quantities',
526
  'name' => __('Item Quantities', 'edd'),
527
- 'desc' => __('Allow item quantities to be changed at checkout.', 'edd'),
528
  'type' => 'checkbox'
529
  ),
530
  'allow_multiple_discounts' => array(
@@ -536,7 +636,7 @@ function edd_get_registered_settings() {
536
  'enable_cart_saving' => array(
537
  'id' => 'enable_cart_saving',
538
  'name' => __( 'Enable Cart Saving', 'edd' ),
539
- 'desc' => __( 'Check this to enable cart saving on the checkout', 'edd' ),
540
  'type' => 'checkbox'
541
  ),
542
  'field_downloads' => array(
@@ -656,7 +756,7 @@ function edd_get_registered_settings() {
656
  'add_to_cart_text' => array(
657
  'id' => 'add_to_cart_text',
658
  'name' => __( 'Add to Cart Text', 'edd' ),
659
- 'desc' => __( 'Text shown on the Add to Cart Buttons', 'edd' ),
660
  'type' => 'text',
661
  'std' => __( 'Add to Cart', 'edd' )
662
  )
@@ -664,7 +764,7 @@ function edd_get_registered_settings() {
664
  )
665
  );
666
 
667
- return $edd_settings;
668
  }
669
 
670
  /**
@@ -707,7 +807,7 @@ function edd_settings_sanitize( $input = array() ) {
707
  }
708
 
709
  // General filter
710
- $input[$key] = apply_filters( 'edd_settings_sanitize', $value, $key );
711
  }
712
 
713
  // Loop through the whitelist and unset any that are empty for the tab being saved
@@ -745,6 +845,10 @@ function edd_settings_sanitize_misc( $input ) {
745
 
746
  global $edd_options;
747
 
 
 
 
 
748
  if( edd_get_file_download_method() != $input['download_method'] || ! edd_htaccess_exists() ) {
749
  // Force the .htaccess files to be updated if the Download method was changed.
750
  edd_create_protection_files( true, $input['download_method'] );
@@ -773,6 +877,10 @@ add_filter( 'edd_settings_misc_sanitize', 'edd_settings_sanitize_misc' );
773
  */
774
  function edd_settings_sanitize_taxes( $input ) {
775
 
 
 
 
 
776
  $new_rates = ! empty( $_POST['tax_rates'] ) ? array_values( $_POST['tax_rates'] ) : array();
777
 
778
  update_option( 'edd_tax_rates', $new_rates );
@@ -797,8 +905,7 @@ add_filter( 'edd_settings_sanitize_text', 'edd_sanitize_text_field' );
797
  * Retrieve settings tabs
798
  *
799
  * @since 1.8
800
- * @param array $input The field value
801
- * @return string $input Sanitizied value
802
  */
803
  function edd_get_settings_tabs() {
804
 
@@ -834,7 +941,7 @@ function edd_get_settings_tabs() {
834
  */
835
  function edd_get_pages( $force = false ) {
836
 
837
- $pages_options = array( 0 => '' ); // Blank option
838
 
839
  if( ( ! isset( $_GET['page'] ) || 'edd-settings' != $_GET['page'] ) && ! $force ) {
840
  return $pages_options;
@@ -876,7 +983,7 @@ function edd_header_callback( $args ) {
876
  function edd_checkbox_callback( $args ) {
877
  global $edd_options;
878
 
879
- $checked = isset( $edd_options[ $args[ 'id' ] ] ) ? checked( 1, $edd_options[ $args[ 'id' ] ], false ) : '';
880
  $html = '<input type="checkbox" id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']" value="1" ' . $checked . '/>';
881
  $html .= '<label for="edd_settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
882
 
@@ -906,6 +1013,70 @@ function edd_multicheck_callback( $args ) {
906
  }
907
  }
908
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
909
  /**
910
  * Radio Callback
911
  *
@@ -1020,7 +1191,7 @@ function edd_text_callback( $args ) {
1020
  function edd_number_callback( $args ) {
1021
  global $edd_options;
1022
 
1023
- if ( isset( $edd_options[ $args['id'] ] ) )
1024
  $value = $edd_options[ $args['id'] ];
1025
  else
1026
  $value = isset( $args['std'] ) ? $args['std'] : '';
@@ -1054,7 +1225,6 @@ function edd_textarea_callback( $args ) {
1054
  else
1055
  $value = isset( $args['std'] ) ? $args['std'] : '';
1056
 
1057
- $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
1058
  $html = '<textarea class="large-text" cols="50" rows="5" id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']">' . esc_textarea( stripslashes( $value ) ) . '</textarea>';
1059
  $html .= '<label for="edd_settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
1060
 
@@ -1117,7 +1287,17 @@ function edd_select_callback($args) {
1117
  else
1118
  $value = isset( $args['std'] ) ? $args['std'] : '';
1119
 
1120
- $html = '<select id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']"/>';
 
 
 
 
 
 
 
 
 
 
1121
 
1122
  foreach ( $args['options'] as $option => $name ) :
1123
  $selected = selected( $option, $value, false );
@@ -1174,14 +1354,21 @@ function edd_color_select_callback( $args ) {
1174
  function edd_rich_editor_callback( $args ) {
1175
  global $edd_options, $wp_version;
1176
 
1177
- if ( isset( $edd_options[ $args['id'] ] ) )
1178
  $value = $edd_options[ $args['id'] ];
1179
- else
 
 
 
 
1180
  $value = isset( $args['std'] ) ? $args['std'] : '';
 
 
 
1181
 
1182
  if ( $wp_version >= 3.3 && function_exists( 'wp_editor' ) ) {
1183
  ob_start();
1184
- wp_editor( stripslashes( $value ), 'edd_settings_' . $args['id'], array( 'textarea_name' => 'edd_settings[' . $args['id'] . ']' ) );
1185
  $html = ob_get_clean();
1186
  } else {
1187
  $html = '<textarea class="large-text" rows="10" id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']">' . esc_textarea( stripslashes( $value ) ) . '</textarea>';
@@ -1211,7 +1398,7 @@ function edd_upload_callback( $args ) {
1211
  $value = isset($args['std']) ? $args['std'] : '';
1212
 
1213
  $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
1214
- $html = '<input type="text" class="' . $size . '-text edd_upload_field" id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']" value="' . esc_attr( stripslashes( $value ) ) . '"/>';
1215
  $html .= '<span>&nbsp;<input type="button" class="edd_settings_upload_button button-secondary" value="' . __( 'Upload File', 'edd' ) . '"/></span>';
1216
  $html .= '<label for="edd_settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
1217
 
@@ -1259,9 +1446,16 @@ function edd_color_callback( $args ) {
1259
  function edd_shop_states_callback($args) {
1260
  global $edd_options;
1261
 
 
 
 
 
 
1262
  $states = edd_get_shop_states();
1263
- $class = empty( $states ) ? ' class="edd-no-states"' : '';
1264
- $html = '<select id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']"' . $class . '/>';
 
 
1265
 
1266
  foreach ( $states as $option => $name ) :
1267
  $selected = isset( $edd_options[ $args['id'] ] ) ? selected( $option, $edd_options[$args['id']], false ) : '';
@@ -1310,7 +1504,9 @@ function edd_tax_rates_callback($args) {
1310
  'selected' => $rate['country'],
1311
  'show_option_all' => false,
1312
  'show_option_none' => false,
1313
- 'class' => 'edd-select edd-tax-country'
 
 
1314
  ) );
1315
  ?>
1316
  </td>
@@ -1323,7 +1519,9 @@ function edd_tax_rates_callback($args) {
1323
  'name' => 'tax_rates[' . $key . '][state]',
1324
  'selected' => $rate['state'],
1325
  'show_option_all' => false,
1326
- 'show_option_none' => false
 
 
1327
  ) );
1328
  } else {
1329
  echo EDD()->html->text( array(
@@ -1349,7 +1547,9 @@ function edd_tax_rates_callback($args) {
1349
  'name' => 'tax_rates[0][country]',
1350
  'show_option_all' => false,
1351
  'show_option_none' => false,
1352
- 'class' => 'edd-select edd-tax-country'
 
 
1353
  ) ); ?>
1354
  </td>
1355
  <td class="edd_tax_state">
@@ -1373,6 +1573,18 @@ function edd_tax_rates_callback($args) {
1373
  echo ob_get_clean();
1374
  }
1375
 
 
 
 
 
 
 
 
 
 
 
 
 
1376
 
1377
  /**
1378
  * Registers the license field callback for Software Licensing
@@ -1399,6 +1611,8 @@ if ( ! function_exists( 'edd_license_key_callback' ) ) {
1399
  }
1400
  $html .= '<label for="edd_settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
1401
 
 
 
1402
  echo $html;
1403
  }
1404
  }
@@ -1413,7 +1627,7 @@ if ( ! function_exists( 'edd_license_key_callback' ) ) {
1413
  * @return void
1414
  */
1415
  function edd_hook_callback( $args ) {
1416
- do_action( 'edd_' . $args['id'] );
1417
  }
1418
 
1419
  /**
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Settings
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
28
  return apply_filters( 'edd_get_option_' . $key, $value, $key, $default );
29
  }
30
 
31
+ /**
32
+ * Update an option
33
+ *
34
+ * Updates an edd setting value in both the db and the global variable.
35
+ * Warning: Passing in an empty, false or null string value will remove
36
+ * the key from the edd_options array.
37
+ *
38
+ * @since 2.3
39
+ * @param string $key The Key to update
40
+ * @param string|bool|int $value The value to set the key to
41
+ * @return boolean True if updated, false if not.
42
+ */
43
+ function edd_update_option( $key = '', $value = false ) {
44
+
45
+ // If no key, exit
46
+ if ( empty( $key ) ){
47
+ return false;
48
+ }
49
+
50
+ if ( empty( $value ) ) {
51
+ $remove_option = edd_delete_option( $key );
52
+ return $remove_option;
53
+ }
54
+
55
+ // First let's grab the current settings
56
+ $options = get_option( 'edd_settings' );
57
+
58
+ // Let's let devs alter that value coming in
59
+ $value = apply_filters( 'edd_update_option', $value, $key );
60
+
61
+ // Next let's try to update the value
62
+ $options[ $key ] = $value;
63
+ $did_update = update_option( 'edd_settings', $options );
64
+
65
+ // If it updated, let's update the global variable
66
+ if ( $did_update ){
67
+ global $edd_options;
68
+ $edd_options[ $key ] = $value;
69
+
70
+ }
71
+
72
+ return $did_update;
73
+ }
74
+
75
+ /**
76
+ * Remove an option
77
+ *
78
+ * Removes an edd setting value in both the db and the global variable.
79
+ *
80
+ * @since 2.3
81
+ * @param string $key The Key to delete
82
+ * @return boolean True if updated, false if not.
83
+ */
84
+ function edd_delete_option( $key = '' ) {
85
+
86
+ // If no key, exit
87
+ if ( empty( $key ) ){
88
+ return false;
89
+ }
90
+
91
+ // First let's grab the current settings
92
+ $options = get_option( 'edd_settings' );
93
+
94
+ // Next let's try to update the value
95
+ if( isset( $options[ $key ] ) ) {
96
+
97
+ unset( $options[ $key ] );
98
+
99
+ }
100
+
101
+ $did_update = update_option( 'edd_settings', $options );
102
+
103
+ // If it updated, let's update the global variable
104
+ if ( $did_update ){
105
+ global $edd_options;
106
+ $edd_options = $options;
107
+ }
108
+
109
+ return $did_update;
110
+ }
111
+
112
  /**
113
  * Get Settings
114
  *
174
  'edd_settings_' . $tab,
175
  'edd_settings_' . $tab,
176
  array(
177
+ 'section' => $tab,
178
+ 'id' => isset( $option['id'] ) ? $option['id'] : null,
179
+ 'desc' => ! empty( $option['desc'] ) ? $option['desc'] : '',
180
+ 'name' => isset( $option['name'] ) ? $option['name'] : null,
181
+ 'size' => isset( $option['size'] ) ? $option['size'] : null,
182
+ 'options' => isset( $option['options'] ) ? $option['options'] : '',
183
+ 'std' => isset( $option['std'] ) ? $option['std'] : '',
184
+ 'min' => isset( $option['min'] ) ? $option['min'] : null,
185
+ 'max' => isset( $option['max'] ) ? $option['max'] : null,
186
+ 'step' => isset( $option['step'] ) ? $option['step'] : null,
187
+ 'chosen' => isset( $option['chosen'] ) ? $option['chosen'] : null,
188
+ 'placeholder' => isset( $option['placeholder'] ) ? $option['placeholder'] : null,
189
+ 'allow_blank' => isset( $option['allow_blank'] ) ? $option['allow_blank'] : true
190
  )
191
  );
192
  }
226
  'name' => __( 'Checkout Page', 'edd' ),
227
  'desc' => __( 'This is the checkout page where buyers will complete their purchases. The [download_checkout] short code must be on this page.', 'edd' ),
228
  'type' => 'select',
229
+ 'options' => edd_get_pages(),
230
+ 'chosen' => true,
231
+ 'placeholder' => __( 'Select a page', 'edd' )
232
  ),
233
  'success_page' => array(
234
  'id' => 'success_page',
235
  'name' => __( 'Success Page', 'edd' ),
236
  'desc' => __( 'This is the page buyers are sent to after completing their purchases. The [edd_receipt] short code should be on this page.', 'edd' ),
237
  'type' => 'select',
238
+ 'options' => edd_get_pages(),
239
+ 'chosen' => true,
240
+ 'placeholder' => __( 'Select a page', 'edd' )
241
  ),
242
  'failure_page' => array(
243
  'id' => 'failure_page',
244
  'name' => __( 'Failed Transaction Page', 'edd' ),
245
  'desc' => __( 'This is the page buyers are sent to if their transaction is cancelled or fails', 'edd' ),
246
  'type' => 'select',
247
+ 'options' => edd_get_pages(),
248
+ 'chosen' => true,
249
+ 'placeholder' => __( 'Select a page', 'edd' )
250
  ),
251
  'purchase_history_page' => array(
252
  'id' => 'purchase_history_page',
253
  'name' => __( 'Purchase History Page', 'edd' ),
254
  'desc' => __( 'This page shows a complete purchase history for the current user, including download links', 'edd' ),
255
  'type' => 'select',
256
+ 'options' => edd_get_pages(),
257
+ 'chosen' => true,
258
+ 'placeholder' => __( 'Select a page', 'edd' )
259
+ ),
260
+ 'base_country' => array(
261
+ 'id' => 'base_country',
262
+ 'name' => __( 'Base Country', 'edd' ),
263
+ 'desc' => __( 'Where does your store operate from?', 'edd' ),
264
+ 'type' => 'select',
265
+ 'options' => edd_get_country_list(),
266
+ 'chosen' => true,
267
+ 'placeholder' => __( 'Select a country', 'edd' )
268
+ ),
269
+ 'base_state' => array(
270
+ 'id' => 'base_state',
271
+ 'name' => __( 'Base State / Province', 'edd' ),
272
+ 'desc' => __( 'What state / province does your store operate from?', 'edd' ),
273
+ 'type' => 'shop_states',
274
+ 'chosen' => true,
275
+ 'placeholder' => __( 'Select a state', 'edd' )
276
  ),
277
  'currency_settings' => array(
278
  'id' => 'currency_settings',
285
  'name' => __( 'Currency', 'edd' ),
286
  'desc' => __( 'Choose your currency. Note that some payment gateways have currency restrictions.', 'edd' ),
287
  'type' => 'select',
288
+ 'options' => edd_get_currencies(),
289
+ 'chosen' => true
290
  ),
291
  'currency_position' => array(
292
  'id' => 'currency_position',
367
  'id' => 'accepted_cards',
368
  'name' => __( 'Accepted Payment Method Icons', 'edd' ),
369
  'desc' => __( 'Display icons for the selected payment methods', 'edd' ) . '<br/>' . __( 'You will also need to configure your gateway settings if you are accepting credit cards', 'edd' ),
370
+ 'type' => 'payment_icons',
371
  'options' => apply_filters('edd_accepted_payment_icons', array(
372
  'mastercard' => 'Mastercard',
373
  'visa' => 'Visa',
415
  'type' => 'select',
416
  'options' => edd_get_email_templates()
417
  ),
418
+ 'email_logo' => array(
419
+ 'id' => 'email_logo',
420
+ 'name' => __( 'Logo', 'edd' ),
421
+ 'desc' => __( 'Upload or choose a logo to be displayed at the top of the purchase receipt emails. Displayed on HTML emails only.', 'edd' ),
422
+ 'type' => 'upload'
423
+ ),
424
  'email_settings' => array(
425
  'id' => 'email_settings',
426
  'name' => '',
530
  'desc' => __( 'Check this to enable taxes on purchases.', 'edd' ),
531
  'type' => 'checkbox',
532
  ),
533
+ 'tax_rates' => array(
534
+ 'id' => 'tax_rates',
535
+ 'name' => '<strong>' . __( 'Tax Rates', 'edd' ) . '</strong>',
536
+ 'desc' => __( 'Enter tax rates for specific regions.', 'edd' ),
537
+ 'type' => 'tax_rates'
538
+ ),
539
  'tax_rate' => array(
540
  'id' => 'tax_rate',
541
+ 'name' => __( 'Fallback Tax Rate', 'edd' ),
542
+ 'desc' => __( 'Enter a percentage, such as 6.5. Customers not in a specific rate will be charged this rate.', 'edd' ),
543
  'type' => 'text',
544
  'size' => 'small'
545
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
546
  'prices_include_tax' => array(
547
  'id' => 'prices_include_tax',
548
  'name' => __( 'Prices entered with tax', 'edd' ),
570
  'yes' => __( 'Including tax', 'edd' ),
571
  'no' => __( 'Excluding tax', 'edd' )
572
  )
 
 
 
 
 
 
 
 
 
 
 
 
573
  )
574
  )
575
  ),
624
  'item_quantities' => array(
625
  'id' => 'item_quantities',
626
  'name' => __('Item Quantities', 'edd'),
627
+ 'desc' => __('Allow item quantities to be changed.', 'edd'),
628
  'type' => 'checkbox'
629
  ),
630
  'allow_multiple_discounts' => array(
636
  'enable_cart_saving' => array(
637
  'id' => 'enable_cart_saving',
638
  'name' => __( 'Enable Cart Saving', 'edd' ),
639
+ 'desc' => __( 'Check this to enable cart saving on the checkout.', 'edd' ),
640
  'type' => 'checkbox'
641
  ),
642
  'field_downloads' => array(
756
  'add_to_cart_text' => array(
757
  'id' => 'add_to_cart_text',
758
  'name' => __( 'Add to Cart Text', 'edd' ),
759
+ 'desc' => __( 'Text shown on the Add to Cart Buttons.', 'edd' ),
760
  'type' => 'text',
761
  'std' => __( 'Add to Cart', 'edd' )
762
  )
764
  )
765
  );
766
 
767
+ return apply_filters( 'edd_registered_settings', $edd_settings );
768
  }
769
 
770
  /**
807
  }
808
 
809
  // General filter
810
+ $input[$key] = apply_filters( 'edd_settings_sanitize', $input[$key], $key );
811
  }
812
 
813
  // Loop through the whitelist and unset any that are empty for the tab being saved
845
 
846
  global $edd_options;
847
 
848
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
849
+ return $input;
850
+ }
851
+
852
  if( edd_get_file_download_method() != $input['download_method'] || ! edd_htaccess_exists() ) {
853
  // Force the .htaccess files to be updated if the Download method was changed.
854
  edd_create_protection_files( true, $input['download_method'] );
877
  */
878
  function edd_settings_sanitize_taxes( $input ) {
879
 
880
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
881
+ return $input;
882
+ }
883
+
884
  $new_rates = ! empty( $_POST['tax_rates'] ) ? array_values( $_POST['tax_rates'] ) : array();
885
 
886
  update_option( 'edd_tax_rates', $new_rates );
905
  * Retrieve settings tabs
906
  *
907
  * @since 1.8
908
+ * @return array $tabs
 
909
  */
910
  function edd_get_settings_tabs() {
911
 
941
  */
942
  function edd_get_pages( $force = false ) {
943
 
944
+ $pages_options = array( '' => '' ); // Blank option
945
 
946
  if( ( ! isset( $_GET['page'] ) || 'edd-settings' != $_GET['page'] ) && ! $force ) {
947
  return $pages_options;
983
  function edd_checkbox_callback( $args ) {
984
  global $edd_options;
985
 
986
+ $checked = isset( $edd_options[ $args['id'] ] ) ? checked( 1, $edd_options[ $args['id'] ], false ) : '';
987
  $html = '<input type="checkbox" id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']" value="1" ' . $checked . '/>';
988
  $html .= '<label for="edd_settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
989
 
1013
  }
1014
  }
1015
 
1016
+ /**
1017
+ * Payment method icons callback
1018
+ *
1019
+ * @since 2.1
1020
+ * @param array $args Arguments passed by the setting
1021
+ * @global $edd_options Array of all the EDD Options
1022
+ * @return void
1023
+ */
1024
+ function edd_payment_icons_callback( $args ) {
1025
+ global $edd_options;
1026
+
1027
+ if ( ! empty( $args['options'] ) ) {
1028
+ foreach( $args['options'] as $key => $option ) {
1029
+
1030
+ if( isset( $edd_options[$args['id']][$key] ) ) {
1031
+ $enabled = $option;
1032
+ } else {
1033
+ $enabled = NULL;
1034
+ }
1035
+
1036
+ echo '<label for="edd_settings[' . $args['id'] . '][' . $key . ']" style="margin-right:10px;line-height:16px;height:16px;display:inline-block;">';
1037
+
1038
+ echo '<input name="edd_settings[' . $args['id'] . '][' . $key . ']" id="edd_settings[' . $args['id'] . '][' . $key . ']" type="checkbox" value="' . esc_attr( $option ) . '" ' . checked( $option, $enabled, false ) . '/>&nbsp;';
1039
+
1040
+ if( edd_string_is_image_url( $key ) ) {
1041
+
1042
+ echo '<img class="payment-icon" src="' . esc_url( $key ) . '" style="width:32px;height:24px;position:relative;top:6px;margin-right:5px;"/>';
1043
+
1044
+ } else {
1045
+
1046
+ $card = strtolower( str_replace( ' ', '', $option ) );
1047
+
1048
+ if( has_filter( 'edd_accepted_payment_' . $card . '_image' ) ) {
1049
+
1050
+ $image = apply_filters( 'edd_accepted_payment_' . $card . '_image', '' );
1051
+
1052
+ } else {
1053
+
1054
+ $image = edd_locate_template( 'images' . DIRECTORY_SEPARATOR . 'icons' . DIRECTORY_SEPARATOR . $card . '.gif', false );
1055
+ $content_dir = WP_CONTENT_DIR;
1056
+
1057
+ if( function_exists( 'wp_normalize_path' ) ) {
1058
+
1059
+ // Replaces backslashes with forward slashes for Windows systems
1060
+ $image = wp_normalize_path( $image );
1061
+ $content_dir = wp_normalize_path( $content_dir );
1062
+
1063
+ }
1064
+
1065
+ $image = str_replace( $content_dir, WP_CONTENT_URL, $image );
1066
+
1067
+ }
1068
+
1069
+ echo '<img class="payment-icon" src="' . esc_url( $image ) . '" style="width:32px;height:24px;position:relative;top:6px;margin-right:5px;"/>';
1070
+ }
1071
+
1072
+
1073
+ echo $option . '</label>';
1074
+
1075
+ }
1076
+ echo '<p class="description" style="margin-top:16px;">' . $args['desc'] . '</p>';
1077
+ }
1078
+ }
1079
+
1080
  /**
1081
  * Radio Callback
1082
  *
1191
  function edd_number_callback( $args ) {
1192
  global $edd_options;
1193
 
1194
+ if ( isset( $edd_options[ $args['id'] ] ) )
1195
  $value = $edd_options[ $args['id'] ];
1196
  else
1197
  $value = isset( $args['std'] ) ? $args['std'] : '';
1225
  else
1226
  $value = isset( $args['std'] ) ? $args['std'] : '';
1227
 
 
1228
  $html = '<textarea class="large-text" cols="50" rows="5" id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']">' . esc_textarea( stripslashes( $value ) ) . '</textarea>';
1229
  $html .= '<label for="edd_settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
1230
 
1287
  else
1288
  $value = isset( $args['std'] ) ? $args['std'] : '';
1289
 
1290
+ if ( isset( $args['placeholder'] ) )
1291
+ $placeholder = $args['placeholder'];
1292
+ else
1293
+ $placeholder = '';
1294
+
1295
+ if ( isset( $args['chosen'] ) )
1296
+ $chosen = 'class="edd-chosen"';
1297
+ else
1298
+ $chosen = '';
1299
+
1300
+ $html = '<select id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']" ' . $chosen . 'data-placeholder="' . $placeholder . '" />';
1301
 
1302
  foreach ( $args['options'] as $option => $name ) :
1303
  $selected = selected( $option, $value, false );
1354
  function edd_rich_editor_callback( $args ) {
1355
  global $edd_options, $wp_version;
1356
 
1357
+ if ( isset( $edd_options[ $args['id'] ] ) ) {
1358
  $value = $edd_options[ $args['id'] ];
1359
+
1360
+ if( empty( $args['allow_blank'] ) && empty( $value ) ) {
1361
+ $value = isset( $args['std'] ) ? $args['std'] : '';
1362
+ }
1363
+ } else {
1364
  $value = isset( $args['std'] ) ? $args['std'] : '';
1365
+ }
1366
+
1367
+ $rows = isset( $args['size'] ) ? $args['size'] : 20;
1368
 
1369
  if ( $wp_version >= 3.3 && function_exists( 'wp_editor' ) ) {
1370
  ob_start();
1371
+ wp_editor( stripslashes( $value ), 'edd_settings_' . $args['id'], array( 'textarea_name' => 'edd_settings[' . $args['id'] . ']', 'textarea_rows' => $rows ) );
1372
  $html = ob_get_clean();
1373
  } else {
1374
  $html = '<textarea class="large-text" rows="10" id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']">' . esc_textarea( stripslashes( $value ) ) . '</textarea>';
1398
  $value = isset($args['std']) ? $args['std'] : '';
1399
 
1400
  $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
1401
+ $html = '<input type="text" class="' . $size . '-text" id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']" value="' . esc_attr( stripslashes( $value ) ) . '"/>';
1402
  $html .= '<span>&nbsp;<input type="button" class="edd_settings_upload_button button-secondary" value="' . __( 'Upload File', 'edd' ) . '"/></span>';
1403
  $html .= '<label for="edd_settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
1404
 
1446
  function edd_shop_states_callback($args) {
1447
  global $edd_options;
1448
 
1449
+ if ( isset( $args['placeholder'] ) )
1450
+ $placeholder = $args['placeholder'];
1451
+ else
1452
+ $placeholder = '';
1453
+
1454
  $states = edd_get_shop_states();
1455
+
1456
+ $chosen = ( $args['chosen'] ? ' edd-chosen' : '' );
1457
+ $class = empty( $states ) ? ' class="edd-no-states' . $chosen . '"' : 'class="' . $chosen . '"';
1458
+ $html = '<select id="edd_settings[' . $args['id'] . ']" name="edd_settings[' . $args['id'] . ']"' . $class . 'data-placeholder="' . $placeholder . '"/>';
1459
 
1460
  foreach ( $states as $option => $name ) :
1461
  $selected = isset( $edd_options[ $args['id'] ] ) ? selected( $option, $edd_options[$args['id']], false ) : '';
1504
  'selected' => $rate['country'],
1505
  'show_option_all' => false,
1506
  'show_option_none' => false,
1507
+ 'class' => 'edd-select edd-tax-country',
1508
+ 'chosen' => false,
1509
+ 'placeholder' => __( 'Choose a country', 'edd' )
1510
  ) );
1511
  ?>
1512
  </td>
1519
  'name' => 'tax_rates[' . $key . '][state]',
1520
  'selected' => $rate['state'],
1521
  'show_option_all' => false,
1522
+ 'show_option_none' => false,
1523
+ 'chosen' => false,
1524
+ 'placeholder' => __( 'Choose a state', 'edd' )
1525
  ) );
1526
  } else {
1527
  echo EDD()->html->text( array(
1547
  'name' => 'tax_rates[0][country]',
1548
  'show_option_all' => false,
1549
  'show_option_none' => false,
1550
+ 'class' => 'edd-select edd-tax-country',
1551
+ 'chosen' => false,
1552
+ 'placeholder' => __( 'Choose a country', 'edd' )
1553
  ) ); ?>
1554
  </td>
1555
  <td class="edd_tax_state">
1573
  echo ob_get_clean();
1574
  }
1575
 
1576
+ /**
1577
+ * Descriptive text callback.
1578
+ *
1579
+ * Renders descriptive text onto the settings field.
1580
+ *
1581
+ * @since 2.1.3
1582
+ * @param array $args Arguments passed by the setting
1583
+ * @return void
1584
+ */
1585
+ function edd_descriptive_text_callback( $args ) {
1586
+ echo esc_html( $args['desc'] );
1587
+ }
1588
 
1589
  /**
1590
  * Registers the license field callback for Software Licensing
1611
  }
1612
  $html .= '<label for="edd_settings[' . $args['id'] . ']"> ' . $args['desc'] . '</label>';
1613
 
1614
+ wp_nonce_field( $args['id'] . '-nonce', $args['id'] . '-nonce' );
1615
+
1616
  echo $html;
1617
  }
1618
  }
1627
  * @return void
1628
  */
1629
  function edd_hook_callback( $args ) {
1630
+ do_action( 'edd_' . $args['id'], $args );
1631
  }
1632
 
1633
  /**
includes/admin/settings/settings.php DELETED
@@ -1,75 +0,0 @@
1
- <?php
2
- /**
3
- * Admin Options Page
4
- *
5
- * @package Easy Digital Downloads
6
- * @subpackage Admin Options Page
7
- * @copyright Copyright (c) 2012, Pippin Williamson
8
- * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
- * @since 1.0
10
- */
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) exit;
14
-
15
-
16
- /**
17
- * Options Page
18
- *
19
- * Renders the options page contents.
20
- *
21
- * @access private
22
- * @since 1.0
23
- * @return void
24
- */
25
-
26
- function edd_options_page() {
27
- global $edd_options;
28
-
29
- $active_tab = isset( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'general';
30
-
31
- ob_start(); ?>
32
- <div class="wrap">
33
- <h2 class="nav-tab-wrapper">
34
- <a href="<?php echo add_query_arg('tab', 'general', remove_query_arg('settings-updated')); ?>" class="nav-tab <?php echo $active_tab == 'general' ? 'nav-tab-active' : ''; ?>"><?php _e('General', 'edd'); ?></a>
35
- <a href="<?php echo add_query_arg('tab', 'gateways', remove_query_arg('settings-updated')); ?>" class="nav-tab <?php echo $active_tab == 'gateways' ? 'nav-tab-active' : ''; ?>"><?php _e('Payment Gateways', 'edd'); ?></a>
36
- <a href="<?php echo add_query_arg('tab', 'emails', remove_query_arg('settings-updated')); ?>" class="nav-tab <?php echo $active_tab == 'emails' ? 'nav-tab-active' : ''; ?>"><?php _e('Emails', 'edd'); ?></a>
37
- <a href="<?php echo add_query_arg('tab', 'styles', remove_query_arg('settings-updated')); ?>" class="nav-tab <?php echo $active_tab == 'styles' ? 'nav-tab-active' : ''; ?>"><?php _e('Styles', 'edd'); ?></a>
38
- <a href="<?php echo add_query_arg('tab', 'taxes', remove_query_arg('settings-updated')); ?>" class="nav-tab <?php echo $active_tab == 'taxes' ? 'nav-tab-active' : ''; ?>"><?php _e('Taxes', 'edd'); ?></a>
39
- <a href="<?php echo add_query_arg('tab', 'misc', remove_query_arg('settings-updated')); ?>" class="nav-tab <?php echo $active_tab == 'misc' ? 'nav-tab-active' : ''; ?>"><?php _e('Misc', 'edd'); ?></a>
40
- </h2>
41
-
42
- <div id="tab_container">
43
- <?php //settings_errors( 'edd-notices' ); ?>
44
-
45
- <form method="post" action="options.php">
46
- <?php
47
- if ( $active_tab == 'general' ) {
48
- settings_fields( 'edd_settings_general' );
49
- do_settings_sections( 'edd_settings_general' );
50
- } elseif ( $active_tab == 'gateways' ) {
51
- settings_fields( 'edd_settings_gateways' );
52
- do_settings_sections( 'edd_settings_gateways' );
53
- } elseif ( $active_tab == 'emails' ) {
54
- settings_fields( 'edd_settings_emails' );
55
- do_settings_sections( 'edd_settings_emails' );
56
- } elseif ( $active_tab == 'styles' ) {
57
- settings_fields('edd_settings_styles' );
58
- do_settings_sections('edd_settings_styles' );
59
- } elseif ($active_tab == 'taxes' ) {
60
- settings_fields('edd_settings_taxes' );
61
- do_settings_sections('edd_settings_taxes' );
62
- } else {
63
- settings_fields( 'edd_settings_misc' );
64
- do_settings_sections( 'edd_settings_misc' );
65
- }
66
-
67
- submit_button();
68
- ?>
69
-
70
- </form>
71
- </div><!-- #tab_container-->
72
- </div><!-- .wrap -->
73
- <?php
74
- echo ob_get_clean();
75
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/admin/thickbox.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Admin
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
includes/admin/tools.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Tools
9
- * @copyright Copyright (c) 2014, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  */
12
 
@@ -81,16 +81,21 @@ function edd_get_tools_tabs() {
81
  * @return void
82
  */
83
  function edd_tools_banned_emails_display() {
 
 
 
 
 
84
  do_action( 'edd_tools_banned_emails_before' );
85
  ?>
86
  <div class="postbox">
87
  <h3><span><?php _e( 'Banned Emails', 'edd' ); ?></span></h3>
88
  <div class="inside">
89
- <p><?php _e( 'Emails placed in the box below will not be allowed to make purchases.', 'edd' ); ?></p>
90
  <form method="post" action="<?php echo admin_url( 'edit.php?post_type=download&page=edd-tools&tab=general' ); ?>">
91
  <p>
92
  <textarea name="banned_emails" rows="10" class="large-text"><?php echo implode( "\n", edd_get_banned_emails() ); ?></textarea>
93
- <span class="description"><?php _e( 'Enter emails to disallow, one per line', 'edd' ); ?></span>
94
  </p>
95
  <p>
96
  <input type="hidden" name="edd_action" value="save_banned_emails" />
@@ -102,9 +107,42 @@ function edd_tools_banned_emails_display() {
102
  </div><!-- .postbox -->
103
  <?php
104
  do_action( 'edd_tools_banned_emails_after' );
 
105
  }
106
  add_action( 'edd_tools_tab_general', 'edd_tools_banned_emails_display' );
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
  /**
110
  * Display the API Keys
@@ -113,6 +151,11 @@ add_action( 'edd_tools_tab_general', 'edd_tools_banned_emails_display' );
113
  * @return void
114
  */
115
  function edd_tools_api_keys_display() {
 
 
 
 
 
116
  do_action( 'edd_tools_api_keys_before' );
117
 
118
  require_once EDD_PLUGIN_DIR . 'includes/admin/class-api-keys-table.php';
@@ -142,20 +185,55 @@ add_action( 'edd_tools_tab_api_keys', 'edd_tools_api_keys_display' );
142
  * @return void
143
  */
144
  function edd_tools_banned_emails_save() {
145
- if( !wp_verify_nonce( $_POST['edd_banned_emails_nonce'], 'edd_banned_emails_nonce' ) )
146
- return;
147
 
148
  global $edd_options;
149
 
 
 
 
 
 
 
 
 
 
150
  // Sanitize the input
151
  $emails = array_map( 'trim', explode( "\n", $_POST['banned_emails'] ) );
152
- $emails = array_filter( array_map( 'is_email', $emails ) );
 
 
 
 
 
 
 
 
 
153
 
154
  $edd_options['banned_emails'] = $emails;
155
  update_option( 'edd_settings', $edd_options );
156
  }
157
  add_action( 'edd_save_banned_emails', 'edd_tools_banned_emails_save' );
158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
  /**
161
  * Display the tools import/export tab
@@ -164,6 +242,11 @@ add_action( 'edd_save_banned_emails', 'edd_tools_banned_emails_save' );
164
  * @return void
165
  */
166
  function edd_tools_import_export_display() {
 
 
 
 
 
167
  do_action( 'edd_tools_import_export_before' );
168
  ?>
169
  <div class="postbox">
@@ -230,7 +313,7 @@ function edd_tools_import_export_process_export() {
230
 
231
  nocache_headers();
232
  header( 'Content-Type: application/json; charset=utf-8' );
233
- header( 'Content-Disposition: attachment; filename=edd-settings-export-' . date( 'm-d-Y' ) . '.json' );
234
  header( "Expires: 0" );
235
 
236
  echo json_encode( $settings );
@@ -257,13 +340,13 @@ function edd_tools_import_export_process_import() {
257
  return;
258
 
259
  if( edd_get_file_extension( $_FILES['import_file']['name'] ) != 'json' ) {
260
- wp_die( __( 'Please upload a valid .json file', 'edd' ) );
261
  }
262
 
263
  $import_file = $_FILES['import_file']['tmp_name'];
264
 
265
  if( empty( $import_file ) ) {
266
- wp_die( __( 'Please upload a file to import', 'edd' ) );
267
  }
268
 
269
  // Retrieve the settings from the file and convert the json object to an array
@@ -284,6 +367,11 @@ add_action( 'edd_import_settings', 'edd_tools_import_export_process_import' );
284
  * @return void
285
  */
286
  function edd_tools_sysinfo_display() {
 
 
 
 
 
287
  ?>
288
  <form action="<?php echo esc_url( admin_url( 'edit.php?post_type=download&page=edd-tools&tab=system_info' ) ); ?>" method="post" dir="ltr">
289
  <textarea readonly="readonly" onclick="this.focus(); this.select()" id="system-info-textarea" name="edd-sysinfo" title="To copy the system info, click below then press Ctrl + C (PC) or Cmd + C (Mac)."><?php echo edd_tools_sysinfo_get(); ?></textarea>
@@ -303,11 +391,10 @@ add_action( 'edd_tools_tab_system_info', 'edd_tools_sysinfo_display' );
303
  * @since 2.0
304
  * @access public
305
  * @global object $wpdb Used to query the database using the WordPress Database API
306
- * @global array $edd_options Array of all EDD options
307
  * @return string $return A string containing the info to output
308
  */
309
  function edd_tools_sysinfo_get() {
310
- global $wpdb, $edd_options;
311
 
312
  if( !class_exists( 'Browser' ) )
313
  require_once EDD_PLUGIN_DIR . 'includes/libraries/browser.php';
@@ -387,6 +474,7 @@ function edd_tools_sysinfo_get() {
387
 
388
  $return .= 'Remote Post: ' . $WP_REMOTE_POST . "\n";
389
  $return .= 'Table Prefix: ' . 'Length: ' . strlen( $wpdb->prefix ) . ' Status: ' . ( strlen( $wpdb->prefix ) > 16 ? 'ERROR: Too long' : 'Acceptable' ) . "\n";
 
390
  $return .= 'WP_DEBUG: ' . ( defined( 'WP_DEBUG' ) ? WP_DEBUG ? 'Enabled' : 'Disabled' : 'Not set' ) . "\n";
391
  $return .= 'Memory Limit: ' . WP_MEMORY_LIMIT . "\n";
392
  $return .= 'Registered Post Stati: ' . implode( ', ', get_post_stati() ) . "\n";
@@ -400,17 +488,26 @@ function edd_tools_sysinfo_get() {
400
  $return .= 'Test Mode: ' . ( edd_is_test_mode() ? "Enabled\n" : "Disabled\n" );
401
  $return .= 'Ajax: ' . ( ! edd_is_ajax_disabled() ? "Enabled\n" : "Disabled\n" );
402
  $return .= 'Guest Checkout: ' . ( edd_no_guest_checkout() ? "Disabled\n" : "Enabled\n" );
403
- $return .= 'Symlinks: ' . ( apply_filters( 'edd_symlink_file_downloads', isset( $edd_options['symlink_file_downloads'] ) ) && function_exists( 'symlink' ) ? "Enabled\n" : "Disabled\n" );
404
  $return .= 'Download Method: ' . ucfirst( edd_get_file_download_method() ) . "\n";
 
 
 
 
 
405
 
406
  $return = apply_filters( 'edd_sysinfo_after_edd_config', $return );
407
 
408
  // EDD pages
 
 
 
 
409
  $return .= "\n" . '-- EDD Page Configuration' . "\n\n";
410
- $return .= 'Checkout: ' . ( !empty( $edd_options['purchase_page'] ) ? "Valid\n" : "Invalid\n" );
411
- $return .= 'Checkout Page: ' . ( !empty( $edd_options['purchase_page'] ) ? get_permalink( $edd_options['purchase_page'] ) . "\n" : "Unset\n" );
412
- $return .= 'Success Page: ' . ( !empty( $edd_options['success_page'] ) ? get_permalink( $edd_options['success_page'] ) . "\n" : "Unset\n" );
413
- $return .= 'Failure Page: ' . ( !empty( $edd_options['failure_page'] ) ? get_permalink( $edd_options['failure_page'] ) . "\n" : "Unset\n" );
414
  $return .= 'Downloads Slug: ' . ( defined( 'EDD_SLUG' ) ? '/' . EDD_SLUG . "\n" : "/downloads\n" );
415
 
416
  $return = apply_filters( 'edd_sysinfo_after_edd_pages', $return );
@@ -445,12 +542,10 @@ function edd_tools_sysinfo_get() {
445
  // EDD Taxes
446
  $return .= "\n" . '-- EDD Tax Configuration' . "\n\n";
447
  $return .= 'Taxes: ' . ( edd_use_taxes() ? "Enabled\n" : "Disabled\n" );
448
- $return .= 'Taxes Applied: ' . ( edd_taxes_after_discounts() ? "After Discounts\n" : "Before Discounts\n" );
449
  $return .= 'Tax Rate: ' . edd_get_tax_rate() * 100 . "\n";
450
- $return .= 'Display On Checkout: ' . ( !empty( $edd_options['checkout_include_tax'] ) ? "Displayed\n" : "Not Displayed\n" );
451
  $return .= 'Prices Include Tax: ' . ( edd_prices_include_tax() ? "Yes\n" : "No\n" );
452
- $return .= 'Taxes After Discounts: ' . ( edd_taxes_after_discounts() ? "Yes\n" : "No\n" );
453
-
454
  $rates = edd_get_tax_rates();
455
  if( !empty( $rates ) ) {
456
  $return .= 'Country / State Rates: ' . "\n";
@@ -469,13 +564,25 @@ function edd_tools_sysinfo_get() {
469
  foreach( glob( $dir ) as $file ) {
470
  $return .= 'Filename: ' . basename( $file ) . "\n";
471
  }
472
-
473
  $return = apply_filters( 'edd_sysinfo_after_edd_templates', $return );
474
  }
475
 
 
 
 
 
 
 
 
 
 
 
 
 
476
  // WordPress active plugins
477
  $return .= "\n" . '-- WordPress Active Plugins' . "\n\n";
478
-
479
  $plugins = get_plugins();
480
  $active_plugins = get_option( 'active_plugins', array() );
481
 
@@ -523,7 +630,7 @@ function edd_tools_sysinfo_get() {
523
  // Server configuration (really just versioning)
524
  $return .= "\n" . '-- Webserver Configuration' . "\n\n";
525
  $return .= 'PHP Version: ' . PHP_VERSION . "\n";
526
- $return .= 'MySQL Version: ' . mysqli_get_client_version() . "\n";
527
  $return .= 'Webserver Info: ' . $_SERVER['SERVER_SOFTWARE'] . "\n";
528
 
529
  $return = apply_filters( 'edd_sysinfo_after_webserver_config', $return );
@@ -552,7 +659,7 @@ function edd_tools_sysinfo_get() {
552
 
553
  // Session stuff
554
  $return .= "\n" . '-- Session Configuration' . "\n\n";
555
- $return .= 'EDD Use Sessions: ' . ( defined( 'EDD_USE_PHP_SESSIONS' ) ? 'Enabled' : 'Disabled' ) . "\n";
556
  $return .= 'Session: ' . ( isset( $_SESSION ) ? 'Enabled' : 'Disabled' ) . "\n";
557
 
558
  // The rest of this is only relevant is session is enabled
@@ -579,6 +686,11 @@ function edd_tools_sysinfo_get() {
579
  * @return void
580
  */
581
  function edd_tools_sysinfo_download() {
 
 
 
 
 
582
  nocache_headers();
583
 
584
  header( 'Content-Type: text/plain' );
6
  *
7
  * @package EDD
8
  * @subpackage Admin/Tools
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  */
12
 
81
  * @return void
82
  */
83
  function edd_tools_banned_emails_display() {
84
+
85
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
86
+ return;
87
+ }
88
+
89
  do_action( 'edd_tools_banned_emails_before' );
90
  ?>
91
  <div class="postbox">
92
  <h3><span><?php _e( 'Banned Emails', 'edd' ); ?></span></h3>
93
  <div class="inside">
94
+ <p><?php _e( 'Emails placed in the box below will not be allowed to make purchases. To ban an entire domain, enter the domain starting with "@".', 'edd' ); ?></p>
95
  <form method="post" action="<?php echo admin_url( 'edit.php?post_type=download&page=edd-tools&tab=general' ); ?>">
96
  <p>
97
  <textarea name="banned_emails" rows="10" class="large-text"><?php echo implode( "\n", edd_get_banned_emails() ); ?></textarea>
98
+ <span class="description"><?php _e( 'Enter emails and/or to disallow, one per line', 'edd' ); ?></span>
99
  </p>
100
  <p>
101
  <input type="hidden" name="edd_action" value="save_banned_emails" />
107
  </div><!-- .postbox -->
108
  <?php
109
  do_action( 'edd_tools_banned_emails_after' );
110
+ do_action( 'edd_tools_after' );
111
  }
112
  add_action( 'edd_tools_tab_general', 'edd_tools_banned_emails_display' );
113
 
114
+ /**
115
+ * Display the clear upgrades tab
116
+ *
117
+ * @since 2.3.5
118
+ * @return void
119
+ */
120
+ function edd_tools_clear_doing_upgrade_display() {
121
+
122
+ if( ! current_user_can( 'manage_shop_settings' ) || false === get_option( 'edd_doing_upgrade' ) ) {
123
+ return;
124
+ }
125
+
126
+ do_action( 'edd_tools_clear_doing_upgrade_before' );
127
+ ?>
128
+ <div class="postbox">
129
+ <h3><span><?php _e( 'Clear Incomplete Upgrade Notice', 'edd' ); ?></span></h3>
130
+ <div class="inside">
131
+ <p><?php _e( 'Sometimes a database upgrade notice may not be cleared after an upgrade is completed due to conflicts with other extensions or other minor issues.', 'edd' ); ?></p>
132
+ <p><?php _e( 'If you\'re certain these upgrades have been completed, you can clear these upgrade notices by clicking the button below. If you have any questions about this, please contact the Easy Digital Downloads support team and we\'ll be happy to help.', 'edd' ); ?></p>
133
+ <form method="post" action="<?php echo admin_url( 'edit.php?post_type=download&page=edd-tools&tab=general' ); ?>">
134
+ <p>
135
+ <input type="hidden" name="edd_action" value="clear_doing_upgrade" />
136
+ <?php wp_nonce_field( 'edd_clear_upgrades_nonce', 'edd_clear_upgrades_nonce' ); ?>
137
+ <?php submit_button( __( 'Clear Incomplete Upgrade Notice', 'edd' ), 'secondary', 'submit', false ); ?>
138
+ </p>
139
+ </form>
140
+ </div><!-- .inside -->
141
+ </div><!-- .postbox -->
142
+ <?php
143
+ do_action( 'edd_tools_clear_doing_upgrade_after' );
144
+ }
145
+ add_action( 'edd_tools_tab_general', 'edd_tools_clear_doing_upgrade_display' );
146
 
147
  /**
148
  * Display the API Keys
151
  * @return void
152
  */
153
  function edd_tools_api_keys_display() {
154
+
155
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
156
+ return;
157
+ }
158
+
159
  do_action( 'edd_tools_api_keys_before' );
160
 
161
  require_once EDD_PLUGIN_DIR . 'includes/admin/class-api-keys-table.php';
185
  * @return void
186
  */
187
  function edd_tools_banned_emails_save() {
 
 
188
 
189
  global $edd_options;
190
 
191
+ if( ! wp_verify_nonce( $_POST['edd_banned_emails_nonce'], 'edd_banned_emails_nonce' ) ) {
192
+ return;
193
+ }
194
+
195
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
196
+ return;
197
+ }
198
+
199
+
200
  // Sanitize the input
201
  $emails = array_map( 'trim', explode( "\n", $_POST['banned_emails'] ) );
202
+ $emails = array_unique( $emails );
203
+ $emails = array_map( 'sanitize_text_field', $emails );
204
+
205
+ foreach( $emails as $id => $email ) {
206
+ if( ! is_email( $email ) ) {
207
+ if( $email[0] != '@' ) {
208
+ unset( $emails[$id] );
209
+ }
210
+ }
211
+ }
212
 
213
  $edd_options['banned_emails'] = $emails;
214
  update_option( 'edd_settings', $edd_options );
215
  }
216
  add_action( 'edd_save_banned_emails', 'edd_tools_banned_emails_save' );
217
 
218
+ /**
219
+ * Execute upgrade notice clear
220
+ *
221
+ * @since 2.3.5
222
+ * @return void
223
+ */
224
+ function edd_tools_clear_upgrade_notice() {
225
+ if( ! wp_verify_nonce( $_POST['edd_clear_upgrades_nonce'], 'edd_clear_upgrades_nonce' ) ) {
226
+ return;
227
+ }
228
+
229
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
230
+ return;
231
+ }
232
+
233
+ delete_option( 'edd_doing_upgrade' );
234
+ }
235
+ add_action( 'edd_clear_doing_upgrade', 'edd_tools_clear_upgrade_notice' );
236
+
237
 
238
  /**
239
  * Display the tools import/export tab
242
  * @return void
243
  */
244
  function edd_tools_import_export_display() {
245
+
246
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
247
+ return;
248
+ }
249
+
250
  do_action( 'edd_tools_import_export_before' );
251
  ?>
252
  <div class="postbox">
313
 
314
  nocache_headers();
315
  header( 'Content-Type: application/json; charset=utf-8' );
316
+ header( 'Content-Disposition: attachment; filename=' . apply_filters( 'edd_settings_export_filename', 'edd-settings-export-' . date( 'm-d-Y' ) ) . '.json' );
317
  header( "Expires: 0" );
318
 
319
  echo json_encode( $settings );
340
  return;
341
 
342
  if( edd_get_file_extension( $_FILES['import_file']['name'] ) != 'json' ) {
343
+ wp_die( __( 'Please upload a valid .json file', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 400 ) );
344
  }
345
 
346
  $import_file = $_FILES['import_file']['tmp_name'];
347
 
348
  if( empty( $import_file ) ) {
349
+ wp_die( __( 'Please upload a file to import', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 400 ) );
350
  }
351
 
352
  // Retrieve the settings from the file and convert the json object to an array
367
  * @return void
368
  */
369
  function edd_tools_sysinfo_display() {
370
+
371
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
372
+ return;
373
+ }
374
+
375
  ?>
376
  <form action="<?php echo esc_url( admin_url( 'edit.php?post_type=download&page=edd-tools&tab=system_info' ) ); ?>" method="post" dir="ltr">
377
  <textarea readonly="readonly" onclick="this.focus(); this.select()" id="system-info-textarea" name="edd-sysinfo" title="To copy the system info, click below then press Ctrl + C (PC) or Cmd + C (Mac)."><?php echo edd_tools_sysinfo_get(); ?></textarea>
391
  * @since 2.0
392
  * @access public
393
  * @global object $wpdb Used to query the database using the WordPress Database API
 
394
  * @return string $return A string containing the info to output
395
  */
396
  function edd_tools_sysinfo_get() {
397
+ global $wpdb;
398
 
399
  if( !class_exists( 'Browser' ) )
400
  require_once EDD_PLUGIN_DIR . 'includes/libraries/browser.php';
474
 
475
  $return .= 'Remote Post: ' . $WP_REMOTE_POST . "\n";
476
  $return .= 'Table Prefix: ' . 'Length: ' . strlen( $wpdb->prefix ) . ' Status: ' . ( strlen( $wpdb->prefix ) > 16 ? 'ERROR: Too long' : 'Acceptable' ) . "\n";
477
+ $return .= 'Admin AJAX: ' . ( edd_test_ajax_works() ? 'Accessible' : 'Inaccessible' ) . "\n";
478
  $return .= 'WP_DEBUG: ' . ( defined( 'WP_DEBUG' ) ? WP_DEBUG ? 'Enabled' : 'Disabled' : 'Not set' ) . "\n";
479
  $return .= 'Memory Limit: ' . WP_MEMORY_LIMIT . "\n";
480
  $return .= 'Registered Post Stati: ' . implode( ', ', get_post_stati() ) . "\n";
488
  $return .= 'Test Mode: ' . ( edd_is_test_mode() ? "Enabled\n" : "Disabled\n" );
489
  $return .= 'Ajax: ' . ( ! edd_is_ajax_disabled() ? "Enabled\n" : "Disabled\n" );
490
  $return .= 'Guest Checkout: ' . ( edd_no_guest_checkout() ? "Disabled\n" : "Enabled\n" );
491
+ $return .= 'Symlinks: ' . ( apply_filters( 'edd_symlink_file_downloads', edd_get_option( 'symlink_file_downloads', false ) ) && function_exists( 'symlink' ) ? "Enabled\n" : "Disabled\n" );
492
  $return .= 'Download Method: ' . ucfirst( edd_get_file_download_method() ) . "\n";
493
+ $return .= 'Currency Code: ' . edd_get_currency() . "\n";
494
+ $return .= 'Currency Position: ' . edd_get_option( 'currency_position', 'before' ) . "\n";
495
+ $return .= 'Decimal Separator: ' . edd_get_option( 'decimal_separator', '.' ) . "\n";
496
+ $return .= 'Thousands Separator: ' . edd_get_option( 'thousands_separator', ',' ) . "\n";
497
+ $return .= 'Upgrades Completed: ' . implode( ',', edd_get_completed_upgrades() ) . "\n";
498
 
499
  $return = apply_filters( 'edd_sysinfo_after_edd_config', $return );
500
 
501
  // EDD pages
502
+ $purchase_page = edd_get_option( 'purchase_page', '' );
503
+ $success_page = edd_get_option( 'success_page', '' );
504
+ $failure_page = edd_get_option( 'failure_page', '' );
505
+
506
  $return .= "\n" . '-- EDD Page Configuration' . "\n\n";
507
+ $return .= 'Checkout: ' . ( !empty( $purchase_page ) ? "Valid\n" : "Invalid\n" );
508
+ $return .= 'Checkout Page: ' . ( !empty( $purchase_page ) ? get_permalink( $purchase_page ) . "\n" : "Unset\n" );
509
+ $return .= 'Success Page: ' . ( !empty( $success_page ) ? get_permalink( $success_page ) . "\n" : "Unset\n" );
510
+ $return .= 'Failure Page: ' . ( !empty( $failure_page ) ? get_permalink( $failure_page ) . "\n" : "Unset\n" );
511
  $return .= 'Downloads Slug: ' . ( defined( 'EDD_SLUG' ) ? '/' . EDD_SLUG . "\n" : "/downloads\n" );
512
 
513
  $return = apply_filters( 'edd_sysinfo_after_edd_pages', $return );
542
  // EDD Taxes
543
  $return .= "\n" . '-- EDD Tax Configuration' . "\n\n";
544
  $return .= 'Taxes: ' . ( edd_use_taxes() ? "Enabled\n" : "Disabled\n" );
 
545
  $return .= 'Tax Rate: ' . edd_get_tax_rate() * 100 . "\n";
546
+ $return .= 'Display On Checkout: ' . ( edd_get_option( 'checkout_include_tax', false ) ? "Displayed\n" : "Not Displayed\n" );
547
  $return .= 'Prices Include Tax: ' . ( edd_prices_include_tax() ? "Yes\n" : "No\n" );
548
+
 
549
  $rates = edd_get_tax_rates();
550
  if( !empty( $rates ) ) {
551
  $return .= 'Country / State Rates: ' . "\n";
564
  foreach( glob( $dir ) as $file ) {
565
  $return .= 'Filename: ' . basename( $file ) . "\n";
566
  }
567
+
568
  $return = apply_filters( 'edd_sysinfo_after_edd_templates', $return );
569
  }
570
 
571
+ // Must-use plugins
572
+ $muplugins = get_mu_plugins();
573
+ if( count( $muplugins > 0 ) ) {
574
+ $return .= "\n" . '-- Must-Use Plugins' . "\n\n";
575
+
576
+ foreach( $muplugins as $plugin => $plugin_data ) {
577
+ $return .= $plugin_data['Name'] . ': ' . $plugin_data['Version'] . "\n";
578
+ }
579
+
580
+ $return = apply_filters( 'edd_sysinfo_after_wordpress_mu_plugins', $return );
581
+ }
582
+
583
  // WordPress active plugins
584
  $return .= "\n" . '-- WordPress Active Plugins' . "\n\n";
585
+
586
  $plugins = get_plugins();
587
  $active_plugins = get_option( 'active_plugins', array() );
588
 
630
  // Server configuration (really just versioning)
631
  $return .= "\n" . '-- Webserver Configuration' . "\n\n";
632
  $return .= 'PHP Version: ' . PHP_VERSION . "\n";
633
+ $return .= 'MySQL Version: ' . $wpdb->db_version() . "\n";
634
  $return .= 'Webserver Info: ' . $_SERVER['SERVER_SOFTWARE'] . "\n";
635
 
636
  $return = apply_filters( 'edd_sysinfo_after_webserver_config', $return );
659
 
660
  // Session stuff
661
  $return .= "\n" . '-- Session Configuration' . "\n\n";
662
+ $return .= 'EDD Use Sessions: ' . ( defined( 'EDD_USE_PHP_SESSIONS' ) && EDD_USE_PHP_SESSIONS ? 'Enforced' : ( EDD()->session->use_php_sessions() ? 'Enabled' : 'Disabled' ) ) . "\n";
663
  $return .= 'Session: ' . ( isset( $_SESSION ) ? 'Enabled' : 'Disabled' ) . "\n";
664
 
665
  // The rest of this is only relevant is session is enabled
686
  * @return void
687
  */
688
  function edd_tools_sysinfo_download() {
689
+
690
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
691
+ return;
692
+ }
693
+
694
  nocache_headers();
695
 
696
  header( 'Content-Type: text/plain' );
includes/admin/tracking.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8.2
10
  */
@@ -33,7 +33,6 @@ class EDD_Tracking {
33
  * Get things going
34
  *
35
  * @access public
36
- * @return void
37
  */
38
  public function __construct() {
39
 
@@ -53,8 +52,9 @@ class EDD_Tracking {
53
  * @return bool
54
  */
55
  private function tracking_allowed() {
56
- global $edd_options;
57
- return isset( $edd_options['allow_tracking'] );
 
58
  }
59
 
60
  /**
@@ -124,7 +124,7 @@ class EDD_Tracking {
124
  'method' => 'POST',
125
  'timeout' => 20,
126
  'redirection' => 5,
127
- 'httpversion' => '1.0',
128
  'blocking' => true,
129
  'body' => $this->data,
130
  'user-agent' => 'EDD/' . EDD_VERSION . '; ' . get_bloginfo( 'url' )
@@ -197,7 +197,7 @@ class EDD_Tracking {
197
  * Get the last time a checkin was sent
198
  *
199
  * @access private
200
- * @return false/string
201
  */
202
  private function get_last_send() {
203
  return get_option( 'edd_tracking_last_send' );
@@ -221,21 +221,18 @@ class EDD_Tracking {
221
  * @return void
222
  */
223
  public function admin_notice() {
224
-
225
- global $edd_options;
226
-
227
  $hide_notice = get_option( 'edd_tracking_notice' );
228
 
229
  if( $hide_notice )
230
  return;
231
 
232
- if( isset( $edd_options['allow_tracking'] ) )
233
  return;
234
 
235
  if( ! current_user_can( 'manage_options' ) )
236
  return;
237
 
238
- if(
239
  stristr( network_site_url( '/' ), 'dev' ) !== false ||
240
  stristr( network_site_url( '/' ), 'localhost' ) !== false ||
241
  stristr( network_site_url( '/' ), ':8888' ) !== false // This is common with MAMP on OS X
4
  *
5
  * @package EDD
6
  * @subpackage Admin
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8.2
10
  */
33
  * Get things going
34
  *
35
  * @access public
 
36
  */
37
  public function __construct() {
38
 
52
  * @return bool
53
  */
54
  private function tracking_allowed() {
55
+ $allow_tracking = edd_get_option( 'allow_tracking', false );
56
+
57
+ return isset( $allow_tracking );
58
  }
59
 
60
  /**
124
  'method' => 'POST',
125
  'timeout' => 20,
126
  'redirection' => 5,
127
+ 'httpversion' => '1.1',
128
  'blocking' => true,
129
  'body' => $this->data,
130
  'user-agent' => 'EDD/' . EDD_VERSION . '; ' . get_bloginfo( 'url' )
197
  * Get the last time a checkin was sent
198
  *
199
  * @access private
200
+ * @return false|string
201
  */
202
  private function get_last_send() {
203
  return get_option( 'edd_tracking_last_send' );
221
  * @return void
222
  */
223
  public function admin_notice() {
 
 
 
224
  $hide_notice = get_option( 'edd_tracking_notice' );
225
 
226
  if( $hide_notice )
227
  return;
228
 
229
+ if( edd_get_option( 'allow_tracking', false ) )
230
  return;
231
 
232
  if( ! current_user_can( 'manage_options' ) )
233
  return;
234
 
235
+ if(
236
  stristr( network_site_url( '/' ), 'dev' ) !== false ||
237
  stristr( network_site_url( '/' ), 'localhost' ) !== false ||
238
  stristr( network_site_url( '/' ), ':8888' ) !== false // This is common with MAMP on OS X
includes/admin/upgrades/upgrade-functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Upgrades
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.3.1
10
  */
@@ -73,11 +73,67 @@ function edd_show_upgrade_notices() {
73
  );
74
  }
75
 
76
- if ( EDD()->session->get( 'upgrade_sequential' ) && edd_get_payments() ) {
 
 
 
 
77
  printf(
78
- '<div class="updated"><p>' . __( 'Easy Digital Downloads needs to upgrade past order numbers to make them sequential, click <a href="%s">here</a> to start the upgrade.', 'edd' ) . '</p></div>',
79
- admin_url( 'index.php?page=edd-upgrades&edd-upgrade=upgrade_sequential_payment_numbers' )
80
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  }
82
 
83
  }
@@ -92,6 +148,11 @@ add_action( 'admin_notices', 'edd_show_upgrade_notices' );
92
  * @return void
93
  */
94
  function edd_trigger_upgrades() {
 
 
 
 
 
95
  $edd_version = get_option( 'edd_version' );
96
 
97
  if ( ! $edd_version ) {
@@ -127,6 +188,82 @@ function edd_trigger_upgrades() {
127
  }
128
  add_action( 'wp_ajax_edd_trigger_upgrades', 'edd_trigger_upgrades' );
129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  /**
131
  * Converts old sale and file download logs to new logging system
132
  *
@@ -154,12 +291,10 @@ function edd_v131_upgrades() {
154
  );
155
 
156
  $query = new WP_Query( $args );
157
- $count = $query->post_count;
158
  $downloads = $query->get_posts();
159
 
160
  if ( $downloads ) {
161
  $edd_log = new EDD_Logging();
162
- $i = 0;
163
  foreach ( $downloads as $download ) {
164
  // Convert sale logs
165
  $sale_logs = edd_get_download_sales_log( $download->ID, false );
@@ -260,7 +395,6 @@ function edd_v14_upgrades() {
260
 
261
  if ( $discounts ) {
262
  foreach ( $discounts as $discount_key => $discount ) {
263
- $status = isset( $discount['status'] ) ? $discount['status'] : 'inactive';
264
 
265
  $discount_id = wp_insert_post( array(
266
  'post_type' => 'edd_discount',
@@ -368,6 +502,10 @@ function edd_v20_upgrades() {
368
  */
369
  function edd_v20_upgrade_sequential_payment_numbers() {
370
 
 
 
 
 
371
  ignore_user_abort( true );
372
 
373
  if ( ! edd_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
@@ -401,15 +539,15 @@ function edd_v20_upgrade_sequential_payment_numbers() {
401
  $number = ! empty( $_GET['custom'] ) ? absint( $_GET['custom'] ) : intval( edd_get_option( 'sequential_start', 1 ) );
402
 
403
  foreach( $payments as $payment ) {
404
-
405
  // Re-add the prefix and postfix
406
  $payment_number = $prefix . $number . $postfix;
407
 
408
- update_post_meta( $payment->ID, '_edd_payment_number', $payment_number );
409
 
410
  // Increment the payment number
411
  $number++;
412
-
413
  }
414
 
415
  // Payments found so upgrade them
@@ -428,8 +566,421 @@ function edd_v20_upgrade_sequential_payment_numbers() {
428
 
429
  // No more payments found, finish up
430
  EDD()->session->set( 'upgrade_sequential', null );
 
 
431
  wp_redirect( admin_url() ); exit;
432
  }
433
 
434
  }
435
  add_action( 'edd_upgrade_sequential_payment_numbers', 'edd_v20_upgrade_sequential_payment_numbers' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Upgrades
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.3.1
10
  */
73
  );
74
  }
75
 
76
+ // Sequential Orders was the first stepped upgrade, so check if we have a stalled upgrade
77
+ $resume_upgrade = edd_maybe_resume_upgrade();
78
+ if ( ! empty( $resume_upgrade ) ) {
79
+
80
+ $resume_url = add_query_arg( $resume_upgrade, admin_url( 'index.php' ) );
81
  printf(
82
+ '<div class="error"><p>' . __( 'Easy Digital Downloads needs to complete a database upgrade that was previously started, click <a href="%s">here</a> to resume the upgrade.', 'edd' ) . '</p></div>',
83
+ esc_url( $resume_url )
84
  );
85
+
86
+ } else {
87
+
88
+ // Include all 'Stepped' upgrade process notices in this else statement,
89
+ // to avoid having a pending, and new upgrade suggested at the same time
90
+
91
+ if ( EDD()->session->get( 'upgrade_sequential' ) && edd_get_payments() ) {
92
+ printf(
93
+ '<div class="updated"><p>' . __( 'Easy Digital Downloads needs to upgrade past order numbers to make them sequential, click <a href="%s">here</a> to start the upgrade.', 'edd' ) . '</p></div>',
94
+ admin_url( 'index.php?page=edd-upgrades&edd-upgrade=upgrade_sequential_payment_numbers' )
95
+ );
96
+ }
97
+
98
+ if ( version_compare( $edd_version, '2.1', '<' ) ) {
99
+ printf(
100
+ '<div class="updated"><p>' . esc_html__( 'Easy Digital Downloads needs to upgrade the customer database, click %shere%s to start the upgrade.', 'edd' ) . '</p></div>',
101
+ '<a href="' . esc_url( admin_url( 'index.php?page=edd-upgrades&edd-upgrade=upgrade_customers_db' ) ) . '">',
102
+ '</a>'
103
+ );
104
+ }
105
+
106
+ if ( version_compare( $edd_version, '2.2.6', '<' ) ) {
107
+ printf(
108
+ '<div class="updated"><p>' . __( 'Easy Digital Downloads needs to upgrade the payment database, click <a href="%s">here</a> to start the upgrade.', 'edd' ) . '</p></div>',
109
+ esc_url( admin_url( 'index.php?page=edd-upgrades&edd-upgrade=upgrade_payments_price_logs_db' ) )
110
+ );
111
+ }
112
+
113
+ if ( version_compare( $edd_version, '2.3', '<' ) || ! edd_has_upgrade_completed( 'upgrade_customer_payments_association' ) ) {
114
+ printf(
115
+ '<div class="updated"><p>' . __( 'Easy Digital Downloads needs to upgrade the customer database, click <a href="%s">here</a> to start the upgrade.', 'edd' ) . '</p></div>',
116
+ esc_url( admin_url( 'index.php?page=edd-upgrades&edd-upgrade=upgrade_customer_payments_association' ) )
117
+ );
118
+ }
119
+
120
+ if ( version_compare( $edd_version, '2.3', '<' ) || ! edd_has_upgrade_completed( 'upgrade_payment_taxes' ) ) {
121
+ printf(
122
+ '<div class="updated"><p>' . __( 'Easy Digital Downloads needs to upgrade the payments database, click <a href="%s">here</a> to start the upgrade.', 'edd' ) . '</p></div>',
123
+ esc_url( admin_url( 'index.php?page=edd-upgrades&edd-upgrade=upgrade_payment_taxes' ) )
124
+ );
125
+ }
126
+
127
+ /*
128
+ * NOTICE:
129
+ *
130
+ * When adding new upgrade notices, please be sure to put the action into the upgrades array during install:
131
+ * /includes/install.php @ Appox Line 156
132
+ *
133
+ */
134
+
135
+ // End 'Stepped' upgrade process notices
136
+
137
  }
138
 
139
  }
148
  * @return void
149
  */
150
  function edd_trigger_upgrades() {
151
+
152
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
153
+ wp_die( __( 'You do not have permission to do shop upgrades', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
154
+ }
155
+
156
  $edd_version = get_option( 'edd_version' );
157
 
158
  if ( ! $edd_version ) {
188
  }
189
  add_action( 'wp_ajax_edd_trigger_upgrades', 'edd_trigger_upgrades' );
190
 
191
+ /**
192
+ * For use when doing 'stepped' upgrade routines, to see if we need to start somewhere in the middle
193
+ * @since 2.2.6
194
+ * @return mixed When nothing to resume returns false, otherwise starts the upgrade where it left off
195
+ */
196
+ function edd_maybe_resume_upgrade() {
197
+
198
+ $doing_upgrade = get_option( 'edd_doing_upgrade', false );
199
+
200
+ if ( empty( $doing_upgrade ) ) {
201
+ return false;
202
+ }
203
+
204
+ return $doing_upgrade;
205
+
206
+ }
207
+
208
+ /**
209
+ * Check if the upgrade routine has been run for a specific action
210
+ *
211
+ * @since 2.3
212
+ * @param string $upgrade_action The upgrade action to check completion for
213
+ * @return bool If the action has been added to the copmleted actions array
214
+ */
215
+ function edd_has_upgrade_completed( $upgrade_action = '' ) {
216
+
217
+ if ( empty( $upgrade_action ) ) {
218
+ return false;
219
+ }
220
+
221
+ $completed_upgrades = edd_get_completed_upgrades();
222
+
223
+ return in_array( $upgrade_action, $completed_upgrades );
224
+
225
+ }
226
+
227
+ /**
228
+ * Adds an upgrade action to the completed upgrades array
229
+ *
230
+ * @since 2.3
231
+ * @param string $upgrade_action The action to add to the copmleted upgrades array
232
+ * @return bool If the function was successfully added
233
+ */
234
+ function edd_set_upgrade_complete( $upgrade_action = '' ) {
235
+
236
+ if ( empty( $upgrade_action ) ) {
237
+ return false;
238
+ }
239
+
240
+ $completed_upgrades = edd_get_completed_upgrades();
241
+ $completed_upgrades[] = $upgrade_action;
242
+
243
+ // Remove any blanks, and only show uniques
244
+ $completed_upgrades = array_unique( array_values( $completed_upgrades ) );
245
+
246
+ return update_option( 'edd_completed_upgrades', $completed_upgrades );
247
+ }
248
+
249
+ /**
250
+ * Get's the array of completed upgrade actions
251
+ *
252
+ * @since 2.3
253
+ * @return array The array of completed upgrades
254
+ */
255
+ function edd_get_completed_upgrades() {
256
+
257
+ $completed_upgrades = get_option( 'edd_completed_upgrades' );
258
+
259
+ if ( false === $completed_upgrades ) {
260
+ $completed_upgrades = array();
261
+ }
262
+
263
+ return $completed_upgrades;
264
+
265
+ }
266
+
267
  /**
268
  * Converts old sale and file download logs to new logging system
269
  *
291
  );
292
 
293
  $query = new WP_Query( $args );
 
294
  $downloads = $query->get_posts();
295
 
296
  if ( $downloads ) {
297
  $edd_log = new EDD_Logging();
 
298
  foreach ( $downloads as $download ) {
299
  // Convert sale logs
300
  $sale_logs = edd_get_download_sales_log( $download->ID, false );
395
 
396
  if ( $discounts ) {
397
  foreach ( $discounts as $discount_key => $discount ) {
 
398
 
399
  $discount_id = wp_insert_post( array(
400
  'post_type' => 'edd_discount',
502
  */
503
  function edd_v20_upgrade_sequential_payment_numbers() {
504
 
505
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
506
+ wp_die( __( 'You do not have permission to do shop upgrades', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
507
+ }
508
+
509
  ignore_user_abort( true );
510
 
511
  if ( ! edd_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
539
  $number = ! empty( $_GET['custom'] ) ? absint( $_GET['custom'] ) : intval( edd_get_option( 'sequential_start', 1 ) );
540
 
541
  foreach( $payments as $payment ) {
542
+
543
  // Re-add the prefix and postfix
544
  $payment_number = $prefix . $number . $postfix;
545
 
546
+ edd_update_payment_meta( $payment->ID, '_edd_payment_number', $payment_number );
547
 
548
  // Increment the payment number
549
  $number++;
550
+
551
  }
552
 
553
  // Payments found so upgrade them
566
 
567
  // No more payments found, finish up
568
  EDD()->session->set( 'upgrade_sequential', null );
569
+ delete_option( 'edd_doing_upgrade' );
570
+
571
  wp_redirect( admin_url() ); exit;
572
  }
573
 
574
  }
575
  add_action( 'edd_upgrade_sequential_payment_numbers', 'edd_v20_upgrade_sequential_payment_numbers' );
576
+
577
+ /**
578
+ * Upgrades for EDD v2.1 and the new customers database
579
+ *
580
+ * @since 2.1
581
+ * @return void
582
+ */
583
+ function edd_v21_upgrade_customers_db() {
584
+
585
+ global $wpdb;
586
+
587
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
588
+ wp_die( __( 'You do not have permission to do shop upgrades', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
589
+ }
590
+
591
+ ignore_user_abort( true );
592
+
593
+ if ( ! edd_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
594
+ @set_time_limit(0);
595
+ }
596
+
597
+ if( ! get_option( 'edd_upgrade_customers_db_version' ) ) {
598
+ // Create the customers database on the first run
599
+ @EDD()->customers->create_table();
600
+ }
601
+
602
+ $step = isset( $_GET['step'] ) ? absint( $_GET['step'] ) : 1;
603
+ $number = 20;
604
+ $offset = $step == 1 ? 0 : ( $step - 1 ) * $number;
605
+
606
+ $emails = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT meta_value FROM $wpdb->postmeta WHERE meta_key = '_edd_payment_user_email' LIMIT %d,%d;", $offset, $number ) );
607
+
608
+ if( $emails ) {
609
+
610
+ foreach( $emails as $email ) {
611
+
612
+ if( EDD()->customers->exists( $email ) ) {
613
+ continue; // Allow the upgrade routine to be safely re-run in the case of failure
614
+ }
615
+
616
+ $args = array(
617
+ 'user' => $email,
618
+ 'order' => 'ASC',
619
+ 'orderby' => 'ID',
620
+ 'number' => -1,
621
+ 'page' => $step
622
+ );
623
+
624
+ $payments = new EDD_Payments_Query( $args );
625
+ $payments = $payments->get_payments();
626
+
627
+ if( $payments ) {
628
+
629
+ $total_value = 0.00;
630
+ $total_count = 0;
631
+
632
+ foreach( $payments as $payment ) {
633
+
634
+ $status = get_post_status( $payment->ID );
635
+ if( 'revoked' == $status || 'publish' == $status ) {
636
+
637
+ $total_value += $payment->total;
638
+ $total_count += 1;
639
+
640
+ }
641
+
642
+ }
643
+
644
+ $ids = wp_list_pluck( $payments, 'ID' );
645
+
646
+ $user = get_user_by( 'email', $email );
647
+
648
+ $args = array(
649
+ 'email' => $email,
650
+ 'user_id' => $user ? $user->ID : 0,
651
+ 'name' => $user ? $user->display_name : '',
652
+ 'purchase_count' => $total_count,
653
+ 'purchase_value' => round( $total_value, 2 ),
654
+ 'payment_ids' => implode( ',', array_map( 'absint', $ids ) ),
655
+ 'date_created' => $payments[0]->date
656
+ );
657
+
658
+ $customer_id = EDD()->customers->add( $args );
659
+
660
+ foreach( $ids as $id ) {
661
+ update_post_meta( $id, '_edd_payment_customer_id', $customer_id );
662
+ }
663
+
664
+ }
665
+
666
+ }
667
+
668
+ // Customers found so upgrade them
669
+ $step++;
670
+ $redirect = add_query_arg( array(
671
+ 'page' => 'edd-upgrades',
672
+ 'edd-upgrade' => 'upgrade_customers_db',
673
+ 'step' => $step
674
+ ), admin_url( 'index.php' ) );
675
+ wp_redirect( $redirect ); exit;
676
+
677
+ } else {
678
+
679
+ // No more customers found, finish up
680
+
681
+ update_option( 'edd_version', preg_replace( '/[^0-9.].*/', '', EDD_VERSION ) );
682
+ delete_option( 'edd_doing_upgrade' );
683
+
684
+ wp_redirect( admin_url() ); exit;
685
+ }
686
+
687
+ }
688
+ add_action( 'edd_upgrade_customers_db', 'edd_v21_upgrade_customers_db' );
689
+
690
+ /**
691
+ * Fixes the edd_log meta for 2.2.6
692
+ *
693
+ * @since 2.2.6
694
+ * @return void
695
+ */
696
+ function edd_v226_upgrade_payments_price_logs_db() {
697
+ global $wpdb;
698
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
699
+ wp_die( __( 'You do not have permission to do shop upgrades', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
700
+ }
701
+ ignore_user_abort( true );
702
+ if ( ! edd_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
703
+ @set_time_limit(0);
704
+ }
705
+ $step = isset( $_GET['step'] ) ? absint( $_GET['step'] ) : 1;
706
+ $number = 25;
707
+ $offset = $step == 1 ? 0 : ( $step - 1 ) * $number;
708
+ if ( 1 === $step ) {
709
+ // Check if we have any variable price products on the first step
710
+ $sql = "SELECT ID FROM $wpdb->posts p LEFT JOIN $wpdb->postmeta m ON p.ID = m.post_id WHERE m.meta_key = '_variable_pricing' AND m.meta_value = 1 LIMIT 1";
711
+ $has_variable = $wpdb->get_col( $sql );
712
+ if( empty( $has_variable ) ) {
713
+ // We had no variable priced products, so go ahead and just complete
714
+ update_option( 'edd_version', preg_replace( '/[^0-9.].*/', '', EDD_VERSION ) );
715
+ delete_option( 'edd_doing_upgrade' );
716
+ wp_redirect( admin_url() ); exit;
717
+ }
718
+ }
719
+ $payment_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'edd_payment' ORDER BY post_date DESC LIMIT %d,%d;", $offset, $number ) );
720
+ if( ! empty( $payment_ids ) ) {
721
+ foreach( $payment_ids as $payment_id ) {
722
+ $payment_downloads = edd_get_payment_meta_downloads( $payment_id );
723
+ $variable_downloads = array();
724
+ if ( ! is_array( $payment_downloads ) ) {
725
+ continue; // May not be an array due to some very old payments, move along
726
+ }
727
+ foreach ( $payment_downloads as $download ) {
728
+ // Don't care if the download is a single price id
729
+ if ( ! isset( $download['options']['price_id'] ) ) {
730
+ continue;
731
+ }
732
+ $variable_downloads[] = array( 'id' => $download['id'], 'price_id' => $download['options']['price_id'] );
733
+ }
734
+ $variable_download_ids = array_unique( wp_list_pluck( $variable_downloads, 'id' ) );
735
+ $unique_download_ids = implode( ',', $variable_download_ids );
736
+ if ( empty( $unique_download_ids ) ) {
737
+ continue; // If there were no downloads, just fees, move along
738
+ }
739
+ // Get all Log Ids where the post parent is in the set of download IDs we found in the cart meta
740
+ $logs = $wpdb->get_results( "SELECT m.post_id AS log_id, p.post_parent AS download_id FROM $wpdb->postmeta m LEFT JOIN $wpdb->posts p ON m.post_id = p.ID WHERE meta_key = '_edd_log_payment_id' AND meta_value = $payment_id AND p.post_parent IN ($unique_download_ids)", ARRAY_A );
741
+ $mapped_logs = array();
742
+ // Go through each cart item
743
+ foreach( $variable_downloads as $cart_item ) {
744
+ // Itterate through the logs we found attached to this payment
745
+ foreach ( $logs as $key => $log ) {
746
+ // If this Log ID is associated with this download ID give it the price_id
747
+ if ( (int) $log['download_id'] === (int) $cart_item['id'] ) {
748
+ $mapped_logs[$log['log_id']] = $cart_item['price_id'];
749
+ // Remove this Download/Log ID from the list, for multipurchase compatibility
750
+ unset( $logs[$key] );
751
+ // These aren't the logs we're looking for. Move Along, Move Along.
752
+ break;
753
+ }
754
+ }
755
+ }
756
+ if ( ! empty( $mapped_logs ) ) {
757
+ $update = "UPDATE $wpdb->postmeta SET meta_value = ";
758
+ $case = "CASE post_id ";
759
+ foreach ( $mapped_logs as $post_id => $value ) {
760
+ $case .= "WHEN $post_id THEN $value ";
761
+ }
762
+ $case .= "END ";
763
+ $log_ids = implode( ',', array_keys( $mapped_logs ) );
764
+ $where = "WHERE post_id IN ($log_ids) AND meta_key = '_edd_log_price_id'";
765
+ $sql = $update . $case . $where;
766
+ // Execute our query to update this payment
767
+ $wpdb->query( $sql );
768
+ }
769
+ }
770
+ // More Payments found so upgrade them
771
+ $step++;
772
+ $redirect = add_query_arg( array(
773
+ 'page' => 'edd-upgrades',
774
+ 'edd-upgrade' => 'upgrade_payments_price_logs_db',
775
+ 'step' => $step
776
+ ), admin_url( 'index.php' ) );
777
+ wp_redirect( $redirect ); exit;
778
+ } else {
779
+ // No more payments found, finish up
780
+ update_option( 'edd_version', preg_replace( '/[^0-9.].*/', '', EDD_VERSION ) );
781
+ delete_option( 'edd_doing_upgrade' );
782
+ wp_redirect( admin_url() ); exit;
783
+ }
784
+ }
785
+ add_action( 'edd_upgrade_payments_price_logs_db', 'edd_v226_upgrade_payments_price_logs_db' );
786
+
787
+ /**
788
+ * Upgrades payment taxes for 2.3
789
+ *
790
+ * @since 2.3
791
+ * @return void
792
+ */
793
+ function edd_v23_upgrade_payment_taxes() {
794
+ global $wpdb;
795
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
796
+ wp_die( __( 'You do not have permission to do shop upgrades', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
797
+ }
798
+ ignore_user_abort( true );
799
+ if ( ! edd_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
800
+ @set_time_limit(0);
801
+ }
802
+
803
+ $step = isset( $_GET['step'] ) ? absint( $_GET['step'] ) : 1;
804
+ $number = 50;
805
+ $offset = $step == 1 ? 0 : ( $step - 1 ) * $number;
806
+
807
+ if ( $step < 2 ) {
808
+ // Check if we have any payments before moving on
809
+ $sql = "SELECT ID FROM $wpdb->posts WHERE post_type = 'edd_payment' LIMIT 1";
810
+ $has_payments = $wpdb->get_col( $sql );
811
+
812
+ if( empty( $has_payments ) ) {
813
+ // We had no payments, just complete
814
+ update_option( 'edd_version', preg_replace( '/[^0-9.].*/', '', EDD_VERSION ) );
815
+ edd_set_upgrade_complete( 'upgrade_payment_taxes' );
816
+ delete_option( 'edd_doing_upgrade' );
817
+ wp_redirect( admin_url() ); exit;
818
+ }
819
+ }
820
+
821
+ $total = isset( $_GET['total'] ) ? absint( $_GET['total'] ) : false;
822
+ if ( empty( $total ) || $total <= 1 ) {
823
+ $total_sql = "SELECT COUNT(ID) as total_payments FROM $wpdb->posts WHERE post_type = 'edd_payment'";
824
+ $results = $wpdb->get_row( $total_sql, 0 );
825
+
826
+ $total = $results->total_payments;
827
+ }
828
+
829
+ $payment_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type = 'edd_payment' ORDER BY post_date DESC LIMIT %d,%d;", $offset, $number ) );
830
+
831
+ if( $payment_ids ) {
832
+ foreach( $payment_ids as $payment_id ) {
833
+
834
+ // Add the new _edd_payment_meta item
835
+ $payment_tax = edd_get_payment_tax( $payment_id );
836
+ edd_update_payment_meta( $payment_id, '_edd_payment_tax', $payment_tax );
837
+
838
+ }
839
+
840
+ // Payments found so upgrade them
841
+ $step++;
842
+ $redirect = add_query_arg( array(
843
+ 'page' => 'edd-upgrades',
844
+ 'edd-upgrade' => 'upgrade_payment_taxes',
845
+ 'step' => $step,
846
+ 'number' => $number,
847
+ 'total' => $total
848
+ ), admin_url( 'index.php' ) );
849
+ wp_redirect( $redirect ); exit;
850
+ } else {
851
+ // No more payments found, finish up
852
+ update_option( 'edd_version', preg_replace( '/[^0-9.].*/', '', EDD_VERSION ) );
853
+ edd_set_upgrade_complete( 'upgrade_payment_taxes' );
854
+ delete_option( 'edd_doing_upgrade' );
855
+ wp_redirect( admin_url() ); exit;
856
+ }
857
+ }
858
+ add_action( 'edd_upgrade_payment_taxes', 'edd_v23_upgrade_payment_taxes' );
859
+
860
+ /**
861
+ * Run the upgrade for the customers to find all payment attachments
862
+ *
863
+ * @since 2.3
864
+ * @return void
865
+ */
866
+ function edd_v23_upgrade_customer_purchases() {
867
+ global $wpdb;
868
+
869
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
870
+ wp_die( __( 'You do not have permission to do shop upgrades', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
871
+ }
872
+
873
+ ignore_user_abort( true );
874
+
875
+ if ( ! edd_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
876
+ @set_time_limit(0);
877
+ }
878
+
879
+ $step = isset( $_GET['step'] ) ? absint( $_GET['step'] ) : 1;
880
+ $number = 50;
881
+ $offset = $step == 1 ? 0 : ( $step - 1 ) * $number;
882
+
883
+ if ( $step < 2 ) {
884
+ // Check if we have any payments before moving on
885
+ $sql = "SELECT ID FROM $wpdb->posts WHERE post_type = 'edd_payment' LIMIT 1";
886
+ $has_payments = $wpdb->get_col( $sql );
887
+
888
+ if( empty( $has_payments ) ) {
889
+ // We had no payments, just complete
890
+ update_option( 'edd_version', preg_replace( '/[^0-9.].*/', '', EDD_VERSION ) );
891
+ edd_set_upgrade_complete( 'upgrade_customer_payments_association' );
892
+ delete_option( 'edd_doing_upgrade' );
893
+ wp_redirect( admin_url() ); exit;
894
+ }
895
+ }
896
+
897
+ $total = isset( $_GET['total'] ) ? absint( $_GET['total'] ) : false;
898
+
899
+ if ( empty( $total ) || $total <= 1 ) {
900
+ $total = EDD()->customers->count();
901
+ }
902
+
903
+ $customers = EDD()->customers->get_customers( array( 'number' => $number, 'offset' => $offset ) );
904
+
905
+ if( ! empty( $customers ) ) {
906
+
907
+ foreach( $customers as $customer ) {
908
+
909
+ // Get payments by email and user ID
910
+ $select = "SELECT ID FROM $wpdb->posts p ";
911
+ $join = "LEFT JOIN $wpdb->postmeta m ON p.ID = m.post_id ";
912
+ $where = "WHERE p.post_type = 'edd_payment' ";
913
+
914
+ if ( ! empty( $customer->user_id ) && intval( $customer->user_id ) > 0 ) {
915
+ $where .= "AND ( ( m.meta_key = '_edd_payment_user_email' AND m.meta_value = '$customer->email' ) OR ( m.meta_key = '_edd_payment_customer_id' AND m.meta_value = '$customer->id' ) OR ( m.meta_key = '_edd_payment_user_id' AND m.meta_value = '$customer->user_id' ) )";
916
+ } else {
917
+ $where .= "AND ( ( m.meta_key = '_edd_payment_user_email' AND m.meta_value = '$customer->email' ) OR ( m.meta_key = '_edd_payment_customer_id' AND m.meta_value = '$customer->id' ) ) ";
918
+ }
919
+
920
+ $sql = $select . $join . $where;
921
+ $found_payments = $wpdb->get_col( $sql );
922
+
923
+ $unique_payment_ids = array_unique( array_filter( $found_payments ) );
924
+
925
+ if ( ! empty( $unique_payment_ids ) ) {
926
+
927
+ $unique_ids_string = implode( ',', $unique_payment_ids );
928
+
929
+ $customer_data = array( 'payment_ids' => $unique_ids_string );
930
+
931
+ $purchase_value_sql = "SELECT SUM( m.meta_value ) FROM $wpdb->postmeta m LEFT JOIN $wpdb->posts p ON m.post_id = p.ID WHERE m.post_id IN ( $unique_ids_string ) AND p.post_status IN ( 'publish', 'revoked' ) AND m.meta_key = '_edd_payment_total'";
932
+ $purchase_value = $wpdb->get_col( $purchase_value_sql );
933
+
934
+ $purchase_count_sql = "SELECT COUNT( m.post_id ) FROM $wpdb->postmeta m LEFT JOIN $wpdb->posts p ON m.post_id = p.ID WHERE m.post_id IN ( $unique_ids_string ) AND p.post_status IN ( 'publish', 'revoked' ) AND m.meta_key = '_edd_payment_total'";
935
+ $purchase_count = $wpdb->get_col( $purchase_count_sql );
936
+
937
+ if ( ! empty( $purchase_value ) && ! empty( $purchase_count ) ) {
938
+
939
+ $purchase_value = $purchase_value[0];
940
+ $purchase_count = $purchase_count[0];
941
+
942
+ $customer_data['purchase_count'] = $purchase_count;
943
+ $customer_data['purchase_value'] = $purchase_value;
944
+
945
+ }
946
+
947
+ } else {
948
+
949
+ $customer_data['purchase_count'] = 0;
950
+ $customer_data['purchase_value'] = 0;
951
+ $customer_data['payment_ids'] = '';
952
+
953
+ }
954
+
955
+
956
+ if ( ! empty( $customer_data ) ) {
957
+
958
+ $customer = new EDD_Customer( $customer->id );
959
+ $customer->update( $customer_data );
960
+
961
+ }
962
+
963
+ }
964
+
965
+ // More Payments found so upgrade them
966
+ $step++;
967
+ $redirect = add_query_arg( array(
968
+ 'page' => 'edd-upgrades',
969
+ 'edd-upgrade' => 'upgrade_customer_payments_association',
970
+ 'step' => $step,
971
+ 'number' => $number,
972
+ 'total' => $total
973
+ ), admin_url( 'index.php' ) );
974
+ wp_redirect( $redirect ); exit;
975
+ } else {
976
+
977
+ // No more customers found, finish up
978
+
979
+ update_option( 'edd_version', preg_replace( '/[^0-9.].*/', '', EDD_VERSION ) );
980
+ edd_set_upgrade_complete( 'upgrade_customer_payments_association' );
981
+ delete_option( 'edd_doing_upgrade' );
982
+
983
+ wp_redirect( admin_url() ); exit;
984
+ }
985
+ }
986
+ add_action( 'edd_upgrade_customer_payments_association', 'edd_v23_upgrade_customer_purchases' );
includes/admin/upgrades/upgrades.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Upgrades
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.3.1
10
  */
@@ -23,21 +23,37 @@ function edd_upgrades_screen() {
23
  $step = isset( $_GET['step'] ) ? absint( $_GET['step'] ) : 1;
24
  $total = isset( $_GET['total'] ) ? absint( $_GET['total'] ) : false;
25
  $custom = isset( $_GET['custom'] ) ? absint( $_GET['custom'] ) : 0;
26
- $steps = round( ( $total / 100 ), 0 );
27
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  <div class="wrap">
29
  <h2><?php _e( 'Easy Digital Downloads - Upgrades', 'edd' ); ?></h2>
30
-
31
  <?php if( ! empty( $action ) ) : ?>
32
 
33
  <div id="edd-upgrade-status">
34
  <p><?php _e( 'The upgrade process has started, please be patient. This could take several minutes. You will be automatically redirected when the upgrade is finished.', 'edd' ); ?></p>
 
35
  <?php if( ! empty( $total ) ) : ?>
36
- <p><strong><?php printf( __( 'Step %d of approximately %d running', 'edd' ), $step, $steps ); ?>
37
  <?php endif; ?>
38
  </div>
39
  <script type="text/javascript">
40
- document.location.href = "index.php?edd_action=<?php echo $action; ?>&step=<?php echo $step; ?>&total=<?php echo $total; ?>&custom=<?php echo $custom; ?>";
41
  </script>
42
 
43
  <?php else : ?>
@@ -65,4 +81,4 @@ function edd_upgrades_screen() {
65
 
66
  </div>
67
  <?php
68
- }
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Upgrades
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.3.1
10
  */
23
  $step = isset( $_GET['step'] ) ? absint( $_GET['step'] ) : 1;
24
  $total = isset( $_GET['total'] ) ? absint( $_GET['total'] ) : false;
25
  $custom = isset( $_GET['custom'] ) ? absint( $_GET['custom'] ) : 0;
26
+ $number = isset( $_GET['number'] ) ? absint( $_GET['number'] ) : 100;
27
+ $steps = round( ( $total / $number ), 0 );
28
+
29
+ $doing_upgrade_args = array(
30
+ 'page' => 'edd-upgrades',
31
+ 'edd-upgrade' => $action,
32
+ 'step' => $step,
33
+ 'total' => $total,
34
+ 'custom' => $custom,
35
+ 'steps' => $steps
36
+ );
37
+ update_option( 'edd_doing_upgrade', $doing_upgrade_args );
38
+ if ( $step > $steps ) {
39
+ // Prevent a weird case where the estimate was off. Usually only a couple.
40
+ $steps = $step;
41
+ }
42
+ ?>
43
  <div class="wrap">
44
  <h2><?php _e( 'Easy Digital Downloads - Upgrades', 'edd' ); ?></h2>
45
+
46
  <?php if( ! empty( $action ) ) : ?>
47
 
48
  <div id="edd-upgrade-status">
49
  <p><?php _e( 'The upgrade process has started, please be patient. This could take several minutes. You will be automatically redirected when the upgrade is finished.', 'edd' ); ?></p>
50
+
51
  <?php if( ! empty( $total ) ) : ?>
52
+ <p><strong><?php printf( __( 'Step %d of approximately %d running', 'edd' ), $step, $steps ); ?></strong></p>
53
  <?php endif; ?>
54
  </div>
55
  <script type="text/javascript">
56
+ setTimeout(function() { document.location.href = "index.php?edd_action=<?php echo $action; ?>&step=<?php echo $step; ?>&total=<?php echo $total; ?>&custom=<?php echo $custom; ?>"; }, 250);
57
  </script>
58
 
59
  <?php else : ?>
81
 
82
  </div>
83
  <?php
84
+ }
includes/admin/upload-functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Upload
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Upload
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
includes/admin/welcome.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Welcome
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
@@ -55,6 +55,15 @@ class EDD_Welcome {
55
  array( $this, 'about_screen' )
56
  );
57
 
 
 
 
 
 
 
 
 
 
58
  // Getting Started Page
59
  add_dashboard_page(
60
  __( 'Getting started with Easy Digital Downloads', 'edd' ),
@@ -83,6 +92,7 @@ class EDD_Welcome {
83
  */
84
  public function admin_head() {
85
  remove_submenu_page( 'index.php', 'edd-about' );
 
86
  remove_submenu_page( 'index.php', 'edd-getting-started' );
87
  remove_submenu_page( 'index.php', 'edd-credits' );
88
 
@@ -166,62 +176,49 @@ class EDD_Welcome {
166
  <?php $this->tabs(); ?>
167
 
168
  <div class="changelog">
169
- <h3><?php _e( 'Sequential Order Numbers', 'edd' );?></h3>
170
 
171
  <div class="feature-section">
172
 
173
- <img src="<?php echo EDD_PLUGIN_URL . 'assets/images/screenshots/20-sequential.png'; ?>" class="edd-welcome-screenshots"/>
174
 
175
- <h4><?php _e( 'Prefix, Postfix, and Starting Number', 'edd' );?></h4>
176
- <p><?php printf( __( 'Sequential order numbers are now supported out of the box. Simply go to <a href="%s">Settings &rarr; Misc</a> to enable them. The starting number, prefix, and postfix for order numbers can all be easily configured.', 'edd' ), admin_url( 'edit.php?post_type=download&page=edd-settings&tab=misc' ) ); ?></p>
177
 
178
- <h4><?php _e( 'Upgrade Routine', 'edd' );?></h4>
179
- <p><?php _e( 'Sequential order numbers are important for some and even mandatory for others, so we want to ensure that all users can make use of them. For this reason, we have provided a one-click upgrade routine that will update all previous purchase records with sequential order numbers matching your settings.', 'edd' );?></p>
 
 
 
 
 
 
180
 
181
  </div>
182
  </div>
183
 
184
  <div class="changelog">
185
- <h3><?php _e( 'Improved Checkout Experience', 'edd' );?></h3>
186
 
187
  <div class="feature-section">
188
 
189
- <img src="<?php echo EDD_PLUGIN_URL . 'assets/images/screenshots/20-register-login.png'; ?>" class="edd-welcome-screenshots"/>
190
-
191
- <h4><?php _e( 'Registration / Login Forms', 'edd' );?></h4>
192
- <p><?php _e( 'The registration and login form options for the checkout form have been further refined in version 2.0. They now include granular control that let you determine exactly which forms are displayed. You can have just a login form, just a registration form, both forms, or neither. The choice is yours.', 'edd' );?></p>
193
-
194
- <h4><?php _e( 'Live Item Quantity Updates', 'edd' );?></h4>
195
- <p><?php _e( 'Cart item quantities are now updated on the fly when customers adjust them, meaning customers no longer need to click Update Cart and wait for the page to reload to see their new purchase total. This creates a more fluid and rapid checkout experience.', 'edd' );?></p>
196
-
197
- <h4><?php _e( '100% Discounts and Credit Cards', 'edd' );?></h4>
198
- <p><?php _e( 'Many users choose to offer 100% discount codes to customers, perhaps as part of a promotion or giveaway. As of version 2.0, 100% discount codes now work perfectly even when using a credit card processing payment gateway.', 'edd' );?></p>
199
-
200
- <img src="<?php echo EDD_PLUGIN_URL . 'assets/images/screenshots/20-discount.png'; ?>" class="edd-welcome-screenshots"/>
201
-
202
- <h4><?php _e( 'Redeeming Discount Code', 'edd' );?></h4>
203
- <p><?php _e( 'The discount code redemption proceess during checkout is now smoother and more intuitive. Simpler checkout processes for customers means more successful sales for you.', 'edd' );?></p>
204
- <p><?php _e( 'In version 2.0, customers are given the opportunity to redeem their discount code before selecting their payment method, if the site has AJAX processing disabled.', 'edd' );?></p>
205
-
206
 
207
  </div>
208
  </div>
209
 
210
  <div class="changelog">
211
- <h3><?php _e( 'Payment History Enhancements', 'edd' );?></h3>
212
 
213
  <div class="feature-section">
214
 
215
- <h4><?php _e( 'Copy Download Link(s)','edd' );?></h4>
216
- <p><?php _e( 'The Purchased Downloads section of the order details screen now includes an option to copy secure download links for any file purchased, letting you easily copy-and-paste new file download links for customers.', 'edd' );?></p>
217
-
218
- <h4><?php _e( 'Transaction ID Searching', 'edd' ); ?></h4>
219
- <p><?php _e( 'Version 2.0 now supports searching for payment records by the transaction ID from the payment processor. Have you refunded a purchase in PayPal and now need to locate it in your store\'s history? Now it is even easier.', 'edd' ); ?></p>
220
 
221
- <img src="<?php echo EDD_PLUGIN_URL . 'assets/images/screenshots/20-unlimited-downloads.png'; ?>" class="edd-welcome-screenshots"/>
 
222
 
223
- <h4><?php _e( 'Unlimited File Downloads', 'edd' ); ?></h4>
224
- <p><?php _e( 'Several versions ago, EDD supported giving specific customers unlimited file downloads for a particular purchase. This option was accidentially removed but has now been brought back from the sad, sad grave. It is now a happy feature. You can use this option to bypass the standard file download limits imposed on purchases.', 'edd' ); ?></p>
225
 
226
  </div>
227
  </div>
@@ -231,28 +228,65 @@ class EDD_Welcome {
231
 
232
  <div class="feature-section col three-col">
233
  <div>
234
- <h4><?php _e( 'API Keys', 'edd' );?></h4>
235
- <p><?php _e( 'EDD has a complete REST API for interfacing with 3rd party systems, such as mobile devices. Granting users access to the API data was always a bit cumbersome, so in version 2.0 we have introduced a completely new API Keys table under the Tools page.', 'edd' );?></p>
236
 
237
- <h4><?php _e( 'Tools Page', 'edd' );?></h4>
238
- <p><?php _e( 'As more and more tools have been developed to assist with managing your store, the Tools page got a bit cluttered. We have now taken the time to introduce a proper tabbed interface to keep things neat and tidy.', 'edd' );?></p>
 
 
 
 
239
  </div>
240
 
241
  <div>
242
- <h4><?php _e( 'Banned Emails', 'edd' );?></h4>
243
- <p><?php _e( 'Along with the new Tools page, we have introduced a new tool that allows you to blacklist specific email addresses. Emails placed on this list will not be allowed to make purchases. This is useful for combatting fraud.' ,'edd' );?></p>
244
 
245
- <h4><?php _e( 'Shortcode: [edd_register]', 'edd' );?></h4>
246
- <p><?php _e( 'Many users have asked for an option to give potential customers a way to register an account on the site without being required to go through the checkout screen. The new [edd_register] shortcode lets you place a stand-alone registration form on any page.', 'edd' );?></p>
 
 
 
 
247
  </div>
248
 
249
  <div class="last-feature">
250
- <h4><?php _e( 'Export Earnings / Sales Over Time', 'edd' );?></h4>
251
- <p><?php _e( 'The export options have been improved in version 2.0. You can now export a CSV file of earnings and sales over time. Want to have a CSV that shows earnings and sale counts for the last six months? Now you can.', 'edd' );?></p>
252
 
253
- <h4><?php _e( 'Improved Discount Edit Screen', 'edd' ); ?></h4>
254
- <p><?php _e( 'We try and live up to our name and make all aspects of running your store easy. Unfortunately, the options available when creating discount codes have never been <em>easy</em>. Version 2.0 introduces several refinements to the discount edit screen that make it dramatically more intuitive.', 'edd' );?></p>
 
255
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  </div>
257
  </div>
258
 
@@ -407,6 +441,34 @@ class EDD_Welcome {
407
  }
408
 
409
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
  /**
411
  * Render Contributors List
412
  *
@@ -474,12 +536,9 @@ class EDD_Welcome {
474
  *
475
  * @access public
476
  * @since 1.4
477
- * @global $edd_options Array of all the EDD Options
478
  * @return void
479
  */
480
  public function welcome() {
481
- global $edd_options;
482
-
483
  // Bail if no activation redirect
484
  if ( ! get_transient( '_edd_activation_redirect' ) )
485
  return;
4
  *
5
  * @package EDD
6
  * @subpackage Admin/Welcome
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4
10
  */
55
  array( $this, 'about_screen' )
56
  );
57
 
58
+ // Changelog Page
59
+ add_dashboard_page(
60
+ __( 'Easy Digital Downloads Changelog', 'edd' ),
61
+ __( 'Easy Digital Downloads Changelog', 'edd' ),
62
+ $this->minimum_capability,
63
+ 'edd-changelog',
64
+ array( $this, 'changelog_screen' )
65
+ );
66
+
67
  // Getting Started Page
68
  add_dashboard_page(
69
  __( 'Getting started with Easy Digital Downloads', 'edd' ),
92
  */
93
  public function admin_head() {
94
  remove_submenu_page( 'index.php', 'edd-about' );
95
+ remove_submenu_page( 'index.php', 'edd-changelog' );
96
  remove_submenu_page( 'index.php', 'edd-getting-started' );
97
  remove_submenu_page( 'index.php', 'edd-credits' );
98
 
176
  <?php $this->tabs(); ?>
177
 
178
  <div class="changelog">
179
+ <h3><?php _e( 'New Customer Management UI', 'edd' );?></h3>
180
 
181
  <div class="feature-section">
182
 
183
+ <p><?php _e( 'Version 2.3 introduces a comprehensive customer management interface. Get detailed statistics on your customers, quickly make edits, and leave detailed notes.', 'edd' );?></p>
184
 
185
+ <img src="<?php echo EDD_PLUGIN_URL . 'assets/images/screenshots/customer-ui.png'; ?>" class="edd-welcome-screenshots"/>
 
186
 
187
+ <h4><?php _e( 'Better Customer Details on Payment', 'edd' );?></h4>
188
+ <p><?php _e( 'The Customer Details section of the View Order Details screen has been updated to make it easier to move payment records between customers. A quick link to the customer\'s overview page has also been added, letting you easily see all purchases made by the customer.', 'edd' );?></p>
189
+
190
+ <h4><?php _e( 'Create New Customers Quickly', 'edd' );?></h4>
191
+ <p><?php _e( 'New customer records can now be created directly from the View Order Details screen, making it easier for you to manage change requests from your customers.', 'edd' );?></p>
192
+
193
+ <h4><?php _e( 'More Accessible', 'edd' );?></h4>
194
+ <p><?php _e( 'Your store\'s customer history has been moved to a dedicated submenu of the Downloads menu, making it significantly easier to locate. No longer is it hidden in an obscure section of the Reports page.', 'edd' );?></p>
195
 
196
  </div>
197
  </div>
198
 
199
  <div class="changelog">
200
+ <h3><?php _e( 'Signed URLs', 'edd' );?></h3>
201
 
202
  <div class="feature-section">
203
 
204
+ <p><?php _e( 'We take security seriously and with Easy Digital Downloads 2.3, we have introduced a better, more secure file download mechanism that keeps your files safe and secure.', 'edd' );?></p>
205
+ <p><?php _e( 'Download URLs provided to customers have been improved to be shorter and more secure, and now use tokens to verify the URL prior to allowing the download to start.', 'edd' );?></p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
 
207
  </div>
208
  </div>
209
 
210
  <div class="changelog">
211
+ <h3><?php _e( 'Improved Order Details', 'edd' );?></h3>
212
 
213
  <div class="feature-section">
214
 
215
+ <img src="<?php echo EDD_PLUGIN_URL . 'assets/images/screenshots/22-purchased-downloads2.png'; ?>" class="edd-welcome-screenshots"/>
 
 
 
 
216
 
217
+ <h4><?php _e( 'Focus on Purchased Downloads', 'edd' );?></h4>
218
+ <p><?php _e( 'The Download products your customer has purchased is one of the most important parts of this screen, so we have put it up front and in the spotlight.', 'edd' );?></p>
219
 
220
+ <h4><?php _e( 'More Accurate Statistics', 'edd' );?></h4>
221
+ <p><?php _e( 'Adding or removing Downloads to and from a payment record now properly triggers an update routine to ensure the sales and earnings for the affected products are properly updated.', 'edd' );?></p>
222
 
223
  </div>
224
  </div>
228
 
229
  <div class="feature-section col three-col">
230
  <div>
 
 
231
 
232
+ <h4><?php _e( 'PolyLang Support', 'edd' );?></h4>
233
+ <p><?php _e( 'We\'ve improved support for the popular PolyLang Plugin in 2.3 making EDD more accessible in more languages.', 'edd' );?></p>
234
+
235
+ <h4><?php _e( 'Customer API', 'edd' );?></h4>
236
+ <p><?php _e( 'A new EDD_Customer class has been introduced that makes it easy for developers to interact with customer data.', 'edd' );?></p>
237
+
238
  </div>
239
 
240
  <div>
 
 
241
 
242
+ <h4><?php _e( 'Schema Validation', 'edd' );?></h4>
243
+ <p><?php _e( 'The Schema Markup has been improved and now properly includes prices for both single and multi-price option products.' ,'edd' );?></p>
244
+
245
+ <h4><?php _e( 'Buy Now Button Improvements', 'edd' );?></h4>
246
+ <p><?php _e( 'Buy Now buttons no longer create pending payment records when they are clicked. Buy Now buttons are now automatically deactivated if no supported payment gateway is activated.' ,'edd' );?></p>
247
+
248
  </div>
249
 
250
  <div class="last-feature">
 
 
251
 
252
+ <h4><?php _e( 'Improved Upgrade Routine API', 'edd' );?></h4>
253
+ <p><?php _e( 'The upgrade routine has been improved to be more robust and user friendly. It now supports multiple upgrades in a single release, logs which have been completed ,as well as allows incomplete upgrades to be resumed.', 'edd' );?></p>
254
+
255
  </div>
256
+
257
+ </div>
258
+ </div>
259
+
260
+ <div class="return-to-dashboard">
261
+ <a href="<?php echo esc_url( admin_url( add_query_arg( array( 'post_type' => 'download', 'page' => 'edd-settings' ), 'edit.php' ) ) ); ?>"><?php _e( 'Go to Easy Digital Downloads Settings', 'edd' ); ?></a> &middot;
262
+ <a href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'edd-changelog' ), 'index.php' ) ) ); ?>"><?php _e( 'View the Full Changelog', 'edd' ); ?></a>
263
+ </div>
264
+ </div>
265
+ <?php
266
+ }
267
+
268
+ /**
269
+ * Render Changelog Screen
270
+ *
271
+ * @access public
272
+ * @since 2.0.3
273
+ * @return void
274
+ */
275
+ public function changelog_screen() {
276
+ list( $display_version ) = explode( '-', EDD_VERSION );
277
+ ?>
278
+ <div class="wrap about-wrap">
279
+ <h1><?php _e( 'Easy Digital Downloads Changelog', 'edd' ); ?></h1>
280
+ <div class="about-text"><?php printf( __( 'Thank you for updating to the latest version! Easy Digital Downloads %s is ready to make your online store faster, safer, and better!', 'edd' ), $display_version ); ?></div>
281
+ <div class="edd-badge"><?php printf( __( 'Version %s', 'edd' ), $display_version ); ?></div>
282
+
283
+ <?php $this->tabs(); ?>
284
+
285
+ <div class="changelog">
286
+ <h3><?php _e( 'Full Changelog', 'edd' );?></h3>
287
+
288
+ <div class="feature-section">
289
+ <?php echo $this->parse_readme(); ?>
290
  </div>
291
  </div>
292
 
441
  }
442
 
443
 
444
+ /**
445
+ * Parse the EDD readme.txt file
446
+ *
447
+ * @since 2.0.3
448
+ * @return string $readme HTML formatted readme file
449
+ */
450
+ public function parse_readme() {
451
+ $file = file_exists( EDD_PLUGIN_DIR . 'readme.txt' ) ? EDD_PLUGIN_DIR . 'readme.txt' : null;
452
+
453
+ if ( ! $file ) {
454
+ $readme = '<p>' . __( 'No valid changlog was found.', 'edd' ) . '</p>';
455
+ } else {
456
+ $readme = file_get_contents( $file );
457
+ $readme = nl2br( esc_html( $readme ) );
458
+ $readme = explode( '== Changelog ==', $readme );
459
+ $readme = end( $readme );
460
+
461
+ $readme = preg_replace( '/`(.*?)`/', '<code>\\1</code>', $readme );
462
+ $readme = preg_replace( '/[\040]\*\*(.*?)\*\*/', ' <strong>\\1</strong>', $readme );
463
+ $readme = preg_replace( '/[\040]\*(.*?)\*/', ' <em>\\1</em>', $readme );
464
+ $readme = preg_replace( '/= (.*?) =/', '<h4>\\1</h4>', $readme );
465
+ $readme = preg_replace( '/\[(.*?)\]\((.*?)\)/', '<a href="\\2">\\1</a>', $readme );
466
+ }
467
+
468
+ return $readme;
469
+ }
470
+
471
+
472
  /**
473
  * Render Contributors List
474
  *
536
  *
537
  * @access public
538
  * @since 1.4
 
539
  * @return void
540
  */
541
  public function welcome() {
 
 
542
  // Bail if no activation redirect
543
  if ( ! get_transient( '_edd_activation_redirect' ) )
544
  return;
includes/ajax-functions.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Functions/AJAX
9
- * @copyright Copyright (c) 2014, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.0
12
  */
@@ -27,6 +27,81 @@ function edd_is_ajax_enabled() {
27
  return apply_filters( 'edd_is_ajax_enabled', $retval );
28
  }
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  /**
31
  * Checks whether AJAX is disabled.
32
  *
@@ -70,9 +145,10 @@ function edd_ajax_remove_from_cart() {
70
  edd_remove_from_cart( $_POST['cart_item'] );
71
 
72
  $return = array(
73
- 'removed' => 1,
74
- 'subtotal' => html_entity_decode( edd_currency_filter( edd_format_amount( edd_get_cart_subtotal() ) ), ENT_COMPAT, 'UTF-8' ),
75
- 'total' => html_entity_decode( edd_currency_filter( edd_format_amount( edd_get_cart_total() ) ), ENT_COMPAT, 'UTF-8' )
 
76
  );
77
 
78
  echo json_encode( $return );
@@ -103,8 +179,21 @@ function edd_ajax_add_to_cart() {
103
 
104
  foreach ( $to_add as $options ) {
105
 
106
- if( $_POST['download_id'] == $options['price_id'] )
107
  $options = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
  $key = edd_add_to_cart( $_POST['download_id'], $options );
110
 
@@ -119,9 +208,10 @@ function edd_ajax_add_to_cart() {
119
  }
120
 
121
  $return = array(
122
- 'subtotal' => html_entity_decode( edd_currency_filter( edd_format_amount( edd_get_cart_subtotal() ) ), ENT_COMPAT, 'UTF-8' ),
123
- 'total' => html_entity_decode( edd_currency_filter( edd_format_amount( edd_get_cart_total() ) ), ENT_COMPAT, 'UTF-8' ),
124
- 'cart_item' => $items
 
125
  );
126
 
127
  echo json_encode( $return );
@@ -156,7 +246,7 @@ add_action( 'wp_ajax_nopriv_edd_get_subtotal', 'edd_ajax_get_subtotal' );
156
  function edd_ajax_apply_discount() {
157
  if ( isset( $_POST['code'] ) ) {
158
 
159
- $discount_code = $_POST['code'];
160
 
161
  $return = array(
162
  'msg' => '',
@@ -174,7 +264,7 @@ function edd_ajax_apply_discount() {
174
  'amount' => $amount,
175
  'total_plain' => $total,
176
  'total' => html_entity_decode( edd_currency_filter( edd_format_amount( $total ) ), ENT_COMPAT, 'UTF-8' ),
177
- 'code' => $_POST['code'],
178
  'html' => edd_get_cart_discounts_html( $discounts )
179
  );
180
  } else {
@@ -204,13 +294,15 @@ function edd_ajax_update_cart_item_quantity() {
204
 
205
  $download_id = absint( $_POST['download_id'] );
206
  $quantity = absint( $_POST['quantity'] );
 
207
 
208
- edd_set_cart_item_quantity( $download_id, absint( $_POST['quantity'] ) );
209
  $total = edd_get_cart_total();
210
 
211
  $return = array(
212
  'download_id' => $download_id,
213
  'quantity' => $quantity,
 
214
  'subtotal' => html_entity_decode( edd_currency_filter( edd_format_amount( edd_get_cart_subtotal() ) ), ENT_COMPAT, 'UTF-8' ),
215
  'total' => html_entity_decode( edd_currency_filter( edd_format_amount( $total ) ), ENT_COMPAT, 'UTF-8' )
216
  );
@@ -339,6 +431,7 @@ function edd_ajax_get_states_field() {
339
  $args = array(
340
  'name' => $_POST['field_name'],
341
  'id' => $_POST['field_name'],
 
342
  'options' => edd_get_shop_states( $_POST['country'] ),
343
  'show_option_all' => false,
344
  'show_option_none' => false
@@ -367,14 +460,43 @@ add_action( 'wp_ajax_nopriv_edd_get_shop_states', 'edd_ajax_get_states_field' );
367
  function edd_ajax_download_search() {
368
  global $wpdb;
369
 
370
- $search = esc_sql( sanitize_text_field( $_GET['s'] ) );
 
 
 
 
371
  $results = array();
372
- if ( current_user_can( 'edit_products' ) ) {
373
- $items = $wpdb->get_results( "SELECT ID,post_title FROM $wpdb->posts WHERE `post_type` = 'download' AND `post_title` LIKE '%$search%' LIMIT 50" );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  } else {
375
- $items = $wpdb->get_results( "SELECT ID,post_title FROM $wpdb->posts WHERE `post_type` = 'download' AND `post_status` = 'publish' AND `post_title` LIKE '%$search%' LIMIT 50" );
376
  }
377
 
 
 
 
378
  if( $items ) {
379
 
380
  foreach( $items as $item ) {
@@ -401,6 +523,56 @@ function edd_ajax_download_search() {
401
  add_action( 'wp_ajax_edd_download_search', 'edd_ajax_download_search' );
402
  add_action( 'wp_ajax_nopriv_edd_download_search', 'edd_ajax_download_search' );
403
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
  /**
405
  * Check for Download Price Variations via AJAX (this function can only be used
406
  * in WordPress Admin). This function is used for the Edit Payment screen when downloads
@@ -434,9 +606,9 @@ function edd_check_for_download_price_variations() {
434
  $ajax_response .= '<option value="' . esc_attr( $key ) . '">' . esc_html( $price['name'] ) . '</option>';
435
  }
436
  $ajax_response .= '</select>';
 
437
  }
438
 
439
- echo $ajax_response;
440
  }
441
 
442
  edd_die();
@@ -455,17 +627,26 @@ function edd_ajax_search_users() {
455
  if( current_user_can( 'manage_shop_settings' ) ) {
456
 
457
  $search_query = trim( $_POST['user_name'] );
 
458
 
459
- $found_users = get_users( array(
460
- 'number' => 9999,
461
- 'search' => $search_query . '*'
462
- )
463
  );
464
 
 
 
 
 
 
 
 
 
 
465
  $user_list = '<ul>';
466
  if( $found_users ) {
467
  foreach( $found_users as $user ) {
468
- $user_list .= '<li><a href="#" data-login="' . esc_attr( $user->user_login ) . '">' . esc_html( $user->user_login ) . '</a></li>';
469
  }
470
  } else {
471
  $user_list .= '<li>' . __( 'No users found', 'edd' ) . '</li>';
@@ -477,4 +658,4 @@ function edd_ajax_search_users() {
477
  }
478
  die();
479
  }
480
- add_action( 'wp_ajax_edd_search_users', 'edd_ajax_search_users' );
6
  *
7
  * @package EDD
8
  * @subpackage Functions/AJAX
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.0
12
  */
27
  return apply_filters( 'edd_is_ajax_enabled', $retval );
28
  }
29
 
30
+ /**
31
+ * Check if AJAX works as expected
32
+ *
33
+ * @since 2.2
34
+ * @return bool True if AJAX works, false otherwise
35
+ */
36
+ function edd_test_ajax_works() {
37
+
38
+ // Check if the Airplane Mode plugin is installed
39
+ if ( class_exists( 'Airplane_Mode_Core' ) ) {
40
+
41
+ global $Airplane_Mode_Core;
42
+
43
+ if ( method_exists( $Airplane_Mode_Core, 'enabled' ) ) {
44
+
45
+ if ( $Airplane_Mode_Core->enabled() ) {
46
+ return true;
47
+ }
48
+
49
+ } else {
50
+
51
+ if ( $Airplane_Mode_Core->check_status() == 'on' ) {
52
+ return true;
53
+ }
54
+ }
55
+ }
56
+
57
+ add_filter( 'block_local_requests', '__return_false' );
58
+
59
+ if ( get_transient( '_edd_ajax_works' ) ) {
60
+ return true;
61
+ }
62
+
63
+ $params = array(
64
+ 'sslverify' => false,
65
+ 'timeout' => 30,
66
+ 'body' => array(
67
+ 'action' => 'edd_test_ajax'
68
+ )
69
+ );
70
+
71
+ $ajax = wp_remote_post( edd_get_ajax_url(), $params );
72
+ $works = true;
73
+
74
+ if ( is_wp_error( $ajax ) ) {
75
+
76
+ $works = false;
77
+
78
+ } else {
79
+
80
+ if( empty( $ajax['response'] ) ) {
81
+ $works = false;
82
+ }
83
+
84
+ if( empty( $ajax['response']['code'] ) || 200 !== (int) $ajax['response']['code'] ) {
85
+ $works = false;
86
+ }
87
+
88
+ if( empty( $ajax['response']['message'] ) || 'OK' !== $ajax['response']['message'] ) {
89
+ $works = false;
90
+ }
91
+
92
+ if( ! isset( $ajax['body'] ) || 0 !== (int) $ajax['body'] ) {
93
+ $works = false;
94
+ }
95
+
96
+ }
97
+
98
+ if ( $works ) {
99
+ set_transient( '_edd_ajax_works', '1', DAY_IN_SECONDS );
100
+ }
101
+
102
+ return $works;
103
+ }
104
+
105
  /**
106
  * Checks whether AJAX is disabled.
107
  *
145
  edd_remove_from_cart( $_POST['cart_item'] );
146
 
147
  $return = array(
148
+ 'removed' => 1,
149
+ 'subtotal' => html_entity_decode( edd_currency_filter( edd_format_amount( edd_get_cart_subtotal() ) ), ENT_COMPAT, 'UTF-8' ),
150
+ 'total' => html_entity_decode( edd_currency_filter( edd_format_amount( edd_get_cart_total() ) ), ENT_COMPAT, 'UTF-8' ),
151
+ 'cart_quantity' => html_entity_decode( edd_get_cart_quantity() ),
152
  );
153
 
154
  echo json_encode( $return );
179
 
180
  foreach ( $to_add as $options ) {
181
 
182
+ if( $_POST['download_id'] == $options['price_id'] ) {
183
  $options = array();
184
+ }
185
+
186
+ parse_str( $_POST['post_data'], $post_data );
187
+
188
+ if( isset( $options['price_id'] ) && isset( $post_data['edd_download_quantity_' . $options['price_id'] ] ) ) {
189
+
190
+ $options['quantity'] = absint( $post_data['edd_download_quantity_' . $options['price_id'] ] );
191
+
192
+ } else {
193
+
194
+ $options['quantity'] = isset( $post_data['edd_download_quantity'] ) ? absint( $post_data['edd_download_quantity'] ) : 1;
195
+
196
+ }
197
 
198
  $key = edd_add_to_cart( $_POST['download_id'], $options );
199
 
208
  }
209
 
210
  $return = array(
211
+ 'subtotal' => html_entity_decode( edd_currency_filter( edd_format_amount( edd_get_cart_subtotal() ) ), ENT_COMPAT, 'UTF-8' ),
212
+ 'total' => html_entity_decode( edd_currency_filter( edd_format_amount( edd_get_cart_total() ) ), ENT_COMPAT, 'UTF-8' ),
213
+ 'cart_item' => $items,
214
+ 'cart_quantity' => html_entity_decode( edd_get_cart_quantity() )
215
  );
216
 
217
  echo json_encode( $return );
246
  function edd_ajax_apply_discount() {
247
  if ( isset( $_POST['code'] ) ) {
248
 
249
+ $discount_code = sanitize_text_field( $_POST['code'] );
250
 
251
  $return = array(
252
  'msg' => '',
264
  'amount' => $amount,
265
  'total_plain' => $total,
266
  'total' => html_entity_decode( edd_currency_filter( edd_format_amount( $total ) ), ENT_COMPAT, 'UTF-8' ),
267
+ 'code' => $discount_code,
268
  'html' => edd_get_cart_discounts_html( $discounts )
269
  );
270
  } else {
294
 
295
  $download_id = absint( $_POST['download_id'] );
296
  $quantity = absint( $_POST['quantity'] );
297
+ $options = maybe_unserialize( stripslashes( $_POST['options'] ) );
298
 
299
+ edd_set_cart_item_quantity( $download_id, absint( $_POST['quantity'] ), $options );
300
  $total = edd_get_cart_total();
301
 
302
  $return = array(
303
  'download_id' => $download_id,
304
  'quantity' => $quantity,
305
+ 'taxes' => html_entity_decode( edd_cart_tax(), ENT_COMPAT, 'UTF-8' ),
306
  'subtotal' => html_entity_decode( edd_currency_filter( edd_format_amount( edd_get_cart_subtotal() ) ), ENT_COMPAT, 'UTF-8' ),
307
  'total' => html_entity_decode( edd_currency_filter( edd_format_amount( $total ) ), ENT_COMPAT, 'UTF-8' )
308
  );
431
  $args = array(
432
  'name' => $_POST['field_name'],
433
  'id' => $_POST['field_name'],
434
+ 'class' => $_POST['field_name'] . ' edd-select',
435
  'options' => edd_get_shop_states( $_POST['country'] ),
436
  'show_option_all' => false,
437
  'show_option_none' => false
460
  function edd_ajax_download_search() {
461
  global $wpdb;
462
 
463
+ $search = esc_sql( sanitize_text_field( $_GET['s'] ) );
464
+ $excludes = ( isset( $_GET['current_id'] ) ? (array) $_GET['current_id'] : array() );
465
+ $excludes = array_map( 'absint', $excludes );
466
+ $exclude = implode( ',', $excludes );
467
+
468
  $results = array();
469
+
470
+ // Setup the SELECT statement
471
+ $select = "SELECT ID,post_title FROM $wpdb->posts ";
472
+
473
+ // Setup the WHERE clause
474
+ $where = "WHERE `post_type` = 'download' and `post_title` LIKE '%s' ";
475
+
476
+ // If we have items to exclude, exclude them
477
+ if( ! empty( $exclude ) ) {
478
+ $where .= "AND `ID` NOT IN (%s) ";
479
+ }
480
+
481
+ // If the user can't edit products, limit to just published items
482
+ if( ! current_user_can( 'edit_products' ) ) {
483
+ $where .= "AND `post_status` = 'publish' ";
484
+ }
485
+
486
+ // Limit the result sets
487
+ $limit = "LIMIT 50";
488
+
489
+ $sql = $select . $where . $limit;
490
+
491
+ if( ! empty( $exclude ) ) {
492
+ $prepared_statement = $wpdb->prepare( $sql, '%' . $search . '%', $exclude );
493
  } else {
494
+ $prepared_statement = $wpdb->prepare( $sql, '%' . $search . '%' );
495
  }
496
 
497
+
498
+ $items = $wpdb->get_results( $prepared_statement );
499
+
500
  if( $items ) {
501
 
502
  foreach( $items as $item ) {
523
  add_action( 'wp_ajax_edd_download_search', 'edd_ajax_download_search' );
524
  add_action( 'wp_ajax_nopriv_edd_download_search', 'edd_ajax_download_search' );
525
 
526
+ /**
527
+ * Search the customers database via Ajax
528
+ *
529
+ * @since 2.2
530
+ * @return void
531
+ */
532
+ function edd_ajax_customer_search() {
533
+ global $wpdb;
534
+
535
+ $search = esc_sql( sanitize_text_field( $_GET['s'] ) );
536
+ $results = array();
537
+ if ( ! current_user_can( 'view_shop_reports' ) ) {
538
+ $customers = array();
539
+ } else {
540
+ $select = "SELECT id, name, email FROM {$wpdb->prefix}edd_customers ";
541
+ if ( is_numeric( $search ) ) {
542
+ $where = "WHERE `id` LIKE '%$search%' OR `user_id` LIKE '%$search%' ";
543
+ } else {
544
+ $where = "WHERE `name` LIKE '%$search%' OR `email` LIKE '%$search%' ";
545
+ }
546
+ $limit = "LIMIT 50";
547
+
548
+ $customers = $wpdb->get_results( $select . $where . $limit );
549
+ }
550
+
551
+ if( $customers ) {
552
+
553
+ foreach( $customers as $customer ) {
554
+
555
+ $results[] = array(
556
+ 'id' => $customer->id,
557
+ 'name' => $customer->name . '(' . $customer->email . ')'
558
+ );
559
+ }
560
+
561
+ } else {
562
+
563
+ $customers[] = array(
564
+ 'id' => 0,
565
+ 'name' => __( 'No results found', 'edd' )
566
+ );
567
+
568
+ }
569
+
570
+ echo json_encode( $results );
571
+
572
+ edd_die();
573
+ }
574
+ add_action( 'wp_ajax_edd_customer_search', 'edd_ajax_customer_search' );
575
+
576
  /**
577
  * Check for Download Price Variations via AJAX (this function can only be used
578
  * in WordPress Admin). This function is used for the Edit Payment screen when downloads
606
  $ajax_response .= '<option value="' . esc_attr( $key ) . '">' . esc_html( $price['name'] ) . '</option>';
607
  }
608
  $ajax_response .= '</select>';
609
+ echo $ajax_response;
610
  }
611
 
 
612
  }
613
 
614
  edd_die();
627
  if( current_user_can( 'manage_shop_settings' ) ) {
628
 
629
  $search_query = trim( $_POST['user_name'] );
630
+ $exclude = trim( $_POST['exclude'] );
631
 
632
+ $get_users_args = array(
633
+ 'number' => 9999,
634
+ 'search' => $search_query . '*'
 
635
  );
636
 
637
+ if ( ! empty( $exclude ) ) {
638
+ $exclude_array = explode( ',', $exclude );
639
+ $get_users_args['exclude'] = $exclude_array;
640
+ }
641
+
642
+ $get_users_args = apply_filters( 'edd_search_users_args', $get_users_args );
643
+
644
+ $found_users = get_users( $get_users_args );
645
+
646
  $user_list = '<ul>';
647
  if( $found_users ) {
648
  foreach( $found_users as $user ) {
649
+ $user_list .= '<li><a href="#" data-userid="' . esc_attr( $user->ID ) . '" data-login="' . esc_attr( $user->user_login ) . '">' . esc_html( $user->user_login ) . '</a></li>';
650
  }
651
  } else {
652
  $user_list .= '<li>' . __( 'No users found', 'edd' ) . '</li>';
658
  }
659
  die();
660
  }
661
+ add_action( 'wp_ajax_edd_search_users', 'edd_ajax_search_users' );
includes/cart/actions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Cart
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -147,7 +147,7 @@ add_action( 'edd_update_cart', 'edd_process_cart_update' );
147
  function edd_process_cart_save( $data ) {
148
 
149
  $cart = edd_save_cart();
150
- if( ! is_wp_error( $cart ) ) {
151
  wp_redirect( edd_get_checkout_uri() ); exit;
152
  }
153
 
4
  *
5
  * @package EDD
6
  * @subpackage Cart
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
147
  function edd_process_cart_save( $data ) {
148
 
149
  $cart = edd_save_cart();
150
+ if( ! $cart ) {
151
  wp_redirect( edd_get_checkout_uri() ); exit;
152
  }
153
 
includes/cart/functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Cart
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -34,39 +34,63 @@ function edd_get_cart_contents() {
34
  */
35
  function edd_get_cart_content_details() {
36
 
 
 
37
  $cart_items = edd_get_cart_contents();
38
 
39
  if ( empty( $cart_items ) ) {
40
  return false;
41
  }
42
 
43
- $details = array();
 
44
 
45
  foreach( $cart_items as $key => $item ) {
46
 
 
 
 
 
 
 
47
  $item_price = edd_get_cart_item_price( $item['id'], $item['options'] );
48
- $discount = apply_filters( 'edd_get_cart_content_details_item_discount_amount', edd_get_cart_item_discount_amount( $item ), $item );
49
- $tax = edd_get_cart_item_tax( $item );
50
  $quantity = edd_get_cart_item_quantity( $item['id'], $item['options'] );
 
 
 
 
 
 
 
 
 
51
 
52
- $item_price = round( $item_price, 2 );
53
- $discount = round( $discount, 2 );
54
- $subtotal = round( $item_price * $quantity, 2 );
55
- $tax = round( $tax * $quantity, 2 );
56
- $total = round( ( $subtotal - $discount + $tax ), 2 );
57
 
58
  $details[ $key ] = array(
59
  'name' => get_the_title( $item['id'] ),
60
  'id' => $item['id'],
61
  'item_number' => $item,
62
- 'item_price' => $item_price,
63
  'quantity' => $quantity,
64
- 'discount' => $discount,
65
- 'subtotal' => $subtotal,
66
- 'tax' => $tax,
67
- 'price' => $total,
 
68
  );
69
 
 
 
 
 
 
 
70
  }
71
 
72
  return $details;
@@ -76,10 +100,20 @@ function edd_get_cart_content_details() {
76
  * Get Cart Quantity
77
  *
78
  * @since 1.0
79
- * @return int Quantity of items in the cart
80
  */
81
  function edd_get_cart_quantity() {
82
- return ( $cart = edd_get_cart_contents() ) ? count( $cart ) : 0;
 
 
 
 
 
 
 
 
 
 
83
  }
84
 
85
  /**
@@ -96,8 +130,6 @@ function edd_get_cart_quantity() {
96
  */
97
  function edd_add_to_cart( $download_id, $options = array() ) {
98
 
99
- $cart = apply_filters( 'edd_pre_add_to_cart_contents', edd_get_cart_contents() );
100
-
101
  $download = get_post( $download_id );
102
 
103
  if( 'download' != $download->post_type )
@@ -108,15 +140,13 @@ function edd_add_to_cart( $download_id, $options = array() ) {
108
 
109
  do_action( 'edd_pre_add_to_cart', $download_id, $options );
110
 
 
 
111
  if ( edd_has_variable_prices( $download_id ) && ! isset( $options['price_id'] ) ) {
112
  // Forces to the first price ID if none is specified and download has variable prices
113
  $options['price_id'] = '0';
114
  }
115
 
116
- $item = array();
117
- $to_add = array();
118
- $new_item = array();
119
-
120
  if( isset( $options['quantity'] ) ) {
121
  $quantity = absint( preg_replace( '/[^0-9\.]/', '', $options['quantity'] ) );
122
  unset( $options['quantity'] );
@@ -124,15 +154,20 @@ function edd_add_to_cart( $download_id, $options = array() ) {
124
  $quantity = 1;
125
  }
126
 
 
 
 
 
 
127
  if ( isset( $options['price_id'] ) && is_array( $options['price_id'] ) ) {
128
 
129
  // Process multiple price options at once
130
  foreach ( $options['price_id'] as $price ) {
131
 
132
- $item = array(
133
  'id' => $download_id,
134
  'options' => array(
135
- 'price_id' => preg_replace( '/[^0-9\.]/', '', $price )
136
  ),
137
  'quantity' => $quantity
138
  );
@@ -151,27 +186,31 @@ function edd_add_to_cart( $download_id, $options = array() ) {
151
  }
152
 
153
  // Add a single item
154
- $item = array(
155
  'id' => $download_id,
156
  'options' => $options,
157
  'quantity' => $quantity
158
  );
159
  }
160
 
161
- $to_add = apply_filters( 'edd_add_to_cart_item', $item );
 
 
 
162
 
163
- if ( ! is_array( $to_add ) )
164
- return;
165
 
166
- if ( ! isset( $to_add['id'] ) || empty( $to_add['id'] ) )
167
- return;
168
 
169
- $new_item[] = $to_add;
 
170
 
171
- if ( is_array( $cart ) ) {
172
- $cart = array_merge( $cart, $new_item );
173
- } else {
174
- $cart = $new_item;
 
175
  }
176
 
177
  EDD()->session->set( 'edd_cart', $cart );
@@ -199,7 +238,7 @@ function edd_remove_from_cart( $cart_key ) {
199
  if ( ! is_array( $cart ) ) {
200
  return true; // Empty cart
201
  } else {
202
- $item_id = isset( $cart[ $cart_key ][ 'id' ] ) ? $cart[ $cart_key ][ 'id' ] : null;
203
  unset( $cart[ $cart_key ] );
204
  }
205
 
@@ -283,9 +322,8 @@ function edd_get_item_position_in_cart( $download_id = 0, $options = array() ) {
283
  * @return bool
284
  */
285
  function edd_item_quantities_enabled() {
286
- global $edd_options;
287
- $ret = isset( $edd_options['item_quantities'] );
288
- return apply_filters( 'edd_item_quantities_enabled', $ret );
289
  }
290
 
291
  /**
@@ -339,24 +377,41 @@ function edd_get_cart_item_quantity( $download_id = 0, $options = array() ) {
339
  * @return string Fully formatted price
340
  */
341
  function edd_cart_item_price( $item_id = 0, $options = array() ) {
342
- global $edd_options;
 
343
 
344
- $tax_on_prices = edd_prices_show_tax_on_checkout();
 
 
 
 
 
 
 
 
 
 
345
 
346
- $price = edd_get_cart_item_price( $item_id, $options, $tax_on_prices );
347
- $price = edd_currency_filter( edd_format_amount( $price ) );
348
- $label = '';
349
- if( edd_display_tax_rate() ) {
350
- $label = '&nbsp;&ndash;&nbsp;';
351
- if( edd_prices_show_tax_on_checkout() ) {
352
- $label .= sprintf( __( 'includes %s tax', 'edd' ), edd_get_formatted_tax_rate() );
353
- } else {
354
- $label .= sprintf( __( 'excludes %s tax', 'edd' ), edd_get_formatted_tax_rate() );
355
  }
356
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
  }
358
 
359
- return esc_html( $price . $label );
 
 
360
  }
361
 
362
  /**
@@ -368,40 +423,41 @@ function edd_cart_item_price( $item_id = 0, $options = array() ) {
368
  * Use edd_get_cart_item_final_price()
369
  *
370
  * @since 1.0
371
- * @param int $item_id Download ID number
372
  * @param array $options Optional parameters, used for defining variable prices
373
- * @param bool $include_tax Whether the price should include taxes
374
  * @return float|bool Price for this item
375
  */
376
- function edd_get_cart_item_price( $download_id = 0, $options = array(), $include_taxes = false ) {
377
- global $edd_options;
 
 
378
 
379
- $price = false;
380
 
381
- if ( edd_has_variable_prices( $download_id ) && ! empty( $options ) ) {
382
  $prices = edd_get_variable_prices( $download_id );
 
383
  if ( $prices ) {
384
- $price = isset( $prices[ $options['price_id'] ] ) ? $prices[ $options['price_id'] ]['amount'] : false;
385
- }
386
- }
387
 
388
- if( ! $price ) {
389
- // Get the standard Download price if not using variable prices
390
- $price = edd_get_download_price( $download_id );
391
- }
392
 
393
- if( ! edd_download_is_tax_exclusive( $download_id ) ) {
 
 
 
 
 
 
394
 
395
- if( edd_prices_include_tax() && ! $include_taxes ) {
396
- // If price is entered with tax, we have to deduct the taxed amount from the price to determine the actual price
397
- $price -= edd_calculate_tax( $price );
398
- } elseif( ! edd_prices_include_tax() && $include_taxes ) {
399
- $price += edd_calculate_tax( $price );
400
  }
401
 
402
  }
403
 
404
- return apply_filters( 'edd_cart_item_price', $price, $download_id, $options, $include_taxes );
 
 
 
 
 
405
  }
406
 
407
  /**
@@ -423,40 +479,24 @@ function edd_get_cart_item_final_price( $item_key = 0 ) {
423
  * Get cart item tax
424
  *
425
  * @since 1.9
426
- * @param int $item Cart item array
 
 
427
  * @return float Tax amount
428
  */
429
- function edd_get_cart_item_tax( $item = array() ) {
430
-
431
- $tax = 0;
432
- $price = false;
433
 
434
- if( ! edd_download_is_tax_exclusive( $item['id'] ) ) {
435
-
436
- if ( edd_has_variable_prices( $item['id'] ) && ! empty( $item['options'] ) ) {
437
- $prices = edd_get_variable_prices( $item['id'] );
438
- if ( $prices ) {
439
- $price = isset( $prices[ $item['options']['price_id'] ] ) ? $prices[ $item['options']['price_id'] ]['amount'] : false;
440
- }
441
- }
442
-
443
- if( ! $price ) {
444
- // Get the standard Download price if not using variable prices
445
- $price = edd_get_download_price( $item['id'] );
446
- }
447
-
448
- if( edd_taxes_after_discounts() ) {
449
- $price -= apply_filters( 'edd_get_cart_item_tax_item_discount_amount', edd_get_cart_item_discount_amount( $item ), $item );
450
- }
451
 
452
  $country = ! empty( $_POST['billing_country'] ) ? $_POST['billing_country'] : false;
453
  $state = ! empty( $_POST['card_state'] ) ? $_POST['card_state'] : false;
454
 
455
- $tax = edd_calculate_tax( $price, $country, $state );
456
 
457
  }
458
 
459
- return apply_filters( 'edd_get_cart_item_tax', $tax, $item['id'], $item );
460
  }
461
 
462
  /**
@@ -512,7 +552,7 @@ function edd_get_cart_item_price_id( $item = array() ) {
512
  function edd_get_cart_item_price_name( $item = array() ) {
513
  $price_id = (int) edd_get_cart_item_price_id( $item );
514
  $prices = edd_get_variable_prices( $item['id'] );
515
- $name = ! empty( $prices ) ? $prices[ $price_id ]['name'] : '';
516
  return apply_filters( 'edd_get_cart_item_price_name', $name, $item['id'], $price_id, $item );
517
  }
518
 
@@ -522,12 +562,9 @@ function edd_get_cart_item_price_name( $item = array() ) {
522
  * Shows the subtotal for the shopping cart (no taxes)
523
  *
524
  * @since 1.4
525
- * @global $edd_options Array of all the EDD Options
526
  * @return float Total amount before taxes fully formatted
527
  */
528
  function edd_cart_subtotal() {
529
- global $edd_options;
530
-
531
  $price = esc_html( edd_currency_filter( edd_format_amount( edd_get_cart_subtotal() ) ) );
532
 
533
  // Todo - Show tax labels here (if needed)
@@ -542,18 +579,15 @@ function edd_cart_subtotal() {
542
  * uses edd_get_cart_contents().
543
  *
544
  * @since 1.3.3
545
- * @global $edd_options Array of all the EDD Options
546
  * @return float Total amount before taxes
547
  */
548
  function edd_get_cart_subtotal() {
549
- global $edd_options;
550
-
551
  $subtotal = 0.00;
552
  $items = edd_get_cart_content_details();
553
 
554
  if( $items ) {
555
 
556
- $prices = wp_list_pluck( $items, 'subtotal' );
557
 
558
  if( is_array( $prices ) ) {
559
  $subtotal = array_sum( $prices );
@@ -576,18 +610,15 @@ function edd_get_cart_subtotal() {
576
  * Returns amount after taxes and discounts
577
  *
578
  * @since 1.4.1
579
- * @global $edd_options Array of all the EDD Options
580
  * @param bool $discounts Array of discounts to apply (needed during AJAX calls)
581
  * @return float Cart amount
582
  */
583
  function edd_get_cart_total( $discounts = false ) {
584
- global $edd_options;
585
-
586
- $subtotal = edd_get_cart_subtotal();
587
- $fees = edd_get_cart_fee_total();
588
- $cart_tax = edd_get_cart_tax();
589
- $discount = edd_get_cart_discounted_amount();
590
- $total = $subtotal + $fees + $cart_tax - $discount;
591
 
592
  if( $total < 0 )
593
  $total = 0.00;
@@ -602,15 +633,12 @@ function edd_get_cart_total( $discounts = false ) {
602
  * Gets the fully formatted total price amount in the cart.
603
  * uses edd_get_cart_amount().
604
  *
605
- * @global $edd_options Array of all the EDD Options
606
  * @since 1.3.3
607
  *
608
  * @param bool $echo
609
  * @return mixed|string|void
610
  */
611
  function edd_cart_total( $echo = true ) {
612
- global $edd_options;
613
-
614
  $total = apply_filters( 'edd_cart_total', edd_currency_filter( edd_format_amount( edd_get_cart_total() ) ) );
615
 
616
  // Todo - Show tax labels here (if needed)
@@ -643,11 +671,12 @@ function edd_cart_has_fees( $type = 'all' ) {
643
  *
644
  * @since 1.5
645
  * @param string $type
 
646
  * @uses EDD()->fees->get_fees()
647
  * @return array All the cart fees that have been applied
648
  */
649
- function edd_get_cart_fees( $type = 'all' ) {
650
- return EDD()->fees->get_fees( $type );
651
  }
652
 
653
  /**
@@ -679,12 +708,17 @@ function edd_get_cart_fee_tax() {
679
 
680
  foreach ( $fees as $fee_id => $fee ) {
681
 
682
- if( ! empty( $fee['no_tax' ] ) ) {
683
  continue;
684
  }
685
 
 
 
 
686
  $tax += edd_calculate_tax( $fee['amount'] );
687
 
 
 
688
  }
689
  }
690
 
@@ -732,7 +766,7 @@ function edd_get_cart_tax() {
732
 
733
  if( $items ) {
734
 
735
- $taxes = wp_list_pluck( $items, 'tax' );
736
 
737
  if( is_array( $taxes ) ) {
738
  $cart_tax = array_sum( $taxes );
@@ -742,7 +776,7 @@ function edd_get_cart_tax() {
742
 
743
  $cart_tax += edd_get_cart_fee_tax();
744
 
745
- return apply_filters( 'edd_get_cart_tax', $cart_tax );
746
  }
747
 
748
  /**
@@ -811,19 +845,18 @@ function edd_add_collection_to_cart( $taxonomy, $terms ) {
811
  * @since 1.0
812
  * @global $post
813
  * @param int $cart_key Cart item key
814
- * @param object $post Download (post) object
815
- * @param bool $ajax AJAX?
816
  * @return string $remove_url URL to remove the cart item
817
  */
818
- function edd_remove_item_url( $cart_key, $post, $ajax = false ) {
819
- global $post;
 
820
 
821
  if ( defined('DOING_AJAX') ){
822
  $current_page = edd_get_checkout_uri();
823
  } else if( is_page() ) {
824
- $current_page = add_query_arg( 'page_id', $post->ID, home_url( 'index.php' ) );
825
  } else if( is_singular() ) {
826
- $current_page = add_query_arg( 'p', $post->ID, home_url( 'index.php' ) );
827
  } else {
828
  $current_page = edd_get_current_page_url();
829
  }
@@ -857,28 +890,6 @@ function edd_remove_cart_fee_url( $fee_id = '') {
857
  return apply_filters( 'edd_remove_fee_url', $remove_url );
858
  }
859
 
860
- /**
861
- * Show Added To Cart Messages
862
- *
863
- * @since 1.0
864
- * @param int $download_id Download (Post) ID
865
- * @return void
866
- */
867
- function edd_show_added_to_cart_messages( $download_id ) {
868
- if ( isset( $_POST['edd_action'] ) && $_POST['edd_action'] == 'add_to_cart' ) {
869
- if ( $download_id != absint( $_POST['download_id'] ) )
870
- $download_id = absint( $_POST['download_id'] );
871
-
872
- $alert = '<div class="edd_added_to_cart_alert">'
873
- . sprintf( __('You have successfully added %s to your shopping cart.', 'edd'), get_the_title( $download_id ) )
874
- . ' <a href="' . edd_get_checkout_uri() . '" class="edd_alert_checkout_link">' . __('Checkout.', 'edd') . '</a>'
875
- . '</div>';
876
-
877
- echo apply_filters( 'edd_show_added_to_cart_messages', $alert );
878
- }
879
- }
880
- add_action('edd_after_download_content', 'edd_show_added_to_cart_messages');
881
-
882
  /**
883
  * Empties the Cart
884
  *
@@ -910,7 +921,7 @@ function edd_empty_cart() {
910
  *
911
  * @uses EDD()->session->set()
912
  */
913
- function edd_set_purchase_session( $purchase_data ) {
914
  EDD()->session->set( 'edd_purchase', $purchase_data );
915
  }
916
 
@@ -932,13 +943,11 @@ function edd_get_purchase_session() {
932
  * Checks if cart saving has been disabled
933
  *
934
  * @since 1.8
935
- * @global $edd_options
936
  * @return bool Whether or not cart saving has been disabled
937
  */
938
  function edd_is_cart_saving_disabled() {
939
- global $edd_options;
940
-
941
- return apply_filters( 'edd_cart_saving_disabled', ! isset( $edd_options['enable_cart_saving'] ) );
942
  }
943
 
944
  /**
@@ -948,7 +957,6 @@ function edd_is_cart_saving_disabled() {
948
  * @return bool
949
  */
950
  function edd_is_cart_saved() {
951
-
952
  if( edd_is_cart_saving_disabled() )
953
  return false;
954
 
@@ -979,21 +987,17 @@ function edd_is_cart_saved() {
979
  return true;
980
 
981
  }
982
-
983
- return false;
984
  }
985
 
986
  /**
987
  * Process the Cart Save
988
  *
989
  * @since 1.8
990
- * @return void
991
  */
992
  function edd_save_cart() {
993
- global $edd_options;
994
-
995
  if ( edd_is_cart_saving_disabled() )
996
- return;
997
 
998
  $user_id = get_current_user_id();
999
  $cart = EDD()->session->get( 'edd_cart' );
@@ -1026,6 +1030,12 @@ function edd_save_cart() {
1026
  );
1027
 
1028
  EDD()->session->set( 'edd_cart_messages', $messages );
 
 
 
 
 
 
1029
  }
1030
 
1031
 
@@ -1033,12 +1043,12 @@ function edd_save_cart() {
1033
  * Process the Cart Restoration
1034
  *
1035
  * @since 1.8
1036
- * @return void || false Returns false if cart saving is disabled
1037
  */
1038
  function edd_restore_cart() {
1039
 
1040
  if ( edd_is_cart_saving_disabled() )
1041
- return;
1042
 
1043
  $user_id = get_current_user_id();
1044
  $saved_cart = get_user_meta( $user_id, 'edd_saved_cart', true );
@@ -1055,13 +1065,15 @@ function edd_restore_cart() {
1055
 
1056
  $messages['edd_cart_restoration_failed'] = sprintf( '<strong>%1$s</strong>: %2$s', __( 'Error', 'edd' ), __( 'Cart restoration failed. Invalid token.', 'edd' ) );
1057
  EDD()->session->set( 'edd_cart_messages', $messages );
1058
-
1059
- return new WP_Error( 'invalid_cart_token', __( 'The cart cannot be restored. Invalid token.', 'edd' ) );
1060
  }
1061
 
1062
  delete_user_meta( $user_id, 'edd_saved_cart' );
1063
  delete_user_meta( $user_id, 'edd_cart_token' );
1064
 
 
 
 
 
1065
  } elseif ( ! is_user_logged_in() && isset( $_COOKIE['edd_saved_cart'] ) && $token ) {
1066
 
1067
  $saved_cart = $_COOKIE['edd_saved_cart'];
@@ -1084,6 +1096,8 @@ function edd_restore_cart() {
1084
  $messages['edd_cart_restoration_successful'] = sprintf( '<strong>%1$s</strong>: %2$s', __( 'Success', 'edd' ), __( 'Cart restored successfully.', 'edd' ) );
1085
  EDD()->session->set( 'edd_cart', $saved_cart );
1086
  EDD()->session->set( 'edd_cart_messages', $messages );
 
 
1087
  }
1088
 
1089
  /**
4
  *
5
  * @package EDD
6
  * @subpackage Cart
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
34
  */
35
  function edd_get_cart_content_details() {
36
 
37
+ global $edd_is_last_cart_item, $edd_flat_discount_total;
38
+
39
  $cart_items = edd_get_cart_contents();
40
 
41
  if ( empty( $cart_items ) ) {
42
  return false;
43
  }
44
 
45
+ $details = array();
46
+ $length = count( $cart_items ) - 1;
47
 
48
  foreach( $cart_items as $key => $item ) {
49
 
50
+ if( $key >= $length ) {
51
+ $edd_is_last_cart_item = true;
52
+ }
53
+
54
+ $item['quantity'] = edd_item_quantities_enabled() ? absint( $item['quantity'] ) : 1;
55
+
56
  $item_price = edd_get_cart_item_price( $item['id'], $item['options'] );
57
+ $discount = edd_get_cart_item_discount_amount( $item );
58
+ $discount = apply_filters( 'edd_get_cart_content_details_item_discount_amount', $discount, $item );
59
  $quantity = edd_get_cart_item_quantity( $item['id'], $item['options'] );
60
+ $fees = edd_get_cart_fees( 'fee', $item['id'] );
61
+ $subtotal = $item_price * $quantity;
62
+ $tax = edd_get_cart_item_tax( $item['id'], $item['options'], $subtotal - $discount );
63
+
64
+ if( edd_prices_include_tax() ) {
65
+ $subtotal -= round( $tax, edd_currency_decimal_filter() );
66
+ }
67
+
68
+ $total = $subtotal - $discount + $tax;
69
 
70
+ // Do not allow totals to go negatve
71
+ if( $total < 0 ) {
72
+ $total = 0;
73
+ }
 
74
 
75
  $details[ $key ] = array(
76
  'name' => get_the_title( $item['id'] ),
77
  'id' => $item['id'],
78
  'item_number' => $item,
79
+ 'item_price' => round( $item_price, edd_currency_decimal_filter() ),
80
  'quantity' => $quantity,
81
+ 'discount' => round( $discount, edd_currency_decimal_filter() ),
82
+ 'subtotal' => round( $subtotal, edd_currency_decimal_filter() ),
83
+ 'tax' => round( $tax, edd_currency_decimal_filter() ),
84
+ 'fees' => $fees,
85
+ 'price' => round( $total, edd_currency_decimal_filter() )
86
  );
87
 
88
+ if( $edd_is_last_cart_item ) {
89
+
90
+ $edd_is_last_cart_item = false;
91
+ $edd_flat_discount_total = 0.00;
92
+ }
93
+
94
  }
95
 
96
  return $details;
100
  * Get Cart Quantity
101
  *
102
  * @since 1.0
103
+ * @return int Sum quantity of items in the cart
104
  */
105
  function edd_get_cart_quantity() {
106
+
107
+ $total_quantity = 0;
108
+ $cart = edd_get_cart_contents();
109
+
110
+ if ( ! empty( $cart ) ) {
111
+ $quantities = wp_list_pluck( $cart, 'quantity' );
112
+ $total_quantity = absint( array_sum( $quantities ) );
113
+ }
114
+
115
+
116
+ return apply_filters( 'edd_get_cart_quantity', $total_quantity, $cart );
117
  }
118
 
119
  /**
130
  */
131
  function edd_add_to_cart( $download_id, $options = array() ) {
132
 
 
 
133
  $download = get_post( $download_id );
134
 
135
  if( 'download' != $download->post_type )
140
 
141
  do_action( 'edd_pre_add_to_cart', $download_id, $options );
142
 
143
+ $cart = apply_filters( 'edd_pre_add_to_cart_contents', edd_get_cart_contents() );
144
+
145
  if ( edd_has_variable_prices( $download_id ) && ! isset( $options['price_id'] ) ) {
146
  // Forces to the first price ID if none is specified and download has variable prices
147
  $options['price_id'] = '0';
148
  }
149
 
 
 
 
 
150
  if( isset( $options['quantity'] ) ) {
151
  $quantity = absint( preg_replace( '/[^0-9\.]/', '', $options['quantity'] ) );
152
  unset( $options['quantity'] );
154
  $quantity = 1;
155
  }
156
 
157
+ // If the price IDs are a string and is a coma separted list, make it an array (allows custom add to cart URLs)
158
+ if ( isset( $options['price_id'] ) && ! is_array( $options['price_id'] ) && false !== strpos( $options['price_id'], ',' ) ) {
159
+ $options['price_id'] = explode( ',', $options['price_id'] );
160
+ }
161
+
162
  if ( isset( $options['price_id'] ) && is_array( $options['price_id'] ) ) {
163
 
164
  // Process multiple price options at once
165
  foreach ( $options['price_id'] as $price ) {
166
 
167
+ $items[] = array(
168
  'id' => $download_id,
169
  'options' => array(
170
+ 'price_id' => preg_replace( '/[^0-9\.-]/', '', $price )
171
  ),
172
  'quantity' => $quantity
173
  );
186
  }
187
 
188
  // Add a single item
189
+ $items[] = array(
190
  'id' => $download_id,
191
  'options' => $options,
192
  'quantity' => $quantity
193
  );
194
  }
195
 
196
+ foreach ( $items as $item ) {
197
+ $to_add = apply_filters( 'edd_add_to_cart_item', $item );
198
+ if ( ! is_array( $to_add ) )
199
+ return;
200
 
201
+ if ( ! isset( $to_add['id'] ) || empty( $to_add['id'] ) )
202
+ return;
203
 
204
+ if( edd_item_in_cart( $to_add['id'], $to_add['options'] ) && edd_item_quantities_enabled() ) {
 
205
 
206
+ $key = edd_get_item_position_in_cart( $to_add['id'], $to_add['options'] );
207
+ $cart[ $key ]['quantity'] += $quantity;
208
 
209
+ } else {
210
+
211
+ $cart[] = $to_add;
212
+
213
+ }
214
  }
215
 
216
  EDD()->session->set( 'edd_cart', $cart );
238
  if ( ! is_array( $cart ) ) {
239
  return true; // Empty cart
240
  } else {
241
+ $item_id = isset( $cart[ $cart_key ]['id'] ) ? $cart[ $cart_key ]['id'] : null;
242
  unset( $cart[ $cart_key ] );
243
  }
244
 
322
  * @return bool
323
  */
324
  function edd_item_quantities_enabled() {
325
+ $ret = edd_get_option( 'item_quantities', false );
326
+ return (bool) apply_filters( 'edd_item_quantities_enabled', $ret );
 
327
  }
328
 
329
  /**
377
  * @return string Fully formatted price
378
  */
379
  function edd_cart_item_price( $item_id = 0, $options = array() ) {
380
+ $price = edd_get_cart_item_price( $item_id, $options );
381
+ $label = '';
382
 
383
+ $price_id = isset( $options['price_id'] ) ? $options['price_id'] : false;
384
+
385
+ if ( ! edd_is_free_download( $item_id, $price_id ) && ! edd_download_is_tax_exclusive( $item_id ) ) {
386
+
387
+ if( edd_prices_show_tax_on_checkout() && ! edd_prices_include_tax() ) {
388
+
389
+ $price += edd_get_cart_item_tax( $item_id, $options, $price );
390
+
391
+ } if( ! edd_prices_show_tax_on_checkout() && edd_prices_include_tax() ) {
392
+
393
+ $price -= edd_get_cart_item_tax( $item_id, $options, $price );
394
 
 
 
 
 
 
 
 
 
 
395
  }
396
 
397
+ if( edd_display_tax_rate() ) {
398
+
399
+ $label = '&nbsp;&ndash;&nbsp;';
400
+
401
+ if( edd_prices_show_tax_on_checkout() ) {
402
+ $label .= sprintf( __( 'includes %s tax', 'edd' ), edd_get_formatted_tax_rate() );
403
+ } else {
404
+ $label .= sprintf( __( 'excludes %s tax', 'edd' ), edd_get_formatted_tax_rate() );
405
+ }
406
+
407
+ $label = apply_filters( 'edd_cart_item_tax_description', $label, $item_id, $options );
408
+
409
+ }
410
  }
411
 
412
+ $price = edd_currency_filter( edd_format_amount( $price ) );
413
+
414
+ return apply_filters( 'edd_cart_item_price_label', $price . $label, $item_id, $options );
415
  }
416
 
417
  /**
423
  * Use edd_get_cart_item_final_price()
424
  *
425
  * @since 1.0
426
+ * @param int $download_id Download ID number
427
  * @param array $options Optional parameters, used for defining variable prices
 
428
  * @return float|bool Price for this item
429
  */
430
+ function edd_get_cart_item_price( $download_id = 0, $options = array() ) {
431
+
432
+ $price = 0;
433
+ $variable_prices = edd_has_variable_prices( $download_id );
434
 
435
+ if ( $variable_prices ) {
436
 
 
437
  $prices = edd_get_variable_prices( $download_id );
438
+
439
  if ( $prices ) {
 
 
 
440
 
441
+ if( ! empty( $options ) ) {
 
 
 
442
 
443
+ $price = isset( $prices[ $options['price_id'] ] ) ? $prices[ $options['price_id'] ]['amount'] : false;
444
+
445
+ } else {
446
+
447
+ $price = false;
448
+
449
+ }
450
 
 
 
 
 
 
451
  }
452
 
453
  }
454
 
455
+ if( ! $variable_prices || false === $price ) {
456
+ // Get the standard Download price if not using variable prices
457
+ $price = edd_get_download_price( $download_id );
458
+ }
459
+
460
+ return apply_filters( 'edd_cart_item_price', $price, $download_id, $options );
461
  }
462
 
463
  /**
479
  * Get cart item tax
480
  *
481
  * @since 1.9
482
+ * @param array $download_id Download ID
483
+ * @param array $options Cart item options
484
+ * @param float $subtotal Cart item subtotal
485
  * @return float Tax amount
486
  */
487
+ function edd_get_cart_item_tax( $download_id = 0, $options = array(), $subtotal = '' ) {
 
 
 
488
 
489
+ $tax = 0;
490
+ if( ! edd_download_is_tax_exclusive( $download_id ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
 
492
  $country = ! empty( $_POST['billing_country'] ) ? $_POST['billing_country'] : false;
493
  $state = ! empty( $_POST['card_state'] ) ? $_POST['card_state'] : false;
494
 
495
+ $tax = edd_calculate_tax( $subtotal, $country, $state );
496
 
497
  }
498
 
499
+ return apply_filters( 'edd_get_cart_item_tax', $tax, $download_id, $options, $subtotal );
500
  }
501
 
502
  /**
552
  function edd_get_cart_item_price_name( $item = array() ) {
553
  $price_id = (int) edd_get_cart_item_price_id( $item );
554
  $prices = edd_get_variable_prices( $item['id'] );
555
+ $name = ! empty( $prices[ $price_id ] ) ? $prices[ $price_id ]['name'] : '';
556
  return apply_filters( 'edd_get_cart_item_price_name', $name, $item['id'], $price_id, $item );
557
  }
558
 
562
  * Shows the subtotal for the shopping cart (no taxes)
563
  *
564
  * @since 1.4
 
565
  * @return float Total amount before taxes fully formatted
566
  */
567
  function edd_cart_subtotal() {
 
 
568
  $price = esc_html( edd_currency_filter( edd_format_amount( edd_get_cart_subtotal() ) ) );
569
 
570
  // Todo - Show tax labels here (if needed)
579
  * uses edd_get_cart_contents().
580
  *
581
  * @since 1.3.3
 
582
  * @return float Total amount before taxes
583
  */
584
  function edd_get_cart_subtotal() {
 
 
585
  $subtotal = 0.00;
586
  $items = edd_get_cart_content_details();
587
 
588
  if( $items ) {
589
 
590
+ $prices = wp_list_pluck( $items, 'subtotal' );
591
 
592
  if( is_array( $prices ) ) {
593
  $subtotal = array_sum( $prices );
610
  * Returns amount after taxes and discounts
611
  *
612
  * @since 1.4.1
 
613
  * @param bool $discounts Array of discounts to apply (needed during AJAX calls)
614
  * @return float Cart amount
615
  */
616
  function edd_get_cart_total( $discounts = false ) {
617
+ $subtotal = edd_get_cart_subtotal();
618
+ $discounts = edd_get_cart_discounted_amount();
619
+ $cart_tax = edd_get_cart_tax();
620
+ $fees = edd_get_cart_fee_total();
621
+ $total = $subtotal - $discounts + $cart_tax + $fees;
 
 
622
 
623
  if( $total < 0 )
624
  $total = 0.00;
633
  * Gets the fully formatted total price amount in the cart.
634
  * uses edd_get_cart_amount().
635
  *
 
636
  * @since 1.3.3
637
  *
638
  * @param bool $echo
639
  * @return mixed|string|void
640
  */
641
  function edd_cart_total( $echo = true ) {
 
 
642
  $total = apply_filters( 'edd_cart_total', edd_currency_filter( edd_format_amount( edd_get_cart_total() ) ) );
643
 
644
  // Todo - Show tax labels here (if needed)
671
  *
672
  * @since 1.5
673
  * @param string $type
674
+ * @param int $download_id
675
  * @uses EDD()->fees->get_fees()
676
  * @return array All the cart fees that have been applied
677
  */
678
+ function edd_get_cart_fees( $type = 'all', $download_id = 0 ) {
679
+ return EDD()->fees->get_fees( $type, $download_id );
680
  }
681
 
682
  /**
708
 
709
  foreach ( $fees as $fee_id => $fee ) {
710
 
711
+ if( ! empty( $fee['no_tax'] ) ) {
712
  continue;
713
  }
714
 
715
+ // Fees must (at this time) be exclusive of tax
716
+ add_filter( 'edd_prices_include_tax', '__return_false' );
717
+
718
  $tax += edd_calculate_tax( $fee['amount'] );
719
 
720
+ remove_filter( 'edd_prices_include_tax', '__return_false' );
721
+
722
  }
723
  }
724
 
766
 
767
  if( $items ) {
768
 
769
+ $taxes = wp_list_pluck( $items, 'tax' );
770
 
771
  if( is_array( $taxes ) ) {
772
  $cart_tax = array_sum( $taxes );
776
 
777
  $cart_tax += edd_get_cart_fee_tax();
778
 
779
+ return apply_filters( 'edd_get_cart_tax', edd_sanitize_amount( $cart_tax ) );
780
  }
781
 
782
  /**
845
  * @since 1.0
846
  * @global $post
847
  * @param int $cart_key Cart item key
 
 
848
  * @return string $remove_url URL to remove the cart item
849
  */
850
+ function edd_remove_item_url( $cart_key ) {
851
+
852
+ global $wp_query;
853
 
854
  if ( defined('DOING_AJAX') ){
855
  $current_page = edd_get_checkout_uri();
856
  } else if( is_page() ) {
857
+ $current_page = add_query_arg( 'page_id', $wp_query->queried_object_id, home_url( 'index.php' ) );
858
  } else if( is_singular() ) {
859
+ $current_page = add_query_arg( 'p', $wp_query->queried_object_id, home_url( 'index.php' ) );
860
  } else {
861
  $current_page = edd_get_current_page_url();
862
  }
890
  return apply_filters( 'edd_remove_fee_url', $remove_url );
891
  }
892
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
893
  /**
894
  * Empties the Cart
895
  *
921
  *
922
  * @uses EDD()->session->set()
923
  */
924
+ function edd_set_purchase_session( $purchase_data = array() ) {
925
  EDD()->session->set( 'edd_purchase', $purchase_data );
926
  }
927
 
943
  * Checks if cart saving has been disabled
944
  *
945
  * @since 1.8
 
946
  * @return bool Whether or not cart saving has been disabled
947
  */
948
  function edd_is_cart_saving_disabled() {
949
+ $ret = edd_get_option( 'enable_cart_saving', false );
950
+ return apply_filters( 'edd_cart_saving_disabled', ! $ret );
 
951
  }
952
 
953
  /**
957
  * @return bool
958
  */
959
  function edd_is_cart_saved() {
 
960
  if( edd_is_cart_saving_disabled() )
961
  return false;
962
 
987
  return true;
988
 
989
  }
 
 
990
  }
991
 
992
  /**
993
  * Process the Cart Save
994
  *
995
  * @since 1.8
996
+ * @return bool
997
  */
998
  function edd_save_cart() {
 
 
999
  if ( edd_is_cart_saving_disabled() )
1000
+ return false;
1001
 
1002
  $user_id = get_current_user_id();
1003
  $cart = EDD()->session->get( 'edd_cart' );
1030
  );
1031
 
1032
  EDD()->session->set( 'edd_cart_messages', $messages );
1033
+
1034
+ if( $cart ) {
1035
+ return true;
1036
+ }
1037
+
1038
+ return false;
1039
  }
1040
 
1041
 
1043
  * Process the Cart Restoration
1044
  *
1045
  * @since 1.8
1046
+ * @return mixed || false Returns false if cart saving is disabled
1047
  */
1048
  function edd_restore_cart() {
1049
 
1050
  if ( edd_is_cart_saving_disabled() )
1051
+ return false;
1052
 
1053
  $user_id = get_current_user_id();
1054
  $saved_cart = get_user_meta( $user_id, 'edd_saved_cart', true );
1065
 
1066
  $messages['edd_cart_restoration_failed'] = sprintf( '<strong>%1$s</strong>: %2$s', __( 'Error', 'edd' ), __( 'Cart restoration failed. Invalid token.', 'edd' ) );
1067
  EDD()->session->set( 'edd_cart_messages', $messages );
 
 
1068
  }
1069
 
1070
  delete_user_meta( $user_id, 'edd_saved_cart' );
1071
  delete_user_meta( $user_id, 'edd_cart_token' );
1072
 
1073
+ if ( isset( $_GET['edd_cart_token'] ) && $_GET['edd_cart_token'] != $token ) {
1074
+ return new WP_Error( 'invalid_cart_token', __( 'The cart cannot be restored. Invalid token.', 'edd' ) );
1075
+ }
1076
+
1077
  } elseif ( ! is_user_logged_in() && isset( $_COOKIE['edd_saved_cart'] ) && $token ) {
1078
 
1079
  $saved_cart = $_COOKIE['edd_saved_cart'];
1096
  $messages['edd_cart_restoration_successful'] = sprintf( '<strong>%1$s</strong>: %2$s', __( 'Success', 'edd' ), __( 'Cart restored successfully.', 'edd' ) );
1097
  EDD()->session->set( 'edd_cart', $saved_cart );
1098
  EDD()->session->set( 'edd_cart_messages', $messages );
1099
+
1100
+ return true;
1101
  }
1102
 
1103
  /**
includes/cart/template.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Cart
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -48,8 +48,6 @@ function edd_checkout_cart() {
48
  * @return string Fully formatted cart
49
  */
50
  function edd_shopping_cart( $echo = false ) {
51
- global $edd_options;
52
-
53
  ob_start();
54
 
55
  do_action( 'edd_before_cart' );
@@ -78,9 +76,10 @@ function edd_get_cart_item_template( $cart_key, $item, $ajax = false ) {
78
 
79
  $id = is_array( $item ) ? $item['id'] : $item;
80
 
81
- $remove_url = edd_remove_item_url( $cart_key, $post, $ajax );
82
  $title = get_the_title( $id );
83
  $options = !empty( $item['options'] ) ? $item['options'] : array();
 
84
  $price = edd_get_cart_item_price( $id, $options );
85
 
86
  if ( ! empty( $options ) ) {
@@ -97,6 +96,7 @@ function edd_get_cart_item_template( $cart_key, $item, $ajax = false ) {
97
  $item = str_replace( '{item_amount}', edd_currency_filter( edd_format_amount( $price ) ), $item );
98
  $item = str_replace( '{cart_item_id}', absint( $cart_key ), $item );
99
  $item = str_replace( '{item_id}', absint( $id ), $item );
 
100
  $item = str_replace( '{remove_url}', $remove_url, $item );
101
  $subtotal = '';
102
  if ( $ajax ){
@@ -146,16 +146,13 @@ function edd_checkout_cart_columns() {
146
  * Display the "Save Cart" button on the checkout
147
  *
148
  * @since 1.8
149
- * @global $edd_options Array of all the EDD Options
150
  * @return void
151
  */
152
  function edd_save_cart_button() {
153
- global $edd_options;
154
-
155
  if ( edd_is_cart_saving_disabled() )
156
  return;
157
 
158
- $color = isset( $edd_options[ 'checkout_color' ] ) ? $edd_options[ 'checkout_color' ] : 'blue';
159
  $color = ( $color == 'inherit' ) ? '' : $color;
160
 
161
  if ( edd_is_cart_saved() ) : ?>
@@ -186,16 +183,13 @@ add_action( 'edd_cart_empty', 'edd_empty_cart_restore_cart_link' );
186
  * Display the "Save Cart" button on the checkout
187
  *
188
  * @since 1.8
189
- * @global $edd_options Array of all the EDD Options
190
  * @return void
191
  */
192
  function edd_update_cart_button() {
193
- global $edd_options;
194
-
195
  if ( ! edd_item_quantities_enabled() )
196
  return;
197
 
198
- $color = isset( $edd_options[ 'checkout_color' ] ) ? $edd_options[ 'checkout_color' ] : 'blue';
199
  $color = ( $color == 'inherit' ) ? '' : $color;
200
  ?>
201
  <input type="submit" name="edd_update_cart_submit" class="edd-submit edd-no-js button<?php echo ' ' . $color; ?>" value="<?php _e( 'Update Cart', 'edd' ); ?>"/>
@@ -229,3 +223,25 @@ function edd_display_cart_messages() {
229
  }
230
  }
231
  add_action( 'edd_before_checkout_cart', 'edd_display_cart_messages' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  *
5
  * @package EDD
6
  * @subpackage Cart
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
48
  * @return string Fully formatted cart
49
  */
50
  function edd_shopping_cart( $echo = false ) {
 
 
51
  ob_start();
52
 
53
  do_action( 'edd_before_cart' );
76
 
77
  $id = is_array( $item ) ? $item['id'] : $item;
78
 
79
+ $remove_url = edd_remove_item_url( $cart_key );
80
  $title = get_the_title( $id );
81
  $options = !empty( $item['options'] ) ? $item['options'] : array();
82
+ $quantity = edd_get_cart_item_quantity( $id, $options );
83
  $price = edd_get_cart_item_price( $id, $options );
84
 
85
  if ( ! empty( $options ) ) {
96
  $item = str_replace( '{item_amount}', edd_currency_filter( edd_format_amount( $price ) ), $item );
97
  $item = str_replace( '{cart_item_id}', absint( $cart_key ), $item );
98
  $item = str_replace( '{item_id}', absint( $id ), $item );
99
+ $item = str_replace( '{item_quantity}', absint( $quantity ), $item );
100
  $item = str_replace( '{remove_url}', $remove_url, $item );
101
  $subtotal = '';
102
  if ( $ajax ){
146
  * Display the "Save Cart" button on the checkout
147
  *
148
  * @since 1.8
 
149
  * @return void
150
  */
151
  function edd_save_cart_button() {
 
 
152
  if ( edd_is_cart_saving_disabled() )
153
  return;
154
 
155
+ $color = edd_get_option( 'checkout_color', 'blue' );
156
  $color = ( $color == 'inherit' ) ? '' : $color;
157
 
158
  if ( edd_is_cart_saved() ) : ?>
183
  * Display the "Save Cart" button on the checkout
184
  *
185
  * @since 1.8
 
186
  * @return void
187
  */
188
  function edd_update_cart_button() {
 
 
189
  if ( ! edd_item_quantities_enabled() )
190
  return;
191
 
192
+ $color = edd_get_option( 'checkout_color', 'blue' );
193
  $color = ( $color == 'inherit' ) ? '' : $color;
194
  ?>
195
  <input type="submit" name="edd_update_cart_submit" class="edd-submit edd-no-js button<?php echo ' ' . $color; ?>" value="<?php _e( 'Update Cart', 'edd' ); ?>"/>
223
  }
224
  }
225
  add_action( 'edd_before_checkout_cart', 'edd_display_cart_messages' );
226
+
227
+ /**
228
+ * Show Added To Cart Messages
229
+ *
230
+ * @since 1.0
231
+ * @param int $download_id Download (Post) ID
232
+ * @return void
233
+ */
234
+ function edd_show_added_to_cart_messages( $download_id ) {
235
+ if ( isset( $_POST['edd_action'] ) && $_POST['edd_action'] == 'add_to_cart' ) {
236
+ if ( $download_id != absint( $_POST['download_id'] ) )
237
+ $download_id = absint( $_POST['download_id'] );
238
+
239
+ $alert = '<div class="edd_added_to_cart_alert">'
240
+ . sprintf( __('You have successfully added %s to your shopping cart.', 'edd'), get_the_title( $download_id ) )
241
+ . ' <a href="' . edd_get_checkout_uri() . '" class="edd_alert_checkout_link">' . __('Checkout.', 'edd') . '</a>'
242
+ . '</div>';
243
+
244
+ echo apply_filters( 'edd_show_added_to_cart_messages', $alert );
245
+ }
246
+ }
247
+ add_action('edd_after_download_content', 'edd_show_added_to_cart_messages');
includes/checkout/functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Checkout
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -19,8 +19,25 @@ if ( ! defined( 'ABSPATH' ) ) exit;
19
  * @return bool True if on the Checkout page, false otherwise
20
  */
21
  function edd_is_checkout() {
22
- global $edd_options;
23
- $is_checkout = isset( $edd_options['purchase_page'] ) ? is_page( $edd_options['purchase_page'] ) : false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  return apply_filters( 'edd_is_checkout', $is_checkout );
25
  }
26
 
@@ -28,12 +45,9 @@ function edd_is_checkout() {
28
  * Determines if a user can checkout or not
29
  *
30
  * @since 1.3.3
31
- * @global $edd_options Array of all the EDD Options
32
  * @return bool Can user checkout?
33
  */
34
  function edd_can_checkout() {
35
- global $edd_options;
36
-
37
  $can_checkout = true; // Always true for now
38
 
39
  return (bool) apply_filters( 'edd_can_checkout', $can_checkout );
@@ -47,11 +61,10 @@ function edd_can_checkout() {
47
  * @return string
48
  */
49
  function edd_get_success_page_uri() {
50
- global $edd_options;
51
-
52
- $page_id = isset( $edd_options['success_page'] ) ? absint( $edd_options['success_page'] ) : 0;
53
 
54
- return apply_filters( 'edd_get_success_page_uri', get_permalink( $edd_options['success_page'] ) );
55
  }
56
 
57
  /**
@@ -61,8 +74,9 @@ function edd_get_success_page_uri() {
61
  * @return bool True if on the Success page, false otherwise.
62
  */
63
  function edd_is_success_page() {
64
- global $edd_options;
65
- $is_success_page = isset( $edd_options['success_page'] ) ? is_page( $edd_options['success_page'] ) : false;
 
66
  return apply_filters( 'edd_is_success_page', $is_success_page );
67
  }
68
 
@@ -77,14 +91,14 @@ function edd_is_success_page() {
77
  * @return void
78
  */
79
  function edd_send_to_success_page( $query_string = null ) {
80
- global $edd_options;
81
-
82
  $redirect = edd_get_success_page_uri();
83
 
84
  if ( $query_string )
85
  $redirect .= $query_string;
86
 
87
- wp_redirect( apply_filters('edd_success_page_redirect', $redirect, $_POST['edd-gateway'], $query_string) );
 
 
88
  edd_die();
89
  }
90
 
@@ -92,14 +106,12 @@ function edd_send_to_success_page( $query_string = null ) {
92
  * Get the URL of the Checkout page
93
  *
94
  * @since 1.0.8
95
- * @global $edd_options Array of all the EDD Options
96
  * @param array $args Extra query args to add to the URI
97
  * @return mixed Full URL to the checkout page, if present | null if it doesn't exist
98
  */
99
  function edd_get_checkout_uri( $args = array() ) {
100
- global $edd_options;
101
-
102
- $uri = isset( $edd_options['purchase_page'] ) ? get_permalink( $edd_options['purchase_page'] ) : NULL;
103
 
104
  if ( ! empty( $args ) ) {
105
  // Check for backward compatibility
@@ -115,11 +127,11 @@ function edd_get_checkout_uri( $args = array() ) {
115
 
116
  $ajax_url = admin_url( 'admin-ajax.php', $scheme );
117
 
118
- if ( ( ! preg_match( '/^https/', $uri ) && preg_match( '/^https/', $ajax_url ) ) || edd_is_ssl_enforced() ) {
119
  $uri = preg_replace( '/^http:/', 'https:', $uri );
120
  }
121
 
122
- if ( isset( $edd_options['no_cache_checkout'] ) && edd_is_caching_plugin_active() )
123
  $uri = add_query_arg( 'nocache', 'true', $uri );
124
 
125
  return apply_filters( 'edd_get_checkout_uri', $uri );
@@ -164,9 +176,9 @@ function edd_send_back_to_checkout( $args = array() ) {
164
  * @return string
165
  */
166
  function edd_get_success_page_url( $query_string = null ) {
167
- global $edd_options;
 
168
 
169
- $success_page = get_permalink($edd_options['success_page']);
170
  if ( $query_string )
171
  $success_page .= $query_string;
172
 
@@ -177,21 +189,32 @@ function edd_get_success_page_url( $query_string = null ) {
177
  * Get the URL of the Transaction Failed page
178
  *
179
  * @since 1.3.4
180
- * @global $edd_options Array of all the EDD Options
181
- *
182
  * @param bool $extras Extras to append to the URL
183
  * @return mixed|void Full URL to the Transaction Failed page, if present, home page if it doesn't exist
184
  */
185
  function edd_get_failed_transaction_uri( $extras = false ) {
186
- global $edd_options;
187
-
188
- $uri = ! empty( $edd_options['failure_page'] ) ? trailingslashit( get_permalink( $edd_options['failure_page'] ) ) : home_url();
189
  if ( $extras )
190
  $uri .= $extras;
191
 
192
  return apply_filters( 'edd_get_failed_transaction_uri', $uri );
193
  }
194
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  /**
196
  * Mark payments as Failed when returning to the Failed Transaction page
197
  *
@@ -200,13 +223,19 @@ function edd_get_failed_transaction_uri( $extras = false ) {
200
  * @return void
201
  */
202
  function edd_listen_for_failed_payments() {
203
-
204
  $failed_page = edd_get_option( 'failure_page', 0 );
205
 
206
  if( ! empty( $failed_page ) && is_page( $failed_page ) && ! empty( $_GET['payment-id'] ) ) {
207
 
208
  $payment_id = absint( $_GET['payment-id'] );
209
- edd_update_payment_status( $payment_id, 'failed' );
 
 
 
 
 
 
210
 
211
  }
212
 
@@ -250,12 +279,24 @@ function edd_is_email_banned( $email = '' ) {
250
  return false;
251
  }
252
 
253
- $ret = in_array( trim( $email ), edd_get_banned_emails() );
254
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  return apply_filters( 'edd_is_email_banned', $ret, $email );
256
  }
257
 
258
- /**
259
  * Determines if secure checkout pages are enforced
260
  *
261
  * @since 2.0
@@ -270,14 +311,13 @@ function edd_is_ssl_enforced() {
270
  * Handle redirections for SSL enforced checkouts
271
  *
272
  * @since 2.0
273
- * @global $edd_options Array of all the EDD Options
274
  * @return void
275
  */
276
  function edd_enforced_ssl_redirect_handler() {
277
  if ( ! edd_is_ssl_enforced() || ! edd_is_checkout() || is_admin() || is_ssl() ) {
278
  return;
279
  }
280
-
281
  if ( isset( $_SERVER["HTTPS"] ) && $_SERVER["HTTPS"] == "on" ) {
282
  return;
283
  }
@@ -313,7 +353,7 @@ function edd_enforced_ssl_asset_handler() {
313
  'stylesheet_directory_uri',
314
  'site_url'
315
  );
316
-
317
  $filters = apply_filters( 'edd_enforced_ssl_asset_filters', $filters );
318
 
319
  foreach ( $filters as $filter ) {
@@ -330,11 +370,43 @@ add_action( 'template_redirect', 'edd_enforced_ssl_asset_handler' );
330
  * @return mixed
331
  */
332
  function edd_enforced_ssl_asset_filter( $content ) {
 
333
  if ( is_array( $content ) ) {
 
334
  $content = array_map( 'edd_enforced_ssl_asset_filter', $content );
 
335
  } else {
336
- $content = str_replace( 'http:', 'https:', $content );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  }
338
 
339
  return $content;
340
- }
4
  *
5
  * @package EDD
6
  * @subpackage Checkout
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
19
  * @return bool True if on the Checkout page, false otherwise
20
  */
21
  function edd_is_checkout() {
22
+
23
+ global $wp_query;
24
+
25
+ $is_object_set = isset( $wp_query->queried_object );
26
+ $is_object_id_set = isset( $wp_query->queried_object_id );
27
+ $is_checkout = is_page( edd_get_option( 'purchase_page' ) );
28
+
29
+ if( ! $is_object_set ) {
30
+
31
+ unset( $wp_query->queried_object );
32
+
33
+ }
34
+
35
+ if( ! $is_object_id_set ) {
36
+
37
+ unset( $wp_query->queried_object_id );
38
+
39
+ }
40
+
41
  return apply_filters( 'edd_is_checkout', $is_checkout );
42
  }
43
 
45
  * Determines if a user can checkout or not
46
  *
47
  * @since 1.3.3
 
48
  * @return bool Can user checkout?
49
  */
50
  function edd_can_checkout() {
 
 
51
  $can_checkout = true; // Always true for now
52
 
53
  return (bool) apply_filters( 'edd_can_checkout', $can_checkout );
61
  * @return string
62
  */
63
  function edd_get_success_page_uri() {
64
+ $page_id = edd_get_option( 'success_page', 0 );
65
+ $page_id = absint( $page_id );
 
66
 
67
+ return apply_filters( 'edd_get_success_page_uri', get_permalink( $page_id ) );
68
  }
69
 
70
  /**
74
  * @return bool True if on the Success page, false otherwise.
75
  */
76
  function edd_is_success_page() {
77
+ $is_success_page = edd_get_option( 'success_page', false );
78
+ $is_success_page = isset( $is_success_page ) ? is_page( $is_success_page ) : false;
79
+
80
  return apply_filters( 'edd_is_success_page', $is_success_page );
81
  }
82
 
91
  * @return void
92
  */
93
  function edd_send_to_success_page( $query_string = null ) {
 
 
94
  $redirect = edd_get_success_page_uri();
95
 
96
  if ( $query_string )
97
  $redirect .= $query_string;
98
 
99
+ $gateway = isset( $_REQUEST['edd-gateway'] ) ? $_REQUEST['edd-gateway'] : '';
100
+
101
+ wp_redirect( apply_filters('edd_success_page_redirect', $redirect, $gateway, $query_string) );
102
  edd_die();
103
  }
104
 
106
  * Get the URL of the Checkout page
107
  *
108
  * @since 1.0.8
 
109
  * @param array $args Extra query args to add to the URI
110
  * @return mixed Full URL to the checkout page, if present | null if it doesn't exist
111
  */
112
  function edd_get_checkout_uri( $args = array() ) {
113
+ $uri = edd_get_option( 'purchase_page', false );
114
+ $uri = isset( $uri ) ? get_permalink( $uri ) : NULL;
 
115
 
116
  if ( ! empty( $args ) ) {
117
  // Check for backward compatibility
127
 
128
  $ajax_url = admin_url( 'admin-ajax.php', $scheme );
129
 
130
+ if ( ( ! preg_match( '/^https/', $uri ) && preg_match( '/^https/', $ajax_url ) && edd_is_ajax_enabled() ) || edd_is_ssl_enforced() ) {
131
  $uri = preg_replace( '/^http:/', 'https:', $uri );
132
  }
133
 
134
+ if ( edd_get_option( 'no_cache_checkout', false ) && edd_is_caching_plugin_active() )
135
  $uri = add_query_arg( 'nocache', 'true', $uri );
136
 
137
  return apply_filters( 'edd_get_checkout_uri', $uri );
176
  * @return string
177
  */
178
  function edd_get_success_page_url( $query_string = null ) {
179
+ $success_page = edd_get_option( 'success_page', 0 );
180
+ $success_page = get_permalink( $success_page );
181
 
 
182
  if ( $query_string )
183
  $success_page .= $query_string;
184
 
189
  * Get the URL of the Transaction Failed page
190
  *
191
  * @since 1.3.4
 
 
192
  * @param bool $extras Extras to append to the URL
193
  * @return mixed|void Full URL to the Transaction Failed page, if present, home page if it doesn't exist
194
  */
195
  function edd_get_failed_transaction_uri( $extras = false ) {
196
+ $uri = edd_get_option( 'failure_page', '' );
197
+ $uri = ! empty( $uri ) ? trailingslashit( get_permalink( $uri ) ) : home_url();
198
+
199
  if ( $extras )
200
  $uri .= $extras;
201
 
202
  return apply_filters( 'edd_get_failed_transaction_uri', $uri );
203
  }
204
 
205
+ /**
206
+ * Determines if we're currently on the Failed Transaction page.
207
+ *
208
+ * @since 2.1
209
+ * @return bool True if on the Failed Transaction page, false otherwise.
210
+ */
211
+ function edd_is_failed_transaction_page() {
212
+ $ret = edd_get_option( 'failure_page', false );
213
+ $ret = isset( $ret ) ? is_page( $ret ) : false;
214
+
215
+ return apply_filters( 'edd_is_failure_page', $ret );
216
+ }
217
+
218
  /**
219
  * Mark payments as Failed when returning to the Failed Transaction page
220
  *
223
  * @return void
224
  */
225
  function edd_listen_for_failed_payments() {
226
+
227
  $failed_page = edd_get_option( 'failure_page', 0 );
228
 
229
  if( ! empty( $failed_page ) && is_page( $failed_page ) && ! empty( $_GET['payment-id'] ) ) {
230
 
231
  $payment_id = absint( $_GET['payment-id'] );
232
+ $status = edd_get_payment_status( $payment_id );
233
+
234
+ if( $status && 'pending' === strtolower( $status ) ) {
235
+
236
+ edd_update_payment_status( $payment_id, 'failed' );
237
+
238
+ }
239
 
240
  }
241
 
279
  return false;
280
  }
281
 
282
+ $banned_emails = edd_get_banned_emails();
283
 
284
+ foreach( $banned_emails as $banned_email ) {
285
+ if( is_email( $banned_email ) ) {
286
+ $ret = ( $banned_email == trim( $email ) ? true : false );
287
+ } else {
288
+ $ret = ( stristr( trim( $email ), $banned_email ) ? true : false );
289
+ }
290
+
291
+ if( true === $ret ) {
292
+ break;
293
+ }
294
+ }
295
+
296
  return apply_filters( 'edd_is_email_banned', $ret, $email );
297
  }
298
 
299
+ /**
300
  * Determines if secure checkout pages are enforced
301
  *
302
  * @since 2.0
311
  * Handle redirections for SSL enforced checkouts
312
  *
313
  * @since 2.0
 
314
  * @return void
315
  */
316
  function edd_enforced_ssl_redirect_handler() {
317
  if ( ! edd_is_ssl_enforced() || ! edd_is_checkout() || is_admin() || is_ssl() ) {
318
  return;
319
  }
320
+
321
  if ( isset( $_SERVER["HTTPS"] ) && $_SERVER["HTTPS"] == "on" ) {
322
  return;
323
  }
353
  'stylesheet_directory_uri',
354
  'site_url'
355
  );
356
+
357
  $filters = apply_filters( 'edd_enforced_ssl_asset_filters', $filters );
358
 
359
  foreach ( $filters as $filter ) {
370
  * @return mixed
371
  */
372
  function edd_enforced_ssl_asset_filter( $content ) {
373
+
374
  if ( is_array( $content ) ) {
375
+
376
  $content = array_map( 'edd_enforced_ssl_asset_filter', $content );
377
+
378
  } else {
379
+
380
+ // Detect if URL ends in a common domain suffix. We want to only affect assets
381
+ $extension = untrailingslashit( edd_get_file_extension( $content ) );
382
+ $suffixes = array(
383
+ 'br',
384
+ 'ca',
385
+ 'cn',
386
+ 'com',
387
+ 'de',
388
+ 'dev',
389
+ 'edu',
390
+ 'fr',
391
+ 'in',
392
+ 'info',
393
+ 'jp',
394
+ 'local',
395
+ 'mobi',
396
+ 'name',
397
+ 'net',
398
+ 'nz',
399
+ 'org',
400
+ 'ru',
401
+ );
402
+
403
+ if( ! in_array( $extension, $suffixes ) ) {
404
+
405
+ $content = str_replace( 'http:', 'https:', $content );
406
+
407
+ }
408
+
409
  }
410
 
411
  return $content;
412
+ }
includes/checkout/template.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Checkout
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -16,20 +16,15 @@ if ( ! defined( 'ABSPATH' ) ) exit;
16
  * Get Checkout Form
17
  *
18
  * @since 1.0
19
- * @global $edd_options Array of all the EDD options
20
- * @global $user_ID ID of current logged in user
21
- * @global $post Current Post Object
22
  * @return string
23
  */
24
  function edd_checkout_form() {
25
- global $edd_options, $user_ID, $post;
26
-
27
  $payment_mode = edd_get_chosen_gateway();
28
  $form_action = esc_url( edd_get_checkout_uri( 'payment-mode=' . $payment_mode ) );
29
 
30
  ob_start();
31
  echo '<div id="edd_checkout_wrap">';
32
- if ( edd_get_cart_contents() || edd_get_cart_fees() ) :
33
 
34
  edd_checkout_cart();
35
  ?>
@@ -37,6 +32,11 @@ function edd_checkout_form() {
37
  <?php do_action( 'edd_before_purchase_form' ); ?>
38
  <form id="edd_purchase_form" class="edd_form" action="<?php echo $form_action; ?>" method="POST">
39
  <?php
 
 
 
 
 
40
  do_action( 'edd_checkout_form_top' );
41
 
42
  if ( edd_show_gateways() ) {
@@ -45,6 +45,11 @@ function edd_checkout_form() {
45
  do_action( 'edd_purchase_form' );
46
  }
47
 
 
 
 
 
 
48
  do_action( 'edd_checkout_form_bottom' )
49
  ?>
50
  </form>
@@ -52,6 +57,11 @@ function edd_checkout_form() {
52
  </div><!--end #edd_checkout_form_wrap-->
53
  <?php
54
  else:
 
 
 
 
 
55
  do_action( 'edd_cart_empty' );
56
  endif;
57
  echo '</div><!--end #edd_checkout_wrap-->';
@@ -65,14 +75,16 @@ function edd_checkout_form() {
65
  * if credit cards are enabled
66
  *
67
  * @since 1.4
68
- * @global $edd_options Array of all the EDD options
69
  * @return string
70
  */
71
  function edd_show_purchase_form() {
72
- global $edd_options;
73
-
74
  $payment_mode = edd_get_chosen_gateway();
75
 
 
 
 
 
 
76
  do_action( 'edd_purchase_form_top' );
77
 
78
  if ( edd_can_checkout() ) {
@@ -80,20 +92,25 @@ function edd_show_purchase_form() {
80
  do_action( 'edd_purchase_form_before_register_login' );
81
 
82
  $show_register_form = edd_get_option( 'show_register_form', 'none' ) ;
83
- if( ( $show_register_form == 'registration' || ( $show_register_form == 'both' && ! isset( $_GET['login'] ) ) ) && ! is_user_logged_in() ) : ?>
84
  <div id="edd_checkout_login_register">
85
  <?php do_action( 'edd_purchase_form_register_fields' ); ?>
86
  </div>
87
- <?php elseif( ( $show_register_form == 'login' || ( $show_register_form == 'both' && isset( $_GET['login'] ) ) ) && ! is_user_logged_in() ) : ?>
88
  <div id="edd_checkout_login_register">
89
  <?php do_action( 'edd_purchase_form_login_fields' ); ?>
90
  </div>
91
  <?php endif; ?>
92
 
93
- <?php if( ( !isset( $_GET['login'] ) && is_user_logged_in() ) || ! isset( $edd_options['show_register_form'] ) || 'none' == $show_register_form ) {
94
  do_action( 'edd_purchase_form_after_user_info' );
95
  }
96
 
 
 
 
 
 
97
  do_action( 'edd_purchase_form_before_cc_form' );
98
 
99
  if( edd_get_cart_total() > 0 ) {
@@ -107,6 +124,11 @@ function edd_show_purchase_form() {
107
 
108
  }
109
 
 
 
 
 
 
110
  do_action( 'edd_purchase_form_after_cc_form' );
111
 
112
  } else {
@@ -114,6 +136,11 @@ function edd_show_purchase_form() {
114
  do_action( 'edd_purchase_form_no_access' );
115
  }
116
 
 
 
 
 
 
117
  do_action( 'edd_purchase_form_bottom' );
118
  }
119
  add_action( 'edd_purchase_form', 'edd_show_purchase_form' );
@@ -165,6 +192,7 @@ function edd_user_info_fields() {
165
  <input class="edd-input<?php if( edd_field_is_required( 'edd_last' ) ) { echo ' required'; } ?>" type="text" name="edd_last" id="edd-last" placeholder="<?php _e( 'Last name', 'edd' ); ?>" value="<?php echo is_user_logged_in() ? $user_data->last_name : ''; ?>"/>
166
  </p>
167
  <?php do_action( 'edd_purchase_form_user_info' ); ?>
 
168
  </fieldset>
169
  <?php
170
  }
@@ -205,7 +233,7 @@ function edd_get_cc_form() {
205
  <span class="edd-required-indicator">*</span>
206
  </label>
207
  <span class="edd-description"><?php _e( 'The 3 digit (back) or 4 digit (front) value on your card.', 'edd' ); ?></span>
208
- <input type="text" size="4" autocomplete="off" name="card_cvc" id="card_cvc" class="card-cvc edd-input required" placeholder="<?php _e( 'Security code', 'edd' ); ?>" />
209
  </p>
210
  <p id="edd-card-name-wrap">
211
  <label for="card_name" class="edd-label">
@@ -383,21 +411,15 @@ add_action( 'edd_purchase_form_after_cc_form', 'edd_checkout_tax_fields', 999 );
383
  * @return string
384
  */
385
  function edd_get_register_fields() {
386
- global $edd_options;
387
- global $user_ID;
388
-
389
- if ( is_user_logged_in() )
390
- $user_data = get_userdata( $user_ID );
391
-
392
  $show_register_form = edd_get_option( 'show_register_form', 'none' );
393
 
394
  ob_start(); ?>
395
  <fieldset id="edd_register_fields">
396
 
397
  <?php if( $show_register_form == 'both' ) { ?>
398
- <p id="edd-login-account-wrap"><?php _e( 'Already have an account?', 'edd' ); ?> <a href="<?php echo esc_url( add_query_arg('login', 1) ); ?>" class="edd_checkout_register_login" data-action="checkout_login"><?php _e( 'Login', 'edd' ); ?></a></p>
399
  <?php } ?>
400
-
401
  <?php do_action('edd_register_fields_before'); ?>
402
 
403
  <fieldset id="edd_register_account_fields">
@@ -441,6 +463,7 @@ function edd_get_register_fields() {
441
  <input type="hidden" name="edd-purchase-var" value="needs-to-register"/>
442
 
443
  <?php do_action( 'edd_purchase_form_user_info' ); ?>
 
444
 
445
  </fieldset>
446
  <?php
@@ -457,11 +480,9 @@ add_action( 'edd_purchase_form_register_fields', 'edd_get_register_fields' );
457
  * @return string
458
  */
459
  function edd_get_login_fields() {
460
- global $edd_options;
461
-
462
- $color = isset( $edd_options[ 'checkout_color' ] ) ? $edd_options[ 'checkout_color' ] : 'gray';
463
  $color = ( $color == 'inherit' ) ? '' : $color;
464
- $style = isset( $edd_options[ 'button_style' ] ) ? $edd_options[ 'button_style' ] : 'button';
465
 
466
  $show_register_form = edd_get_option( 'show_register_form', 'none' );
467
 
@@ -552,40 +573,65 @@ add_action( 'edd_payment_mode_select', 'edd_payment_mode_select' );
552
  * then outputting the icons.
553
  *
554
  * @since 1.0
555
- * @global $edd_options Array of all the EDD Options
556
  * @return void
557
  */
558
  function edd_show_payment_icons() {
559
- global $edd_options;
560
 
561
- if( edd_show_gateways() && did_action( 'edd_payment_mode_top' ) )
 
 
 
 
 
 
562
  return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
563
 
564
- if ( isset( $edd_options['accepted_cards'] ) ) {
565
- echo '<div class="edd-payment-icons">';
566
- foreach( $edd_options['accepted_cards'] as $key => $card ) {
567
- if( edd_string_is_image_url( $key ) ) {
568
- echo '<img class="payment-icon" src="' . esc_url( $key ) . '"/>';
569
  } else {
570
- $image = edd_locate_template( 'images' . DIRECTORY_SEPARATOR . 'icons' . DIRECTORY_SEPARATOR . strtolower( str_replace( ' ', '', $card ) ) . '.gif', false );
571
- $content_dir = WP_CONTENT_DIR;
 
572
 
573
  if( function_exists( 'wp_normalize_path' ) ) {
 
574
  // Replaces backslashes with forward slashes for Windows systems
575
  $image = wp_normalize_path( $image );
576
  $content_dir = wp_normalize_path( $content_dir );
 
577
  }
 
578
  $image = str_replace( $content_dir, WP_CONTENT_URL, $image );
579
 
580
- if( edd_is_ssl_enforced() || is_ssl() ) {
581
- $image = edd_enforced_ssl_asset_filter( $image );
582
- }
 
 
583
 
584
- echo '<img class="payment-icon" src="' . esc_url( $image ) . '"/>';
585
  }
 
 
586
  }
587
- echo '</div>';
588
  }
 
 
589
  }
590
  add_action( 'edd_payment_mode_top', 'edd_show_payment_icons' );
591
  add_action( 'edd_checkout_form_top', 'edd_show_payment_icons' );
@@ -605,6 +651,10 @@ function edd_discount_field() {
605
  return; // Only show before a payment method has been selected if ajax is disabled
606
  }
607
 
 
 
 
 
608
  if ( edd_has_active_discounts() && edd_get_cart_total() ) :
609
 
610
  $color = edd_get_option( 'checkout_color', 'blue' );
@@ -615,7 +665,7 @@ function edd_discount_field() {
615
  <p id="edd_show_discount" style="display:none;">
616
  <?php _e( 'Have a discount code?', 'edd' ); ?> <a href="#" class="edd_discount_link"><?php echo _x( 'Click to enter it', 'Entering a discount code', 'edd' ); ?></a>
617
  </p>
618
- <p id="edd-discount-code-wrap">
619
  <label class="edd-label" for="edd-discount">
620
  <?php _e( 'Discount', 'edd' ); ?>
621
  <img src="<?php echo EDD_PLUGIN_URL; ?>assets/images/loading.gif" id="edd-discount-loader" style="display:none;"/>
@@ -637,18 +687,18 @@ add_action( 'edd_checkout_form_top', 'edd_discount_field', -1 );
637
  * set in the EDD Settings.
638
  *
639
  * @since 1.3.2
640
- * @global $edd_options Array of all the EDD Options
641
  * @return void
642
  */
643
  function edd_terms_agreement() {
644
- global $edd_options;
645
- if ( isset( $edd_options['show_agree_to_terms'] ) ) {
 
646
  ?>
647
  <fieldset id="edd_terms_agreement">
648
  <div id="edd_terms" style="display:none;">
649
  <?php
650
  do_action( 'edd_before_terms' );
651
- echo wpautop( stripslashes( $edd_options['agree_text'] ) );
652
  do_action( 'edd_after_terms' );
653
  ?>
654
  </div>
@@ -656,7 +706,7 @@ function edd_terms_agreement() {
656
  <a href="#" class="edd_terms_links"><?php _e( 'Show Terms', 'edd' ); ?></a>
657
  <a href="#" class="edd_terms_links" style="display:none;"><?php _e( 'Hide Terms', 'edd' ); ?></a>
658
  </div>
659
- <label for="edd_agree_to_terms"><?php echo isset( $edd_options['agree_label'] ) ? stripslashes( $edd_options['agree_label'] ) : __( 'Agree to Terms?', 'edd' ); ?></label>
660
  <input name="edd_agree_to_terms" class="required" type="checkbox" id="edd_agree_to_terms" value="1"/>
661
  </fieldset>
662
  <?php
@@ -710,20 +760,18 @@ add_action( 'edd_purchase_form_after_cc_form', 'edd_checkout_submit', 9999 );
710
  * Renders the Next button on the Checkout
711
  *
712
  * @since 1.2
713
- * @global $edd_options Array of all the EDD Options
714
  * @return string
715
  */
716
  function edd_checkout_button_next() {
717
- global $edd_options;
718
-
719
- $color = isset( $edd_options[ 'checkout_color' ] ) ? $edd_options[ 'checkout_color' ] : 'blue';
720
  $color = ( $color == 'inherit' ) ? '' : $color;
721
- $style = isset( $edd_options[ 'button_style' ] ) ? $edd_options[ 'button_style' ] : 'button';
 
722
 
723
  ob_start();
724
  ?>
725
  <input type="hidden" name="edd_action" value="gateway_select" />
726
- <input type="hidden" name="page_id" value="<?php echo absint( $edd_options['purchase_page'] ); ?>"/>
727
  <input type="submit" name="gateway_submit" id="edd_next_button" class="edd-submit <?php echo $color; ?> <?php echo $style; ?>" value="<?php _e( 'Next', 'edd' ); ?>"/>
728
  <?php
729
  return apply_filters( 'edd_checkout_button_next', ob_get_clean() );
@@ -733,20 +781,18 @@ function edd_checkout_button_next() {
733
  * Renders the Purchase button on the Checkout
734
  *
735
  * @since 1.2
736
- * @global $edd_options Array of all the EDD Options
737
  * @return string
738
  */
739
  function edd_checkout_button_purchase() {
740
- global $edd_options;
741
-
742
- $color = isset( $edd_options[ 'checkout_color' ] ) ? $edd_options[ 'checkout_color' ] : 'blue';
743
  $color = ( $color == 'inherit' ) ? '' : $color;
744
- $style = isset( $edd_options[ 'button_style' ] ) ? $edd_options[ 'button_style' ] : 'button';
 
745
 
746
  if ( edd_get_cart_total() ) {
747
- $complete_purchase = ! empty( $edd_options['checkout_label'] ) ? $edd_options['checkout_label'] : __( 'Purchase', 'edd' );
748
  } else {
749
- $complete_purchase = ! empty( $edd_options['checkout_label'] ) ? $edd_options['checkout_label'] : __( 'Free Download', 'edd' );
750
  }
751
 
752
  ob_start();
@@ -761,13 +807,10 @@ function edd_checkout_button_purchase() {
761
  * the T&Cs text
762
  *
763
  * @since 1.0
764
- * @global $edd_options Array of all the EDD Options
765
  * @return void
766
  */
767
  function edd_agree_to_terms_js() {
768
- global $edd_options;
769
-
770
- if ( isset( $edd_options['show_agree_to_terms'] ) ) {
771
  ?>
772
  <script type="text/javascript">
773
  jQuery(document).ready(function($){
@@ -810,14 +853,12 @@ function edd_checkout_hidden_fields() {
810
  * @return string $content Filtered content
811
  */
812
  function edd_filter_success_page_content( $content ) {
813
- global $edd_options;
814
-
815
- if ( isset( $edd_options['success_page'] ) && isset( $_GET['payment-confirmation'] ) && is_page( $edd_options['success_page'] ) ) {
816
  if ( has_filter( 'edd_payment_confirm_' . $_GET['payment-confirmation'] ) ) {
817
  $content = apply_filters( 'edd_payment_confirm_' . $_GET['payment-confirmation'], $content );
818
  }
819
  }
820
-
821
  return $content;
822
  }
823
  add_filter( 'the_content', 'edd_filter_success_page_content' );
4
  *
5
  * @package EDD
6
  * @subpackage Checkout
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
16
  * Get Checkout Form
17
  *
18
  * @since 1.0
 
 
 
19
  * @return string
20
  */
21
  function edd_checkout_form() {
 
 
22
  $payment_mode = edd_get_chosen_gateway();
23
  $form_action = esc_url( edd_get_checkout_uri( 'payment-mode=' . $payment_mode ) );
24
 
25
  ob_start();
26
  echo '<div id="edd_checkout_wrap">';
27
+ if ( edd_get_cart_contents() || edd_cart_has_fees() ) :
28
 
29
  edd_checkout_cart();
30
  ?>
32
  <?php do_action( 'edd_before_purchase_form' ); ?>
33
  <form id="edd_purchase_form" class="edd_form" action="<?php echo $form_action; ?>" method="POST">
34
  <?php
35
+ /**
36
+ * Hooks in at the top of the checkout form
37
+ *
38
+ * @since 1.0
39
+ */
40
  do_action( 'edd_checkout_form_top' );
41
 
42
  if ( edd_show_gateways() ) {
45
  do_action( 'edd_purchase_form' );
46
  }
47
 
48
+ /**
49
+ * Hooks in at the bottom of the checkout form
50
+ *
51
+ * @since 1.0
52
+ */
53
  do_action( 'edd_checkout_form_bottom' )
54
  ?>
55
  </form>
57
  </div><!--end #edd_checkout_form_wrap-->
58
  <?php
59
  else:
60
+ /**
61
+ * Fires off when there is nothing in the cart
62
+ *
63
+ * @since 1.0
64
+ */
65
  do_action( 'edd_cart_empty' );
66
  endif;
67
  echo '</div><!--end #edd_checkout_wrap-->';
75
  * if credit cards are enabled
76
  *
77
  * @since 1.4
 
78
  * @return string
79
  */
80
  function edd_show_purchase_form() {
 
 
81
  $payment_mode = edd_get_chosen_gateway();
82
 
83
+ /**
84
+ * Hooks in at the top of the purchase form
85
+ *
86
+ * @since 1.4
87
+ */
88
  do_action( 'edd_purchase_form_top' );
89
 
90
  if ( edd_can_checkout() ) {
92
  do_action( 'edd_purchase_form_before_register_login' );
93
 
94
  $show_register_form = edd_get_option( 'show_register_form', 'none' ) ;
95
+ if( ( $show_register_form === 'registration' || ( $show_register_form === 'both' && ! isset( $_GET['login'] ) ) ) && ! is_user_logged_in() ) : ?>
96
  <div id="edd_checkout_login_register">
97
  <?php do_action( 'edd_purchase_form_register_fields' ); ?>
98
  </div>
99
+ <?php elseif( ( $show_register_form === 'login' || ( $show_register_form === 'both' && isset( $_GET['login'] ) ) ) && ! is_user_logged_in() ) : ?>
100
  <div id="edd_checkout_login_register">
101
  <?php do_action( 'edd_purchase_form_login_fields' ); ?>
102
  </div>
103
  <?php endif; ?>
104
 
105
+ <?php if( ( !isset( $_GET['login'] ) && is_user_logged_in() ) || ! isset( $show_register_form ) || 'none' === $show_register_form ) {
106
  do_action( 'edd_purchase_form_after_user_info' );
107
  }
108
 
109
+ /**
110
+ * Hooks in before Credit Card Form
111
+ *
112
+ * @since 1.4
113
+ */
114
  do_action( 'edd_purchase_form_before_cc_form' );
115
 
116
  if( edd_get_cart_total() > 0 ) {
124
 
125
  }
126
 
127
+ /**
128
+ * Hooks in after Credit Card Form
129
+ *
130
+ * @since 1.4
131
+ */
132
  do_action( 'edd_purchase_form_after_cc_form' );
133
 
134
  } else {
136
  do_action( 'edd_purchase_form_no_access' );
137
  }
138
 
139
+ /**
140
+ * Hooks in at the bottom of the purchase form
141
+ *
142
+ * @since 1.4
143
+ */
144
  do_action( 'edd_purchase_form_bottom' );
145
  }
146
  add_action( 'edd_purchase_form', 'edd_show_purchase_form' );
192
  <input class="edd-input<?php if( edd_field_is_required( 'edd_last' ) ) { echo ' required'; } ?>" type="text" name="edd_last" id="edd-last" placeholder="<?php _e( 'Last name', 'edd' ); ?>" value="<?php echo is_user_logged_in() ? $user_data->last_name : ''; ?>"/>
193
  </p>
194
  <?php do_action( 'edd_purchase_form_user_info' ); ?>
195
+ <?php do_action( 'edd_purchase_form_user_info_fields' ); ?>
196
  </fieldset>
197
  <?php
198
  }
233
  <span class="edd-required-indicator">*</span>
234
  </label>
235
  <span class="edd-description"><?php _e( 'The 3 digit (back) or 4 digit (front) value on your card.', 'edd' ); ?></span>
236
+ <input type="text" size="4" maxlength="4" autocomplete="off" name="card_cvc" id="card_cvc" class="card-cvc edd-input required" placeholder="<?php _e( 'Security code', 'edd' ); ?>" />
237
  </p>
238
  <p id="edd-card-name-wrap">
239
  <label for="card_name" class="edd-label">
411
  * @return string
412
  */
413
  function edd_get_register_fields() {
 
 
 
 
 
 
414
  $show_register_form = edd_get_option( 'show_register_form', 'none' );
415
 
416
  ob_start(); ?>
417
  <fieldset id="edd_register_fields">
418
 
419
  <?php if( $show_register_form == 'both' ) { ?>
420
+ <p id="edd-login-account-wrap"><?php _e( 'Already have an account?', 'edd' ); ?> <a href="<?php echo esc_url( add_query_arg( 'login', 1 ) ); ?>" class="edd_checkout_register_login" data-action="checkout_login"><?php _e( 'Login', 'edd' ); ?></a></p>
421
  <?php } ?>
422
+
423
  <?php do_action('edd_register_fields_before'); ?>
424
 
425
  <fieldset id="edd_register_account_fields">
463
  <input type="hidden" name="edd-purchase-var" value="needs-to-register"/>
464
 
465
  <?php do_action( 'edd_purchase_form_user_info' ); ?>
466
+ <?php do_action( 'edd_purchase_form_user_register_fields' ); ?>
467
 
468
  </fieldset>
469
  <?php
480
  * @return string
481
  */
482
  function edd_get_login_fields() {
483
+ $color = edd_get_option( 'checkout_color', 'gray' );
 
 
484
  $color = ( $color == 'inherit' ) ? '' : $color;
485
+ $style = edd_get_option( 'button_style', 'button' );
486
 
487
  $show_register_form = edd_get_option( 'show_register_form', 'none' );
488
 
573
  * then outputting the icons.
574
  *
575
  * @since 1.0
 
576
  * @return void
577
  */
578
  function edd_show_payment_icons() {
 
579
 
580
+ if( edd_show_gateways() && did_action( 'edd_payment_mode_top' ) ) {
581
+ return;
582
+ }
583
+
584
+ $payment_methods = edd_get_option( 'accepted_cards', array() );
585
+
586
+ if( empty( $payment_methods ) ) {
587
  return;
588
+ }
589
+
590
+ echo '<div class="edd-payment-icons">';
591
+
592
+ foreach( $payment_methods as $key => $card ) {
593
+
594
+ if( edd_string_is_image_url( $key ) ) {
595
+
596
+ echo '<img class="payment-icon" src="' . esc_url( $key ) . '"/>';
597
+
598
+ } else {
599
+
600
+ $card = strtolower( str_replace( ' ', '', $card ) );
601
+
602
+ if( has_filter( 'edd_accepted_payment_' . $card . '_image' ) ) {
603
+
604
+ $image = apply_filters( 'edd_accepted_payment_' . $card . '_image', '' );
605
 
 
 
 
 
 
606
  } else {
607
+
608
+ $image = edd_locate_template( 'images' . DIRECTORY_SEPARATOR . 'icons' . DIRECTORY_SEPARATOR . $card . '.gif', false );
609
+ $content_dir = WP_CONTENT_DIR;
610
 
611
  if( function_exists( 'wp_normalize_path' ) ) {
612
+
613
  // Replaces backslashes with forward slashes for Windows systems
614
  $image = wp_normalize_path( $image );
615
  $content_dir = wp_normalize_path( $content_dir );
616
+
617
  }
618
+
619
  $image = str_replace( $content_dir, WP_CONTENT_URL, $image );
620
 
621
+ }
622
+
623
+ if( edd_is_ssl_enforced() || is_ssl() ) {
624
+
625
+ $image = edd_enforced_ssl_asset_filter( $image );
626
 
 
627
  }
628
+
629
+ echo '<img class="payment-icon" src="' . esc_url( $image ) . '"/>';
630
  }
631
+
632
  }
633
+
634
+ echo '</div>';
635
  }
636
  add_action( 'edd_payment_mode_top', 'edd_show_payment_icons' );
637
  add_action( 'edd_checkout_form_top', 'edd_show_payment_icons' );
651
  return; // Only show before a payment method has been selected if ajax is disabled
652
  }
653
 
654
+ if( ! edd_is_checkout() ) {
655
+ return;
656
+ }
657
+
658
  if ( edd_has_active_discounts() && edd_get_cart_total() ) :
659
 
660
  $color = edd_get_option( 'checkout_color', 'blue' );
665
  <p id="edd_show_discount" style="display:none;">
666
  <?php _e( 'Have a discount code?', 'edd' ); ?> <a href="#" class="edd_discount_link"><?php echo _x( 'Click to enter it', 'Entering a discount code', 'edd' ); ?></a>
667
  </p>
668
+ <p id="edd-discount-code-wrap" class="edd-cart-adjustment">
669
  <label class="edd-label" for="edd-discount">
670
  <?php _e( 'Discount', 'edd' ); ?>
671
  <img src="<?php echo EDD_PLUGIN_URL; ?>assets/images/loading.gif" id="edd-discount-loader" style="display:none;"/>
687
  * set in the EDD Settings.
688
  *
689
  * @since 1.3.2
 
690
  * @return void
691
  */
692
  function edd_terms_agreement() {
693
+ if ( edd_get_option( 'show_agree_to_terms', false ) ) {
694
+ $agree_text = edd_get_option( 'agree_text', '' );
695
+ $agree_label = edd_get_option( 'agree_label', __( 'Agree to Terms?', 'edd' ) );
696
  ?>
697
  <fieldset id="edd_terms_agreement">
698
  <div id="edd_terms" style="display:none;">
699
  <?php
700
  do_action( 'edd_before_terms' );
701
+ echo wpautop( stripslashes( $agree_text ) );
702
  do_action( 'edd_after_terms' );
703
  ?>
704
  </div>
706
  <a href="#" class="edd_terms_links"><?php _e( 'Show Terms', 'edd' ); ?></a>
707
  <a href="#" class="edd_terms_links" style="display:none;"><?php _e( 'Hide Terms', 'edd' ); ?></a>
708
  </div>
709
+ <label for="edd_agree_to_terms"><?php echo stripslashes( $agree_label ); ?></label>
710
  <input name="edd_agree_to_terms" class="required" type="checkbox" id="edd_agree_to_terms" value="1"/>
711
  </fieldset>
712
  <?php
760
  * Renders the Next button on the Checkout
761
  *
762
  * @since 1.2
 
763
  * @return string
764
  */
765
  function edd_checkout_button_next() {
766
+ $color = edd_get_option( 'checkout_color', 'blue' );
 
 
767
  $color = ( $color == 'inherit' ) ? '' : $color;
768
+ $style = edd_get_option( 'button_style', 'button' );
769
+ $purchase_page = edd_get_option( 'purchase_page', '0' );
770
 
771
  ob_start();
772
  ?>
773
  <input type="hidden" name="edd_action" value="gateway_select" />
774
+ <input type="hidden" name="page_id" value="<?php echo absint( $purchase_page ); ?>"/>
775
  <input type="submit" name="gateway_submit" id="edd_next_button" class="edd-submit <?php echo $color; ?> <?php echo $style; ?>" value="<?php _e( 'Next', 'edd' ); ?>"/>
776
  <?php
777
  return apply_filters( 'edd_checkout_button_next', ob_get_clean() );
781
  * Renders the Purchase button on the Checkout
782
  *
783
  * @since 1.2
 
784
  * @return string
785
  */
786
  function edd_checkout_button_purchase() {
787
+ $color = edd_get_option( 'checkout_color', 'blue' );
 
 
788
  $color = ( $color == 'inherit' ) ? '' : $color;
789
+ $style = edd_get_option( 'button_style', 'button' );
790
+ $label = edd_get_option( 'checkout_label', '' );
791
 
792
  if ( edd_get_cart_total() ) {
793
+ $complete_purchase = ! empty( $label ) ? $label : __( 'Purchase', 'edd' );
794
  } else {
795
+ $complete_purchase = ! empty( $label ) ? $label : __( 'Free Download', 'edd' );
796
  }
797
 
798
  ob_start();
807
  * the T&Cs text
808
  *
809
  * @since 1.0
 
810
  * @return void
811
  */
812
  function edd_agree_to_terms_js() {
813
+ if ( edd_get_option( 'show_agree_to_terms', false ) ) {
 
 
814
  ?>
815
  <script type="text/javascript">
816
  jQuery(document).ready(function($){
853
  * @return string $content Filtered content
854
  */
855
  function edd_filter_success_page_content( $content ) {
856
+ if ( isset( $_GET['payment-confirmation'] ) && edd_is_success_page() ) {
 
 
857
  if ( has_filter( 'edd_payment_confirm_' . $_GET['payment-confirmation'] ) ) {
858
  $content = apply_filters( 'edd_payment_confirm_' . $_GET['payment-confirmation'], $content );
859
  }
860
  }
861
+
862
  return $content;
863
  }
864
  add_filter( 'the_content', 'edd_filter_success_page_content' );
includes/class-edd-api.php CHANGED
@@ -10,7 +10,7 @@
10
  *
11
  * @package EDD
12
  * @subpackage Classes/API
13
- * @copyright Copyright (c) 2014, Pippin Williamson
14
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
15
  * @since 1.5
16
  */
@@ -48,7 +48,7 @@ class EDD_API {
48
  * @access private
49
  * @since 1.5
50
  */
51
- private $log_requests = true;
52
 
53
  /**
54
  * Is this a valid request?
@@ -140,7 +140,7 @@ class EDD_API {
140
  * @since 1.5
141
  * @author Daniel J Griffiths
142
  * @param array $vars Query vars
143
- * @return array $vars New query vars
144
  */
145
  public function query_vars( $vars ) {
146
  $vars[] = 'token';
@@ -193,7 +193,7 @@ class EDD_API {
193
  $secret = get_user_meta( $user, 'edd_user_secret_key', true );
194
  $public = urldecode( $wp_query->query_vars['key'] );
195
 
196
- if ( hash( 'md5', $secret . $public ) === $token )
197
  $this->is_valid_request = true;
198
  else
199
  $this->invalid_auth();
@@ -226,12 +226,18 @@ class EDD_API {
226
  return false;
227
  }
228
 
229
- $user = $wpdb->get_var( $wpdb->prepare( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'edd_user_public_key' AND meta_value = %s LIMIT 1", $key ) );
 
 
 
 
 
230
 
231
  if ( $user != NULL ) {
232
  $this->user_id = $user;
233
  return $user;
234
  }
 
235
  return false;
236
  }
237
 
@@ -245,6 +251,7 @@ class EDD_API {
245
  * @since 1.5
246
  */
247
  private function missing_auth() {
 
248
  $error['error'] = __( 'You must specify both a token and API key!', 'edd' );
249
 
250
  $this->data = $error;
@@ -261,6 +268,7 @@ class EDD_API {
261
  * @return void
262
  */
263
  private function invalid_auth() {
 
264
  $error['error'] = __( 'Your request could not be authenticated!', 'edd' );
265
 
266
  $this->data = $error;
@@ -278,6 +286,7 @@ class EDD_API {
278
  * @return void
279
  */
280
  private function invalid_key() {
 
281
  $error['error'] = __( 'Invalid API key!', 'edd' );
282
 
283
  $this->data = $error;
@@ -394,7 +403,7 @@ class EDD_API {
394
  ) );
395
 
396
  $query = isset( $wp_query->query_vars['edd-api'] ) ? $wp_query->query_vars['edd-api'] : null;
397
-
398
  // Make sure our query is valid
399
  if ( ! in_array( $query, $accepted ) ) {
400
  $error['error'] = __( 'Invalid query!', 'edd' );
@@ -484,74 +493,94 @@ class EDD_API {
484
  $startdate = strtotime( $args['startdate'] );
485
  $enddate = strtotime( $args['enddate'] );
486
  $dates['day_start'] = date( 'd', $startdate );
487
- $dates['day_end'] = date( 'd', $enddate );
488
- $dates['m_start'] = date( 'n', $startdate );
489
- $dates['m_end'] = date( 'n', $enddate );
490
- $dates['year'] = date( 'Y', $startdate );
491
  $dates['year_end'] = date( 'Y', $enddate );
492
  } else {
493
  // Modify dates based on predefined ranges
494
  switch ( $args['date'] ) :
495
 
496
  case 'this_month' :
497
- $dates['day'] = null;
498
- $dates['m_start'] = date( 'n', $current_time );
499
- $dates['m_end'] = date( 'n', $current_time );
500
- $dates['year'] = date( 'Y', $current_time );
501
  break;
502
 
503
  case 'last_month' :
504
- $dates['day'] = null;
505
  $dates['m_start'] = date( 'n', $current_time ) == 1 ? 12 : date( 'n', $current_time ) - 1;
506
- $dates['m_end'] = $dates['m_start'];
507
  $dates['year'] = date( 'n', $current_time ) == 1 ? date( 'Y', $current_time ) - 1 : date( 'Y', $current_time );
508
  break;
509
 
510
  case 'today' :
511
- $dates['day'] = date( 'd', $current_time );
512
- $dates['m_start'] = date( 'n', $current_time );
513
- $dates['m_end'] = date( 'n', $current_time );
514
- $dates['year'] = date( 'Y', $current_time );
515
  break;
516
 
517
  case 'yesterday' :
518
- $month = date( 'n', $current_time ) == 1 && date( 'd', $current_time ) == 1 ? 12 : date( 'n', $current_time );
519
- $days_in_month = cal_days_in_month( CAL_GREGORIAN, $month, date( 'Y', $current_time ) );
520
- $yesterday = date( 'd', $current_time ) == 1 ? $days_in_month : date( 'd', $current_time ) - 1;
521
- $dates['day'] = $yesterday;
522
- $dates['m_start'] = $month;
523
- $dates['m_end'] = $month;
524
- $dates['year'] = $month == 1 && date( 'd', $current_time ) == 1 ? date( 'Y', $current_time ) - 1 : date( 'Y', $current_time );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
  break;
526
 
527
  case 'this_quarter' :
528
  $month_now = date( 'n', $current_time );
529
 
530
- $dates['day'] = null;
531
 
532
  if ( $month_now <= 3 ) {
533
 
534
- $dates['m_start'] = 1;
535
- $dates['m_end'] = 3;
536
- $dates['year'] = date( 'Y', $current_time );
537
 
538
  } else if ( $month_now <= 6 ) {
539
 
540
- $dates['m_start'] = 4;
541
- $dates['m_end'] = 6;
542
- $dates['year'] = date( 'Y', $current_time );
543
 
544
  } else if ( $month_now <= 9 ) {
545
 
546
- $dates['m_start'] = 7;
547
- $dates['m_end'] = 9;
548
- $dates['year'] = date( 'Y', $current_time );
549
 
550
  } else {
551
 
552
- $dates['m_start'] = 10;
553
- $dates['m_end'] = 12;
554
- $dates['year'] = date( 'Y', $current_time );
555
 
556
  }
557
  break;
@@ -559,47 +588,47 @@ class EDD_API {
559
  case 'last_quarter' :
560
  $month_now = date( 'n', $current_time );
561
 
562
- $dates['day'] = null;
563
 
564
  if ( $month_now <= 3 ) {
565
 
566
- $dates['m_start'] = 10;
567
- $dates['m_end'] = 12;
568
- $dates['year'] = date( 'Y', $current_time ) - 1; // Previous year
569
 
570
  } else if ( $month_now <= 6 ) {
571
 
572
- $dates['m_start'] = 1;
573
- $dates['m_end'] = 3;
574
- $dates['year'] = date( 'Y', $current_time );
575
 
576
  } else if ( $month_now <= 9 ) {
577
 
578
- $dates['m_start'] = 4;
579
- $dates['m_end'] = 6;
580
- $dates['year'] = date( 'Y', $current_time );
581
 
582
  } else {
583
 
584
- $dates['m_start'] = 7;
585
- $dates['m_end'] = 9;
586
- $dates['year'] = date( 'Y', $current_time );
587
 
588
  }
589
  break;
590
 
591
  case 'this_year' :
592
- $dates['day'] = null;
593
- $dates['m_start'] = null;
594
- $dates['m_end'] = null;
595
- $dates['year'] = date( 'Y', $current_time );
596
  break;
597
 
598
  case 'last_year' :
599
- $dates['day'] = null;
600
- $dates['m_start'] = null;
601
- $dates['m_end'] = null;
602
- $dates['year'] = date( 'Y', $current_time ) - 1;
603
  break;
604
 
605
  endswitch;
@@ -629,69 +658,79 @@ class EDD_API {
629
  public function get_customers( $customer = null ) {
630
 
631
  $customers = array();
632
-
633
  if( ! user_can( $this->user_id, 'view_shop_sensitive_data' ) && ! $this->override ) {
634
  return $customers;
635
  }
636
 
637
- if ( $customer == null ) {
638
- global $wpdb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
639
 
640
- $paged = $this->get_paged();
641
- $per_page = $this->per_page();
642
- $offset = $per_page * ( $paged - 1 );
643
- $customer_list_query = $wpdb->get_col( "SELECT DISTINCT meta_value FROM $wpdb->postmeta where meta_key = '_edd_payment_user_email' ORDER BY meta_id DESC LIMIT $per_page OFFSET $offset" );
644
- $customer_count = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
645
 
646
- foreach ( $customer_list_query as $customer_email ) {
647
- $customer_info = get_user_by( 'email', $customer_email );
648
 
649
- if ( $customer_info ) {
650
  // Customer with registered account
651
- $customers['customers'][$customer_count]['info']['id'] = $customer_info->ID;
652
- $customers['customers'][$customer_count]['info']['username'] = $customer_info->user_login;
653
- $customers['customers'][$customer_count]['info']['display_name'] = $customer_info->display_name;
654
- $customers['customers'][$customer_count]['info']['first_name'] = $customer_info->user_firstname;
655
- $customers['customers'][$customer_count]['info']['last_name'] = $customer_info->user_lastname;
656
- $customers['customers'][$customer_count]['info']['email'] = $customer_info->user_email;
657
- } else {
658
- // Guest customer
659
- $customers['customers'][$customer_count]['info']['id'] = -1;
660
- $customers['customers'][$customer_count]['info']['username'] = __( 'Guest', 'edd' );
661
- $customers['customers'][$customer_count]['info']['display_name'] = __( 'Guest', 'edd' );
662
- $customers['customers'][$customer_count]['info']['first_name'] = __( 'Guest', 'edd' );
663
- $customers['customers'][$customer_count]['info']['last_name'] = __( 'Guest', 'edd' );
664
- $customers['customers'][$customer_count]['info']['email'] = $customer_email;
665
  }
666
 
667
- $customers['customers'][$customer_count]['stats']['total_purchases'] = edd_count_purchases_of_customer( $customer_email );
668
- $customers['customers'][$customer_count]['stats']['total_spent'] = edd_purchase_total_of_user( $customer_email );
669
- $customers['customers'][$customer_count]['stats']['total_downloads'] = edd_count_file_downloads_of_user( $customer_email );
670
 
671
  $customer_count++;
 
672
  }
 
 
 
 
 
 
673
  } else {
674
- if ( is_numeric( $customer ) ) {
675
- $customer_info = get_userdata( $customer );
676
- } else {
677
- $customer_info = get_user_by( 'email', $customer );
678
- }
679
 
680
- if ( $customer_info && edd_has_purchases( $customer_info->ID ) ) {
681
- $customers['customers'][0]['info']['id'] = $customer_info->ID;
682
- $customers['customers'][0]['info']['username'] = $customer_info->user_login;
683
- $customers['customers'][0]['info']['display_name'] = $customer_info->display_name;
684
- $customers['customers'][0]['info']['first_name'] = $customer_info->user_firstname;
685
- $customers['customers'][0]['info']['last_name'] = $customer_info->user_lastname;
686
- $customers['customers'][0]['info']['email'] = $customer_info->user_email;
687
-
688
- $customers['customers'][0]['stats']['total_purchases'] = edd_count_purchases_of_customer( $customer );
689
- $customers['customers'][0]['stats']['total_spent'] = edd_purchase_total_of_user( $customer );
690
- $customers['customers'][0]['stats']['total_downloads'] = edd_count_file_downloads_of_user( $customer );
691
- } else {
692
- $error['error'] = sprintf( __( 'Customer %s not found!', 'edd' ), $customer );
693
- return $error;
694
- }
695
  }
696
 
697
  return $customers;
@@ -709,6 +748,7 @@ class EDD_API {
709
  public function get_products( $product = null ) {
710
 
711
  $products = array();
 
712
 
713
  if ( $product == null ) {
714
  $products['products'] = array();
@@ -731,6 +771,7 @@ class EDD_API {
731
  $products['products'][$i]['info']['status'] = $product_info->post_status;
732
  $products['products'][$i]['info']['link'] = html_entity_decode( $product_info->guid );
733
  $products['products'][$i]['info']['content'] = $product_info->post_content;
 
734
  $products['products'][$i]['info']['thumbnail'] = wp_get_attachment_url( get_post_thumbnail_id( $product_info->ID ) );
735
  $products['products'][$i]['info']['category'] = get_the_terms( $product_info, 'download_category' );
736
  $products['products'][$i]['info']['tags'] = get_the_terms( $product_info, 'download_tag' );
@@ -833,8 +874,13 @@ class EDD_API {
833
  $dates = $this->get_dates( $args );
834
 
835
  $stats = array();
836
- $earnings = array();
837
- $sales = array();
 
 
 
 
 
838
 
839
  if( ! user_can( $this->user_id, 'view_shop_reports' ) && ! $this->override ) {
840
  return $stats;
@@ -880,19 +926,25 @@ class EDD_API {
880
  $i = $month_start;
881
  while ( $i <= $month_end ) :
882
 
883
- if( $i == $dates['m_start'] )
884
  $d = $dates['day_start'];
885
- else
886
  $d = 1;
 
887
 
888
- if( $i == $dates['m_end'] )
889
  $num_of_days = $dates['day_end'];
890
- else
891
  $num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
 
892
 
893
  while ( $d <= $num_of_days ) :
894
  $sale_count = edd_get_sales_by_date( $d, $i, $y );
895
- $sales['sales'][ date( 'Ymd', strtotime( $y . '/' . $i . '/' . $d ) ) ] += $sale_count;
 
 
 
 
896
  $total += $sale_count;
897
  $d++;
898
  endwhile;
@@ -961,6 +1013,9 @@ class EDD_API {
961
 
962
  // Loop through the years
963
  $y = $dates['year'];
 
 
 
964
  while( $y <= $dates['year_end'] ) :
965
 
966
  if( $dates['year'] == $dates['year_end'] ) {
@@ -985,14 +1040,19 @@ class EDD_API {
985
  else
986
  $d = 1;
987
 
988
- if( $i == $dates['m_end'] )
989
  $num_of_days = $dates['day_end'];
990
- else
991
  $num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
 
992
 
993
  while ( $d <= $num_of_days ) :
994
  $earnings_stat = edd_get_earnings_by_date( $d, $i, $y );
995
- $earnings['earnings'][ date( 'Ymd', strtotime( $y . '/' . $i . '/' . $d ) ) ] += $earnings_stat;
 
 
 
 
996
  $total += $earnings_stat;
997
  $d++;
998
  endwhile;
@@ -1095,17 +1155,18 @@ class EDD_API {
1095
  $user_info = edd_get_payment_meta_user_info( $payment->ID );
1096
  $cart_items = edd_get_payment_meta_cart_details( $payment->ID );
1097
 
1098
- $sales['sales'][ $i ]['ID'] = $payment->ID;
1099
- $sales['sales'][ $i ]['key'] = edd_get_payment_key( $payment->ID );
1100
- $sales['sales'][ $i ]['discount'] = isset( $user_info['discount'] ) && $user_info['discount'] != 'none' ? explode( ',', $user_info['discount'] ) : array();
1101
- $sales['sales'][ $i ]['subtotal'] = edd_get_payment_subtotal( $payment->ID );
1102
- $sales['sales'][ $i ]['tax'] = edd_get_payment_tax( $payment->ID );
1103
- $sales['sales'][ $i ]['fees'] = edd_get_payment_fees( $payment->ID );
1104
- $sales['sales'][ $i ]['total'] = edd_get_payment_amount( $payment->ID );
1105
- $sales['sales'][ $i ]['gateway'] = edd_get_payment_gateway( $payment->ID );
1106
- $sales['sales'][ $i ]['email'] = edd_get_payment_user_email( $payment->ID );
1107
- $sales['sales'][ $i ]['date'] = $payment->post_date;
1108
- $sales['sales'][ $i ]['products'] = array();
 
1109
 
1110
  $c = 0;
1111
 
@@ -1121,8 +1182,8 @@ class EDD_API {
1121
  $price = edd_get_download_final_price( $item_id, $user_info, null );
1122
  }
1123
 
 
1124
  if ( isset( $item['item_number'] ) && isset( $item['item_number']['options'] ) ) {
1125
- $price_name = '';
1126
  $price_options = $item['item_number']['options'];
1127
  if ( isset( $price_options['price_id'] ) ) {
1128
  $price_name = edd_get_price_option_name( $item['id'], $price_options['price_id'], $payment->ID );
@@ -1159,6 +1220,7 @@ class EDD_API {
1159
  if( ! user_can( $this->user_id, 'manage_shop_discounts' ) && ! $this->override ) {
1160
  return $discount_list;
1161
  }
 
1162
 
1163
  if ( empty( $discount ) ) {
1164
 
@@ -1169,6 +1231,11 @@ class EDD_API {
1169
  $discounts = edd_get_discounts( array( 'posts_per_page' => $per_page, 'paged' => $paged ) );
1170
  $count = 0;
1171
 
 
 
 
 
 
1172
  foreach ( $discounts as $discount ) {
1173
 
1174
  $discount_list['discounts'][$count]['ID'] = $discount->ID;
@@ -1345,13 +1412,10 @@ class EDD_API {
1345
  * @access public
1346
  * @author Daniel J Griffiths
1347
  * @since 1.5
1348
- * @global $edd_options Array of all the EDD Options
1349
  * @param object $user Current user info
1350
  * @return void
1351
  */
1352
  function user_key_field( $user ) {
1353
- global $edd_options;
1354
-
1355
  if ( ( edd_get_option( 'api_allow_user_keys', false ) || current_user_can( 'manage_shop_settings' ) ) && current_user_can( 'edit_user', $user->ID ) ) {
1356
  $user = get_userdata( $user->ID );
1357
  ?>
@@ -1363,8 +1427,8 @@ class EDD_API {
1363
  </th>
1364
  <td>
1365
  <?php if ( empty( $user->edd_user_public_key ) ) { ?>
1366
- <input name="edd_set_api_key" type="checkbox" id="edd_set_api_key" value="0" />
1367
- <span class="description"><?php _e( 'Generate API Key', 'edd' ); ?></span>
1368
  <?php } else { ?>
1369
  <strong><?php _e( 'Public key:', 'edd' ); ?>&nbsp;</strong><span id="publickey"><?php echo $user->edd_user_public_key; ?></span><br/>
1370
  <strong><?php _e( 'Secret key:', 'edd' ); ?>&nbsp;</strong><span id="privatekey"><?php echo $user->edd_user_secret_key; ?></span><br/>
@@ -1389,6 +1453,12 @@ class EDD_API {
1389
  */
1390
  public function process_api_key( $args ) {
1391
 
 
 
 
 
 
 
1392
  if( is_numeric( $args['user_id'] ) ) {
1393
  $user_id = isset( $args['user_id'] ) ? absint( $args['user_id'] ) : get_current_user_id();
1394
  } else {
@@ -1398,9 +1468,9 @@ class EDD_API {
1398
  $process = isset( $args['edd_api_process'] ) ? strtolower( $args['edd_api_process'] ) : false;
1399
 
1400
  if( $user_id == get_current_user_id() && ! edd_get_option( 'allow_user_api_keys' ) && ! current_user_can( 'manage_shop_settings' ) ) {
1401
- wp_die( sprintf( __( 'You do not have permission to %s API keys for this user', 'edd' ), $process ) );
1402
  } elseif( ! current_user_can( 'manage_shop_settings' ) ) {
1403
- wp_die( sprintf( __( 'You do not have permission to %s API keys for this user', 'edd' ), $process ) );
1404
  }
1405
 
1406
  switch( $process ) {
@@ -1409,7 +1479,7 @@ class EDD_API {
1409
  delete_transient( 'edd-total-api-keys' );
1410
  wp_redirect( add_query_arg( 'edd-message', 'api-key-generated', 'edit.php?post_type=download&page=edd-tools&tab=api_keys' ) ); exit();
1411
  } else {
1412
- wp_redirect( add_query_arg( 'edd-message', 'api-key-exists', 'edit.php?post_type=download&page=edd-tools&tab=api_keys' ) ); exit();
1413
  }
1414
  break;
1415
  case 'regenerate':
@@ -1432,12 +1502,22 @@ class EDD_API {
1432
  *
1433
  * @access public
1434
  * @since 2.0.0
1435
- * @param array $args
1436
- * @return string
 
1437
  */
1438
- public function generate_api_key( $user_id, $regenerate = false ) {
 
 
 
 
 
1439
  $user = get_userdata( $user_id );
1440
 
 
 
 
 
1441
  if ( empty( $user->edd_user_public_key ) ) {
1442
  update_user_meta( $user_id, 'edd_user_public_key', $this->generate_public_key( $user->user_email ) );
1443
  update_user_meta( $user_id, 'edd_user_secret_key', $this->generate_private_key( $user->ID ) );
@@ -1457,13 +1537,23 @@ class EDD_API {
1457
  *
1458
  * @access public
1459
  * @since 2.0.0
1460
- * @param int $args
1461
  * @return string
1462
  */
1463
- public function revoke_api_key( $user_id ) {
 
 
 
 
 
1464
  $user = get_userdata( $user_id );
1465
 
 
 
 
 
1466
  if ( ! empty( $user->edd_user_public_key ) ) {
 
1467
  delete_user_meta( $user_id, 'edd_user_public_key' );
1468
  delete_user_meta( $user_id, 'edd_user_secret_key' );
1469
  } else {
@@ -1494,8 +1584,7 @@ class EDD_API {
1494
  update_user_meta( $user_id, 'edd_user_public_key', $this->generate_public_key( $user->user_email ) );
1495
  update_user_meta( $user_id, 'edd_user_secret_key', $this->generate_private_key( $user->ID ) );
1496
  } else {
1497
- delete_user_meta( $user_id, 'edd_user_public_key' );
1498
- delete_user_meta( $user_id, 'edd_user_secret_key' );
1499
  }
1500
  }
1501
  }
@@ -1551,7 +1640,8 @@ class EDD_API {
1551
  private function get_default_sales_stats() {
1552
 
1553
  // Default sales return
1554
-
 
1555
  $sales['sales']['current_month'] = $this->stats->get_sales( 0, 'this_month' );
1556
  $sales['sales']['last_month'] = $this->stats->get_sales( 0, 'last_month' );
1557
  $sales['sales']['totals'] = edd_get_total_sales();
@@ -1569,7 +1659,8 @@ class EDD_API {
1569
  private function get_default_earnings_stats() {
1570
 
1571
  // Default earnings return
1572
-
 
1573
  $earnings['earnings']['current_month'] = $this->stats->get_earnings( 0, 'this_month' );
1574
  $earnings['earnings']['last_month'] = $this->stats->get_earnings( 0, 'last_month' );
1575
  $earnings['earnings']['totals'] = edd_get_total_earnings();
10
  *
11
  * @package EDD
12
  * @subpackage Classes/API
13
+ * @copyright Copyright (c) 2015, Pippin Williamson
14
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
15
  * @since 1.5
16
  */
48
  * @access private
49
  * @since 1.5
50
  */
51
+ public $log_requests = true;
52
 
53
  /**
54
  * Is this a valid request?
140
  * @since 1.5
141
  * @author Daniel J Griffiths
142
  * @param array $vars Query vars
143
+ * @return string[] $vars New query vars
144
  */
145
  public function query_vars( $vars ) {
146
  $vars[] = 'token';
193
  $secret = get_user_meta( $user, 'edd_user_secret_key', true );
194
  $public = urldecode( $wp_query->query_vars['key'] );
195
 
196
+ if ( hash_equals( md5( $secret . $public ), $token ) )
197
  $this->is_valid_request = true;
198
  else
199
  $this->invalid_auth();
226
  return false;
227
  }
228
 
229
+ $user = get_transient( md5( 'edd_api_user_' . $key ) );
230
+
231
+ if ( false === $user ) {
232
+ $user = $wpdb->get_var( $wpdb->prepare( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'edd_user_public_key' AND meta_value = %s LIMIT 1", $key ) );
233
+ set_transient( md5( 'edd_api_user_' . $key ) , $user, DAY_IN_SECONDS );
234
+ }
235
 
236
  if ( $user != NULL ) {
237
  $this->user_id = $user;
238
  return $user;
239
  }
240
+
241
  return false;
242
  }
243
 
251
  * @since 1.5
252
  */
253
  private function missing_auth() {
254
+ $error = array();
255
  $error['error'] = __( 'You must specify both a token and API key!', 'edd' );
256
 
257
  $this->data = $error;
268
  * @return void
269
  */
270
  private function invalid_auth() {
271
+ $error = array();
272
  $error['error'] = __( 'Your request could not be authenticated!', 'edd' );
273
 
274
  $this->data = $error;
286
  * @return void
287
  */
288
  private function invalid_key() {
289
+ $error = array();
290
  $error['error'] = __( 'Invalid API key!', 'edd' );
291
 
292
  $this->data = $error;
403
  ) );
404
 
405
  $query = isset( $wp_query->query_vars['edd-api'] ) ? $wp_query->query_vars['edd-api'] : null;
406
+ $error = array();
407
  // Make sure our query is valid
408
  if ( ! in_array( $query, $accepted ) ) {
409
  $error['error'] = __( 'Invalid query!', 'edd' );
493
  $startdate = strtotime( $args['startdate'] );
494
  $enddate = strtotime( $args['enddate'] );
495
  $dates['day_start'] = date( 'd', $startdate );
496
+ $dates['day_end'] = date( 'd', $enddate );
497
+ $dates['m_start'] = date( 'n', $startdate );
498
+ $dates['m_end'] = date( 'n', $enddate );
499
+ $dates['year'] = date( 'Y', $startdate );
500
  $dates['year_end'] = date( 'Y', $enddate );
501
  } else {
502
  // Modify dates based on predefined ranges
503
  switch ( $args['date'] ) :
504
 
505
  case 'this_month' :
506
+ $dates['day'] = null;
507
+ $dates['m_start'] = date( 'n', $current_time );
508
+ $dates['m_end'] = date( 'n', $current_time );
509
+ $dates['year'] = date( 'Y', $current_time );
510
  break;
511
 
512
  case 'last_month' :
513
+ $dates['day'] = null;
514
  $dates['m_start'] = date( 'n', $current_time ) == 1 ? 12 : date( 'n', $current_time ) - 1;
515
+ $dates['m_end'] = $dates['m_start'];
516
  $dates['year'] = date( 'n', $current_time ) == 1 ? date( 'Y', $current_time ) - 1 : date( 'Y', $current_time );
517
  break;
518
 
519
  case 'today' :
520
+ $dates['day'] = date( 'd', $current_time );
521
+ $dates['m_start'] = date( 'n', $current_time );
522
+ $dates['m_end'] = date( 'n', $current_time );
523
+ $dates['year'] = date( 'Y', $current_time );
524
  break;
525
 
526
  case 'yesterday' :
527
+
528
+ $year = date( 'Y', $current_time );
529
+ $month = date( 'n', $current_time );
530
+ $day = date( 'd', $current_time );
531
+
532
+ if ( $month == 1 && $day == 1 ) {
533
+
534
+ $year -= 1;
535
+ $month = 12;
536
+ $day = cal_days_in_month( CAL_GREGORIAN, $month, $year );
537
+
538
+ } elseif ( $month > 1 && $day == 1 ) {
539
+
540
+ $month -= 1;
541
+ $day = cal_days_in_month( CAL_GREGORIAN, $month, $year );
542
+
543
+ } else {
544
+
545
+ $day -= 1;
546
+
547
+ }
548
+
549
+ $dates['day'] = $day;
550
+ $dates['m_start'] = $month;
551
+ $dates['m_end'] = $month;
552
+ $dates['year'] = $year;
553
+
554
  break;
555
 
556
  case 'this_quarter' :
557
  $month_now = date( 'n', $current_time );
558
 
559
+ $dates['day'] = null;
560
 
561
  if ( $month_now <= 3 ) {
562
 
563
+ $dates['m_start'] = 1;
564
+ $dates['m_end'] = 3;
565
+ $dates['year'] = date( 'Y', $current_time );
566
 
567
  } else if ( $month_now <= 6 ) {
568
 
569
+ $dates['m_start'] = 4;
570
+ $dates['m_end'] = 6;
571
+ $dates['year'] = date( 'Y', $current_time );
572
 
573
  } else if ( $month_now <= 9 ) {
574
 
575
+ $dates['m_start'] = 7;
576
+ $dates['m_end'] = 9;
577
+ $dates['year'] = date( 'Y', $current_time );
578
 
579
  } else {
580
 
581
+ $dates['m_start'] = 10;
582
+ $dates['m_end'] = 12;
583
+ $dates['year'] = date( 'Y', $current_time );
584
 
585
  }
586
  break;
588
  case 'last_quarter' :
589
  $month_now = date( 'n', $current_time );
590
 
591
+ $dates['day'] = null;
592
 
593
  if ( $month_now <= 3 ) {
594
 
595
+ $dates['m_start'] = 10;
596
+ $dates['m_end'] = 12;
597
+ $dates['year'] = date( 'Y', $current_time ) - 1; // Previous year
598
 
599
  } else if ( $month_now <= 6 ) {
600
 
601
+ $dates['m_start'] = 1;
602
+ $dates['m_end'] = 3;
603
+ $dates['year'] = date( 'Y', $current_time );
604
 
605
  } else if ( $month_now <= 9 ) {
606
 
607
+ $dates['m_start'] = 4;
608
+ $dates['m_end'] = 6;
609
+ $dates['year'] = date( 'Y', $current_time );
610
 
611
  } else {
612
 
613
+ $dates['m_start'] = 7;
614
+ $dates['m_end'] = 9;
615
+ $dates['year'] = date( 'Y', $current_time );
616
 
617
  }
618
  break;
619
 
620
  case 'this_year' :
621
+ $dates['day'] = null;
622
+ $dates['m_start'] = null;
623
+ $dates['m_end'] = null;
624
+ $dates['year'] = date( 'Y', $current_time );
625
  break;
626
 
627
  case 'last_year' :
628
+ $dates['day'] = null;
629
+ $dates['m_start'] = null;
630
+ $dates['m_end'] = null;
631
+ $dates['year'] = date( 'Y', $current_time ) - 1;
632
  break;
633
 
634
  endswitch;
658
  public function get_customers( $customer = null ) {
659
 
660
  $customers = array();
661
+ $error = array();
662
  if( ! user_can( $this->user_id, 'view_shop_sensitive_data' ) && ! $this->override ) {
663
  return $customers;
664
  }
665
 
666
+ global $wpdb;
667
+
668
+ $paged = $this->get_paged();
669
+ $per_page = $this->per_page();
670
+ $offset = $per_page * ( $paged - 1 );
671
+
672
+ if( is_numeric( $customer ) ) {
673
+ $field = 'id';
674
+ } else {
675
+ $field = 'email';
676
+ }
677
+
678
+ $customer_query = EDD()->customers->get_customers( array( 'number' => $per_page, 'offset' => $offset, $field => $customer ) );
679
+ $customer_count = 0;
680
+
681
+ if( $customer_query ) {
682
+
683
+ foreach ( $customer_query as $customer_obj ) {
684
 
685
+ $names = explode( ' ', $customer_obj->name );
686
+ $first_name = ! empty( $names[0] ) ? $names[0] : '';
687
+ $last_name = '';
688
+ if( ! empty( $names[1] ) ) {
689
+ unset( $names[0] );
690
+ $last_name = implode( ' ', $names );
691
+ }
692
+
693
+ $customers['customers'][$customer_count]['info']['id'] = '';
694
+ $customers['customers'][$customer_count]['info']['user_id'] = '';
695
+ $customers['customers'][$customer_count]['info']['username'] = '';
696
+ $customers['customers'][$customer_count]['info']['display_name'] = '';
697
+ $customers['customers'][$customer_count]['info']['customer_id'] = $customer_obj->id;
698
+ $customers['customers'][$customer_count]['info']['first_name'] = $first_name;
699
+ $customers['customers'][$customer_count]['info']['last_name'] = $last_name;
700
+ $customers['customers'][$customer_count]['info']['email'] = $customer_obj->email;
701
+
702
+ if ( ! empty( $customer_obj->user_id ) ) {
703
 
704
+ $user_data = get_userdata( $customer_obj->user_id );
 
705
 
 
706
  // Customer with registered account
707
+
708
+ // id is going to get deprecated in the future, user user_id or customer_id instead
709
+ $customers['customers'][$customer_count]['info']['id'] = $customer_obj->user_id;
710
+ $customers['customers'][$customer_count]['info']['user_id'] = $customer_obj->user_id;
711
+ $customers['customers'][$customer_count]['info']['username'] = $user_data->user_login;
712
+ $customers['customers'][$customer_count]['info']['display_name'] = $user_data->display_name;
713
+
 
 
 
 
 
 
 
714
  }
715
 
716
+ $customers['customers'][$customer_count]['stats']['total_purchases'] = $customer_obj->purchase_count;
717
+ $customers['customers'][$customer_count]['stats']['total_spent'] = $customer_obj->purchase_value;
718
+ $customers['customers'][$customer_count]['stats']['total_downloads'] = edd_count_file_downloads_of_user( $customer_obj->email );
719
 
720
  $customer_count++;
721
+
722
  }
723
+
724
+ } elseif( $customer ) {
725
+
726
+ $error['error'] = sprintf( __( 'Customer %s not found!', 'edd' ), $customer );
727
+ return $error;
728
+
729
  } else {
 
 
 
 
 
730
 
731
+ $error['error'] = __( 'No customers found!', 'edd' );
732
+ return $error;
733
+
 
 
 
 
 
 
 
 
 
 
 
 
734
  }
735
 
736
  return $customers;
748
  public function get_products( $product = null ) {
749
 
750
  $products = array();
751
+ $error = array();
752
 
753
  if ( $product == null ) {
754
  $products['products'] = array();
771
  $products['products'][$i]['info']['status'] = $product_info->post_status;
772
  $products['products'][$i]['info']['link'] = html_entity_decode( $product_info->guid );
773
  $products['products'][$i]['info']['content'] = $product_info->post_content;
774
+ $products['products'][$i]['info']['excerpt'] = $product_info->post_excerpt;
775
  $products['products'][$i]['info']['thumbnail'] = wp_get_attachment_url( get_post_thumbnail_id( $product_info->ID ) );
776
  $products['products'][$i]['info']['category'] = get_the_terms( $product_info, 'download_category' );
777
  $products['products'][$i]['info']['tags'] = get_the_terms( $product_info, 'download_tag' );
874
  $dates = $this->get_dates( $args );
875
 
876
  $stats = array();
877
+ $earnings = array(
878
+ 'earnings' => array()
879
+ );
880
+ $sales = array(
881
+ 'sales' => array()
882
+ );
883
+ $error = array();
884
 
885
  if( ! user_can( $this->user_id, 'view_shop_reports' ) && ! $this->override ) {
886
  return $stats;
926
  $i = $month_start;
927
  while ( $i <= $month_end ) :
928
 
929
+ if( $i == $dates['m_start'] ) {
930
  $d = $dates['day_start'];
931
+ } else {
932
  $d = 1;
933
+ }
934
 
935
+ if( $i == $dates['m_end'] ) {
936
  $num_of_days = $dates['day_end'];
937
+ } else {
938
  $num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
939
+ }
940
 
941
  while ( $d <= $num_of_days ) :
942
  $sale_count = edd_get_sales_by_date( $d, $i, $y );
943
+ $date_key = date( 'Ymd', strtotime( $y . '/' . $i . '/' . $d ) );
944
+ if ( ! isset( $sales['sales'][ $date_key ] ) ) {
945
+ $sales['sales'][ $date_key ] = 0;
946
+ }
947
+ $sales['sales'][ $date_key ] += $sale_count;
948
  $total += $sale_count;
949
  $d++;
950
  endwhile;
1013
 
1014
  // Loop through the years
1015
  $y = $dates['year'];
1016
+ if ( ! isset( $earnings['earnings'] ) ) {
1017
+ $earnings['earnings'] = array();
1018
+ }
1019
  while( $y <= $dates['year_end'] ) :
1020
 
1021
  if( $dates['year'] == $dates['year_end'] ) {
1040
  else
1041
  $d = 1;
1042
 
1043
+ if( $i == $dates['m_end'] ) {
1044
  $num_of_days = $dates['day_end'];
1045
+ } else {
1046
  $num_of_days = cal_days_in_month( CAL_GREGORIAN, $i, $y );
1047
+ }
1048
 
1049
  while ( $d <= $num_of_days ) :
1050
  $earnings_stat = edd_get_earnings_by_date( $d, $i, $y );
1051
+ $date_key = date( 'Ymd', strtotime( $y . '/' . $i . '/' . $d ) );
1052
+ if ( ! isset( $earnings['earnings'][ $date_key ] ) ) {
1053
+ $earnings['earnings'][ $date_key ] = 0;
1054
+ }
1055
+ $earnings['earnings'][ $date_key ] += $earnings_stat;
1056
  $total += $earnings_stat;
1057
  $d++;
1058
  endwhile;
1155
  $user_info = edd_get_payment_meta_user_info( $payment->ID );
1156
  $cart_items = edd_get_payment_meta_cart_details( $payment->ID );
1157
 
1158
+ $sales['sales'][ $i ]['ID'] = edd_get_payment_number( $payment->ID );
1159
+ $sales['sales'][ $i ]['transaction_id'] = edd_get_payment_transaction_id( $payment->ID );
1160
+ $sales['sales'][ $i ]['key'] = edd_get_payment_key( $payment->ID );
1161
+ $sales['sales'][ $i ]['discount'] = isset( $user_info['discount'] ) && $user_info['discount'] != 'none' ? explode( ',', $user_info['discount'] ) : array();
1162
+ $sales['sales'][ $i ]['subtotal'] = edd_get_payment_subtotal( $payment->ID );
1163
+ $sales['sales'][ $i ]['tax'] = edd_get_payment_tax( $payment->ID );
1164
+ $sales['sales'][ $i ]['fees'] = edd_get_payment_fees( $payment->ID );
1165
+ $sales['sales'][ $i ]['total'] = edd_get_payment_amount( $payment->ID );
1166
+ $sales['sales'][ $i ]['gateway'] = edd_get_payment_gateway( $payment->ID );
1167
+ $sales['sales'][ $i ]['email'] = edd_get_payment_user_email( $payment->ID );
1168
+ $sales['sales'][ $i ]['date'] = $payment->post_date;
1169
+ $sales['sales'][ $i ]['products'] = array();
1170
 
1171
  $c = 0;
1172
 
1182
  $price = edd_get_download_final_price( $item_id, $user_info, null );
1183
  }
1184
 
1185
+ $price_name = '';
1186
  if ( isset( $item['item_number'] ) && isset( $item['item_number']['options'] ) ) {
 
1187
  $price_options = $item['item_number']['options'];
1188
  if ( isset( $price_options['price_id'] ) ) {
1189
  $price_name = edd_get_price_option_name( $item['id'], $price_options['price_id'], $payment->ID );
1220
  if( ! user_can( $this->user_id, 'manage_shop_discounts' ) && ! $this->override ) {
1221
  return $discount_list;
1222
  }
1223
+ $error = array();
1224
 
1225
  if ( empty( $discount ) ) {
1226
 
1231
  $discounts = edd_get_discounts( array( 'posts_per_page' => $per_page, 'paged' => $paged ) );
1232
  $count = 0;
1233
 
1234
+ if ( empty( $discounts ) ) {
1235
+ $error['error'] = __( 'No discounts found!', 'edd' );
1236
+ return $error;
1237
+ }
1238
+
1239
  foreach ( $discounts as $discount ) {
1240
 
1241
  $discount_list['discounts'][$count]['ID'] = $discount->ID;
1412
  * @access public
1413
  * @author Daniel J Griffiths
1414
  * @since 1.5
 
1415
  * @param object $user Current user info
1416
  * @return void
1417
  */
1418
  function user_key_field( $user ) {
 
 
1419
  if ( ( edd_get_option( 'api_allow_user_keys', false ) || current_user_can( 'manage_shop_settings' ) ) && current_user_can( 'edit_user', $user->ID ) ) {
1420
  $user = get_userdata( $user->ID );
1421
  ?>
1427
  </th>
1428
  <td>
1429
  <?php if ( empty( $user->edd_user_public_key ) ) { ?>
1430
+ <input name="edd_set_api_key" type="checkbox" id="edd_set_api_key" value="0" />
1431
+ <span class="description"><?php _e( 'Generate API Key', 'edd' ); ?></span>
1432
  <?php } else { ?>
1433
  <strong><?php _e( 'Public key:', 'edd' ); ?>&nbsp;</strong><span id="publickey"><?php echo $user->edd_user_public_key; ?></span><br/>
1434
  <strong><?php _e( 'Secret key:', 'edd' ); ?>&nbsp;</strong><span id="privatekey"><?php echo $user->edd_user_secret_key; ?></span><br/>
1453
  */
1454
  public function process_api_key( $args ) {
1455
 
1456
+ if( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'edd-api-nonce' ) ) {
1457
+
1458
+ wp_die( __( 'Nonce verification failed', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
1459
+
1460
+ }
1461
+
1462
  if( is_numeric( $args['user_id'] ) ) {
1463
  $user_id = isset( $args['user_id'] ) ? absint( $args['user_id'] ) : get_current_user_id();
1464
  } else {
1468
  $process = isset( $args['edd_api_process'] ) ? strtolower( $args['edd_api_process'] ) : false;
1469
 
1470
  if( $user_id == get_current_user_id() && ! edd_get_option( 'allow_user_api_keys' ) && ! current_user_can( 'manage_shop_settings' ) ) {
1471
+ wp_die( sprintf( __( 'You do not have permission to %s API keys for this user', 'edd' ), $process ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
1472
  } elseif( ! current_user_can( 'manage_shop_settings' ) ) {
1473
+ wp_die( sprintf( __( 'You do not have permission to %s API keys for this user', 'edd' ), $process ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
1474
  }
1475
 
1476
  switch( $process ) {
1479
  delete_transient( 'edd-total-api-keys' );
1480
  wp_redirect( add_query_arg( 'edd-message', 'api-key-generated', 'edit.php?post_type=download&page=edd-tools&tab=api_keys' ) ); exit();
1481
  } else {
1482
+ wp_redirect( add_query_arg( 'edd-message', 'api-key-failed', 'edit.php?post_type=download&page=edd-tools&tab=api_keys' ) ); exit();
1483
  }
1484
  break;
1485
  case 'regenerate':
1502
  *
1503
  * @access public
1504
  * @since 2.0.0
1505
+ * @param int $user_id User ID the key is being generated for
1506
+ * @param boolean $regenerate Regenerate the key for the user
1507
+ * @return boolean True if (re)generated succesfully, false otherwise.
1508
  */
1509
+ public function generate_api_key( $user_id = 0, $regenerate = false ) {
1510
+
1511
+ if( empty( $user_id ) ) {
1512
+ return false;
1513
+ }
1514
+
1515
  $user = get_userdata( $user_id );
1516
 
1517
+ if( ! $user ) {
1518
+ return false;
1519
+ }
1520
+
1521
  if ( empty( $user->edd_user_public_key ) ) {
1522
  update_user_meta( $user_id, 'edd_user_public_key', $this->generate_public_key( $user->user_email ) );
1523
  update_user_meta( $user_id, 'edd_user_secret_key', $this->generate_private_key( $user->ID ) );
1537
  *
1538
  * @access public
1539
  * @since 2.0.0
1540
+ * @param int $user_id User ID of user to revoke key for
1541
  * @return string
1542
  */
1543
+ public function revoke_api_key( $user_id = 0 ) {
1544
+
1545
+ if( empty( $user_id ) ) {
1546
+ return false;
1547
+ }
1548
+
1549
  $user = get_userdata( $user_id );
1550
 
1551
+ if( ! $user ) {
1552
+ return false;
1553
+ }
1554
+
1555
  if ( ! empty( $user->edd_user_public_key ) ) {
1556
+ delete_transient( md5( 'edd_api_user_' . $user->edd_user_public_key ) );
1557
  delete_user_meta( $user_id, 'edd_user_public_key' );
1558
  delete_user_meta( $user_id, 'edd_user_secret_key' );
1559
  } else {
1584
  update_user_meta( $user_id, 'edd_user_public_key', $this->generate_public_key( $user->user_email ) );
1585
  update_user_meta( $user_id, 'edd_user_secret_key', $this->generate_private_key( $user->ID ) );
1586
  } else {
1587
+ $this->revoke_api_key( $user_id );
 
1588
  }
1589
  }
1590
  }
1640
  private function get_default_sales_stats() {
1641
 
1642
  // Default sales return
1643
+ $sales = array();
1644
+ $sales['sales']['today'] = $this->stats->get_sales( 0, 'today' );
1645
  $sales['sales']['current_month'] = $this->stats->get_sales( 0, 'this_month' );
1646
  $sales['sales']['last_month'] = $this->stats->get_sales( 0, 'last_month' );
1647
  $sales['sales']['totals'] = edd_get_total_sales();
1659
  private function get_default_earnings_stats() {
1660
 
1661
  // Default earnings return
1662
+ $earnings = array();
1663
+ $earnings['earnings']['today'] = $this->stats->get_earnings( 0, 'today' );
1664
  $earnings['earnings']['current_month'] = $this->stats->get_earnings( 0, 'this_month' );
1665
  $earnings['earnings']['last_month'] = $this->stats->get_earnings( 0, 'last_month' );
1666
  $earnings['earnings']['totals'] = edd_get_total_earnings();
includes/class-edd-cache-helper.php CHANGED
@@ -1,13 +1,14 @@
1
  <?php
2
 
3
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
4
 
5
  /**
6
  * Cache helper
7
  *
8
  * @package EDD
9
  * @subpackage Classes/Cache Helper
10
- * @copyright Copyright (c) 2014, Pippin Williamson
11
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
12
  * @since 1.7
13
  */
@@ -18,7 +19,7 @@ class EDD_Cache_Helper {
18
  */
19
  public function __construct() {
20
 
21
- add_action( 'init', array( $this, 'init' ) );
22
  add_action( 'admin_notices', array( $this, 'notices' ) );
23
  }
24
 
@@ -32,20 +33,21 @@ class EDD_Cache_Helper {
32
 
33
  if ( false === ( $page_uris = get_transient( 'edd_cache_excluded_uris' ) ) ) {
34
 
35
- global $edd_options;
36
-
37
- if( empty( $edd_options['purchase_page'] ) | empty( $edd_options['success_page'] ) )
38
  return;
 
39
 
40
  $page_uris = array();
41
 
42
  // Exclude querystring when using page ID
43
- $page_uris[] = 'p=' . $edd_options['purchase_page'];
44
- $page_uris[] = 'p=' . $edd_options['success_page'];
45
 
46
  // Exclude permalinks
47
- $checkout_page = get_post( $edd_options['purchase_page'] );
48
- $success_page = get_post( $edd_options['success_page'] );
49
 
50
  if ( ! is_null( $checkout_page ) )
51
  $page_uris[] = '/' . $checkout_page->post_name;
@@ -63,6 +65,22 @@ class EDD_Cache_Helper {
63
  }
64
  }
65
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
 
68
  /**
@@ -103,6 +121,26 @@ class EDD_Cache_Helper {
103
  }
104
 
105
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  }
107
 
108
- new EDD_Cache_Helper();
1
  <?php
2
 
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
 
6
  /**
7
  * Cache helper
8
  *
9
  * @package EDD
10
  * @subpackage Classes/Cache Helper
11
+ * @copyright Copyright (c) 2015, Pippin Williamson
12
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
13
  * @since 1.7
14
  */
19
  */
20
  public function __construct() {
21
 
22
+ add_action( 'init', array( $this, 'init' ), 0 );
23
  add_action( 'admin_notices', array( $this, 'notices' ) );
24
  }
25
 
33
 
34
  if ( false === ( $page_uris = get_transient( 'edd_cache_excluded_uris' ) ) ) {
35
 
36
+ $purchase_page = edd_get_option( 'purchase_page', '' );
37
+ $success_page = edd_get_option( 'success_page', '' );
38
+ if ( empty( $purchase_page ) || empty( $success_page ) ) {
39
  return;
40
+ }
41
 
42
  $page_uris = array();
43
 
44
  // Exclude querystring when using page ID
45
+ $page_uris[] = 'p=' . $purchase_page;
46
+ $page_uris[] = 'p=' . $success_page;
47
 
48
  // Exclude permalinks
49
+ $checkout_page = get_post( $purchase_page );
50
+ $success_page = get_post( $success_page );
51
 
52
  if ( ! is_null( $checkout_page ) )
53
  $page_uris[] = '/' . $checkout_page->post_name;
65
  }
66
  }
67
  }
68
+
69
+ if( function_exists( 'wp_suspend_cache_addition' ) ) {
70
+
71
+ add_action('edd_pre_update_discount', array( $this, 'w3tc_suspend_cache_addition_pre' ) );
72
+ add_action('edd_pre_insert_discount', array( $this, 'w3tc_suspend_cache_addition_pre' ) );
73
+ add_action('edd_pre_delete_discount', array( $this, 'w3tc_suspend_cache_addition_pre' ) );
74
+ add_action('edd_pre_update_discount_status', array( $this, 'w3tc_suspend_cache_addition_pre' ) );
75
+ add_action('edd_pre_remove_cart_discount', array( $this, 'w3tc_suspend_cache_addition_pre' ) );
76
+
77
+ add_action('edd_post_update_discount', array( $this, 'w3tc_suspend_cache_addition_post' ) );
78
+ add_action('edd_post_insert_discount', array( $this, 'w3tc_suspend_cache_addition_post' ) );
79
+ add_action('edd_post_delete_discount', array( $this, 'w3tc_suspend_cache_addition_post' ) );
80
+ add_action('edd_post_update_discount_status', array( $this, 'w3tc_suspend_cache_addition_post' ) );
81
+ add_action('edd_post_remove_cart_discount', array( $this, 'w3tc_suspend_cache_addition_post' ) );
82
+
83
+ }
84
  }
85
 
86
  /**
121
  }
122
 
123
  }
124
+
125
+ /**
126
+ * Prevents W3TC from adding to the cache prior to modifying data
127
+ *
128
+ * @access public
129
+ * @return void
130
+ */
131
+ function w3tc_suspend_cache_addition_pre() {
132
+ wp_suspend_cache_addition(true);
133
+ }
134
+
135
+ /**
136
+ * Prevents W3TC from adding to the cache after modifying data
137
+ *
138
+ * @access public
139
+ * @return void
140
+ */
141
+ function w3tc_suspend_cache_addition_post() {
142
+ wp_suspend_cache_addition();
143
+ }
144
  }
145
 
146
+ new EDD_Cache_Helper();
includes/class-edd-cli.php ADDED
@@ -0,0 +1,652 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Easy Digital Downloads WP-CLI
4
+ *
5
+ * This class provides an integration point with the WP-CLI plugin allowing
6
+ * access to EDD from the command line.
7
+ *
8
+ * @package EDD
9
+ * @subpackage Classes/CLI
10
+ * @copyright Copyright (c) 2015, Pippin Williamson
11
+ * @license http://opensource.org/license/gpl-2.0.php GNU Public License
12
+ * @since 2.0
13
+ */
14
+
15
+ // Exit if accessed directly
16
+ if ( ! defined( 'ABSPATH' ) ) exit;
17
+
18
+ WP_CLI::add_command( 'edd', 'EDD_CLI' );
19
+
20
+ /**
21
+ * Work with EDD through WP-CLI
22
+ *
23
+ * EDD_CLI Class
24
+ *
25
+ * Adds CLI support to EDD through WP-CLI
26
+ *
27
+ * @since 2.0
28
+ */
29
+ class EDD_CLI extends WP_CLI_Command {
30
+
31
+ private $api;
32
+
33
+
34
+ public function __construct() {
35
+ $this->api = new EDD_API;
36
+ }
37
+
38
+
39
+ /**
40
+ * Get EDD details
41
+ *
42
+ * ## OPTIONS
43
+ *
44
+ * None. Returns basic info regarding your EDD instance.
45
+ *
46
+ * ## EXAMPLES
47
+ *
48
+ * wp edd details
49
+ *
50
+ * @access public
51
+ * @param array $args
52
+ * @param array $assoc_args
53
+ * @return void
54
+ */
55
+ public function details( $args, $assoc_args ) {
56
+ $symlink_file_downloads = edd_get_option( 'symlink_file_downloads', false );
57
+ $purchase_page = edd_get_option( 'purchase_page', '' );
58
+ $success_page = edd_get_option( 'success_page', '' );
59
+ $failure_page = edd_get_option( 'failure_page', '' );
60
+
61
+ WP_CLI::line( sprintf( __( 'You are running EDD version: %s', 'edd' ), EDD_VERSION ) );
62
+ WP_CLI::line( "\n" . sprintf( __( 'Test mode is: %s', 'edd' ), ( edd_is_test_mode() ? __( 'Enabled', 'edd' ) : __( 'Disabled', 'edd' ) ) ) );
63
+ WP_CLI::line( sprintf( __( 'Ajax is: %s', 'edd' ), ( edd_is_ajax_enabled() ? __( 'Enabled', 'edd' ) : __( 'Disabled', 'edd' ) ) ) );
64
+ WP_CLI::line( sprintf( __( 'Guest checkouts are: %s', 'edd' ), ( edd_no_guest_checkout() ? __( 'Disabled', 'edd' ) : __( 'Enabled', 'edd' ) ) ) );
65
+ WP_CLI::line( sprintf( __( 'Symlinks are: %s', 'edd' ), ( apply_filters( 'edd_symlink_file_downloads', isset( $symlink_file_downloads ) ) && function_exists( 'symlink' ) ? __( 'Enabled', 'edd' ) : __( 'Disabled', 'edd' ) ) ) );
66
+ WP_CLI::line( "\n" . sprintf( __( 'Checkout page is: %s', 'edd' ), ( ! edd_get_option( 'purchase_page', false ) ) ? __( 'Valid', 'edd' ) : __( 'Invalid', 'edd' ) ) );
67
+ WP_CLI::line( sprintf( __( 'Checkout URL is: %s', 'edd' ), ( ! empty( $purchase_page ) ? get_permalink( $purchase_page ) : __( 'Undefined', 'edd' ) ) ) );
68
+ WP_CLI::line( sprintf( __( 'Success URL is: %s', 'edd' ), ( ! empty( $success_page ) ? get_permalink( $success_page ) : __( 'Undefined', 'edd' ) ) ) );
69
+ WP_CLI::line( sprintf( __( 'Failure URL is: %s', 'edd' ), ( ! empty( $failure_page ) ? get_permalink( $failure_page ) : __( 'Undefined', 'edd' ) ) ) );
70
+ WP_CLI::line( sprintf( __( 'Downloads slug is: %s', 'edd' ), ( defined( 'EDD_SLUG' ) ? '/' . EDD_SLUG : '/downloads' ) ) );
71
+ WP_CLI::line( "\n" . sprintf( __( 'Taxes are: %s', 'edd' ), ( edd_use_taxes() ? __( 'Enabled', 'edd' ) : __( 'Disabled', 'edd' ) ) ) );
72
+ WP_CLI::line( sprintf( __( 'Tax rate is: %s', 'edd' ), edd_get_tax_rate() * 100 . '%' ) );
73
+
74
+ $rates = edd_get_tax_rates();
75
+ if( ! empty( $rates ) ) {
76
+ foreach( $rates as $rate ) {
77
+ WP_CLI::line( sprintf( __( 'Country: %s, State: %s, Rate: %s', 'edd' ), $rate['country'], $rate['state'], $rate['rate'] ) );
78
+ }
79
+ }
80
+ }
81
+
82
+
83
+ /**
84
+ * Get stats for your EDD site
85
+ *
86
+ * ## OPTIONS
87
+ *
88
+ * --product=<product_id>: The ID of a specific product to retrieve stats for, or all
89
+ * --date=[range|this_month|last_month|today|yesterday|this_quarter|last_quarter|this_year|last_year]: A specific date range to retrieve stats for
90
+ * --startdate=<date>: The start date of a date range to retrieve stats for
91
+ * --enddate=<date>: The end date of a date range to retrieve stats for
92
+ *
93
+ * ## EXAMPLES
94
+ *
95
+ * wp edd stats --date=this_month
96
+ * wp edd stats --start-date=01/02/2014 --end-date=02/23/2014
97
+ * wp edd stats --date=last_year
98
+ * wp edd stats --date=last_year --product=15
99
+ */
100
+ public function stats( $args, $assoc_args ) {
101
+
102
+ $stats = new EDD_Payment_Stats;
103
+ $date = isset( $assoc_args ) && array_key_exists( 'date', $assoc_args ) ? $assoc_args['date'] : false;
104
+ $start_date = isset( $assoc_args ) && array_key_exists( 'startdate', $assoc_args ) ? $assoc_args['startdate'] : false;
105
+ $end_date = isset( $assoc_args ) && array_key_exists( 'enddate', $assoc_args ) ? $assoc_args['enddate'] : false;
106
+ $download = isset( $assoc_args ) && array_key_exists( 'product', $assoc_args ) ? $assoc_args['product'] : 0;
107
+
108
+ if( ! empty( $date ) ) {
109
+ $start_date = $date;
110
+ $end_date = false;
111
+ } elseif( empty( $date ) && empty( $start_date ) ) {
112
+ $start_date = 'this_month';
113
+ $end_date = false;
114
+ }
115
+
116
+ $earnings = $stats->get_earnings( $download, $start_date, $end_date );
117
+ $sales = $stats->get_sales( $download, $start_date, $end_date );
118
+
119
+ WP_CLI::line( sprintf( __( 'Earnings: %s', 'edd' ), $earnings ) );
120
+ WP_CLI::line( sprintf( __( 'Sales: %s', 'edd' ), $sales ) );
121
+
122
+ }
123
+
124
+
125
+ /**
126
+ * Get the products currently posted on your EDD site
127
+ *
128
+ * ## OPTIONS
129
+ *
130
+ * --id=<product_id>: A specific product ID to retrieve
131
+ *
132
+ *
133
+ * ## EXAMPLES
134
+ *
135
+ * wp edd products --id=103
136
+ */
137
+ public function products( $args, $assoc_args ) {
138
+
139
+ $product_id = isset( $assoc_args ) && array_key_exists( 'id', $assoc_args ) ? absint( $assoc_args['id'] ) : false;
140
+ $products = $this->api->get_products( $product_id );
141
+
142
+ if( isset( $products['error'] ) ) {
143
+ WP_CLI::error( $products['error'] );
144
+ }
145
+
146
+ if( empty( $products ) ) {
147
+ WP_CLI::error( __( 'No Downloads found', 'edd' ) );
148
+ return;
149
+ }
150
+
151
+ foreach( $products['products'] as $product ) {
152
+
153
+ $categories = '';
154
+ $tags = '';
155
+ $pricing = array();
156
+
157
+ if( is_array( $product['info']['category'] ) ) {
158
+
159
+ $categories = array();
160
+ foreach( $product['info']['category'] as $category ) {
161
+ $categories[] = $category->name;
162
+ }
163
+
164
+ $categories = implode( ', ', $categories );
165
+
166
+ }
167
+
168
+ if( is_array( $product['info']['tags'] ) ) {
169
+
170
+ $tags = array();
171
+ foreach( $product['info']['tags'] as $tag ) {
172
+
173
+ $tags[] = $tag->name;
174
+
175
+ }
176
+
177
+ $tags = implode( ', ', $tags );
178
+
179
+ }
180
+
181
+ foreach( $product['pricing'] as $price => $value ) {
182
+
183
+ if( 'amount' != $price ) {
184
+ $price = $price . ' - ';
185
+ }
186
+
187
+ $pricing[] = $price . ': ' . edd_format_amount( $value ) . ' ' . edd_get_currency();
188
+ }
189
+
190
+ $pricing = implode( ', ', $pricing );
191
+
192
+ WP_CLI::line( WP_CLI::colorize( '%G' . $product['info']['title'] . '%N' ) );
193
+ WP_CLI::line( sprintf( __( 'ID: %d', 'edd' ), $product['info']['id'] ) );
194
+ WP_CLI::line( sprintf( __( 'Status: %s', 'edd' ), $product['info']['status'] ) );
195
+ WP_CLI::line( sprintf( __( 'Posted: %s', 'edd' ), $product['info']['create_date'] ) );
196
+ WP_CLI::line( sprintf( __( 'Categories: %s', 'edd' ), $categories ) );
197
+ WP_CLI::line( sprintf( __( 'Tags: %s', 'edd' ), ( is_array( $tags ) ? '' : $tags ) ) );
198
+ WP_CLI::line( sprintf( __( 'Pricing: %s', 'edd' ), $pricing ) );
199
+ WP_CLI::line( sprintf( __( 'Sales: %s', 'edd' ), $product['stats']['total']['sales'] ) );
200
+ WP_CLI::line( sprintf( __( 'Earnings: %s', 'edd' ), edd_format_amount( $product['stats']['total']['earnings'] ) ) ) . ' ' . edd_get_currency();
201
+ WP_CLI::line( '' );
202
+ WP_CLI::line( sprintf( __( 'Slug: %s', 'edd' ), $product['info']['slug'] ) );
203
+ WP_CLI::line( sprintf( __( 'Permalink: %s', 'edd' ), $product['info']['link'] ) );
204
+
205
+ if( array_key_exists( 'files', $product ) ) {
206
+
207
+ WP_CLI::line( '' );
208
+ WP_CLI::line( __( 'Download Files:', 'edd' ) );
209
+
210
+ foreach( $product['files'] as $file ) {
211
+
212
+ WP_CLI::line( ' ' . sprintf( __( 'File: %s (%s)', 'edd' ), $file['name'], $file['file'] ) );
213
+
214
+ if( isset( $file['condition'] ) && 'all' !== $file['condition'] ) {
215
+
216
+ WP_CLI::line( ' ' . sprintf( __( 'Price Assignment: %s', 'edd' ), $file['condition'] ) );
217
+
218
+ }
219
+
220
+ }
221
+
222
+ }
223
+
224
+ WP_CLI::line( '' );
225
+ }
226
+
227
+ }
228
+
229
+
230
+ /**
231
+ * Get the customers currently on your EDD site. Can also be used to create customers records
232
+ *
233
+ * ## OPTIONS
234
+ *
235
+ * --id=<customer_id>: A specific customer ID to retrieve
236
+ * --email=<customer_email>: The email address of the customer to retrieve
237
+ * --create=<number>: The number of arbitrary customers to create. Leave as 1 or blank to create a customer with a speciific email
238
+ *
239
+ * ## EXAMPLES
240
+ *
241
+ * wp edd customers --id=103
242
+ * wp edd customers --email=john@test.com
243
+ * wp edd customers --create=1 --email=john@test.com
244
+ * wp edd customers --create=1 --email=john@test.com --name="John Doe"
245
+ * wp edd customers --create=1 --email=john@test.com --name="John Doe" user_id=1
246
+ * wp edd customers --create=1000
247
+ */
248
+ public function customers( $args, $assoc_args ) {
249
+
250
+ $customer_id = isset( $assoc_args ) && array_key_exists( 'id', $assoc_args ) ? absint( $assoc_args['id'] ) : false;
251
+ $email = isset( $assoc_args ) && array_key_exists( 'email', $assoc_args ) ? $assoc_args['email'] : false;
252
+ $name = isset( $assoc_args ) && array_key_exists( 'name', $assoc_args ) ? $assoc_args['name'] : null;
253
+ $user_id = isset( $assoc_args ) && array_key_exists( 'user_id', $assoc_args ) ? $assoc_args['user_id'] : null;
254
+ $create = isset( $assoc_args ) && array_key_exists( 'create', $assoc_args ) ? $assoc_args['create'] : false;
255
+ $start = time();
256
+
257
+ if( $create ) {
258
+
259
+ $number = 1;
260
+
261
+ // Create one or more customers
262
+ if( ! $email ) {
263
+
264
+ // If no email is specified, look to see if we are generating arbitrary customer accounts
265
+ $number = is_numeric( $create ) ? absint( $create ) : 1;
266
+
267
+ }
268
+
269
+ for( $i = 0; $i < $number; $i++ ) {
270
+
271
+ if( ! $email ) {
272
+
273
+ // Generate fake email
274
+ $email = 'customer-' . uniqid() . '@test.com';
275
+
276
+ }
277
+
278
+ $args = array(
279
+ 'email' => $email,
280
+ 'name' => $name,
281
+ 'user_id' => $user_id
282
+ );
283
+
284
+ $customer_id = EDD()->customers->add( $args );
285
+
286
+ if( $customer_id ) {
287
+ WP_CLI::line( sprintf( __( 'Customer %d created successfully', 'edd' ), $customer_id ) );
288
+ } else {
289
+ WP_CLI::error( __( 'Failed to create customer', 'edd' ) );
290
+ }
291
+
292
+ // Reset email to false so it is generated on the next loop (if creating customers)
293
+ $email = false;
294
+
295
+ }
296
+
297
+ WP_CLI::line( WP_CLI::colorize( '%G' . sprintf( __( '%d customers created in %d seconds', 'edd' ), $create, time() - $start ) . '%N' ) );
298
+
299
+ } else {
300
+
301
+ // Search for customers
302
+
303
+ $search = $customer_id ? $customer_id : $email;
304
+ $customers = $this->api->get_customers( $search );
305
+
306
+ if( isset( $customers['error'] ) ) {
307
+ WP_CLI::error( $customers['error'] );
308
+ }
309
+
310
+ if( empty( $customers ) ) {
311
+ WP_CLI::error( __( 'No customers found', 'edd' ) );
312
+ return;
313
+ }
314
+
315
+ foreach( $customers['customers'] as $customer ) {
316
+ WP_CLI::line( WP_CLI::colorize( '%G' . $customer['info']['email'] . '%N' ) );
317
+ WP_CLI::line( sprintf( __( 'Customer User ID: %s', 'edd' ), $customer['info']['id'] ) );
318
+ WP_CLI::line( sprintf( __( 'Username: %s', 'edd' ), $customer['info']['username'] ) );
319
+ WP_CLI::line( sprintf( __( 'Display Name: %s', 'edd' ), $customer['info']['display_name'] ) );
320
+
321
+ if( array_key_exists( 'first_name', $customer ) ) {
322
+ WP_CLI::line( sprintf( __( 'First Name: %s', 'edd' ), $customer['info']['first_name'] ) );
323
+ }
324
+
325
+ if( array_key_exists( 'last_name', $customer ) ) {
326
+ WP_CLI::line( sprintf( __( 'Last Name: %s', 'edd' ), $customer['info']['last_name'] ) );
327
+ }
328
+
329
+ WP_CLI::line( sprintf( __( 'Email: %s', 'edd' ), $customer['info']['email'] ) );
330
+
331
+ WP_CLI::line( '' );
332
+ WP_CLI::line( sprintf( __( 'Purchases: %s', 'edd' ), $customer['stats']['total_purchases'] ) );
333
+ WP_CLI::line( sprintf( __( 'Total Spent: %s', 'edd' ), edd_format_amount( $customer['stats']['total_spent'] ) . ' ' . edd_get_currency() ) );
334
+ WP_CLI::line( sprintf( __( 'Total Downloads: %s', 'edd' ), $customer['stats']['total_downloads'] ) );
335
+
336
+ WP_CLI::line( '' );
337
+ }
338
+
339
+ }
340
+
341
+ }
342
+
343
+
344
+ /**
345
+ * Get the recent sales for your EDD site
346
+ *
347
+ * ## OPTIONS
348
+ *
349
+ *
350
+ * ## EXAMPLES
351
+ *
352
+ * wp edd sales
353
+ */
354
+ public function sales( $args, $assoc_args ) {
355
+
356
+ $sales = $this->api->get_recent_sales();
357
+
358
+ if( empty( $sales ) ) {
359
+ WP_CLI::error( __( 'No sales found', 'edd' ) );
360
+ return;
361
+ }
362
+
363
+ foreach( $sales['sales'] as $sale ) {
364
+ WP_CLI::line( WP_CLI::colorize( '%G' . $sale['ID'] . '%N' ) );
365
+ WP_CLI::line( sprintf( __( 'Purchase Key: %s', 'edd' ), $sale['key'] ) );
366
+ WP_CLI::line( sprintf( __( 'Email: %s', 'edd' ), $sale['email'] ) );
367
+ WP_CLI::line( sprintf( __( 'Date: %s', 'edd' ), $sale['date'] ) );
368
+ WP_CLI::line( sprintf( __( 'Subtotal: %s', 'edd' ), edd_format_amount( $sale['subtotal'] ) . ' ' . edd_get_currency() ) );
369
+ WP_CLI::line( sprintf( __( 'Tax: %s', 'edd' ), edd_format_amount( $sale['tax'] ) . ' ' . edd_get_currency() ) );
370
+
371
+ if( array_key_exists( 0, $sale['fees'] ) ) {
372
+ WP_CLI::line( __( 'Fees:', 'edd' ) );
373
+
374
+ foreach( $sale['fees'] as $fee ) {
375
+ WP_CLI::line( sprintf( __( ' Fee: %s - %s', 'edd' ), edd_format_amount( $fee['amount'] ) . ' ' . edd_get_currency() ) );
376
+ }
377
+ }
378
+
379
+ WP_CLI::line( sprintf( __( 'Total: %s', 'edd' ), edd_format_amount( $sale['total'] ) . ' ' . edd_get_currency() ) );
380
+ WP_CLI::line( '' );
381
+ WP_CLI::line( sprintf( __( 'Gateway: %s', 'edd' ), $sale['gateway'] ) );
382
+
383
+ if( array_key_exists( 0, $sale['products'] ) ) {
384
+ WP_CLI::line( __( 'Products:', 'edd' ) );
385
+
386
+ foreach( $sale['products'] as $product ) {
387
+ $price_name = ! empty( $product['price_name'] ) ? ' (' . $product['price_name'] . ')' : '';
388
+ WP_CLI::line( sprintf( __( ' Product: %s - %s', 'edd' ), $product['name'], edd_format_amount( $product['price'] ) . ' ' . edd_get_currency() . $price_name ) );
389
+ }
390
+ }
391
+
392
+ WP_CLI::line( '' );
393
+ }
394
+ }
395
+
396
+
397
+ /**
398
+ * Get discount details for on your EDD site
399
+ *
400
+ * ## OPTIONS
401
+ *
402
+ * --id=<discount_id>: A specific discount ID to retrieve
403
+ *
404
+ * ## EXAMPLES
405
+ *
406
+ * wp edd discounts --id=103
407
+ */
408
+ public function discounts( $args, $assoc_args ) {
409
+
410
+ $discount_id = isset( $assoc_args ) && array_key_exists( 'id', $assoc_args ) ? absint( $assoc_args['id'] ) : false;
411
+
412
+ $discounts = $this->api->get_discounts( $discount_id );
413
+
414
+ if( isset( $discounts['error'] ) ) {
415
+ WP_CLI::error( $discounts['error'] );
416
+ }
417
+
418
+ if( empty( $discounts ) ) {
419
+ WP_CLI::error( __( 'No discounts found', 'edd' ) );
420
+ return;
421
+ }
422
+
423
+ foreach( $discounts['discounts'] as $discount ) {
424
+ WP_CLI::line( WP_CLI::colorize( '%G' . $discount['ID'] . '%N' ) );
425
+ WP_CLI::line( sprintf( __( 'Name: %s', 'edd' ), $discount['name'] ) );
426
+ WP_CLI::line( sprintf( __( 'Code: %s', 'edd' ), $discount['code'] ) );
427
+
428
+ if( $discount['type'] == 'percent' ) {
429
+ $amount = $discount['amount'] . '%';
430
+ } else {
431
+ $amount = edd_format_amount( $discount['amount'] ) . ' ' . edd_get_currency();
432
+ }
433
+
434
+ WP_CLI::line( sprintf( __( 'Amount: %s', 'edd' ), $amount ) );
435
+ WP_CLI::line( sprintf( __( 'Uses: %s', 'edd' ), $discount['uses'] ) );
436
+ WP_CLI::line( sprintf( __( 'Max Uses: %s', 'edd' ), ( $discount['max_uses'] == '0' ? __( 'Unlimited', 'edd' ) : $discount['max_uses'] ) ) );
437
+ WP_CLI::line( sprintf( __( 'Start Date: %s', 'edd' ), ( empty( $discount['start_date'] ) ? __( 'No Start Date', 'edd' ) : $discount['start_date'] ) ) );
438
+ WP_CLI::line( sprintf( __( 'Expiration Date: %s', 'edd' ), ( empty( $discount['exp_date'] ) ? __( 'No Expiration', 'edd' ) : $discount['exp_date'] ) ) );
439
+ WP_CLI::line( sprintf( __( 'Status: %s', 'edd' ), ucwords( $discount['status'] ) ) );
440
+
441
+ WP_CLI::line( '' );
442
+
443
+ if( array_key_exists( 0, $discount['product_requirements'] ) ) {
444
+ WP_CLI::line( __( 'Product Requirements:', 'edd' ) );
445
+
446
+ foreach( $discount['product_requirements'] as $req => $req_id ) {
447
+ WP_CLI::line( sprintf( __( ' Product: %s', 'edd' ), $req_id ) );
448
+ }
449
+ }
450
+
451
+ WP_CLI::line( '' );
452
+
453
+ WP_CLI::line( sprintf( __( 'Global Discount: %s', 'edd' ), ( empty( $discount['global_discount'] ) ? 'False' : 'True' ) ) );
454
+ WP_CLI::line( sprintf( __( 'Single Use: %s', 'edd' ), ( empty( $discount['single_use'] ) ? 'False' : 'True' ) ) );
455
+
456
+ WP_CLI::line( '' );
457
+ }
458
+ }
459
+
460
+
461
+ /**
462
+ * Create sample purchase data for your EDD site
463
+ *
464
+ * ## OPTIONS
465
+ *
466
+ * --number: The number of purchases to create
467
+ * --status=<status>: The status to create purchases as
468
+ * --id=<product_id>: A specific product to create purchase data for
469
+ * --price_id=<price_id>: A price ID of the specified product
470
+ *
471
+ * ## EXAMPLES
472
+ *
473
+ * wp edd payments create --number=10 --status=completed
474
+ * wp edd payments create --number=10 --id=103
475
+ */
476
+ public function payments( $args, $assoc_args ) {
477
+
478
+ $error = false;
479
+
480
+ // At some point we'll likely add another action for payments
481
+ if( ! isset( $args ) || count( $args ) == 0 ) {
482
+ $error = __( 'No action specified, did you mean', 'edd' );
483
+ } elseif( isset( $args ) && ! in_array( 'create', $args ) ) {
484
+ $error = __( 'Invalid action specified, did you mean', 'edd' );
485
+ }
486
+
487
+ if( $error ) {
488
+ foreach( $assoc_args as $key => $value ) {
489
+ $query .= ' --' . $key . '=' . $value;
490
+ }
491
+
492
+ WP_CLI::error(
493
+ sprintf( $error . ' %s?', 'wp edd payments create' . $query )
494
+ );
495
+
496
+ return;
497
+ }
498
+
499
+
500
+ // Setup some defaults
501
+ $number = 1;
502
+ $status = 'complete';
503
+ $id = false;
504
+ $price_id = false;
505
+
506
+ if( count( $assoc_args ) > 0 ) {
507
+ $number = ( array_key_exists( 'number', $assoc_args ) ) ? absint( $assoc_args['number'] ) : $number;
508
+ $id = ( array_key_exists( 'id', $assoc_args ) ) ? absint( $assoc_args['id'] ) : $id;
509
+ $price_id = ( array_key_exists( 'price_id', $assoc_args ) ) ? absint( $assoc_args['id'] ) : false;
510
+ $tax = ( array_key_exists( 'tax', $assoc_args ) ) ? floatval( $assoc_args['tax'] ) : 0;
511
+
512
+ // Status requires a bit more validation
513
+ if( array_key_exists( 'status', $assoc_args ) ) {
514
+ $stati = array(
515
+ 'publish',
516
+ 'complete',
517
+ 'pending',
518
+ 'refunded',
519
+ 'revoked',
520
+ 'failed',
521
+ 'abandoned',
522
+ 'preapproval',
523
+ 'cancelled'
524
+ );
525
+
526
+ if( in_array( $assoc_args['status'], $stati ) ) {
527
+ $status = ( $assoc_args['status'] == 'complete' ) ? 'publish' : $assoc_args['status'];
528
+ } else {
529
+ WP_CLI::warning( sprintf(
530
+ __( "Invalid status '%s', defaulting to 'complete'", 'edd' ),
531
+ $assoc_args['status']
532
+ ) );
533
+ }
534
+ }
535
+ }
536
+
537
+ // Build the user info array
538
+ $user_info = array(
539
+ 'id' => 0,
540
+ 'email' => 'guest@local.dev',
541
+ 'first_name' => 'Pippin',
542
+ 'last_name' => 'Williamson',
543
+ 'discount' => 'none'
544
+ );
545
+
546
+ for( $i = 0; $i < $number; $i++ ) {
547
+
548
+ $products = array();
549
+ $total = 0;
550
+
551
+ // No specified product
552
+ if( ! $id ) {
553
+
554
+ $products = get_posts( array(
555
+ 'post_type' => 'download',
556
+ 'orderby' => 'rand',
557
+ 'order' => 'ASC',
558
+ 'posts_per_page'=> 1
559
+ ) );
560
+
561
+ } else {
562
+
563
+ $product = get_post( $id );
564
+
565
+ if( $product->post_type != 'download' ) {
566
+ WP_CLI::error( __( 'Specified ID is not a product', 'edd' ) );
567
+ return;
568
+ }
569
+
570
+ $products[] = $product;
571
+
572
+ }
573
+
574
+ $cart_details = array();
575
+
576
+ // Create the purchases
577
+ foreach( $products as $key => $download ) {
578
+
579
+ if( ! is_a( $download, 'WP_Post' ) ) {
580
+ continue;
581
+ }
582
+
583
+ $options = array();
584
+ $final_downloads = array();
585
+
586
+ // Deal with variable pricing
587
+ if( edd_has_variable_prices( $download->ID ) ) {
588
+
589
+ $prices = edd_get_variable_prices( $download->ID );
590
+
591
+ if( false === $price_id || ! array_key_exists( $price_id, (array) $prices ) ) {
592
+ $price_id = rand( 0, count( $prices ) - 1 );
593
+ }
594
+
595
+ $item_price = $prices[ $price_id ]['amount'];
596
+ $options['price_id'] = $price_id;
597
+
598
+ } else {
599
+
600
+ $item_price = edd_get_download_price( $download->ID );
601
+
602
+ }
603
+
604
+ $item_number = array(
605
+ 'id' => $download->ID,
606
+ 'quantity' => 1,
607
+ 'options' => $options
608
+ );
609
+
610
+ $cart_details[$key] = array(
611
+ 'name' => $download->post_title,
612
+ 'id' => $download->ID,
613
+ 'item_number' => $item_number,
614
+ 'item_price' => edd_sanitize_amount( $item_price ),
615
+ 'subtotal' => edd_sanitize_amount( $item_price ),
616
+ 'price' => edd_sanitize_amount( $item_price ),
617
+ 'quantity' => 1,
618
+ 'discount' => 0,
619
+ 'tax' => $tax
620
+ );
621
+
622
+ $final_downloads[$key] = $item_number;
623
+
624
+ $total += $item_price;
625
+
626
+ }
627
+
628
+ $purchase_data = array(
629
+ 'price' => edd_sanitize_amount( $total ),
630
+ 'tax' => 0,
631
+ 'purchase_key' => strtolower( md5( uniqid() ) ),
632
+ 'user_email' => 'guest@local.dev',
633
+ 'user_info' => $user_info,
634
+ 'currency' => edd_get_currency(),
635
+ 'downloads' => $final_downloads,
636
+ 'cart_details' => $cart_details,
637
+ 'status' => 'pending'
638
+ );
639
+
640
+ $payment_id = edd_insert_payment( $purchase_data );
641
+
642
+ remove_action( 'edd_complete_purchase', 'edd_trigger_purchase_receipt', 999 );
643
+
644
+ if( $status != 'pending' ) {
645
+ edd_update_payment_status( $payment_id, $status );
646
+ }
647
+ }
648
+
649
+ WP_CLI::success( sprintf( __( 'Created %s payments', 'edd' ), $number ) );
650
+ return;
651
+ }
652
+ }
includes/class-edd-cron.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Classes/Cron
7
- * @copyright Copyright (c) 2012, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.6
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Classes/Cron
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.6
10
  */
includes/class-edd-customer.php ADDED
@@ -0,0 +1,638 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Customer Object
4
+ *
5
+ * @package EDD
6
+ * @subpackage Classes/Customer
7
+ * @copyright Copyright (c) 2015, Chris Klosowski
8
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
+ * @since 2.3
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
+
15
+ /**
16
+ * EDD_Customer Class
17
+ *
18
+ * @since 2.3
19
+ */
20
+ class EDD_Customer {
21
+
22
+ /**
23
+ * The customer ID
24
+ *
25
+ * @since 2.3
26
+ */
27
+ public $id = 0;
28
+
29
+ /**
30
+ * The customer's purchase count
31
+ *
32
+ * @since 2.3
33
+ */
34
+ public $purchase_count = 0;
35
+
36
+ /**
37
+ * The customer's lifetime value
38
+ *
39
+ * @since 2.3
40
+ */
41
+ public $purchase_value = 0;
42
+
43
+ /**
44
+ * The customer's email
45
+ *
46
+ * @since 2.3
47
+ */
48
+ public $email;
49
+
50
+ /**
51
+ * The customer's name
52
+ *
53
+ * @since 2.3
54
+ */
55
+ public $name;
56
+
57
+ /**
58
+ * The customer's creation date
59
+ *
60
+ * @since 2.3
61
+ */
62
+ public $date_created;
63
+
64
+ /**
65
+ * The payment IDs associated with the customer
66
+ *
67
+ * @since 2.3
68
+ */
69
+ public $payment_ids;
70
+
71
+ /**
72
+ * The user ID associated with the customer
73
+ *
74
+ * @since 2.3
75
+ */
76
+ public $user_id;
77
+
78
+ /**
79
+ * Customer Notes
80
+ *
81
+ * @since 2.3
82
+ */
83
+ public $notes;
84
+
85
+ /**
86
+ * The Database Abstraction
87
+ *
88
+ * @since 2.3
89
+ */
90
+ protected $db;
91
+
92
+ /**
93
+ * Get things going
94
+ *
95
+ * @since 2.3
96
+ */
97
+ public function __construct( $_id_or_email = false, $by_user_id = false ) {
98
+
99
+ $this->db = new EDD_DB_Customers;
100
+
101
+ if ( false === $_id_or_email || ( is_numeric( $_id_or_email ) && (int) $_id_or_email !== absint( $_id_or_email ) ) ) {
102
+ return false;
103
+ }
104
+
105
+ $by_user_id = is_bool( $by_user_id ) ? $by_user_id : false;
106
+
107
+ if ( is_numeric( $_id_or_email ) ) {
108
+ $field = $by_user_id ? 'user_id' : 'id';
109
+ } else {
110
+ $field = 'email';
111
+ }
112
+
113
+ $customer = $this->db->get_customer_by( $field, $_id_or_email );
114
+
115
+ if ( empty( $customer ) || ! is_object( $customer ) ) {
116
+ return false;
117
+ }
118
+
119
+ $this->setup_customer( $customer );
120
+
121
+ }
122
+
123
+ /**
124
+ * Given the customer data, let's set the variables
125
+ *
126
+ * @since 2.3
127
+ * @param object $customer The Customer Object
128
+ * @return bool If the setup was successful or not
129
+ */
130
+ private function setup_customer( $customer ) {
131
+
132
+ if ( ! is_object( $customer ) ) {
133
+ return false;
134
+ }
135
+
136
+ foreach ( $customer as $key => $value ) {
137
+
138
+ switch ( $key ) {
139
+
140
+ case 'notes':
141
+ $this->$key = $this->get_notes();
142
+ break;
143
+
144
+ default:
145
+ $this->$key = $value;
146
+ break;
147
+
148
+ }
149
+
150
+ }
151
+
152
+ // Customer ID and email are the only things that are necessary, make sure they exist
153
+ if ( ! empty( $this->id ) && ! empty( $this->email ) ) {
154
+ return true;
155
+ }
156
+
157
+ return false;
158
+
159
+ }
160
+
161
+ /**
162
+ * Magic __get function to dispatch a call to retrieve a private property
163
+ *
164
+ * @since 2.3
165
+ */
166
+ public function __get( $key ) {
167
+
168
+ if( method_exists( $this, 'get_' . $key ) ) {
169
+
170
+ return call_user_func( array( $this, 'get_' . $key ) );
171
+
172
+ } else {
173
+
174
+ return new WP_Error( 'edd-customer-invalid-property', sprintf( __( 'Can\'t get property %s', 'edd' ), $key ) );
175
+
176
+ }
177
+
178
+ }
179
+
180
+ /**
181
+ * Creates a customer
182
+ *
183
+ * @since 2.3
184
+ * @param array $data Array of attributes for a customer
185
+ * @return mixed False if not a valid creation, Customer ID if user is found or valid creation
186
+ */
187
+ public function create( $data = array() ) {
188
+
189
+ if ( $this->id != 0 || empty( $data ) ) {
190
+ return false;
191
+ }
192
+
193
+ $defaults = array(
194
+ 'payment_ids' => ''
195
+ );
196
+
197
+ $args = wp_parse_args( $data, $defaults );
198
+ $args = $this->sanitize_columns( $args );
199
+
200
+ if ( empty( $args['email'] ) || ! is_email( $args['email'] ) ) {
201
+ return false;
202
+ }
203
+
204
+ if ( ! empty( $args['payment_ids'] ) && is_array( $args['payment_ids'] ) ) {
205
+ $args['payment_ids'] = implode( ',', array_unique( array_values( $args['payment_ids'] ) ) );
206
+ }
207
+
208
+ do_action( 'edd_customer_pre_create', $args );
209
+
210
+ $created = false;
211
+
212
+ // The DB class 'add' implies an update if the customer being asked to be created already exists
213
+ if ( $this->db->add( $data ) ) {
214
+
215
+ // We've successfully added/updated the customer, reset the class vars with the new data
216
+ $customer = $this->db->get_customer_by( 'email', $args['email'] );
217
+
218
+ // Setup the customer data with the values from DB
219
+ $this->setup_customer( $customer );
220
+
221
+ $created = $this->id;
222
+ }
223
+
224
+ do_action( 'edd_customer_post_create', $created, $args );
225
+
226
+ return $created;
227
+
228
+ }
229
+
230
+ /**
231
+ * Update a customer record
232
+ *
233
+ * @since 2.3
234
+ * @param array $data Array of data attributes for a customer (checked via whitelist)
235
+ * @return bool If the update was successful or not
236
+ */
237
+ public function update( $data = array() ) {
238
+
239
+ if ( empty( $data ) ) {
240
+ return false;
241
+ }
242
+
243
+ $data = $this->sanitize_columns( $data );
244
+
245
+ do_action( 'edd_customer_pre_update', $this->id, $data );
246
+
247
+ $updated = false;
248
+
249
+ if ( $this->db->update( $this->id, $data ) ) {
250
+
251
+ $customer = $this->db->get_customer_by( 'id', $this->id );
252
+ $this->setup_customer( $customer);
253
+
254
+ $updated = true;
255
+ }
256
+
257
+ do_action( 'edd_customer_post_update', $updated, $this->id, $data );
258
+
259
+ return $updated;
260
+ }
261
+
262
+
263
+ /**
264
+ * Attach payment to the customer then triggers increasing stats
265
+ *
266
+ * @since 2.3
267
+ * @param int $payment_id The payment ID to attach to the customer
268
+ * @param bool $update_stats For backwards compatibility, if we should increase the stats or not
269
+ * @return bool If the attachment was successfuly
270
+ */
271
+ public function attach_payment( $payment_id = 0, $update_stats = true ) {
272
+
273
+ if( empty( $payment_id ) ) {
274
+ return false;
275
+ }
276
+
277
+ if( empty( $this->payment_ids ) ) {
278
+
279
+ $new_payment_ids = $payment_id;
280
+
281
+ } else {
282
+
283
+ $payment_ids = array_map( 'absint', explode( ',', $this->payment_ids ) );
284
+
285
+ if ( in_array( $payment_id, $payment_ids ) ) {
286
+ $update_stats = false;
287
+ }
288
+
289
+ $payment_ids[] = $payment_id;
290
+
291
+ $new_payment_ids = implode( ',', array_unique( array_values( $payment_ids ) ) );
292
+
293
+ }
294
+
295
+ do_action( 'edd_customer_pre_attach_payment', $payment_id, $this->id );
296
+
297
+ $payment_added = $this->update( array( 'payment_ids' => $new_payment_ids ) );
298
+
299
+ if ( $payment_added ) {
300
+
301
+ $this->payment_ids = $new_payment_ids;
302
+
303
+ // We added this payment successfully, increment the stats
304
+ if ( $update_stats ) {
305
+ $payment_amount = edd_get_payment_amount( $payment_id );
306
+
307
+ if ( ! empty( $payment_amount ) ) {
308
+ $this->increase_value( $payment_amount );
309
+ }
310
+
311
+ $this->increase_purchase_count();
312
+ }
313
+
314
+ }
315
+
316
+ do_action( 'edd_customer_post_attach_payment', $payment_added, $payment_id, $this->id );
317
+
318
+ return $payment_added;
319
+ }
320
+
321
+
322
+ /**
323
+ * Remove a payment from this customer, then triggers reducing stats
324
+ *
325
+ * @since 2.3
326
+ * @param integer $payment_id The Payment ID to remove
327
+ * @param bool $update_stats For backwards compatibility, if we should increase the stats or not
328
+ * @return boolean If the removal was successful
329
+ */
330
+ public function remove_payment( $payment_id = 0, $update_stats = true ) {
331
+
332
+ if( empty( $payment_id ) ) {
333
+ return false;
334
+ }
335
+
336
+ $new_payment_ids = '';
337
+
338
+ if( ! empty( $this->payment_ids ) ) {
339
+
340
+ $payment_ids = array_map( 'absint', explode( ',', $this->payment_ids ) );
341
+
342
+ $pos = array_search( $payment_id, $payment_ids );
343
+ if ( false === $pos ) {
344
+ return false;
345
+ }
346
+
347
+ unset( $payment_ids[$pos] );
348
+ $payment_ids = array_filter( $payment_ids );
349
+
350
+ $new_payment_ids = implode( ',', array_unique( array_values( $payment_ids ) ) );
351
+
352
+ }
353
+
354
+ do_action( 'edd_customer_pre_remove_payment', $payment_id, $this->id );
355
+
356
+ $payment_removed = $this->update( array( 'payment_ids' => $new_payment_ids ) );
357
+
358
+ if ( $payment_removed ) {
359
+
360
+ $this->payment_ids = $new_payment_ids;
361
+
362
+ if ( $update_stats ) {
363
+ // We removed this payment successfully, decrement the stats
364
+ $payment_amount = edd_get_payment_amount( $payment_id );
365
+
366
+ if ( ! empty( $payment_amount ) ) {
367
+ $this->decrease_value( $payment_amount );
368
+ }
369
+
370
+ $this->decrease_purchase_count();
371
+ }
372
+
373
+ }
374
+
375
+ do_action( 'edd_customer_post_remove_payment', $payment_removed, $payment_id, $this->id );
376
+
377
+ return $payment_removed;
378
+
379
+ }
380
+
381
+ /**
382
+ * Increase the purchase count of a customer
383
+ *
384
+ * @since 2.3
385
+ * @param integer $count The number to imcrement by
386
+ * @return int The purchase count
387
+ */
388
+ public function increase_purchase_count( $count = 1 ) {
389
+
390
+ // Make sure it's numeric and not negative
391
+ if ( ! is_numeric( $count ) || $count != absint( $count ) ) {
392
+ return false;
393
+ }
394
+
395
+ $new_total = (int) $this->purchase_count + (int) $count;
396
+
397
+ do_action( 'edd_customer_pre_increase_purchase_count', $count, $this->id );
398
+
399
+ if ( $this->update( array( 'purchase_count' => $new_total ) ) ) {
400
+ $this->purchase_count = $new_total;
401
+ }
402
+
403
+ do_action( 'edd_customer_post_increase_purchase_count', $this->purchase_count, $count, $this->id );
404
+
405
+ return $this->purchase_count;
406
+ }
407
+
408
+ /**
409
+ * Decrease the customer purchase count
410
+ *
411
+ * @since 2.3
412
+ * @param integer $count The amount to decrease by
413
+ * @return mixed If successful, the new count, otherwise false
414
+ */
415
+ public function decrease_purchase_count( $count = 1 ) {
416
+
417
+ // Make sure it's numeric and not negative
418
+ if ( ! is_numeric( $count ) || $count != absint( $count ) ) {
419
+ return false;
420
+ }
421
+
422
+ $new_total = (int) $this->purchase_count - (int) $count;
423
+
424
+ if( $new_total < 0 ) {
425
+ $new_total = 0;
426
+ }
427
+
428
+ do_action( 'edd_customer_pre_decrease_purchase_count', $count, $this->id );
429
+
430
+ if ( $this->update( array( 'purchase_count' => $new_total ) ) ) {
431
+ $this->purchase_count = $new_total;
432
+ }
433
+
434
+ do_action( 'edd_customer_post_decrease_purchase_count', $this->purchase_count, $count, $this->id );
435
+
436
+ return $this->purchase_count;
437
+ }
438
+
439
+ /**
440
+ * Increase the customer's lifetime value
441
+ *
442
+ * @since 2.3
443
+ * @param float $value The value to increase by
444
+ * @return mixed If successful, the new value, otherwise false
445
+ */
446
+ public function increase_value( $value = 0.00 ) {
447
+
448
+ $new_value = floatval( $this->purchase_value ) + $value;
449
+
450
+ do_action( 'edd_customer_pre_increase_value', $value, $this->id );
451
+
452
+ if ( $this->update( array( 'purchase_value' => $new_value ) ) ) {
453
+ $this->purchase_value = $new_value;
454
+ }
455
+
456
+ do_action( 'edd_customer_post_increase_value', $this->purchase_value, $value, $this->id );
457
+
458
+ return $this->purchase_value;
459
+ }
460
+
461
+ /**
462
+ * Decrease a customer's lifetime value
463
+ *
464
+ * @since 2.3
465
+ * @param float $value The value to decrease by
466
+ * @return mixed If successful, the new value, otherwise false
467
+ */
468
+ public function decrease_value( $value = 0.00 ) {
469
+
470
+ $new_value = floatval( $this->purchase_value ) - $value;
471
+
472
+ if( $new_value < 0 ) {
473
+ $new_value = 0.00;
474
+ }
475
+
476
+ do_action( 'edd_customer_pre_decrease_value', $value, $this->id );
477
+
478
+ if ( $this->update( array( 'purchase_value' => $new_value ) ) ) {
479
+ $this->purchase_value = $new_value;
480
+ }
481
+
482
+ do_action( 'edd_customer_post_decrease_value', $this->purchase_value, $value, $this->id );
483
+
484
+ return $this->purchase_value;
485
+ }
486
+
487
+ /**
488
+ * Get the parsed notes for a customer as an array
489
+ *
490
+ * @since 2.3
491
+ * @param integer $length The number of notes to get
492
+ * @param integer $paged What note to start at
493
+ * @return array The notes requsted
494
+ */
495
+ public function get_notes( $length = 20, $paged = 1 ) {
496
+
497
+ $length = is_numeric( $length ) ? $length : 20;
498
+ $offset = is_numeric( $paged ) && $paged != 1 ? ( ( absint( $paged ) - 1 ) * $length ) : 0;
499
+
500
+ $all_notes = $this->get_raw_notes();
501
+ $notes_array = array_reverse( array_filter( explode( "\n\n", $all_notes ) ) );
502
+
503
+ $desired_notes = array_slice( $notes_array, $offset, $length );
504
+
505
+ return $desired_notes;
506
+
507
+ }
508
+
509
+ /**
510
+ * Get the total number of notes we have after parsing
511
+ *
512
+ * @since 2.3
513
+ * @return int The number of notes for the customer
514
+ */
515
+ public function get_notes_count() {
516
+
517
+ $all_notes = $this->get_raw_notes();
518
+ $notes_array = array_reverse( array_filter( explode( "\n\n", $all_notes ) ) );
519
+
520
+ return count( $notes_array );
521
+
522
+ }
523
+
524
+ /**
525
+ * Add a note for the customer
526
+ *
527
+ * @since 2.3
528
+ * @param string $note The note to add
529
+ * @return string|boolean The new note if added succesfully, false otherwise
530
+ */
531
+ public function add_note( $note = '' ) {
532
+
533
+ $note = trim( $note );
534
+ if ( empty( $note ) ) {
535
+ return false;
536
+ }
537
+
538
+ $notes = $this->get_raw_notes();
539
+
540
+ if( empty( $notes ) ) {
541
+ $notes = '';
542
+ }
543
+
544
+ $note_string = date_i18n( 'F j, Y H:i:s', current_time( 'timestamp' ) ) . ' - ' . $note;
545
+ $new_note = apply_filters( 'edd_customer_add_note_string', $note_string );
546
+ $notes .= "\n\n" . $new_note;
547
+
548
+ do_action( 'edd_customer_pre_add_note', $new_note, $this->id );
549
+
550
+ $updated = $this->update( array( 'notes' => $notes ) );
551
+
552
+ if ( $updated ) {
553
+ $this->notes = $this->get_notes();
554
+ }
555
+
556
+ do_action( 'edd_customer_post_add_note', $this->notes, $new_note, $this->id );
557
+
558
+ // Return the formatted note, so we can test, as well as update any displays
559
+ return $new_note;
560
+
561
+ }
562
+
563
+ /**
564
+ * Get the notes column for the customer
565
+ *
566
+ * @since 2.3
567
+ * @return string The Notes for the customer, non-parsed
568
+ */
569
+ private function get_raw_notes() {
570
+
571
+ $all_notes = $this->db->get_column( 'notes', $this->id );
572
+
573
+ return $all_notes;
574
+
575
+ }
576
+
577
+ /**
578
+ * Sanitize the data for update/create
579
+ *
580
+ * @since 2.3
581
+ * @param array $data The data to sanitize
582
+ * @return array The sanitized data, based off column defaults
583
+ */
584
+ private function sanitize_columns( $data ) {
585
+
586
+ $columns = $this->db->get_columns();
587
+ $default_values = $this->db->get_column_defaults();
588
+
589
+ foreach ( $columns as $key => $type ) {
590
+
591
+ // Only sanitize data that we were provided
592
+ if ( ! array_key_exists( $key, $data ) ) {
593
+ continue;
594
+ }
595
+
596
+ switch( $type ) {
597
+
598
+ case '%s':
599
+ if ( 'email' == $key ) {
600
+ $data[$key] = sanitize_email( $data[$key] );
601
+ } elseif ( 'notes' == $key ) {
602
+ $data[$key] = strip_tags( $data[$key] );
603
+ } else {
604
+ $data[$key] = sanitize_text_field( $data[$key] );
605
+ }
606
+ break;
607
+
608
+ case '%d':
609
+ if ( ! is_numeric( $data[$key] ) || (int) $data[$key] !== absint( $data[$key] ) ) {
610
+ $data[$key] = $default_values[$key];
611
+ } else {
612
+ $data[$key] = absint( $data[$key] );
613
+ }
614
+ break;
615
+
616
+ case '%f':
617
+ // Convert what was given to a float
618
+ $value = floatval( $data[$key] );
619
+
620
+ if ( ! is_float( $value ) ) {
621
+ $data[$key] = $default_values[$key];
622
+ } else {
623
+ $data[$key] = $value;
624
+ }
625
+ break;
626
+
627
+ default:
628
+ $data[$key] = sanitize_text_field( $data[$key] );
629
+ break;
630
+
631
+ }
632
+
633
+ }
634
+
635
+ return $data;
636
+ }
637
+
638
+ }
includes/class-edd-db-customers.php ADDED
@@ -0,0 +1,572 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Customers DB class
4
+ *
5
+ * This class is for interacting with the customers' database table
6
+ *
7
+ * @package EDD
8
+ * @subpackage Classes/DB Customers
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
+ * @since 2.1
12
+ */
13
+
14
+ // Exit if accessed directly
15
+ if ( ! defined( 'ABSPATH' ) ) exit;
16
+
17
+ /**
18
+ * EDD_DB_Customers Class
19
+ *
20
+ * @since 2.1
21
+ */
22
+ class EDD_DB_Customers extends EDD_DB {
23
+
24
+ /**
25
+ * Get things started
26
+ *
27
+ * @access public
28
+ * @since 2.1
29
+ */
30
+ public function __construct() {
31
+
32
+ global $wpdb;
33
+
34
+ $this->table_name = $wpdb->prefix . 'edd_customers';
35
+ $this->primary_key = 'id';
36
+ $this->version = '1.0';
37
+
38
+ }
39
+
40
+ /**
41
+ * Get columns and formats
42
+ *
43
+ * @access public
44
+ * @since 2.1
45
+ */
46
+ public function get_columns() {
47
+ return array(
48
+ 'id' => '%d',
49
+ 'user_id' => '%d',
50
+ 'name' => '%s',
51
+ 'email' => '%s',
52
+ 'payment_ids' => '%s',
53
+ 'purchase_value' => '%f',
54
+ 'purchase_count' => '%d',
55
+ 'notes' => '%s',
56
+ 'date_created' => '%s',
57
+ );
58
+ }
59
+
60
+ /**
61
+ * Get default column values
62
+ *
63
+ * @access public
64
+ * @since 2.1
65
+ */
66
+ public function get_column_defaults() {
67
+ return array(
68
+ 'user_id' => 0,
69
+ 'email' => '',
70
+ 'name' => '',
71
+ 'payment_ids' => '',
72
+ 'purchase_value' => 0.00,
73
+ 'purchase_count' => 0,
74
+ 'notes' => '',
75
+ 'date_created' => date( 'Y-m-d H:i:s' ),
76
+ );
77
+ }
78
+
79
+ /**
80
+ * Add a customer
81
+ *
82
+ * @access public
83
+ * @since 2.1
84
+ */
85
+ public function add( $data = array() ) {
86
+
87
+ $defaults = array(
88
+ 'payment_ids' => ''
89
+ );
90
+
91
+ $args = wp_parse_args( $data, $defaults );
92
+
93
+ if( empty( $args['email'] ) ) {
94
+ return false;
95
+ }
96
+
97
+ if( ! empty( $args['payment_ids'] ) && is_array( $args['payment_ids'] ) ) {
98
+ $args['payment_ids'] = implode( ',', array_unique( array_values( $args['payment_ids'] ) ) );
99
+ }
100
+
101
+ $customer = $this->get_customer_by( 'email', $args['email'] );
102
+
103
+ if( $customer ) {
104
+ // update an existing customer
105
+
106
+ // Update the payment IDs attached to the customer
107
+ if( ! empty( $args['payment_ids'] ) ) {
108
+
109
+ if( empty( $customer->payment_ids ) ) {
110
+
111
+ $customer->payment_ids = $args['payment_ids'];
112
+
113
+ } else {
114
+
115
+ $existing_ids = array_map( 'absint', explode( ',', $customer->payment_ids ) );
116
+ $payment_ids = array_map( 'absint', explode( ',', $args['payment_ids'] ) );
117
+ $payment_ids = array_merge( $payment_ids, $existing_ids );
118
+ $customer->payment_ids = implode( ',', array_unique( array_values( $payment_ids ) ) );
119
+
120
+ }
121
+
122
+ $args['payment_ids'] = $customer->payment_ids;
123
+
124
+ }
125
+
126
+ $this->update( $customer->id, $args );
127
+
128
+ return $customer->id;
129
+
130
+ } else {
131
+
132
+ return $this->insert( $args, 'customer' );
133
+
134
+ }
135
+
136
+ }
137
+
138
+ /**
139
+ * Delete a customer
140
+ *
141
+ * NOTE: This should not be called directly as it does not make necessary changes to
142
+ * the payment meta and logs. Use edd_customer_delete() instead
143
+ *
144
+ * @access public
145
+ * @since 2.3.1
146
+ */
147
+ public function delete( $_id_or_email = false ) {
148
+
149
+ if ( empty( $_id_or_email ) ) {
150
+ return false;
151
+ }
152
+
153
+ $column = is_email( $_id_or_email ) ? 'email' : 'id';
154
+ $customer = $this->get_customer_by( $column, $_id_or_email );
155
+
156
+ if ( $customer->id > 0 ) {
157
+
158
+ global $wpdb;
159
+ return $wpdb->delete( $this->table_name, array( 'id' => $customer->id ), array( '%d' ) );
160
+
161
+ } else {
162
+ return false;
163
+ }
164
+
165
+ }
166
+
167
+ /**
168
+ * Checks if a customer exists by email
169
+ *
170
+ * @access public
171
+ * @since 2.1
172
+ */
173
+ public function exists( $email = '' ) {
174
+
175
+ return (bool) $this->get_column_by( 'id', 'email', $email );
176
+
177
+ }
178
+
179
+ /**
180
+ * Attaches a payment ID to a customer
181
+ *
182
+ * @access public
183
+ * @since 2.1
184
+ */
185
+ public function attach_payment( $customer_id = 0, $payment_id = 0 ) {
186
+
187
+ $customer = new EDD_Customer( $customer_id );
188
+
189
+ if( empty( $customer->id ) ) {
190
+ return false;
191
+ }
192
+
193
+ // Attach the payment, but don't increment stats, as this function previously did not
194
+ return $customer->attach_payment( $payment_id, false );
195
+
196
+ }
197
+
198
+ /**
199
+ * Removes a payment ID from a customer
200
+ *
201
+ * @access public
202
+ * @since 2.1
203
+ */
204
+ public function remove_payment( $customer_id = 0, $payment_id = 0 ) {
205
+
206
+ $customer = new EDD_Customer( $customer_id );
207
+
208
+ if( ! $customer ) {
209
+ return false;
210
+ }
211
+
212
+ // Remove the payment, but don't decrease stats, as this function previously did not
213
+ return $customer->remove_payment( $payment_id, false );
214
+
215
+ }
216
+
217
+ /**
218
+ * Increments customer purchase stats
219
+ *
220
+ * @access public
221
+ * @since 2.1
222
+ */
223
+ public function increment_stats( $customer_id = 0, $amount = 0.00 ) {
224
+
225
+ $customer = new EDD_Customer( $customer_id );
226
+
227
+ if( empty( $customer->id ) ) {
228
+ return false;
229
+ }
230
+
231
+ $increased_count = $customer->increase_purchase_count();
232
+ $increased_value = $customer->increase_value( $amount );
233
+
234
+ return ( $increased_count && $increased_value ) ? true : false;
235
+
236
+ }
237
+
238
+ /**
239
+ * Decrements customer purchase stats
240
+ *
241
+ * @access public
242
+ * @since 2.1
243
+ */
244
+ public function decrement_stats( $customer_id = 0, $amount = 0.00 ) {
245
+
246
+ $customer = new EDD_Customer( $customer_id );
247
+
248
+ if( ! $customer ) {
249
+ return false;
250
+ }
251
+
252
+ $decreased_count = $customer->decrease_purchase_count();
253
+ $decreased_value = $customer->decrease_value( $amount );
254
+
255
+ return ( $decreased_count && $decreased_value ) ? true : false;
256
+
257
+ }
258
+
259
+ /**
260
+ * Retrieves a single customer from the database
261
+ *
262
+ * @access public
263
+ * @since 2.3
264
+ * @param string $column id or email
265
+ * @param mixed $value The Customer ID or email to search
266
+ * @return mixed Upon success, an object of the customer. Upon failure, NULL
267
+ */
268
+ public function get_customer_by( $field = 'id', $value = 0 ) {
269
+ global $wpdb;
270
+
271
+ if ( empty( $field ) || empty( $value ) ) {
272
+ return NULL;
273
+ }
274
+
275
+ if ( 'id' == $field || 'user_id' == $field ) {
276
+ // Make sure the value is numeric to avoid casting objects, for example,
277
+ // to int 1.
278
+ if ( ! is_numeric( $value ) ) {
279
+ return false;
280
+ }
281
+
282
+ $value = intval( $value );
283
+
284
+ if ( $value < 1 ) {
285
+ return false;
286
+ }
287
+
288
+ } elseif ( 'email' === $field ) {
289
+
290
+ if ( ! is_email( $value ) ) {
291
+ return false;
292
+ }
293
+
294
+ $value = trim( $value );
295
+ }
296
+
297
+ if ( ! $value ) {
298
+ return false;
299
+ }
300
+
301
+ switch ( $field ) {
302
+ case 'id':
303
+ $db_field = 'id';
304
+ break;
305
+ case 'email':
306
+ $value = sanitize_text_field( $value );
307
+ $db_field = 'email';
308
+ break;
309
+ case 'user_id':
310
+ $db_field = 'user_id';
311
+ break;
312
+ default:
313
+ return false;
314
+ }
315
+
316
+ if ( ! $customer = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $this->table_name WHERE $db_field = %s LIMIT 1", $value ) ) ) {
317
+ return false;
318
+ }
319
+
320
+ return $customer;
321
+ }
322
+
323
+ /**
324
+ * Retrieve customers from the database
325
+ *
326
+ * @access public
327
+ * @since 2.1
328
+ */
329
+ public function get_customers( $args = array() ) {
330
+
331
+ global $wpdb;
332
+
333
+ $defaults = array(
334
+ 'number' => 20,
335
+ 'offset' => 0,
336
+ 'user_id' => 0,
337
+ 'orderby' => 'id',
338
+ 'order' => 'DESC'
339
+ );
340
+
341
+ $args = wp_parse_args( $args, $defaults );
342
+
343
+ if( $args['number'] < 1 ) {
344
+ $args['number'] = 999999999999;
345
+ }
346
+
347
+ $where = '';
348
+
349
+ // specific customers
350
+ if( ! empty( $args['id'] ) ) {
351
+
352
+ if( is_array( $args['id'] ) ) {
353
+ $ids = implode( ',', $args['id'] );
354
+ } else {
355
+ $ids = intval( $args['id'] );
356
+ }
357
+
358
+ $where .= "WHERE `id` IN( {$ids} ) ";
359
+
360
+ }
361
+
362
+ // customers for specific user accounts
363
+ if( ! empty( $args['user_id'] ) ) {
364
+
365
+ if( is_array( $args['user_id'] ) ) {
366
+ $user_ids = implode( ',', $args['user_id'] );
367
+ } else {
368
+ $user_ids = intval( $args['user_id'] );
369
+ }
370
+
371
+ if( ! empty( $where ) ) {
372
+ $where .= " AND `user_id` IN( {$user_ids} ) ";
373
+ } else {
374
+ $where .= "WHERE `user_id` IN( {$user_ids} ) ";
375
+ }
376
+
377
+
378
+ }
379
+
380
+ //specific customers by email
381
+ if( ! empty( $args['email'] ) ) {
382
+
383
+ if( is_array( $args['email'] ) ) {
384
+ $emails = "'" . implode( "', '", $args['email'] ) . "'";
385
+ } else {
386
+ $emails = "'" . $args['email'] . "'";
387
+ }
388
+
389
+ if( ! empty( $where ) ) {
390
+ $where .= " AND `email` IN( {$emails} ) ";
391
+ } else {
392
+ $where .= "WHERE `email` IN( {$emails} ) ";
393
+ }
394
+
395
+ }
396
+
397
+ // specific customers by name
398
+ if( ! empty( $args['name'] ) ) {
399
+
400
+ if( ! empty( $where ) ) {
401
+ $where .= " AND `name` LIKE '" . $args['name'] . "' ";
402
+ } else {
403
+ $where .= "WHERE `name` LIKE '%%" . $args['name'] . "%%' ";
404
+ }
405
+ }
406
+
407
+ // Customers created for a specific date or in a date range
408
+ if( ! empty( $args['date'] ) ) {
409
+
410
+ if( is_array( $args['date'] ) ) {
411
+
412
+ if( ! empty( $args['date']['start'] ) ) {
413
+
414
+ $start = date( 'Y-m-d H:i:s', strtotime( $args['date']['start'] ) );
415
+
416
+ if( ! empty( $where ) ) {
417
+
418
+ $where .= " AND `date_created` >= '{$start}'";
419
+
420
+ } else {
421
+
422
+ $where .= " WHERE `date_created` >= '{$start}'";
423
+
424
+ }
425
+
426
+ }
427
+
428
+ if( ! empty( $args['date']['end'] ) ) {
429
+
430
+ $end = date( 'Y-m-d H:i:s', strtotime( $args['date']['end'] ) );
431
+
432
+ if( ! empty( $where ) ) {
433
+
434
+ $where .= " AND `date_created` <= '{$end}'";
435
+
436
+ } else {
437
+
438
+ $where .= " WHERE `date_created` <= '{$end}'";
439
+
440
+ }
441
+
442
+ }
443
+
444
+ } else {
445
+
446
+ $year = date( 'Y', strtotime( $args['date'] ) );
447
+ $month = date( 'm', strtotime( $args['date'] ) );
448
+ $day = date( 'd', strtotime( $args['date'] ) );
449
+
450
+ if( empty( $where ) ) {
451
+ $where .= " WHERE";
452
+ } else {
453
+ $where .= " AND";
454
+ }
455
+
456
+ $where .= " $year = YEAR ( date_created ) AND $month = MONTH ( date_created ) AND $day = DAY ( date_created )";
457
+ }
458
+
459
+ }
460
+
461
+ $args['orderby'] = ! array_key_exists( $args['orderby'], $this->get_columns() ) ? 'id' : $args['orderby'];
462
+
463
+ if( 'purchase_value' == $args['orderby'] ) {
464
+ $args['orderby'] = 'purchase_value+0';
465
+ }
466
+
467
+ $cache_key = md5( 'edd_customers_' . serialize( $args ) );
468
+
469
+ $customers = wp_cache_get( $cache_key, 'customers' );
470
+
471
+ if( $customers === false ) {
472
+ $customers = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $this->table_name $where ORDER BY {$args['orderby']} {$args['order']} LIMIT %d,%d;", absint( $args['offset'] ), absint( $args['number'] ) ) );
473
+ wp_cache_set( $cache_key, $customers, 'customers', 3600 );
474
+ }
475
+
476
+ return $customers;
477
+
478
+ }
479
+
480
+
481
+ /**
482
+ * Count the total number of customers in the database
483
+ *
484
+ * @access public
485
+ * @since 2.1
486
+ */
487
+ public function count( $args = array() ) {
488
+
489
+ global $wpdb;
490
+
491
+ $where = '';
492
+
493
+ if( ! empty( $args['date'] ) ) {
494
+
495
+ if( is_array( $args['date'] ) ) {
496
+
497
+ $start = date( 'Y-m-d H:i:s', strtotime( $args['date']['start'] ) );
498
+ $end = date( 'Y-m-d H:i:s', strtotime( $args['date']['end'] ) );
499
+
500
+ if( empty( $where ) ) {
501
+
502
+ $where .= " WHERE `date_created` >= '{$start}' AND `date_created` <= '{$end}'";
503
+
504
+ } else {
505
+
506
+ $where .= " AND `date_created` >= '{$start}' AND `date_created` <= '{$end}'";
507
+
508
+ }
509
+
510
+ } else {
511
+
512
+ $year = date( 'Y', strtotime( $args['date'] ) );
513
+ $month = date( 'm', strtotime( $args['date'] ) );
514
+ $day = date( 'd', strtotime( $args['date'] ) );
515
+
516
+ if( empty( $where ) ) {
517
+ $where .= " WHERE";
518
+ } else {
519
+ $where .= " AND";
520
+ }
521
+
522
+ $where .= " $year = YEAR ( date_created ) AND $month = MONTH ( date_created ) AND $day = DAY ( date_created )";
523
+ }
524
+
525
+ }
526
+
527
+
528
+ $cache_key = md5( 'edd_customers_count' . serialize( $args ) );
529
+
530
+ $count = wp_cache_get( $cache_key, 'customers' );
531
+
532
+ if( $count === false ) {
533
+ $count = $wpdb->get_var( "SELECT COUNT($this->primary_key) FROM " . $this->table_name . "{$where};" );
534
+ wp_cache_set( $cache_key, $count, 'customers', 3600 );
535
+ }
536
+
537
+ return absint( $count );
538
+
539
+ }
540
+
541
+ /**
542
+ * Create the table
543
+ *
544
+ * @access public
545
+ * @since 2.1
546
+ */
547
+ public function create_table() {
548
+
549
+ global $wpdb;
550
+
551
+ require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
552
+
553
+ $sql = "CREATE TABLE " . $this->table_name . " (
554
+ id bigint(20) NOT NULL AUTO_INCREMENT,
555
+ user_id bigint(20) NOT NULL,
556
+ email varchar(50) NOT NULL,
557
+ name mediumtext NOT NULL,
558
+ purchase_value mediumtext NOT NULL,
559
+ purchase_count bigint(20) NOT NULL,
560
+ payment_ids longtext NOT NULL,
561
+ notes longtext NOT NULL,
562
+ date_created datetime NOT NULL,
563
+ PRIMARY KEY (id),
564
+ UNIQUE KEY email (email),
565
+ KEY user (user_id)
566
+ ) CHARACTER SET utf8 COLLATE utf8_general_ci;";
567
+
568
+ dbDelta( $sql );
569
+
570
+ update_option( $this->table_name . '_db_version', $this->version );
571
+ }
572
+ }
includes/class-edd-db.php ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+
6
+ /**
7
+ * EDD DB base class
8
+ *
9
+ * @package EDD
10
+ * @subpackage Classes/EDD DB
11
+ * @copyright Copyright (c) 2015, Pippin Williamson
12
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
13
+ * @since 2.1
14
+ */
15
+ abstract class EDD_DB {
16
+
17
+ /**
18
+ * The name of our database table
19
+ *
20
+ * @access public
21
+ * @since 2.1
22
+ */
23
+ public $table_name;
24
+
25
+ /**
26
+ * The version of our database table
27
+ *
28
+ * @access public
29
+ * @since 2.1
30
+ */
31
+ public $version;
32
+
33
+ /**
34
+ * The name of the primary column
35
+ *
36
+ * @access public
37
+ * @since 2.1
38
+ */
39
+ public $primary_key;
40
+
41
+ /**
42
+ * Get things started
43
+ *
44
+ * @access public
45
+ * @since 2.1
46
+ */
47
+ public function __construct() {}
48
+
49
+ /**
50
+ * Whitelist of columns
51
+ *
52
+ * @access public
53
+ * @since 2.1
54
+ * @return array
55
+ */
56
+ public function get_columns() {
57
+ return array();
58
+ }
59
+
60
+ /**
61
+ * Default column values
62
+ *
63
+ * @access public
64
+ * @since 2.1
65
+ * @return array
66
+ */
67
+ public function get_column_defaults() {
68
+ return array();
69
+ }
70
+
71
+ /**
72
+ * Retrieve a row by the primary key
73
+ *
74
+ * @access public
75
+ * @since 2.1
76
+ * @return object
77
+ */
78
+ public function get( $row_id ) {
79
+ global $wpdb;
80
+ return $wpdb->get_row( "SELECT * FROM $this->table_name WHERE $this->primary_key = $row_id LIMIT 1;" );
81
+ }
82
+
83
+ /**
84
+ * Retrieve a row by a specific column / value
85
+ *
86
+ * @access public
87
+ * @since 2.1
88
+ * @return object
89
+ */
90
+ public function get_by( $column, $row_id ) {
91
+ global $wpdb;
92
+ return $wpdb->get_row( "SELECT * FROM $this->table_name WHERE $column = '$row_id' LIMIT 1;" );
93
+ }
94
+
95
+ /**
96
+ * Retrieve a specific column's value by the primary key
97
+ *
98
+ * @access public
99
+ * @since 2.1
100
+ * @return string
101
+ */
102
+ public function get_column( $column, $row_id ) {
103
+ global $wpdb;
104
+ return $wpdb->get_var( "SELECT $column FROM $this->table_name WHERE $this->primary_key = $row_id LIMIT 1;" );
105
+ }
106
+
107
+ /**
108
+ * Retrieve a specific column's value by the the specified column / value
109
+ *
110
+ * @access public
111
+ * @since 2.1
112
+ * @return string
113
+ */
114
+ public function get_column_by( $column, $column_where, $column_value ) {
115
+ global $wpdb;
116
+ return $wpdb->get_var( "SELECT $column FROM $this->table_name WHERE $column_where = '$column_value' LIMIT 1;" );
117
+ }
118
+
119
+ /**
120
+ * Insert a new row
121
+ *
122
+ * @access public
123
+ * @since 2.1
124
+ * @return int
125
+ */
126
+ public function insert( $data, $type = '' ) {
127
+ global $wpdb;
128
+
129
+ // Set default values
130
+ $data = wp_parse_args( $data, $this->get_column_defaults() );
131
+
132
+ do_action( 'edd_pre_insert_' . $type, $data );
133
+
134
+ // Initialise column format array
135
+ $column_formats = $this->get_columns();
136
+
137
+ // Force fields to lower case
138
+ $data = array_change_key_case( $data );
139
+
140
+ // White list columns
141
+ $data = array_intersect_key( $data, $column_formats );
142
+
143
+ // Reorder $column_formats to match the order of columns given in $data
144
+ $data_keys = array_keys( $data );
145
+ $column_formats = array_merge( array_flip( $data_keys ), $column_formats );
146
+
147
+ $wpdb->insert( $this->table_name, $data, $column_formats );
148
+
149
+ do_action( 'edd_post_insert_' . $type, $wpdb->insert_id, $data );
150
+
151
+ return $wpdb->insert_id;
152
+ }
153
+
154
+ /**
155
+ * Update a row
156
+ *
157
+ * @access public
158
+ * @since 2.1
159
+ * @return bool
160
+ */
161
+ public function update( $row_id, $data = array(), $where = '' ) {
162
+
163
+ global $wpdb;
164
+
165
+ // Row ID must be positive integer
166
+ $row_id = absint( $row_id );
167
+
168
+ if( empty( $row_id ) ) {
169
+ return false;
170
+ }
171
+
172
+ if( empty( $where ) ) {
173
+ $where = $this->primary_key;
174
+ }
175
+
176
+ // Initialise column format array
177
+ $column_formats = $this->get_columns();
178
+
179
+ // Force fields to lower case
180
+ $data = array_change_key_case( $data );
181
+
182
+ // White list columns
183
+ $data = array_intersect_key( $data, $column_formats );
184
+
185
+ // Reorder $column_formats to match the order of columns given in $data
186
+ $data_keys = array_keys( $data );
187
+ $column_formats = array_merge( array_flip( $data_keys ), $column_formats );
188
+
189
+ if ( false === $wpdb->update( $this->table_name, $data, array( $where => $row_id ), $column_formats ) ) {
190
+ return false;
191
+ }
192
+
193
+ return true;
194
+ }
195
+
196
+ /**
197
+ * Delete a row identified by the primary key
198
+ *
199
+ * @access public
200
+ * @since 2.1
201
+ * @return bool
202
+ */
203
+ public function delete( $row_id = 0 ) {
204
+
205
+ global $wpdb;
206
+
207
+ // Row ID must be positive integer
208
+ $row_id = absint( $row_id );
209
+
210
+ if( empty( $row_id ) ) {
211
+ return false;
212
+ }
213
+
214
+ if ( false === $wpdb->query( $wpdb->prepare( "DELETE FROM $this->table_name WHERE $this->primary_key = %d", $row_id ) ) ) {
215
+ return false;
216
+ }
217
+
218
+ return true;
219
+ }
220
+
221
+ }
includes/class-edd-download.php ADDED
@@ -0,0 +1,803 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Download Object
4
+ *
5
+ * @package EDD
6
+ * @subpackage Classes/Download
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
+ * @since 2.2
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
+
15
+ /**
16
+ * EDD_Download Class
17
+ *
18
+ * @since 2.2
19
+ */
20
+ class EDD_Download {
21
+
22
+ /**
23
+ * The download ID
24
+ *
25
+ * @since 2.2
26
+ */
27
+ public $ID = 0;
28
+
29
+ /**
30
+ * The download price
31
+ *
32
+ * @since 2.2
33
+ */
34
+ private $price;
35
+
36
+ /**
37
+ * The download prices, if Variable Prices are enabled
38
+ *
39
+ * @since 2.2
40
+ */
41
+ private $prices;
42
+
43
+ /**
44
+ * The download files
45
+ *
46
+ * @since 2.2
47
+ */
48
+ private $files;
49
+
50
+ /**
51
+ * The download's file download limit
52
+ *
53
+ * @since 2.2
54
+ */
55
+ private $file_download_limit;
56
+
57
+ /**
58
+ * The download type, default or bundle
59
+ *
60
+ * @since 2.2
61
+ */
62
+ private $type;
63
+
64
+ /**
65
+ * The bundled downloads, if this is a bundle type
66
+ *
67
+ * @since 2.2
68
+ */
69
+ private $bundled_downloads;
70
+
71
+ /**
72
+ * The download's sale count
73
+ *
74
+ * @since 2.2
75
+ */
76
+ private $sales;
77
+
78
+ /**
79
+ * The download's total earnings
80
+ *
81
+ * @since 2.2
82
+ */
83
+ private $earnings;
84
+
85
+ /**
86
+ * The download's notes
87
+ *
88
+ * @since 2.2
89
+ */
90
+ private $notes;
91
+
92
+ /**
93
+ * The download sku
94
+ *
95
+ * @since 2.2
96
+ */
97
+ private $sku;
98
+
99
+ /**
100
+ * The download's purchase button behavior
101
+ *
102
+ * @since 2.2
103
+ */
104
+ private $button_behavior;
105
+
106
+ /**
107
+ * Declare the default properities in WP_Post as we can't extend it
108
+ * Anything we've delcared above has been removed.
109
+ */
110
+ public $post_author = 0;
111
+ public $post_date = '0000-00-00 00:00:00';
112
+ public $post_date_gmt = '0000-00-00 00:00:00';
113
+ public $post_content = '';
114
+ public $post_title = '';
115
+ public $post_excerpt = '';
116
+ public $post_status = 'publish';
117
+ public $comment_status = 'open';
118
+ public $ping_status = 'open';
119
+ public $post_password = '';
120
+ public $post_name = '';
121
+ public $to_ping = '';
122
+ public $pinged = '';
123
+ public $post_modified = '0000-00-00 00:00:00';
124
+ public $post_modified_gmt = '0000-00-00 00:00:00';
125
+ public $post_content_filtered = '';
126
+ public $post_parent = 0;
127
+ public $guid = '';
128
+ public $menu_order = 0;
129
+ public $post_mime_type = '';
130
+ public $comment_count = 0;
131
+ public $filter;
132
+
133
+ /**
134
+ * Get things going
135
+ *
136
+ * @since 2.2
137
+ */
138
+ public function __construct( $_id = false, $_args = array() ) {
139
+
140
+ $download = WP_Post::get_instance( $_id );
141
+
142
+ return $this->setup_download( $download );
143
+
144
+ }
145
+
146
+ /**
147
+ * Given the download data, let's set the variables
148
+ *
149
+ * @since 2.3.6
150
+ * @param object $download The Download Object
151
+ * @return bool If the setup was successful or not
152
+ */
153
+ private function setup_download( $download ) {
154
+
155
+ if( ! is_object( $download ) ) {
156
+ return false;
157
+ }
158
+
159
+ if( ! is_a( $download, 'WP_Post' ) ) {
160
+ return false;
161
+ }
162
+
163
+ if( 'download' !== $download->post_type ) {
164
+ return false;
165
+ }
166
+
167
+ foreach ( $download as $key => $value ) {
168
+
169
+ switch ( $key ) {
170
+
171
+ default:
172
+ $this->$key = $value;
173
+ break;
174
+
175
+ }
176
+
177
+ }
178
+
179
+ return true;
180
+
181
+ }
182
+
183
+ /**
184
+ * Magic __get function to dispatch a call to retrieve a private property
185
+ *
186
+ * @since 2.2
187
+ */
188
+ public function __get( $key ) {
189
+
190
+ if( method_exists( $this, 'get_' . $key ) ) {
191
+
192
+ return call_user_func( array( $this, 'get_' . $key ) );
193
+
194
+ } else {
195
+
196
+ return new WP_Error( 'edd-download-invalid-property', sprintf( __( 'Can\'t get property %s', 'edd' ), $key ) );
197
+
198
+ }
199
+
200
+ }
201
+
202
+ /**
203
+ * Creates a download
204
+ *
205
+ * @since 2.3.6
206
+ * @param array $data Array of attributes for a download
207
+ * @return mixed false if data isn't passed and class not instantiated for creation, or New Download ID
208
+ */
209
+ public function create( $data = array() ) {
210
+
211
+ if ( $this->id != 0 ) {
212
+ return false;
213
+ }
214
+
215
+ $defaults = array(
216
+ 'post_type' => 'download',
217
+ 'post_status' => 'draft',
218
+ 'post_title' => __( 'New Download Product', 'edd' )
219
+ );
220
+
221
+ $args = wp_parse_args( $data, $defaults );
222
+
223
+ do_action( 'edd_download_pre_create', $args );
224
+
225
+ $id = wp_insert_post( $args, true );
226
+
227
+ $download = WP_Post::get_instance( $id );
228
+
229
+ do_action( 'edd_download_post_create', $id, $args );
230
+
231
+ return $this->setup_download( $download );
232
+
233
+ }
234
+
235
+ /**
236
+ * Retrieve the ID
237
+ *
238
+ * @since 2.2
239
+ * @return int
240
+ */
241
+ public function get_ID() {
242
+
243
+ return $this->ID;
244
+
245
+ }
246
+
247
+ /**
248
+ * Retrieve the price
249
+ *
250
+ * @since 2.2
251
+ * @return float
252
+ */
253
+ public function get_price() {
254
+
255
+ if ( ! isset( $this->price ) ) {
256
+
257
+ $this->price = get_post_meta( $this->ID, 'edd_price', true );
258
+
259
+ if ( $this->price ) {
260
+
261
+ $this->price = edd_sanitize_amount( $this->price );
262
+
263
+ } else {
264
+
265
+ $this->price = 0;
266
+
267
+ }
268
+
269
+ }
270
+
271
+ /**
272
+ * Override the download price.
273
+ *
274
+ * @since 2.2
275
+ *
276
+ * @param string $price The download price(s).
277
+ * @param string|int $id The downloads ID.
278
+ */
279
+ return apply_filters( 'edd_get_download_price', $this->price, $this->ID );
280
+
281
+ }
282
+
283
+ /**
284
+ * Retrieve the variable prices
285
+ *
286
+ * @since 2.2
287
+ * @return array
288
+ */
289
+ public function get_prices() {
290
+
291
+ if( ! isset( $this->prices ) ) {
292
+
293
+ $this->prices = get_post_meta( $this->ID, 'edd_variable_prices', true );
294
+
295
+ }
296
+
297
+ /**
298
+ * Override variable prices
299
+ *
300
+ * @since 2.2
301
+ *
302
+ * @param array $prices The array of variables prices.
303
+ * @param int|string The ID of the download.
304
+ */
305
+ return apply_filters( 'edd_get_variable_prices', $this->prices, $this->ID );
306
+
307
+ }
308
+
309
+ /**
310
+ * Determine if single price mode is enabled or disabled
311
+ *
312
+ * @since 2.2
313
+ * @return bool
314
+ */
315
+ public function is_single_price_mode() {
316
+
317
+ $ret = get_post_meta( $this->ID, '_edd_price_options_mode', true );
318
+
319
+ /**
320
+ * Override the price mode for a download when checking if is in single price mode.
321
+ *
322
+ * @since 2.3
323
+ *
324
+ * @param bool $ret Is download in single price mode?
325
+ * @param int|string The ID of the download.
326
+ */
327
+ return (bool) apply_filters( 'edd_single_price_option_mode', $ret, $this->ID );
328
+
329
+ }
330
+
331
+ /**
332
+ * Determine if the download has variable prices enabled
333
+ *
334
+ * @since 2.2
335
+ * @return bool
336
+ */
337
+ public function has_variable_prices() {
338
+
339
+ $ret = get_post_meta( $this->ID, '_variable_pricing', true );
340
+
341
+ /**
342
+ * Override whether the download has variables prices.
343
+ *
344
+ * @since 2.3
345
+ *
346
+ * @param bool $ret Does download have variable prices?
347
+ * @param int|string The ID of the download.
348
+ */
349
+ return (bool) apply_filters( 'edd_has_variable_prices', $ret, $this->ID );
350
+
351
+ }
352
+
353
+ /**
354
+ * Retrieve the file downloads
355
+ *
356
+ * @since 2.2
357
+ * @param integer $variable_price_id
358
+ * @return array
359
+ */
360
+ public function get_files( $variable_price_id = null ) {
361
+
362
+ if( ! isset( $this->files ) ) {
363
+
364
+ $this->files = array();
365
+
366
+ // Bundled products are not allowed to have files
367
+ if( $this->is_bundled_download() ) {
368
+ return $this->files;
369
+ }
370
+
371
+ $download_files = get_post_meta( $this->ID, 'edd_download_files', true );
372
+
373
+ if ( $download_files ) {
374
+
375
+
376
+ if ( ! is_null( $variable_price_id ) && $this->has_variable_prices() ) {
377
+
378
+ foreach ( $download_files as $key => $file_info ) {
379
+
380
+ if ( isset( $file_info['condition'] ) ) {
381
+
382
+ if ( $file_info['condition'] == $variable_price_id || 'all' === $file_info['condition'] ) {
383
+
384
+ $this->files[ $key ] = $file_info;
385
+
386
+ }
387
+
388
+ }
389
+
390
+ }
391
+
392
+ } else {
393
+
394
+ $this->files = $download_files;
395
+
396
+ }
397
+
398
+ }
399
+
400
+ }
401
+
402
+ return apply_filters( 'edd_download_files', $this->files, $this->ID, $variable_price_id );
403
+
404
+ }
405
+
406
+ /**
407
+ * Retrieve the file download limit
408
+ *
409
+ * @since 2.2
410
+ * @return int
411
+ */
412
+ public function get_file_download_limit() {
413
+
414
+ if( ! isset( $this->file_download_limit ) ) {
415
+
416
+ $ret = 0;
417
+ $limit = get_post_meta( $this->ID, '_edd_download_limit', true );
418
+ $global = edd_get_option( 'file_download_limit', 0 );
419
+
420
+ if ( ! empty( $limit ) || ( is_numeric( $limit ) && (int)$limit == 0 ) ) {
421
+
422
+ // Download specific limit
423
+ $ret = absint( $limit );
424
+
425
+ } else {
426
+
427
+ // Global limit
428
+ $ret = strlen( $limit ) == 0 || $global ? $global : 0;
429
+
430
+ }
431
+
432
+ $this->file_download_limit = $ret;
433
+
434
+ }
435
+
436
+ return absint( apply_filters( 'edd_file_download_limit', $this->file_download_limit, $this->ID ) );
437
+
438
+ }
439
+
440
+ /**
441
+ * Retrieve the price option that has access to the specified file
442
+ *
443
+ * @since 2.2
444
+ * @return int|string
445
+ */
446
+ public function get_file_price_condition( $file_key = 0 ) {
447
+
448
+ $files = edd_get_download_files( $this->ID );
449
+ $condition = isset( $files[ $file_key ]['condition']) ? $files[ $file_key ]['condition'] : 'all';
450
+
451
+ return apply_filters( 'edd_get_file_price_condition', $condition, $this->ID, $files );
452
+
453
+ }
454
+
455
+ /**
456
+ * Retrieve the download type, default or bundle
457
+ *
458
+ * @since 2.2
459
+ * @return string
460
+ */
461
+ public function get_type() {
462
+
463
+ if( ! isset( $this->type ) ) {
464
+
465
+ $this->type = get_post_meta( $this->ID, '_edd_product_type', true );
466
+
467
+ if( empty( $this->type ) ) {
468
+ $this->type = 'default';
469
+ }
470
+
471
+ }
472
+
473
+ return apply_filters( 'edd_get_download_type', $this->type, $this->ID );
474
+
475
+ }
476
+
477
+ /**
478
+ * Determine if this is a bundled download
479
+ *
480
+ * @since 2.2
481
+ * @return bool
482
+ */
483
+ public function is_bundled_download() {
484
+ return 'bundle' === $this->get_type();
485
+ }
486
+
487
+ /**
488
+ * Retrieves the Download IDs that are bundled with this Download
489
+ *
490
+ * @since 2.2
491
+ * @return array
492
+ */
493
+ public function get_bundled_downloads() {
494
+
495
+ if( ! isset( $this->bundled_downloads ) ) {
496
+
497
+ $this->bundled_downloads = (array) get_post_meta( $this->ID, '_edd_bundled_products', true );
498
+
499
+ }
500
+
501
+ return (array) apply_filters( 'edd_get_bundled_products', array_filter( $this->bundled_downloads ), $this->ID );
502
+
503
+ }
504
+
505
+ /**
506
+ * Retrieve the download notes
507
+ *
508
+ * @since 2.2
509
+ * @return string
510
+ */
511
+ public function get_notes() {
512
+
513
+ if( ! isset( $this->notes ) ) {
514
+
515
+ $this->notes = get_post_meta( $this->ID, 'edd_product_notes', true );
516
+
517
+ }
518
+
519
+ return (string) apply_filters( 'edd_product_notes', $this->notes, $this->ID );
520
+
521
+ }
522
+
523
+ /**
524
+ * Retrieve the download sku
525
+ *
526
+ * @since 2.2
527
+ * @return string
528
+ */
529
+ public function get_sku() {
530
+
531
+ if( ! isset( $this->sku ) ) {
532
+
533
+ $this->sku = get_post_meta( $this->ID, 'edd_sku', true );
534
+
535
+ if ( empty( $this->sku ) ) {
536
+ $this->sku = '-';
537
+ }
538
+
539
+ }
540
+
541
+ return apply_filters( 'edd_get_download_sku', $this->sku, $this->ID );
542
+
543
+ }
544
+
545
+ /**
546
+ * Retrieve the purchase button behavior
547
+ *
548
+ * @since 2.2
549
+ * @return string
550
+ */
551
+ public function get_button_behavior() {
552
+
553
+ if( ! isset( $this->button_behavior ) ) {
554
+
555
+ $this->button_behavior = get_post_meta( $this->ID, '_edd_button_behavior', true );
556
+
557
+ if( empty( $this->button_behavior ) || ! edd_shop_supports_buy_now() ) {
558
+
559
+ $this->button_behavior = 'add_to_cart';
560
+
561
+ }
562
+
563
+ }
564
+
565
+ return apply_filters( 'edd_get_download_button_behavior', $this->button_behavior, $this->ID );
566
+
567
+ }
568
+
569
+ /**
570
+ * Retrieve the sale count for the download
571
+ *
572
+ * @since 2.2
573
+ * @return int
574
+ */
575
+ public function get_sales() {
576
+
577
+ if( ! isset( $this->sales ) ) {
578
+
579
+ if ( '' == get_post_meta( $this->ID, '_edd_download_sales', true ) ) {
580
+ add_post_meta( $this->ID, '_edd_download_sales', 0 );
581
+ } // End if
582
+
583
+ $this->sales = get_post_meta( $this->ID, '_edd_download_sales', true );
584
+
585
+ if ( $this->sales < 0 ) {
586
+ // Never let sales be less than zero
587
+ $this->sales = 0;
588
+ }
589
+
590
+ }
591
+
592
+ return $this->sales;
593
+
594
+ }
595
+
596
+ /**
597
+ * Increment the sale count by one
598
+ *
599
+ * @since 2.2
600
+ * @param int $quantity The quantity to increase the sales by
601
+ * @return int|false
602
+ */
603
+ public function increase_sales( $quantity = 1 ) {
604
+
605
+ $sales = edd_get_download_sales_stats( $this->ID );
606
+ $quantity = absint( $quantity );
607
+ $total_sales = $sales + $quantity;
608
+
609
+ if ( $this->update_meta( '_edd_download_sales', $total_sales ) ) {
610
+
611
+ $this->sales = $total_sales;
612
+ return $this->sales;
613
+
614
+ }
615
+
616
+ return false;
617
+ }
618
+
619
+ /**
620
+ * Decrement the sale count by one
621
+ *
622
+ * @since 2.2
623
+ * @param int $quantity The quantity to decrease by
624
+ * @return int|false
625
+ */
626
+ public function decrease_sales( $quantity = 1 ) {
627
+
628
+ $sales = edd_get_download_sales_stats( $this->ID );
629
+
630
+ // Only decrease if not already zero
631
+ if ( $sales > 0 ) {
632
+
633
+ $quantity = absint( $quantity );
634
+ $total_sales = $sales - $quantity;
635
+
636
+ if ( $this->update_meta( '_edd_download_sales', $total_sales ) ) {
637
+
638
+ $this->sales = $total_sales;
639
+ return $this->sales;
640
+
641
+ }
642
+
643
+ }
644
+
645
+ return false;
646
+
647
+ }
648
+
649
+ /**
650
+ * Retrieve the total earnings for the download
651
+ *
652
+ * @since 2.2
653
+ * @return float
654
+ */
655
+ public function get_earnings() {
656
+
657
+ if ( ! isset( $this->earnings ) ) {
658
+
659
+ if ( '' == get_post_meta( $this->ID, '_edd_download_earnings', true ) ) {
660
+ add_post_meta( $this->ID, '_edd_download_earnings', 0 );
661
+ }
662
+
663
+ $this->earnings = get_post_meta( $this->ID, '_edd_download_earnings', true );
664
+
665
+ if ( $this->earnings < 0 ) {
666
+ // Never let earnings be less than zero
667
+ $this->earnings = 0;
668
+ }
669
+
670
+ }
671
+
672
+ return $this->earnings;
673
+
674
+ }
675
+
676
+ /**
677
+ * Increase the earnings by the given amount
678
+ *
679
+ * @since 2.2
680
+ * @return float|false
681
+ */
682
+ public function increase_earnings( $amount = 0 ) {
683
+
684
+ $earnings = edd_get_download_earnings_stats( $this->ID );
685
+ $new_amount = $earnings + (float) $amount;
686
+
687
+ if ( $this->update_meta( '_edd_download_earnings', $new_amount ) ) {
688
+
689
+ $this->earnings = $new_amount;
690
+ return $this->earnings;
691
+
692
+ }
693
+
694
+ return false;
695
+
696
+ }
697
+
698
+ /**
699
+ * Decrease the earnings by the given amount
700
+ *
701
+ * @since 2.2
702
+ * @param integer $amount
703
+ * @return float|false
704
+ */
705
+ public function decrease_earnings( $amount ) {
706
+
707
+ $earnings = edd_get_download_earnings_stats( $this->ID );
708
+
709
+ if ( $earnings > 0 ) {
710
+
711
+ // Only decrease if greater than zero
712
+ $new_amount = $earnings - (float) $amount;
713
+
714
+ if ( $this->update_meta( '_edd_download_earnings', $new_amount ) ) {
715
+
716
+ $this->earnings = $new_amount;
717
+ return $this->earnings;
718
+
719
+ }
720
+
721
+ }
722
+
723
+ return false;
724
+
725
+ }
726
+
727
+ /**
728
+ * Determine if the download is free or if the given price ID is free
729
+ *
730
+ * @since 2.2
731
+ * @return bool
732
+ */
733
+ public function is_free( $price_id = false ) {
734
+
735
+ $is_free = false;
736
+ $variable_pricing = edd_has_variable_prices( $this->ID );
737
+
738
+ if ( $variable_pricing && ! is_null( $price_id ) && $price_id !== false ) {
739
+
740
+ $price = edd_get_price_option_amount( $this->ID, $price_id );
741
+
742
+ } elseif ( $variable_pricing && $price_id === false ) {
743
+
744
+ $lowest_price = (float) edd_get_lowest_price_option( $this->ID );
745
+ $highest_price = (float) edd_get_highest_price_option( $this->ID );
746
+
747
+ if ( $lowest_price === 0.00 && $highest_price === 0.00 ) {
748
+ $price = 0;
749
+ }
750
+
751
+ } elseif( ! $variable_pricing ) {
752
+
753
+ $price = get_post_meta( $this->ID, 'edd_price', true );
754
+
755
+ }
756
+
757
+ if( isset( $price ) && (float) $price == 0 ) {
758
+ $is_free = true;
759
+ }
760
+
761
+ return (bool) apply_filters( 'edd_is_free_download', $is_free, $this->ID, $price_id );
762
+
763
+ }
764
+
765
+ /**
766
+ * Updates a single meta entry for the download
767
+ *
768
+ * @since 2.3
769
+ * @access private
770
+ * @param string $meta_key The meta_key to update
771
+ * @param string|array|object $meta_value The value to put into the meta
772
+ * @return bool The result of the update query
773
+ */
774
+ private function update_meta( $meta_key = '', $meta_value = '' ) {
775
+
776
+ global $wpdb;
777
+
778
+ if ( empty( $meta_key ) || empty( $meta_value ) ) {
779
+ return false;
780
+ }
781
+
782
+ // Make sure if it needs to be serialized, we do
783
+ $meta_value = maybe_serialize( $meta_value );
784
+
785
+ if ( is_numeric( $meta_value ) ) {
786
+ $value_type = is_float( $meta_value ) ? '%f' : '%d';
787
+ } else {
788
+ $value_type = "'%s'";
789
+ }
790
+
791
+ $sql = $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_value = $value_type WHERE post_id = $this->ID AND meta_key = '%s'", $meta_value, $meta_key );
792
+
793
+ if ( $wpdb->query( $sql ) ) {
794
+
795
+ clean_post_cache( $this->ID );
796
+ return true;
797
+
798
+ }
799
+
800
+ return false;
801
+ }
802
+
803
+ }
includes/class-edd-fees.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Classes/Fees
9
- * @copyright Copyright (c) 2012, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.5
12
  */
@@ -58,17 +58,19 @@ class EDD_Fees {
58
  'label' => $label,
59
  'id' => $id,
60
  'type' => $type,
61
- 'no_tax' => false
 
62
  );
63
 
64
  } else {
65
 
66
  $defaults = array(
67
- 'amount' => 0,
68
- 'label' => '',
69
- 'id' => '',
70
- 'no_tax' => false,
71
- 'type' => 'fee'
 
72
  );
73
 
74
  $args = wp_parse_args( $args, $defaults );
@@ -79,6 +81,10 @@ class EDD_Fees {
79
 
80
  }
81
 
 
 
 
 
82
  $fees = $this->get_fees( 'all' );
83
 
84
  // Determine the key
@@ -110,14 +116,14 @@ class EDD_Fees {
110
  * @return array $fees
111
  */
112
  public function remove_fee( $id = '' ) {
 
113
  $fees = $this->get_fees( 'all' );
114
 
115
  if ( isset( $fees[ $id ] ) ) {
116
  unset( $fees[ $id ] );
 
117
  }
118
 
119
- EDD()->session->set( 'edd_cart_fees', $fees );
120
-
121
  return $fees;
122
  }
123
 
@@ -131,6 +137,15 @@ class EDD_Fees {
131
  * @return bool
132
  */
133
  public function has_fees( $type = 'fee' ) {
 
 
 
 
 
 
 
 
 
134
  $fees = $this->get_fees( $type );
135
  return ! empty( $fees ) && is_array( $fees );
136
  }
@@ -141,18 +156,67 @@ class EDD_Fees {
141
  * @access public
142
  * @since 1.5
143
  * @param string $type Fee type, "fee" or "item"
 
144
  * @uses EDD_Session::get()
145
  * @return mixed array|bool
146
  */
147
- public function get_fees( $type = 'fee' ) {
 
148
  $fees = EDD()->session->get( 'edd_cart_fees' );
 
 
 
 
 
 
149
  if( ! empty( $fees ) && ! empty( $type ) && 'all' !== $type ) {
 
150
  foreach( $fees as $key => $fee ) {
 
151
  if( ! empty( $fee['type'] ) && $type != $fee['type'] ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  unset( $fees[ $key ] );
 
153
  }
 
154
  }
 
155
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  return ! empty( $fees ) ? $fees : array();
157
  }
158
 
@@ -207,10 +271,11 @@ class EDD_Fees {
207
  * @since 1.5
208
  * @uses EDD_Fees::get_fees()
209
  * @uses EDD_Fees::has_fees()
 
210
  * @return float $total Total fee amount
211
  */
212
- public function total() {
213
- $fees = $this->get_fees( 'all' );
214
  $total = (float) 0.00;
215
 
216
  if ( $this->has_fees( 'all' ) ) {
6
  *
7
  * @package EDD
8
  * @subpackage Classes/Fees
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.5
12
  */
58
  'label' => $label,
59
  'id' => $id,
60
  'type' => $type,
61
+ 'no_tax' => false,
62
+ 'download_id' => 0
63
  );
64
 
65
  } else {
66
 
67
  $defaults = array(
68
+ 'amount' => 0,
69
+ 'label' => '',
70
+ 'id' => '',
71
+ 'no_tax' => false,
72
+ 'type' => 'fee',
73
+ 'download_id' => 0
74
  );
75
 
76
  $args = wp_parse_args( $args, $defaults );
81
 
82
  }
83
 
84
+ if( 'item' === $args['type'] && ! empty( $args['download_id'] ) ) {
85
+ unset( $args['download_id'] );
86
+ }
87
+
88
  $fees = $this->get_fees( 'all' );
89
 
90
  // Determine the key
116
  * @return array $fees
117
  */
118
  public function remove_fee( $id = '' ) {
119
+
120
  $fees = $this->get_fees( 'all' );
121
 
122
  if ( isset( $fees[ $id ] ) ) {
123
  unset( $fees[ $id ] );
124
+ EDD()->session->set( 'edd_cart_fees', $fees );
125
  }
126
 
 
 
127
  return $fees;
128
  }
129
 
137
  * @return bool
138
  */
139
  public function has_fees( $type = 'fee' ) {
140
+
141
+ if( 'all' == $type || 'fee' == $type ) {
142
+
143
+ if( ! edd_get_cart_contents() ) {
144
+ $type = 'item';
145
+ }
146
+
147
+ }
148
+
149
  $fees = $this->get_fees( $type );
150
  return ! empty( $fees ) && is_array( $fees );
151
  }
156
  * @access public
157
  * @since 1.5
158
  * @param string $type Fee type, "fee" or "item"
159
+ * @param int $download_id The download ID whose fees to retrieve
160
  * @uses EDD_Session::get()
161
  * @return mixed array|bool
162
  */
163
+ public function get_fees( $type = 'fee', $download_id = 0 ) {
164
+
165
  $fees = EDD()->session->get( 'edd_cart_fees' );
166
+
167
+ if( ! edd_get_cart_contents() ) {
168
+ // We can only get item type fees when the cart is empty
169
+ $type = 'item';
170
+ }
171
+
172
  if( ! empty( $fees ) && ! empty( $type ) && 'all' !== $type ) {
173
+
174
  foreach( $fees as $key => $fee ) {
175
+
176
  if( ! empty( $fee['type'] ) && $type != $fee['type'] ) {
177
+
178
+ unset( $fees[ $key ] );
179
+
180
+ }
181
+
182
+ }
183
+
184
+ }
185
+
186
+ if( ! empty( $fees ) && ! empty( $download_id ) ) {
187
+
188
+ // Remove fees that don't belong to the specified Download
189
+ foreach( $fees as $key => $fee ) {
190
+
191
+ if( (int) $download_id !== (int) $fee['download_id'] ) {
192
+
193
  unset( $fees[ $key ] );
194
+
195
  }
196
+
197
  }
198
+
199
  }
200
+
201
+ if( ! empty( $fees ) ) {
202
+
203
+ // Remove fees that belong to a specific download but are not in the cart
204
+ foreach( $fees as $key => $fee ) {
205
+
206
+ if( empty( $fee['download_id'] ) ) {
207
+ continue;
208
+ }
209
+
210
+ if( ! edd_item_in_cart( $fee['download_id'] ) ) {
211
+
212
+ unset( $fees[ $key ] );
213
+
214
+ }
215
+
216
+ }
217
+
218
+ }
219
+
220
  return ! empty( $fees ) ? $fees : array();
221
  }
222
 
271
  * @since 1.5
272
  * @uses EDD_Fees::get_fees()
273
  * @uses EDD_Fees::has_fees()
274
+ * @param int $download_id The download ID whose fees to retrieve
275
  * @return float $total Total fee amount
276
  */
277
+ public function total( $download_id = 0 ) {
278
+ $fees = $this->get_fees( 'all', $download_id );
279
  $total = (float) 0.00;
280
 
281
  if ( $this->has_fees( 'all' ) ) {
includes/class-edd-html-elements.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Classes/HTML
9
- * @copyright Copyright (c) 2012, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.5
12
  */
@@ -26,8 +26,7 @@ class EDD_HTML_Elements {
26
  *
27
  * @access public
28
  * @since 1.5
29
- * @param string $name Name attribute of the dropdown
30
- * @param int $selected Download to select automatically
31
  * @return string $output Product dropdown
32
  */
33
  public function product_dropdown( $args = array() ) {
@@ -38,17 +37,34 @@ class EDD_HTML_Elements {
38
  'class' => '',
39
  'multiple' => false,
40
  'selected' => 0,
41
- 'chosen' => false
 
 
 
42
  );
43
 
44
  $args = wp_parse_args( $args, $defaults );
45
 
46
- $products = get_posts( array(
47
  'post_type' => 'download',
48
  'orderby' => 'title',
49
  'order' => 'ASC',
50
- 'posts_per_page' => 30
51
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  $options = array();
54
 
@@ -67,8 +83,8 @@ class EDD_HTML_Elements {
67
  $options[$item] = get_the_title( $item );
68
  }
69
  }
70
- } else {
71
- if( ! in_array( $args['selected'], $options ) ) {
72
  $options[$args['selected']] = get_the_title( $args['selected'] );
73
  }
74
  }
@@ -79,6 +95,78 @@ class EDD_HTML_Elements {
79
  'id' => $args['id'],
80
  'class' => $args['class'],
81
  'options' => $options,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  'multiple' => $args['multiple'],
83
  'chosen' => $args['chosen'],
84
  'show_option_all' => false,
@@ -102,7 +190,7 @@ class EDD_HTML_Elements {
102
  $args = array( 'nopaging' => true );
103
 
104
  if ( ! empty( $status ) )
105
- $args[ 'post_status' ] = $status;
106
 
107
  $discounts = edd_get_discounts( $args );
108
  $options = array();
@@ -161,16 +249,20 @@ class EDD_HTML_Elements {
161
  * @since 1.5.2
162
  * @param string $name Name attribute of the dropdown
163
  * @param int $selected Year to select automatically
 
 
164
  * @return string $output Year dropdown
165
  */
166
- public function year_dropdown( $name = 'year', $selected = 0 ) {
167
- $current = date( 'Y' );
168
- $year = $current - 5;
169
- $selected = empty( $selected ) ? date( 'Y' ) : $selected;
170
-
171
- while ( $year <= $current ) {
172
- $options[ absint( $year ) ] = $year;
173
- $year++;
 
 
174
  }
175
 
176
  $output = $this->select( array(
@@ -231,6 +323,7 @@ class EDD_HTML_Elements {
231
  'id' => '',
232
  'selected' => 0,
233
  'chosen' => false,
 
234
  'multiple' => false,
235
  'show_option_all' => _x( 'All', 'all dropdown items', 'edd' ),
236
  'show_option_none' => _x( 'None', 'no dropdown items', 'edd' )
@@ -249,28 +342,35 @@ class EDD_HTML_Elements {
249
  $args['class'] .= ' edd-select-chosen';
250
  }
251
 
252
- $output = '<select name="' . esc_attr( $args[ 'name' ] ) . '" id="' . esc_attr( sanitize_key( str_replace( '-', '_', $args[ 'id' ] ) ) ) . '" class="edd-select ' . esc_attr( $args[ 'class'] ) . '"' . $multiple . '>';
 
 
 
 
253
 
254
- if ( ! empty( $args[ 'options' ] ) ) {
255
- if ( $args[ 'show_option_all' ] ) {
256
- if( $args['multiple'] ) {
257
- $selected = selected( true, in_array( 0, $args['selected'] ), false );
258
- } else {
259
- $selected = selected( $args['selected'], 0, false );
260
- }
261
- $output .= '<option value="all"' . $selected . '>' . esc_html( $args[ 'show_option_all' ] ) . '</option>';
262
  }
 
 
263
 
264
- if ( $args[ 'show_option_none' ] ) {
 
 
265
  if( $args['multiple'] ) {
266
  $selected = selected( true, in_array( -1, $args['selected'] ), false );
267
  } else {
268
  $selected = selected( $args['selected'], -1, false );
269
  }
270
- $output .= '<option value="-1"' . $selected . '>' . esc_html( $args[ 'show_option_none' ] ) . '</option>';
271
  }
272
 
273
- foreach( $args[ 'options' ] as $key => $option ) {
274
 
275
  if( $args['multiple'] && is_array( $args['selected'] ) ) {
276
  $selected = selected( true, in_array( $key, $args['selected'] ), false );
@@ -300,12 +400,23 @@ class EDD_HTML_Elements {
300
  $defaults = array(
301
  'name' => null,
302
  'current' => null,
303
- 'class' => 'edd-checkbox'
 
 
 
 
304
  );
305
 
306
  $args = wp_parse_args( $args, $defaults );
307
 
308
- $output = '<input type="checkbox" name="' . esc_attr( $args[ 'name' ] ) . '" id="' . esc_attr( $args[ 'name' ] ) . '" class="' . $args[ 'class' ] . ' ' . esc_attr( $args[ 'name'] ) . '" ' . checked( 1, $args[ 'current' ], false ) . ' />';
 
 
 
 
 
 
 
309
 
310
  return $output;
311
  }
@@ -315,10 +426,7 @@ class EDD_HTML_Elements {
315
  *
316
  * @since 1.5.2
317
  *
318
- * @param string $name Name attribute of the text field
319
- * @param string $value The value to prepopulate the field with
320
- * @param string $label
321
- * @param string $desc
322
  * @return string Text field
323
  */
324
  public function text( $args = array() ) {
@@ -340,7 +448,8 @@ class EDD_HTML_Elements {
340
  'placeholder' => '',
341
  'class' => 'regular-text',
342
  'disabled' => false,
343
- 'autocomplete' => ''
 
344
  );
345
 
346
  $args = wp_parse_args( $args, $defaults );
@@ -350,15 +459,22 @@ class EDD_HTML_Elements {
350
  $disabled = ' disabled="disabled"';
351
  }
352
 
353
- $output = '<span id="edd-' . sanitize_key( $args[ 'name' ] ) . '-wrap">';
354
-
355
- $output .= '<label class="edd-label" for="edd-' . sanitize_key( $args[ 'name' ] ) . '">' . esc_html( $args[ 'label' ] ) . '</label>';
 
 
 
 
 
356
 
357
- if ( ! empty( $args[ 'desc' ] ) ) {
358
- $output .= '<span class="edd-description">' . esc_html( $args[ 'desc' ] ) . '</span>';
 
 
359
  }
360
 
361
- $output .= '<input type="text" name="' . esc_attr( $args[ 'name' ] ) . '" id="' . esc_attr( $args[ 'name' ] ) . '" autocomplete="' . esc_attr( $args[ 'autocomplete' ] ) . '" value="' . esc_attr( $args[ 'value' ] ) . '" placeholder="' . esc_attr( $args[ 'placeholder' ] ) . '" class="' . $args[ 'class' ] . '"' . $disabled . '/>';
362
 
363
  $output .= '</span>';
364
 
@@ -370,10 +486,7 @@ class EDD_HTML_Elements {
370
  *
371
  * @since 1.9
372
  *
373
- * @param string $name Name attribute of the textarea
374
- * @param string $value The value to prepopulate the field with
375
- * @param string $label
376
- * @param string $desc
377
  * @return string textarea
378
  */
379
  public function textarea( $args = array() ) {
@@ -382,7 +495,7 @@ class EDD_HTML_Elements {
382
  'value' => null,
383
  'label' => null,
384
  'desc' => null,
385
- 'class' => 'large-text',
386
  'disabled' => false
387
  );
388
 
@@ -393,14 +506,14 @@ class EDD_HTML_Elements {
393
  $disabled = ' disabled="disabled"';
394
  }
395
 
396
- $output = '<span id="edd-' . sanitize_key( $args[ 'name' ] ) . '-wrap">';
397
 
398
- $output .= '<label class="edd-label" for="edd-' . sanitize_key( $args[ 'name' ] ) . '">' . esc_html( $args[ 'label' ] ) . '</label>';
399
 
400
- $output .= '<textarea name="' . esc_attr( $args[ 'name' ] ) . '" id="' . esc_attr( $args[ 'name' ] ) . '" class="' . $args[ 'class' ] . '"' . $disabled . '>' . esc_attr( $args[ 'value' ] ) . '</textarea>';
401
 
402
- if ( ! empty( $args[ 'desc' ] ) ) {
403
- $output .= '<span class="edd-description">' . esc_html( $args[ 'desc' ] ) . '</span>';
404
  }
405
 
406
  $output .= '</span>';
@@ -424,18 +537,19 @@ class EDD_HTML_Elements {
424
  'placeholder' => __( 'Enter username', 'edd' ),
425
  'label' => null,
426
  'desc' => null,
427
- 'class' => '',
428
  'disabled' => false,
429
- 'autocomplete'=> 'off'
 
430
  );
431
 
432
  $args = wp_parse_args( $args, $defaults );
433
 
434
  $args['class'] = 'edd-ajax-user-search ' . $args['class'];
435
 
436
- $output = '<span class="edd_user_search_wrap">';
437
  $output .= $this->text( $args );
438
- $output .= '<span class="edd_user_search_results"></span>';
439
  $output .= '</span>';
440
 
441
  return $output;
6
  *
7
  * @package EDD
8
  * @subpackage Classes/HTML
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.5
12
  */
26
  *
27
  * @access public
28
  * @since 1.5
29
+ * @param array $args Arguments for the dropdown
 
30
  * @return string $output Product dropdown
31
  */
32
  public function product_dropdown( $args = array() ) {
37
  'class' => '',
38
  'multiple' => false,
39
  'selected' => 0,
40
+ 'chosen' => false,
41
+ 'number' => 30,
42
+ 'bundles' => true,
43
+ 'placeholder' => sprintf( __( 'Select a %s', 'edd' ), edd_get_label_singular() )
44
  );
45
 
46
  $args = wp_parse_args( $args, $defaults );
47
 
48
+ $product_args = array(
49
  'post_type' => 'download',
50
  'orderby' => 'title',
51
  'order' => 'ASC',
52
+ 'posts_per_page' => $args['number']
53
+ );
54
+
55
+ // Maybe disable bundles
56
+ if( ! $args['bundles'] ) {
57
+ $product_args['meta_query'] = array(
58
+ 'relation' => 'AND',
59
+ array(
60
+ 'key' => '_edd_product_type',
61
+ 'value' => 'bundle',
62
+ 'compare' => 'NOT EXISTS'
63
+ )
64
+ );
65
+ }
66
+
67
+ $products = get_posts( $product_args );
68
 
69
  $options = array();
70
 
83
  $options[$item] = get_the_title( $item );
84
  }
85
  }
86
+ } elseif ( is_numeric( $args['selected'] ) && $args['selected'] !== 0 ) {
87
+ if ( ! in_array( $args['selected'], $options ) ) {
88
  $options[$args['selected']] = get_the_title( $args['selected'] );
89
  }
90
  }
95
  'id' => $args['id'],
96
  'class' => $args['class'],
97
  'options' => $options,
98
+ 'chosen' => $args['chosen'],
99
+ 'multiple' => $args['multiple'],
100
+ 'placeholder' => $args['placeholder'],
101
+ 'show_option_all' => false,
102
+ 'show_option_none' => false
103
+ ) );
104
+
105
+ return $output;
106
+ }
107
+
108
+ /**
109
+ * Renders an HTML Dropdown of all customers
110
+ *
111
+ * @access public
112
+ * @since 2.2
113
+ * @param array $args
114
+ * @return string $output Customer dropdown
115
+ */
116
+ public function customer_dropdown( $args = array() ) {
117
+
118
+ $defaults = array(
119
+ 'name' => 'customers',
120
+ 'id' => 'customers',
121
+ 'class' => '',
122
+ 'multiple' => false,
123
+ 'selected' => 0,
124
+ 'chosen' => true,
125
+ 'placeholder' => __( 'Select a Customer', 'edd' ),
126
+ 'number' => 30
127
+ );
128
+
129
+ $args = wp_parse_args( $args, $defaults );
130
+
131
+ $customers = EDD()->customers->get_customers( array(
132
+ 'number' => $args['number']
133
+ ) );
134
+
135
+ $options = array();
136
+
137
+ if ( $customers ) {
138
+ $options[0] = __( 'No customer attached', 'edd' );
139
+ foreach ( $customers as $customer ) {
140
+ $options[ absint( $customer->id ) ] = esc_html( $customer->name . ' (' . $customer->email . ')' );
141
+ }
142
+ } else {
143
+ $options[0] = __( 'No customers found', 'edd' );
144
+ }
145
+
146
+ if( ! empty( $args['selected'] ) ) {
147
+
148
+ // If a selected customer has been specified, we need to ensure it's in the initial list of customers displayed
149
+
150
+ if( ! array_key_exists( $args['selected'], $options ) ) {
151
+
152
+ $customer = new EDD_Customer( $args['selected'] );
153
+
154
+ if( $customer ) {
155
+
156
+ $options[ absint( $args['selected'] ) ] = esc_html( $customer->name . ' (' . $customer->email . ')' );
157
+
158
+ }
159
+
160
+ }
161
+
162
+ }
163
+
164
+ $output = $this->select( array(
165
+ 'name' => $args['name'],
166
+ 'selected' => $args['selected'],
167
+ 'id' => $args['id'],
168
+ 'class' => $args['class'] . ' edd-customer-select',
169
+ 'options' => $options,
170
  'multiple' => $args['multiple'],
171
  'chosen' => $args['chosen'],
172
  'show_option_all' => false,
190
  $args = array( 'nopaging' => true );
191
 
192
  if ( ! empty( $status ) )
193
+ $args['post_status'] = $status;
194
 
195
  $discounts = edd_get_discounts( $args );
196
  $options = array();
249
  * @since 1.5.2
250
  * @param string $name Name attribute of the dropdown
251
  * @param int $selected Year to select automatically
252
+ * @param int $years_before Number of years before the current year the dropdown should start with
253
+ * @param int $years_after Number of years after the current year the dropdown should finish at
254
  * @return string $output Year dropdown
255
  */
256
+ public function year_dropdown( $name = 'year', $selected = 0, $years_before = 5, $years_after = 0 ) {
257
+ $current = date( 'Y' );
258
+ $start_year = $current - absint( $years_before );
259
+ $end_year = $current + absint( $years_after );
260
+ $selected = empty( $selected ) ? date( 'Y' ) : $selected;
261
+ $options = array();
262
+
263
+ while ( $start_year <= $end_year ) {
264
+ $options[ absint( $start_year ) ] = $start_year;
265
+ $start_year++;
266
  }
267
 
268
  $output = $this->select( array(
323
  'id' => '',
324
  'selected' => 0,
325
  'chosen' => false,
326
+ 'placeholder' => null,
327
  'multiple' => false,
328
  'show_option_all' => _x( 'All', 'all dropdown items', 'edd' ),
329
  'show_option_none' => _x( 'None', 'no dropdown items', 'edd' )
342
  $args['class'] .= ' edd-select-chosen';
343
  }
344
 
345
+ if( $args['placeholder'] ) {
346
+ $placeholder = $args['placeholder'];
347
+ } else {
348
+ $placeholder = '';
349
+ }
350
 
351
+ $output = '<select name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( sanitize_key( str_replace( '-', '_', $args['id'] ) ) ) . '" class="edd-select ' . esc_attr( $args['class'] ) . '"' . $multiple . ' data-placeholder="' . $placeholder . '">';
352
+
353
+ if ( $args['show_option_all'] ) {
354
+ if( $args['multiple'] ) {
355
+ $selected = selected( true, in_array( 0, $args['selected'] ), false );
356
+ } else {
357
+ $selected = selected( $args['selected'], 0, false );
 
358
  }
359
+ $output .= '<option value="all"' . $selected . '>' . esc_html( $args['show_option_all'] ) . '</option>';
360
+ }
361
 
362
+ if ( ! empty( $args['options'] ) ) {
363
+
364
+ if ( $args['show_option_none'] ) {
365
  if( $args['multiple'] ) {
366
  $selected = selected( true, in_array( -1, $args['selected'] ), false );
367
  } else {
368
  $selected = selected( $args['selected'], -1, false );
369
  }
370
+ $output .= '<option value="-1"' . $selected . '>' . esc_html( $args['show_option_none'] ) . '</option>';
371
  }
372
 
373
+ foreach( $args['options'] as $key => $option ) {
374
 
375
  if( $args['multiple'] && is_array( $args['selected'] ) ) {
376
  $selected = selected( true, in_array( $key, $args['selected'] ), false );
400
  $defaults = array(
401
  'name' => null,
402
  'current' => null,
403
+ 'class' => 'edd-checkbox',
404
+ 'options' => array(
405
+ 'disabled' => false,
406
+ 'readonly' => false
407
+ )
408
  );
409
 
410
  $args = wp_parse_args( $args, $defaults );
411
 
412
+ $options = '';
413
+ if ( ! empty( $args['options']['disabled'] ) ) {
414
+ $options .= ' disabled="disabled"';
415
+ } elseif ( ! empty( $args['options']['readonly'] ) ) {
416
+ $options .= ' readonly';
417
+ }
418
+
419
+ $output = '<input type="checkbox"' . $options . ' name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['name'] ) . '" class="' . $args['class'] . ' ' . esc_attr( $args['name'] ) . '" ' . checked( 1, $args['current'], false ) . ' />';
420
 
421
  return $output;
422
  }
426
  *
427
  * @since 1.5.2
428
  *
429
+ * @param array $args Arguments for the text field
 
 
 
430
  * @return string Text field
431
  */
432
  public function text( $args = array() ) {
448
  'placeholder' => '',
449
  'class' => 'regular-text',
450
  'disabled' => false,
451
+ 'autocomplete' => '',
452
+ 'data' => false
453
  );
454
 
455
  $args = wp_parse_args( $args, $defaults );
459
  $disabled = ' disabled="disabled"';
460
  }
461
 
462
+ $data = '';
463
+ if ( ! empty( $args['data'] ) ) {
464
+ foreach ( $args['data'] as $key => $value ) {
465
+ $data .= 'data-' . $key . '="' . $value . '" ';
466
+ }
467
+ }
468
+
469
+ $output = '<span id="edd-' . sanitize_key( $args['name'] ) . '-wrap">';
470
 
471
+ $output .= '<label class="edd-label" for="edd-' . sanitize_key( $args['name'] ) . '">' . esc_html( $args['label'] ) . '</label>';
472
+
473
+ if ( ! empty( $args['desc'] ) ) {
474
+ $output .= '<span class="edd-description">' . esc_html( $args['desc'] ) . '</span>';
475
  }
476
 
477
+ $output .= '<input type="text" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['name'] ) . '" autocomplete="' . esc_attr( $args['autocomplete'] ) . '" value="' . esc_attr( $args['value'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" class="' . $args['class'] . '" ' . $data . '' . $disabled . '/>';
478
 
479
  $output .= '</span>';
480
 
486
  *
487
  * @since 1.9
488
  *
489
+ * @param array $args Arguments for the textarea
 
 
 
490
  * @return string textarea
491
  */
492
  public function textarea( $args = array() ) {
495
  'value' => null,
496
  'label' => null,
497
  'desc' => null,
498
+ 'class' => 'large-text',
499
  'disabled' => false
500
  );
501
 
506
  $disabled = ' disabled="disabled"';
507
  }
508
 
509
+ $output = '<span id="edd-' . sanitize_key( $args['name'] ) . '-wrap">';
510
 
511
+ $output .= '<label class="edd-label" for="edd-' . sanitize_key( $args['name'] ) . '">' . esc_html( $args['label'] ) . '</label>';
512
 
513
+ $output .= '<textarea name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['name'] ) . '" class="' . $args['class'] . '"' . $disabled . '>' . esc_attr( $args['value'] ) . '</textarea>';
514
 
515
+ if ( ! empty( $args['desc'] ) ) {
516
+ $output .= '<span class="edd-description">' . esc_html( $args['desc'] ) . '</span>';
517
  }
518
 
519
  $output .= '</span>';
537
  'placeholder' => __( 'Enter username', 'edd' ),
538
  'label' => null,
539
  'desc' => null,
540
+ 'class' => '',
541
  'disabled' => false,
542
+ 'autocomplete'=> 'off',
543
+ 'data' => false
544
  );
545
 
546
  $args = wp_parse_args( $args, $defaults );
547
 
548
  $args['class'] = 'edd-ajax-user-search ' . $args['class'];
549
 
550
+ $output = '<span class="edd_user_search_wrap">';
551
  $output .= $this->text( $args );
552
+ $output .= '<span class="edd_user_search_results hidden"><a class="edd-ajax-user-cancel" title="' . __( 'Cancel', 'edd' ) . '" aria-label="' . __( 'Cancel', 'edd' ) . '" href="#">x</a><span></span></span>';
553
  $output .= '</span>';
554
 
555
  return $output;
includes/class-edd-license-handler.php CHANGED
@@ -8,7 +8,8 @@
8
  * @version 1.1
9
  */
10
 
11
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
12
 
13
  if ( ! class_exists( 'EDD_License' ) ) :
14
 
@@ -22,12 +23,11 @@ class EDD_License {
22
  private $item_shortname;
23
  private $version;
24
  private $author;
25
- private $api_url = 'https://easydigitaldownloads.com';
26
 
27
  /**
28
  * Class constructor
29
  *
30
- * @global array $edd_options
31
  * @param string $_file
32
  * @param string $_item_name
33
  * @param string $_version
@@ -36,13 +36,11 @@ class EDD_License {
36
  * @param string $_api_url
37
  */
38
  function __construct( $_file, $_item_name, $_version, $_author, $_optname = null, $_api_url = null ) {
39
- global $edd_options;
40
-
41
  $this->file = $_file;
42
  $this->item_name = $_item_name;
43
  $this->item_shortname = 'edd_' . preg_replace( '/[^a-zA-Z0-9_\s]/', '', str_replace( ' ', '_', strtolower( $this->item_name ) ) );
44
  $this->version = $_version;
45
- $this->license = isset( $edd_options[ $this->item_shortname . '_license_key' ] ) ? trim( $edd_options[ $this->item_shortname . '_license_key' ] ) : '';
46
  $this->author = $_author;
47
  $this->api_url = is_null( $_api_url ) ? $this->api_url : $_api_url;
48
 
@@ -52,8 +50,12 @@ class EDD_License {
52
  * handler will automatically pick these up and use those in lieu of the
53
  * user having to reactive their license.
54
  */
55
- if ( ! empty( $_optname ) && isset( $edd_options[ $_optname ] ) && empty( $this->license ) ) {
56
- $this->license = trim( $edd_options[ $_optname ] );
 
 
 
 
57
  }
58
 
59
  // Setup hooks
@@ -79,6 +81,7 @@ class EDD_License {
79
  * @return void
80
  */
81
  private function hooks() {
 
82
  // Register settings
83
  add_filter( 'edd_settings_licenses', array( $this, 'settings' ), 1 );
84
 
@@ -89,14 +92,15 @@ class EDD_License {
89
  add_action( 'admin_init', array( $this, 'deactivate_license' ) );
90
 
91
  // Updater
92
- add_action( 'plugins_loaded', array( $this, 'auto_updater' ) );
 
 
93
  }
94
 
95
  /**
96
  * Auto updater
97
  *
98
  * @access private
99
- * @global array $edd_options
100
  * @return void
101
  */
102
  public function auto_updater() {
@@ -153,7 +157,7 @@ class EDD_License {
153
  return;
154
  }
155
 
156
- if ( ! isset( $_POST['edd_settings'][ $this->item_shortname . '_license_key' ] ) ) {
157
  return;
158
  }
159
 
@@ -164,15 +168,25 @@ class EDD_License {
164
  }
165
  }
166
 
 
 
 
 
 
 
167
  if( ! current_user_can( 'manage_shop_settings' ) ) {
168
  return;
169
  }
170
 
171
- if ( 'valid' == get_option( $this->item_shortname . '_license_active' ) ) {
172
  return;
173
  }
174
 
175
- $license = sanitize_text_field( $_POST['edd_settings'][ $this->item_shortname . '_license_key' ] );
 
 
 
 
176
 
177
  // Data to send to the API
178
  $api_params = array(
@@ -183,17 +197,19 @@ class EDD_License {
183
  );
184
 
185
  // Call the API
186
- $response = wp_remote_get(
187
- add_query_arg( $api_params, $this->api_url ),
188
  array(
189
  'timeout' => 15,
190
- 'sslverify' => false
 
191
  )
192
  );
193
 
194
  // Make sure there are no errors
195
- if ( is_wp_error( $response ) )
196
  return;
 
197
 
198
  // Tell WordPress to look for updates
199
  set_site_transient( 'update_plugins', null );
@@ -202,6 +218,12 @@ class EDD_License {
202
  $license_data = json_decode( wp_remote_retrieve_body( $response ) );
203
 
204
  update_option( $this->item_shortname . '_license_active', $license_data->license );
 
 
 
 
 
 
205
  }
206
 
207
 
@@ -216,15 +238,21 @@ class EDD_License {
216
  if ( ! isset( $_POST['edd_settings'] ) )
217
  return;
218
 
219
- if ( ! isset( $_POST['edd_settings'][ $this->item_shortname . '_license_key' ] ) )
220
  return;
221
 
 
 
 
 
 
 
222
  if( ! current_user_can( 'manage_shop_settings' ) ) {
223
  return;
224
  }
225
 
226
  // Run on deactivate button press
227
- if ( isset( $_POST[ $this->item_shortname . '_license_key_deactivate' ] ) ) {
228
 
229
  // Data to send to the API
230
  $api_params = array(
@@ -235,24 +263,95 @@ class EDD_License {
235
  );
236
 
237
  // Call the API
238
- $response = wp_remote_get(
239
- add_query_arg( $api_params, $this->api_url ),
240
  array(
241
  'timeout' => 15,
242
- 'sslverify' => false
 
243
  )
244
  );
245
 
246
  // Make sure there are no errors
247
- if ( is_wp_error( $response ) )
248
  return;
 
249
 
250
  // Decode the license data
251
  $license_data = json_decode( wp_remote_retrieve_body( $response ) );
252
 
253
  delete_option( $this->item_shortname . '_license_active' );
 
 
 
 
 
 
254
  }
255
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  }
257
 
258
  endif; // end class_exists check
8
  * @version 1.1
9
  */
10
 
11
+ // Exit if accessed directly
12
+ if ( ! defined( 'ABSPATH' ) ) exit;
13
 
14
  if ( ! class_exists( 'EDD_License' ) ) :
15
 
23
  private $item_shortname;
24
  private $version;
25
  private $author;
26
+ private $api_url = 'https://easydigitaldownloads.com/edd-sl-api/';
27
 
28
  /**
29
  * Class constructor
30
  *
 
31
  * @param string $_file
32
  * @param string $_item_name
33
  * @param string $_version
36
  * @param string $_api_url
37
  */
38
  function __construct( $_file, $_item_name, $_version, $_author, $_optname = null, $_api_url = null ) {
 
 
39
  $this->file = $_file;
40
  $this->item_name = $_item_name;
41
  $this->item_shortname = 'edd_' . preg_replace( '/[^a-zA-Z0-9_\s]/', '', str_replace( ' ', '_', strtolower( $this->item_name ) ) );
42
  $this->version = $_version;
43
+ $this->license = trim( edd_get_option( $this->item_shortname . '_license_key', '' ) );
44
  $this->author = $_author;
45
  $this->api_url = is_null( $_api_url ) ? $this->api_url : $_api_url;
46
 
50
  * handler will automatically pick these up and use those in lieu of the
51
  * user having to reactive their license.
52
  */
53
+ if ( ! empty( $_optname ) ) {
54
+ $opt = edd_get_option( $_optname, false );
55
+
56
+ if( isset( $opt ) && empty( $this->license ) ) {
57
+ $this->license = trim( $opt );
58
+ }
59
  }
60
 
61
  // Setup hooks
81
  * @return void
82
  */
83
  private function hooks() {
84
+
85
  // Register settings
86
  add_filter( 'edd_settings_licenses', array( $this, 'settings' ), 1 );
87
 
92
  add_action( 'admin_init', array( $this, 'deactivate_license' ) );
93
 
94
  // Updater
95
+ add_action( 'admin_init', array( $this, 'auto_updater' ), 0 );
96
+
97
+ add_action( 'admin_notices', array( $this, 'notices' ) );
98
  }
99
 
100
  /**
101
  * Auto updater
102
  *
103
  * @access private
 
104
  * @return void
105
  */
106
  public function auto_updater() {
157
  return;
158
  }
159
 
160
+ if ( ! isset( $_POST['edd_settings'][ $this->item_shortname . '_license_key'] ) ) {
161
  return;
162
  }
163
 
168
  }
169
  }
170
 
171
+ if( ! wp_verify_nonce( $_REQUEST[ $this->item_shortname . '_license_key-nonce'], $this->item_shortname . '_license_key-nonce' ) ) {
172
+
173
+ wp_die( __( 'Nonce verification failed', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
174
+
175
+ }
176
+
177
  if( ! current_user_can( 'manage_shop_settings' ) ) {
178
  return;
179
  }
180
 
181
+ if ( 'valid' === get_option( $this->item_shortname . '_license_active' ) ) {
182
  return;
183
  }
184
 
185
+ $license = sanitize_text_field( $_POST['edd_settings'][ $this->item_shortname . '_license_key'] );
186
+
187
+ if( empty( $license ) ) {
188
+ return;
189
+ }
190
 
191
  // Data to send to the API
192
  $api_params = array(
197
  );
198
 
199
  // Call the API
200
+ $response = wp_remote_post(
201
+ $this->api_url,
202
  array(
203
  'timeout' => 15,
204
+ 'sslverify' => false,
205
+ 'body' => $api_params
206
  )
207
  );
208
 
209
  // Make sure there are no errors
210
+ if ( is_wp_error( $response ) ) {
211
  return;
212
+ }
213
 
214
  // Tell WordPress to look for updates
215
  set_site_transient( 'update_plugins', null );
218
  $license_data = json_decode( wp_remote_retrieve_body( $response ) );
219
 
220
  update_option( $this->item_shortname . '_license_active', $license_data->license );
221
+
222
+ if( ! (bool) $license_data->success ) {
223
+ set_transient( 'edd_license_error', $license_data, 1000 );
224
+ } else {
225
+ delete_transient( 'edd_license_error' );
226
+ }
227
  }
228
 
229
 
238
  if ( ! isset( $_POST['edd_settings'] ) )
239
  return;
240
 
241
+ if ( ! isset( $_POST['edd_settings'][ $this->item_shortname . '_license_key'] ) )
242
  return;
243
 
244
+ if( ! wp_verify_nonce( $_REQUEST[ $this->item_shortname . '_license_key-nonce'], $this->item_shortname . '_license_key-nonce' ) ) {
245
+
246
+ wp_die( __( 'Nonce verification failed', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
247
+
248
+ }
249
+
250
  if( ! current_user_can( 'manage_shop_settings' ) ) {
251
  return;
252
  }
253
 
254
  // Run on deactivate button press
255
+ if ( isset( $_POST[ $this->item_shortname . '_license_key_deactivate'] ) ) {
256
 
257
  // Data to send to the API
258
  $api_params = array(
263
  );
264
 
265
  // Call the API
266
+ $response = wp_remote_post(
267
+ $this->api_url,
268
  array(
269
  'timeout' => 15,
270
+ 'sslverify' => false,
271
+ 'body' => $api_params
272
  )
273
  );
274
 
275
  // Make sure there are no errors
276
+ if ( is_wp_error( $response ) ) {
277
  return;
278
+ }
279
 
280
  // Decode the license data
281
  $license_data = json_decode( wp_remote_retrieve_body( $response ) );
282
 
283
  delete_option( $this->item_shortname . '_license_active' );
284
+
285
+ if( ! (bool) $license_data->success ) {
286
+ set_transient( 'edd_license_error', $license_data, 1000 );
287
+ } else {
288
+ delete_transient( 'edd_license_error' );
289
+ }
290
  }
291
  }
292
+
293
+
294
+ /**
295
+ * Admin notices for errors
296
+ *
297
+ * @access public
298
+ * @return void
299
+ */
300
+ public function notices() {
301
+
302
+ if( ! isset( $_GET['page'] ) || 'edd-settings' !== $_GET['page'] ) {
303
+ return;
304
+ }
305
+
306
+ if( ! isset( $_GET['tab'] ) || 'licenses' !== $_GET['tab'] ) {
307
+ return;
308
+ }
309
+
310
+ $license_error = get_transient( 'edd_license_error' );
311
+
312
+ if( false === $license_error ) {
313
+ return;
314
+ }
315
+
316
+ if( ! empty( $license_error->error ) ) {
317
+
318
+ switch( $license_error->error ) {
319
+
320
+ case 'item_name_mismatch' :
321
+
322
+ $message = __( 'This license does not belong to the product you have entered it for.', 'edd' );
323
+ break;
324
+
325
+ case 'no_activations_left' :
326
+
327
+ $message = __( 'This license does not have any activations left', 'edd' );
328
+ break;
329
+
330
+ case 'expired' :
331
+
332
+ $message = __( 'This license key is expired. Please renew it.', 'edd' );
333
+ break;
334
+
335
+ default :
336
+
337
+ $message = sprintf( __( 'There was a problem activating your license key, please try again or contact support. Error code: %s', 'edd' ), $license_error->error );
338
+ break;
339
+
340
+ }
341
+
342
+ }
343
+
344
+ if( ! empty( $message ) ) {
345
+
346
+ echo '<div class="error">';
347
+ echo '<p>' . $message . '</p>';
348
+ echo '</div>';
349
+
350
+ }
351
+
352
+ delete_transient( 'edd_license_error' );
353
+
354
+ }
355
  }
356
 
357
  endif; // end class_exists check
includes/class-edd-logging.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Logging
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.3.1
10
  */
@@ -199,7 +199,8 @@ class EDD_Logging {
199
  * @return bool True if successful, false otherwise
200
  */
201
  public function update_log( $log_data = array(), $log_meta = array() ) {
202
- do_action( 'edd_pre_update_log', $log_id, $log_data, $log_meta );
 
203
 
204
  $defaults = array(
205
  'post_type' => 'edd_log',
@@ -274,7 +275,7 @@ class EDD_Logging {
274
  * @return int Log count
275
  */
276
  public function get_log_count( $object_id = 0, $type = null, $meta_query = null, $date_query = null ) {
277
-
278
  global $pagenow, $typenow;
279
 
280
  $query_args = array(
@@ -321,19 +322,19 @@ class EDD_Logging {
321
  */
322
  public function delete_logs( $object_id = 0, $type = null, $meta_query = null ) {
323
  $query_args = array(
324
- 'post_parent' => $object_id,
325
- 'post_type' => 'edd_log',
326
- 'posts_per_page'=> -1,
327
- 'post_status' => 'publish',
328
- 'fields' => 'ids'
329
  );
330
 
331
  if ( ! empty( $type ) && $this->valid_type( $type ) ) {
332
  $query_args['tax_query'] = array(
333
  array(
334
- 'taxonomy' => 'edd_log_type',
335
- 'field' => 'slug',
336
- 'terms' => $type,
337
  )
338
  );
339
  }
@@ -378,4 +379,4 @@ function edd_record_log( $title = '', $message = '', $parent = 0, $type = null )
378
  global $edd_logs;
379
  $log = $edd_logs->add( $title, $message, $parent, $type );
380
  return $log;
381
- }
4
  *
5
  * @package EDD
6
  * @subpackage Logging
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.3.1
10
  */
199
  * @return bool True if successful, false otherwise
200
  */
201
  public function update_log( $log_data = array(), $log_meta = array() ) {
202
+
203
+ do_action( 'edd_pre_update_log', $log_data, $log_meta );
204
 
205
  $defaults = array(
206
  'post_type' => 'edd_log',
275
  * @return int Log count
276
  */
277
  public function get_log_count( $object_id = 0, $type = null, $meta_query = null, $date_query = null ) {
278
+
279
  global $pagenow, $typenow;
280
 
281
  $query_args = array(
322
  */
323
  public function delete_logs( $object_id = 0, $type = null, $meta_query = null ) {
324
  $query_args = array(
325
+ 'post_parent' => $object_id,
326
+ 'post_type' => 'edd_log',
327
+ 'posts_per_page' => -1,
328
+ 'post_status' => 'publish',
329
+ 'fields' => 'ids'
330
  );
331
 
332
  if ( ! empty( $type ) && $this->valid_type( $type ) ) {
333
  $query_args['tax_query'] = array(
334
  array(
335
+ 'taxonomy' => 'edd_log_type',
336
+ 'field' => 'slug',
337
+ 'terms' => $type,
338
  )
339
  );
340
  }
379
  global $edd_logs;
380
  $log = $edd_logs->add( $title, $message, $parent, $type );
381
  return $log;
382
+ }
includes/class-edd-roles.php CHANGED
@@ -4,11 +4,14 @@
4
  *
5
  * @package EDD
6
  * @subpackage Classes/Roles
7
- * @copyright Copyright (c) 2012, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4.4
10
  */
11
 
 
 
 
12
  /**
13
  * EDD_Roles Class
14
  *
@@ -102,9 +105,11 @@ class EDD_Roles {
102
  public function add_caps() {
103
  global $wp_roles;
104
 
105
- if ( class_exists('WP_Roles') )
106
- if ( ! isset( $wp_roles ) )
107
  $wp_roles = new WP_Roles();
 
 
108
 
109
  if ( is_object( $wp_roles ) ) {
110
  $wp_roles->add_cap( 'shop_manager', 'view_shop_reports' );
@@ -202,6 +207,10 @@ class EDD_Roles {
202
 
203
  case 'view_product_stats' :
204
 
 
 
 
 
205
  $download = get_post( $args[0] );
206
  if ( empty( $download ) ) {
207
  break;
@@ -226,9 +235,14 @@ class EDD_Roles {
226
  * @return void
227
  */
228
  public function remove_caps() {
229
- if ( class_exists( 'WP_Roles' ) )
230
- if ( ! isset( $wp_roles ) )
 
 
 
231
  $wp_roles = new WP_Roles();
 
 
232
 
233
  if ( is_object( $wp_roles ) ) {
234
  /** Shop Manager Capabilities */
@@ -272,4 +286,4 @@ class EDD_Roles {
272
  $wp_roles->remove_cap( 'shop_vendor', 'upload_files' );
273
  }
274
  }
275
- }
4
  *
5
  * @package EDD
6
  * @subpackage Classes/Roles
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.4.4
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
+
15
  /**
16
  * EDD_Roles Class
17
  *
105
  public function add_caps() {
106
  global $wp_roles;
107
 
108
+ if ( class_exists('WP_Roles') ) {
109
+ if ( ! isset( $wp_roles ) ) {
110
  $wp_roles = new WP_Roles();
111
+ }
112
+ }
113
 
114
  if ( is_object( $wp_roles ) ) {
115
  $wp_roles->add_cap( 'shop_manager', 'view_shop_reports' );
207
 
208
  case 'view_product_stats' :
209
 
210
+ if( empty( $args[0] ) ) {
211
+ break;
212
+ }
213
+
214
  $download = get_post( $args[0] );
215
  if ( empty( $download ) ) {
216
  break;
235
  * @return void
236
  */
237
  public function remove_caps() {
238
+
239
+ global $wp_roles;
240
+
241
+ if ( class_exists( 'WP_Roles' ) ) {
242
+ if ( ! isset( $wp_roles ) ) {
243
  $wp_roles = new WP_Roles();
244
+ }
245
+ }
246
 
247
  if ( is_object( $wp_roles ) ) {
248
  /** Shop Manager Capabilities */
286
  $wp_roles->remove_cap( 'shop_vendor', 'upload_files' );
287
  }
288
  }
289
+ }
includes/class-edd-session.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Classes/Session
9
- * @copyright Copyright (c) 2014, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.5
12
  */
@@ -28,20 +28,27 @@ class EDD_Session {
28
  * @access private
29
  * @since 1.5
30
  */
31
- private $session = array();
32
 
33
 
34
  /**
35
  * Whether to use PHP $_SESSION or WP_Session
36
  *
37
- * PHP $_SESSION is opt-in only by defining the EDD_USE_PHP_SESSIONS constant
38
- *
39
  * @var bool
40
  * @access private
41
  * @since 1.5,1
42
  */
43
  private $use_php_sessions = false;
44
 
 
 
 
 
 
 
 
 
 
45
 
46
  /**
47
  * Get things started
@@ -52,17 +59,20 @@ class EDD_Session {
52
  * @since 1.5
53
  */
54
  public function __construct() {
55
-
56
- $this->use_php_sessions = defined( 'EDD_USE_PHP_SESSIONS' ) && EDD_USE_PHP_SESSIONS;
57
 
58
  if( $this->use_php_sessions ) {
59
 
60
- // Use PHP SESSION (must be enabled via the EDD_USE_PHP_SESSIONS constant)
61
 
62
- if( ! session_id() ) {
63
- add_action( 'init', 'session_start', -2 );
64
  }
65
 
 
 
 
66
  } else {
67
 
68
  // Use WP_Session (default)
@@ -79,9 +89,9 @@ class EDD_Session {
79
  require_once EDD_PLUGIN_DIR . 'includes/libraries/class-wp-session.php';
80
  require_once EDD_PLUGIN_DIR . 'includes/libraries/wp-session.php';
81
  }
82
-
83
- //add_filter( 'wp_session_expiration_variant', array( $this, 'set_expiration_variant_time' ), 99999 );
84
- //add_filter( 'wp_session_expiration', array( $this, 'set_expiration_time' ), 99999 );
85
 
86
  }
87
 
@@ -93,7 +103,6 @@ class EDD_Session {
93
 
94
  }
95
 
96
-
97
  /**
98
  * Setup the WP_Session instance
99
  *
@@ -104,7 +113,7 @@ class EDD_Session {
104
  public function init() {
105
 
106
  if( $this->use_php_sessions ) {
107
- $this->session = isset( $_SESSION['edd'] ) && is_array( $_SESSION['edd'] ) ? $_SESSION['edd'] : array();
108
  } else {
109
  $this->session = WP_Session::get_instance();
110
  }
@@ -152,20 +161,24 @@ class EDD_Session {
152
  *
153
  * @since 1.5
154
  *
155
- * @param $key Session key
156
- * @param $value Session variable
157
- * @return mixed Session variable
158
  */
159
  public function set( $key, $value ) {
 
160
  $key = sanitize_key( $key );
161
 
162
- if ( is_array( $value ) )
163
  $this->session[ $key ] = serialize( $value );
164
- else
165
  $this->session[ $key ] = $value;
 
166
 
167
- if( $this->use_php_sessions )
168
- $_SESSION['edd'] = $this->session;
 
 
169
 
170
  return $this->session[ $key ];
171
  }
@@ -213,4 +226,66 @@ class EDD_Session {
213
  public function set_expiration_time( $exp ) {
214
  return ( 30 * 60 * 24 );
215
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  }
 
6
  *
7
  * @package EDD
8
  * @subpackage Classes/Session
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.5
12
  */
28
  * @access private
29
  * @since 1.5
30
  */
31
+ private $session;
32
 
33
 
34
  /**
35
  * Whether to use PHP $_SESSION or WP_Session
36
  *
 
 
37
  * @var bool
38
  * @access private
39
  * @since 1.5,1
40
  */
41
  private $use_php_sessions = false;
42
 
43
+ /**
44
+ * Session index prefix
45
+ *
46
+ * @var string
47
+ * @access private
48
+ * @since 2.3
49
+ */
50
+ private $prefix = '';
51
+
52
 
53
  /**
54
  * Get things started
59
  * @since 1.5
60
  */
61
  public function __construct() {
62
+
63
+ $this->use_php_sessions = $this->use_php_sessions();
64
 
65
  if( $this->use_php_sessions ) {
66
 
67
+ if( is_multisite() ) {
68
 
69
+ $this->prefix = '_' . get_current_blog_id();
70
+
71
  }
72
 
73
+ // Use PHP SESSION (must be enabled via the EDD_USE_PHP_SESSIONS constant)
74
+ add_action( 'init', array( $this, 'maybe_start_session' ), -2 );
75
+
76
  } else {
77
 
78
  // Use WP_Session (default)
89
  require_once EDD_PLUGIN_DIR . 'includes/libraries/class-wp-session.php';
90
  require_once EDD_PLUGIN_DIR . 'includes/libraries/wp-session.php';
91
  }
92
+
93
+ add_filter( 'wp_session_expiration_variant', array( $this, 'set_expiration_variant_time' ), 99999 );
94
+ add_filter( 'wp_session_expiration', array( $this, 'set_expiration_time' ), 99999 );
95
 
96
  }
97
 
103
 
104
  }
105
 
 
106
  /**
107
  * Setup the WP_Session instance
108
  *
113
  public function init() {
114
 
115
  if( $this->use_php_sessions ) {
116
+ $this->session = isset( $_SESSION['edd' . $this->prefix ] ) && is_array( $_SESSION['edd' . $this->prefix ] ) ? $_SESSION['edd' . $this->prefix ] : array();
117
  } else {
118
  $this->session = WP_Session::get_instance();
119
  }
161
  *
162
  * @since 1.5
163
  *
164
+ * @param string $key Session key
165
+ * @param integer $value Session variable
166
+ * @return string Session variable
167
  */
168
  public function set( $key, $value ) {
169
+
170
  $key = sanitize_key( $key );
171
 
172
+ if ( is_array( $value ) ) {
173
  $this->session[ $key ] = serialize( $value );
174
+ } else {
175
  $this->session[ $key ] = $value;
176
+ }
177
 
178
+ if( $this->use_php_sessions ) {
179
+
180
+ $_SESSION['edd' . $this->prefix ] = $this->session;
181
+ }
182
 
183
  return $this->session[ $key ];
184
  }
226
  public function set_expiration_time( $exp ) {
227
  return ( 30 * 60 * 24 );
228
  }
229
+
230
+ /**
231
+ * Starts a new session if one hasn't started yet.
232
+ *
233
+ * @return boolean
234
+ * Checks to see if the server supports PHP sessions
235
+ * or if the EDD_USE_PHP_SESSIONS constant is defined
236
+ *
237
+ * @access public
238
+ * @since 2.1
239
+ * @author Daniel J Griffiths
240
+ * @return boolean $ret True if we are using PHP sessions, false otherwise
241
+ */
242
+ public function use_php_sessions() {
243
+
244
+ $ret = false;
245
+
246
+ // If the database variable is already set, no need to run autodetection
247
+ $edd_use_php_sessions = (bool) get_option( 'edd_use_php_sessions' );
248
+
249
+ if ( ! $edd_use_php_sessions ) {
250
+
251
+ // Attempt to detect if the server supports PHP sessions
252
+ if( function_exists( 'session_start' ) && ! ini_get( 'safe_mode' ) ) {
253
+
254
+ $this->set( 'edd_use_php_sessions', 1 );
255
+
256
+ if( $this->get( 'edd_use_php_sessions' ) ) {
257
+
258
+ $ret = true;
259
+
260
+ // Set the database option
261
+ update_option( 'edd_use_php_sessions', true );
262
+
263
+ }
264
+
265
+ }
266
+
267
+ } else {
268
+ $ret = $edd_use_php_sessions;
269
+ }
270
+
271
+ // Enable or disable PHP Sessions based on the EDD_USE_PHP_SESSIONS constant
272
+ if ( defined( 'EDD_USE_PHP_SESSIONS' ) && EDD_USE_PHP_SESSIONS ) {
273
+ $ret = true;
274
+ } else if ( defined( 'EDD_USE_PHP_SESSIONS' ) && ! EDD_USE_PHP_SESSIONS ) {
275
+ $ret = false;
276
+ }
277
+
278
+ return (bool) apply_filters( 'edd_use_php_sessions', $ret );
279
+ }
280
+
281
+ /**
282
+ * Starts a new session if one hasn't started yet.
283
+ */
284
+ public function maybe_start_session() {
285
+ if( ! session_id() && ! headers_sent() ) {
286
+ session_start();
287
+ }
288
+ }
289
+
290
  }
291
+
includes/class-edd-stats.php CHANGED
@@ -4,11 +4,13 @@
4
  *
5
  * @package EDD
6
  * @subpackage Classes/Stats
7
- * @copyright Copyright (c) 2012, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8
10
  */
11
 
 
 
12
 
13
  /**
14
  * EDD_Stats Class
@@ -105,19 +107,15 @@ class EDD_Stats {
105
  public function setup_dates( $_start_date = 'this_month', $_end_date = false ) {
106
 
107
  if( empty( $_start_date ) ) {
108
- $this->start_date = 'this_month';
109
  }
110
 
111
- $this->start_date = $_start_date;
112
-
113
- if( ! empty( $_end_date ) ) {
114
- $this->end_date = $_end_date;
115
- } else {
116
- $this->end_date = $this->start_date;
117
  }
118
 
119
- $this->start_date = $this->convert_date( $this->start_date );
120
- $this->end_date = $this->convert_date( $this->end_date, true );
121
 
122
  }
123
 
@@ -159,7 +157,7 @@ class EDD_Stats {
159
 
160
  $month = 12;
161
  $year--;
162
-
163
  } else {
164
 
165
  $month--;
@@ -173,7 +171,7 @@ class EDD_Stats {
173
  break;
174
 
175
  case 'today' :
176
-
177
  $day = date( 'd', current_time( 'timestamp' ) );
178
 
179
  if( $end_date ) {
@@ -194,16 +192,15 @@ class EDD_Stats {
194
  // If current month is 1
195
  if( 1 == $month ) {
196
 
197
- $year -= 1; // Today is January 1, so skip back to December
198
- $month -= 1;
199
-
200
- // Get the last day of the month
201
- $day = cal_days_in_month( CAL_GREGORIAN, $month, $year );
202
 
203
  } else {
204
 
205
- // Get the last day of the month
206
- $day = cal_days_in_month( CAL_GREGORIAN, $month, $year );
 
207
 
208
  }
209
  }
@@ -213,7 +210,7 @@ class EDD_Stats {
213
  case 'this_week' :
214
 
215
  $days_to_week_start = ( date( 'w', current_time( 'timestamp' ) ) - 1 ) *60*60*24;
216
- $today = date( 'd', current_time( 'timestamp' ) );
217
 
218
  if( $today < $days_to_week_start ) {
219
 
@@ -246,7 +243,7 @@ class EDD_Stats {
246
  case 'last_week' :
247
 
248
  $days_to_week_start = ( date( 'w', current_time( 'timestamp' ) ) - 1 ) *60*60*24;
249
- $today = date( 'd', current_time( 'timestamp' ) );
250
 
251
  if( $today < $days_to_week_start ) {
252
 
@@ -535,4 +532,4 @@ class EDD_Stats {
535
  return $where;
536
  }
537
 
538
- }
4
  *
5
  * @package EDD
6
  * @subpackage Classes/Stats
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
 
15
  /**
16
  * EDD_Stats Class
107
  public function setup_dates( $_start_date = 'this_month', $_end_date = false ) {
108
 
109
  if( empty( $_start_date ) ) {
110
+ $_start_date = 'this_month';
111
  }
112
 
113
+ if( empty( $_end_date ) ) {
114
+ $_end_date = $_start_date;
 
 
 
 
115
  }
116
 
117
+ $this->start_date = $this->convert_date( $_start_date );
118
+ $this->end_date = $this->convert_date( $_end_date, true );
119
 
120
  }
121
 
157
 
158
  $month = 12;
159
  $year--;
160
+
161
  } else {
162
 
163
  $month--;
171
  break;
172
 
173
  case 'today' :
174
+
175
  $day = date( 'd', current_time( 'timestamp' ) );
176
 
177
  if( $end_date ) {
192
  // If current month is 1
193
  if( 1 == $month ) {
194
 
195
+ $year -= 1; // Today is January 1, so skip back to last day of December
196
+ $month = 12;
197
+ $day = cal_days_in_month( CAL_GREGORIAN, $month, $year );
 
 
198
 
199
  } else {
200
 
201
+ // Go back one month and get the last day of the month
202
+ $month -= 1;
203
+ $day = cal_days_in_month( CAL_GREGORIAN, $month, $year );
204
 
205
  }
206
  }
210
  case 'this_week' :
211
 
212
  $days_to_week_start = ( date( 'w', current_time( 'timestamp' ) ) - 1 ) *60*60*24;
213
+ $today = date( 'd', current_time( 'timestamp' ) ) *60*60*24;
214
 
215
  if( $today < $days_to_week_start ) {
216
 
243
  case 'last_week' :
244
 
245
  $days_to_week_start = ( date( 'w', current_time( 'timestamp' ) ) - 1 ) *60*60*24;
246
+ $today = date( 'd', current_time( 'timestamp' ) ) *60*60*24;
247
 
248
  if( $today < $days_to_week_start ) {
249
 
532
  return $where;
533
  }
534
 
535
+ }
includes/country-functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.6
10
  */
@@ -20,8 +20,8 @@ if ( ! defined( 'ABSPATH' ) ) exit;
20
  * @return string $country The two letter country code for the shop's base country
21
  */
22
  function edd_get_shop_country() {
23
- global $edd_options;
24
- $country = isset( $edd_options['base_country'] ) ? $edd_options['base_country'] : 'US';
25
  return apply_filters( 'edd_shop_country', $country );
26
  }
27
 
@@ -32,8 +32,8 @@ function edd_get_shop_country() {
32
  * @return string $state The shop's base state name
33
  */
34
  function edd_get_shop_state() {
35
- global $edd_options;
36
- $state = isset( $edd_options['base_state'] ) ? $edd_options['base_state'] : false;
37
  return apply_filters( 'edd_shop_state', $state );
38
  }
39
 
@@ -46,8 +46,6 @@ function edd_get_shop_state() {
46
  * @return mixed|void A list of states for the shop's base country
47
  */
48
  function edd_get_shop_states( $country = null ) {
49
- global $edd_options;
50
-
51
  if( empty( $country ) )
52
  $country = edd_get_shop_country();
53
 
@@ -62,6 +60,12 @@ function edd_get_shop_states( $country = null ) {
62
  case 'AU' :
63
  $states = edd_get_australian_states_list();
64
  break;
 
 
 
 
 
 
65
  case 'BR' :
66
  $states = edd_get_brazil_states_list();
67
  break;
@@ -80,18 +84,42 @@ function edd_get_shop_states( $country = null ) {
80
  case 'IN' :
81
  $states = edd_get_indian_states_list();
82
  break;
 
 
 
 
 
 
 
 
 
 
 
 
83
  case 'MY' :
84
  $states = edd_get_malaysian_states_list();
85
  break;
 
 
 
86
  case 'NZ' :
87
  $states = edd_get_new_zealand_states_list();
88
  break;
 
 
 
89
  case 'TH' :
90
  $states = edd_get_thailand_states_list();
91
  break;
 
 
 
92
  case 'ZA' :
93
  $states = edd_get_south_african_states_list();
94
  break;
 
 
 
95
  default :
96
  $states = array();
97
  break;
@@ -110,11 +138,12 @@ function edd_get_shop_states( $country = null ) {
110
  */
111
  function edd_get_country_list() {
112
  $countries = array(
113
- '0' => __( 'Choose', 'edd' ),
114
  'US' => 'United States',
115
  'CA' => 'Canada',
116
  'GB' => 'United Kingdom',
117
  'AF' => 'Afghanistan',
 
118
  'AL' => 'Albania',
119
  'DZ' => 'Algeria',
120
  'AS' => 'American Samoa',
@@ -140,6 +169,7 @@ function edd_get_country_list() {
140
  'BM' => 'Bermuda',
141
  'BT' => 'Bhutan',
142
  'BO' => 'Bolivia',
 
143
  'BA' => 'Bosnia and Herzegovina',
144
  'BW' => 'Botswana',
145
  'BV' => 'Bouvet Island',
@@ -168,7 +198,8 @@ function edd_get_country_list() {
168
  'CI' => 'Cote d\'Ivoire',
169
  'HR' => 'Croatia/Hrvatska',
170
  'CU' => 'Cuba',
171
- 'CY' => 'Cyprus Island',
 
172
  'CZ' => 'Czech Republic',
173
  'DK' => 'Denmark',
174
  'DJ' => 'Djibouti',
@@ -244,7 +275,7 @@ function edd_get_country_list() {
244
  'MG' => 'Madagascar',
245
  'MW' => 'Malawi',
246
  'MY' => 'Malaysia',
247
- 'Mv' => 'Maldives',
248
  'ML' => 'Mali',
249
  'MT' => 'Malta',
250
  'MH' => 'Marshall Islands',
@@ -291,17 +322,21 @@ function edd_get_country_list() {
291
  'PT' => 'Portugal',
292
  'PR' => 'Puerto Rico',
293
  'QA' => 'Qatar',
 
294
  'RE' => 'Reunion Island',
295
  'RO' => 'Romania',
296
  'RU' => 'Russian Federation',
297
  'RW' => 'Rwanda',
 
298
  'SH' => 'Saint Helena',
299
  'KN' => 'Saint Kitts and Nevis',
300
  'LC' => 'Saint Lucia',
 
 
301
  'PM' => 'Saint Pierre and Miquelon',
302
  'VC' => 'Saint Vincent and the Grenadines',
303
  'SM' => 'San Marino',
304
- 'ST' => 'Sao Tome and Principe',
305
  'SA' => 'Saudi Arabia',
306
  'SN' => 'Senegal',
307
  'RS' => 'Serbia',
@@ -315,6 +350,7 @@ function edd_get_country_list() {
315
  'ZA' => 'South Africa',
316
  'GS' => 'South Georgia',
317
  'KP' => 'South Korea',
 
318
  'ES' => 'Spain',
319
  'LK' => 'Sri Lanka',
320
  'SD' => 'Sudan',
@@ -327,10 +363,11 @@ function edd_get_country_list() {
327
  'TW' => 'Taiwan',
328
  'TJ' => 'Tajikistan',
329
  'TZ' => 'Tanzania',
 
 
330
  'TG' => 'Togo',
331
  'TK' => 'Tokelau',
332
  'TO' => 'Tonga',
333
- 'TH' => 'Thailand',
334
  'TT' => 'Trinidad and Tobago',
335
  'TN' => 'Tunisia',
336
  'TR' => 'Turkey',
@@ -352,7 +389,6 @@ function edd_get_country_list() {
352
  'EH' => 'Western Sahara',
353
  'WS' => 'Western Samoa',
354
  'YE' => 'Yemen',
355
- 'YU' => 'Yugoslavia',
356
  'ZM' => 'Zambia',
357
  'ZW' => 'Zimbabwe'
358
  );
@@ -369,7 +405,7 @@ function edd_get_country_list() {
369
  */
370
  function edd_get_states_list() {
371
  $states = array(
372
- '0' => __( 'Choose', 'edd' ),
373
  'AL' => 'Alabama',
374
  'AK' => 'Alaska',
375
  'AZ' => 'Arizona',
@@ -450,7 +486,7 @@ function edd_get_states_list() {
450
  */
451
  function edd_get_provinces_list() {
452
  $provinces = array(
453
- '0' => __( 'Choose', 'edd' ),
454
  'AB' => 'Alberta',
455
  'BC' => 'British Columbia',
456
  'MB' => 'Manitoba',
@@ -477,7 +513,7 @@ function edd_get_provinces_list() {
477
  */
478
  function edd_get_australian_states_list() {
479
  $states = array(
480
- '0' => __( 'Choose', 'edd' ),
481
  'ACT' => 'Australian Capital Territory',
482
  'NSW' => 'New South Wales',
483
  'NT' => 'Northern Territory',
@@ -491,6 +527,84 @@ function edd_get_australian_states_list() {
491
  return apply_filters( 'edd_australian_states', $states );
492
  }
493
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494
  /**
495
  * Get Brazil States
496
  *
@@ -499,7 +613,7 @@ function edd_get_australian_states_list() {
499
  */
500
  function edd_get_brazil_states_list() {
501
  $states = array(
502
- '0' => __( 'Choose', 'edd' ),
503
  'AC' => 'Acre',
504
  'AL' => 'Alagoas',
505
  'AP' => 'Amap&aacute;',
@@ -532,6 +646,48 @@ function edd_get_brazil_states_list() {
532
  return apply_filters( 'edd_brazil_states', $states );
533
  }
534
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
535
  /**
536
  * Get Hong Kong States
537
  *
@@ -540,7 +696,7 @@ function edd_get_brazil_states_list() {
540
  */
541
  function edd_get_hong_kong_states_list() {
542
  $states = array(
543
- '0' => __( 'Choose', 'edd' ),
544
  'HONG KONG' => 'Hong Kong Island',
545
  'KOWLOON' => 'Kowloon',
546
  'NEW TERRITORIES' => 'New Territories'
@@ -557,7 +713,7 @@ function edd_get_hong_kong_states_list() {
557
  */
558
  function edd_get_hungary_states_list() {
559
  $states = array(
560
- '0' => __( 'Choose', 'edd' ),
561
  'BK' => 'Bács-Kiskun',
562
  'BE' => 'Békés',
563
  'BA' => 'Baranya',
@@ -583,6 +739,67 @@ function edd_get_hungary_states_list() {
583
  return apply_filters( 'edd_hungary_states', $states );
584
  }
585
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
586
  /**
587
  * Get Chinese States
588
  *
@@ -591,7 +808,7 @@ function edd_get_hungary_states_list() {
591
  */
592
  function edd_get_chinese_states_list() {
593
  $states = array(
594
- '0' => __( 'Choose', 'edd' ),
595
  'CN1' => 'Yunnan / &#20113;&#21335;',
596
  'CN2' => 'Beijing / &#21271;&#20140;',
597
  'CN3' => 'Tianjin / &#22825;&#27941;',
@@ -637,7 +854,7 @@ function edd_get_chinese_states_list() {
637
  */
638
  function edd_get_new_zealand_states_list() {
639
  $states = array(
640
- '0' => __( 'Choose', 'edd' ),
641
  'AK' => 'Auckland',
642
  'BP' => 'Bay of Plenty',
643
  'CT' => 'Canterbury',
@@ -658,6 +875,46 @@ function edd_get_new_zealand_states_list() {
658
  return apply_filters( 'edd_new_zealand_states', $states );
659
  }
660
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
661
  /**
662
  * Get Indonesian States
663
  *
@@ -666,7 +923,7 @@ function edd_get_new_zealand_states_list() {
666
  */
667
  function edd_get_indonesian_states_list() {
668
  $states = array(
669
- '0' => __( 'Choose', 'edd' ),
670
  'AC' => 'Daerah Istimewa Aceh',
671
  'SU' => 'Sumatera Utara',
672
  'SB' => 'Sumatera Barat',
@@ -714,8 +971,8 @@ function edd_get_indonesian_states_list() {
714
  */
715
  function edd_get_indian_states_list() {
716
  $states = array(
717
- '0' => __( 'Choose', 'edd' ),
718
- 'AP' => 'Andra Pradesh',
719
  'AR' => 'Arunachal Pradesh',
720
  'AS' => 'Assam',
721
  'BR' => 'Bihar',
@@ -739,8 +996,9 @@ function edd_get_indian_states_list() {
739
  'RJ' => 'Rajasthan',
740
  'SK' => 'Sikkim',
741
  'TN' => 'Tamil Nadu',
 
742
  'TR' => 'Tripura',
743
- 'UT' => 'Uttaranchal',
744
  'UP' => 'Uttar Pradesh',
745
  'WB' => 'West Bengal',
746
  'AN' => 'Andaman and Nicobar Islands',
@@ -748,13 +1006,182 @@ function edd_get_indian_states_list() {
748
  'DN' => 'Dadar and Nagar Haveli',
749
  'DD' => 'Daman and Diu',
750
  'DL' => 'Delhi',
751
- 'LD' => 'Lakshadeep',
752
  'PY' => 'Pondicherry (Puducherry)'
753
  );
754
 
755
  return apply_filters( 'edd_indian_states', $states );
756
  }
757
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
758
  /**
759
  * Get Malaysian States
760
  *
@@ -763,7 +1190,7 @@ function edd_get_indian_states_list() {
763
  */
764
  function edd_get_malaysian_states_list() {
765
  $states = array(
766
- '0' => __( 'Choose', 'edd' ),
767
  'JHR' => 'Johor',
768
  'KDH' => 'Kedah',
769
  'KTN' => 'Kelantan',
@@ -785,6 +1212,141 @@ function edd_get_malaysian_states_list() {
785
  return apply_filters( 'edd_malaysian_states', $states );
786
  }
787
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
788
  /**
789
  * Get South African States
790
  *
@@ -793,7 +1355,7 @@ function edd_get_malaysian_states_list() {
793
  */
794
  function edd_get_south_african_states_list() {
795
  $states = array(
796
- '0' => __( 'Choose', 'edd' ),
797
  'EC' => 'Eastern Cape',
798
  'FS' => 'Free State',
799
  'GP' => 'Gauteng',
@@ -816,7 +1378,7 @@ function edd_get_south_african_states_list() {
816
  */
817
  function edd_get_thailand_states_list() {
818
  $states = array(
819
- '0' => __( 'Choose', 'edd' ),
820
  'TH-37' => 'Amnat Charoen (&#3629;&#3635;&#3609;&#3634;&#3592;&#3648;&#3592;&#3619;&#3636;&#3597;)',
821
  'TH-15' => 'Ang Thong (&#3629;&#3656;&#3634;&#3591;&#3607;&#3629;&#3591;)',
822
  'TH-14' => 'Ayutthaya (&#3614;&#3619;&#3632;&#3609;&#3588;&#3619;&#3624;&#3619;&#3637;&#3629;&#3618;&#3640;&#3608;&#3618;&#3634;)',
@@ -898,3 +1460,164 @@ function edd_get_thailand_states_list() {
898
 
899
  return apply_filters( 'edd_thailand_states', $states );
900
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.6
10
  */
20
  * @return string $country The two letter country code for the shop's base country
21
  */
22
  function edd_get_shop_country() {
23
+ $country = edd_get_option( 'base_country', 'US' );
24
+
25
  return apply_filters( 'edd_shop_country', $country );
26
  }
27
 
32
  * @return string $state The shop's base state name
33
  */
34
  function edd_get_shop_state() {
35
+ $state = edd_get_option( 'base_state', false );
36
+
37
  return apply_filters( 'edd_shop_state', $state );
38
  }
39
 
46
  * @return mixed|void A list of states for the shop's base country
47
  */
48
  function edd_get_shop_states( $country = null ) {
 
 
49
  if( empty( $country ) )
50
  $country = edd_get_shop_country();
51
 
60
  case 'AU' :
61
  $states = edd_get_australian_states_list();
62
  break;
63
+ case 'BD' :
64
+ $states = edd_get_bangladeshi_states_list();
65
+ break;
66
+ case 'BG' :
67
+ $states = edd_get_bulgarian_states_list();
68
+ break;
69
  case 'BR' :
70
  $states = edd_get_brazil_states_list();
71
  break;
84
  case 'IN' :
85
  $states = edd_get_indian_states_list();
86
  break;
87
+ case 'IR' :
88
+ $states = edd_get_iranian_states_list();
89
+ break;
90
+ case 'IT' :
91
+ $states = edd_get_italian_states_list();
92
+ break;
93
+ case 'JP' :
94
+ $states = edd_get_japanese_states_list();
95
+ break;
96
+ case 'MX' :
97
+ $states = edd_get_mexican_states_list();
98
+ break;
99
  case 'MY' :
100
  $states = edd_get_malaysian_states_list();
101
  break;
102
+ case 'NP' :
103
+ $states = edd_get_nepalese_states_list();
104
+ break;
105
  case 'NZ' :
106
  $states = edd_get_new_zealand_states_list();
107
  break;
108
+ case 'PE' :
109
+ $states = edd_get_peruvian_states_list();
110
+ break;
111
  case 'TH' :
112
  $states = edd_get_thailand_states_list();
113
  break;
114
+ case 'TR' :
115
+ $states = edd_get_turkey_states_list();
116
+ break;
117
  case 'ZA' :
118
  $states = edd_get_south_african_states_list();
119
  break;
120
+ case 'ES' :
121
+ $states = edd_get_spain_states_list();
122
+ break;
123
  default :
124
  $states = array();
125
  break;
138
  */
139
  function edd_get_country_list() {
140
  $countries = array(
141
+ '' => '',
142
  'US' => 'United States',
143
  'CA' => 'Canada',
144
  'GB' => 'United Kingdom',
145
  'AF' => 'Afghanistan',
146
+ 'AX' => '&#197;land Islands',
147
  'AL' => 'Albania',
148
  'DZ' => 'Algeria',
149
  'AS' => 'American Samoa',
169
  'BM' => 'Bermuda',
170
  'BT' => 'Bhutan',
171
  'BO' => 'Bolivia',
172
+ 'BQ' => 'Bonaire, Saint Eustatius and Saba',
173
  'BA' => 'Bosnia and Herzegovina',
174
  'BW' => 'Botswana',
175
  'BV' => 'Bouvet Island',
198
  'CI' => 'Cote d\'Ivoire',
199
  'HR' => 'Croatia/Hrvatska',
200
  'CU' => 'Cuba',
201
+ 'CW' => 'Cura&Ccedil;ao',
202
+ 'CY' => 'Cyprus',
203
  'CZ' => 'Czech Republic',
204
  'DK' => 'Denmark',
205
  'DJ' => 'Djibouti',
275
  'MG' => 'Madagascar',
276
  'MW' => 'Malawi',
277
  'MY' => 'Malaysia',
278
+ 'MV' => 'Maldives',
279
  'ML' => 'Mali',
280
  'MT' => 'Malta',
281
  'MH' => 'Marshall Islands',
322
  'PT' => 'Portugal',
323
  'PR' => 'Puerto Rico',
324
  'QA' => 'Qatar',
325
+ 'XK' => 'Republic of Kosovo',
326
  'RE' => 'Reunion Island',
327
  'RO' => 'Romania',
328
  'RU' => 'Russian Federation',
329
  'RW' => 'Rwanda',
330
+ 'BL' => 'Saint Barth&eacute;lemy',
331
  'SH' => 'Saint Helena',
332
  'KN' => 'Saint Kitts and Nevis',
333
  'LC' => 'Saint Lucia',
334
+ 'MF' => 'Saint Martin (French)',
335
+ 'SX' => 'Saint Martin (Dutch)',
336
  'PM' => 'Saint Pierre and Miquelon',
337
  'VC' => 'Saint Vincent and the Grenadines',
338
  'SM' => 'San Marino',
339
+ 'ST' => 'S&atilde;o Tom&eacute; and Pr&iacute;ncipe',
340
  'SA' => 'Saudi Arabia',
341
  'SN' => 'Senegal',
342
  'RS' => 'Serbia',
350
  'ZA' => 'South Africa',
351
  'GS' => 'South Georgia',
352
  'KP' => 'South Korea',
353
+ 'SS' => 'South Sudan',
354
  'ES' => 'Spain',
355
  'LK' => 'Sri Lanka',
356
  'SD' => 'Sudan',
363
  'TW' => 'Taiwan',
364
  'TJ' => 'Tajikistan',
365
  'TZ' => 'Tanzania',
366
+ 'TH' => 'Thailand',
367
+ 'TL' => 'Timor-Leste',
368
  'TG' => 'Togo',
369
  'TK' => 'Tokelau',
370
  'TO' => 'Tonga',
 
371
  'TT' => 'Trinidad and Tobago',
372
  'TN' => 'Tunisia',
373
  'TR' => 'Turkey',
389
  'EH' => 'Western Sahara',
390
  'WS' => 'Western Samoa',
391
  'YE' => 'Yemen',
 
392
  'ZM' => 'Zambia',
393
  'ZW' => 'Zimbabwe'
394
  );
405
  */
406
  function edd_get_states_list() {
407
  $states = array(
408
+ '' => '',
409
  'AL' => 'Alabama',
410
  'AK' => 'Alaska',
411
  'AZ' => 'Arizona',
486
  */
487
  function edd_get_provinces_list() {
488
  $provinces = array(
489
+ '' => '',
490
  'AB' => 'Alberta',
491
  'BC' => 'British Columbia',
492
  'MB' => 'Manitoba',
513
  */
514
  function edd_get_australian_states_list() {
515
  $states = array(
516
+ '' => '',
517
  'ACT' => 'Australian Capital Territory',
518
  'NSW' => 'New South Wales',
519
  'NT' => 'Northern Territory',
527
  return apply_filters( 'edd_australian_states', $states );
528
  }
529
 
530
+ /**
531
+ * Get Bangladeshi States (districts)
532
+ *
533
+ * @since 2.2.3
534
+ * @return array $states A list of states
535
+ */
536
+ function edd_get_bangladeshi_states_list() {
537
+ $states = array(
538
+ '' => '',
539
+ 'BAG' => 'Bagerhat',
540
+ 'BAN' => 'Bandarban',
541
+ 'BAR' => 'Barguna',
542
+ 'BARI'=> 'Barisal',
543
+ 'BHO' => 'Bhola',
544
+ 'BOG' => 'Bogra',
545
+ 'BRA' => 'Brahmanbaria',
546
+ 'CHA' => 'Chandpur',
547
+ 'CHI' => 'Chittagong',
548
+ 'CHU' => 'Chuadanga',
549
+ 'COM' => 'Comilla',
550
+ 'COX' => 'Cox\'s Bazar',
551
+ 'DHA' => 'Dhaka',
552
+ 'DIN' => 'Dinajpur',
553
+ 'FAR' => 'Faridpur',
554
+ 'FEN' => 'Feni',
555
+ 'GAI' => 'Gaibandha',
556
+ 'GAZI'=> 'Gazipur',
557
+ 'GOP' => 'Gopalganj',
558
+ 'HAB' => 'Habiganj',
559
+ 'JAM' => 'Jamalpur',
560
+ 'JES' => 'Jessore',
561
+ 'JHA' => 'Jhalokati',
562
+ 'JHE' => 'Jhenaidah',
563
+ 'JOY' => 'Joypurhat',
564
+ 'KHA' => 'Khagrachhari',
565
+ 'KHU' => 'Khulna',
566
+ 'KIS' => 'Kishoreganj',
567
+ 'KUR' => 'Kurigram',
568
+ 'KUS' => 'Kushtia',
569
+ 'LAK' => 'Lakshmipur',
570
+ 'LAL' => 'Lalmonirhat',
571
+ 'MAD' => 'Madaripur',
572
+ 'MAG' => 'Magura',
573
+ 'MAN' => 'Manikganj',
574
+ 'MEH' => 'Meherpur',
575
+ 'MOU' => 'Moulvibazar',
576
+ 'MUN' => 'Munshiganj',
577
+ 'MYM' => 'Mymensingh',
578
+ 'NAO' => 'Naogaon',
579
+ 'NAR' => 'Narail',
580
+ 'NARG'=> 'Narayanganj',
581
+ 'NARD'=> 'Narsingdi',
582
+ 'NAT' => 'Natore',
583
+ 'NAW' => 'Nawabganj',
584
+ 'NET' => 'Netrakona',
585
+ 'NIL' => 'Nilphamari',
586
+ 'NOA' => 'Noakhali',
587
+ 'PAB' => 'Pabna',
588
+ 'PAN' => 'Panchagarh',
589
+ 'PAT' => 'Patuakhali',
590
+ 'PIR' => 'Pirojpur',
591
+ 'RAJB'=> 'Rajbari',
592
+ 'RAJ' => 'Rajshahi',
593
+ 'RAN' => 'Rangamati',
594
+ 'RANP'=> 'Rangpur',
595
+ 'SAT' => 'Satkhira',
596
+ 'SHA' => 'Shariatpur',
597
+ 'SHE' => 'Sherpur',
598
+ 'SIR' => 'Sirajganj',
599
+ 'SUN' => 'Sunamganj',
600
+ 'SYL' => 'Sylhet',
601
+ 'TAN' => 'Tangail',
602
+ 'THA' => 'Thakurgaon'
603
+ );
604
+
605
+ return apply_filters( 'edd_bangladeshi_states', $states );
606
+ }
607
+
608
  /**
609
  * Get Brazil States
610
  *
613
  */
614
  function edd_get_brazil_states_list() {
615
  $states = array(
616
+ '' => '',
617
  'AC' => 'Acre',
618
  'AL' => 'Alagoas',
619
  'AP' => 'Amap&aacute;',
646
  return apply_filters( 'edd_brazil_states', $states );
647
  }
648
 
649
+ /**
650
+ * Get Bulgarian States
651
+ *
652
+ * @since 2.2.3
653
+ * @return array $states A list of states
654
+ */
655
+ function edd_get_bulgarian_states_list() {
656
+ $states = array(
657
+ '' => '',
658
+ 'BG-01' => 'Blagoevgrad',
659
+ 'BG-02' => 'Burgas',
660
+ 'BG-08' => 'Dobrich',
661
+ 'BG-07' => 'Gabrovo',
662
+ 'BG-26' => 'Haskovo',
663
+ 'BG-09' => 'Kardzhali',
664
+ 'BG-10' => 'Kyustendil',
665
+ 'BG-11' => 'Lovech',
666
+ 'BG-12' => 'Montana',
667
+ 'BG-13' => 'Pazardzhik',
668
+ 'BG-14' => 'Pernik',
669
+ 'BG-15' => 'Pleven',
670
+ 'BG-16' => 'Plovdiv',
671
+ 'BG-17' => 'Razgrad',
672
+ 'BG-18' => 'Ruse',
673
+ 'BG-27' => 'Shumen',
674
+ 'BG-19' => 'Silistra',
675
+ 'BG-20' => 'Sliven',
676
+ 'BG-21' => 'Smolyan',
677
+ 'BG-23' => 'Sofia',
678
+ 'BG-22' => 'Sofia-Grad',
679
+ 'BG-24' => 'Stara Zagora',
680
+ 'BG-25' => 'Targovishte',
681
+ 'BG-03' => 'Varna',
682
+ 'BG-04' => 'Veliko Tarnovo',
683
+ 'BG-05' => 'Vidin',
684
+ 'BG-06' => 'Vratsa',
685
+ 'BG-28' => 'Yambol'
686
+ );
687
+
688
+ return apply_filters( 'edd_bulgarian_states', $states );
689
+ }
690
+
691
  /**
692
  * Get Hong Kong States
693
  *
696
  */
697
  function edd_get_hong_kong_states_list() {
698
  $states = array(
699
+ '' => '',
700
  'HONG KONG' => 'Hong Kong Island',
701
  'KOWLOON' => 'Kowloon',
702
  'NEW TERRITORIES' => 'New Territories'
713
  */
714
  function edd_get_hungary_states_list() {
715
  $states = array(
716
+ '' => '',
717
  'BK' => 'Bács-Kiskun',
718
  'BE' => 'Békés',
719
  'BA' => 'Baranya',
739
  return apply_filters( 'edd_hungary_states', $states );
740
  }
741
 
742
+ /**
743
+ * Get Japanese States
744
+ *
745
+ * @since 2.2.3
746
+ * @return array $states A list of states
747
+ */
748
+ function edd_get_japanese_states_list() {
749
+ $states = array(
750
+ '' => '',
751
+ 'JP01' => 'Hokkaido',
752
+ 'JP02' => 'Aomori',
753
+ 'JP03' => 'Iwate',
754
+ 'JP04' => 'Miyagi',
755
+ 'JP05' => 'Akita',
756
+ 'JP06' => 'Yamagata',
757
+ 'JP07' => 'Fukushima',
758
+ 'JP08' => 'Ibaraki',
759
+ 'JP09' => 'Tochigi',
760
+ 'JP10' => 'Gunma',
761
+ 'JP11' => 'Saitama',
762
+ 'JP12' => 'Chiba',
763
+ 'JP13' => 'Tokyo',
764
+ 'JP14' => 'Kanagawa',
765
+ 'JP15' => 'Niigata',
766
+ 'JP16' => 'Toyama',
767
+ 'JP17' => 'Ishikawa',
768
+ 'JP18' => 'Fukui',
769
+ 'JP19' => 'Yamanashi',
770
+ 'JP20' => 'Nagano',
771
+ 'JP21' => 'Gifu',
772
+ 'JP22' => 'Shizuoka',
773
+ 'JP23' => 'Aichi',
774
+ 'JP24' => 'Mie',
775
+ 'JP25' => 'Shiga',
776
+ 'JP26' => 'Kyouto',
777
+ 'JP27' => 'Osaka',
778
+ 'JP28' => 'Hyougo',
779
+ 'JP29' => 'Nara',
780
+ 'JP30' => 'Wakayama',
781
+ 'JP31' => 'Tottori',
782
+ 'JP32' => 'Shimane',
783
+ 'JP33' => 'Okayama',
784
+ 'JP34' => 'Hiroshima',
785
+ 'JP35' => 'Yamaguchi',
786
+ 'JP36' => 'Tokushima',
787
+ 'JP37' => 'Kagawa',
788
+ 'JP38' => 'Ehime',
789
+ 'JP39' => 'Kochi',
790
+ 'JP40' => 'Fukuoka',
791
+ 'JP41' => 'Saga',
792
+ 'JP42' => 'Nagasaki',
793
+ 'JP43' => 'Kumamoto',
794
+ 'JP44' => 'Oita',
795
+ 'JP45' => 'Miyazaki',
796
+ 'JP46' => 'Kagoshima',
797
+ 'JP47' => 'Okinawa'
798
+ );
799
+
800
+ return apply_filters( 'edd_japanese_states', $states );
801
+ }
802
+
803
  /**
804
  * Get Chinese States
805
  *
808
  */
809
  function edd_get_chinese_states_list() {
810
  $states = array(
811
+ '' => '',
812
  'CN1' => 'Yunnan / &#20113;&#21335;',
813
  'CN2' => 'Beijing / &#21271;&#20140;',
814
  'CN3' => 'Tianjin / &#22825;&#27941;',
854
  */
855
  function edd_get_new_zealand_states_list() {
856
  $states = array(
857
+ '' => '',
858
  'AK' => 'Auckland',
859
  'BP' => 'Bay of Plenty',
860
  'CT' => 'Canterbury',
875
  return apply_filters( 'edd_new_zealand_states', $states );
876
  }
877
 
878
+ /**
879
+ * Get Peruvian States
880
+ *
881
+ * @since 2.2.3
882
+ * @return array $states A list of states
883
+ */
884
+ function edd_get_peruvian_states_list() {
885
+ $states = array(
886
+ '' => '',
887
+ 'CAL' => 'El Callao',
888
+ 'LMA' => 'Municipalidad Metropolitana de Lima',
889
+ 'AMA' => 'Amazonas',
890
+ 'ANC' => 'Ancash',
891
+ 'APU' => 'Apur&iacute;mac',
892
+ 'ARE' => 'Arequipa',
893
+ 'AYA' => 'Ayacucho',
894
+ 'CAJ' => 'Cajamarca',
895
+ 'CUS' => 'Cusco',
896
+ 'HUV' => 'Huancavelica',
897
+ 'HUC' => 'Hu&aacute;nuco',
898
+ 'ICA' => 'Ica',
899
+ 'JUN' => 'Jun&iacute;n',
900
+ 'LAL' => 'La Libertad',
901
+ 'LAM' => 'Lambayeque',
902
+ 'LIM' => 'Lima',
903
+ 'LOR' => 'Loreto',
904
+ 'MDD' => 'Madre de Dios',
905
+ 'MOQ' => 'Moquegua',
906
+ 'PAS' => 'Pasco',
907
+ 'PIU' => 'Piura',
908
+ 'PUN' => 'Puno',
909
+ 'SAM' => 'San Mart&iacute;n',
910
+ 'TAC' => 'Tacna',
911
+ 'TUM' => 'Tumbes',
912
+ 'UCA' => 'Ucayali'
913
+ );
914
+
915
+ return apply_filters( 'edd_peruvian_states', $states );
916
+ }
917
+
918
  /**
919
  * Get Indonesian States
920
  *
923
  */
924
  function edd_get_indonesian_states_list() {
925
  $states = array(
926
+ '' => '',
927
  'AC' => 'Daerah Istimewa Aceh',
928
  'SU' => 'Sumatera Utara',
929
  'SB' => 'Sumatera Barat',
971
  */
972
  function edd_get_indian_states_list() {
973
  $states = array(
974
+ '' => '',
975
+ 'AP' => 'Andhra Pradesh',
976
  'AR' => 'Arunachal Pradesh',
977
  'AS' => 'Assam',
978
  'BR' => 'Bihar',
996
  'RJ' => 'Rajasthan',
997
  'SK' => 'Sikkim',
998
  'TN' => 'Tamil Nadu',
999
+ 'TG' => 'Telangana',
1000
  'TR' => 'Tripura',
1001
+ 'UT' => 'Uttarakhand',
1002
  'UP' => 'Uttar Pradesh',
1003
  'WB' => 'West Bengal',
1004
  'AN' => 'Andaman and Nicobar Islands',
1006
  'DN' => 'Dadar and Nagar Haveli',
1007
  'DD' => 'Daman and Diu',
1008
  'DL' => 'Delhi',
1009
+ 'LD' => 'Lakshadweep',
1010
  'PY' => 'Pondicherry (Puducherry)'
1011
  );
1012
 
1013
  return apply_filters( 'edd_indian_states', $states );
1014
  }
1015
 
1016
+ /**
1017
+ * Get Iranian States
1018
+ *
1019
+ * @since 2.2.3
1020
+ * @return array $states A list of states
1021
+ */
1022
+ function edd_get_iranian_states_list() {
1023
+ $states = array(
1024
+ '' => '',
1025
+ 'KHZ' => 'Khuzestan',
1026
+ 'THR' => 'Tehran',
1027
+ 'ILM' => 'Ilaam',
1028
+ 'BHR' => 'Bushehr',
1029
+ 'ADL' => 'Ardabil',
1030
+ 'ESF' => 'Isfahan',
1031
+ 'YZD' => 'Yazd',
1032
+ 'KRH' => 'Kermanshah',
1033
+ 'KRN' => 'Kerman',
1034
+ 'HDN' => 'Hamadan',
1035
+ 'GZN' => 'Ghazvin',
1036
+ 'ZJN' => 'Zanjan',
1037
+ 'LRS' => 'Luristan',
1038
+ 'ABZ' => 'Alborz',
1039
+ 'EAZ' => 'East Azerbaijan',
1040
+ 'WAZ' => 'West Azerbaijan',
1041
+ 'CHB' => 'Chaharmahal and Bakhtiari',
1042
+ 'SKH' => 'South Khorasan',
1043
+ 'RKH' => 'Razavi Khorasan',
1044
+ 'NKH' => 'North Khorasan',
1045
+ 'SMN' => 'Semnan',
1046
+ 'FRS' => 'Fars',
1047
+ 'QHM' => 'Qom',
1048
+ 'KRD' => 'Kurdistan',
1049
+ 'KBD' => 'Kohgiluyeh and BoyerAhmad',
1050
+ 'GLS' => 'Golestan',
1051
+ 'GIL' => 'Gilan',
1052
+ 'MZN' => 'Mazandaran',
1053
+ 'MKZ' => 'Markazi',
1054
+ 'HRZ' => 'Hormozgan',
1055
+ 'SBN' => 'Sistan and Baluchestan'
1056
+ );
1057
+
1058
+ return apply_filters( 'edd_iranian_states', $states );
1059
+ }
1060
+
1061
+ /**
1062
+ * Get Italian Provinces
1063
+ *
1064
+ * @since 2.2.3
1065
+ * @return array $states A list of states
1066
+ */
1067
+ function edd_get_italian_states_list() {
1068
+ $states = array(
1069
+ '' => '',
1070
+ 'AG' => 'Agrigento',
1071
+ 'AL' => 'Alessandria',
1072
+ 'AN' => 'Ancona',
1073
+ 'AO' => 'Aosta',
1074
+ 'AR' => 'Arezzo',
1075
+ 'AP' => 'Ascoli Piceno',
1076
+ 'AT' => 'Asti',
1077
+ 'AV' => 'Avellino',
1078
+ 'BA' => 'Bari',
1079
+ 'BT' => 'Barletta-Andria-Trani',
1080
+ 'BL' => 'Belluno',
1081
+ 'BN' => 'Benevento',
1082
+ 'BG' => 'Bergamo',
1083
+ 'BI' => 'Biella',
1084
+ 'BO' => 'Bologna',
1085
+ 'BZ' => 'Bolzano',
1086
+ 'BS' => 'Brescia',
1087
+ 'BR' => 'Brindisi',
1088
+ 'CA' => 'Cagliari',
1089
+ 'CL' => 'Caltanissetta',
1090
+ 'CB' => 'Campobasso',
1091
+ 'CI' => 'Caltanissetta',
1092
+ 'CE' => 'Caserta',
1093
+ 'CT' => 'Catania',
1094
+ 'CZ' => 'Catanzaro',
1095
+ 'CH' => 'Chieti',
1096
+ 'CO' => 'Como',
1097
+ 'CS' => 'Cosenza',
1098
+ 'CR' => 'Cremona',
1099
+ 'KR' => 'Crotone',
1100
+ 'CN' => 'Cuneo',
1101
+ 'EN' => 'Enna',
1102
+ 'FM' => 'Fermo',
1103
+ 'FE' => 'Ferrara',
1104
+ 'FI' => 'Firenze',
1105
+ 'FG' => 'Foggia',
1106
+ 'FC' => 'Forli-Cesena',
1107
+ 'FR' => 'Frosinone',
1108
+ 'GE' => 'Genova',
1109
+ 'GO' => 'Gorizia',
1110
+ 'GR' => 'Grosseto',
1111
+ 'IM' => 'Imperia',
1112
+ 'IS' => 'Isernia',
1113
+ 'SP' => 'La Spezia',
1114
+ 'AQ' => 'L&apos;Aquila',
1115
+ 'LT' => 'Latina',
1116
+ 'LE' => 'Lecce',
1117
+ 'LC' => 'Lecco',
1118
+ 'LI' => 'Livorno',
1119
+ 'LO' => 'Lodi',
1120
+ 'LU' => 'Lucca',
1121
+ 'MC' => 'Macerata',
1122
+ 'MN' => 'Mantova',
1123
+ 'MS' => 'Massa-Carrara',
1124
+ 'MT' => 'Matera',
1125
+ 'ME' => 'Messina',
1126
+ 'MI' => 'Milano',
1127
+ 'MO' => 'Modena',
1128
+ 'MB' => 'Monza e della Brianza',
1129
+ 'NA' => 'Napoli',
1130
+ 'NO' => 'Novara',
1131
+ 'NU' => 'Nuoro',
1132
+ 'OT' => 'Olbia-Tempio',
1133
+ 'OR' => 'Oristano',
1134
+ 'PD' => 'Padova',
1135
+ 'PA' => 'Palermo',
1136
+ 'PR' => 'Parma',
1137
+ 'PV' => 'Pavia',
1138
+ 'PG' => 'Perugia',
1139
+ 'PU' => 'Pesaro e Urbino',
1140
+ 'PE' => 'Pescara',
1141
+ 'PC' => 'Piacenza',
1142
+ 'PI' => 'Pisa',
1143
+ 'PT' => 'Pistoia',
1144
+ 'PN' => 'Pordenone',
1145
+ 'PZ' => 'Potenza',
1146
+ 'PO' => 'Prato',
1147
+ 'RG' => 'Ragusa',
1148
+ 'RA' => 'Ravenna',
1149
+ 'RC' => 'Reggio Calabria',
1150
+ 'RE' => 'Reggio Emilia',
1151
+ 'RI' => 'Rieti',
1152
+ 'RN' => 'Rimini',
1153
+ 'RM' => 'Roma',
1154
+ 'RO' => 'Rovigo',
1155
+ 'SA' => 'Salerno',
1156
+ 'VS' => 'Medio Campidano',
1157
+ 'SS' => 'Sassari',
1158
+ 'SV' => 'Savona',
1159
+ 'SI' => 'Siena',
1160
+ 'SR' => 'Siracusa',
1161
+ 'SO' => 'Sondrio',
1162
+ 'TA' => 'Taranto',
1163
+ 'TE' => 'Teramo',
1164
+ 'TR' => 'Terni',
1165
+ 'TO' => 'Torino',
1166
+ 'OG' => 'Ogliastra',
1167
+ 'TP' => 'Trapani',
1168
+ 'TN' => 'Trento',
1169
+ 'TV' => 'Treviso',
1170
+ 'TS' => 'Trieste',
1171
+ 'UD' => 'Udine',
1172
+ 'VA' => 'Varesa',
1173
+ 'VE' => 'Venezia',
1174
+ 'VB' => 'Verbano-Cusio-Ossola',
1175
+ 'VC' => 'Vercelli',
1176
+ 'VR' => 'Verona',
1177
+ 'VV' => 'Vibo Valentia',
1178
+ 'VI' => 'Vicenza',
1179
+ 'VT' => 'Viterbo'
1180
+ );
1181
+
1182
+ return apply_filters( 'edd_italian_states', $states );
1183
+ }
1184
+
1185
  /**
1186
  * Get Malaysian States
1187
  *
1190
  */
1191
  function edd_get_malaysian_states_list() {
1192
  $states = array(
1193
+ '' => '',
1194
  'JHR' => 'Johor',
1195
  'KDH' => 'Kedah',
1196
  'KTN' => 'Kelantan',
1212
  return apply_filters( 'edd_malaysian_states', $states );
1213
  }
1214
 
1215
+ /**
1216
+ * Get Mexican States
1217
+ *
1218
+ * @since 2.2.3
1219
+ * @return array $states A list of states
1220
+ */
1221
+ function edd_get_mexican_states_list() {
1222
+ $states = array(
1223
+ '' => '',
1224
+ 'DIF' => 'Distrito Federal',
1225
+ 'JAL' => 'Jalisco',
1226
+ 'NLE' => 'Nuevo Le&oacute;n',
1227
+ 'AGU' => 'Aguascalientes',
1228
+ 'BCN' => 'Baja California Norte',
1229
+ 'BCS' => 'Baja California Sur',
1230
+ 'CAM' => 'Campeche',
1231
+ 'CHP' => 'Chiapas',
1232
+ 'CHH' => 'Chihuahua',
1233
+ 'COA' => 'Coahuila',
1234
+ 'COL' => 'Colima',
1235
+ 'DUR' => 'Durango',
1236
+ 'GUA' => 'Guanajuato',
1237
+ 'GRO' => 'Guerrero',
1238
+ 'HID' => 'Hidalgo',
1239
+ 'MEX' => 'Edo. de M&eacute;xico',
1240
+ 'MIC' => 'Michoac&aacute;n',
1241
+ 'MOR' => 'Morelos',
1242
+ 'NAY' => 'Nayarit',
1243
+ 'OAX' => 'Oaxaca',
1244
+ 'PUE' => 'Puebla',
1245
+ 'QUE' => 'Quer&eacute;taro',
1246
+ 'ROO' => 'Quintana Roo',
1247
+ 'SLP' => 'San Luis Potos&iacute;',
1248
+ 'SIN' => 'Sinaloa',
1249
+ 'SON' => 'Sonora',
1250
+ 'TAB' => 'Tabasco',
1251
+ 'TAM' => 'Tamaulipas',
1252
+ 'TLA' => 'Tlaxcala',
1253
+ 'VER' => 'Veracruz',
1254
+ 'YUC' => 'Yucat&aacute;n',
1255
+ 'ZAC' => 'Zacatecas'
1256
+ );
1257
+
1258
+ return apply_filters( 'edd_mexican_states', $states );
1259
+ }
1260
+
1261
+ /**
1262
+ * Get Nepalese States (Districts)
1263
+ *
1264
+ * @since 2.2.3
1265
+ * @return array $states A list of states
1266
+ */
1267
+ function edd_get_nepalese_states_list() {
1268
+ $states = array(
1269
+ '' => '',
1270
+ 'ILL' => 'Illam',
1271
+ 'JHA' => 'Jhapa',
1272
+ 'PAN' => 'Panchthar',
1273
+ 'TAP' => 'Taplejung',
1274
+ 'BHO' => 'Bhojpur',
1275
+ 'DKA' => 'Dhankuta',
1276
+ 'MOR' => 'Morang',
1277
+ 'SUN' => 'Sunsari',
1278
+ 'SAN' => 'Sankhuwa',
1279
+ 'TER' => 'Terhathum',
1280
+ 'KHO' => 'Khotang',
1281
+ 'OKH' => 'Okhaldhunga',
1282
+ 'SAP' => 'Saptari',
1283
+ 'SIR' => 'Siraha',
1284
+ 'SOL' => 'Solukhumbu',
1285
+ 'UDA' => 'Udayapur',
1286
+ 'DHA' => 'Dhanusa',
1287
+ 'DLK' => 'Dolakha',
1288
+ 'MOH' => 'Mohottari',
1289
+ 'RAM' => 'Ramechha',
1290
+ 'SAR' => 'Sarlahi',
1291
+ 'SIN' => 'Sindhuli',
1292
+ 'BHA' => 'Bhaktapur',
1293
+ 'DHD' => 'Dhading',
1294
+ 'KTM' => 'Kathmandu',
1295
+ 'KAV' => 'Kavrepalanchowk',
1296
+ 'LAL' => 'Lalitpur',
1297
+ 'NUW' => 'Nuwakot',
1298
+ 'RAS' => 'Rasuwa',
1299
+ 'SPC' => 'Sindhupalchowk',
1300
+ 'BAR' => 'Bara',
1301
+ 'CHI' => 'Chitwan',
1302
+ 'MAK' => 'Makwanpur',
1303
+ 'PAR' => 'Parsa',
1304
+ 'RAU' => 'Rautahat',
1305
+ 'GOR' => 'Gorkha',
1306
+ 'KAS' => 'Kaski',
1307
+ 'LAM' => 'Lamjung',
1308
+ 'MAN' => 'Manang',
1309
+ 'SYN' => 'Syangja',
1310
+ 'TAN' => 'Tanahun',
1311
+ 'BAG' => 'Baglung',
1312
+ 'PBT' => 'Parbat',
1313
+ 'MUS' => 'Mustang',
1314
+ 'MYG' => 'Myagdi',
1315
+ 'AGR' => 'Agrghakanchi',
1316
+ 'GUL' => 'Gulmi',
1317
+ 'KAP' => 'Kapilbastu',
1318
+ 'NAW' => 'Nawalparasi',
1319
+ 'PAL' => 'Palpa',
1320
+ 'RUP' => 'Rupandehi',
1321
+ 'DAN' => 'Dang',
1322
+ 'PYU' => 'Pyuthan',
1323
+ 'ROL' => 'Rolpa',
1324
+ 'RUK' => 'Rukum',
1325
+ 'SAL' => 'Salyan',
1326
+ 'BAN' => 'Banke',
1327
+ 'BDA' => 'Bardiya',
1328
+ 'DAI' => 'Dailekh',
1329
+ 'JAJ' => 'Jajarkot',
1330
+ 'SUR' => 'Surkhet',
1331
+ 'DOL' => 'Dolpa',
1332
+ 'HUM' => 'Humla',
1333
+ 'JUM' => 'Jumla',
1334
+ 'KAL' => 'Kalikot',
1335
+ 'MUG' => 'Mugu',
1336
+ 'ACH' => 'Achham',
1337
+ 'BJH' => 'Bajhang',
1338
+ 'BJU' => 'Bajura',
1339
+ 'DOT' => 'Doti',
1340
+ 'KAI' => 'Kailali',
1341
+ 'BAI' => 'Baitadi',
1342
+ 'DAD' => 'Dadeldhura',
1343
+ 'DAR' => 'Darchula',
1344
+ 'KAN' => 'Kanchanpur'
1345
+ );
1346
+
1347
+ return apply_filters( 'edd_nepalese_states', $states );
1348
+ }
1349
+
1350
  /**
1351
  * Get South African States
1352
  *
1355
  */
1356
  function edd_get_south_african_states_list() {
1357
  $states = array(
1358
+ '' => '',
1359
  'EC' => 'Eastern Cape',
1360
  'FS' => 'Free State',
1361
  'GP' => 'Gauteng',
1378
  */
1379
  function edd_get_thailand_states_list() {
1380
  $states = array(
1381
+ '' => '',
1382
  'TH-37' => 'Amnat Charoen (&#3629;&#3635;&#3609;&#3634;&#3592;&#3648;&#3592;&#3619;&#3636;&#3597;)',
1383
  'TH-15' => 'Ang Thong (&#3629;&#3656;&#3634;&#3591;&#3607;&#3629;&#3591;)',
1384
  'TH-14' => 'Ayutthaya (&#3614;&#3619;&#3632;&#3609;&#3588;&#3619;&#3624;&#3619;&#3637;&#3629;&#3618;&#3640;&#3608;&#3618;&#3634;)',
1460
 
1461
  return apply_filters( 'edd_thailand_states', $states );
1462
  }
1463
+
1464
+ /**
1465
+ * Get Turkey States
1466
+ *
1467
+ * @since 2.2.3
1468
+ * @return array $states A list of states
1469
+ */
1470
+ function edd_get_turkey_states_list() {
1471
+ $states = array(
1472
+ '' => '',
1473
+ 'TR01' => 'Adana',
1474
+ 'TR02' => 'Ad&#305;yaman',
1475
+ 'TR03' => 'Afyon',
1476
+ 'TR04' => 'A&#287;r&#305;',
1477
+ 'TR05' => 'Amasya',
1478
+ 'TR06' => 'Ankara',
1479
+ 'TR07' => 'Antalya',
1480
+ 'TR08' => 'Artvin',
1481
+ 'TR09' => 'Ayd&#305;n',
1482
+ 'TR10' => 'Bal&#305;kesir',
1483
+ 'TR11' => 'Bilecik',
1484
+ 'TR12' => 'Bing&#246;l',
1485
+ 'TR13' => 'Bitlis',
1486
+ 'TR14' => 'Bolu',
1487
+ 'TR15' => 'Burdur',
1488
+ 'TR16' => 'Bursa',
1489
+ 'TR17' => '&#199;anakkale',
1490
+ 'TR18' => '&#199;ank&#305;kesir',
1491
+ 'TR19' => '&#199;orum',
1492
+ 'TR20' => 'Denizli',
1493
+ 'TR21' => 'Diyarbak&#305;r',
1494
+ 'TR22' => 'Edirne',
1495
+ 'TR23' => 'Elaz&#305;&#287;',
1496
+ 'TR24' => 'Erzincan',
1497
+ 'TR25' => 'Erzurum',
1498
+ 'TR26' => 'Eski&#351;ehir',
1499
+ 'TR27' => 'Gaziantep',
1500
+ 'TR28' => 'Giresun',
1501
+ 'TR29' => 'G&#252;m&#252;&#351;hane',
1502
+ 'TR30' => 'Hakkari',
1503
+ 'TR31' => 'Hatay',
1504
+ 'TR32' => 'Isparta',
1505
+ 'TR33' => '&#304;&#231;el',
1506
+ 'TR34' => '&#304;stanbul',
1507
+ 'TR35' => '&#304;zmir',
1508
+ 'TR36' => 'Kars',
1509
+ 'TR37' => 'Kastamonu',
1510
+ 'TR38' => 'Kayseri',
1511
+ 'TR39' => 'K&#305;rklareli',
1512
+ 'TR40' => 'K&#305;r&#351;ehir',
1513
+ 'TR41' => 'Kocaeli',
1514
+ 'TR42' => 'Konya',
1515
+ 'TR43' => 'K&#252;tahya',
1516
+ 'TR44' => 'Malatya',
1517
+ 'TR45' => 'Manisa',
1518
+ 'TR46' => 'Kahramanmara&#351;',
1519
+ 'TR47' => 'Mardin',
1520
+ 'TR48' => 'Mu&#287;la',
1521
+ 'TR49' => 'Mu&#351;',
1522
+ 'TR50' => 'Nev&#351;ehir',
1523
+ 'TR51' => 'Ni&#287;de',
1524
+ 'TR52' => 'Ordu',
1525
+ 'TR53' => 'Rize',
1526
+ 'TR54' => 'Sakarya',
1527
+ 'TR55' => 'Samsun',
1528
+ 'TR56' => 'Siirt',
1529
+ 'TR57' => 'Sinop',
1530
+ 'TR58' => 'Sivas',
1531
+ 'TR59' => 'Tekirda&#287;',
1532
+ 'TR60' => 'Tokat',
1533
+ 'TR61' => 'Trabzon',
1534
+ 'TR62' => 'Tunceli',
1535
+ 'TR63' => '&#350;anl&#305;urfa',
1536
+ 'TR64' => 'U&#351;ak',
1537
+ 'TR65' => 'Van',
1538
+ 'TR66' => 'Yozgat',
1539
+ 'TR67' => 'Zonguldak',
1540
+ 'TR68' => 'Aksaray',
1541
+ 'TR69' => 'Bayburt',
1542
+ 'TR70' => 'Karaman',
1543
+ 'TR71' => 'K&#305;r&#305;kkale',
1544
+ 'TR72' => 'Batman',
1545
+ 'TR73' => '&#350;&#305;rnak',
1546
+ 'TR74' => 'Bart&#305;n',
1547
+ 'TR75' => 'Ardahan',
1548
+ 'TR76' => 'I&#287;d&#305;r',
1549
+ 'TR77' => 'Yalova',
1550
+ 'TR78' => 'Karab&#252;k',
1551
+ 'TR79' => 'Kilis',
1552
+ 'TR80' => 'Osmaniye',
1553
+ 'TR81' => 'D&#252;zce'
1554
+ );
1555
+
1556
+ return apply_filters( 'edd_turkey_states', $states );
1557
+ }
1558
+
1559
+ /**
1560
+ * Get Spain States
1561
+ *
1562
+ * @since 2.2
1563
+ * @return array $states A list of states
1564
+ */
1565
+ function edd_get_spain_states_list() {
1566
+ $states = array(
1567
+ '' => '',
1568
+ 'C' => __( 'A Coru&ntilde;a', 'edd' ),
1569
+ 'VI' => __( 'Araba', 'edd' ),
1570
+ 'AB' => __( 'Albacete', 'edd' ),
1571
+ 'A' => __( 'Alicante', 'edd' ),
1572
+ 'AL' => __( 'Almer&iacute;a', 'edd' ),
1573
+ 'O' => __( 'Asturias', 'edd' ),
1574
+ 'AV' => __( '&Aacute;vila', 'edd' ),
1575
+ 'BA' => __( 'Badajoz', 'edd' ),
1576
+ 'PM' => __( 'Baleares', 'edd' ),
1577
+ 'B' => __( 'Barcelona', 'edd' ),
1578
+ 'BU' => __( 'Burgos', 'edd' ),
1579
+ 'CC' => __( 'C&aacute;ceres', 'edd' ),
1580
+ 'CA' => __( 'C&aacute;diz', 'edd' ),
1581
+ 'S' => __( 'Cantabria', 'edd' ),
1582
+ 'CS' => __( 'Castell&oacute;n', 'edd' ),
1583
+ 'CE' => __( 'Ceuta', 'edd' ),
1584
+ 'CR' => __( 'Ciudad Real', 'edd' ),
1585
+ 'CO' => __( 'C&oacute;rdoba', 'edd' ),
1586
+ 'CU' => __( 'Cuenca', 'edd' ),
1587
+ 'GI' => __( 'Girona', 'edd' ),
1588
+ 'GR' => __( 'Granada', 'edd' ),
1589
+ 'GU' => __( 'Guadalajara', 'edd' ),
1590
+ 'SS' => __( 'Gipuzkoa', 'edd' ),
1591
+ 'H' => __( 'Huelva', 'edd' ),
1592
+ 'HU' => __( 'Huesca', 'edd' ),
1593
+ 'J' => __( 'Ja&eacute;n', 'edd' ),
1594
+ 'LO' => __( 'La Rioja', 'edd' ),
1595
+ 'GC' => __( 'Las Palmas', 'edd' ),
1596
+ 'LE' => __( 'Le&oacute;n', 'edd' ),
1597
+ 'L' => __( 'Lleida', 'edd' ),
1598
+ 'LU' => __( 'Lugo', 'edd' ),
1599
+ 'M' => __( 'Madrid', 'edd' ),
1600
+ 'MA' => __( 'M&aacute;laga', 'edd' ),
1601
+ 'ML' => __( 'Melilla', 'edd' ),
1602
+ 'MU' => __( 'Murcia', 'edd' ),
1603
+ 'NA' => __( 'Navarra', 'edd' ),
1604
+ 'OR' => __( 'Ourense', 'edd' ),
1605
+ 'P' => __( 'Palencia', 'edd' ),
1606
+ 'PO' => __( 'Pontevedra', 'edd' ),
1607
+ 'SA' => __( 'Salamanca', 'edd' ),
1608
+ 'TF' => __( 'Santa Cruz de Tenerife', 'edd' ),
1609
+ 'SG' => __( 'Segovia', 'edd' ),
1610
+ 'SE' => __( 'Sevilla', 'edd' ),
1611
+ 'SO' => __( 'Soria', 'edd' ),
1612
+ 'T' => __( 'Tarragona', 'edd' ),
1613
+ 'TE' => __( 'Teruel', 'edd' ),
1614
+ 'TO' => __( 'Toledo', 'edd' ),
1615
+ 'V' => __( 'Valencia', 'edd' ),
1616
+ 'VA' => __( 'Valladolid', 'edd' ),
1617
+ 'BI' => __( 'Bizkaia', 'edd' ),
1618
+ 'ZA' => __( 'Zamora', 'edd' ),
1619
+ 'Z' => __( 'Zaragoza', 'edd' )
1620
+ );
1621
+
1622
+ return apply_filters( 'edd_spain_states', $states );
1623
+ }
includes/deprecated-functions.php CHANGED
@@ -6,7 +6,7 @@
6
  *
7
  * @package EDD
8
  * @subpackage Deprecated
9
- * @copyright Copyright (c) 2014, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.0
12
  */
@@ -257,7 +257,7 @@ function edd_get_cart_amount( $add_taxes = true, $local_override = false ) {
257
 
258
  _edd_deprecated_function( __FUNCTION__, '1.9', 'edd_get_cart_subtotal() or edd_get_cart_total()', $backtrace );
259
 
260
- $amount = edd_get_cart_subtotal( false );
261
  if ( ! empty( $_POST['edd-discount'] ) || edd_get_cart_discounts() !== false ) {
262
  // Retrieve the discount stored in cookies
263
  $discounts = edd_get_cart_discounts();
@@ -350,3 +350,197 @@ function edd_get_sale_notification_template_tags() {
350
 
351
  return apply_filters( 'edd_sale_notification_template_tags_description', $tags );
352
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  *
7
  * @package EDD
8
  * @subpackage Deprecated
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11
  * @since 1.0
12
  */
257
 
258
  _edd_deprecated_function( __FUNCTION__, '1.9', 'edd_get_cart_subtotal() or edd_get_cart_total()', $backtrace );
259
 
260
+ $amount = edd_get_cart_subtotal( );
261
  if ( ! empty( $_POST['edd-discount'] ) || edd_get_cart_discounts() !== false ) {
262
  // Retrieve the discount stored in cookies
263
  $discounts = edd_get_cart_discounts();
350
 
351
  return apply_filters( 'edd_sale_notification_template_tags_description', $tags );
352
  }
353
+
354
+ /**
355
+ * Email Template Header
356
+ *
357
+ * @access private
358
+ * @since 1.0.8.2
359
+ * @deprecated 2.0
360
+ * @return string Email template header
361
+ */
362
+ function edd_get_email_body_header() {
363
+ $backtrace = debug_backtrace();
364
+
365
+ _edd_deprecated_function( __FUNCTION__, '2.0', '', $backtrace );
366
+
367
+ ob_start();
368
+ ?>
369
+ <html>
370
+ <head>
371
+ <style type="text/css">#outlook a { padding: 0; }</style>
372
+ </head>
373
+ <body dir="<?php echo is_rtl() ? 'rtl' : 'ltr'; ?>">
374
+ <?php
375
+ do_action( 'edd_email_body_header' );
376
+ return ob_get_clean();
377
+ }
378
+
379
+ /**
380
+ * Email Template Footer
381
+ *
382
+ * @since 1.0.8.2
383
+ * @deprecated 2.0
384
+ * @return string Email template footer
385
+ */
386
+ function edd_get_email_body_footer() {
387
+
388
+ $backtrace = debug_backtrace();
389
+
390
+ _edd_deprecated_function( __FUNCTION__, '2.0', '', $backtrace );
391
+
392
+ ob_start();
393
+ do_action( 'edd_email_body_footer' );
394
+ ?>
395
+ </body>
396
+ </html>
397
+ <?php
398
+ return ob_get_clean();
399
+ }
400
+
401
+ /**
402
+ * Applies the Chosen Email Template
403
+ *
404
+ * @since 1.0.8.2
405
+ * @deprecated 2.0
406
+ * @param string $body The contents of the receipt email
407
+ * @param int $payment_id The ID of the payment we are sending a receipt for
408
+ * @param array $payment_data An array of meta information for the payment
409
+ * @return string $email Formatted email with the template applied
410
+ */
411
+ function edd_apply_email_template( $body, $payment_id, $payment_data=array() ) {
412
+ global $edd_options;
413
+
414
+ $backtrace = debug_backtrace();
415
+
416
+ _edd_deprecated_function( __FUNCTION__, '2.0', '', $backtrace );
417
+
418
+ $template_name = isset( $edd_options['email_template'] ) ? $edd_options['email_template'] : 'default';
419
+ $template_name = apply_filters( 'edd_email_template', $template_name, $payment_id );
420
+
421
+ if ( $template_name == 'none' ) {
422
+ if ( is_admin() )
423
+ $body = edd_email_preview_template_tags( $body );
424
+
425
+ return $body; // Return the plain email with no template
426
+ }
427
+
428
+ ob_start();
429
+
430
+ do_action( 'edd_email_template_' . $template_name );
431
+
432
+ $template = ob_get_clean();
433
+
434
+ if ( is_admin() )
435
+ $body = edd_email_preview_template_tags( $body );
436
+
437
+ $body = apply_filters( 'edd_purchase_receipt_' . $template_name, $body );
438
+
439
+ $email = str_replace( '{email}', $body, $template );
440
+
441
+ return $email;
442
+
443
+ }
444
+
445
+ /**
446
+ * Checks if the user has enabled the option to calculate taxes after discounts
447
+ * have been entered
448
+ *
449
+ * @since 1.4.1
450
+ * @deprecated 2.1
451
+ * @global $edd_options
452
+ * @return bool Whether or not taxes are calculated after discount
453
+ */
454
+ function edd_taxes_after_discounts() {
455
+
456
+ $backtrace = debug_backtrace();
457
+
458
+ _edd_deprecated_function( __FUNCTION__, '2.1', 'none', $backtrace );
459
+
460
+ global $edd_options;
461
+ $ret = isset( $edd_options['taxes_after_discounts'] ) && edd_use_taxes();
462
+ return apply_filters( 'edd_taxes_after_discounts', $ret );
463
+ }
464
+
465
+ /**
466
+ * Verifies a download purchase using a purchase key and email.
467
+ *
468
+ * @deprecated Please avoid usage of this function in favor of the tokenized urls with edd_validate_url_token()
469
+ * introduced in EDD 2.3
470
+ *
471
+ * @since 1.0
472
+ *
473
+ * @param int $download_id
474
+ * @param string $key
475
+ * @param string $email
476
+ * @param string $expire
477
+ * @param int $file_key
478
+ *
479
+ * @return bool True if payment and link was verified, false otherwise
480
+ */
481
+ function edd_verify_download_link( $download_id = 0, $key = '', $email = '', $expire = '', $file_key = 0 ) {
482
+
483
+ $meta_query = array(
484
+ 'relation' => 'AND',
485
+ array(
486
+ 'key' => '_edd_payment_purchase_key',
487
+ 'value' => $key
488
+ ),
489
+ array(
490
+ 'key' => '_edd_payment_user_email',
491
+ 'value' => $email
492
+ )
493
+ );
494
+
495
+ $accepted_stati = apply_filters( 'edd_allowed_download_stati', array( 'publish', 'complete' ) );
496
+
497
+ $payments = get_posts( array( 'meta_query' => $meta_query, 'post_type' => 'edd_payment', 'post_status' => $accepted_stati ) );
498
+
499
+ if ( $payments ) {
500
+ foreach ( $payments as $payment ) {
501
+
502
+ $cart_details = edd_get_payment_meta_cart_details( $payment->ID, true );
503
+
504
+ if ( ! empty( $cart_details ) ) {
505
+ foreach ( $cart_details as $cart_key => $cart_item ) {
506
+
507
+ if ( $cart_item['id'] != $download_id )
508
+ continue;
509
+
510
+ $price_options = isset( $cart_item['item_number']['options'] ) ? $cart_item['item_number']['options'] : false;
511
+ $price_id = isset( $price_options['price_id'] ) ? $price_options['price_id'] : false;
512
+
513
+ $file_condition = edd_get_file_price_condition( $cart_item['id'], $file_key );
514
+
515
+ // Check to see if the file download limit has been reached
516
+ if ( edd_is_file_at_download_limit( $cart_item['id'], $payment->ID, $file_key, $price_id ) )
517
+ wp_die( apply_filters( 'edd_download_limit_reached_text', __( 'Sorry but you have hit your download limit for this file.', 'edd' ) ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
518
+
519
+ // If this download has variable prices, we have to confirm that this file was included in their purchase
520
+ if ( ! empty( $price_options ) && $file_condition != 'all' && edd_has_variable_prices( $cart_item['id'] ) ) {
521
+ if ( $file_condition == $price_options['price_id'] )
522
+ return $payment->ID;
523
+ }
524
+
525
+ // Make sure the link hasn't expired
526
+
527
+ if ( base64_encode( base64_decode( $expire, true ) ) === $expire ) {
528
+ $expire = base64_decode( $expire ); // If it is a base64 string, decode it. Old expiration dates were in base64
529
+ }
530
+
531
+ if ( current_time( 'timestamp' ) > $expire ) {
532
+ wp_die( apply_filters( 'edd_download_link_expired_text', __( 'Sorry but your download link has expired.', 'edd' ) ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
533
+ }
534
+ return $payment->ID; // Payment has been verified and link is still valid
535
+ }
536
+
537
+ }
538
+
539
+ }
540
+
541
+ } else {
542
+ wp_die( __( 'No payments matching your request were found.', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
543
+ }
544
+ // Payment not verified
545
+ return false;
546
+ }
includes/discount-functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -85,7 +85,7 @@ function edd_has_active_discounts() {
85
  * Retrieves a complete discount code by discount ID.
86
  *
87
  * @since 1.0
88
- * @param string $discount_id Discount ID
89
  * @return array
90
  */
91
  function edd_get_discount( $discount_id = 0 ) {
@@ -163,9 +163,9 @@ function edd_get_discount_by( $field = '', $value = '' ) {
163
  break;
164
 
165
  case 'name':
166
- $discount = query_posts( array(
167
  'post_type' => 'edd_discount',
168
- 'name' => sanitize_title( $value ),
169
  'posts_per_page' => 1,
170
  'post_status' => 'any'
171
  ) );
@@ -200,11 +200,13 @@ function edd_store_discount( $details, $discount_id = null ) {
200
 
201
  $meta = array(
202
  'code' => isset( $details['code'] ) ? $details['code'] : '',
 
 
203
  'uses' => isset( $details['uses'] ) ? $details['uses'] : '',
204
  'max_uses' => isset( $details['max'] ) ? $details['max'] : '',
205
  'amount' => isset( $details['amount'] ) ? $details['amount'] : '',
206
- 'start' => isset( $details['start'] ) ? $details['start'] : false,
207
- 'expiration' => isset( $details['expiration'] ) ? $details['expiration'] : false,
208
  'type' => isset( $details['type'] ) ? $details['type'] : '',
209
  'min_price' => isset( $details['min_price'] ) ? $details['min_price'] : '',
210
  'product_reqs' => isset( $details['products'] ) ? $details['products'] : array(),
@@ -214,49 +216,60 @@ function edd_store_discount( $details, $discount_id = null ) {
214
  'is_single_use' => isset( $details['use_once'] ) ? $details['use_once'] : false,
215
  );
216
 
217
- if( $meta['start'] ) {
218
- $meta['start'] = date( 'm/d/Y H:i:s', strtotime( $meta['start'] ) );
 
 
219
  }
220
 
221
- if( $meta['expiration'] ) {
222
- $meta['expiration'] = date( 'm/d/Y H:i:s', strtotime( date( 'm/d/Y', strtotime( $meta['expiration'] ) ) . ' 23:59:59' ) );
223
- if( ! empty( $meta['start'] ) && $meta['start'] > $meta['expiration'] ) {
 
 
 
 
224
  // Set the expiration date to the start date if start is later than expiration
225
  $meta['expiration'] = $meta['start'];
 
226
  }
 
227
  }
228
 
229
  if ( edd_discount_exists( $discount_id ) && ! empty( $discount_id ) ) {
 
230
  // Update an existing discount
231
 
232
- $details = apply_filters( 'edd_update_discount', $details, $discount_id );
233
 
234
- do_action( 'edd_pre_update_discount', $details, $discount_id );
235
 
236
  wp_update_post( array(
237
  'ID' => $discount_id,
238
- 'post_title' => $details['name'],
239
- 'post_status' => $details['status']
240
  ) );
241
 
242
  foreach( $meta as $key => $value ) {
243
  update_post_meta( $discount_id, '_edd_discount_' . $key, $value );
244
  }
245
 
246
- do_action( 'edd_post_update_discount', $details, $discount_id );
247
 
248
  // Discount code updated
249
  return $discount_id;
 
250
  } else {
 
251
  // Add the discount
252
 
253
- $details = apply_filters( 'edd_insert_discount', $details );
254
 
255
- do_action( 'edd_pre_insert_discount', $details );
256
 
257
  $discount_id = wp_insert_post( array(
258
  'post_type' => 'edd_discount',
259
- 'post_title' => isset( $details['name'] ) ? $details['name'] : '',
260
  'post_status' => 'active'
261
  ) );
262
 
@@ -264,11 +277,12 @@ function edd_store_discount( $details, $discount_id = null ) {
264
  update_post_meta( $discount_id, '_edd_discount_' . $key, $value );
265
  }
266
 
267
- do_action( 'edd_post_insert_discount', $details, $discount_id );
268
 
269
  // Discount code created
270
  return $discount_id;
271
  }
 
272
  }
273
 
274
 
@@ -516,7 +530,7 @@ function edd_get_discount_product_condition( $code_id = 0 ) {
516
  * @since 1.5
517
  * @param int $code_id Discount ID
518
  * @return array $product_reqs IDs of the required products
519
- * @return bool Whether or not discount code is global
520
  */
521
  function edd_is_discount_not_global( $code_id = 0 ) {
522
  return (bool) get_post_meta( $code_id, '_edd_discount_is_not_global', true );
@@ -668,12 +682,27 @@ function edd_discount_product_reqs_met( $code_id = null ) {
668
  $cart_ids = $cart_items ? wp_list_pluck( $cart_items, 'id' ) : null;
669
  $ret = false;
670
 
671
- if ( empty( $product_reqs ) ) {
672
  $ret = true;
673
  }
674
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
675
  // Ensure we have requirements before proceeding
676
- if ( ! $ret ) {
 
677
  switch( $condition ) {
678
  case 'all' :
679
  // Default back to true
@@ -691,19 +720,30 @@ function edd_discount_product_reqs_met( $code_id = null ) {
691
 
692
  default : // Any
693
  foreach ( $product_reqs as $download_id ) {
 
694
  if ( edd_item_in_cart( $download_id ) ) {
695
  $ret = true;
696
  break;
697
- } else {
698
- edd_set_error( 'edd-discount-error', __( 'The product requirements for this discount are not met.', 'edd' ) );
699
  }
 
 
 
 
 
 
 
700
  }
701
 
702
  break;
703
  }
 
 
 
 
 
704
  }
705
 
706
- if( $excluded_ps ) {
707
  // Check that there are products other than excluded ones in the cart
708
  if( $cart_ids == $excluded_ps ) {
709
  edd_set_error( 'edd-discount-error', __( 'This discount is not valid for the cart contents.', 'edd' ) );
@@ -794,7 +834,7 @@ function edd_is_discount_used( $code = null, $user = '', $code_id = 0 ) {
794
  * @param string $user User info
795
  * @return bool
796
  */
797
- function edd_is_discount_valid( $code = '', $user = '' ) {
798
 
799
 
800
  $return = false;
@@ -814,7 +854,7 @@ function edd_is_discount_valid( $code = '', $user = '' ) {
814
  ) {
815
  $return = true;
816
  }
817
- } else {
818
  edd_set_error( 'edd-discount-error', __( 'This discount is invalid.', 'edd' ) );
819
  }
820
 
@@ -926,7 +966,7 @@ function edd_format_discount_rate( $type, $amount ) {
926
  *
927
  * @since 1.4.1
928
  * @param string $code Discount code
929
- * @return array All currently active discounts
930
  */
931
  function edd_set_cart_discount( $code = '' ) {
932
 
@@ -1023,7 +1063,7 @@ function edd_cart_has_discounts() {
1023
  */
1024
  function edd_get_cart_discounted_amount( $discounts = false ) {
1025
 
1026
- $amount = 0;
1027
  $items = edd_get_cart_content_details();
1028
  if( $items ) {
1029
 
@@ -1047,8 +1087,10 @@ function edd_get_cart_discounted_amount( $discounts = false ) {
1047
  */
1048
  function edd_get_cart_item_discount_amount( $item = array() ) {
1049
 
 
 
1050
  $amount = 0;
1051
- $price = edd_get_cart_item_price( $item['id'], $item['options'], edd_prices_include_tax() );
1052
  $discounted_price = $price;
1053
 
1054
  // Retrieve all discounts applied to the cart
@@ -1058,7 +1100,13 @@ function edd_get_cart_item_discount_amount( $item = array() ) {
1058
 
1059
  foreach ( $discounts as $discount ) {
1060
 
1061
- $code_id = edd_get_discount_id_by_code( $discount );
 
 
 
 
 
 
1062
  $reqs = edd_get_discount_product_reqs( $code_id );
1063
  $excluded_products = edd_get_discount_excluded_products( $code_id );
1064
 
@@ -1087,10 +1135,27 @@ function edd_get_cart_item_discount_amount( $item = array() ) {
1087
  * are distributed across all cart items. The discount amount is divided by the number
1088
  * of items in the cart and then a portion is evenly applied to each cart item
1089
  */
1090
-
1091
- $discounted_amount = edd_get_discount_amount( $code_id );
1092
- $discounted_amount = ( $discounted_amount / edd_get_cart_quantity() );
 
 
 
 
 
 
 
 
 
1093
  $discounted_price -= $discounted_amount;
 
 
 
 
 
 
 
 
1094
  } else {
1095
 
1096
  $discounted_price -= $price - edd_get_discounted_amount( $discount, $price );
@@ -1246,9 +1311,8 @@ add_action( 'edd_post_remove_from_cart', 'edd_maybe_remove_cart_discount' );
1246
  * @return bool
1247
  */
1248
  function edd_multiple_discounts_allowed() {
1249
- global $edd_options;
1250
- $ret = isset( $edd_options['allow_multiple_discounts'] );
1251
- return apply_filters( 'edd_multiple_discounts_allowed', $ret );
1252
  }
1253
 
1254
  /**
@@ -1259,21 +1323,38 @@ function edd_multiple_discounts_allowed() {
1259
  */
1260
  function edd_listen_for_cart_discount() {
1261
 
1262
- if( ! edd_is_checkout() ) {
1263
  return;
1264
  }
1265
 
1266
- if( empty( $_REQUEST['discount'] ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1267
  return;
1268
  }
1269
 
1270
- $code = sanitize_text_field( $_REQUEST['discount'] );
1271
-
1272
- if( ! edd_is_discount_valid( $code ) ) {
1273
  return;
1274
  }
1275
 
 
 
1276
  edd_set_cart_discount( $code );
1277
 
 
1278
  }
1279
- add_action( 'template_redirect', 'edd_listen_for_cart_discount', 500 );
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
85
  * Retrieves a complete discount code by discount ID.
86
  *
87
  * @since 1.0
88
+ * @param integer $discount_id Discount ID
89
  * @return array
90
  */
91
  function edd_get_discount( $discount_id = 0 ) {
163
  break;
164
 
165
  case 'name':
166
+ $discount = get_posts( array(
167
  'post_type' => 'edd_discount',
168
+ 'name' => $value,
169
  'posts_per_page' => 1,
170
  'post_status' => 'any'
171
  ) );
200
 
201
  $meta = array(
202
  'code' => isset( $details['code'] ) ? $details['code'] : '',
203
+ 'name' => isset( $details['name'] ) ? $details['name'] : '',
204
+ 'status' => isset( $details['status'] ) ? $details['status'] : 'active',
205
  'uses' => isset( $details['uses'] ) ? $details['uses'] : '',
206
  'max_uses' => isset( $details['max'] ) ? $details['max'] : '',
207
  'amount' => isset( $details['amount'] ) ? $details['amount'] : '',
208
+ 'start' => isset( $details['start'] ) ? $details['start'] : '',
209
+ 'expiration' => isset( $details['expiration'] ) ? $details['expiration'] : '',
210
  'type' => isset( $details['type'] ) ? $details['type'] : '',
211
  'min_price' => isset( $details['min_price'] ) ? $details['min_price'] : '',
212
  'product_reqs' => isset( $details['products'] ) ? $details['products'] : array(),
216
  'is_single_use' => isset( $details['use_once'] ) ? $details['use_once'] : false,
217
  );
218
 
219
+ $start_timestamp = strtotime( $meta['start'] );
220
+
221
+ if( ! empty( $meta['start'] ) ) {
222
+ $meta['start'] = date( 'm/d/Y H:i:s', $start_timestamp );
223
  }
224
 
225
+ if( ! empty( $meta['expiration'] ) ) {
226
+
227
+ $meta['expiration'] = date( 'm/d/Y H:i:s', strtotime( date( 'm/d/Y', strtotime( $meta['expiration'] ) ) . ' 23:59:59' ) );
228
+ $end_timestamp = strtotime( $meta['expiration'] );
229
+
230
+ if( ! empty( $meta['start'] ) && $start_timestamp > $end_timestamp ) {
231
+
232
  // Set the expiration date to the start date if start is later than expiration
233
  $meta['expiration'] = $meta['start'];
234
+
235
  }
236
+
237
  }
238
 
239
  if ( edd_discount_exists( $discount_id ) && ! empty( $discount_id ) ) {
240
+
241
  // Update an existing discount
242
 
243
+ $meta = apply_filters( 'edd_update_discount', $meta, $discount_id );
244
 
245
+ do_action( 'edd_pre_update_discount', $meta, $discount_id );
246
 
247
  wp_update_post( array(
248
  'ID' => $discount_id,
249
+ 'post_title' => $meta['name'],
250
+ 'post_status' => $meta['status']
251
  ) );
252
 
253
  foreach( $meta as $key => $value ) {
254
  update_post_meta( $discount_id, '_edd_discount_' . $key, $value );
255
  }
256
 
257
+ do_action( 'edd_post_update_discount', $meta, $discount_id );
258
 
259
  // Discount code updated
260
  return $discount_id;
261
+
262
  } else {
263
+
264
  // Add the discount
265
 
266
+ $meta = apply_filters( 'edd_insert_discount', $meta );
267
 
268
+ do_action( 'edd_pre_insert_discount', $meta );
269
 
270
  $discount_id = wp_insert_post( array(
271
  'post_type' => 'edd_discount',
272
+ 'post_title' => $meta['name'],
273
  'post_status' => 'active'
274
  ) );
275
 
277
  update_post_meta( $discount_id, '_edd_discount_' . $key, $value );
278
  }
279
 
280
+ do_action( 'edd_post_insert_discount', $meta, $discount_id );
281
 
282
  // Discount code created
283
  return $discount_id;
284
  }
285
+
286
  }
287
 
288
 
530
  * @since 1.5
531
  * @param int $code_id Discount ID
532
  * @return array $product_reqs IDs of the required products
533
+ * @return boolean Whether or not discount code is global
534
  */
535
  function edd_is_discount_not_global( $code_id = 0 ) {
536
  return (bool) get_post_meta( $code_id, '_edd_discount_is_not_global', true );
682
  $cart_ids = $cart_items ? wp_list_pluck( $cart_items, 'id' ) : null;
683
  $ret = false;
684
 
685
+ if ( empty( $product_reqs ) && empty( $excluded_ps ) ) {
686
  $ret = true;
687
  }
688
 
689
+ // Normalize our data for product requiremetns, exlusions and cart data
690
+ // First absint the items, then sort, and reset the array keys
691
+ $product_reqs = array_map( 'absint', $product_reqs );
692
+ asort( $product_reqs );
693
+ $product_reqs = array_values( $product_reqs );
694
+
695
+ $excluded_ps = array_map( 'absint', $excluded_ps );
696
+ asort( $excluded_ps );
697
+ $excluded_ps = array_values( $excluded_ps );
698
+
699
+ $cart_ids = array_map( 'absint', $cart_ids );
700
+ asort( $cart_ids );
701
+ $cart_ids = array_values( $cart_ids );
702
+
703
  // Ensure we have requirements before proceeding
704
+ if ( ! $ret && ! empty( $product_reqs ) ) {
705
+
706
  switch( $condition ) {
707
  case 'all' :
708
  // Default back to true
720
 
721
  default : // Any
722
  foreach ( $product_reqs as $download_id ) {
723
+
724
  if ( edd_item_in_cart( $download_id ) ) {
725
  $ret = true;
726
  break;
 
 
727
  }
728
+
729
+ }
730
+
731
+ if( ! $ret ) {
732
+
733
+ edd_set_error( 'edd-discount-error', __( 'The product requirements for this discount are not met.', 'edd' ) );
734
+
735
  }
736
 
737
  break;
738
  }
739
+
740
+ } else {
741
+
742
+ $ret = true;
743
+
744
  }
745
 
746
+ if( ! empty( $excluded_ps ) ) {
747
  // Check that there are products other than excluded ones in the cart
748
  if( $cart_ids == $excluded_ps ) {
749
  edd_set_error( 'edd-discount-error', __( 'This discount is not valid for the cart contents.', 'edd' ) );
834
  * @param string $user User info
835
  * @return bool
836
  */
837
+ function edd_is_discount_valid( $code = '', $user = '', $set_error = true ) {
838
 
839
 
840
  $return = false;
854
  ) {
855
  $return = true;
856
  }
857
+ } elseif( $set_error ) {
858
  edd_set_error( 'edd-discount-error', __( 'This discount is invalid.', 'edd' ) );
859
  }
860
 
966
  *
967
  * @since 1.4.1
968
  * @param string $code Discount code
969
+ * @return string[] All currently active discounts
970
  */
971
  function edd_set_cart_discount( $code = '' ) {
972
 
1063
  */
1064
  function edd_get_cart_discounted_amount( $discounts = false ) {
1065
 
1066
+ $amount = 0.00;
1067
  $items = edd_get_cart_content_details();
1068
  if( $items ) {
1069
 
1087
  */
1088
  function edd_get_cart_item_discount_amount( $item = array() ) {
1089
 
1090
+ global $edd_is_last_cart_item, $edd_flat_discount_total;
1091
+
1092
  $amount = 0;
1093
+ $price = edd_get_cart_item_price( $item['id'], $item['options'] );
1094
  $discounted_price = $price;
1095
 
1096
  // Retrieve all discounts applied to the cart
1100
 
1101
  foreach ( $discounts as $discount ) {
1102
 
1103
+ $code_id = edd_get_discount_id_by_code( $discount );
1104
+
1105
+ // Check discount exists
1106
+ if( ! $code_id ) {
1107
+ continue;
1108
+ }
1109
+
1110
  $reqs = edd_get_discount_product_reqs( $code_id );
1111
  $excluded_products = edd_get_discount_excluded_products( $code_id );
1112
 
1135
  * are distributed across all cart items. The discount amount is divided by the number
1136
  * of items in the cart and then a portion is evenly applied to each cart item
1137
  */
1138
+ $items_subtotal = 0.00;
1139
+ $cart_items = edd_get_cart_contents();
1140
+ foreach( $cart_items as $cart_item ) {
1141
+ if( ! in_array( $cart_item['id'], $excluded_products ) ) {
1142
+ $item_price = edd_get_cart_item_price( $cart_item['id'], $cart_item['options'] );
1143
+ $items_subtotal += $item_price * $cart_item['quantity'];
1144
+ }
1145
+ }
1146
+
1147
+ $subtotal_percent = ( ( $price * $item['quantity'] ) / $items_subtotal );
1148
+ $code_amount = edd_get_discount_amount( $code_id );
1149
+ $discounted_amount = $code_amount * $subtotal_percent;
1150
  $discounted_price -= $discounted_amount;
1151
+
1152
+ $edd_flat_discount_total += round( $discounted_amount, edd_currency_decimal_filter() );
1153
+
1154
+ if( $edd_is_last_cart_item && $edd_flat_discount_total < $code_amount ) {
1155
+ $adjustment = $code_amount - $edd_flat_discount_total;
1156
+ $discounted_price -= $adjustment;
1157
+ }
1158
+
1159
  } else {
1160
 
1161
  $discounted_price -= $price - edd_get_discounted_amount( $discount, $price );
1311
  * @return bool
1312
  */
1313
  function edd_multiple_discounts_allowed() {
1314
+ $ret = edd_get_option( 'allow_multiple_discounts', false );
1315
+ return (bool) apply_filters( 'edd_multiple_discounts_allowed', $ret );
 
1316
  }
1317
 
1318
  /**
1323
  */
1324
  function edd_listen_for_cart_discount() {
1325
 
1326
+ if ( empty( $_REQUEST['discount'] ) ) {
1327
  return;
1328
  }
1329
 
1330
+ $code = sanitize_text_field( $_REQUEST['discount'] );
1331
+
1332
+ EDD()->session->set( 'preset_discount', $code );
1333
+ }
1334
+ add_action( 'init', 'edd_listen_for_cart_discount', 0 );
1335
+
1336
+ /**
1337
+ * Applies the preset discount, if any. This is separated from edd_listen_for_cart_discount() in order to allow items to be
1338
+ * added to the cart and for it to persist across page loads if necessary
1339
+ *
1340
+ * @return void
1341
+ */
1342
+ function edd_apply_preset_discount() {
1343
+
1344
+ $code = sanitize_text_field( EDD()->session->get( 'preset_discount' ) );
1345
+
1346
+ if ( ! $code ) {
1347
  return;
1348
  }
1349
 
1350
+ if ( ! edd_is_discount_valid( $code, '', false ) ) {
 
 
1351
  return;
1352
  }
1353
 
1354
+ $code = apply_filters( 'edd_apply_preset_discount', $code );
1355
+
1356
  edd_set_cart_discount( $code );
1357
 
1358
+ EDD()->session->set( 'preset_discount', null );
1359
  }
1360
+ add_action( 'init', 'edd_apply_preset_discount', 999 );
includes/download-functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -39,9 +39,9 @@ function edd_get_download_by( $field = '', $value = '' ) {
39
 
40
  case 'slug':
41
  case 'name':
42
- $download = query_posts( array(
43
  'post_type' => 'download',
44
- 'name' => sanitize_title_for_query( $value ),
45
  'posts_per_page' => 1,
46
  'post_status' => 'any'
47
  ) );
@@ -53,7 +53,7 @@ function edd_get_download_by( $field = '', $value = '' ) {
53
  break;
54
 
55
  case 'sku':
56
- $download = query_posts( array(
57
  'post_type' => 'download',
58
  'meta_key' => 'edd_sku',
59
  'meta_value' => $value,
@@ -85,7 +85,7 @@ function edd_get_download_by( $field = '', $value = '' ) {
85
  * @param int $download Download ID
86
  * @return WP_Post $download Entire download data
87
  */
88
- function edd_get_download( $download ) {
89
  if ( is_numeric( $download ) ) {
90
  $download = get_post( $download );
91
  if ( ! $download || 'download' !== $download->post_type )
@@ -108,6 +108,25 @@ function edd_get_download( $download ) {
108
  return null;
109
  }
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  /**
112
  * Returns the price of a download, but only for non-variable priced downloads.
113
  *
@@ -116,13 +135,13 @@ function edd_get_download( $download ) {
116
  * @return mixed string|int Price of the download
117
  */
118
  function edd_get_download_price( $download_id = 0 ) {
119
- $price = get_post_meta( $download_id, 'edd_price', true );
120
- if ( $price )
121
- $price = edd_sanitize_amount( $price );
122
- else
123
- $price = 0;
124
 
125
- return apply_filters( 'edd_get_download_price', $price, $download_id );
 
 
 
 
 
126
  }
127
 
128
  /**
@@ -131,29 +150,42 @@ function edd_get_download_price( $download_id = 0 ) {
131
  * @since 1.0
132
  * @param int $download_id ID of the download price to show
133
  * @param bool $echo Whether to echo or return the results
 
134
  * @return void
135
  */
136
- function edd_price( $download_id, $echo = true ) {
 
 
 
 
 
137
  if ( edd_has_variable_prices( $download_id ) ) {
 
138
  $prices = edd_get_variable_prices( $download_id );
139
- // Return the lowest price
140
- $price_float = 0;
141
- foreach ($prices as $key => $value)
142
- if ( ( ( (float)$prices[ $key ]['amount'] ) < $price_float ) or ( $price_float == 0 ) )
143
- $price_float = (float)$prices[ $key ]['amount'];
144
- $price = edd_sanitize_amount( $price_float );
 
 
 
145
  } else {
 
146
  $price = edd_get_download_price( $download_id );
147
- }
148
 
149
- $price = apply_filters( 'edd_download_price', edd_sanitize_amount( $price ), $download_id );
150
 
151
- $price = '<span class="edd_price" id="edd_price_' . $download_id . '">' . $price . '</span>';
 
 
152
 
153
- if ( $echo )
154
- echo $price;
155
- else
156
- return $price;
 
157
  }
158
  add_filter( 'edd_download_price', 'edd_format_amount', 10 );
159
  add_filter( 'edd_download_price', 'edd_currency_filter', 20 );
@@ -168,7 +200,7 @@ add_filter( 'edd_download_price', 'edd_currency_filter', 20 );
168
  * @param string $amount_override a custom amount that over rides the 'edd_price' meta, used for variable prices
169
  * @return string - the price of the download
170
  */
171
- function edd_get_download_final_price( $download_id, $user_purchase_info, $amount_override = null ) {
172
  if ( is_null( $amount_override ) ) {
173
  $original_price = get_post_meta( $download_id, 'edd_price', true );
174
  } else {
@@ -193,9 +225,14 @@ function edd_get_download_final_price( $download_id, $user_purchase_info, $amoun
193
  * @param int $download_id ID of the download
194
  * @return array Variable prices
195
  */
196
- function edd_get_variable_prices( $download_id ) {
197
- $variable_prices = get_post_meta( $download_id, 'edd_variable_prices', true );
198
- return apply_filters( 'edd_get_variable_prices', $variable_prices, $download_id );
 
 
 
 
 
199
  }
200
 
201
  /**
@@ -205,12 +242,39 @@ function edd_get_variable_prices( $download_id ) {
205
  * @param int $download_id ID number of the download to check
206
  * @return bool true if has variable prices, false otherwise
207
  */
208
- function edd_has_variable_prices( $download_id ) {
209
- if ( get_post_meta( $download_id, '_variable_pricing', true ) ) {
210
- return true;
 
211
  }
212
 
213
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  }
215
 
216
  /**
@@ -231,7 +295,7 @@ function edd_get_price_option_name( $download_id = 0, $price_id = 0, $payment_id
231
  $price_name = $prices[ $price_id ]['name'];
232
  }
233
 
234
- return apply_filters( 'edd_get_price_option_name', $price_name, $download_id, $payment_id );
235
  }
236
 
237
  /**
@@ -243,7 +307,7 @@ function edd_get_price_option_name( $download_id = 0, $price_id = 0, $payment_id
243
  * @param int @payment_id ID of the payment
244
  * @return float $amount Amount of the price option
245
  */
246
- function edd_get_price_option_amount( $download_id, $price_id = 0 ) {
247
  $prices = edd_get_variable_prices( $download_id );
248
  $amount = 0.00;
249
 
@@ -252,7 +316,7 @@ function edd_get_price_option_amount( $download_id, $price_id = 0 ) {
252
  $amount = $prices[ $price_id ]['amount'];
253
  }
254
 
255
- return apply_filters( 'edd_get_price_option_amount', edd_sanitize_amount( $amount ), $download_id );
256
  }
257
 
258
  /**
@@ -266,24 +330,35 @@ function edd_get_lowest_price_option( $download_id = 0 ) {
266
  if ( empty( $download_id ) )
267
  $download_id = get_the_ID();
268
 
269
- if ( ! edd_has_variable_prices( $download_id ) )
270
  return edd_get_download_price( $download_id );
 
271
 
272
  $prices = edd_get_variable_prices( $download_id );
273
 
274
  $low = 0.00;
275
 
276
  if ( ! empty( $prices ) ) {
277
- $min = 0;
278
 
279
  foreach ( $prices as $key => $price ) {
280
- if ( empty( $price['amount'] ) )
 
281
  continue;
282
- if ( $prices[ $min ]['amount'] > $price['amount'] )
283
- $min = $key;
 
 
 
 
 
 
 
 
 
284
  }
285
 
286
- $low = $prices[ $min ]['amount'];
 
287
  }
288
 
289
  return edd_sanitize_amount( $low );
@@ -297,28 +372,37 @@ function edd_get_lowest_price_option( $download_id = 0 ) {
297
  * @return float Amount of the highest price
298
  */
299
  function edd_get_highest_price_option( $download_id = 0 ) {
300
- if ( empty( $download_id ) )
 
301
  $download_id = get_the_ID();
 
302
 
303
- if ( ! edd_has_variable_prices( $download_id ) )
304
  return edd_get_download_price( $download_id );
 
305
 
306
  $prices = edd_get_variable_prices( $download_id );
307
 
308
  $high = 0.00;
309
 
310
  if ( ! empty( $prices ) ) {
 
311
  $max = 0;
312
 
313
  foreach ( $prices as $key => $price ) {
314
- if ( empty( $price['amount'] ) )
 
315
  continue;
 
316
 
317
- if ( $prices[ $max ]['amount'] < $price['amount'] )
318
- $max = $key;
 
 
 
319
  }
320
 
321
- $high = $prices[ $max ]['amount'];
322
  }
323
 
324
  return edd_sanitize_amount( $high );
@@ -349,12 +433,20 @@ function edd_price_range( $download_id = 0 ) {
349
  * @return bool
350
  */
351
  function edd_single_price_option_mode( $download_id = 0 ) {
352
- if ( empty( $download_id ) )
353
- $download_id = get_the_ID();
354
 
355
- $ret = get_post_meta( $download_id, '_edd_price_options_mode', true );
 
 
 
 
 
 
 
 
 
 
 
356
 
357
- return (bool) apply_filters( 'edd_single_price_option_mode', $ret, $download_id );
358
  }
359
 
360
  /**
@@ -380,11 +472,9 @@ function edd_get_download_types() {
380
  * @param int $download_id Download ID
381
  * @return string $type Download type
382
  */
383
- function edd_get_download_type( $download_id ) {
384
- $type = get_post_meta( $download_id, '_edd_product_type', true );
385
- if( empty( $type ) )
386
- $type = 'default';
387
- return apply_filters( 'edd_get_download_type', $type, $download_id );
388
  }
389
 
390
  /**
@@ -395,7 +485,8 @@ function edd_get_download_type( $download_id ) {
395
  * @return bool
396
  */
397
  function edd_is_bundled_product( $download_id = 0 ) {
398
- return 'bundle' === edd_get_download_type( $download_id );
 
399
  }
400
 
401
 
@@ -407,8 +498,8 @@ function edd_is_bundled_product( $download_id = 0 ) {
407
  * @return array $products Products in the bundle
408
  */
409
  function edd_get_bundled_products( $download_id = 0 ) {
410
- $products = get_post_meta( $download_id, '_edd_bundled_products', true );
411
- return apply_filters( 'edd_get_bundled_products', $products, $download_id );
412
  }
413
 
414
  /**
@@ -418,20 +509,9 @@ function edd_get_bundled_products( $download_id = 0 ) {
418
  * @param int $download_id Download ID
419
  * @return int $earnings Earnings for a certain download
420
  */
421
- function edd_get_download_earnings_stats( $download_id ) {
422
-
423
- if ( '' == get_post_meta( $download_id, '_edd_download_earnings', true ) ) {
424
- add_post_meta( $download_id, '_edd_download_earnings', 0 );
425
- }
426
-
427
- $earnings = get_post_meta( $download_id, '_edd_download_earnings', true );
428
-
429
- if( $earnings < 0 ) {
430
- // Never let earnings be less than zero
431
- $earnings = 0;
432
- }
433
-
434
- return $earnings;
435
  }
436
 
437
  /**
@@ -441,20 +521,9 @@ function edd_get_download_earnings_stats( $download_id ) {
441
  * @param int $download_id Download ID
442
  * @return int $sales Amount of sales for a certain download
443
  */
444
- function edd_get_download_sales_stats( $download_id ) {
445
-
446
- if ( '' == get_post_meta( $download_id, '_edd_download_sales', true ) ) {
447
- add_post_meta( $download_id, '_edd_download_sales', 0 );
448
- } // End if
449
-
450
- $sales = get_post_meta( $download_id, '_edd_download_sales', true );
451
-
452
- if ( $sales < 0 ) {
453
- // Never let sales be less than zero
454
- $sales = 0;
455
- }
456
-
457
- return $sales;
458
  }
459
 
460
  /**
@@ -467,14 +536,17 @@ function edd_get_download_sales_stats( $download_id ) {
467
  * @param int $download_id Download ID
468
  * @param int $payment_id Payment ID
469
  * @param bool|int $price_id Price ID, if any
 
470
  * @return void
471
  */
472
- function edd_record_sale_in_log( $download_id, $payment_id, $price_id = false ) {
473
  global $edd_logs;
474
 
475
  $log_data = array(
476
- 'post_parent' => $download_id,
477
- 'log_type' => 'sale'
 
 
478
  );
479
 
480
  $log_meta = array(
@@ -500,7 +572,7 @@ function edd_record_sale_in_log( $download_id, $payment_id, $price_id = false )
500
  * @param int $price_id Price ID, if any
501
  * @return void
502
  */
503
- function edd_record_download_in_log( $download_id, $file_id, $user_info, $ip, $payment_id, $price_id = false ) {
504
  global $edd_logs;
505
 
506
  $log_data = array(
@@ -549,15 +621,13 @@ add_action( 'delete_post', 'edd_remove_download_logs_on_delete' );
549
  *
550
  * @since 1.0
551
  * @param int $download_id Download ID
 
552
  * @return bool|int
553
  */
554
- function edd_increase_purchase_count( $download_id ) {
555
- $sales = edd_get_download_sales_stats( $download_id );
556
- $sales = $sales + 1;
557
- if ( update_post_meta( $download_id, '_edd_download_sales', $sales ) )
558
- return $sales;
559
-
560
- return false;
561
  }
562
 
563
  /**
@@ -568,15 +638,9 @@ function edd_increase_purchase_count( $download_id ) {
568
  * @param int $download_id Download ID
569
  * @return bool|int
570
  */
571
- function edd_decrease_purchase_count( $download_id ) {
572
- $sales = edd_get_download_sales_stats( $download_id );
573
- if ( $sales > 0 ) // Only decrease if not already zero
574
- $sales = $sales - 1;
575
-
576
- if ( update_post_meta( $download_id, '_edd_download_sales', $sales ) )
577
- return $sales;
578
-
579
- return false;
580
  }
581
 
582
  /**
@@ -587,14 +651,9 @@ function edd_decrease_purchase_count( $download_id ) {
587
  * @param int $amount Earnings
588
  * @return bool|int
589
  */
590
- function edd_increase_earnings( $download_id, $amount ) {
591
- $earnings = edd_get_download_earnings_stats( $download_id );
592
- $earnings = $earnings + $amount;
593
-
594
- if ( update_post_meta( $download_id, '_edd_download_earnings', $earnings ) )
595
- return $earnings;
596
-
597
- return false;
598
  }
599
 
600
  /**
@@ -605,16 +664,9 @@ function edd_increase_earnings( $download_id, $amount ) {
605
  * @param int $amount Earnings
606
  * @return bool|int
607
  */
608
- function edd_decrease_earnings( $download_id, $amount ) {
609
- $earnings = edd_get_download_earnings_stats( $download_id );
610
-
611
- if ( $earnings > 0 ) // Only decrease if greater than zero
612
- $earnings = $earnings - $amount;
613
-
614
- if ( update_post_meta( $download_id, '_edd_download_earnings', $earnings ) )
615
- return $earnings;
616
-
617
- return false;
618
  }
619
 
620
  /**
@@ -624,13 +676,13 @@ function edd_decrease_earnings( $download_id, $amount ) {
624
  * @param int $download_id Download ID
625
  * @return float $earnings Average monthly earnings
626
  */
627
- function edd_get_average_monthly_download_earnings( $download_id ) {
628
  $earnings = edd_get_download_earnings_stats( $download_id );
629
  $release_date = get_post_field( 'post_date', $download_id );
630
 
631
  $diff = abs( current_time( 'timestamp' ) - strtotime( $release_date ) );
632
 
633
- $months = floor( $diff / ( 30 * 60 * 60 * 24 ) ); // Number of months since publication
634
 
635
  if ( $months > 0 ) {
636
  $earnings = ( $earnings / $months );
@@ -646,18 +698,18 @@ function edd_get_average_monthly_download_earnings( $download_id ) {
646
  * @param int $download_id Download ID
647
  * @return float $sales Average monthly sales
648
  */
649
- function edd_get_average_monthly_download_sales( $download_id ) {
650
- $sales = edd_get_download_sales_stats( $download_id );
651
- $release_date = get_post_field( 'post_date', $download_id );
652
 
653
- $diff = abs( current_time( 'timestamp' ) - strtotime( $release_date ) );
654
 
655
- $months = floor( $diff / ( 30 * 60 * 60 * 24 ) ); // Number of months since publication
656
 
657
- if ( $months > 0 )
658
- $sales = ( $sales / $months );
659
 
660
- return $sales;
661
  }
662
 
663
  /**
@@ -671,29 +723,8 @@ function edd_get_average_monthly_download_sales( $download_id ) {
671
  * @return array $files Download files
672
  */
673
  function edd_get_download_files( $download_id = 0, $variable_price_id = null ) {
674
- $files = array();
675
-
676
- // Bundled products are not allowed to have files
677
- if( edd_is_bundled_product( $download_id ) )
678
- return $files;
679
-
680
- $download_files = get_post_meta( $download_id, 'edd_download_files', true );
681
-
682
- if ( $download_files ) {
683
- if ( ! is_null( $variable_price_id ) ) {
684
- foreach ( $download_files as $key => $file_info ) {
685
- if ( isset( $file_info['condition'] ) ) {
686
- if ( $file_info['condition'] == $variable_price_id || 'all' === $file_info['condition'] ) {
687
- $files[ $key ] = $file_info;
688
- }
689
- }
690
- }
691
- } else {
692
- $files = $download_files;
693
- }
694
- }
695
-
696
- return apply_filters( 'edd_download_files', $files, $download_id, $variable_price_id );
697
  }
698
 
699
  /**
@@ -752,20 +783,8 @@ function edd_get_file_downloaded_count( $download_id = 0, $file_key = 0, $paymen
752
  * @return int $limit File download limit
753
  */
754
  function edd_get_file_download_limit( $download_id = 0 ) {
755
- global $edd_options;
756
-
757
- $ret = 0;
758
- $limit = get_post_meta( $download_id, '_edd_download_limit', true );
759
- $global = edd_get_option( 'file_download_limit', 0 );
760
-
761
- if ( ! empty( $limit ) || ( is_numeric( $limit ) && (int)$limit == 0 ) ) {
762
- // Download specific limit
763
- $ret = absint( $limit );
764
- } else {
765
- // Global limit
766
- $ret = strlen( $limit ) == 0 || $global ? $global : 0;
767
- }
768
- return apply_filters( 'edd_file_download_limit', $ret, $download_id );
769
  }
770
 
771
  /**
@@ -877,15 +896,9 @@ function edd_is_file_at_download_limit( $download_id = 0, $payment_id = 0, $file
877
  * @param string $file_key File Key
878
  * @return string - the price ID if restricted, "all" otherwise
879
  */
880
- function edd_get_file_price_condition( $download_id, $file_key ) {
881
- $files = edd_get_download_files( $download_id );
882
-
883
- if ( ! $files )
884
- return false;
885
-
886
- $condition = isset( $files[ $file_key ]['condition']) ? $files[ $file_key ]['condition'] : 'all';
887
-
888
- return $condition;
889
  }
890
 
891
  /**
@@ -902,105 +915,55 @@ function edd_get_file_price_condition( $download_id, $file_key ) {
902
  *
903
  * @return string Constructed download URL
904
  */
905
- function edd_get_download_file_url( $key, $email, $filekey, $download_id, $price_id = false ) {
906
- global $edd_options;
907
 
908
- $hours = isset( $edd_options['download_link_expiration'] )
909
- && is_numeric( $edd_options['download_link_expiration'] )
910
- ? absint( $edd_options['download_link_expiration'] ) : 24;
911
 
912
- if ( ! ( $date = strtotime( '+' . $hours . 'hours', current_time( 'timestamp') ) ) )
913
  $date = 2147472000; // Highest possible date, January 19, 2038
 
914
 
915
- $params = array(
916
- 'download_key' => $key,
917
- 'email' => rawurlencode( $email ),
918
- 'file' => $filekey,
 
919
  'price_id' => (int) $price_id,
920
- 'download_id' => $download_id,
921
- 'expire' => rawurlencode( base64_encode( $date ) )
922
  );
923
 
924
- $params = apply_filters( 'edd_download_file_url_args', $params );
925
 
926
- $download_url = add_query_arg( $params, home_url( 'index.php' ) );
927
 
928
- return $download_url;
929
- }
930
-
931
- /**
932
- * Verifies a download purchase using a purchase key and email.
933
- *
934
- * @since 1.0
935
- *
936
- * @param int $download_id
937
- * @param string $key
938
- * @param string $email
939
- * @param string $expire
940
- * @param int $file_key
941
- *
942
- * @return bool True if payment and link was verified, false otherwise
943
- */
944
- function edd_verify_download_link( $download_id = 0, $key = '', $email = '', $expire = '', $file_key = 0 ) {
945
-
946
- $meta_query = array(
947
- 'relation' => 'AND',
948
- array(
949
- 'key' => '_edd_payment_purchase_key',
950
- 'value' => $key
951
- ),
952
- array(
953
- 'key' => '_edd_payment_user_email',
954
- 'value' => $email
955
- )
956
- );
957
-
958
- $accepted_stati = apply_filters( 'edd_allowed_download_stati', array( 'publish', 'complete' ) );
959
-
960
- $payments = get_posts( array( 'meta_query' => $meta_query, 'post_type' => 'edd_payment', 'post_status' => $accepted_stati ) );
961
-
962
- if ( $payments ) {
963
- foreach ( $payments as $payment ) {
964
-
965
- $cart_details = edd_get_payment_meta_cart_details( $payment->ID, true );
966
-
967
- if ( ! empty( $cart_details ) ) {
968
- foreach ( $cart_details as $cart_key => $cart_item ) {
969
-
970
- if ( $cart_item['id'] != $download_id )
971
- continue;
972
 
973
- $price_options = isset( $cart_item['item_number']['options'] ) ? $cart_item['item_number']['options'] : false;
974
- $price_id = isset( $price_options['price_id'] ) ? $price_options['price_id'] : false;
975
 
976
- $file_condition = edd_get_file_price_condition( $cart_item['id'], $file_key );
 
 
 
977
 
978
- // Check to see if the file download limit has been reached
979
- if ( edd_is_file_at_download_limit( $cart_item['id'], $payment->ID, $file_key, $price_id ) )
980
- wp_die( apply_filters( 'edd_download_limit_reached_text', __( 'Sorry but you have hit your download limit for this file.', 'edd' ) ), __( 'Error', 'edd' ) );
981
 
982
- // If this download has variable prices, we have to confirm that this file was included in their purchase
983
- if ( ! empty( $price_options ) && $file_condition != 'all' && edd_has_variable_prices( $cart_item['id'] ) ) {
984
- if ( $file_condition == $price_options['price_id'] )
985
- return $payment->ID;
986
- }
987
 
988
- // Make sure the link hasn't expired
989
- if ( current_time( 'timestamp' ) > $expire ) {
990
- wp_die( apply_filters( 'edd_download_link_expired_text', __( 'Sorry but your download link has expired.', 'edd' ) ), __( 'Error', 'edd' ) );
991
- }
992
- return $payment->ID; // Payment has been verified and link is still valid
993
- }
994
 
995
- }
 
 
996
 
997
- }
998
 
999
- } else {
1000
- wp_die( __( 'No payments matching your request were found.', 'edd' ), __( 'Error', 'edd' ) );
1001
- }
1002
- // Payment not verified
1003
- return false;
1004
  }
1005
 
1006
  /**
@@ -1010,13 +973,9 @@ function edd_verify_download_link( $download_id = 0, $key = '', $email = '', $ex
1010
  * @param int $download_id Download ID
1011
  * @return string $notes Product notes
1012
  */
1013
- function edd_get_product_notes( $download_id ) {
1014
- $notes = get_post_meta( $download_id, 'edd_product_notes', true );
1015
-
1016
- if ( $notes )
1017
- return (string) apply_filters( 'edd_product_notes', $notes, $download_id );
1018
-
1019
- return '';
1020
  }
1021
 
1022
  /**
@@ -1030,11 +989,8 @@ function edd_get_product_notes( $download_id ) {
1030
  * @return mixed|void Download SKU
1031
  */
1032
  function edd_get_download_sku( $download_id = 0 ) {
1033
- $sku = get_post_meta( $download_id, 'edd_sku', true );
1034
- if ( empty( $sku ) )
1035
- $sku = '-';
1036
-
1037
- return apply_filters( 'edd_get_download_sku', $sku, $download_id );
1038
  }
1039
 
1040
  /**
@@ -1046,11 +1002,8 @@ function edd_get_download_sku( $download_id = 0 ) {
1046
  * @return mixed|void Add to Cart or Direct
1047
  */
1048
  function edd_get_download_button_behavior( $download_id = 0 ) {
1049
- $behavior = get_post_meta( $download_id, '_edd_button_behavior', true );
1050
- if( empty( $behavior ) ) {
1051
- $behavior = 'add_to_cart';
1052
- }
1053
- return apply_filters( 'edd_get_download_button_behavior', $behavior, $download_id );
1054
  }
1055
 
1056
  /**
@@ -1060,8 +1013,7 @@ function edd_get_download_button_behavior( $download_id = 0 ) {
1060
  * @return string The method to use for file downloads
1061
  */
1062
  function edd_get_file_download_method() {
1063
- global $edd_options;
1064
- $method = isset( $edd_options['download_method'] ) ? $edd_options['download_method'] : 'direct';
1065
  return apply_filters( 'edd_file_download_method', $method );
1066
  }
1067
 
@@ -1094,3 +1046,120 @@ function edd_get_random_downloads( $num = 3, $post_ids = true ) {
1094
  $args = apply_filters( 'edd_get_random_downloads', $args );
1095
  return get_posts( $args );
1096
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
39
 
40
  case 'slug':
41
  case 'name':
42
+ $download = get_posts( array(
43
  'post_type' => 'download',
44
+ 'name' => $value,
45
  'posts_per_page' => 1,
46
  'post_status' => 'any'
47
  ) );
53
  break;
54
 
55
  case 'sku':
56
+ $download = get_posts( array(
57
  'post_type' => 'download',
58
  'meta_key' => 'edd_sku',
59
  'meta_value' => $value,
85
  * @param int $download Download ID
86
  * @return WP_Post $download Entire download data
87
  */
88
+ function edd_get_download( $download = 0 ) {
89
  if ( is_numeric( $download ) ) {
90
  $download = get_post( $download );
91
  if ( ! $download || 'download' !== $download->post_type )
108
  return null;
109
  }
110
 
111
+ /**
112
+ * Checks whether or not a download is free
113
+ *
114
+ * @since 2.1
115
+ * @author Daniel J Griffiths
116
+ * @param int $download_id ID number of the download to check
117
+ * @param int $price_id (Optional) ID number of a variably priced item to check
118
+ * @return bool $is_free True if the product is free, false if the product is not free or the check fails
119
+ */
120
+ function edd_is_free_download( $download_id = 0, $price_id = false ) {
121
+
122
+ if( empty( $download_id ) ) {
123
+ return false;
124
+ }
125
+
126
+ $download = new EDD_Download( $download_id );
127
+ return $download->is_free( $price_id );
128
+ }
129
+
130
  /**
131
  * Returns the price of a download, but only for non-variable priced downloads.
132
  *
135
  * @return mixed string|int Price of the download
136
  */
137
  function edd_get_download_price( $download_id = 0 ) {
 
 
 
 
 
138
 
139
+ if( empty( $download_id ) ) {
140
+ return false;
141
+ }
142
+
143
+ $download = new EDD_Download( $download_id );
144
+ return $download->price;
145
  }
146
 
147
  /**
150
  * @since 1.0
151
  * @param int $download_id ID of the download price to show
152
  * @param bool $echo Whether to echo or return the results
153
+ * @param int $price_id Optional price id for variable pricing
154
  * @return void
155
  */
156
+ function edd_price( $download_id = 0, $echo = true, $price_id = false ) {
157
+
158
+ if( empty( $download_id ) ) {
159
+ $download_id = get_the_ID();
160
+ }
161
+
162
  if ( edd_has_variable_prices( $download_id ) ) {
163
+
164
  $prices = edd_get_variable_prices( $download_id );
165
+
166
+ if ( false !== $price_id && isset( $prices[$price_id] ) ) {
167
+ $price = (float) $prices[$price_id]['amount'];
168
+ } else {
169
+ $price = edd_get_lowest_price_option( $download_id );
170
+ }
171
+
172
+ $price = edd_sanitize_amount( $price );
173
+
174
  } else {
175
+
176
  $price = edd_get_download_price( $download_id );
 
177
 
178
+ }
179
 
180
+ $price = apply_filters( 'edd_download_price', edd_sanitize_amount( $price ), $download_id, $price_id );
181
+ $formatted_price = '<span class="edd_price" id="edd_price_' . $download_id . '">' . $price . '</span>';
182
+ $formatted_price = apply_filters( 'edd_download_price_after_html', $formatted_price, $download_id, $price, $price_id );
183
 
184
+ if ( $echo ) {
185
+ echo $formatted_price;
186
+ } else {
187
+ return $formatted_price;
188
+ }
189
  }
190
  add_filter( 'edd_download_price', 'edd_format_amount', 10 );
191
  add_filter( 'edd_download_price', 'edd_currency_filter', 20 );
200
  * @param string $amount_override a custom amount that over rides the 'edd_price' meta, used for variable prices
201
  * @return string - the price of the download
202
  */
203
+ function edd_get_download_final_price( $download_id = 0, $user_purchase_info, $amount_override = null ) {
204
  if ( is_null( $amount_override ) ) {
205
  $original_price = get_post_meta( $download_id, 'edd_price', true );
206
  } else {
225
  * @param int $download_id ID of the download
226
  * @return array Variable prices
227
  */
228
+ function edd_get_variable_prices( $download_id = 0 ) {
229
+
230
+ if( empty( $download_id ) ) {
231
+ return false;
232
+ }
233
+
234
+ $download = new EDD_Download( $download_id );
235
+ return $download->prices;
236
  }
237
 
238
  /**
242
  * @param int $download_id ID number of the download to check
243
  * @return bool true if has variable prices, false otherwise
244
  */
245
+ function edd_has_variable_prices( $download_id = 0 ) {
246
+
247
+ if( empty( $download_id ) ) {
248
+ return false;
249
  }
250
 
251
+ $download = new EDD_Download( $download_id );
252
+ return $download->has_variable_prices();
253
+ }
254
+
255
+ /**
256
+ * Returns the default price ID for variable pricing, or the first
257
+ * price if none is set
258
+ *
259
+ * @since 2.2
260
+ * @param int $download_id ID number of the download to check
261
+ * @return int The Price ID to select by default
262
+ */
263
+ function edd_get_default_variable_price( $download_id = 0 ) {
264
+
265
+ if ( ! edd_has_variable_prices( $download_id ) ) {
266
+ return false;
267
+ }
268
+
269
+ $prices = edd_get_variable_prices( $download_id );
270
+ $default_price_id = get_post_meta( $download_id, '_edd_default_price_id', true );
271
+
272
+ if ( $default_price_id === '' || ! isset( $prices[$default_price_id] ) ) {
273
+ $default_price_id = current( array_keys( $prices ) );
274
+ }
275
+
276
+ return apply_filters( 'edd_variable_default_price_id', absint( $default_price_id ), $download_id );
277
+
278
  }
279
 
280
  /**
295
  $price_name = $prices[ $price_id ]['name'];
296
  }
297
 
298
+ return apply_filters( 'edd_get_price_option_name', $price_name, $download_id, $payment_id, $price_id );
299
  }
300
 
301
  /**
307
  * @param int @payment_id ID of the payment
308
  * @return float $amount Amount of the price option
309
  */
310
+ function edd_get_price_option_amount( $download_id = 0, $price_id = 0 ) {
311
  $prices = edd_get_variable_prices( $download_id );
312
  $amount = 0.00;
313
 
316
  $amount = $prices[ $price_id ]['amount'];
317
  }
318
 
319
+ return apply_filters( 'edd_get_price_option_amount', edd_sanitize_amount( $amount ), $download_id, $price_id );
320
  }
321
 
322
  /**
330
  if ( empty( $download_id ) )
331
  $download_id = get_the_ID();
332
 
333
+ if ( ! edd_has_variable_prices( $download_id ) ) {
334
  return edd_get_download_price( $download_id );
335
+ }
336
 
337
  $prices = edd_get_variable_prices( $download_id );
338
 
339
  $low = 0.00;
340
 
341
  if ( ! empty( $prices ) ) {
 
342
 
343
  foreach ( $prices as $key => $price ) {
344
+
345
+ if ( empty( $price['amount'] ) ) {
346
  continue;
347
+ }
348
+
349
+ if ( ! isset( $min ) ) {
350
+ $min = $price['amount'];
351
+ } else {
352
+ $min = min( $min, $price['amount'] );
353
+ }
354
+
355
+ if ( $price['amount'] == $min ) {
356
+ $min_id = $key;
357
+ }
358
  }
359
 
360
+ $low = $prices[ $min_id ]['amount'];
361
+
362
  }
363
 
364
  return edd_sanitize_amount( $low );
372
  * @return float Amount of the highest price
373
  */
374
  function edd_get_highest_price_option( $download_id = 0 ) {
375
+
376
+ if ( empty( $download_id ) ) {
377
  $download_id = get_the_ID();
378
+ }
379
 
380
+ if ( ! edd_has_variable_prices( $download_id ) ) {
381
  return edd_get_download_price( $download_id );
382
+ }
383
 
384
  $prices = edd_get_variable_prices( $download_id );
385
 
386
  $high = 0.00;
387
 
388
  if ( ! empty( $prices ) ) {
389
+
390
  $max = 0;
391
 
392
  foreach ( $prices as $key => $price ) {
393
+
394
+ if ( empty( $price['amount'] ) ) {
395
  continue;
396
+ }
397
 
398
+ $max = max( $max, $price['amount'] );
399
+
400
+ if ( $price['amount'] == $max ) {
401
+ $max_id = $key;
402
+ }
403
  }
404
 
405
+ $high = $prices[ $max_id ]['amount'];
406
  }
407
 
408
  return edd_sanitize_amount( $high );
433
  * @return bool
434
  */
435
  function edd_single_price_option_mode( $download_id = 0 ) {
 
 
436
 
437
+ if ( empty( $download_id ) ) {
438
+ $download = get_post();
439
+
440
+ $download_id = isset( $download->ID ) ? $download->ID : 0;
441
+ }
442
+
443
+ if ( empty( $download_id ) ) {
444
+ return false;
445
+ }
446
+
447
+ $download = new EDD_Download( $download_id );
448
+ return $download->is_single_price_mode();
449
 
 
450
  }
451
 
452
  /**
472
  * @param int $download_id Download ID
473
  * @return string $type Download type
474
  */
475
+ function edd_get_download_type( $download_id = 0 ) {
476
+ $download = new EDD_Download( $download_id );
477
+ return $download->type;
 
 
478
  }
479
 
480
  /**
485
  * @return bool
486
  */
487
  function edd_is_bundled_product( $download_id = 0 ) {
488
+ $download = new EDD_Download( $download_id );
489
+ return $download->is_bundled_download();
490
  }
491
 
492
 
498
  * @return array $products Products in the bundle
499
  */
500
  function edd_get_bundled_products( $download_id = 0 ) {
501
+ $download = new EDD_Download( $download_id );
502
+ return $download->bundled_downloads;
503
  }
504
 
505
  /**
509
  * @param int $download_id Download ID
510
  * @return int $earnings Earnings for a certain download
511
  */
512
+ function edd_get_download_earnings_stats( $download_id = 0 ) {
513
+ $download = new EDD_Download( $download_id );
514
+ return $download->earnings;
 
 
 
 
 
 
 
 
 
 
 
515
  }
516
 
517
  /**
521
  * @param int $download_id Download ID
522
  * @return int $sales Amount of sales for a certain download
523
  */
524
+ function edd_get_download_sales_stats( $download_id = 0 ) {
525
+ $download = new EDD_Download( $download_id );
526
+ return $download->sales;
 
 
 
 
 
 
 
 
 
 
 
527
  }
528
 
529
  /**
536
  * @param int $download_id Download ID
537
  * @param int $payment_id Payment ID
538
  * @param bool|int $price_id Price ID, if any
539
+ * @param string|null $sale_date The date of the sale
540
  * @return void
541
  */
542
+ function edd_record_sale_in_log( $download_id = 0, $payment_id, $price_id = false, $sale_date = null ) {
543
  global $edd_logs;
544
 
545
  $log_data = array(
546
+ 'post_parent' => $download_id,
547
+ 'log_type' => 'sale',
548
+ 'post_date' => isset( $sale_date ) ? $sale_date : null,
549
+ 'post_date_gmt' => isset( $sale_date ) ? $sale_date : null
550
  );
551
 
552
  $log_meta = array(
572
  * @param int $price_id Price ID, if any
573
  * @return void
574
  */
575
+ function edd_record_download_in_log( $download_id = 0, $file_id, $user_info, $ip, $payment_id, $price_id = false ) {
576
  global $edd_logs;
577
 
578
  $log_data = array(
621
  *
622
  * @since 1.0
623
  * @param int $download_id Download ID
624
+ * @param int $quantity Quantity to increase purchase count by
625
  * @return bool|int
626
  */
627
+ function edd_increase_purchase_count( $download_id = 0, $quantity = 1 ) {
628
+ $quantity = (int) $quantity;
629
+ $download = new EDD_Download( $download_id );
630
+ return $download->increase_sales( $quantity );
 
 
 
631
  }
632
 
633
  /**
638
  * @param int $download_id Download ID
639
  * @return bool|int
640
  */
641
+ function edd_decrease_purchase_count( $download_id = 0, $quantity = 1 ) {
642
+ $download = new EDD_Download( $download_id );
643
+ return $download->decrease_sales( $quantity );
 
 
 
 
 
 
644
  }
645
 
646
  /**
651
  * @param int $amount Earnings
652
  * @return bool|int
653
  */
654
+ function edd_increase_earnings( $download_id = 0, $amount ) {
655
+ $download = new EDD_Download( $download_id );
656
+ return $download->increase_earnings( $amount );
 
 
 
 
 
657
  }
658
 
659
  /**
664
  * @param int $amount Earnings
665
  * @return bool|int
666
  */
667
+ function edd_decrease_earnings( $download_id = 0, $amount ) {
668
+ $download = new EDD_Download( $download_id );
669
+ return $download->decrease_earnings( $amount );
 
 
 
 
 
 
 
670
  }
671
 
672
  /**
676
  * @param int $download_id Download ID
677
  * @return float $earnings Average monthly earnings
678
  */
679
+ function edd_get_average_monthly_download_earnings( $download_id = 0 ) {
680
  $earnings = edd_get_download_earnings_stats( $download_id );
681
  $release_date = get_post_field( 'post_date', $download_id );
682
 
683
  $diff = abs( current_time( 'timestamp' ) - strtotime( $release_date ) );
684
 
685
+ $months = floor( $diff / ( 30 * 60 * 60 * 24 ) ); // Number of months since publication
686
 
687
  if ( $months > 0 ) {
688
  $earnings = ( $earnings / $months );
698
  * @param int $download_id Download ID
699
  * @return float $sales Average monthly sales
700
  */
701
+ function edd_get_average_monthly_download_sales( $download_id = 0 ) {
702
+ $sales = edd_get_download_sales_stats( $download_id );
703
+ $release_date = get_post_field( 'post_date', $download_id );
704
 
705
+ $diff = abs( current_time( 'timestamp' ) - strtotime( $release_date ) );
706
 
707
+ $months = floor( $diff / ( 30 * 60 * 60 * 24 ) ); // Number of months since publication
708
 
709
+ if ( $months > 0 )
710
+ $sales = ( $sales / $months );
711
 
712
+ return $sales;
713
  }
714
 
715
  /**
723
  * @return array $files Download files
724
  */
725
  function edd_get_download_files( $download_id = 0, $variable_price_id = null ) {
726
+ $download = new EDD_Download( $download_id );
727
+ return $download->get_files( $variable_price_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
728
  }
729
 
730
  /**
783
  * @return int $limit File download limit
784
  */
785
  function edd_get_file_download_limit( $download_id = 0 ) {
786
+ $download = new EDD_Download( $download_id );
787
+ return $download->get_file_download_limit();
 
 
 
 
 
 
 
 
 
 
 
 
788
  }
789
 
790
  /**
896
  * @param string $file_key File Key
897
  * @return string - the price ID if restricted, "all" otherwise
898
  */
899
+ function edd_get_file_price_condition( $download_id = 0, $file_key ) {
900
+ $download = new EDD_Download( $download_id );
901
+ return $download->get_file_price_condition( $file_key );
 
 
 
 
 
 
902
  }
903
 
904
  /**
915
  *
916
  * @return string Constructed download URL
917
  */
918
+ function edd_get_download_file_url( $key, $email, $filekey, $download_id = 0, $price_id = false ) {
 
919
 
920
+ $hours = absint( edd_get_option( 'download_link_expiration', 24 ) );
 
 
921
 
922
+ if ( ! ( $date = strtotime( '+' . $hours . 'hours', current_time( 'timestamp') ) ) ) {
923
  $date = 2147472000; // Highest possible date, January 19, 2038
924
+ }
925
 
926
+ // Leaving in this array and the filter for backwards compatibility now
927
+ $old_args = array(
928
+ 'download_key' => rawurlencode( $key ),
929
+ 'email' => rawurlencode( $email ),
930
+ 'file' => rawurlencode( $filekey ),
931
  'price_id' => (int) $price_id,
932
+ 'download_id' => $download_id,
933
+ 'expire' => rawurlencode( $date )
934
  );
935
 
936
+ $params = apply_filters( 'edd_download_file_url_args', $old_args );
937
 
938
+ $payment = edd_get_payment_by( 'key', $params['download_key'] );
939
 
940
+ if ( ! $payment ) {
941
+ return false;
942
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
943
 
944
+ if ( ! empty( $payment->ID ) ) {
 
945
 
946
+ // Simply the URL by concatenating required data using a colon as a delimiter.
947
+ $args = array(
948
+ 'eddfile' => rawurlencode( sprintf( '%d:%d:%d:%d', $payment->ID, $params['download_id'], $params['file'], $price_id ) )
949
+ );
950
 
951
+ if ( isset( $params['expire'] ) ) {
952
+ $args['ttl'] = $params['expire'];
953
+ }
954
 
955
+ // Ensure all custom args registered with extensions through edd_download_file_url_args get added to the URL, but without adding all the old args
956
+ $args = array_merge( $args, array_diff_key( $params, $old_args ) );
 
 
 
957
 
958
+ $args = apply_filters( 'edd_get_download_file_url_args', $args, $payment->ID, $params );
 
 
 
 
 
959
 
960
+ $args['file'] = $params['file'];
961
+ $args['token'] = edd_get_download_token( add_query_arg( $args, untrailingslashit( home_url() ) ) );
962
+ }
963
 
964
+ $download_url = add_query_arg( $args, home_url( 'index.php' ) );
965
 
966
+ return $download_url;
 
 
 
 
967
  }
968
 
969
  /**
973
  * @param int $download_id Download ID
974
  * @return string $notes Product notes
975
  */
976
+ function edd_get_product_notes( $download_id = 0 ) {
977
+ $download = new EDD_Download( $download_id );
978
+ return $download->notes;
 
 
 
 
979
  }
980
 
981
  /**
989
  * @return mixed|void Download SKU
990
  */
991
  function edd_get_download_sku( $download_id = 0 ) {
992
+ $download = new EDD_Download( $download_id );
993
+ return $download->sku;
 
 
 
994
  }
995
 
996
  /**
1002
  * @return mixed|void Add to Cart or Direct
1003
  */
1004
  function edd_get_download_button_behavior( $download_id = 0 ) {
1005
+ $download = new EDD_Download( $download_id );
1006
+ return $download->button_behavior;
 
 
 
1007
  }
1008
 
1009
  /**
1013
  * @return string The method to use for file downloads
1014
  */
1015
  function edd_get_file_download_method() {
1016
+ $method = edd_get_option( 'download_method', 'direct' );
 
1017
  return apply_filters( 'edd_file_download_method', $method );
1018
  }
1019
 
1046
  $args = apply_filters( 'edd_get_random_downloads', $args );
1047
  return get_posts( $args );
1048
  }
1049
+
1050
+ /**
1051
+ * Generates a token for a given URL.
1052
+ *
1053
+ * An 'o' query parameter on a URL can include optional variables to test
1054
+ * against when verifying a token without passing those variables around in
1055
+ * the URL. For example, downloads can be limited to the IP that the URL was
1056
+ * generated for by adding 'o=ip' to the query string.
1057
+ *
1058
+ * Or suppose when WordPress requested a URL for automatic updates, the user
1059
+ * agent could be tested to ensure the URL is only valid for requests from
1060
+ * that user agent.
1061
+ *
1062
+ * @since 2.3
1063
+ *
1064
+ * @param string $url The URL to generate a token for.
1065
+ * @return string The token for the URL.
1066
+ */
1067
+ function edd_get_download_token( $url = '' ) {
1068
+
1069
+ $args = array();
1070
+ $hash = apply_filters( 'edd_get_url_token_algorithm', 'sha256' );
1071
+ $secret = apply_filters( 'edd_get_url_token_secret', hash( $hash, wp_salt() ) );
1072
+
1073
+ /*
1074
+ * Add additional args to the URL for generating the token.
1075
+ * Allows for restricting access to IP and/or user agent.
1076
+ */
1077
+ $parts = parse_url( $url );
1078
+ $options = array();
1079
+
1080
+ if ( isset( $parts['query'] ) ) {
1081
+
1082
+ wp_parse_str( $parts['query'], $query_args );
1083
+
1084
+ // o = option checks (ip, user agent).
1085
+ if ( ! empty( $query_args['o'] ) ) {
1086
+
1087
+ // Multiple options can be checked by separating them with a colon in the query parameter.
1088
+ $options = explode( ':', rawurldecode( $query_args['o'] ) );
1089
+
1090
+ if ( in_array( 'ip', $options ) ) {
1091
+
1092
+ $args['ip'] = edd_get_ip();
1093
+
1094
+ }
1095
+
1096
+ if ( in_array( 'ua', $options ) ) {
1097
+
1098
+ $ua = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
1099
+ $args['user_agent'] = rawurlencode( $ua );
1100
+
1101
+ }
1102
+
1103
+ }
1104
+
1105
+ }
1106
+
1107
+ /*
1108
+ * Filter to modify arguments and allow custom options to be tested.
1109
+ * Be sure to rawurlencode any custom options for consistent results.
1110
+ */
1111
+ $args = apply_filters( 'edd_get_url_token_args', $args, $url, $options );
1112
+
1113
+ $args['secret'] = $secret;
1114
+ $args['token'] = false; // Removes a token if present.
1115
+
1116
+ $url = add_query_arg( $args, $url );
1117
+ $parts = parse_url( $url );
1118
+
1119
+ // In the event there isn't a path, set an empty one so we can MD5 the token
1120
+ if ( ! isset( $parts['path'] ) ) {
1121
+
1122
+ $parts['path'] = '';
1123
+
1124
+ }
1125
+
1126
+ $token = md5( $parts['path'] . '?' . $parts['query'] );
1127
+
1128
+ return $token;
1129
+
1130
+ }
1131
+
1132
+ /**
1133
+ * Generate a token for a URL and match it against the existing token to make
1134
+ * sure the URL hasn't been tampered with.
1135
+ *
1136
+ * @since 2.3
1137
+ *
1138
+ * @param string $url URL to test.
1139
+ * @return bool
1140
+ */
1141
+ function edd_validate_url_token( $url = '' ) {
1142
+
1143
+ $ret = false;
1144
+ $parts = parse_url( $url );
1145
+
1146
+ if ( isset( $parts['query'] ) ) {
1147
+
1148
+ wp_parse_str( $parts['query'], $query_args );
1149
+
1150
+ if ( isset( $query_args['ttl'] ) && current_time( 'timestamp' ) > $query_args['ttl'] ) {
1151
+
1152
+ wp_die( apply_filters( 'edd_download_link_expired_text', __( 'Sorry but your download link has expired.', 'edd' ) ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
1153
+
1154
+ }
1155
+
1156
+ if ( isset( $query_args['token'] ) && $query_args['token'] == edd_get_download_token( $url ) ) {
1157
+
1158
+ $ret = true;
1159
+
1160
+ }
1161
+
1162
+ }
1163
+
1164
+ return apply_filters( 'edd_validate_url_token', $ret, $url, $query_args );
1165
+ }
includes/emails/actions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Emails
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0.8.2
10
  */
@@ -37,12 +37,22 @@ add_action( 'edd_complete_purchase', 'edd_trigger_purchase_receipt', 999, 1 );
37
  * @return void
38
  */
39
  function edd_resend_purchase_receipt( $data ) {
40
- $purchase_id = $data['purchase_id'];
 
 
 
 
 
 
 
 
 
 
41
  edd_email_purchase_receipt( $purchase_id, false );
42
 
43
  // Grab all downloads of the purchase and update their file download limits, if needed
44
  // This allows admins to resend purchase receipts to grant additional file downloads
45
- $downloads = edd_get_payment_meta_downloads( $purchase_id );
46
 
47
  if ( is_array( $downloads ) ) {
48
  foreach ( $downloads as $download ) {
4
  *
5
  * @package EDD
6
  * @subpackage Emails
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0.8.2
10
  */
37
  * @return void
38
  */
39
  function edd_resend_purchase_receipt( $data ) {
40
+
41
+ $purchase_id = absint( $data['purchase_id'] );
42
+
43
+ if( empty( $purchase_id ) ) {
44
+ return;
45
+ }
46
+
47
+ if( ! current_user_can( 'edit_shop_payments' ) ) {
48
+ wp_die( __( 'You do not have permission to edit this payment record', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
49
+ }
50
+
51
  edd_email_purchase_receipt( $purchase_id, false );
52
 
53
  // Grab all downloads of the purchase and update their file download limits, if needed
54
  // This allows admins to resend purchase receipts to grant additional file downloads
55
+ $downloads = edd_get_payment_meta_cart_details( $purchase_id, true );
56
 
57
  if ( is_array( $downloads ) ) {
58
  foreach ( $downloads as $download ) {
includes/emails/class-edd-email-tags.php ADDED
@@ -0,0 +1,854 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Easy Digital Downloads API for creating Email template tags
4
+ *
5
+ * Email tags are wrapped in { }
6
+ *
7
+ * A few examples:
8
+ *
9
+ * {download_list}
10
+ * {name}
11
+ * {sitename}
12
+ *
13
+ *
14
+ * To replace tags in content, use: edd_do_email_tags( $content, payment_id );
15
+ *
16
+ * To add tags, use: edd_add_email_tag( $tag, $description, $func ). Be sure to wrap edd_add_email_tag()
17
+ * in a function hooked to the 'edd_email_tags' action
18
+ *
19
+ * @package EDD
20
+ * @subpackage Emails
21
+ * @copyright Copyright (c) 2015, Pippin Williamson
22
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
23
+ * @since 1.9
24
+ * @author Barry Kooij
25
+ */
26
+
27
+ // Exit if accessed directly
28
+ if ( ! defined( 'ABSPATH' ) ) exit;
29
+
30
+ class EDD_Email_Template_Tags {
31
+
32
+ /**
33
+ * Container for storing all tags
34
+ *
35
+ * @since 1.9
36
+ */
37
+ private $tags;
38
+
39
+ /**
40
+ * Payment ID
41
+ *
42
+ * @since 1.9
43
+ */
44
+ private $payment_id;
45
+
46
+ /**
47
+ * Add an email tag
48
+ *
49
+ * @since 1.9
50
+ *
51
+ * @param string $tag Email tag to be replace in email
52
+ * @param callable $func Hook to run when email tag is found
53
+ */
54
+ public function add( $tag, $description, $func ) {
55
+ if ( is_callable( $func ) ) {
56
+ $this->tags[$tag] = array(
57
+ 'tag' => $tag,
58
+ 'description' => $description,
59
+ 'func' => $func
60
+ );
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Remove an email tag
66
+ *
67
+ * @since 1.9
68
+ *
69
+ * @param string $tag Email tag to remove hook from
70
+ */
71
+ public function remove( $tag ) {
72
+ unset( $this->tags[$tag] );
73
+ }
74
+
75
+ /**
76
+ * Check if $tag is a registered email tag
77
+ *
78
+ * @since 1.9
79
+ *
80
+ * @param string $tag Email tag that will be searched
81
+ *
82
+ * @return bool
83
+ */
84
+ public function email_tag_exists( $tag ) {
85
+ return array_key_exists( $tag, $this->tags );
86
+ }
87
+
88
+ /**
89
+ * Returns a list of all email tags
90
+ *
91
+ * @since 1.9
92
+ *
93
+ * @return array
94
+ */
95
+ public function get_tags() {
96
+ return $this->tags;
97
+ }
98
+
99
+ /**
100
+ * Search content for email tags and filter email tags through their hooks
101
+ *
102
+ * @param string $content Content to search for email tags
103
+ * @param int $payment_id The payment id
104
+ *
105
+ * @since 1.9
106
+ *
107
+ * @return string Content with email tags filtered out.
108
+ */
109
+ public function do_tags( $content, $payment_id ) {
110
+
111
+ // Check if there is atleast one tag added
112
+ if ( empty( $this->tags ) || ! is_array( $this->tags ) ) {
113
+ return $content;
114
+ }
115
+
116
+ $this->payment_id = $payment_id;
117
+
118
+ $new_content = preg_replace_callback( "/{([A-z0-9\-\_]+)}/s", array( $this, 'do_tag' ), $content );
119
+
120
+ $this->payment_id = null;
121
+
122
+ return $new_content;
123
+ }
124
+
125
+ /**
126
+ * Do a specific tag, this function should not be used. Please use edd_do_email_tags instead.
127
+ *
128
+ * @since 1.9
129
+ *
130
+ * @param $m message
131
+ *
132
+ * @return mixed
133
+ */
134
+ public function do_tag( $m ) {
135
+
136
+ // Get tag
137
+ $tag = $m[1];
138
+
139
+ // Return tag if tag not set
140
+ if ( ! $this->email_tag_exists( $tag ) ) {
141
+ return $m[0];
142
+ }
143
+
144
+ return call_user_func( $this->tags[$tag]['func'], $this->payment_id, $tag );
145
+ }
146
+
147
+ }
148
+
149
+ /**
150
+ * Add an email tag
151
+ *
152
+ * @since 1.9
153
+ *
154
+ * @param string $tag Email tag to be replace in email
155
+ * @param callable $func Hook to run when email tag is found
156
+ */
157
+ function edd_add_email_tag( $tag, $description, $func ) {
158
+ EDD()->email_tags->add( $tag, $description, $func );
159
+ }
160
+
161
+ /**
162
+ * Remove an email tag
163
+ *
164
+ * @since 1.9
165
+ *
166
+ * @param string $tag Email tag to remove hook from
167
+ */
168
+ function edd_remove_email_tag( $tag ) {
169
+ EDD()->email_tags->remove( $tag );
170
+ }
171
+
172
+ /**
173
+ * Check if $tag is a registered email tag
174
+ *
175
+ * @since 1.9
176
+ *
177
+ * @param string $tag Email tag that will be searched
178
+ *
179
+ * @return bool
180
+ */
181
+ function edd_email_tag_exists( $tag ) {
182
+ return EDD()->email_tags->email_tag_exists( $tag );
183
+ }
184
+
185
+ /**
186
+ * Get all email tags
187
+ *
188
+ * @since 1.9
189
+ *
190
+ * @return array
191
+ */
192
+ function edd_get_email_tags() {
193
+ return EDD()->email_tags->get_tags();
194
+ }
195
+
196
+ /**
197
+ * Get a formatted HTML list of all available email tags
198
+ *
199
+ * @since 1.9
200
+ *
201
+ * @return string
202
+ */
203
+ function edd_get_emails_tags_list() {
204
+ // The list
205
+ $list = '';
206
+
207
+ // Get all tags
208
+ $email_tags = edd_get_email_tags();
209
+
210
+ // Check
211
+ if ( count( $email_tags ) > 0 ) {
212
+
213
+ // Loop
214
+ foreach ( $email_tags as $email_tag ) {
215
+
216
+ // Add email tag to list
217
+ $list .= '{' . $email_tag['tag'] . '} - ' . $email_tag['description'] . '<br/>';
218
+
219
+ }
220
+
221
+ }
222
+
223
+ // Return the list
224
+ return $list;
225
+ }
226
+
227
+ /**
228
+ * Search content for email tags and filter email tags through their hooks
229
+ *
230
+ * @param string $content Content to search for email tags
231
+ * @param int $payment_id The payment id
232
+ *
233
+ * @since 1.9
234
+ *
235
+ * @return string Content with email tags filtered out.
236
+ */
237
+ function edd_do_email_tags( $content, $payment_id ) {
238
+
239
+ // Replace all tags
240
+ $content = EDD()->email_tags->do_tags( $content, $payment_id );
241
+
242
+ // Maintaining backwards compatibility
243
+ $content = apply_filters( 'edd_email_template_tags', $content, edd_get_payment_meta( $payment_id ), $payment_id );
244
+
245
+ // Return content
246
+ return $content;
247
+ }
248
+
249
+ /**
250
+ * Load email tags
251
+ *
252
+ * @since 1.9
253
+ */
254
+ function edd_load_email_tags() {
255
+ do_action( 'edd_add_email_tags' );
256
+ }
257
+ add_action( 'init', 'edd_load_email_tags', -999 );
258
+
259
+ /**
260
+ * Add default EDD email template tags
261
+ *
262
+ * @since 1.9
263
+ */
264
+ function edd_setup_email_tags() {
265
+
266
+ // Setup default tags array
267
+ $email_tags = array(
268
+ array(
269
+ 'tag' => 'download_list',
270
+ 'description' => __( 'A list of download links for each download purchased', 'edd' ),
271
+ 'function' => 'text/html' == EDD()->emails->get_content_type() ? 'edd_email_tag_download_list' : 'edd_email_tag_download_list_plain'
272
+ ),
273
+ array(
274
+ 'tag' => 'file_urls',
275
+ 'description' => __( 'A plain-text list of download URLs for each download purchased', 'edd' ),
276
+ 'function' => 'edd_email_tag_file_urls'
277
+ ),
278
+ array(
279
+ 'tag' => 'name',
280
+ 'description' => __( "The buyer's first name", 'edd' ),
281
+ 'function' => 'edd_email_tag_first_name'
282
+ ),
283
+ array(
284
+ 'tag' => 'fullname',
285
+ 'description' => __( "The buyer's full name, first and last", 'edd' ),
286
+ 'function' => 'edd_email_tag_fullname'
287
+ ),
288
+ array(
289
+ 'tag' => 'username',
290
+ 'description' => __( "The buyer's user name on the site, if they registered an account", 'edd' ),
291
+ 'function' => 'edd_email_tag_username'
292
+ ),
293
+ array(
294
+ 'tag' => 'user_email',
295
+ 'description' => __( "The buyer's email address", 'edd' ),
296
+ 'function' => 'edd_email_tag_user_email'
297
+ ),
298
+ array(
299
+ 'tag' => 'billing_address',
300
+ 'description' => __( 'The buyer\'s billing address', 'edd' ),
301
+ 'function' => 'edd_email_tag_billing_address'
302
+ ),
303
+ array(
304
+ 'tag' => 'date',
305
+ 'description' => __( 'The date of the purchase', 'edd' ),
306
+ 'function' => 'edd_email_tag_date'
307
+ ),
308
+ array(
309
+ 'tag' => 'subtotal',
310
+ 'description' => __( 'The price of the purchase before taxes', 'edd' ),
311
+ 'function' => 'edd_email_tag_subtotal'
312
+ ),
313
+ array(
314
+ 'tag' => 'tax',
315
+ 'description' => __( 'The taxed amount of the purchase', 'edd' ),
316
+ 'function' => 'edd_email_tag_tax'
317
+ ),
318
+ array(
319
+ 'tag' => 'price',
320
+ 'description' => __( 'The total price of the purchase', 'edd' ),
321
+ 'function' => 'edd_email_tag_price'
322
+ ),
323
+ array(
324
+ 'tag' => 'payment_id',
325
+ 'description' => __( 'The unique ID number for this purchase', 'edd' ),
326
+ 'function' => 'edd_email_tag_payment_id'
327
+ ),
328
+ array(
329
+ 'tag' => 'receipt_id',
330
+ 'description' => __( 'The unique ID number for this purchase receipt', 'edd' ),
331
+ 'function' => 'edd_email_tag_receipt_id'
332
+ ),
333
+ array(
334
+ 'tag' => 'payment_method',
335
+ 'description' => __( 'The method of payment used for this purchase', 'edd' ),
336
+ 'function' => 'edd_email_tag_payment_method'
337
+ ),
338
+ array(
339
+ 'tag' => 'sitename',
340
+ 'description' => __( 'Your site name', 'edd' ),
341
+ 'function' => 'edd_email_tag_sitename'
342
+ ),
343
+ array(
344
+ 'tag' => 'receipt_link',
345
+ 'description' => __( 'Adds a link so users can view their receipt directly on your website if they are unable to view it in the browser correctly.', 'edd' ),
346
+ 'function' => 'edd_email_tag_receipt_link'
347
+ ),
348
+ array(
349
+ 'tag' => 'discount_codes',
350
+ 'description' => __( 'Adds a list of any discount codes applied to this purchase', 'edd' ),
351
+ 'function' => 'edd_email_tag_discount_codes'
352
+ ),
353
+ array(
354
+ 'tag' => 'ip_address',
355
+ 'description' => __( 'The buyer\'s IP Address', 'edd' ),
356
+ 'function' => 'edd_email_tag_ip_address'
357
+ )
358
+ );
359
+
360
+ // Apply edd_email_tags filter
361
+ $email_tags = apply_filters( 'edd_email_tags', $email_tags );
362
+
363
+ // Add email tags
364
+ foreach ( $email_tags as $email_tag ) {
365
+ edd_add_email_tag( $email_tag['tag'], $email_tag['description'], $email_tag['function'] );
366
+ }
367
+
368
+ }
369
+ add_action( 'edd_add_email_tags', 'edd_setup_email_tags' );
370
+
371
+ /**
372
+ * Email template tag: download_list
373
+ * A list of download links for each download purchased
374
+ *
375
+ * @param int $payment_id
376
+ *
377
+ * @return string download_list
378
+ */
379
+ function edd_email_tag_download_list( $payment_id ) {
380
+
381
+ $payment_data = edd_get_payment_meta( $payment_id );
382
+ $download_list = '<ul>';
383
+ $cart_items = edd_get_payment_meta_cart_details( $payment_id );
384
+ $email = edd_get_payment_user_email( $payment_id );
385
+
386
+ if ( $cart_items ) {
387
+ $show_names = apply_filters( 'edd_email_show_names', true );
388
+ $show_links = apply_filters( 'edd_email_show_links', true );
389
+
390
+ foreach ( $cart_items as $item ) {
391
+
392
+ if ( edd_use_skus() ) {
393
+ $sku = edd_get_download_sku( $item['id'] );
394
+ }
395
+
396
+ if ( edd_item_quantities_enabled() ) {
397
+ $quantity = $item['quantity'];
398
+ }
399
+
400
+ $price_id = edd_get_cart_item_price_id( $item );
401
+ if ( $show_names ) {
402
+
403
+ $title = '<strong>' . get_the_title( $item['id'] ) . '</strong>';
404
+
405
+ if ( ! empty( $quantity ) && $quantity > 1 ) {
406
+ $title .= "&nbsp;&ndash;&nbsp;" . __( 'Quantity', 'edd' ) . ': ' . $quantity;
407
+ }
408
+
409
+ if ( ! empty( $sku ) ) {
410
+ $title .= "&nbsp;&ndash;&nbsp;" . __( 'SKU', 'edd' ) . ': ' . $sku;
411
+ }
412
+
413
+ if ( $price_id !== null ) {
414
+ $title .= "&nbsp;&ndash;&nbsp;" . edd_get_price_option_name( $item['id'], $price_id, $payment_id );
415
+ }
416
+
417
+ $download_list .= '<li>' . apply_filters( 'edd_email_receipt_download_title', $title, $item, $price_id, $payment_id ) . '<br/>';
418
+ }
419
+
420
+ $files = edd_get_download_files( $item['id'], $price_id );
421
+
422
+ if ( ! empty( $files ) ) {
423
+
424
+ foreach ( $files as $filekey => $file ) {
425
+
426
+ if ( $show_links ) {
427
+ $download_list .= '<div>';
428
+ $file_url = edd_get_download_file_url( $payment_data['key'], $email, $filekey, $item['id'], $price_id );
429
+ $download_list .= '<a href="' . esc_url( $file_url ) . '">' . edd_get_file_name( $file ) . '</a>';
430
+ $download_list .= '</div>';
431
+ } else {
432
+ $download_list .= '<div>';
433
+ $download_list .= edd_get_file_name( $file );
434
+ $download_list .= '</div>';
435
+ }
436
+
437
+ }
438
+
439
+ } elseif ( edd_is_bundled_product( $item['id'] ) ) {
440
+
441
+ $bundled_products = apply_filters( 'edd_email_tag_bundled_products', edd_get_bundled_products( $item['id'] ), $item, $payment_id, 'download_list' );
442
+
443
+ foreach ( $bundled_products as $bundle_item ) {
444
+
445
+ $download_list .= '<div class="edd_bundled_product"><strong>' . get_the_title( $bundle_item ) . '</strong></div>';
446
+
447
+ $files = edd_get_download_files( $bundle_item );
448
+
449
+ foreach ( $files as $filekey => $file ) {
450
+ if ( $show_links ) {
451
+ $download_list .= '<div>';
452
+ $file_url = edd_get_download_file_url( $payment_data['key'], $email, $filekey, $bundle_item, $price_id );
453
+ $download_list .= '<a href="' . esc_url( $file_url ) . '">' . $file['name'] . '</a>';
454
+ $download_list .= '</div>';
455
+ } else {
456
+ $download_list .= '<div>';
457
+ $download_list .= $file['name'];
458
+ $download_list .= '</div>';
459
+ }
460
+ }
461
+ }
462
+ }
463
+
464
+
465
+ if ( '' != edd_get_product_notes( $item['id'] ) ) {
466
+ $download_list .= ' &mdash; <small>' . edd_get_product_notes( $item['id'] ) . '</small>';
467
+ }
468
+
469
+
470
+ if ( $show_names ) {
471
+ $download_list .= '</li>';
472
+ }
473
+ }
474
+ }
475
+ $download_list .= '</ul>';
476
+
477
+ return $download_list;
478
+ }
479
+
480
+ /**
481
+ * Email template tag: download_list
482
+ * A list of download links for each download purchased in plaintext
483
+ *
484
+ * @since 2.1.1
485
+ * @param int $payment_id
486
+ *
487
+ * @return string download_list
488
+ */
489
+ function edd_email_tag_download_list_plain( $payment_id ) {
490
+
491
+ $payment_data = edd_get_payment_meta( $payment_id );
492
+ $cart_items = edd_get_payment_meta_cart_details( $payment_id );
493
+ $email = edd_get_payment_user_email( $payment_id );
494
+ $download_list = '';
495
+
496
+ if ( $cart_items ) {
497
+ $show_names = apply_filters( 'edd_email_show_names', true );
498
+ $show_links = apply_filters( 'edd_email_show_links', true );
499
+
500
+ foreach ( $cart_items as $item ) {
501
+
502
+ if ( edd_use_skus() ) {
503
+ $sku = edd_get_download_sku( $item['id'] );
504
+ }
505
+
506
+ if ( edd_item_quantities_enabled() ) {
507
+ $quantity = $item['quantity'];
508
+ }
509
+
510
+ $price_id = edd_get_cart_item_price_id( $item );
511
+ if ( $show_names ) {
512
+
513
+ $title = get_the_title( $item['id'] );
514
+
515
+ if ( ! empty( $quantity ) && $quantity > 1 ) {
516
+ $title .= __( 'Quantity', 'edd' ) . ': ' . $quantity;
517
+ }
518
+
519
+ if ( ! empty( $sku ) ) {
520
+ $title .= __( 'SKU', 'edd' ) . ': ' . $sku;
521
+ }
522
+
523
+ if ( $price_id !== null ) {
524
+ $title .= edd_get_price_option_name( $item['id'], $price_id, $payment_id );
525
+ }
526
+
527
+ $download_list .= "\n";
528
+
529
+ $download_list .= apply_filters( 'edd_email_receipt_download_title', $title, $item, $price_id, $payment_id ) . "\n";
530
+ }
531
+
532
+ $files = edd_get_download_files( $item['id'], $price_id );
533
+
534
+ if ( ! empty( $files ) ) {
535
+
536
+ foreach ( $files as $filekey => $file ) {
537
+ if( $show_links ) {
538
+ $download_list .= "\n";
539
+ $file_url = edd_get_download_file_url( $payment_data['key'], $email, $filekey, $item['id'], $price_id );
540
+ $download_list .= edd_get_file_name( $file ) . ': ' . $file_url . "\n";
541
+ } else {
542
+ $download_list .= "\n";
543
+ $download_list .= edd_get_file_name( $file ) . "\n";
544
+ }
545
+ }
546
+
547
+ } elseif ( edd_is_bundled_product( $item['id'] ) ) {
548
+
549
+ $bundled_products = apply_filters( 'edd_email_tag_bundled_products', edd_get_bundled_products( $item['id'] ), $item, $payment_id, 'download_list' );
550
+
551
+ foreach ( $bundled_products as $bundle_item ) {
552
+
553
+ $download_list .= '<div class="edd_bundled_product"><strong>' . get_the_title( $bundle_item ) . '</strong></div>';
554
+
555
+ $files = edd_get_download_files( $bundle_item );
556
+
557
+ foreach ( $files as $filekey => $file ) {
558
+ if( $show_links ) {
559
+ $file_url = edd_get_download_file_url( $payment_data['key'], $email, $filekey, $bundle_item, $price_id );
560
+ $download_list .= $file['name'] . ': ' . $file_url . "\n";
561
+ } else {
562
+ $download_list .= $file['name'] . "\n";
563
+ }
564
+ }
565
+ }
566
+ }
567
+
568
+
569
+ if ( '' != edd_get_product_notes( $item['id'] ) ) {
570
+ $download_list .= "\n";
571
+ $download_list .= edd_get_product_notes( $item['id'] ) . "\n";
572
+ }
573
+ }
574
+ }
575
+
576
+ return $download_list;
577
+ }
578
+
579
+ /**
580
+ * Email template tag: file_urls
581
+ * A plain-text list of download URLs for each download purchased
582
+ *
583
+ * @param int $payment_id
584
+ *
585
+ * @return string $file_urls
586
+ */
587
+ function edd_email_tag_file_urls( $payment_id ) {
588
+
589
+ $payment_data = edd_get_payment_meta( $payment_id );
590
+ $file_urls = '';
591
+ $cart_items = edd_get_payment_meta_cart_details( $payment_id );
592
+ $email = edd_get_payment_user_email( $payment_id );
593
+
594
+ foreach ( $cart_items as $item ) {
595
+
596
+ $price_id = edd_get_cart_item_price_id( $item );
597
+ $files = edd_get_download_files( $item['id'], $price_id );
598
+
599
+ if ( $files ) {
600
+ foreach ( $files as $filekey => $file ) {
601
+ $file_url = edd_get_download_file_url( $payment_data['key'], $email, $filekey, $item['id'], $price_id );
602
+
603
+ $file_urls .= esc_html( $file_url ) . '<br/>';
604
+ }
605
+ }
606
+ elseif ( edd_is_bundled_product( $item['id'] ) ) {
607
+
608
+ $bundled_products = apply_filters( 'edd_email_tag_bundled_products', edd_get_bundled_products( $item['id'] ), $item, $payment_id, 'file_urls' );
609
+
610
+ foreach ( $bundled_products as $bundle_item ) {
611
+
612
+ $files = edd_get_download_files( $bundle_item );
613
+ foreach ( $files as $filekey => $file ) {
614
+ $file_url = edd_get_download_file_url( $payment_data['key'], $email, $filekey, $bundle_item, $price_id );
615
+ $file_urls .= esc_html( $file_url ) . '<br/>';
616
+ }
617
+
618
+ }
619
+ }
620
+
621
+ }
622
+
623
+ return $file_urls;
624
+ }
625
+
626
+ /**
627
+ * Email template tag: name
628
+ * The buyer's first name
629
+ *
630
+ * @param int $payment_id
631
+ *
632
+ * @return string name
633
+ */
634
+ function edd_email_tag_first_name( $payment_id ) {
635
+ $payment_data = edd_get_payment_meta( $payment_id );
636
+ if( empty( $payment_data['user_info'] ) ) {
637
+ return '';
638
+ }
639
+ $email_name = edd_get_email_names( $payment_data['user_info'] );
640
+ return $email_name['name'];
641
+ }
642
+
643
+ /**
644
+ * Email template tag: fullname
645
+ * The buyer's full name, first and last
646
+ *
647
+ * @param int $payment_id
648
+ *
649
+ * @return string fullname
650
+ */
651
+ function edd_email_tag_fullname( $payment_id ) {
652
+ $payment_data = edd_get_payment_meta( $payment_id );
653
+ if( empty( $payment_data['user_info'] ) ) {
654
+ return '';
655
+ }
656
+ $email_name = edd_get_email_names( $payment_data['user_info'] );
657
+ return $email_name['fullname'];
658
+ }
659
+
660
+ /**
661
+ * Email template tag: username
662
+ * The buyer's user name on the site, if they registered an account
663
+ *
664
+ * @param int $payment_id
665
+ *
666
+ * @return string username
667
+ */
668
+ function edd_email_tag_username( $payment_id ) {
669
+ $payment_data = edd_get_payment_meta( $payment_id );
670
+ if( empty( $payment_data['user_info'] ) ) {
671
+ return '';
672
+ }
673
+ $email_name = edd_get_email_names( $payment_data['user_info'] );
674
+ return $email_name['username'];
675
+ }
676
+
677
+ /**
678
+ * Email template tag: user_email
679
+ * The buyer's email address
680
+ *
681
+ * @param int $payment_id
682
+ *
683
+ * @return string user_email
684
+ */
685
+ function edd_email_tag_user_email( $payment_id ) {
686
+ return edd_get_payment_user_email( $payment_id );
687
+ }
688
+
689
+ /**
690
+ * Email template tag: billing_address
691
+ * The buyer's billing address
692
+ *
693
+ * @param int $payment_id
694
+ *
695
+ * @return string billing_address
696
+ */
697
+ function edd_email_tag_billing_address( $payment_id ) {
698
+
699
+ $user_info = edd_get_payment_meta_user_info( $payment_id );
700
+ $user_address = ! empty( $user_info['address'] ) ? $user_info['address'] : array( 'line1' => '', 'line2' => '', 'city' => '', 'country' => '', 'state' => '', 'zip' => '' );
701
+
702
+ $return = $user_address['line1'] . "\n";
703
+ if( ! empty( $user_address['line2'] ) ) {
704
+ $return .= $user_address['line2'] . "\n";
705
+ }
706
+ $return .= $user_address['city'] . ' ' . $user_address['zip'] . ' ' . $user_address['state'] . "\n";
707
+ $return .= $user_address['country'];
708
+
709
+ return $return;
710
+ }
711
+
712
+ /**
713
+ * Email template tag: date
714
+ * Date of purchase
715
+ *
716
+ * @param int $payment_id
717
+ *
718
+ * @return string date
719
+ */
720
+ function edd_email_tag_date( $payment_id ) {
721
+ $payment_data = edd_get_payment_meta( $payment_id );
722
+ return date_i18n( get_option( 'date_format' ), strtotime( $payment_data['date'] ) );
723
+ }
724
+
725
+ /**
726
+ * Email template tag: subtotal
727
+ * Price of purchase before taxes
728
+ *
729
+ * @param int $payment_id
730
+ *
731
+ * @return string subtotal
732
+ */
733
+ function edd_email_tag_subtotal( $payment_id ) {
734
+ $subtotal = edd_currency_filter( edd_format_amount( edd_get_payment_subtotal( $payment_id ) ), edd_get_payment_currency_code( $payment_id ) );
735
+ return html_entity_decode( $subtotal, ENT_COMPAT, 'UTF-8' );
736
+ }
737
+
738
+ /**
739
+ * Email template tag: tax
740
+ * The taxed amount of the purchase
741
+ *
742
+ * @param int $payment_id
743
+ *
744
+ * @return string tax
745
+ */
746
+ function edd_email_tag_tax( $payment_id ) {
747
+ $tax = edd_currency_filter( edd_format_amount( edd_get_payment_tax( $payment_id ) ), edd_get_payment_currency_code( $payment_id ) );
748
+ return html_entity_decode( $tax, ENT_COMPAT, 'UTF-8' );
749
+ }
750
+
751
+ /**
752
+ * Email template tag: price
753
+ * The total price of the purchase
754
+ *
755
+ * @param int $payment_id
756
+ *
757
+ * @return string price
758
+ */
759
+ function edd_email_tag_price( $payment_id ) {
760
+ $price = edd_currency_filter( edd_format_amount( edd_get_payment_amount( $payment_id ) ), edd_get_payment_currency_code( $payment_id ) );
761
+ return html_entity_decode( $price, ENT_COMPAT, 'UTF-8' );
762
+ }
763
+
764
+ /**
765
+ * Email template tag: payment_id
766
+ * The unique ID number for this purchase
767
+ *
768
+ * @param int $payment_id
769
+ *
770
+ * @return int payment_id
771
+ */
772
+ function edd_email_tag_payment_id( $payment_id ) {
773
+ return edd_get_payment_number( $payment_id );
774
+ }
775
+
776
+ /**
777
+ * Email template tag: receipt_id
778
+ * The unique ID number for this purchase receipt
779
+ *
780
+ * @param int $payment_id
781
+ *
782
+ * @return string receipt_id
783
+ */
784
+ function edd_email_tag_receipt_id( $payment_id ) {
785
+ return edd_get_payment_key( $payment_id );
786
+ }
787
+
788
+ /**
789
+ * Email template tag: payment_method
790
+ * The method of payment used for this purchase
791
+ *
792
+ * @param int $payment_id
793
+ *
794
+ * @return string gateway
795
+ */
796
+ function edd_email_tag_payment_method( $payment_id ) {
797
+ return edd_get_gateway_checkout_label( edd_get_payment_gateway( $payment_id ) );
798
+ }
799
+
800
+ /**
801
+ * Email template tag: sitename
802
+ * Your site name
803
+ *
804
+ * @param int $payment_id
805
+ *
806
+ * @return string sitename
807
+ */
808
+ function edd_email_tag_sitename( $payment_id ) {
809
+ return wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
810
+ }
811
+
812
+ /**
813
+ * Email template tag: receipt_link
814
+ * Adds a link so users can view their receipt directly on your website if they are unable to view it in the browser correctly
815
+ *
816
+ * @param $int payment_id
817
+ *
818
+ * @return string receipt_link
819
+ */
820
+ function edd_email_tag_receipt_link( $payment_id ) {
821
+ return sprintf( __( '%1$sView it in your browser.%2$s', 'edd' ), '<a href="' . esc_url( add_query_arg( array( 'payment_key' => edd_get_payment_key( $payment_id ), 'edd_action' => 'view_receipt' ), home_url() ) ) . '">', '</a>' );
822
+ }
823
+
824
+ /**
825
+ * Email template tag: discount_codes
826
+ * Adds a list of any discount codes applied to this purchase
827
+ *
828
+ * @since 2.0
829
+ * @param $int payment_id
830
+ * @return string $discount_codes
831
+ */
832
+ function edd_email_tag_discount_codes( $payment_id ) {
833
+ $user_info = edd_get_payment_meta_user_info( $payment_id );
834
+
835
+ $discount_codes = '';
836
+
837
+ if( isset( $user_info['discount'] ) && $user_info['discount'] !== 'none' ) {
838
+ $discount_codes = $user_info['discount'];
839
+ }
840
+
841
+ return $discount_codes;
842
+ }
843
+
844
+ /**
845
+ * Email template tag: IP address
846
+ * IP address of the customer
847
+ *
848
+ * @since 2.3
849
+ * @param int $payment_id
850
+ * @return string IP address
851
+ */
852
+ function edd_email_tag_ip_address( $payment_id ) {
853
+ return edd_get_payment_user_ip( $payment_id );
854
+ }
includes/emails/class-edd-emails.php ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Emails
4
+ *
5
+ * This class handles all emails sent through EDD
6
+ *
7
+ * @package EDD
8
+ * @subpackage Classes/Emails
9
+ * @copyright Copyright (c) 2015, Pippin Williamson
10
+ * @license http://opensource.org/licenses/gpl-2.1.php GNU Public License
11
+ * @since 2.1
12
+ */
13
+
14
+ // Exit if accessed directly
15
+ if ( ! defined( 'ABSPATH' ) ) exit;
16
+
17
+ /**
18
+ * EDD_Emails Class
19
+ *
20
+ * @since 2.1
21
+ */
22
+ class EDD_Emails {
23
+
24
+ /**
25
+ * Holds the from address
26
+ *
27
+ * @since 2.1
28
+ */
29
+ private $from_address;
30
+
31
+ /**
32
+ * Holds the from name
33
+ *
34
+ * @since 2.1
35
+ */
36
+ private $from_name;
37
+
38
+ /**
39
+ * Holds the email content type
40
+ *
41
+ * @since 2.1
42
+ */
43
+ private $content_type;
44
+
45
+ /**
46
+ * Holds the email headers
47
+ *
48
+ * @since 2.1
49
+ */
50
+ private $headers;
51
+
52
+ /**
53
+ * Whether to send email in HTML
54
+ *
55
+ * @since 2.1
56
+ */
57
+ private $html = true;
58
+
59
+ /**
60
+ * The email template to use
61
+ *
62
+ * @since 2.1
63
+ */
64
+ private $template;
65
+
66
+ /**
67
+ * The header text for the email
68
+ *
69
+ * @since 2.1
70
+ */
71
+ private $heading = '';
72
+
73
+ /**
74
+ * Get things going
75
+ *
76
+ * @since 2.1
77
+ */
78
+ public function __construct() {
79
+
80
+ if ( 'none' === $this->get_template() ) {
81
+ $this->html = false;
82
+ }
83
+
84
+ add_action( 'edd_email_send_before', array( $this, 'send_before' ) );
85
+ add_action( 'edd_email_send_after', array( $this, 'send_after' ) );
86
+
87
+ }
88
+
89
+ /**
90
+ * Set a property
91
+ *
92
+ * @since 2.1
93
+ */
94
+ public function __set( $key, $value ) {
95
+ $this->$key = $value;
96
+ }
97
+
98
+ /**
99
+ * Get the email from name
100
+ *
101
+ * @since 2.1
102
+ */
103
+ public function get_from_name() {
104
+ if ( ! $this->from_name ) {
105
+ $this->from_name = edd_get_option( 'from_name', get_bloginfo( 'name' ) );
106
+ }
107
+
108
+ return apply_filters( 'edd_email_from_name', wp_specialchars_decode( $this->from_name ), $this );
109
+ }
110
+
111
+ /**
112
+ * Get the email from address
113
+ *
114
+ * @since 2.1
115
+ */
116
+ public function get_from_address() {
117
+ if ( ! $this->from_address ) {
118
+ $this->from_address = edd_get_option( 'from_email', get_option( 'admin_email' ) );
119
+ }
120
+
121
+ return apply_filters( 'edd_email_from_address', $this->from_address, $this );
122
+ }
123
+
124
+ /**
125
+ * Get the email content type
126
+ *
127
+ * @since 2.1
128
+ */
129
+ public function get_content_type() {
130
+ if ( ! $this->content_type && $this->html ) {
131
+ $this->content_type = apply_filters( 'edd_email_default_content_type', 'text/html', $this );
132
+ } else if ( ! $this->html ) {
133
+ $this->content_type = 'text/plain';
134
+ }
135
+
136
+ return apply_filters( 'edd_email_content_type', $this->content_type, $this );
137
+ }
138
+
139
+ /**
140
+ * Get the email headers
141
+ *
142
+ * @since 2.1
143
+ */
144
+ public function get_headers() {
145
+ if ( ! $this->headers ) {
146
+ $this->headers = "From: {$this->get_from_name()} <{$this->get_from_address()}>\r\n";
147
+ $this->headers .= "Reply-To: {$this->get_from_address()}\r\n";
148
+ $this->headers .= "Content-Type: {$this->get_content_type()}; charset=utf-8\r\n";
149
+ }
150
+
151
+ return apply_filters( 'edd_email_headers', $this->headers, $this );
152
+ }
153
+
154
+ /**
155
+ * Retrieve email templates
156
+ *
157
+ * @since 2.1
158
+ */
159
+ public function get_templates() {
160
+ $templates = array(
161
+ 'default' => __( 'Default Template', 'edd' ),
162
+ 'none' => __( 'No template, plain text only', 'edd' )
163
+ );
164
+
165
+ return apply_filters( 'edd_email_templates', $templates );
166
+ }
167
+
168
+ /**
169
+ * Get the enabled email template
170
+ *
171
+ * @since 2.1
172
+ *
173
+ * @return string|null
174
+ */
175
+ public function get_template() {
176
+ if ( ! $this->template ) {
177
+ $this->template = edd_get_option( 'email_template', 'default' );
178
+ }
179
+
180
+ return apply_filters( 'edd_email_template', $this->template );
181
+ }
182
+
183
+ /**
184
+ * Get the header text for the email
185
+ *
186
+ * @since 2.1
187
+ */
188
+ public function get_heading() {
189
+ return apply_filters( 'edd_email_heading', $this->heading );
190
+ }
191
+
192
+ /**
193
+ * Parse email template tags
194
+ *
195
+ * @since 2.1
196
+ * @param string $content
197
+ */
198
+ public function parse_tags( $content ) {
199
+
200
+ // The email tags are parsed during setup for purchase receipts and sale notifications
201
+ // Onoce tags are not restricted to payments, we'll expand this. See https://github.com/easydigitaldownloads/Easy-Digital-Downloads/issues/2151
202
+
203
+ return $content;
204
+ }
205
+
206
+ /**
207
+ * Build the final email
208
+ *
209
+ * @since 2.1
210
+ * @param string $message
211
+ *
212
+ * @return string
213
+ */
214
+ public function build_email( $message ) {
215
+
216
+ if ( false === $this->html ) {
217
+ return apply_filters( 'edd_email_message', wp_strip_all_tags( $message ), $this );
218
+ }
219
+
220
+ $message = $this->text_to_html( $message );
221
+
222
+ ob_start();
223
+
224
+ edd_get_template_part( 'emails/header', $this->get_template(), true );
225
+
226
+ /**
227
+ * Hooks into the email header
228
+ *
229
+ * @since 2.1
230
+ */
231
+ do_action( 'edd_email_header', $this );
232
+
233
+ if ( has_action( 'edd_email_template_' . $this->get_template() ) ) {
234
+ /**
235
+ * Hooks into the template of the email
236
+ *
237
+ * @param string $this->template Gets the enabled email template
238
+ * @since 2.1
239
+ */
240
+ do_action( 'edd_email_template_' . $this->get_template() );
241
+ } else {
242
+ edd_get_template_part( 'emails/body', $this->get_template(), true );
243
+ }
244
+
245
+ /**
246
+ * Hooks into the body of the email
247
+ *
248
+ * @since 2.1
249
+ */
250
+ do_action( 'edd_email_body', $this );
251
+
252
+ edd_get_template_part( 'emails/footer', $this->get_template(), true );
253
+
254
+ /**
255
+ * Hooks into the footer of the email
256
+ *
257
+ * @since 2.1
258
+ */
259
+ do_action( 'edd_email_footer', $this );
260
+
261
+ $body = ob_get_clean();
262
+ $message = str_replace( '{email}', $message, $body );
263
+
264
+ return apply_filters( 'edd_email_message', $message, $this );
265
+ }
266
+
267
+ /**
268
+ * Send the email
269
+ * @param string $to The To address to send to.
270
+ * @param string $subject The subject line of the email to send.
271
+ * @param string $message The body of the email to send.
272
+ * @param string|array $attachments Attachments to the email in a format supported by wp_mail()
273
+ * @since 2.1
274
+ */
275
+ public function send( $to, $subject, $message, $attachments = '' ) {
276
+
277
+ if ( ! did_action( 'init' ) && ! did_action( 'admin_init' ) ) {
278
+ _doing_it_wrong( __FUNCTION__, __( 'You cannot send email with EDD_Emails until init/admin_init has been reached', 'edd' ), null );
279
+ return false;
280
+ }
281
+
282
+ /**
283
+ * Hooks before the email is sent
284
+ *
285
+ * @since 2.1
286
+ */
287
+ do_action( 'edd_email_send_before', $this );
288
+
289
+ $subject = $this->parse_tags( $subject );
290
+ $message = $this->parse_tags( $message );
291
+
292
+ $message = $this->build_email( $message );
293
+
294
+ $attachments = apply_filters( 'edd_email_attachments', $attachments, $this );
295
+
296
+ $sent = wp_mail( $to, $subject, $message, $this->get_headers(), $attachments );
297
+
298
+ /**
299
+ * Hooks after the email is sent
300
+ *
301
+ * @since 2.1
302
+ */
303
+ do_action( 'edd_email_send_after', $this );
304
+
305
+ return $sent;
306
+
307
+ }
308
+
309
+ /**
310
+ * Add filters / actions before the email is sent
311
+ *
312
+ * @since 2.1
313
+ */
314
+ public function send_before() {
315
+ add_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
316
+ add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );
317
+ add_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) );
318
+ }
319
+
320
+ /**
321
+ * Remove filters / actions after the email is sent
322
+ *
323
+ * @since 2.1
324
+ */
325
+ public function send_after() {
326
+ remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
327
+ remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );
328
+ remove_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) );
329
+
330
+ // Reset heading to an empty string
331
+ $this->heading = '';
332
+ }
333
+
334
+ /**
335
+ * Converts text to formatted HTML. This is primarily for turning line breaks into <p> and <br/> tags.
336
+ *
337
+ * @since 2.1
338
+ */
339
+ public function text_to_html( $message ) {
340
+
341
+ if ( 'text/html' == $this->content_type || true === $this->html ) {
342
+ $message = wpautop( $message );
343
+ }
344
+
345
+ return $message;
346
+ }
347
+
348
+ }
includes/emails/email-tags.php CHANGED
@@ -686,7 +686,7 @@ function edd_email_tag_sitename( $payment_id ) {
686
  * @return string receipt_link
687
  */
688
  function edd_email_tag_receipt_link( $payment_id ) {
689
- return sprintf( __( '%1$sView it in your browser.%2$s', 'edd' ), '<a href="' . esc_url( add_query_arg( array( 'payment_key' => edd_get_payment_key( $payment_id ), 'edd_action' => 'view_receipt' ), home_url() ) ) . '">', '</a>' );
690
  }
691
 
692
  /**
686
  * @return string receipt_link
687
  */
688
  function edd_email_tag_receipt_link( $payment_id ) {
689
+ return sprintf( __( '%1$sView it in your browser.%2$s', 'edd' ), '<a href="' . add_query_arg( array( 'payment_key' => edd_get_payment_key( $payment_id ), 'edd_action' => 'view_receipt' ), home_url() ) . '">', '</a>' );
690
  }
691
 
692
  /**
includes/emails/functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Emails
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -22,49 +22,35 @@ if ( ! defined( 'ABSPATH' ) ) exit;
22
  * @return void
23
  */
24
  function edd_email_purchase_receipt( $payment_id, $admin_notice = true ) {
25
- global $edd_options;
26
 
27
  $payment_data = edd_get_payment_meta( $payment_id );
28
- $user_id = edd_get_payment_user_id( $payment_id );
29
- $user_info = maybe_unserialize( $payment_data['user_info'] );
30
- $email = edd_get_payment_user_email( $payment_id );
31
-
32
- if ( isset( $user_id ) && $user_id > 0 ) {
33
- $user_data = get_userdata($user_id);
34
- $name = $user_data->display_name;
35
- } elseif ( isset( $user_info['first_name'] ) && isset( $user_info['last_name'] ) ) {
36
- $name = $user_info['first_name'] . ' ' . $user_info['last_name'];
37
- } else {
38
- $name = $email;
39
- }
40
 
41
- $message = edd_get_email_body_header();
42
- $message .= edd_get_email_body_content( $payment_id, $payment_data, $admin_notice );
43
- $message .= edd_get_email_body_footer();
44
 
45
- $from_name = isset( $edd_options['from_name'] ) ? $edd_options['from_name'] : get_bloginfo('name');
46
- $from_name = apply_filters( 'edd_purchase_from_name', $from_name, $payment_id, $payment_data );
47
 
48
- $from_email = isset( $edd_options['from_email'] ) ? $edd_options['from_email'] : get_option('admin_email');
49
- $from_email = apply_filters( 'edd_purchase_from_address', $from_email, $payment_id, $payment_data );
50
 
51
- $subject = apply_filters( 'edd_purchase_subject', ! empty( $edd_options['purchase_subject'] )
52
- ? wp_strip_all_tags( $edd_options['purchase_subject'], true )
53
- : __( 'Purchase Receipt', 'edd' ), $payment_id );
54
 
55
- $subject = edd_do_email_tags( $subject, $payment_id );
 
56
 
57
- $headers = "From: " . stripslashes_deep( html_entity_decode( $from_name, ENT_COMPAT, 'UTF-8' ) ) . " <$from_email>\r\n";
58
- $headers .= "Reply-To: ". $from_email . "\r\n";
59
- //$headers .= "MIME-Version: 1.0\r\n";
60
- $headers .= "Content-Type: text/html; charset=utf-8\r\n";
61
- $headers = apply_filters( 'edd_receipt_headers', $headers, $payment_id, $payment_data );
62
 
63
- // Allow add-ons to add file attachments
64
- $attachments = apply_filters( 'edd_receipt_attachments', array(), $payment_id, $payment_data );
65
- if ( apply_filters( 'edd_email_purchase_receipt', true ) ) {
66
- wp_mail( $email, $subject, $message, $headers, $attachments );
67
- }
 
 
 
 
68
 
69
  if ( $admin_notice && ! edd_admin_notices_disabled( $payment_id ) ) {
70
  do_action( 'edd_admin_sale_notice', $payment_id, $payment_data );
@@ -75,37 +61,34 @@ function edd_email_purchase_receipt( $payment_id, $admin_notice = true ) {
75
  * Email the download link(s) and payment confirmation to the admin accounts for testing.
76
  *
77
  * @since 1.5
78
- * @global $edd_options Array of all the EDD Options
79
  * @return void
80
  */
81
  function edd_email_test_purchase_receipt() {
82
- global $edd_options;
83
 
84
- $default_email_body = __( "Dear", "edd" ) . " {name},\n\n";
85
- $default_email_body .= __( "Thank you for your purchase. Please click on the link(s) below to download your files.", "edd" ) . "\n\n";
86
- $default_email_body .= "{download_list}\n\n";
87
- $default_email_body .= "{sitename}";
 
 
 
 
 
88
 
89
- $email = isset( $edd_options['purchase_receipt'] ) ? $edd_options['purchase_receipt'] : $default_email_body;
90
 
91
- $message = edd_get_email_body_header();
92
- $message .= apply_filters( 'edd_purchase_receipt', edd_email_preview_template_tags( $email ), 0, array() );
93
- $message .= edd_get_email_body_footer();
94
 
95
- $from_name = isset( $edd_options['from_name'] ) ? $edd_options['from_name'] : get_bloginfo('name');
96
- $from_email = isset( $edd_options['from_email'] ) ? $edd_options['from_email'] : get_option('admin_email');
 
 
97
 
98
- $subject = apply_filters( 'edd_purchase_subject', isset( $edd_options['purchase_subject'] )
99
- ? trim( $edd_options['purchase_subject'] )
100
- : __( 'Purchase Receipt', 'edd' ), 0 );
101
 
102
- $headers = "From: " . stripslashes_deep( html_entity_decode( $from_name, ENT_COMPAT, 'UTF-8' ) ) . " <$from_email>\r\n";
103
- $headers .= "Reply-To: ". $from_email . "\r\n";
104
- //$headers .= "MIME-Version: 1.0\r\n";
105
- $headers .= "Content-Type: text/html; charset=utf-8\r\n";
106
- $headers = apply_filters( 'edd_test_purchase_headers', $headers );
107
 
108
- wp_mail( edd_get_admin_notice_emails(), $subject, $message, $headers );
109
  }
110
 
111
  /**
@@ -117,47 +100,45 @@ function edd_email_test_purchase_receipt() {
117
  * @return void
118
  */
119
  function edd_admin_email_notice( $payment_id = 0, $payment_data = array() ) {
120
- global $edd_options;
121
-
122
- /* Send an email notification to the admin */
123
- $admin_email = edd_get_admin_notice_emails();
124
- $user_id = edd_get_payment_user_id( $payment_id );
125
- $user_info = maybe_unserialize( $payment_data['user_info'] );
126
-
127
- if ( isset( $user_id ) && $user_id > 0 ) {
128
- $user_data = get_userdata($user_id);
129
- $name = $user_data->display_name;
130
- } elseif ( isset( $user_info['first_name'] ) && isset( $user_info['last_name'] ) ) {
131
- $name = $user_info['first_name'] . ' ' . $user_info['last_name'];
132
- } else {
133
- $name = $user_info['email'];
134
- }
135
 
136
- $admin_message = edd_get_email_body_header();
137
- $admin_message .= edd_get_sale_notification_body_content( $payment_id, $payment_data );
138
- $admin_message .= edd_get_email_body_footer();
139
 
140
- if( ! empty( $edd_options['sale_notification_subject'] ) ) {
141
- $admin_subject = wp_strip_all_tags( $edd_options['sale_notification_subject'], true );
142
- } else {
143
- $admin_subject = sprintf( __( 'New download purchase - Order #%1$s', 'edd' ), $payment_id );
 
 
144
  }
145
 
146
- $admin_subject = edd_do_email_tags( $admin_subject, $payment_id );
147
- $admin_subject = apply_filters( 'edd_admin_sale_notification_subject', $admin_subject, $payment_id, $payment_data );
 
 
 
 
 
 
 
148
 
149
- $from_name = isset( $edd_options['from_name'] ) ? $edd_options['from_name'] : get_bloginfo('name');
150
- $from_email = isset( $edd_options['from_email'] ) ? $edd_options['from_email'] : get_option('admin_email');
 
 
 
151
 
152
- $admin_headers = "From: " . stripslashes_deep( html_entity_decode( $from_name, ENT_COMPAT, 'UTF-8' ) ) . " <$from_email>\r\n";
153
- $admin_headers .= "Reply-To: ". $from_email . "\r\n";
154
- //$admin_headers .= "MIME-Version: 1.0\r\n";
155
- $admin_headers .= "Content-Type: text/html; charset=utf-8\r\n";
156
- $admin_headers .= apply_filters( 'edd_admin_sale_notification_headers', $admin_headers, $payment_id, $payment_data );
157
 
158
- $admin_attachments = apply_filters( 'edd_admin_sale_notification_attachments', array(), $payment_id, $payment_data );
 
 
 
 
 
 
 
 
159
 
160
- wp_mail( $admin_email, $admin_subject, $admin_message, $admin_headers, $admin_attachments );
161
  }
162
  add_action( 'edd_admin_sale_notice', 'edd_admin_email_notice', 10, 2 );
163
 
@@ -166,13 +147,11 @@ add_action( 'edd_admin_sale_notice', 'edd_admin_email_notice', 10, 2 );
166
  * changed in the EDD Settings)
167
  *
168
  * @since 1.0
169
- * @global $edd_options Array of all the EDD Options
170
  * @return mixed
171
  */
172
  function edd_get_admin_notice_emails() {
173
- global $edd_options;
174
-
175
- $emails = isset( $edd_options['admin_notice_emails'] ) && strlen( trim( $edd_options['admin_notice_emails'] ) ) > 0 ? $edd_options['admin_notice_emails'] : get_bloginfo( 'admin_email' );
176
  $emails = array_map( 'trim', explode( "\n", $emails ) );
177
 
178
  return apply_filters( 'edd_admin_notice_emails', $emails );
@@ -187,9 +166,8 @@ function edd_get_admin_notice_emails() {
187
  * @return mixed
188
  */
189
  function edd_admin_notices_disabled( $payment_id = 0 ) {
190
- global $edd_options;
191
- $retval = isset( $edd_options['disable_admin_notices'] );
192
- return apply_filters( 'edd_admin_notices_disabled', $retval, $payment_id );
193
  }
194
 
195
  /**
@@ -202,8 +180,6 @@ function edd_admin_notices_disabled( $payment_id = 0 ) {
202
  * @return string $message
203
  */
204
  function edd_get_default_sale_notification_email() {
205
- global $edd_options;
206
-
207
  $default_email_body = __( 'Hello', 'edd' ) . "\n\n" . sprintf( __( 'A %s purchase has been made', 'edd' ), edd_get_label_plural() ) . ".\n\n";
208
  $default_email_body .= sprintf( __( '%s sold:', 'edd' ), edd_get_label_plural() ) . "\n\n";
209
  $default_email_body .= '{download_list}' . "\n\n";
@@ -212,7 +188,8 @@ function edd_get_default_sale_notification_email() {
212
  $default_email_body .= __( 'Payment Method: ', 'edd' ) . ' {payment_method}' . "\n\n";
213
  $default_email_body .= __( 'Thank you', 'edd' );
214
 
215
- $message = ( isset( $edd_options['sale_notification'] ) && !empty( $edd_options['sale_notification'] ) ) ? $edd_options['sale_notification'] : $default_email_body;
 
216
 
217
  return $message;
218
  }
@@ -229,19 +206,19 @@ function edd_get_email_names( $user_info ) {
229
  $email_names = array();
230
  $user_info = maybe_unserialize( $user_info );
231
 
232
- $email_names[ 'fullname' ] = '';
233
  if ( isset( $user_info['id'] ) && $user_info['id'] > 0 && isset( $user_info['first_name'] ) ) {
234
  $user_data = get_userdata( $user_info['id'] );
235
- $email_names[ 'name' ] = $user_info['first_name'];
236
- $email_names[ 'fullname' ] = $user_info['first_name'] . ' ' . $user_info['last_name'];
237
- $email_names[ 'username' ] = $user_data->user_login;
238
  } elseif ( isset( $user_info['first_name'] ) ) {
239
- $email_names[ 'name' ] = $user_info['first_name'];
240
- $email_names[ 'fullname' ] = $user_info['first_name'] . ' ' . $user_info['last_name'];
241
- $email_names[ 'username' ] = $user_info['first_name'];
242
  } else {
243
- $email_names[ 'name' ] = $user_info['email'];
244
- $email_names[ 'username' ] = $user_info['email'];
245
  }
246
 
247
  return $email_names;
4
  *
5
  * @package EDD
6
  * @subpackage Emails
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
22
  * @return void
23
  */
24
  function edd_email_purchase_receipt( $payment_id, $admin_notice = true ) {
 
25
 
26
  $payment_data = edd_get_payment_meta( $payment_id );
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ $from_name = edd_get_option( 'from_name', wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ) );
29
+ $from_name = apply_filters( 'edd_purchase_from_name', $from_name, $payment_id, $payment_data );
 
30
 
31
+ $from_email = edd_get_option( 'from_email', get_bloginfo( 'admin_email' ) );
32
+ $from_email = apply_filters( 'edd_purchase_from_address', $from_email, $payment_id, $payment_data );
33
 
34
+ $to_email = edd_get_payment_user_email( $payment_id );
 
35
 
36
+ $subject = edd_get_option( 'purchase_subject', __( 'Purchase Receipt', 'edd' ) );
37
+ $subject = apply_filters( 'edd_purchase_subject', wp_strip_all_tags( $subject ), $payment_id );
38
+ $subject = edd_do_email_tags( $subject, $payment_id );
39
 
40
+ $attachments = apply_filters( 'edd_receipt_attachments', array(), $payment_id, $payment_data );
41
+ $message = edd_do_email_tags( edd_get_email_body_content( $payment_id, $payment_data ), $payment_id );
42
 
43
+ $emails = EDD()->emails;
 
 
 
 
44
 
45
+ $emails->__set( 'from_name', $from_name );
46
+ $emails->__set( 'from_email', $from_email );
47
+ $emails->__set( 'heading', __( 'Purchase Receipt', 'edd' ) );
48
+
49
+
50
+ $headers = apply_filters( 'edd_receipt_headers', $emails->get_headers(), $payment_id, $payment_data );
51
+ $emails->__set( 'headers', $headers );
52
+
53
+ $emails->send( $to_email, $subject, $message, $attachments );
54
 
55
  if ( $admin_notice && ! edd_admin_notices_disabled( $payment_id ) ) {
56
  do_action( 'edd_admin_sale_notice', $payment_id, $payment_data );
61
  * Email the download link(s) and payment confirmation to the admin accounts for testing.
62
  *
63
  * @since 1.5
 
64
  * @return void
65
  */
66
  function edd_email_test_purchase_receipt() {
 
67
 
68
+ $from_name = edd_get_option( 'from_name', wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ) );
69
+ $from_name = apply_filters( 'edd_purchase_from_name', $from_name, 0, array() );
70
+
71
+ $from_email = edd_get_option( 'from_email', get_bloginfo( 'admin_email' ) );
72
+ $from_email = apply_filters( 'edd_purchase_from_address', $from_email, 0, array() );
73
+
74
+ $subject = edd_get_option( 'purchase_subject', __( 'Purchase Receipt', 'edd' ) );
75
+ $subject = apply_filters( 'edd_purchase_subject', wp_strip_all_tags( $subject ), 0 );
76
+ $subject = edd_do_email_tags( $subject, 0 );
77
 
78
+ $attachments = apply_filters( 'edd_receipt_attachments', array(), 0, array() );
79
 
80
+ $message = edd_do_email_tags( edd_get_email_body_content( 0, array() ), 0 );
 
 
81
 
82
+ $emails = EDD()->emails;
83
+ $emails->__set( 'from_name', $from_name );
84
+ $emails->__set( 'from_email', $from_email );
85
+ $emails->__set( 'heading', __( 'Purchase Receipt', 'edd' ) );
86
 
87
+ $headers = apply_filters( 'edd_receipt_headers', $emails->get_headers(), 0, array() );
88
+ $emails->__set( 'headers', $headers );
 
89
 
90
+ $emails->send( edd_get_admin_notice_emails(), $subject, $message, $attachments );
 
 
 
 
91
 
 
92
  }
93
 
94
  /**
100
  * @return void
101
  */
102
  function edd_admin_email_notice( $payment_id = 0, $payment_data = array() ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
+ $payment_id = absint( $payment_id );
 
 
105
 
106
+ if( empty( $payment_id ) ) {
107
+ return;
108
+ }
109
+
110
+ if( ! edd_get_payment_by( 'id', $payment_id ) ) {
111
+ return;
112
  }
113
 
114
+ $from_name = edd_get_option( 'from_name', wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ) );
115
+ $from_name = apply_filters( 'edd_purchase_from_name', $from_name, $payment_id, $payment_data );
116
+
117
+ $from_email = edd_get_option( 'from_email', get_bloginfo( 'admin_email' ) );
118
+ $from_email = apply_filters( 'edd_purchase_from_address', $from_email, $payment_id, $payment_data );
119
+
120
+ $subject = edd_get_option( 'sale_notification_subject', sprintf( __( 'New download purchase - Order #%1$s', 'edd' ), $payment_id ) );
121
+ $subject = apply_filters( 'edd_admin_sale_notification_subject', wp_strip_all_tags( $subject ), $payment_id );
122
+ $subject = edd_do_email_tags( $subject, $payment_id );
123
 
124
+ $headers = "From: " . stripslashes_deep( html_entity_decode( $from_name, ENT_COMPAT, 'UTF-8' ) ) . " <$from_email>\r\n";
125
+ $headers .= "Reply-To: ". $from_email . "\r\n";
126
+ //$headers .= "MIME-Version: 1.0\r\n";
127
+ $headers .= "Content-Type: text/html; charset=utf-8\r\n";
128
+ $headers = apply_filters( 'edd_admin_sale_notification_headers', $headers, $payment_id, $payment_data );
129
 
130
+ $attachments = apply_filters( 'edd_admin_sale_notification_attachments', array(), $payment_id, $payment_data );
 
 
 
 
131
 
132
+ $message = edd_get_sale_notification_body_content( $payment_id, $payment_data );
133
+
134
+ $emails = EDD()->emails;
135
+ $emails->__set( 'from_name', $from_name );
136
+ $emails->__set( 'from_email', $from_email );
137
+ $emails->__set( 'headers', $headers );
138
+ $emails->__set( 'heading', __( 'New Sale!', 'edd' ) );
139
+
140
+ $emails->send( edd_get_admin_notice_emails(), $subject, $message, $attachments );
141
 
 
142
  }
143
  add_action( 'edd_admin_sale_notice', 'edd_admin_email_notice', 10, 2 );
144
 
147
  * changed in the EDD Settings)
148
  *
149
  * @since 1.0
 
150
  * @return mixed
151
  */
152
  function edd_get_admin_notice_emails() {
153
+ $emails = edd_get_option( 'admin_notice_emails', false );
154
+ $emails = strlen( trim( $emails ) ) > 0 ? $emails : get_bloginfo( 'admin_email' );
 
155
  $emails = array_map( 'trim', explode( "\n", $emails ) );
156
 
157
  return apply_filters( 'edd_admin_notice_emails', $emails );
166
  * @return mixed
167
  */
168
  function edd_admin_notices_disabled( $payment_id = 0 ) {
169
+ $ret = edd_get_option( 'disable_admin_notices', false );
170
+ return (bool) apply_filters( 'edd_admin_notices_disabled', $ret, $payment_id );
 
171
  }
172
 
173
  /**
180
  * @return string $message
181
  */
182
  function edd_get_default_sale_notification_email() {
 
 
183
  $default_email_body = __( 'Hello', 'edd' ) . "\n\n" . sprintf( __( 'A %s purchase has been made', 'edd' ), edd_get_label_plural() ) . ".\n\n";
184
  $default_email_body .= sprintf( __( '%s sold:', 'edd' ), edd_get_label_plural() ) . "\n\n";
185
  $default_email_body .= '{download_list}' . "\n\n";
188
  $default_email_body .= __( 'Payment Method: ', 'edd' ) . ' {payment_method}' . "\n\n";
189
  $default_email_body .= __( 'Thank you', 'edd' );
190
 
191
+ $message = edd_get_option( 'sale_notification', false );
192
+ $message = ! empty( $message ) ? $message : $default_email_body;
193
 
194
  return $message;
195
  }
206
  $email_names = array();
207
  $user_info = maybe_unserialize( $user_info );
208
 
209
+ $email_names['fullname'] = '';
210
  if ( isset( $user_info['id'] ) && $user_info['id'] > 0 && isset( $user_info['first_name'] ) ) {
211
  $user_data = get_userdata( $user_info['id'] );
212
+ $email_names['name'] = $user_info['first_name'];
213
+ $email_names['fullname'] = $user_info['first_name'] . ' ' . $user_info['last_name'];
214
+ $email_names['username'] = $user_data->user_login;
215
  } elseif ( isset( $user_info['first_name'] ) ) {
216
+ $email_names['name'] = $user_info['first_name'];
217
+ $email_names['fullname'] = $user_info['first_name'] . ' ' . $user_info['last_name'];
218
+ $email_names['username'] = $user_info['first_name'];
219
  } else {
220
+ $email_names['name'] = $user_info['email'];
221
+ $email_names['username'] = $user_info['email'];
222
  }
223
 
224
  return $email_names;
includes/emails/template.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Emails
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -16,16 +16,14 @@ if ( !defined( 'ABSPATH' ) ) exit;
16
  * Gets all the email templates that have been registerd. The list is extendable
17
  * and more templates can be added.
18
  *
 
 
19
  * @since 1.0.8.2
20
  * @return array $templates All the registered email templates
21
  */
22
  function edd_get_email_templates() {
23
- $templates = array(
24
- 'default' => __( 'Default Template', 'edd' ),
25
- 'none' => __( 'No template, plain text only', 'edd' )
26
- );
27
-
28
- return apply_filters( 'edd_email_templates', $templates );
29
  }
30
 
31
  /**
@@ -48,20 +46,16 @@ function edd_email_template_tags( $message, $payment_data, $payment_id, $admin_n
48
  * Email Preview Template Tags
49
  *
50
  * @since 1.0
51
- * @global $edd_options Array of all the EDD Options
52
  * @param string $message Email message with template tags
53
  * @return string $message Fully formatted message
54
  */
55
  function edd_email_preview_template_tags( $message ) {
56
- global $edd_options;
57
-
58
  $download_list = '<ul>';
59
  $download_list .= '<li>' . __( 'Sample Product Title', 'edd' ) . '<br />';
60
- $download_list .= '<ul>';
61
- $download_list .= '<li>';
62
  $download_list .= '<a href="#">' . __( 'Sample Download File Name', 'edd' ) . '</a> - <small>' . __( 'Optional notes about this download.', 'edd' ) . '</small>';
 
63
  $download_list .= '</li>';
64
- $download_list .= '</ul></li>';
65
  $download_list .= '</ul>';
66
 
67
  $file_urls = esc_html( trailingslashit( get_site_url() ) . 'test.zip?test=key&key=123' );
@@ -80,11 +74,13 @@ function edd_email_preview_template_tags( $message ) {
80
 
81
  $payment_id = rand(1, 100);
82
 
 
 
83
  $message = str_replace( '{download_list}', $download_list, $message );
84
  $message = str_replace( '{file_urls}', $file_urls, $message );
85
- $message = str_replace( '{name}', 'John', $message );
86
- $message = str_replace( '{fullname}', 'John Doe', $message );
87
- $message = str_replace( '{username}', 'john-doe', $message );
88
  $message = str_replace( '{date}', date( get_option( 'date_format' ), current_time( 'timestamp' ) ), $message );
89
  $message = str_replace( '{subtotal}', $sub_total, $message );
90
  $message = str_replace( '{tax}', $tax, $message );
@@ -94,73 +90,60 @@ function edd_email_preview_template_tags( $message ) {
94
  $message = str_replace( '{sitename}', get_bloginfo( 'name' ), $message );
95
  $message = str_replace( '{product_notes}', $notes, $message );
96
  $message = str_replace( '{payment_id}', $payment_id, $message );
97
- $message = str_replace( '{receipt_link}', sprintf( __( '%1$sView it in your browser.%2$s', 'edd' ), '<a href="' . add_query_arg( array ( 'payment_key' => $receipt_id, 'edd_action' => 'view_receipt' ), home_url() ) . '">', '</a>' ), $message );
98
 
99
  return wpautop( apply_filters( 'edd_email_preview_template_tags', $message ) );
100
  }
101
 
102
- /**
103
- * Email Default Formatting
104
- *
105
- * @since 1.0
106
- * @param string $message Message without <p> tags
107
- * @return string $message Formatted message with <p> tags added
108
- */
109
- function edd_email_default_formatting( $message ) {
110
- return wpautop( stripslashes( $message ) );
111
- }
112
- add_filter( 'edd_purchase_receipt', 'edd_email_default_formatting' );
113
-
114
  /**
115
  * Email Template Preview
116
  *
117
  * @access private
118
- * @global $edd_options Array of all the EDD Options
119
  * @since 1.0.8.2
120
  */
121
  function edd_email_template_preview() {
122
- global $edd_options;
123
-
124
- $default_email_body = __( "Dear", "edd" ) . " {name},\n\n";
125
- $default_email_body .= __( "Thank you for your purchase. Please click on the link(s) below to download your files.", "edd" ) . "\n\n";
126
- $default_email_body .= "{download_list}\n\n";
127
- $default_email_body .= "{sitename}";
128
 
129
- $email_body = isset( $edd_options['purchase_receipt'] ) ? stripslashes( $edd_options['purchase_receipt'] ) : $default_email_body;
130
  ob_start();
131
  ?>
132
- <a href="#email-preview" id="open-email-preview" class="button-secondary" title="<?php _e( 'Purchase Receipt Preview', 'edd' ); ?> "><?php _e( 'Preview Purchase Receipt', 'edd' ); ?></a>
133
  <a href="<?php echo wp_nonce_url( add_query_arg( array( 'edd_action' => 'send_test_email' ) ), 'edd-test-email' ); ?>" title="<?php _e( 'This will send a demo purchase receipt to the emails listed below.', 'edd' ); ?>" class="button-secondary"><?php _e( 'Send Test Email', 'edd' ); ?></a>
134
-
135
- <div id="email-preview-wrap" style="display:none;">
136
- <div id="email-preview">
137
- <?php echo edd_apply_email_template( $email_body, null, null ); ?>
138
- </div>
139
- </div>
140
  <?php
141
  echo ob_get_clean();
142
  }
143
  add_action( 'edd_email_settings', 'edd_email_template_preview' );
144
 
145
  /**
146
- * Email Template Header
147
  *
148
- * @access private
149
- * @since 1.0.8.2
150
- * @return string Email template header
151
  */
152
- function edd_get_email_body_header() {
153
- ob_start();
154
- ?>
155
- <html>
156
- <head>
157
- <style type="text/css">#outlook a { padding: 0; }</style>
158
- </head>
159
- <body dir="<?php echo is_rtl() ? 'rtl' : 'ltr'; ?>">
160
- <?php
161
- do_action( 'edd_email_body_header' );
162
- return ob_get_clean();
 
 
 
 
 
 
 
 
 
 
163
  }
 
164
 
165
  /**
166
  * Email Template Body
@@ -171,16 +154,17 @@ function edd_get_email_body_header() {
171
  * @return string $email_body Body of the email
172
  */
173
  function edd_get_email_body_content( $payment_id = 0, $payment_data = array() ) {
174
- global $edd_options;
175
-
176
  $default_email_body = __( "Dear", "edd" ) . " {name},\n\n";
177
  $default_email_body .= __( "Thank you for your purchase. Please click on the link(s) below to download your files.", "edd" ) . "\n\n";
178
  $default_email_body .= "{download_list}\n\n";
179
  $default_email_body .= "{sitename}";
180
 
181
- $email = isset( $edd_options['purchase_receipt'] ) ? stripslashes( $edd_options['purchase_receipt'] ) : $default_email_body;
 
182
 
183
- $email_body = edd_do_email_tags( $email, $payment_id );
 
 
184
 
185
  return apply_filters( 'edd_purchase_receipt', $email_body, $payment_id, $payment_data );
186
  }
@@ -195,8 +179,6 @@ function edd_get_email_body_content( $payment_id = 0, $payment_data = array() )
195
  * @return string $email_body Body of the email
196
  */
197
  function edd_get_sale_notification_body_content( $payment_id = 0, $payment_data = array() ) {
198
- global $edd_options;
199
-
200
  $user_info = maybe_unserialize( $payment_data['user_info'] );
201
  $email = edd_get_payment_user_email( $payment_id );
202
 
@@ -235,7 +217,8 @@ function edd_get_sale_notification_body_content( $payment_id = 0, $payment_data
235
  $default_email_body .= __( 'Payment Method: ', 'edd' ) . " " . $gateway . "\n\n";
236
  $default_email_body .= __( 'Thank you', 'edd' );
237
 
238
- $email = isset( $edd_options['sale_notification'] ) ? stripslashes( $edd_options['sale_notification'] ) : $default_email_body;
 
239
 
240
  //$email_body = edd_email_template_tags( $email, $payment_data, $payment_id, true );
241
  $email_body = edd_do_email_tags( $email, $payment_id );
@@ -243,99 +226,6 @@ function edd_get_sale_notification_body_content( $payment_id = 0, $payment_data
243
  return apply_filters( 'edd_sale_notification', wpautop( $email_body ), $payment_id, $payment_data );
244
  }
245
 
246
- /**
247
- * Email Template Footer
248
- *
249
- * @since 1.0.8.2
250
- * @return string Email template footer
251
- */
252
- function edd_get_email_body_footer() {
253
- ob_start();
254
- do_action( 'edd_email_body_footer' );
255
- ?>
256
- </body>
257
- </html>
258
- <?php
259
- return ob_get_clean();
260
- }
261
-
262
- /**
263
- * Applies the Chosen Email Template
264
- *
265
- * @since 1.0.8.2
266
- * @param string $body The contents of the receipt email
267
- * @param int $payment_id The ID of the payment we are sending a receipt for
268
- * @param array $payment_data An array of meta information for the payment
269
- * @return string $email Formatted email with the template applied
270
- */
271
- function edd_apply_email_template( $body, $payment_id, $payment_data=array() ) {
272
- global $edd_options;
273
-
274
- $template_name = isset( $edd_options['email_template'] ) ? $edd_options['email_template'] : 'default';
275
- $template_name = apply_filters( 'edd_email_template', $template_name, $payment_id );
276
-
277
- if ( $template_name == 'none' ) {
278
- if ( is_admin() )
279
- $body = edd_email_preview_template_tags( $body );
280
-
281
- return $body; // Return the plain email with no template
282
- }
283
-
284
- ob_start();
285
-
286
- do_action( 'edd_email_template_' . $template_name );
287
-
288
- $template = ob_get_clean();
289
-
290
- if ( is_admin() )
291
- $body = edd_email_preview_template_tags( $body );
292
-
293
- $body = apply_filters( 'edd_purchase_receipt_' . $template_name, $body );
294
-
295
- $email = str_replace( '{email}', $body, $template );
296
-
297
- return $email;
298
- }
299
- add_filter( 'edd_purchase_receipt', 'edd_apply_email_template', 20, 3 );
300
-
301
- /**
302
- * Default Email Template
303
- *
304
- * @access private
305
- * @since 1.0.8.2
306
- */
307
- function edd_default_email_template() {
308
- $text_align = is_rtl() ? 'right' : 'left';
309
- echo '<div style="margin: 0; background-color: #fafafa; width: auto; padding: 30px;"><center>';
310
- echo '<div style="border: 1px solid #ddd; width: 660px; background: #f0f0f0; padding: 8px; margin: 0;">';
311
- echo '<div id="edd-email-content" style="background: #fff; border: 1px solid #ddd; padding: 15px; text-align: ' . $text_align . ' !important;">';
312
- echo '{email}'; // This tag is required in order for the contents of the email to be shown
313
- echo '</div>';
314
- echo '</div>';
315
- echo '</center></div>';
316
- }
317
- add_action( 'edd_email_template_default', 'edd_default_email_template' );
318
-
319
- /**
320
- * Default Email Template Styling Extras
321
- *
322
- * @since 1.0.9.1
323
- * @param string $email_body Email template without styling
324
- * @return string $email_body Email template with styling
325
- */
326
- function edd_default_email_styling( $email_body ) {
327
- $first_p = strpos( $email_body, '<p style="font-size: 14px;">' );
328
- if( $first_p ) {
329
- $email_body = substr_replace( $email_body, '<p style="font-size: 14px; margin-top:0;">', $first_p, 3 );
330
- }
331
- $email_body = str_replace( '<p>', '<p style="font-size: 14px; line-height: 150%">', $email_body );
332
- $email_body = str_replace( '<ul>', '<ul style="margin: 0 0 10px 0; padding: 0;">', $email_body );
333
- $email_body = str_replace( '<li>', '<li style="font-size: 14px; line-height: 150%; display:block; margin: 0 0 4px 0;">', $email_body );
334
-
335
- return $email_body;
336
- }
337
- add_filter( 'edd_purchase_receipt_default', 'edd_default_email_styling' );
338
-
339
  /**
340
  * Render Receipt in the Browser
341
  *
4
  *
5
  * @package EDD
6
  * @subpackage Emails
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
16
  * Gets all the email templates that have been registerd. The list is extendable
17
  * and more templates can be added.
18
  *
19
+ * As of 2.0, this is simply a wrapper to EDD_Email_Templates->get_templates()
20
+ *
21
  * @since 1.0.8.2
22
  * @return array $templates All the registered email templates
23
  */
24
  function edd_get_email_templates() {
25
+ $templates = new EDD_Emails;
26
+ return $templates->get_templates();
 
 
 
 
27
  }
28
 
29
  /**
46
  * Email Preview Template Tags
47
  *
48
  * @since 1.0
 
49
  * @param string $message Email message with template tags
50
  * @return string $message Fully formatted message
51
  */
52
  function edd_email_preview_template_tags( $message ) {
 
 
53
  $download_list = '<ul>';
54
  $download_list .= '<li>' . __( 'Sample Product Title', 'edd' ) . '<br />';
55
+ $download_list .= '<div>';
 
56
  $download_list .= '<a href="#">' . __( 'Sample Download File Name', 'edd' ) . '</a> - <small>' . __( 'Optional notes about this download.', 'edd' ) . '</small>';
57
+ $download_list .= '</div>';
58
  $download_list .= '</li>';
 
59
  $download_list .= '</ul>';
60
 
61
  $file_urls = esc_html( trailingslashit( get_site_url() ) . 'test.zip?test=key&key=123' );
74
 
75
  $payment_id = rand(1, 100);
76
 
77
+ $user = wp_get_current_user();
78
+
79
  $message = str_replace( '{download_list}', $download_list, $message );
80
  $message = str_replace( '{file_urls}', $file_urls, $message );
81
+ $message = str_replace( '{name}', $user->display_name, $message );
82
+ $message = str_replace( '{fullname}', $user->display_name, $message );
83
+ $message = str_replace( '{username}', $user->user_login, $message );
84
  $message = str_replace( '{date}', date( get_option( 'date_format' ), current_time( 'timestamp' ) ), $message );
85
  $message = str_replace( '{subtotal}', $sub_total, $message );
86
  $message = str_replace( '{tax}', $tax, $message );
90
  $message = str_replace( '{sitename}', get_bloginfo( 'name' ), $message );
91
  $message = str_replace( '{product_notes}', $notes, $message );
92
  $message = str_replace( '{payment_id}', $payment_id, $message );
93
+ $message = str_replace( '{receipt_link}', sprintf( __( '%1$sView it in your browser.%2$s', 'edd' ), '<a href="' . esc_url( add_query_arg( array ( 'payment_key' => $receipt_id, 'edd_action' => 'view_receipt' ), home_url() ) ) . '">', '</a>' ), $message );
94
 
95
  return wpautop( apply_filters( 'edd_email_preview_template_tags', $message ) );
96
  }
97
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  /**
99
  * Email Template Preview
100
  *
101
  * @access private
 
102
  * @since 1.0.8.2
103
  */
104
  function edd_email_template_preview() {
105
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
106
+ return;
107
+ }
 
 
 
108
 
 
109
  ob_start();
110
  ?>
111
+ <a href="<?php echo esc_url( add_query_arg( array( 'edd_action' => 'preview_email' ), home_url() ) ); ?>" class="button-secondary" target="_blank" title="<?php _e( 'Purchase Receipt Preview', 'edd' ); ?> "><?php _e( 'Preview Purchase Receipt', 'edd' ); ?></a>
112
  <a href="<?php echo wp_nonce_url( add_query_arg( array( 'edd_action' => 'send_test_email' ) ), 'edd-test-email' ); ?>" title="<?php _e( 'This will send a demo purchase receipt to the emails listed below.', 'edd' ); ?>" class="button-secondary"><?php _e( 'Send Test Email', 'edd' ); ?></a>
 
 
 
 
 
 
113
  <?php
114
  echo ob_get_clean();
115
  }
116
  add_action( 'edd_email_settings', 'edd_email_template_preview' );
117
 
118
  /**
119
+ * Displays the email preview
120
  *
121
+ * @since 2.1
122
+ * @return void
 
123
  */
124
+ function edd_display_email_template_preview() {
125
+
126
+ if( empty( $_GET['edd_action'] ) ) {
127
+ return;
128
+ }
129
+
130
+ if( 'preview_email' !== $_GET['edd_action'] ) {
131
+ return;
132
+ }
133
+
134
+ if( ! current_user_can( 'manage_shop_settings' ) ) {
135
+ return;
136
+ }
137
+
138
+
139
+ EDD()->emails->heading = __( 'Purchase Receipt', 'edd' );
140
+
141
+ echo EDD()->emails->build_email( edd_email_preview_template_tags( edd_get_email_body_content( 0, array() ) ) );
142
+
143
+ exit;
144
+
145
  }
146
+ add_action( 'template_redirect', 'edd_display_email_template_preview' );
147
 
148
  /**
149
  * Email Template Body
154
  * @return string $email_body Body of the email
155
  */
156
  function edd_get_email_body_content( $payment_id = 0, $payment_data = array() ) {
 
 
157
  $default_email_body = __( "Dear", "edd" ) . " {name},\n\n";
158
  $default_email_body .= __( "Thank you for your purchase. Please click on the link(s) below to download your files.", "edd" ) . "\n\n";
159
  $default_email_body .= "{download_list}\n\n";
160
  $default_email_body .= "{sitename}";
161
 
162
+ $email = edd_get_option( 'purchase_receipt', false );
163
+ $email = $email ? stripslashes( $email ) : $default_email_body;
164
 
165
+ $email_body = wpautop( $email );
166
+
167
+ $email_body = apply_filters( 'edd_purchase_receipt_' . EDD()->emails->get_template(), $email_body, $payment_id, $payment_data );
168
 
169
  return apply_filters( 'edd_purchase_receipt', $email_body, $payment_id, $payment_data );
170
  }
179
  * @return string $email_body Body of the email
180
  */
181
  function edd_get_sale_notification_body_content( $payment_id = 0, $payment_data = array() ) {
 
 
182
  $user_info = maybe_unserialize( $payment_data['user_info'] );
183
  $email = edd_get_payment_user_email( $payment_id );
184
 
217
  $default_email_body .= __( 'Payment Method: ', 'edd' ) . " " . $gateway . "\n\n";
218
  $default_email_body .= __( 'Thank you', 'edd' );
219
 
220
+ $email = edd_get_option( 'sale_notification', false );
221
+ $email = $email ? stripslashes( $email ) : $default_email_body;
222
 
223
  //$email_body = edd_email_template_tags( $email, $payment_data, $payment_id, true );
224
  $email_body = edd_do_email_tags( $email, $payment_id );
226
  return apply_filters( 'edd_sale_notification', wpautop( $email_body ), $payment_id, $payment_data );
227
  }
228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  /**
230
  * Render Receipt in the Browser
231
  *
includes/error-tracking.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Functions/Errors
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -126,8 +126,8 @@ function _edd_die_handler() {
126
  * @since 1.6
127
  * @return void
128
  */
129
- function edd_die() {
130
  add_filter( 'wp_die_ajax_handler', '_edd_die_handler', 10, 3 );
131
  add_filter( 'wp_die_handler', '_edd_die_handler', 10, 3 );
132
- wp_die('');
133
- }
4
  *
5
  * @package EDD
6
  * @subpackage Functions/Errors
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
126
  * @since 1.6
127
  * @return void
128
  */
129
+ function edd_die( $message = '', $title = '', $status = 400 ) {
130
  add_filter( 'wp_die_ajax_handler', '_edd_die_handler', 10, 3 );
131
  add_filter( 'wp_die_handler', '_edd_die_handler', 10, 3 );
132
+ wp_die( $message, $title, array( 'response' => $status ));
133
+ }
includes/formatting.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Functions/Formatting
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.2
10
  */
@@ -22,8 +22,6 @@ if ( ! defined( 'ABSPATH' ) ) exit;
22
  * @return string $amount Newly sanitized amount
23
  */
24
  function edd_sanitize_amount( $amount ) {
25
- global $edd_options;
26
-
27
  $is_negative = false;
28
  $thousands_sep = edd_get_option( 'thousands_separator', ',' );
29
  $decimal_sep = edd_get_option( 'decimal_separator', '.' );
@@ -60,20 +58,18 @@ function edd_sanitize_amount( $amount ) {
60
  * Returns a nicely formatted amount.
61
  *
62
  * @since 1.0
63
- *
64
  * @param string $amount Price amount to format
65
  * @param string $decimals Whether or not to use decimals. Useful when set to false for non-currency numbers.
66
- *
67
  * @return string $amount Newly formatted amount or Price Not Available
68
  */
69
  function edd_format_amount( $amount, $decimals = true ) {
70
- global $edd_options;
71
-
72
  $thousands_sep = edd_get_option( 'thousands_separator', ',' );
73
  $decimal_sep = edd_get_option( 'decimal_separator', '.' );
74
 
75
  // Format the amount
76
- if ( $decimal_sep == ',' && false !== ( $found = strpos( $amount, $decimal_sep ) ) ) {
77
  $whole = substr( $amount, 0, $sep_found );
78
  $part = substr( $amount, $sep_found + 1, ( strlen( $amount ) - 1 ) );
79
  $amount = $whole . '.' . $part;
@@ -92,7 +88,7 @@ function edd_format_amount( $amount, $decimals = true ) {
92
  if ( empty( $amount ) ) {
93
  $amount = 0;
94
  }
95
-
96
  $decimals = apply_filters( 'edd_format_amount_decimals', $decimals ? 2 : 0, $amount );
97
  $formatted = number_format( $amount, $decimals, $decimal_sep, $thousands_sep );
98
 
@@ -107,11 +103,14 @@ function edd_format_amount( $amount, $decimals = true ) {
107
  * @param string $price Price
108
  * @return array $currency Currencies displayed correctly
109
  */
110
- function edd_currency_filter( $price ) {
111
- global $edd_options;
112
 
113
- $currency = edd_get_currency();
114
- $position = isset( $edd_options['currency_position'] ) ? $edd_options['currency_position'] : 'before';
 
 
 
115
 
116
  $negative = $price < 0;
117
 
@@ -119,17 +118,13 @@ function edd_currency_filter( $price ) {
119
  $price = substr( $price, 1 ); // Remove proceeding "-" -
120
  }
121
 
 
 
122
  if ( $position == 'before' ):
123
  switch ( $currency ):
124
  case "GBP" :
125
- $formatted = '&pound;' . $price;
126
- break;
127
  case "BRL" :
128
- $formatted = 'R&#36;' . $price;
129
- break;
130
  case "EUR" :
131
- $formatted = '&euro;' . $price;
132
- break;
133
  case "USD" :
134
  case "AUD" :
135
  case "CAD" :
@@ -137,40 +132,30 @@ function edd_currency_filter( $price ) {
137
  case "MXN" :
138
  case "NZD" :
139
  case "SGD" :
140
- $formatted = '&#36;' . $price;
141
- break;
142
  case "JPY" :
143
- $formatted = '&yen;' . $price;
144
  break;
145
  default :
146
- $formatted = $currency . ' ' . $price;
147
  break;
148
  endswitch;
149
  $formatted = apply_filters( 'edd_' . strtolower( $currency ) . '_currency_filter_before', $formatted, $currency, $price );
150
  else :
151
  switch ( $currency ) :
152
  case "GBP" :
153
- $formatted = $price . '&pound;';
154
- break;
155
  case "BRL" :
156
- $formatted = $price . 'R&#36;';
157
- break;
158
  case "EUR" :
159
- $formatted = $price . '&euro;';
160
- break;
161
  case "USD" :
162
  case "AUD" :
163
  case "CAD" :
164
  case "HKD" :
165
  case "MXN" :
166
  case "SGD" :
167
- $formatted = $price . '&#36;';
168
- break;
169
  case "JPY" :
170
- $formatted = $price . '&yen;';
171
  break;
172
  default :
173
- $formatted = $price . ' ' . $currency;
174
  break;
175
  endswitch;
176
  $formatted = apply_filters( 'edd_' . strtolower( $currency ) . '_currency_filter_after', $formatted, $currency, $price );
@@ -192,7 +177,6 @@ function edd_currency_filter( $price ) {
192
  * @return int $decimals
193
  */
194
  function edd_currency_decimal_filter( $decimals = 2 ) {
195
- global $edd_options;
196
 
197
  $currency = edd_get_currency();
198
 
@@ -205,7 +189,7 @@ function edd_currency_decimal_filter( $decimals = 2 ) {
205
  break;
206
  }
207
 
208
- return $decimals;
209
  }
210
  add_filter( 'edd_sanitize_amount_decimals', 'edd_currency_decimal_filter' );
211
  add_filter( 'edd_format_amount_decimals', 'edd_currency_decimal_filter' );
4
  *
5
  * @package EDD
6
  * @subpackage Functions/Formatting
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.2
10
  */
22
  * @return string $amount Newly sanitized amount
23
  */
24
  function edd_sanitize_amount( $amount ) {
 
 
25
  $is_negative = false;
26
  $thousands_sep = edd_get_option( 'thousands_separator', ',' );
27
  $decimal_sep = edd_get_option( 'decimal_separator', '.' );
58
  * Returns a nicely formatted amount.
59
  *
60
  * @since 1.0
61
+ *
62
  * @param string $amount Price amount to format
63
  * @param string $decimals Whether or not to use decimals. Useful when set to false for non-currency numbers.
64
+ *
65
  * @return string $amount Newly formatted amount or Price Not Available
66
  */
67
  function edd_format_amount( $amount, $decimals = true ) {
 
 
68
  $thousands_sep = edd_get_option( 'thousands_separator', ',' );
69
  $decimal_sep = edd_get_option( 'decimal_separator', '.' );
70
 
71
  // Format the amount
72
+ if ( $decimal_sep == ',' && false !== ( $sep_found = strpos( $amount, $decimal_sep ) ) ) {
73
  $whole = substr( $amount, 0, $sep_found );
74
  $part = substr( $amount, $sep_found + 1, ( strlen( $amount ) - 1 ) );
75
  $amount = $whole . '.' . $part;
88
  if ( empty( $amount ) ) {
89
  $amount = 0;
90
  }
91
+
92
  $decimals = apply_filters( 'edd_format_amount_decimals', $decimals ? 2 : 0, $amount );
93
  $formatted = number_format( $amount, $decimals, $decimal_sep, $thousands_sep );
94
 
103
  * @param string $price Price
104
  * @return array $currency Currencies displayed correctly
105
  */
106
+ function edd_currency_filter( $price = '', $currency = '' ) {
107
+ if( empty( $currency ) ) {
108
 
109
+ $currency = edd_get_currency();
110
+
111
+ }
112
+
113
+ $position = edd_get_option( 'currency_position', 'before' );
114
 
115
  $negative = $price < 0;
116
 
118
  $price = substr( $price, 1 ); // Remove proceeding "-" -
119
  }
120
 
121
+ $symbol = edd_currency_symbol( $currency );
122
+
123
  if ( $position == 'before' ):
124
  switch ( $currency ):
125
  case "GBP" :
 
 
126
  case "BRL" :
 
 
127
  case "EUR" :
 
 
128
  case "USD" :
129
  case "AUD" :
130
  case "CAD" :
132
  case "MXN" :
133
  case "NZD" :
134
  case "SGD" :
 
 
135
  case "JPY" :
136
+ $formatted = $symbol . $price;
137
  break;
138
  default :
139
+ $formatted = $currency . ' ' . $price;
140
  break;
141
  endswitch;
142
  $formatted = apply_filters( 'edd_' . strtolower( $currency ) . '_currency_filter_before', $formatted, $currency, $price );
143
  else :
144
  switch ( $currency ) :
145
  case "GBP" :
 
 
146
  case "BRL" :
 
 
147
  case "EUR" :
 
 
148
  case "USD" :
149
  case "AUD" :
150
  case "CAD" :
151
  case "HKD" :
152
  case "MXN" :
153
  case "SGD" :
 
 
154
  case "JPY" :
155
+ $formatted = $price . $symbol;
156
  break;
157
  default :
158
+ $formatted = $price . ' ' . $currency;
159
  break;
160
  endswitch;
161
  $formatted = apply_filters( 'edd_' . strtolower( $currency ) . '_currency_filter_after', $formatted, $currency, $price );
177
  * @return int $decimals
178
  */
179
  function edd_currency_decimal_filter( $decimals = 2 ) {
 
180
 
181
  $currency = edd_get_currency();
182
 
189
  break;
190
  }
191
 
192
+ return apply_filters( 'edd_currency_decimal_count', $decimals, $currency );
193
  }
194
  add_filter( 'edd_sanitize_amount_decimals', 'edd_currency_decimal_filter' );
195
  add_filter( 'edd_format_amount_decimals', 'edd_currency_decimal_filter' );
includes/gateways/actions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Gateways
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.7
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Gateways
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.7
10
  */
includes/gateways/functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Gateways
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -42,10 +42,8 @@ function edd_get_payment_gateways() {
42
  * @return array $gateway_list All the available gateways
43
  */
44
  function edd_get_enabled_payment_gateways() {
45
- global $edd_options;
46
-
47
  $gateways = edd_get_payment_gateways();
48
- $enabled = isset( $edd_options['gateways'] ) ? $edd_options['gateways'] : false;
49
 
50
  $gateway_list = array();
51
 
@@ -76,12 +74,12 @@ function edd_is_gateway_active( $gateway ) {
76
  * Gets the default payment gateway selected from the EDD Settings
77
  *
78
  * @since 1.5
79
- * @global $edd_options Array of all the EDD Options
80
  * @return string Gateway ID
81
  */
82
  function edd_get_default_gateway() {
83
- global $edd_options;
84
- $default = isset( $edd_options['default_gateway'] ) && edd_is_gateway_active( $edd_options['default_gateway'] ) ? $edd_options['default_gateway'] : 'paypal';
 
85
  return apply_filters( 'edd_default_gateway', $default );
86
  }
87
 
@@ -160,7 +158,7 @@ function edd_shop_supports_buy_now() {
160
  $gateways = edd_get_enabled_payment_gateways();
161
  $ret = false;
162
 
163
- if( $gateways ) {
164
  foreach( $gateways as $gateway_id => $gateway ) {
165
  if( edd_gateway_supports_buy_now( $gateway_id ) ) {
166
  $ret = true;
@@ -188,7 +186,7 @@ function edd_build_straight_to_gateway_data( $download_id = 0, $options = array(
188
  if( empty( $options ) || ! edd_has_variable_prices( $download_id ) ) {
189
  $price = edd_get_download_price( $download_id );
190
  } else {
191
-
192
  if( is_array( $options['price_id'] ) ) {
193
  $price_id = $options['price_id'][0];
194
  } else {
@@ -199,7 +197,7 @@ function edd_build_straight_to_gateway_data( $download_id = 0, $options = array(
199
 
200
  // Make sure a valid price ID was supplied
201
  if( ! isset( $prices[ $price_id ] ) ) {
202
- wp_die( __( 'The requested price ID does not exist.', 'edd' ), __( 'Error', 'edd' ) );
203
  }
204
 
205
  $price_options = array(
@@ -247,7 +245,7 @@ function edd_build_straight_to_gateway_data( $download_id = 0, $options = array(
247
  'email' => is_user_logged_in() ? $current_user->user_email : '',
248
  'first_name' => is_user_logged_in() ? $current_user->user_firstname : '',
249
  'last_name' => is_user_logged_in() ? $current_user->user_lastname : '',
250
- 'discount' => '',
251
  'address' => array()
252
  );
253
 
@@ -266,6 +264,7 @@ function edd_build_straight_to_gateway_data( $download_id = 0, $options = array(
266
  'post_data' => array(),
267
  'cart_details' => $cart_details,
268
  'gateway' => 'paypal',
 
269
  'card_info' => array()
270
  );
271
 
@@ -282,6 +281,9 @@ function edd_build_straight_to_gateway_data( $download_id = 0, $options = array(
282
  * @return void
283
  */
284
  function edd_send_to_gateway( $gateway, $payment_data ) {
 
 
 
285
  // $gateway must match the ID used when registering the gateway
286
  do_action( 'edd_gateway_' . $gateway, $payment_data );
287
  }
@@ -301,7 +303,7 @@ function edd_show_gateways() {
301
 
302
  if ( count( $gateways ) > 1 && ! isset( $_GET['payment-mode'] ) ) {
303
  $show_gateways = true;
304
- if ( edd_get_cart_subtotal() <= 0 ) {
305
  $show_gateways = false;
306
  }
307
  }
@@ -383,4 +385,4 @@ function edd_count_sales_by_gateway( $gateway_id = 'paypal', $status = 'publish'
383
  if( $payments )
384
  $ret = $payments->post_count;
385
  return $ret;
386
- }
4
  *
5
  * @package EDD
6
  * @subpackage Gateways
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
42
  * @return array $gateway_list All the available gateways
43
  */
44
  function edd_get_enabled_payment_gateways() {
 
 
45
  $gateways = edd_get_payment_gateways();
46
+ $enabled = edd_get_option( 'gateways', false );
47
 
48
  $gateway_list = array();
49
 
74
  * Gets the default payment gateway selected from the EDD Settings
75
  *
76
  * @since 1.5
 
77
  * @return string Gateway ID
78
  */
79
  function edd_get_default_gateway() {
80
+ $gateway = edd_get_option( 'default_gateway', 'paypal' );
81
+ $default = edd_is_gateway_active( $gateway ) ? $gateway : 'paypal';
82
+
83
  return apply_filters( 'edd_default_gateway', $default );
84
  }
85
 
158
  $gateways = edd_get_enabled_payment_gateways();
159
  $ret = false;
160
 
161
+ if( ! edd_use_taxes() && $gateways ) {
162
  foreach( $gateways as $gateway_id => $gateway ) {
163
  if( edd_gateway_supports_buy_now( $gateway_id ) ) {
164
  $ret = true;
186
  if( empty( $options ) || ! edd_has_variable_prices( $download_id ) ) {
187
  $price = edd_get_download_price( $download_id );
188
  } else {
189
+
190
  if( is_array( $options['price_id'] ) ) {
191
  $price_id = $options['price_id'][0];
192
  } else {
197
 
198
  // Make sure a valid price ID was supplied
199
  if( ! isset( $prices[ $price_id ] ) ) {
200
+ wp_die( __( 'The requested price ID does not exist.', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 404 ) );
201
  }
202
 
203
  $price_options = array(
245
  'email' => is_user_logged_in() ? $current_user->user_email : '',
246
  'first_name' => is_user_logged_in() ? $current_user->user_firstname : '',
247
  'last_name' => is_user_logged_in() ? $current_user->user_lastname : '',
248
+ 'discount' => 'none',
249
  'address' => array()
250
  );
251
 
264
  'post_data' => array(),
265
  'cart_details' => $cart_details,
266
  'gateway' => 'paypal',
267
+ 'buy_now' => true,
268
  'card_info' => array()
269
  );
270
 
281
  * @return void
282
  */
283
  function edd_send_to_gateway( $gateway, $payment_data ) {
284
+
285
+ $payment_data['gateway_nonce'] = wp_create_nonce( 'edd-gateway' );
286
+
287
  // $gateway must match the ID used when registering the gateway
288
  do_action( 'edd_gateway_' . $gateway, $payment_data );
289
  }
303
 
304
  if ( count( $gateways ) > 1 && ! isset( $_GET['payment-mode'] ) ) {
305
  $show_gateways = true;
306
+ if ( edd_get_cart_total() <= 0 ) {
307
  $show_gateways = false;
308
  }
309
  }
385
  if( $payments )
386
  $ret = $payments->post_count;
387
  return $ret;
388
+ }
includes/gateways/manual.php CHANGED
@@ -4,11 +4,14 @@
4
  *
5
  * @package EDD
6
  * @subpackage Gateways
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
11
 
 
 
 
12
  /**
13
  * Manual Gateway does not need a CC form, so remove it.
14
  *
@@ -22,12 +25,13 @@ add_action( 'edd_manual_cc_form', '__return_false' );
22
  * the transaction in the Purchase History
23
  *
24
  * @since 1.0
25
- * @global $edd_options Array of all the EDD Options
26
  * @param array $purchase_data Purchase Data
27
  * @return void
28
  */
29
  function edd_manual_payment( $purchase_data ) {
30
- global $edd_options;
 
 
31
 
32
  /*
33
  * Purchase data comes in like this
4
  *
5
  * @package EDD
6
  * @subpackage Gateways
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
+
15
  /**
16
  * Manual Gateway does not need a CC form, so remove it.
17
  *
25
  * the transaction in the Purchase History
26
  *
27
  * @since 1.0
 
28
  * @param array $purchase_data Purchase Data
29
  * @return void
30
  */
31
  function edd_manual_payment( $purchase_data ) {
32
+ if( ! wp_verify_nonce( $purchase_data['gateway_nonce'], 'edd-gateway' ) ) {
33
+ wp_die( __( 'Nonce verification has failed', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
34
+ }
35
 
36
  /*
37
  * Purchase data comes in like this
includes/gateways/paypal-standard.php CHANGED
@@ -4,11 +4,14 @@
4
  *
5
  * @package EDD
6
  * @subpackage Gateways
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
11
 
 
 
 
12
  /**
13
  * PayPal Remove CC Form
14
  *
@@ -23,12 +26,13 @@ add_action( 'edd_paypal_cc_form', '__return_false' );
23
  * Process PayPal Purchase
24
  *
25
  * @since 1.0
26
- * @global $edd_options Array of all the EDD Options
27
  * @param array $purchase_data Purchase Data
28
  * @return void
29
  */
30
  function edd_process_paypal_purchase( $purchase_data ) {
31
- global $edd_options;
 
 
32
 
33
  // Collect payment data
34
  $payment_data = array(
@@ -41,7 +45,7 @@ function edd_process_paypal_purchase( $purchase_data ) {
41
  'user_info' => $purchase_data['user_info'],
42
  'cart_details' => $purchase_data['cart_details'],
43
  'gateway' => 'paypal',
44
- 'status' => 'pending'
45
  );
46
 
47
  // Record the pending payment
@@ -61,17 +65,16 @@ function edd_process_paypal_purchase( $purchase_data ) {
61
  $return_url = add_query_arg( array(
62
  'payment-confirmation' => 'paypal',
63
  'payment-id' => $payment
64
-
65
- ), get_permalink( $edd_options['success_page'] ) );
66
 
67
  // Get the PayPal redirect uri
68
  $paypal_redirect = trailingslashit( edd_get_paypal_redirect() ) . '?';
69
 
70
  // Setup PayPal arguments
71
  $paypal_args = array(
72
- 'business' => $edd_options['paypal_email'],
73
  'email' => $purchase_data['user_email'],
74
- 'invoice' => $purchase_data['purchase_key'],
75
  'no_shipping' => '1',
76
  'shipping' => '0',
77
  'no_note' => '1',
@@ -83,7 +86,8 @@ function edd_process_paypal_purchase( $purchase_data ) {
83
  'cancel_return' => edd_get_failed_transaction_uri( '?payment-id=' . $payment ),
84
  'notify_url' => $listener_url,
85
  'page_style' => edd_get_paypal_page_style(),
86
- 'cbt' => get_bloginfo( 'name' ),
 
87
  );
88
 
89
  if ( ! empty( $purchase_data['user_info']['address'] ) ) {
@@ -104,17 +108,25 @@ function edd_process_paypal_purchase( $purchase_data ) {
104
  $i = 1;
105
  foreach ( $purchase_data['cart_details'] as $item ) {
106
 
 
 
 
 
 
 
107
  if ( edd_has_variable_prices( $item['id'] ) && edd_get_cart_item_price_id( $item ) !== false ) {
108
 
109
  $item['name'] .= ' - ' . edd_get_cart_item_price_name( $item );
110
  }
111
 
112
- $paypal_args['item_name_' . $i ] = stripslashes_deep( html_entity_decode( wp_strip_all_tags( $item['name'] ), ENT_COMPAT, 'UTF-8' ) );
 
 
 
113
  if ( edd_use_skus() ) {
114
  $paypal_args['item_number_' . $i ] = edd_get_download_sku( $item['id'] );
115
  }
116
- $paypal_args['quantity_' . $i ] = $item['quantity'];
117
- $paypal_args['amount_' . $i ] = $item['item_price'] - edd_sanitize_amount( $item['discount'] / $item['quantity'] );
118
  $i++;
119
 
120
  }
@@ -129,7 +141,7 @@ function edd_process_paypal_purchase( $purchase_data ) {
129
  // this is a positive fee
130
  $paypal_args['item_name_' . $i ] = stripslashes_deep( html_entity_decode( wp_strip_all_tags( $fee['label'] ), ENT_COMPAT, 'UTF-8' ) );
131
  $paypal_args['quantity_' . $i ] = '1';
132
- $paypal_args['amount_' . $i ] = $fee['amount'];
133
  $i++;
134
  } else {
135
  // This is a negative fee (discount)
@@ -139,12 +151,14 @@ function edd_process_paypal_purchase( $purchase_data ) {
139
  }
140
 
141
  if ( $discounted_amount > '0' ) {
142
- $paypal_args['discount_amount_cart'] = $discounted_amount;
143
  }
144
 
145
  // Add taxes to the cart
146
  if ( edd_use_taxes() ) {
147
- $paypal_args['tax_cart'] = $purchase_data['tax'];
 
 
148
  }
149
 
150
  $paypal_args = apply_filters( 'edd_paypal_redirect_args', $paypal_args, $purchase_data );
@@ -170,12 +184,9 @@ add_action( 'edd_gateway_paypal', 'edd_process_paypal_purchase' );
170
  * Listens for a PayPal IPN requests and then sends to the processing function
171
  *
172
  * @since 1.0
173
- * @global $edd_options Array of all the EDD Options
174
  * @return void
175
  */
176
  function edd_listen_for_paypal_ipn() {
177
- global $edd_options;
178
-
179
  // Regular PayPal IPN
180
  if ( isset( $_GET['edd-listener'] ) && $_GET['edd-listener'] == 'IPN' ) {
181
  do_action( 'edd_verify_paypal_ipn' );
@@ -187,19 +198,16 @@ add_action( 'init', 'edd_listen_for_paypal_ipn' );
187
  * Process PayPal IPN
188
  *
189
  * @since 1.0
190
- * @global $edd_options Array of all the EDD Options
191
  * @return void
192
  */
193
  function edd_process_paypal_ipn() {
194
- global $edd_options;
195
-
196
  // Check the request method is POST
197
  if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] != 'POST' ) {
198
  return;
199
  }
200
 
201
- // Set initial post data to false
202
- $post_data = false;
203
 
204
  // Fallback just in case post_max_size is lower than needed
205
  if ( ini_get( 'allow_url_fopen' ) ) {
@@ -224,7 +232,7 @@ function edd_process_paypal_ipn() {
224
  // Nothing to do
225
  return;
226
  } else {
227
- // Loop trough each POST
228
  foreach ( $_POST as $key => $value ) {
229
  // Encode the value and append the data
230
  $encoded_data .= $arg_separator."$key=" . urlencode( $value );
@@ -246,7 +254,7 @@ function edd_process_paypal_ipn() {
246
  'method' => 'POST',
247
  'timeout' => 45,
248
  'redirection' => 5,
249
- 'httpversion' => '1.0',
250
  'blocking' => true,
251
  'headers' => array(
252
  'host' => 'www.paypal.com',
@@ -267,7 +275,7 @@ function edd_process_paypal_ipn() {
267
  return; // Something went wrong
268
  }
269
 
270
- if ( $api_response['body'] !== 'VERIFIED' && !isset( $edd_options['disable_paypal_verification'] ) ) {
271
  edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid IPN verification response. IPN data: %s', 'edd' ), json_encode( $api_response ) ) );
272
  return; // Response not okay
273
  }
@@ -278,12 +286,21 @@ function edd_process_paypal_ipn() {
278
  if ( ! is_array( $encoded_data_array ) && !empty( $encoded_data_array ) )
279
  return;
280
 
 
 
 
 
 
 
 
 
 
281
  if ( has_action( 'edd_paypal_' . $encoded_data_array['txn_type'] ) ) {
282
  // Allow PayPal IPN types to be processed separately
283
- do_action( 'edd_paypal_' . $encoded_data_array['txn_type'], $encoded_data_array );
284
  } else {
285
  // Fallback to web accept just in case the txn_type isn't present
286
- do_action( 'edd_paypal_web_accept', $encoded_data_array );
287
  }
288
  exit;
289
  }
@@ -293,31 +310,33 @@ add_action( 'edd_verify_paypal_ipn', 'edd_process_paypal_ipn' );
293
  * Process web accept (one time) payment IPNs
294
  *
295
  * @since 1.3.4
296
- * @global $edd_options Array of all the EDD Options
297
  * @param array $data IPN Data
298
  * @return void
299
  */
300
- function edd_process_paypal_web_accept_and_cart( $data ) {
301
- global $edd_options;
 
 
302
 
303
- if ( $data['txn_type'] != 'web_accept' && $data['txn_type'] != 'cart' )
304
  return;
 
305
 
306
  // Collect payment details
307
- $payment_id = $data['custom'];
308
  $purchase_key = isset( $data['invoice'] ) ? $data['invoice'] : $data['item_number'];
309
  $paypal_amount = $data['mc_gross'];
310
  $payment_status = strtolower( $data['payment_status'] );
311
  $currency_code = strtolower( $data['mc_currency'] );
312
  $business_email = isset( $data['business'] ) && is_email( $data['business'] ) ? trim( $data['business'] ) : trim( $data['receiver_email'] );
 
 
313
 
314
  if ( edd_get_payment_gateway( $payment_id ) != 'paypal' ) {
315
  return; // this isn't a PayPal standard IPN
316
  }
317
 
318
  // Verify payment recipient
319
- if ( strcasecmp( $business_email, trim( $edd_options['paypal_email'] ) ) != 0 ) {
320
-
321
  edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid business email in IPN response. IPN data: %s', 'edd' ), json_encode( $data ) ), $payment_id );
322
  edd_update_payment_status( $payment_id, 'failed' );
323
  edd_insert_payment_note( $payment_id, __( 'Payment failed due to invalid PayPal business email.', 'edd' ) );
@@ -325,7 +344,7 @@ function edd_process_paypal_web_accept_and_cart( $data ) {
325
  }
326
 
327
  // Verify payment currency
328
- if ( $currency_code != strtolower( edd_get_currency() ) ) {
329
 
330
  edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid currency in IPN response. IPN data: %s', 'edd' ), json_encode( $data ) ), $payment_id );
331
  edd_update_payment_status( $payment_id, 'failed' );
@@ -338,34 +357,33 @@ function edd_process_paypal_web_accept_and_cart( $data ) {
338
  // This runs when a Buy Now purchase was made. It bypasses checkout so no personal info is collected until PayPal
339
 
340
  // No email associated with purchase, so store from PayPal
341
- update_post_meta( $payment_id, '_edd_payment_user_email', $data['payer_email'] );
342
 
343
  // Setup and store the customers's details
344
  $address = array();
345
- $address['line1'] = ! empty( $data['address_street'] ) ? $data['address_street'] : false;
346
- $address['city'] = ! empty( $data['address_city'] ) ? $data['address_city'] : false;
347
- $address['state'] = ! empty( $data['address_state'] ) ? $data['address_state'] : false;
348
- $address['country'] = ! empty( $data['address_country_code'] ) ? $data['address_country_code'] : false;
349
- $address['zip'] = ! empty( $data['address_zip'] ) ? $data['address_zip'] : false;
350
 
351
  $user_info = array(
352
  'id' => '-1',
353
- 'email' => $data['payer_email'],
354
- 'first_name' => $data['first_name'],
355
- 'last_name' => $data['last_name'],
356
  'discount' => '',
357
  'address' => $address
358
  );
359
 
360
- $payment_meta = get_post_meta( $payment_id, '_edd_payment_meta', true );
361
  $payment_meta['user_info'] = $user_info;
362
- update_post_meta( $payment_id, '_edd_payment_meta', $payment_meta );
363
  }
364
 
365
- if ( $payment_status == 'refunded' ) {
366
 
367
  // Process a refund
368
- edd_process_paypal_refund( $data );
369
 
370
  } else {
371
 
@@ -391,34 +409,119 @@ function edd_process_paypal_web_accept_and_cart( $data ) {
391
  return;
392
  }
393
 
394
- if ( $payment_status == 'completed' || edd_is_test_mode() ) {
 
395
  edd_insert_payment_note( $payment_id, sprintf( __( 'PayPal Transaction ID: %s', 'edd' ) , $data['txn_id'] ) );
 
396
  edd_update_payment_status( $payment_id, 'publish' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
  }
398
  }
399
  }
400
- add_action( 'edd_paypal_web_accept', 'edd_process_paypal_web_accept_and_cart' );
401
 
402
  /**
403
  * Process PayPal IPN Refunds
404
  *
405
  * @since 1.3.4
406
- * @global $edd_options Array of all the EDD Options
407
  * @param array $data IPN Data
408
  * @return void
409
  */
410
- function edd_process_paypal_refund( $data ) {
411
- global $edd_options;
412
 
413
  // Collect payment details
414
- $payment_id = intval( $data['custom'] );
 
 
 
415
 
416
  if ( get_post_status( $payment_id ) == 'refunded' ) {
417
  return; // Only refund payments once
418
  }
419
 
420
- edd_insert_payment_note( $payment_id, sprintf( __( 'PayPal Payment #%s Refunded', 'edd' ) , $data['parent_txn_id'] ) );
421
- edd_insert_payment_note( $payment_id, sprintf( __( 'PayPal Refund Transaction ID: %s', 'edd' ) , $data['txn_id'] ) );
 
 
 
 
 
 
 
 
 
 
422
  edd_update_payment_status( $payment_id, 'refunded' );
423
  }
424
 
@@ -426,13 +529,10 @@ function edd_process_paypal_refund( $data ) {
426
  * Get PayPal Redirect
427
  *
428
  * @since 1.0.8.2
429
- * @global $edd_options Array of all the EDD Options
430
  * @param bool $ssl_check Is SSL?
431
  * @return string
432
  */
433
  function edd_get_paypal_redirect( $ssl_check = false ) {
434
- global $edd_options;
435
-
436
  if ( is_ssl() || ! $ssl_check ) {
437
  $protocal = 'https://';
438
  } else {
@@ -455,17 +555,10 @@ function edd_get_paypal_redirect( $ssl_check = false ) {
455
  * Set the Page Style for PayPal Purchase page
456
  *
457
  * @since 1.4.1
458
- * @global $edd_options Array of all the EDD Options
459
  * @return string
460
  */
461
  function edd_get_paypal_page_style() {
462
- global $edd_options;
463
-
464
- $page_style = 'PayPal';
465
-
466
- if ( isset( $edd_options['paypal_page_style'] ) )
467
- $page_style = trim( $edd_options['paypal_page_style'] );
468
-
469
  return apply_filters( 'edd_paypal_page_style', $page_style );
470
  }
471
 
@@ -507,3 +600,44 @@ function edd_paypal_success_page_content( $content ) {
507
 
508
  }
509
  add_filter( 'edd_payment_confirm_paypal', 'edd_paypal_success_page_content' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  *
5
  * @package EDD
6
  * @subpackage Gateways
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
+
15
  /**
16
  * PayPal Remove CC Form
17
  *
26
  * Process PayPal Purchase
27
  *
28
  * @since 1.0
 
29
  * @param array $purchase_data Purchase Data
30
  * @return void
31
  */
32
  function edd_process_paypal_purchase( $purchase_data ) {
33
+ if( ! wp_verify_nonce( $purchase_data['gateway_nonce'], 'edd-gateway' ) ) {
34
+ wp_die( __( 'Nonce verification has failed', 'edd' ), __( 'Error', 'edd' ), array( 'response' => 403 ) );
35
+ }
36
 
37
  // Collect payment data
38
  $payment_data = array(
45
  'user_info' => $purchase_data['user_info'],
46
  'cart_details' => $purchase_data['cart_details'],
47
  'gateway' => 'paypal',
48
+ 'status' => ! empty( $purchase_data['buy_now'] ) ? 'private' : 'pending'
49
  );
50
 
51
  // Record the pending payment
65
  $return_url = add_query_arg( array(
66
  'payment-confirmation' => 'paypal',
67
  'payment-id' => $payment
68
+ ), get_permalink( edd_get_option( 'success_page', false ) ) );
 
69
 
70
  // Get the PayPal redirect uri
71
  $paypal_redirect = trailingslashit( edd_get_paypal_redirect() ) . '?';
72
 
73
  // Setup PayPal arguments
74
  $paypal_args = array(
75
+ 'business' => edd_get_option( 'paypal_email', false ),
76
  'email' => $purchase_data['user_email'],
77
+ 'invoice' => $purchase_data['purchase_key'],
78
  'no_shipping' => '1',
79
  'shipping' => '0',
80
  'no_note' => '1',
86
  'cancel_return' => edd_get_failed_transaction_uri( '?payment-id=' . $payment ),
87
  'notify_url' => $listener_url,
88
  'page_style' => edd_get_paypal_page_style(),
89
+ 'cbt' => get_bloginfo( 'name' ),
90
+ 'bn' => 'EasyDigitalDownloads_SP'
91
  );
92
 
93
  if ( ! empty( $purchase_data['user_info']['address'] ) ) {
108
  $i = 1;
109
  foreach ( $purchase_data['cart_details'] as $item ) {
110
 
111
+ $item_amount = round( ( $item['subtotal'] / $item['quantity'] ) - ( $item['discount'] / $item['quantity'] ), 2 );
112
+
113
+ if( $item_amount <= 0 ) {
114
+ $item_amount = 0;
115
+ }
116
+
117
  if ( edd_has_variable_prices( $item['id'] ) && edd_get_cart_item_price_id( $item ) !== false ) {
118
 
119
  $item['name'] .= ' - ' . edd_get_cart_item_price_name( $item );
120
  }
121
 
122
+ $paypal_args['item_name_' . $i ] = stripslashes_deep( html_entity_decode( wp_strip_all_tags( $item['name'] ), ENT_COMPAT, 'UTF-8' ) );
123
+ $paypal_args['quantity_' . $i ] = $item['quantity'];
124
+ $paypal_args['amount_' . $i ] = $item_amount;
125
+
126
  if ( edd_use_skus() ) {
127
  $paypal_args['item_number_' . $i ] = edd_get_download_sku( $item['id'] );
128
  }
129
+
 
130
  $i++;
131
 
132
  }
141
  // this is a positive fee
142
  $paypal_args['item_name_' . $i ] = stripslashes_deep( html_entity_decode( wp_strip_all_tags( $fee['label'] ), ENT_COMPAT, 'UTF-8' ) );
143
  $paypal_args['quantity_' . $i ] = '1';
144
+ $paypal_args['amount_' . $i ] = edd_sanitize_amount( $fee['amount'] );
145
  $i++;
146
  } else {
147
  // This is a negative fee (discount)
151
  }
152
 
153
  if ( $discounted_amount > '0' ) {
154
+ $paypal_args['discount_amount_cart'] = edd_sanitize_amount( $discounted_amount );
155
  }
156
 
157
  // Add taxes to the cart
158
  if ( edd_use_taxes() ) {
159
+
160
+ $paypal_args['tax_cart'] = edd_sanitize_amount( $purchase_data['tax'] );
161
+
162
  }
163
 
164
  $paypal_args = apply_filters( 'edd_paypal_redirect_args', $paypal_args, $purchase_data );
184
  * Listens for a PayPal IPN requests and then sends to the processing function
185
  *
186
  * @since 1.0
 
187
  * @return void
188
  */
189
  function edd_listen_for_paypal_ipn() {
 
 
190
  // Regular PayPal IPN
191
  if ( isset( $_GET['edd-listener'] ) && $_GET['edd-listener'] == 'IPN' ) {
192
  do_action( 'edd_verify_paypal_ipn' );
198
  * Process PayPal IPN
199
  *
200
  * @since 1.0
 
201
  * @return void
202
  */
203
  function edd_process_paypal_ipn() {
 
 
204
  // Check the request method is POST
205
  if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] != 'POST' ) {
206
  return;
207
  }
208
 
209
+ // Set initial post data to empty string
210
+ $post_data = '';
211
 
212
  // Fallback just in case post_max_size is lower than needed
213
  if ( ini_get( 'allow_url_fopen' ) ) {
232
  // Nothing to do
233
  return;
234
  } else {
235
+ // Loop through each POST
236
  foreach ( $_POST as $key => $value ) {
237
  // Encode the value and append the data
238
  $encoded_data .= $arg_separator."$key=" . urlencode( $value );
254
  'method' => 'POST',
255
  'timeout' => 45,
256
  'redirection' => 5,
257
+ 'httpversion' => '1.1',
258
  'blocking' => true,
259
  'headers' => array(
260
  'host' => 'www.paypal.com',
275
  return; // Something went wrong
276
  }
277
 
278
+ if ( $api_response['body'] !== 'VERIFIED' && edd_get_option( 'disable_paypal_verification', false ) ) {
279
  edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid IPN verification response. IPN data: %s', 'edd' ), json_encode( $api_response ) ) );
280
  return; // Response not okay
281
  }
286
  if ( ! is_array( $encoded_data_array ) && !empty( $encoded_data_array ) )
287
  return;
288
 
289
+ $defaults = array(
290
+ 'txn_type' => '',
291
+ 'payment_status' => ''
292
+ );
293
+
294
+ $encoded_data_array = wp_parse_args( $encoded_data_array, $defaults );
295
+
296
+ $payment_id = isset( $encoded_data_array['custom'] ) ? absint( $encoded_data_array['custom'] ) : 0;
297
+
298
  if ( has_action( 'edd_paypal_' . $encoded_data_array['txn_type'] ) ) {
299
  // Allow PayPal IPN types to be processed separately
300
+ do_action( 'edd_paypal_' . $encoded_data_array['txn_type'], $encoded_data_array, $payment_id );
301
  } else {
302
  // Fallback to web accept just in case the txn_type isn't present
303
+ do_action( 'edd_paypal_web_accept', $encoded_data_array, $payment_id );
304
  }
305
  exit;
306
  }
310
  * Process web accept (one time) payment IPNs
311
  *
312
  * @since 1.3.4
 
313
  * @param array $data IPN Data
314
  * @return void
315
  */
316
+ function edd_process_paypal_web_accept_and_cart( $data, $payment_id ) {
317
+ if ( $data['txn_type'] != 'web_accept' && $data['txn_type'] != 'cart' && $data['payment_status'] != 'Refunded' ) {
318
+ return;
319
+ }
320
 
321
+ if( empty( $payment_id ) ) {
322
  return;
323
+ }
324
 
325
  // Collect payment details
 
326
  $purchase_key = isset( $data['invoice'] ) ? $data['invoice'] : $data['item_number'];
327
  $paypal_amount = $data['mc_gross'];
328
  $payment_status = strtolower( $data['payment_status'] );
329
  $currency_code = strtolower( $data['mc_currency'] );
330
  $business_email = isset( $data['business'] ) && is_email( $data['business'] ) ? trim( $data['business'] ) : trim( $data['receiver_email'] );
331
+ $payment_meta = edd_get_payment_meta( $payment_id );
332
+
333
 
334
  if ( edd_get_payment_gateway( $payment_id ) != 'paypal' ) {
335
  return; // this isn't a PayPal standard IPN
336
  }
337
 
338
  // Verify payment recipient
339
+ if ( strcasecmp( $business_email, trim( edd_get_option( 'paypal_email', false ) ) ) != 0 ) {
 
340
  edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid business email in IPN response. IPN data: %s', 'edd' ), json_encode( $data ) ), $payment_id );
341
  edd_update_payment_status( $payment_id, 'failed' );
342
  edd_insert_payment_note( $payment_id, __( 'Payment failed due to invalid PayPal business email.', 'edd' ) );
344
  }
345
 
346
  // Verify payment currency
347
+ if ( $currency_code != strtolower( $payment_meta['currency'] ) ) {
348
 
349
  edd_record_gateway_error( __( 'IPN Error', 'edd' ), sprintf( __( 'Invalid currency in IPN response. IPN data: %s', 'edd' ), json_encode( $data ) ), $payment_id );
350
  edd_update_payment_status( $payment_id, 'failed' );
357
  // This runs when a Buy Now purchase was made. It bypasses checkout so no personal info is collected until PayPal
358
 
359
  // No email associated with purchase, so store from PayPal
360
+ edd_update_payment_meta( $payment_id, '_edd_payment_user_email', $data['payer_email'] );
361
 
362
  // Setup and store the customers's details
363
  $address = array();
364
+ $address['line1'] = ! empty( $data['address_street'] ) ? sanitize_text_field( $data['address_street'] ) : false;
365
+ $address['city'] = ! empty( $data['address_city'] ) ? sanitize_text_field( $data['address_city'] ) : false;
366
+ $address['state'] = ! empty( $data['address_state'] ) ? sanitize_text_field( $data['address_state'] ) : false;
367
+ $address['country'] = ! empty( $data['address_country_code'] ) ? sanitize_text_field( $data['address_country_code'] ) : false;
368
+ $address['zip'] = ! empty( $data['address_zip'] ) ? sanitize_text_field( $data['address_zip'] ) : false;
369
 
370
  $user_info = array(
371
  'id' => '-1',
372
+ 'email' => sanitize_text_field( $data['payer_email'] ),
373
+ 'first_name' => sanitize_text_field( $data['first_name'] ),
374
+ 'last_name' => sanitize_text_field( $data['last_name'] ),
375
  'discount' => '',
376
  'address' => $address
377
  );
378
 
 
379
  $payment_meta['user_info'] = $user_info;
380
+ edd_update_payment_meta( $payment_id, '_edd_payment_meta', $payment_meta );
381
  }
382
 
383
+ if ( $payment_status == 'refunded' || $payment_status == 'reversed' ) {
384
 
385
  // Process a refund
386
+ edd_process_paypal_refund( $data, $payment_id );
387
 
388
  } else {
389
 
409
  return;
410
  }
411
 
412
+ if ( 'completed' == $payment_status || edd_is_test_mode() ) {
413
+
414
  edd_insert_payment_note( $payment_id, sprintf( __( 'PayPal Transaction ID: %s', 'edd' ) , $data['txn_id'] ) );
415
+ edd_set_payment_transaction_id( $payment_id, $data['txn_id'] );
416
  edd_update_payment_status( $payment_id, 'publish' );
417
+
418
+ } else if ( 'pending' == $payment_status && isset( $data['pending_reason'] ) ) {
419
+
420
+ // Look for possible pending reasons, such as an echeck
421
+
422
+ $note = '';
423
+
424
+ switch( strtolower( $data['pending_reason'] ) ) {
425
+
426
+ case 'echeck' :
427
+
428
+ $note = __( 'Payment made via eCheck and will clear automatically in 5-8 days', 'edd' );
429
+
430
+ break;
431
+
432
+ case 'address' :
433
+
434
+ $note = __( 'Payment requires a confirmed customer address and must be accepted manually through PayPal', 'edd' );
435
+
436
+ break;
437
+
438
+ case 'intl' :
439
+
440
+ $note = __( 'Payment must be accepted manually through PayPal due to international account regulations', 'edd' );
441
+
442
+ break;
443
+
444
+ case 'multi-currency' :
445
+
446
+ $note = __( 'Payment received in non-shop currency and must be accepted manually through PayPal', 'edd' );
447
+
448
+ break;
449
+
450
+ case 'paymentreview' :
451
+ case 'regulatory_review' :
452
+
453
+ $note = __( 'Payment is being reviewed by PayPal staff as high-risk or in possible violation of government regulations', 'edd' );
454
+
455
+ break;
456
+
457
+ case 'unilateral' :
458
+
459
+ $note = __( 'Payment was sent to non-confirmed or non-registered email address.', 'edd' );
460
+
461
+ break;
462
+
463
+ case 'upgrade' :
464
+
465
+ $note = __( 'PayPal account must be upgraded before this payment can be accepted', 'edd' );
466
+
467
+ break;
468
+
469
+ case 'verify' :
470
+
471
+ $note = __( 'PayPal account is not verified. Verify account in order to accept this payment', 'edd' );
472
+
473
+ break;
474
+
475
+ case 'other' :
476
+
477
+ $note = __( 'Payment is pending for unknown reasons. Contact PayPal support for assistance', 'edd' );
478
+
479
+ break;
480
+
481
+ }
482
+
483
+ if( ! empty( $note ) ) {
484
+
485
+ edd_insert_payment_note( $payment_id, $note );
486
+
487
+ }
488
+
489
  }
490
  }
491
  }
492
+ add_action( 'edd_paypal_web_accept', 'edd_process_paypal_web_accept_and_cart', 10, 2 );
493
 
494
  /**
495
  * Process PayPal IPN Refunds
496
  *
497
  * @since 1.3.4
 
498
  * @param array $data IPN Data
499
  * @return void
500
  */
501
+ function edd_process_paypal_refund( $data, $payment_id = 0 ) {
 
502
 
503
  // Collect payment details
504
+
505
+ if( empty( $payment_id ) ) {
506
+ return;
507
+ }
508
 
509
  if ( get_post_status( $payment_id ) == 'refunded' ) {
510
  return; // Only refund payments once
511
  }
512
 
513
+ $payment_amount = edd_get_payment_amount( $payment_id );
514
+ $refund_amount = $data['payment_gross'] * -1;
515
+
516
+ if ( number_format( (float) $refund_amount, 2 ) < number_format( (float) $payment_amount, 2 ) ) {
517
+
518
+ edd_insert_payment_note( $payment_id, sprintf( __( 'Partial PayPal refund processed: %s', 'edd' ), $data['parent_txn_id'] ) );
519
+ return; // This is a partial refund
520
+
521
+ }
522
+
523
+ edd_insert_payment_note( $payment_id, sprintf( __( 'PayPal Payment #%s Refunded for reason: %s', 'edd' ), $data['parent_txn_id'], $data['reason_code'] ) );
524
+ edd_insert_payment_note( $payment_id, sprintf( __( 'PayPal Refund Transaction ID: %s', 'edd' ), $data['txn_id'] ) );
525
  edd_update_payment_status( $payment_id, 'refunded' );
526
  }
527
 
529
  * Get PayPal Redirect
530
  *
531
  * @since 1.0.8.2
 
532
  * @param bool $ssl_check Is SSL?
533
  * @return string
534
  */
535
  function edd_get_paypal_redirect( $ssl_check = false ) {
 
 
536
  if ( is_ssl() || ! $ssl_check ) {
537
  $protocal = 'https://';
538
  } else {
555
  * Set the Page Style for PayPal Purchase page
556
  *
557
  * @since 1.4.1
 
558
  * @return string
559
  */
560
  function edd_get_paypal_page_style() {
561
+ $page_style = trim( edd_get_option( 'paypal_page_style', 'PayPal' ) );
 
 
 
 
 
 
562
  return apply_filters( 'edd_paypal_page_style', $page_style );
563
  }
564
 
600
 
601
  }
602
  add_filter( 'edd_payment_confirm_paypal', 'edd_paypal_success_page_content' );
603
+
604
+ /**
605
+ * Given a Payment ID, extract the transaction ID
606
+ *
607
+ * @since 2.1
608
+ * @param string $payment_id Payment ID
609
+ * @return string Transaction ID
610
+ */
611
+ function edd_paypal_get_payment_transaction_id( $payment_id ) {
612
+
613
+ $transaction_id = '';
614
+ $notes = edd_get_payment_notes( $payment_id );
615
+
616
+ foreach ( $notes as $note ) {
617
+ if ( preg_match( '/^PayPal Transaction ID: ([^\s]+)/', $note->comment_content, $match ) ) {
618
+ $transaction_id = $match[1];
619
+ continue;
620
+ }
621
+ }
622
+
623
+ return apply_filters( 'edd_paypal_set_payment_transaction_id', $transaction_id, $payment_id );
624
+ }
625
+ add_filter( 'edd_get_payment_transaction_id-paypal', 'edd_paypal_get_payment_transaction_id', 10, 1 );
626
+
627
+ /**
628
+ * Given a transaction ID, generate a link to the PayPal transaction ID details
629
+ *
630
+ * @since 2.2
631
+ * @param string $transaction_id The Transaction ID
632
+ * @param int $payment_id The payment ID for this transaction
633
+ * @return string A link to the PayPal transaction details
634
+ */
635
+ function edd_paypal_link_transaction_id( $transaction_id, $payment_id ) {
636
+
637
+ $paypal_base_url = 'https://history.paypal.com/cgi-bin/webscr?cmd=_history-details-from-hub&id=';
638
+ $transaction_url = '<a href="' . esc_url( $paypal_base_url . $transaction_id ) . '" target="_blank">' . $transaction_id . '</a>';
639
+
640
+ return apply_filters( 'edd_paypal_link_payment_details_transaction_id', $transaction_url );
641
+
642
+ }
643
+ add_filter( 'edd_payment_details_transaction_id-paypal', 'edd_paypal_link_transaction_id', 10, 2 );
includes/install.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Functions/Install
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -30,6 +30,10 @@ if ( ! defined( 'ABSPATH' ) ) exit;
30
  function edd_install() {
31
  global $wpdb, $edd_options, $wp_version;
32
 
 
 
 
 
33
  // Setup the Downloads Custom Post Type
34
  edd_setup_edd_post_types();
35
 
@@ -49,7 +53,7 @@ function edd_install() {
49
  $options = array();
50
 
51
  // Checks if the purchase page option exists
52
- if ( ! isset( $edd_options['purchase_page'] ) ) {
53
  // Checkout Page
54
  $checkout = wp_insert_post(
55
  array(
@@ -107,9 +111,6 @@ function edd_install() {
107
  $options['failure_page'] = $failed;
108
  $options['purchase_history_page'] = $history;
109
 
110
- // Add a temporary option to note that EDD pages have been created
111
- set_transient( '_edd_installed', $options, 30 );
112
-
113
  }
114
 
115
  // Populate some default values
@@ -136,11 +137,34 @@ function edd_install() {
136
  $roles->add_roles();
137
  $roles->add_caps();
138
 
 
 
 
 
 
 
 
 
 
139
  // Bail if activating from network, or bulk
140
  if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) {
141
  return;
142
  }
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  // Add the transient to redirect
145
  set_transient( '_edd_activation_redirect', true, 30 );
146
  }
@@ -168,6 +192,9 @@ function edd_after_install() {
168
  return;
169
  }
170
 
 
 
 
171
  // Delete the transient
172
  delete_transient( '_edd_installed' );
173
 
4
  *
5
  * @package EDD
6
  * @subpackage Functions/Install
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
30
  function edd_install() {
31
  global $wpdb, $edd_options, $wp_version;
32
 
33
+ if( ! function_exists( 'edd_create_protection_files' ) ) {
34
+ require_once EDD_PLUGIN_DIR . 'includes/admin/upload-functions.php';
35
+ }
36
+
37
  // Setup the Downloads Custom Post Type
38
  edd_setup_edd_post_types();
39
 
53
  $options = array();
54
 
55
  // Checks if the purchase page option exists
56
+ if ( ! edd_get_option( 'purchase_page', false ) ) {
57
  // Checkout Page
58
  $checkout = wp_insert_post(
59
  array(
111
  $options['failure_page'] = $failed;
112
  $options['purchase_history_page'] = $history;
113
 
 
 
 
114
  }
115
 
116
  // Populate some default values
137
  $roles->add_roles();
138
  $roles->add_caps();
139
 
140
+ // Create the customers database
141
+ @EDD()->customers->create_table();
142
+
143
+ // Check for PHP Session support, and enable if available
144
+ EDD()->session->use_php_sessions();
145
+
146
+ // Add a temporary option to note that EDD pages have been created
147
+ set_transient( '_edd_installed', $options, 30 );
148
+
149
  // Bail if activating from network, or bulk
150
  if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) {
151
  return;
152
  }
153
 
154
+ if ( ! $current_version ) {
155
+ require_once EDD_PLUGIN_DIR . 'includes/admin/upgrades/upgrade-functions.php';
156
+
157
+ // When new upgrade routines are added, mark them as complete on fresh install
158
+ $upgrade_routines = array(
159
+ 'upgrade_payment_taxes',
160
+ 'upgrade_customer_payments_association'
161
+ );
162
+
163
+ foreach ( $upgrade_routines as $upgrade ) {
164
+ edd_set_upgrade_complete( $upgrade );
165
+ }
166
+ }
167
+
168
  // Add the transient to redirect
169
  set_transient( '_edd_activation_redirect', true, 30 );
170
  }
192
  return;
193
  }
194
 
195
+ // Create the customers database (this ensures it creates it on multisite instances where it is network activated)
196
+ @EDD()->customers->create_table();
197
+
198
  // Delete the transient
199
  delete_transient( '_edd_installed' );
200
 
includes/libraries/array2xml.php CHANGED
@@ -1,4 +1,8 @@
1
  <?php
 
 
 
 
2
  class Array2XML {
3
 
4
  private static $xml = null;
1
  <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+
6
  class Array2XML {
7
 
8
  private static $xml = null;
includes/libraries/browser.php CHANGED
@@ -1,1082 +1,1103 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /**
3
- * Modified to remove var
4
- * Chris Christoff on 12/26/2012
5
- * Changes: Changes vars to publics
6
- *
7
- * Modified to work for EDD by
8
- * Chris Christoff on 12/23/2012
9
- * Changes: Removed the browser string return and added spacing. Also removed return HTML formatting.
10
- *
11
- * Modified to add formatted User Agent string for EDD System Info by
12
- * Chris Christoff on 12/23/2012
13
- * Changes: Split user string and add formatting so we can print a nicely
14
- * formatted user agent string on the EDD System Info
15
- *
16
- * File: Browser.php
17
- * Author: Chris Schuld (http://chrisschuld.com/)
18
- * Last Modified: August 20th, 2010
19
- * @version 1.9
20
- * @package PegasusPHP
21
- *
22
- * Copyright (C) 2008-2010 Chris Schuld (chris@chrisschuld.com)
23
- *
24
- * This program is free software; you can redistribute it and/or
25
- * modify it under the terms of the GNU General Public License as
26
- * published by the Free Software Foundation; either version 2 of
27
- * the License, or (at your option) any later version.
28
- *
29
- * This program is distributed in the hope that it will be useful,
30
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
- * GNU General Public License for more details at:
33
- * http://www.gnu.org/copyleft/gpl.html
34
- *
35
- *
36
- * Typical Usage:
37
- *
38
- * $browser = new Browser();
39
- * if( $browser->getBrowser() == Browser::BROWSER_FIREFOX && $browser->getVersion() >= 2 ) {
40
- * echo 'You have FireFox version 2 or greater';
41
- * }
42
- *
43
- * User Agents Sampled from: http://www.useragentstring.com/
44
- *
45
- * This implementation is based on the original work from Gary White
46
- * http://apptools.com/phptools/browser/
47
  *
48
- * UPDATES:
 
 
 
 
 
 
49
  *
50
- * 2010-08-20 (v1.9):
51
- * + Added MSN Explorer Browser (legacy)
52
- * + Added Bing/MSN Robot (Thanks Rob MacDonald)
53
- * + Added the Android Platform (PLATFORM_ANDROID)
54
- * + Fixed issue with Android 1.6/2.2 (Thanks Tom Hirashima)
55
  *
56
- * 2010-04-27 (v1.8):
57
- * + Added iPad Support
 
 
 
58
  *
59
- * 2010-03-07 (v1.7):
60
- * + *MAJOR* Rebuild (preg_match and other "slow" routine removal(s))
61
- * + Almost allof Gary's original code has been replaced
62
- * + Large PHPUNIT testing environment created to validate new releases and additions
63
- * + Added FreeBSD Platform
64
- * + Added OpenBSD Platform
65
- * + Added NetBSD Platform
66
- * + Added SunOS Platform
67
- * + Added OpenSolaris Platform
68
- * + Added support of the Iceweazel Browser
69
- * + Added isChromeFrame() call to check if chromeframe is in use
70
- * + Moved the Opera check in front of the Firefox check due to legacy Opera User Agents
71
- * + Added the __toString() method (Thanks Deano)
72
  *
73
- * 2009-11-15:
74
- * + Updated the checkes for Firefox
75
- * + Added the NOKIA platform
76
- * + Added Checks for the NOKIA brower(s)
 
77
  *
78
- * 2009-11-08:
79
- * + PHP 5.3 Support
80
- * + Added support for BlackBerry OS and BlackBerry browser
81
- * + Added support for the Opera Mini browser
82
- * + Added additional documenation
83
- * + Added support for isRobot() and isMobile()
84
- * + Added support for Opera version 10
85
- * + Added support for deprecated Netscape Navigator version 9
86
- * + Added support for IceCat
87
- * + Added support for Shiretoko
88
  *
89
- * 2010-04-27 (v1.8):
90
- * + Added iPad Support
 
 
 
91
  *
92
- * 2009-08-18:
93
- * + Updated to support PHP 5.3 - removed all deprecated function calls
94
- * + Updated to remove all double quotes (") -- converted to single quotes (')
 
 
95
  *
96
- * 2009-04-27:
97
- * + Updated the IE check to remove a typo and bug (thanks John)
 
 
 
98
  *
99
- * 2009-04-22:
100
- * + Added detection for GoogleBot
101
- * + Added detection for the W3C Validator.
102
- * + Added detection for Yahoo! Slurp
 
103
  *
104
- * 2009-03-14:
105
- * + Added detection for iPods.
106
- * + Added Platform detection for iPhones
107
- * + Added Platform detection for iPods
 
108
  *
109
- * 2009-02-16: (Rick Hale)
110
- * + Added version detection for Android phones.
 
 
 
111
  *
112
- * 2008-12-09:
113
- * + Removed unused constant
 
 
 
114
  *
115
- * 2008-11-07:
116
- * + Added Google's Chrome to the detection list
117
- * + Added isBrowser(string) to the list of functions special thanks to
118
- * Daniel 'mavrick' Lang for the function concept (http://mavrick.id.au)
 
119
  *
 
 
 
 
 
120
  *
121
- * Gary White noted: "Since browser detection is so unreliable, I am
122
- * no longer maintaining this script. You are free to use and or
123
- * modify/update it as you want, however the author assumes no
124
- * responsibility for the accuracy of the detected values."
 
125
  *
126
- * Anyone experienced with Gary's script might be interested in these notes:
 
 
 
 
 
 
 
 
127
  *
128
- * Added class constants
129
- * Added detection and version detection for Google's Chrome
130
- * Updated the version detection for Amaya
131
- * Updated the version detection for Firefox
132
- * Updated the version detection for Lynx
133
- * Updated the version detection for WebTV
134
- * Updated the version detection for NetPositive
135
- * Updated the version detection for IE
136
- * Updated the version detection for OmniWeb
137
- * Updated the version detection for iCab
138
- * Updated the version detection for Safari
139
- * Updated Safari to remove mobile devices (iPhone)
140
- * Added detection for iPhone
141
- * Added detection for robots
142
- * Added detection for mobile devices
143
- * Added detection for BlackBerry
144
- * Removed Netscape checks (matches heavily with firefox & mozilla)
145
  *
 
146
  */
147
-
148
- class Browser {
149
- public $_agent = '';
150
- public $_browser_name = '';
151
- public $_version = '';
152
- public $_platform = '';
153
- public $_os = '';
154
- public $_is_aol = false;
155
- public $_is_mobile = false;
156
- public $_is_robot = false;
157
- public $_aol_version = '';
158
-
159
- public $BROWSER_UNKNOWN = 'unknown';
160
- public $VERSION_UNKNOWN = 'unknown';
161
-
162
- public $BROWSER_OPERA = 'Opera'; // Http://www.opera.com/
163
- public $BROWSER_OPERA_MINI = 'Opera Mini'; // Http://www.opera.com/mini/
164
- public $BROWSER_WEBTV = 'WebTV'; // Http://www.webtv.net/pc/
165
- public $BROWSER_IE = 'Internet Explorer'; // Http://www.microsoft.com/ie/
166
- public $BROWSER_POCKET_IE = 'Pocket Internet Explorer'; // Http://en.wikipedia.org/wiki/Internet_Explorer_Mobile
167
- public $BROWSER_KONQUEROR = 'Konqueror'; // Http://www.konqueror.org/
168
- public $BROWSER_ICAB = 'iCab'; // Http://www.icab.de/
169
- public $BROWSER_OMNIWEB = 'OmniWeb'; // Http://www.omnigroup.com/applications/omniweb/
170
- public $BROWSER_FIREBIRD = 'Firebird'; // Http://www.ibphoenix.com/
171
- public $BROWSER_FIREFOX = 'Firefox'; // Http://www.mozilla.com/en-US/firefox/firefox.html
172
- public $BROWSER_ICEWEASEL = 'Iceweasel'; // Http://www.geticeweasel.org/
173
- public $BROWSER_SHIRETOKO = 'Shiretoko'; // Http://wiki.mozilla.org/Projects/shiretoko
174
- public $BROWSER_MOZILLA = 'Mozilla'; // Http://www.mozilla.com/en-US/
175
- public $BROWSER_AMAYA = 'Amaya'; // Http://www.w3.org/Amaya/
176
- public $BROWSER_LYNX = 'Lynx'; // Http://en.wikipedia.org/wiki/Lynx
177
- public $BROWSER_SAFARI = 'Safari'; // Http://apple.com
178
- public $BROWSER_IPHONE = 'iPhone'; // Http://apple.com
179
- public $BROWSER_IPOD = 'iPod'; // Http://apple.com
180
- public $BROWSER_IPAD = 'iPad'; // Http://apple.com
181
- public $BROWSER_CHROME = 'Chrome'; // Http://www.google.com/chrome
182
- public $BROWSER_ANDROID = 'Android'; // Http://www.android.com/
183
- public $BROWSER_GOOGLEBOT = 'GoogleBot'; // Http://en.wikipedia.org/wiki/Googlebot
184
- public $BROWSER_SLURP = 'Yahoo! Slurp'; // Http://en.wikipedia.org/wiki/Yahoo!_Slurp
185
- public $BROWSER_W3CVALIDATOR = 'W3C Validator'; // Http://validator.w3.org/
186
- public $BROWSER_BLACKBERRY = 'BlackBerry'; // Http://www.blackberry.com/
187
- public $BROWSER_ICECAT = 'IceCat'; // Http://en.wikipedia.org/wiki/GNU_IceCat
188
- public $BROWSER_NOKIA_S60 = 'Nokia S60 OSS Browser'; // Http://en.wikipedia.org/wiki/Web_Browser_for_S60
189
- public $BROWSER_NOKIA = 'Nokia Browser'; // * all other WAP-based browsers on the Nokia Platform
190
- public $BROWSER_MSN = 'MSN Browser'; // Http://explorer.msn.com/
191
- public $BROWSER_MSNBOT = 'MSN Bot'; // Http://search.msn.com/msnbot.htm
192
- // Http://en.wikipedia.org/wiki/Msnbot (used for Bing as well)
193
-
194
- public $BROWSER_NETSCAPE_NAVIGATOR = 'Netscape Navigator'; // Http://browser.netscape.com/ (DEPRECATED)
195
- public $BROWSER_GALEON = 'Galeon'; // Http://galeon.sourceforge.net/ (DEPRECATED)
196
- public $BROWSER_NETPOSITIVE = 'NetPositive'; // Http://en.wikipedia.org/wiki/NetPositive (DEPRECATED)
197
- public $BROWSER_PHOENIX = 'Phoenix'; // Http://en.wikipedia.org/wiki/History_of_Mozilla_Firefox (DEPRECATED)
198
-
199
- public $PLATFORM_UNKNOWN = 'unknown';
200
- public $PLATFORM_WINDOWS = 'Windows';
201
- public $PLATFORM_WINDOWS_CE = 'Windows CE';
202
- public $PLATFORM_APPLE = 'Apple';
203
- public $PLATFORM_LINUX = 'Linux';
204
- public $PLATFORM_OS2 = 'OS/2';
205
- public $PLATFORM_BEOS = 'BeOS';
206
- public $PLATFORM_IPHONE = 'iPhone';
207
- public $PLATFORM_IPOD = 'iPod';
208
- public $PLATFORM_IPAD = 'iPad';
209
- public $PLATFORM_BLACKBERRY = 'BlackBerry';
210
- public $PLATFORM_NOKIA = 'Nokia';
211
- public $PLATFORM_FREEBSD = 'FreeBSD';
212
- public $PLATFORM_OPENBSD = 'OpenBSD';
213
- public $PLATFORM_NETBSD = 'NetBSD';
214
- public $PLATFORM_SUNOS = 'SunOS';
215
- public $PLATFORM_OPENSOLARIS = 'OpenSolaris';
216
- public $PLATFORM_ANDROID = 'Android';
217
-
218
- public $OPERATING_SYSTEM_UNKNOWN = 'unknown';
219
-
220
- function Browser($useragent="") {
221
- $this->reset();
222
- if( $useragent != "" ) {
223
- $this->setUserAgent($useragent);
224
- }
225
- else {
226
- $this->determine();
227
- }
228
- }
229
-
230
- /**
231
- * Reset all properties
232
- */
233
- function reset() {
234
- $this->_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : "";
235
- $this->_browser_name = $this->BROWSER_UNKNOWN;
236
- $this->_version = $this->VERSION_UNKNOWN;
237
- $this->_platform = $this->PLATFORM_UNKNOWN;
238
- $this->_os = $this->OPERATING_SYSTEM_UNKNOWN;
239
- $this->_is_aol = false;
240
- $this->_is_mobile = false;
241
- $this->_is_robot = false;
242
- $this->_aol_version = $this->VERSION_UNKNOWN;
243
- }
244
-
245
- /**
246
- * Check to see if the specific browser is valid
247
- * @param string $browserName
248
- * @return True if the browser is the specified browser
249
- */
250
- function isBrowser($browserName) { return( 0 == strcasecmp($this->_browser_name, trim($browserName))); }
251
-
252
- /**
253
- * The name of the browser. All return types are from the class contants
254
- * @return string Name of the browser
255
- */
256
- function getBrowser() { return $this->_browser_name; }
257
- /**
258
- * Set the name of the browser
259
- * @param $browser The name of the Browser
260
- */
261
- function setBrowser($browser) { return $this->_browser_name = $browser; }
262
- /**
263
- * The name of the platform. All return types are from the class contants
264
- * @return string Name of the browser
265
- */
266
- function getPlatform() { return $this->_platform; }
267
- /**
268
- * Set the name of the platform
269
- * @param $platform The name of the Platform
270
- */
271
- function setPlatform($platform) { return $this->_platform = $platform; }
272
- /**
273
- * The version of the browser.
274
- * @return string Version of the browser (will only contain alpha-numeric characters and a period)
275
- */
276
- function getVersion() { return $this->_version; }
277
- /**
278
- * Set the version of the browser
279
- * @param $version The version of the Browser
280
- */
281
- function setVersion($version) { $this->_version = preg_replace('/[^0-9,.,a-z,A-Z-]/','',$version); }
282
- /**
283
- * The version of AOL.
284
- * @return string Version of AOL (will only contain alpha-numeric characters and a period)
285
- */
286
- function getAolVersion() { return $this->_aol_version; }
287
- /**
288
- * Set the version of AOL
289
- * @param $version The version of AOL
290
- */
291
- function setAolVersion($version) { $this->_aol_version = preg_replace('/[^0-9,.,a-z,A-Z]/','',$version); }
292
- /**
293
- * Is the browser from AOL?
294
- * @return boolean True if the browser is from AOL otherwise false
295
- */
296
- function isAol() { return $this->_is_aol; }
297
- /**
298
- * Is the browser from a mobile device?
299
- * @return boolean True if the browser is from a mobile device otherwise false
300
- */
301
- function isMobile() { return $this->_is_mobile; }
302
- /**
303
- * Is the browser from a robot (ex Slurp,GoogleBot)?
304
- * @return boolean True if the browser is from a robot otherwise false
305
- */
306
- function isRobot() { return $this->_is_robot; }
307
- /**
308
- * Set the browser to be from AOL
309
- * @param $isAol
310
- */
311
- function setAol($isAol) { $this->_is_aol = $isAol; }
312
- /**
313
- * Set the Browser to be mobile
314
- * @param boolean $value is the browser a mobile brower or not
315
- */
316
- function setMobile($value=true) { $this->_is_mobile = $value; }
317
- /**
318
- * Set the Browser to be a robot
319
- * @param boolean $value is the browser a robot or not
320
- */
321
- function setRobot($value=true) { $this->_is_robot = $value; }
322
- /**
323
- * Get the user agent value in use to determine the browser
324
- * @return string The user agent from the HTTP header
325
- */
326
- function getUserAgent() { return $this->_agent; }
327
- /**
328
- * Set the user agent value (the construction will use the HTTP header value - this will overwrite it)
329
- * @param $agent_string The value for the User Agent
330
- */
331
- function setUserAgent($agent_string) {
332
- $this->reset();
333
- $this->_agent = $agent_string;
334
- $this->determine();
335
- }
336
- /**
337
- * Used to determine if the browser is actually "chromeframe"
338
- * @since 1.7
339
- * @return boolean True if the browser is using chromeframe
340
- */
341
- function isChromeFrame() {
342
- return( strpos($this->_agent,"chromeframe") !== false );
343
- }
344
- /**
345
- * Returns a formatted string with a summary of the details of the browser.
346
- * @return string formatted string with a summary of the browser
347
- */
348
- function __toString() {
349
  $text1 = $this->getUserAgent(); //grabs the UA (user agent) string
350
- $UAline1 = substr($text1, 0, 32); //the first line we print should only be the first 32 characters of the UA string
351
  $text2 = $this->getUserAgent();//now we grab it again and save it to a string
352
- $towrapUA = str_replace($UAline1, '', $text2);//the rest of the printoff (other than first line) is equivolent
353
  // To the whole string minus the part we printed off. IE
354
  // User Agent: thefirst32charactersfromUAline1
355
  // the rest of it is now stored in
356
  // $text2 to be printed off
357
  // But we need to add spaces before each line that is split other than line 1
358
  $space = '';
359
- for($i = 0; $i < 25; $i++) {
360
- $space .= ' ';
361
  }
362
  // Now we split the remaining string of UA ($text2) into lines that are prefixed by spaces for formatting
363
- $wordwrapped = chunk_split($towrapUA, 32, "\n $space");
364
- return "Platform: {$this->getPlatform()} \n".
365
- "Browser Name: {$this->getBrowser()} \n" .
366
- "Browser Version: {$this->getVersion()} \n" .
367
- "User Agent String: $UAline1 \n\t\t\t " .
368
- "$wordwrapped";
369
- }
370
- /**
371
- * Protected routine to calculate and determine what the browser is in use (including platform)
372
- */
373
- function determine() {
374
- $this->checkPlatform();
375
- $this->checkBrowsers();
376
- $this->checkForAol();
377
- }
378
- /**
379
- * Protected routine to determine the browser type
380
- * @return boolean True if the browser was detected otherwise false
381
- */
382
- function checkBrowsers() {
383
- return (
384
- // Well-known, well-used
385
- // Special Notes:
386
- // (1) Opera must be checked before FireFox due to the odd
387
- // user agents used in some older versions of Opera
388
- // (2) WebTV is strapped onto Internet Explorer so we must
389
- // check for WebTV before IE
390
- // (3) (deprecated) Galeon is based on Firefox and needs to be
391
- // tested before Firefox is tested
392
- // (4) OmniWeb is based on Safari so OmniWeb check must occur
393
- // before Safari
394
- // (5) Netscape 9+ is based on Firefox so Netscape checks
395
- // before FireFox are necessary
396
- $this->checkBrowserWebTv() ||
397
- $this->checkBrowserInternetExplorer() ||
398
- $this->checkBrowserOpera() ||
399
- $this->checkBrowserGaleon() ||
400
- $this->checkBrowserNetscapeNavigator9Plus() ||
401
- $this->checkBrowserFirefox() ||
402
- $this->checkBrowserChrome() ||
403
- $this->checkBrowserOmniWeb() ||
 
404
 
405
- // Common mobile
406
- $this->checkBrowserAndroid() ||
407
- $this->checkBrowseriPad() ||
408
- $this->checkBrowseriPod() ||
409
- $this->checkBrowseriPhone() ||
410
- $this->checkBrowserBlackBerry() ||
411
- $this->checkBrowserNokia() ||
412
 
413
- // Common bots
414
- $this->checkBrowserGoogleBot() ||
415
- $this->checkBrowserMSNBot() ||
416
- $this->checkBrowserSlurp() ||
417
 
418
- // WebKit base check (post mobile and others)
419
- $this->checkBrowserSafari() ||
420
 
421
- // Everyone else
422
- $this->checkBrowserNetPositive() ||
423
- $this->checkBrowserFirebird() ||
424
- $this->checkBrowserKonqueror() ||
425
- $this->checkBrowserIcab() ||
426
- $this->checkBrowserPhoenix() ||
427
- $this->checkBrowserAmaya() ||
428
- $this->checkBrowserLynx() ||
429
 
430
- $this->checkBrowserShiretoko() ||
431
- $this->checkBrowserIceCat() ||
432
- $this->checkBrowserW3CValidator() ||
433
- $this->checkBrowserMozilla() /* Mozilla is such an open standard that you must check it last */
434
- );
435
- }
436
 
437
- /**
438
- * Determine if the user is using a BlackBerry (last updated 1.7)
439
- * @return boolean True if the browser is the BlackBerry browser otherwise false
440
- */
441
- function checkBrowserBlackBerry() {
442
- if( stripos($this->_agent,'blackberry') !== false ) {
443
- $aresult = explode("/",stristr($this->_agent,"BlackBerry"));
444
- $aversion = explode(' ',$aresult[1]);
445
- $this->setVersion($aversion[0]);
446
- $this->_browser_name = $this->BROWSER_BLACKBERRY;
447
- $this->setMobile(true);
448
- return true;
449
- }
450
- return false;
451
- }
 
452
 
453
- /**
454
- * Determine if the user is using an AOL User Agent (last updated 1.7)
455
- * @return boolean True if the browser is from AOL otherwise false
456
- */
457
- function checkForAol() {
458
- $this->setAol(false);
459
- $this->setAolVersion($this->VERSION_UNKNOWN);
 
460
 
461
- if( stripos($this->_agent,'aol') !== false ) {
462
- $aversion = explode(' ',stristr($this->_agent, 'AOL'));
463
- $this->setAol(true);
464
- $this->setAolVersion(preg_replace('/[^0-9\.a-z]/i', '', $aversion[1]));
465
- return true;
466
- }
467
- return false;
468
- }
469
 
470
- /**
471
- * Determine if the browser is the GoogleBot or not (last updated 1.7)
472
- * @return boolean True if the browser is the GoogletBot otherwise false
473
- */
474
- function checkBrowserGoogleBot() {
475
- if( stripos($this->_agent,'googlebot') !== false ) {
476
- $aresult = explode('/',stristr($this->_agent,'googlebot'));
477
- $aversion = explode(' ',$aresult[1]);
478
- $this->setVersion(str_replace(';','',$aversion[0]));
479
- $this->_browser_name = $this->BROWSER_GOOGLEBOT;
480
- $this->setRobot(true);
481
- return true;
482
- }
483
- return false;
484
- }
 
485
 
486
- /**
487
- * Determine if the browser is the MSNBot or not (last updated 1.9)
488
- * @return boolean True if the browser is the MSNBot otherwise false
489
- */
490
- function checkBrowserMSNBot() {
491
- if( stripos($this->_agent,"msnbot") !== false ) {
492
- $aresult = explode("/",stristr($this->_agent,"msnbot"));
493
- $aversion = explode(" ",$aresult[1]);
494
- $this->setVersion(str_replace(";","",$aversion[0]));
495
- $this->_browser_name = $this->BROWSER_MSNBOT;
496
- $this->setRobot(true);
497
- return true;
498
- }
499
- return false;
500
  }
 
 
501
 
502
- /**
503
- * Determine if the browser is the W3C Validator or not (last updated 1.7)
504
- * @return boolean True if the browser is the W3C Validator otherwise false
505
- */
506
- function checkBrowserW3CValidator() {
507
- if( stripos($this->_agent,'W3C-checklink') !== false ) {
508
- $aresult = explode('/',stristr($this->_agent,'W3C-checklink'));
509
- $aversion = explode(' ',$aresult[1]);
510
- $this->setVersion($aversion[0]);
511
- $this->_browser_name = $this->BROWSER_W3CVALIDATOR;
512
- return true;
513
- }
514
- else if( stripos($this->_agent,'W3C_Validator') !== false ) {
515
- // Some of the Validator versions do not delineate w/ a slash - add it back in
516
- $ua = str_replace("W3C_Validator ", "W3C_Validator/", $this->_agent);
517
- $aresult = explode('/',stristr($ua,'W3C_Validator'));
518
- $aversion = explode(' ',$aresult[1]);
519
- $this->setVersion($aversion[0]);
520
- $this->_browser_name = $this->BROWSER_W3CVALIDATOR;
521
- return true;
522
- }
523
- return false;
524
- }
525
 
526
- /**
527
- * Determine if the browser is the Yahoo! Slurp Robot or not (last updated 1.7)
528
- * @return boolean True if the browser is the Yahoo! Slurp Robot otherwise false
529
- */
530
- function checkBrowserSlurp() {
531
- if( stripos($this->_agent,'slurp') !== false ) {
532
- $aresult = explode('/',stristr($this->_agent,'Slurp'));
533
- $aversion = explode(' ',$aresult[1]);
534
- $this->setVersion($aversion[0]);
535
- $this->_browser_name = $this->BROWSER_SLURP;
536
- $this->setRobot(true);
537
- $this->setMobile(false);
538
- return true;
539
- }
540
- return false;
541
- }
 
542
 
543
- /**
544
- * Determine if the browser is Internet Explorer or not (last updated 1.7)
545
- * @return boolean True if the browser is Internet Explorer otherwise false
546
- */
547
- function checkBrowserInternetExplorer() {
 
548
 
549
- // Test for v1 - v1.5 IE
550
- if( stripos($this->_agent,'microsoft internet explorer') !== false ) {
551
- $this->setBrowser($this->BROWSER_IE);
552
- $this->setVersion('1.0');
553
- $aresult = stristr($this->_agent, '/');
554
- if( preg_match('/308|425|426|474|0b1/i', $aresult) ) {
555
- $this->setVersion('1.5');
556
- }
 
 
 
 
 
 
 
 
 
557
  return true;
558
- }
559
- // Test for versions > 1.5
560
- else if( stripos($this->_agent,'msie') !== false && stripos($this->_agent,'opera') === false ) {
561
- // See if the browser is the odd MSN Explorer
562
- if( stripos($this->_agent,'msnb') !== false ) {
563
- $aresult = explode(' ',stristr(str_replace(';','; ',$this->_agent),'MSN'));
564
- $this->setBrowser( $this->BROWSER_MSN );
565
- $this->setVersion(str_replace(array('(',')',';'),'',$aresult[1]));
566
- return true;
567
- }
568
- $aresult = explode(' ',stristr(str_replace(';','; ',$this->_agent),'msie'));
569
- $this->setBrowser( $this->BROWSER_IE );
570
- $this->setVersion(str_replace(array('(',')',';'),'',$aresult[1]));
571
- return true;
572
- }
573
- // Test for Pocket IE
574
- else if( stripos($this->_agent,'mspie') !== false || stripos($this->_agent,'pocket') !== false ) {
575
- $aresult = explode(' ',stristr($this->_agent,'mspie'));
576
- $this->setPlatform( $this->PLATFORM_WINDOWS_CE );
577
- $this->setBrowser( $this->BROWSER_POCKET_IE );
578
- $this->setMobile(true);
579
-
580
- if( stripos($this->_agent,'mspie') !== false ) {
581
- $this->setVersion($aresult[1]);
582
- }
583
- else {
584
- $aversion = explode('/',$this->_agent);
585
- $this->setVersion($aversion[1]);
586
- }
587
- return true;
588
- }
589
- return false;
590
- }
591
 
592
- /**
593
- * Determine if the browser is Opera or not (last updated 1.7)
594
- * @return boolean True if the browser is Opera otherwise false
595
- */
596
- function checkBrowserOpera() {
597
- if( stripos($this->_agent,'opera mini') !== false ) {
598
- $resultant = stristr($this->_agent, 'opera mini');
599
- if( preg_match('/\//',$resultant) ) {
600
- $aresult = explode('/',$resultant);
601
- $aversion = explode(' ',$aresult[1]);
602
- $this->setVersion($aversion[0]);
603
- }
604
- else {
605
- $aversion = explode(' ',stristr($resultant,'opera mini'));
606
- $this->setVersion($aversion[1]);
607
- }
608
- $this->_browser_name = $this->BROWSER_OPERA_MINI;
609
- $this->setMobile(true);
610
- return true;
611
- }
612
- else if( stripos($this->_agent,'opera') !== false ) {
613
- $resultant = stristr($this->_agent, 'opera');
614
- if( preg_match('/Version\/(10.*)$/',$resultant,$matches) ) {
615
- $this->setVersion($matches[1]);
616
- }
617
- else if( preg_match('/\//',$resultant) ) {
618
- $aresult = explode('/',str_replace("("," ",$resultant));
619
- $aversion = explode(' ',$aresult[1]);
620
- $this->setVersion($aversion[0]);
621
- }
622
- else {
623
- $aversion = explode(' ',stristr($resultant,'opera'));
624
- $this->setVersion(isset($aversion[1])?$aversion[1]:"");
625
- }
626
- $this->_browser_name = $this->BROWSER_OPERA;
627
- return true;
628
- }
629
- return false;
630
- }
631
 
632
- /**
633
- * Determine if the browser is Chrome or not (last updated 1.7)
634
- * @return boolean True if the browser is Chrome otherwise false
635
- */
636
- function checkBrowserChrome() {
637
- if( stripos($this->_agent,'Chrome') !== false ) {
638
- $aresult = explode('/',stristr($this->_agent,'Chrome'));
639
- $aversion = explode(' ',$aresult[1]);
640
- $this->setVersion($aversion[0]);
641
- $this->setBrowser($this->BROWSER_CHROME);
642
- return true;
643
- }
644
- return false;
645
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
647
 
648
- /**
649
- * Determine if the browser is WebTv or not (last updated 1.7)
650
- * @return boolean True if the browser is WebTv otherwise false
651
- */
652
- function checkBrowserWebTv() {
653
- if( stripos($this->_agent,'webtv') !== false ) {
654
- $aresult = explode('/',stristr($this->_agent,'webtv'));
655
- $aversion = explode(' ',$aresult[1]);
656
- $this->setVersion($aversion[0]);
657
- $this->setBrowser($this->BROWSER_WEBTV);
658
- return true;
659
- }
660
- return false;
661
- }
662
 
663
- /**
664
- * Determine if the browser is NetPositive or not (last updated 1.7)
665
- * @return boolean True if the browser is NetPositive otherwise false
666
- */
667
- function checkBrowserNetPositive() {
668
- if( stripos($this->_agent,'NetPositive') !== false ) {
669
- $aresult = explode('/',stristr($this->_agent,'NetPositive'));
670
- $aversion = explode(' ',$aresult[1]);
671
- $this->setVersion(str_replace(array('(',')',';'),'',$aversion[0]));
672
- $this->setBrowser($this->BROWSER_NETPOSITIVE);
673
- return true;
674
- }
675
- return false;
676
- }
 
677
 
678
- /**
679
- * Determine if the browser is Galeon or not (last updated 1.7)
680
- * @return boolean True if the browser is Galeon otherwise false
681
- */
682
- function checkBrowserGaleon() {
683
- if( stripos($this->_agent,'galeon') !== false ) {
684
- $aresult = explode(' ',stristr($this->_agent,'galeon'));
685
- $aversion = explode('/',$aresult[0]);
686
- $this->setVersion($aversion[1]);
687
- $this->setBrowser($this->BROWSER_GALEON);
688
- return true;
689
- }
690
- return false;
691
- }
 
692
 
693
- /**
694
- * Determine if the browser is Konqueror or not (last updated 1.7)
695
- * @return boolean True if the browser is Konqueror otherwise false
696
- */
697
- function checkBrowserKonqueror() {
698
- if( stripos($this->_agent,'Konqueror') !== false ) {
699
- $aresult = explode(' ',stristr($this->_agent,'Konqueror'));
700
- $aversion = explode('/',$aresult[0]);
701
- $this->setVersion($aversion[1]);
702
- $this->setBrowser($this->BROWSER_KONQUEROR);
703
- return true;
704
- }
705
- return false;
706
- }
 
707
 
708
- /**
709
- * Determine if the browser is iCab or not (last updated 1.7)
710
- * @return boolean True if the browser is iCab otherwise false
711
- */
712
- function checkBrowserIcab() {
713
- if( stripos($this->_agent,'icab') !== false ) {
714
- $aversion = explode(' ',stristr(str_replace('/',' ',$this->_agent),'icab'));
715
- $this->setVersion($aversion[1]);
716
- $this->setBrowser($this->BROWSER_ICAB);
717
- return true;
718
- }
719
- return false;
720
- }
 
 
721
 
722
- /**
723
- * Determine if the browser is OmniWeb or not (last updated 1.7)
724
- * @return boolean True if the browser is OmniWeb otherwise false
725
- */
726
- function checkBrowserOmniWeb() {
727
- if( stripos($this->_agent,'omniweb') !== false ) {
728
- $aresult = explode('/',stristr($this->_agent,'omniweb'));
729
- $aversion = explode(' ',isset($aresult[1])?$aresult[1]:"");
730
- $this->setVersion($aversion[0]);
731
- $this->setBrowser($this->BROWSER_OMNIWEB);
732
- return true;
733
- }
734
- return false;
735
- }
736
 
737
- /**
738
- * Determine if the browser is Phoenix or not (last updated 1.7)
739
- * @return boolean True if the browser is Phoenix otherwise false
740
- */
741
- function checkBrowserPhoenix() {
742
- if( stripos($this->_agent,'Phoenix') !== false ) {
743
- $aversion = explode('/',stristr($this->_agent,'Phoenix'));
744
- $this->setVersion($aversion[1]);
745
- $this->setBrowser($this->BROWSER_PHOENIX);
746
- return true;
747
- }
748
- return false;
749
- }
 
 
750
 
751
- /**
752
- * Determine if the browser is Firebird or not (last updated 1.7)
753
- * @return boolean True if the browser is Firebird otherwise false
754
- */
755
- function checkBrowserFirebird() {
756
- if( stripos($this->_agent,'Firebird') !== false ) {
757
- $aversion = explode('/',stristr($this->_agent,'Firebird'));
758
- $this->setVersion($aversion[1]);
759
- $this->setBrowser($this->BROWSER_FIREBIRD);
760
- return true;
761
- }
762
- return false;
763
- }
 
764
 
765
- /**
766
- * Determine if the browser is Netscape Navigator 9+ or not (last updated 1.7)
767
- * NOTE: (http://browser.netscape.com/ - Official support ended on March 1st, 2008)
768
- * @return boolean True if the browser is Netscape Navigator 9+ otherwise false
769
- */
770
- function checkBrowserNetscapeNavigator9Plus() {
771
- if( stripos($this->_agent,'Firefox') !== false && preg_match('/Navigator\/([^ ]*)/i',$this->_agent,$matches) ) {
772
- $this->setVersion($matches[1]);
773
- $this->setBrowser($this->BROWSER_NETSCAPE_NAVIGATOR);
774
- return true;
775
- }
776
- else if( stripos($this->_agent,'Firefox') === false && preg_match('/Netscape6?\/([^ ]*)/i',$this->_agent,$matches) ) {
777
- $this->setVersion($matches[1]);
778
- $this->setBrowser($this->BROWSER_NETSCAPE_NAVIGATOR);
779
- return true;
780
- }
781
- return false;
782
- }
783
 
784
- /**
785
- * Determine if the browser is Shiretoko or not (https://wiki.mozilla.org/Projects/shiretoko) (last updated 1.7)
786
- * @return boolean True if the browser is Shiretoko otherwise false
787
- */
788
- function checkBrowserShiretoko() {
789
- if( stripos($this->_agent,'Mozilla') !== false && preg_match('/Shiretoko\/([^ ]*)/i',$this->_agent,$matches) ) {
790
- $this->setVersion($matches[1]);
791
- $this->setBrowser($this->BROWSER_SHIRETOKO);
792
- return true;
793
- }
794
- return false;
795
- }
 
 
 
 
 
 
796
 
797
- /**
798
- * Determine if the browser is Ice Cat or not (http://en.wikipedia.org/wiki/GNU_IceCat) (last updated 1.7)
799
- * @return boolean True if the browser is Ice Cat otherwise false
800
- */
801
- function checkBrowserIceCat() {
802
- if( stripos($this->_agent,'Mozilla') !== false && preg_match('/IceCat\/([^ ]*)/i',$this->_agent,$matches) ) {
803
- $this->setVersion($matches[1]);
804
- $this->setBrowser($this->BROWSER_ICECAT);
805
- return true;
806
- }
807
- return false;
808
- }
 
809
 
810
- /**
811
- * Determine if the browser is Nokia or not (last updated 1.7)
812
- * @return boolean True if the browser is Nokia otherwise false
813
- */
814
- function checkBrowserNokia() {
815
- if( preg_match("/Nokia([^\/]+)\/([^ SP]+)/i",$this->_agent,$matches) ) {
816
- $this->setVersion($matches[2]);
817
- if( stripos($this->_agent,'Series60') !== false || strpos($this->_agent,'S60') !== false ) {
818
- $this->setBrowser($this->BROWSER_NOKIA_S60);
819
- }
820
- else {
821
- $this->setBrowser( $this->BROWSER_NOKIA );
822
- }
823
- $this->setMobile(true);
824
- return true;
825
- }
826
- return false;
827
- }
828
 
829
- /**
830
- * Determine if the browser is Firefox or not (last updated 1.7)
831
- * @return boolean True if the browser is Firefox otherwise false
832
- */
833
- function checkBrowserFirefox() {
834
- if( stripos($this->_agent,'safari') === false ) {
835
- if( preg_match("/Firefox[\/ \(]([^ ;\)]+)/i",$this->_agent,$matches) ) {
836
- $this->setVersion($matches[1]);
837
- $this->setBrowser($this->BROWSER_FIREFOX);
838
- return true;
839
- }
840
- else if( preg_match("/Firefox$/i",$this->_agent,$matches) ) {
841
- $this->setVersion("");
842
- $this->setBrowser($this->BROWSER_FIREFOX);
843
- return true;
844
- }
845
  }
846
- return false;
847
- }
 
 
 
848
 
849
- /**
850
- * Determine if the browser is Firefox or not (last updated 1.7)
851
- * @return boolean True if the browser is Firefox otherwise false
852
- */
853
- function checkBrowserIceweasel() {
854
- if( stripos($this->_agent,'Iceweasel') !== false ) {
855
- $aresult = explode('/',stristr($this->_agent,'Iceweasel'));
856
- $aversion = explode(' ',$aresult[1]);
857
- $this->setVersion($aversion[0]);
858
- $this->setBrowser($this->BROWSER_ICEWEASEL);
 
 
 
 
859
  return true;
860
  }
861
- return false;
862
  }
863
- /**
864
- * Determine if the browser is Mozilla or not (last updated 1.7)
865
- * @return boolean True if the browser is Mozilla otherwise false
866
- */
867
- function checkBrowserMozilla() {
868
- if( stripos($this->_agent,'mozilla') !== false && preg_match('/rv:[0-9].[0-9][a-b]?/i',$this->_agent) && stripos($this->_agent,'netscape') === false) {
869
- $aversion = explode(' ',stristr($this->_agent,'rv:'));
870
- preg_match('/rv:[0-9].[0-9][a-b]?/i',$this->_agent,$aversion);
871
- $this->setVersion(str_replace('rv:','',$aversion[0]));
872
- $this->setBrowser($this->BROWSER_MOZILLA);
873
- return true;
874
- }
875
- else if( stripos($this->_agent,'mozilla') !== false && preg_match('/rv:[0-9]\.[0-9]/i',$this->_agent) && stripos($this->_agent,'netscape') === false ) {
876
- $aversion = explode('',stristr($this->_agent,'rv:'));
877
- $this->setVersion(str_replace('rv:','',$aversion[0]));
878
- $this->setBrowser($this->BROWSER_MOZILLA);
879
- return true;
880
- }
881
- else if( stripos($this->_agent,'mozilla') !== false && preg_match('/mozilla\/([^ ]*)/i',$this->_agent,$matches) && stripos($this->_agent,'netscape') === false ) {
882
- $this->setVersion($matches[1]);
883
- $this->setBrowser($this->BROWSER_MOZILLA);
884
- return true;
885
- }
886
- return false;
887
- }
888
 
889
- /**
890
- * Determine if the browser is Lynx or not (last updated 1.7)
891
- * @return boolean True if the browser is Lynx otherwise false
892
- */
893
- function checkBrowserLynx() {
894
- if( stripos($this->_agent,'lynx') !== false ) {
895
- $aresult = explode('/',stristr($this->_agent,'Lynx'));
896
- $aversion = explode(' ',(isset($aresult[1])?$aresult[1]:""));
897
- $this->setVersion($aversion[0]);
898
- $this->setBrowser($this->BROWSER_LYNX);
899
- return true;
900
- }
901
- return false;
902
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
903
 
904
- /**
905
- * Determine if the browser is Amaya or not (last updated 1.7)
906
- * @return boolean True if the browser is Amaya otherwise false
907
- */
908
- function checkBrowserAmaya() {
909
- if( stripos($this->_agent,'amaya') !== false ) {
910
- $aresult = explode('/',stristr($this->_agent,'Amaya'));
911
- $aversion = explode(' ',$aresult[1]);
912
- $this->setVersion($aversion[0]);
913
- $this->setBrowser($this->BROWSER_AMAYA);
914
- return true;
915
- }
916
- return false;
917
- }
 
918
 
919
- /**
920
- * Determine if the browser is Safari or not (last updated 1.7)
921
- * @return boolean True if the browser is Safari otherwise false
922
- */
923
- function checkBrowserSafari() {
924
- if( stripos($this->_agent,'Safari') !== false && stripos($this->_agent,'iPhone') === false && stripos($this->_agent,'iPod') === false ) {
925
- $aresult = explode('/',stristr($this->_agent,'Version'));
926
- if( isset($aresult[1]) ) {
927
- $aversion = explode(' ',$aresult[1]);
928
- $this->setVersion($aversion[0]);
929
- }
930
- else {
931
- $this->setVersion($this->VERSION_UNKNOWN);
932
- }
933
- $this->setBrowser($this->BROWSER_SAFARI);
934
- return true;
935
- }
936
- return false;
937
- }
938
 
939
- /**
940
- * Determine if the browser is iPhone or not (last updated 1.7)
941
- * @return boolean True if the browser is iPhone otherwise false
942
- */
943
- function checkBrowseriPhone() {
944
- if( stripos($this->_agent,'iPhone') !== false ) {
945
- $aresult = explode('/',stristr($this->_agent,'Version'));
946
- if( isset($aresult[1]) ) {
947
- $aversion = explode(' ',$aresult[1]);
948
- $this->setVersion($aversion[0]);
949
- }
950
- else {
951
- $this->setVersion($this->VERSION_UNKNOWN);
952
- }
953
- $this->setMobile(true);
954
- $this->setBrowser($this->BROWSER_IPHONE);
955
- return true;
956
- }
957
- return false;
958
- }
959
 
960
- /**
961
- * Determine if the browser is iPod or not (last updated 1.7)
962
- * @return boolean True if the browser is iPod otherwise false
963
- */
964
- function checkBrowseriPad() {
965
- if( stripos($this->_agent,'iPad') !== false ) {
966
- $aresult = explode('/',stristr($this->_agent,'Version'));
967
- if( isset($aresult[1]) ) {
968
- $aversion = explode(' ',$aresult[1]);
969
- $this->setVersion($aversion[0]);
970
- }
971
- else {
972
- $this->setVersion($this->VERSION_UNKNOWN);
973
- }
974
- $this->setMobile(true);
975
- $this->setBrowser($this->BROWSER_IPAD);
976
- return true;
977
- }
978
- return false;
979
- }
980
 
981
- /**
982
- * Determine if the browser is iPod or not (last updated 1.7)
983
- * @return boolean True if the browser is iPod otherwise false
984
- */
985
- function checkBrowseriPod() {
986
- if( stripos($this->_agent,'iPod') !== false ) {
987
- $aresult = explode('/',stristr($this->_agent,'Version'));
988
- if( isset($aresult[1]) ) {
989
- $aversion = explode(' ',$aresult[1]);
990
- $this->setVersion($aversion[0]);
991
- }
992
- else {
993
- $this->setVersion($this->VERSION_UNKNOWN);
994
- }
995
- $this->setMobile(true);
996
- $this->setBrowser($this->BROWSER_IPOD);
997
- return true;
998
- }
999
- return false;
1000
- }
1001
 
1002
- /**
1003
- * Determine if the browser is Android or not (last updated 1.7)
1004
- * @return boolean True if the browser is Android otherwise false
1005
- */
1006
- function checkBrowserAndroid() {
1007
- if( stripos($this->_agent,'Android') !== false ) {
1008
- $aresult = explode(' ',stristr($this->_agent,'Android'));
1009
- if( isset($aresult[1]) ) {
1010
- $aversion = explode(' ',$aresult[1]);
1011
- $this->setVersion($aversion[0]);
1012
- }
1013
- else {
1014
- $this->setVersion($this->VERSION_UNKNOWN);
1015
- }
1016
- $this->setMobile(true);
1017
- $this->setBrowser($this->BROWSER_ANDROID);
1018
- return true;
1019
- }
1020
- return false;
1021
- }
1022
 
1023
- /**
1024
- * Determine the user's platform (last updated 1.7)
1025
- */
1026
- function checkPlatform() {
1027
- if( stripos($this->_agent, 'windows') !== false ) {
1028
- $this->_platform = $this->PLATFORM_WINDOWS;
1029
- }
1030
- else if( stripos($this->_agent, 'iPad') !== false ) {
1031
- $this->_platform = $this->PLATFORM_IPAD;
1032
- }
1033
- else if( stripos($this->_agent, 'iPod') !== false ) {
1034
- $this->_platform = $this->PLATFORM_IPOD;
1035
- }
1036
- else if( stripos($this->_agent, 'iPhone') !== false ) {
1037
- $this->_platform = $this->PLATFORM_IPHONE;
1038
- }
1039
- elseif( stripos($this->_agent, 'mac') !== false ) {
1040
- $this->_platform = $this->PLATFORM_APPLE;
1041
- }
1042
- elseif( stripos($this->_agent, 'android') !== false ) {
1043
- $this->_platform = $this->PLATFORM_ANDROID;
1044
- }
1045
- elseif( stripos($this->_agent, 'linux') !== false ) {
1046
- $this->_platform = $this->PLATFORM_LINUX;
1047
- }
1048
- else if( stripos($this->_agent, 'Nokia') !== false ) {
1049
- $this->_platform = $this->PLATFORM_NOKIA;
1050
- }
1051
- else if( stripos($this->_agent, 'BlackBerry') !== false ) {
1052
- $this->_platform = $this->PLATFORM_BLACKBERRY;
1053
- }
1054
- elseif( stripos($this->_agent,'FreeBSD') !== false ) {
1055
- $this->_platform = $this->PLATFORM_FREEBSD;
1056
- }
1057
- elseif( stripos($this->_agent,'OpenBSD') !== false ) {
1058
- $this->_platform = $this->PLATFORM_OPENBSD;
1059
- }
1060
- elseif( stripos($this->_agent,'NetBSD') !== false ) {
1061
- $this->_platform = $this->PLATFORM_NETBSD;
1062
- }
1063
- elseif( stripos($this->_agent, 'OpenSolaris') !== false ) {
1064
- $this->_platform = $this->PLATFORM_OPENSOLARIS;
1065
- }
1066
- elseif( stripos($this->_agent, 'SunOS') !== false ) {
1067
- $this->_platform = $this->PLATFORM_SUNOS;
1068
- }
1069
- elseif( stripos($this->_agent, 'OS\/2') !== false ) {
1070
- $this->_platform = $this->PLATFORM_OS2;
1071
- }
1072
- elseif( stripos($this->_agent, 'BeOS') !== false ) {
1073
- $this->_platform = $this->PLATFORM_BEOS;
1074
- }
1075
- elseif( stripos($this->_agent, 'win') !== false ) {
1076
- $this->_platform = $this->PLATFORM_WINDOWS;
1077
- }
1078
 
1079
- }
1080
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1081
 
1082
- ?>
 
1
  <?php
2
+
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+
6
+ /**
7
+ * Modified to remove var
8
+ * Chris Christoff on 12/26/2012
9
+ * Changes: Changes vars to publics
10
+ *
11
+ * Modified to work for EDD by
12
+ * Chris Christoff on 12/23/2012
13
+ * Changes: Removed the browser string return and added spacing. Also removed return HTML formatting.
14
+ *
15
+ * Modified to add formatted User Agent string for EDD System Info by
16
+ * Chris Christoff on 12/23/2012
17
+ * Changes: Split user string and add formatting so we can print a nicely
18
+ * formatted user agent string on the EDD System Info
19
+ *
20
+ * File: Browser.php
21
+ * Author: Chris Schuld (http://chrisschuld.com/)
22
+ * Last Modified: August 20th, 2010
23
+ *
24
+ * @version 1.9
25
+ * @package PegasusPHP
26
+ *
27
+ * Copyright (C) 2008-2010 Chris Schuld (chris@chrisschuld.com)
28
+ *
29
+ * This program is free software; you can redistribute it and/or
30
+ * modify it under the terms of the GNU General Public License as
31
+ * published by the Free Software Foundation; either version 2 of
32
+ * the License, or (at your option) any later version.
33
+ *
34
+ * This program is distributed in the hope that it will be useful,
35
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37
+ * GNU General Public License for more details at:
38
+ * http://www.gnu.org/copyleft/gpl.html
39
+ *
40
+ *
41
+ * Typical Usage:
42
+ *
43
+ * $browser = new Browser();
44
+ * if( $browser->getBrowser() == Browser::BROWSER_FIREFOX && $browser->getVersion() >= 2 ) {
45
+ * echo 'You have FireFox version 2 or greater';
46
+ * }
47
+ *
48
+ * User Agents Sampled from: http://www.useragentstring.com/
49
+ *
50
+ * This implementation is based on the original work from Gary White
51
+ * http://apptools.com/phptools/browser/
52
+ *
53
+ * UPDATES:
54
+ *
55
+ * 2010-08-20 (v1.9):
56
+ * + Added MSN Explorer Browser (legacy)
57
+ * + Added Bing/MSN Robot (Thanks Rob MacDonald)
58
+ * + Added the Android Platform (PLATFORM_ANDROID)
59
+ * + Fixed issue with Android 1.6/2.2 (Thanks Tom Hirashima)
60
+ *
61
+ * 2010-04-27 (v1.8):
62
+ * + Added iPad Support
63
+ *
64
+ * 2010-03-07 (v1.7):
65
+ * + *MAJOR* Rebuild (preg_match and other "slow" routine removal(s))
66
+ * + Almost allof Gary's original code has been replaced
67
+ * + Large PHPUNIT testing environment created to validate new releases and additions
68
+ * + Added FreeBSD Platform
69
+ * + Added OpenBSD Platform
70
+ * + Added NetBSD Platform
71
+ * + Added SunOS Platform
72
+ * + Added OpenSolaris Platform
73
+ * + Added support of the Iceweazel Browser
74
+ * + Added isChromeFrame() call to check if chromeframe is in use
75
+ * + Moved the Opera check in front of the Firefox check due to legacy Opera User Agents
76
+ * + Added the __toString() method (Thanks Deano)
77
+ *
78
+ * 2009-11-15:
79
+ * + Updated the checkes for Firefox
80
+ * + Added the NOKIA platform
81
+ * + Added Checks for the NOKIA brower(s)
82
+ *
83
+ * 2009-11-08:
84
+ * + PHP 5.3 Support
85
+ * + Added support for BlackBerry OS and BlackBerry browser
86
+ * + Added support for the Opera Mini browser
87
+ * + Added additional documenation
88
+ * + Added support for isRobot() and isMobile()
89
+ * + Added support for Opera version 10
90
+ * + Added support for deprecated Netscape Navigator version 9
91
+ * + Added support for IceCat
92
+ * + Added support for Shiretoko
93
+ *
94
+ * 2010-04-27 (v1.8):
95
+ * + Added iPad Support
96
+ *
97
+ * 2009-08-18:
98
+ * + Updated to support PHP 5.3 - removed all deprecated function calls
99
+ * + Updated to remove all double quotes (") -- converted to single quotes (')
100
+ *
101
+ * 2009-04-27:
102
+ * + Updated the IE check to remove a typo and bug (thanks John)
103
+ *
104
+ * 2009-04-22:
105
+ * + Added detection for GoogleBot
106
+ * + Added detection for the W3C Validator.
107
+ * + Added detection for Yahoo! Slurp
108
+ *
109
+ * 2009-03-14:
110
+ * + Added detection for iPods.
111
+ * + Added Platform detection for iPhones
112
+ * + Added Platform detection for iPods
113
+ *
114
+ * 2009-02-16: (Rick Hale)
115
+ * + Added version detection for Android phones.
116
+ *
117
+ * 2008-12-09:
118
+ * + Removed unused constant
119
+ *
120
+ * 2008-11-07:
121
+ * + Added Google's Chrome to the detection list
122
+ * + Added isBrowser(string) to the list of functions special thanks to
123
+ * Daniel 'mavrick' Lang for the function concept (http://mavrick.id.au)
124
+ *
125
+ *
126
+ * Gary White noted: "Since browser detection is so unreliable, I am
127
+ * no longer maintaining this script. You are free to use and or
128
+ * modify/update it as you want, however the author assumes no
129
+ * responsibility for the accuracy of the detected values."
130
+ *
131
+ * Anyone experienced with Gary's script might be interested in these notes:
132
+ *
133
+ * Added class constants
134
+ * Added detection and version detection for Google's Chrome
135
+ * Updated the version detection for Amaya
136
+ * Updated the version detection for Firefox
137
+ * Updated the version detection for Lynx
138
+ * Updated the version detection for WebTV
139
+ * Updated the version detection for NetPositive
140
+ * Updated the version detection for IE
141
+ * Updated the version detection for OmniWeb
142
+ * Updated the version detection for iCab
143
+ * Updated the version detection for Safari
144
+ * Updated Safari to remove mobile devices (iPhone)
145
+ * Added detection for iPhone
146
+ * Added detection for robots
147
+ * Added detection for mobile devices
148
+ * Added detection for BlackBerry
149
+ * Removed Netscape checks (matches heavily with firefox & mozilla)
150
+ *
151
+ */
152
+
153
+ class Browser {
154
+ public $_agent = '';
155
+ public $_browser_name = '';
156
+ public $_version = '';
157
+ public $_platform = '';
158
+ public $_os = '';
159
+ public $_is_aol = false;
160
+ public $_is_mobile = false;
161
+ public $_is_robot = false;
162
+ public $_aol_version = '';
163
+
164
+ public $BROWSER_UNKNOWN = 'unknown';
165
+ public $VERSION_UNKNOWN = 'unknown';
166
+
167
+ public $BROWSER_OPERA = 'Opera'; // Http://www.opera.com/
168
+ public $BROWSER_OPERA_MINI = 'Opera Mini'; // Http://www.opera.com/mini/
169
+ public $BROWSER_WEBTV = 'WebTV'; // Http://www.webtv.net/pc/
170
+ public $BROWSER_IE = 'Internet Explorer'; // Http://www.microsoft.com/ie/
171
+ public $BROWSER_POCKET_IE = 'Pocket Internet Explorer'; // Http://en.wikipedia.org/wiki/Internet_Explorer_Mobile
172
+ public $BROWSER_KONQUEROR = 'Konqueror'; // Http://www.konqueror.org/
173
+ public $BROWSER_ICAB = 'iCab'; // Http://www.icab.de/
174
+ public $BROWSER_OMNIWEB = 'OmniWeb'; // Http://www.omnigroup.com/applications/omniweb/
175
+ public $BROWSER_FIREBIRD = 'Firebird'; // Http://www.ibphoenix.com/
176
+ public $BROWSER_FIREFOX = 'Firefox'; // Http://www.mozilla.com/en-US/firefox/firefox.html
177
+ public $BROWSER_ICEWEASEL = 'Iceweasel'; // Http://www.geticeweasel.org/
178
+ public $BROWSER_SHIRETOKO = 'Shiretoko'; // Http://wiki.mozilla.org/Projects/shiretoko
179
+ public $BROWSER_MOZILLA = 'Mozilla'; // Http://www.mozilla.com/en-US/
180
+ public $BROWSER_AMAYA = 'Amaya'; // Http://www.w3.org/Amaya/
181
+ public $BROWSER_LYNX = 'Lynx'; // Http://en.wikipedia.org/wiki/Lynx
182
+ public $BROWSER_SAFARI = 'Safari'; // Http://apple.com
183
+ public $BROWSER_IPHONE = 'iPhone'; // Http://apple.com
184
+ public $BROWSER_IPOD = 'iPod'; // Http://apple.com
185
+ public $BROWSER_IPAD = 'iPad'; // Http://apple.com
186
+ public $BROWSER_CHROME = 'Chrome'; // Http://www.google.com/chrome
187
+ public $BROWSER_ANDROID = 'Android'; // Http://www.android.com/
188
+ public $BROWSER_GOOGLEBOT = 'GoogleBot'; // Http://en.wikipedia.org/wiki/Googlebot
189
+ public $BROWSER_SLURP = 'Yahoo! Slurp'; // Http://en.wikipedia.org/wiki/Yahoo!_Slurp
190
+ public $BROWSER_W3CVALIDATOR = 'W3C Validator'; // Http://validator.w3.org/
191
+ public $BROWSER_BLACKBERRY = 'BlackBerry'; // Http://www.blackberry.com/
192
+ public $BROWSER_ICECAT = 'IceCat'; // Http://en.wikipedia.org/wiki/GNU_IceCat
193
+ public $BROWSER_NOKIA_S60 = 'Nokia S60 OSS Browser'; // Http://en.wikipedia.org/wiki/Web_Browser_for_S60
194
+ public $BROWSER_NOKIA = 'Nokia Browser'; // * all other WAP-based browsers on the Nokia Platform
195
+ public $BROWSER_MSN = 'MSN Browser'; // Http://explorer.msn.com/
196
+ public $BROWSER_MSNBOT = 'MSN Bot'; // Http://search.msn.com/msnbot.htm
197
+ // Http://en.wikipedia.org/wiki/Msnbot (used for Bing as well)
198
+
199
+ public $BROWSER_NETSCAPE_NAVIGATOR = 'Netscape Navigator'; // Http://browser.netscape.com/ (DEPRECATED)
200
+ public $BROWSER_GALEON = 'Galeon'; // Http://galeon.sourceforge.net/ (DEPRECATED)
201
+ public $BROWSER_NETPOSITIVE = 'NetPositive'; // Http://en.wikipedia.org/wiki/NetPositive (DEPRECATED)
202
+ public $BROWSER_PHOENIX = 'Phoenix'; // Http://en.wikipedia.org/wiki/History_of_Mozilla_Firefox (DEPRECATED)
203
+
204
+ public $PLATFORM_UNKNOWN = 'unknown';
205
+ public $PLATFORM_WINDOWS = 'Windows';
206
+ public $PLATFORM_WINDOWS_CE = 'Windows CE';
207
+ public $PLATFORM_APPLE = 'Apple';
208
+ public $PLATFORM_LINUX = 'Linux';
209
+ public $PLATFORM_OS2 = 'OS/2';
210
+ public $PLATFORM_BEOS = 'BeOS';
211
+ public $PLATFORM_IPHONE = 'iPhone';
212
+ public $PLATFORM_IPOD = 'iPod';
213
+ public $PLATFORM_IPAD = 'iPad';
214
+ public $PLATFORM_BLACKBERRY = 'BlackBerry';
215
+ public $PLATFORM_NOKIA = 'Nokia';
216
+ public $PLATFORM_FREEBSD = 'FreeBSD';
217
+ public $PLATFORM_OPENBSD = 'OpenBSD';
218
+ public $PLATFORM_NETBSD = 'NetBSD';
219
+ public $PLATFORM_SUNOS = 'SunOS';
220
+ public $PLATFORM_OPENSOLARIS = 'OpenSolaris';
221
+ public $PLATFORM_ANDROID = 'Android';
222
+
223
+ public $OPERATING_SYSTEM_UNKNOWN = 'unknown';
224
+
225
+ function Browser( $useragent="" ) {
226
+ $this->reset();
227
+ if ( $useragent != "" ) {
228
+ $this->setUserAgent( $useragent );
229
+ } else {
230
+ $this->determine();
231
+ }
232
+ }
233
+
234
  /**
235
+ * Reset all properties
236
+ */
237
+ function reset() {
238
+ $this->_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : "";
239
+ $this->_browser_name = $this->BROWSER_UNKNOWN;
240
+ $this->_version = $this->VERSION_UNKNOWN;
241
+ $this->_platform = $this->PLATFORM_UNKNOWN;
242
+ $this->_os = $this->OPERATING_SYSTEM_UNKNOWN;
243
+ $this->_is_aol = false;
244
+ $this->_is_mobile = false;
245
+ $this->_is_robot = false;
246
+ $this->_aol_version = $this->VERSION_UNKNOWN;
247
+ }
248
+
249
+ /**
250
+ * Check to see if the specific browser is valid
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  *
252
+ * @param string $browserName
253
+ * @return True if the browser is the specified browser
254
+ */
255
+ function isBrowser( $browserName ) { return 0 == strcasecmp( $this->_browser_name, trim( $browserName ) ); }
256
+
257
+ /**
258
+ * The name of the browser. All return types are from the class contants
259
  *
260
+ * @return string Name of the browser
261
+ */
262
+ function getBrowser() { return $this->_browser_name; }
263
+ /**
264
+ * Set the name of the browser
265
  *
266
+ * @param unknown $browser The name of the Browser
267
+ */
268
+ function setBrowser( $browser ) { return $this->_browser_name = $browser; }
269
+ /**
270
+ * The name of the platform. All return types are from the class contants
271
  *
272
+ * @return string Name of the browser
273
+ */
274
+ function getPlatform() { return $this->_platform; }
275
+ /**
276
+ * Set the name of the platform
 
 
 
 
 
 
 
 
277
  *
278
+ * @param unknown $platform The name of the Platform
279
+ */
280
+ function setPlatform( $platform ) { return $this->_platform = $platform; }
281
+ /**
282
+ * The version of the browser.
283
  *
284
+ * @return string Version of the browser (will only contain alpha-numeric characters and a period)
285
+ */
286
+ function getVersion() { return $this->_version; }
287
+ /**
288
+ * Set the version of the browser
 
 
 
 
 
289
  *
290
+ * @param unknown $version The version of the Browser
291
+ */
292
+ function setVersion( $version ) { $this->_version = preg_replace( '/[^0-9,.,a-z,A-Z-]/', '', $version ); }
293
+ /**
294
+ * The version of AOL.
295
  *
296
+ * @return string Version of AOL (will only contain alpha-numeric characters and a period)
297
+ */
298
+ function getAolVersion() { return $this->_aol_version; }
299
+ /**
300
+ * Set the version of AOL
301
  *
302
+ * @param unknown $version The version of AOL
303
+ */
304
+ function setAolVersion( $version ) { $this->_aol_version = preg_replace( '/[^0-9,.,a-z,A-Z]/', '', $version ); }
305
+ /**
306
+ * Is the browser from AOL?
307
  *
308
+ * @return boolean True if the browser is from AOL otherwise false
309
+ */
310
+ function isAol() { return $this->_is_aol; }
311
+ /**
312
+ * Is the browser from a mobile device?
313
  *
314
+ * @return boolean True if the browser is from a mobile device otherwise false
315
+ */
316
+ function isMobile() { return $this->_is_mobile; }
317
+ /**
318
+ * Is the browser from a robot (ex Slurp,GoogleBot)?
319
  *
320
+ * @return boolean True if the browser is from a robot otherwise false
321
+ */
322
+ function isRobot() { return $this->_is_robot; }
323
+ /**
324
+ * Set the browser to be from AOL
325
  *
326
+ * @param unknown $isAol
327
+ */
328
+ function setAol( $isAol ) { $this->_is_aol = $isAol; }
329
+ /**
330
+ * Set the Browser to be mobile
331
  *
332
+ * @param boolean $value is the browser a mobile brower or not
333
+ */
334
+ function setMobile( $value=true ) { $this->_is_mobile = $value; }
335
+ /**
336
+ * Set the Browser to be a robot
337
  *
338
+ * @param boolean $value is the browser a robot or not
339
+ */
340
+ function setRobot( $value=true ) { $this->_is_robot = $value; }
341
+ /**
342
+ * Get the user agent value in use to determine the browser
343
  *
344
+ * @return string The user agent from the HTTP header
345
+ */
346
+ function getUserAgent() { return $this->_agent; }
347
+ /**
348
+ * Set the user agent value (the construction will use the HTTP header value - this will overwrite it)
349
  *
350
+ * @param unknown $agent_string The value for the User Agent
351
+ */
352
+ function setUserAgent( $agent_string ) {
353
+ $this->reset();
354
+ $this->_agent = $agent_string;
355
+ $this->determine();
356
+ }
357
+ /**
358
+ * Used to determine if the browser is actually "chromeframe"
359
  *
360
+ * @since 1.7
361
+ * @return boolean True if the browser is using chromeframe
362
+ */
363
+ function isChromeFrame() {
364
+ return strpos( $this->_agent, "chromeframe" ) !== false;
365
+ }
366
+ /**
367
+ * Returns a formatted string with a summary of the details of the browser.
 
 
 
 
 
 
 
 
 
368
  *
369
+ * @return string formatted string with a summary of the browser
370
  */
371
+ function __toString() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  $text1 = $this->getUserAgent(); //grabs the UA (user agent) string
373
+ $UAline1 = substr( $text1, 0, 32 ); //the first line we print should only be the first 32 characters of the UA string
374
  $text2 = $this->getUserAgent();//now we grab it again and save it to a string
375
+ $towrapUA = str_replace( $UAline1, '', $text2 );//the rest of the printoff (other than first line) is equivolent
376
  // To the whole string minus the part we printed off. IE
377
  // User Agent: thefirst32charactersfromUAline1
378
  // the rest of it is now stored in
379
  // $text2 to be printed off
380
  // But we need to add spaces before each line that is split other than line 1
381
  $space = '';
382
+ for ( $i = 0; $i < 25; $i++ ) {
383
+ $space .= ' ';
384
  }
385
  // Now we split the remaining string of UA ($text2) into lines that are prefixed by spaces for formatting
386
+ $wordwrapped = chunk_split( $towrapUA, 32, "\n $space" );
387
+ return "Platform: {$this->getPlatform()} \n".
388
+ "Browser Name: {$this->getBrowser()} \n" .
389
+ "Browser Version: {$this->getVersion()} \n" .
390
+ "User Agent String: $UAline1 \n\t\t\t " .
391
+ "$wordwrapped";
392
+ }
393
+ /**
394
+ * Protected routine to calculate and determine what the browser is in use (including platform)
395
+ */
396
+ function determine() {
397
+ $this->checkPlatform();
398
+ $this->checkBrowsers();
399
+ $this->checkForAol();
400
+ }
401
+ /**
402
+ * Protected routine to determine the browser type
403
+ *
404
+ * @return boolean True if the browser was detected otherwise false
405
+ */
406
+ function checkBrowsers() {
407
+ return (
408
+ // Well-known, well-used
409
+ // Special Notes:
410
+ // (1) Opera must be checked before FireFox due to the odd
411
+ // user agents used in some older versions of Opera
412
+ // (2) WebTV is strapped onto Internet Explorer so we must
413
+ // check for WebTV before IE
414
+ // (3) (deprecated) Galeon is based on Firefox and needs to be
415
+ // tested before Firefox is tested
416
+ // (4) OmniWeb is based on Safari so OmniWeb check must occur
417
+ // before Safari
418
+ // (5) Netscape 9+ is based on Firefox so Netscape checks
419
+ // before FireFox are necessary
420
+ $this->checkBrowserWebTv() ||
421
+ $this->checkBrowserInternetExplorer() ||
422
+ $this->checkBrowserOpera() ||
423
+ $this->checkBrowserGaleon() ||
424
+ $this->checkBrowserNetscapeNavigator9Plus() ||
425
+ $this->checkBrowserFirefox() ||
426
+ $this->checkBrowserChrome() ||
427
+ $this->checkBrowserOmniWeb() ||
428
 
429
+ // Common mobile
430
+ $this->checkBrowserAndroid() ||
431
+ $this->checkBrowseriPad() ||
432
+ $this->checkBrowseriPod() ||
433
+ $this->checkBrowseriPhone() ||
434
+ $this->checkBrowserBlackBerry() ||
435
+ $this->checkBrowserNokia() ||
436
 
437
+ // Common bots
438
+ $this->checkBrowserGoogleBot() ||
439
+ $this->checkBrowserMSNBot() ||
440
+ $this->checkBrowserSlurp() ||
441
 
442
+ // WebKit base check (post mobile and others)
443
+ $this->checkBrowserSafari() ||
444
 
445
+ // Everyone else
446
+ $this->checkBrowserNetPositive() ||
447
+ $this->checkBrowserFirebird() ||
448
+ $this->checkBrowserKonqueror() ||
449
+ $this->checkBrowserIcab() ||
450
+ $this->checkBrowserPhoenix() ||
451
+ $this->checkBrowserAmaya() ||
452
+ $this->checkBrowserLynx() ||
453
 
454
+ $this->checkBrowserShiretoko() ||
455
+ $this->checkBrowserIceCat() ||
456
+ $this->checkBrowserW3CValidator() ||
457
+ $this->checkBrowserMozilla() /* Mozilla is such an open standard that you must check it last */
458
+ );
459
+ }
460
 
461
+ /**
462
+ * Determine if the user is using a BlackBerry (last updated 1.7)
463
+ *
464
+ * @return boolean True if the browser is the BlackBerry browser otherwise false
465
+ */
466
+ function checkBrowserBlackBerry() {
467
+ if ( stripos( $this->_agent, 'blackberry' ) !== false ) {
468
+ $aresult = explode( "/", stristr( $this->_agent, "BlackBerry" ) );
469
+ $aversion = explode( ' ', $aresult[1] );
470
+ $this->setVersion( $aversion[0] );
471
+ $this->_browser_name = $this->BROWSER_BLACKBERRY;
472
+ $this->setMobile( true );
473
+ return true;
474
+ }
475
+ return false;
476
+ }
477
 
478
+ /**
479
+ * Determine if the user is using an AOL User Agent (last updated 1.7)
480
+ *
481
+ * @return boolean True if the browser is from AOL otherwise false
482
+ */
483
+ function checkForAol() {
484
+ $this->setAol( false );
485
+ $this->setAolVersion( $this->VERSION_UNKNOWN );
486
 
487
+ if ( stripos( $this->_agent, 'aol' ) !== false ) {
488
+ $aversion = explode( ' ', stristr( $this->_agent, 'AOL' ) );
489
+ $this->setAol( true );
490
+ $this->setAolVersion( preg_replace( '/[^0-9\.a-z]/i', '', $aversion[1] ) );
491
+ return true;
492
+ }
493
+ return false;
494
+ }
495
 
496
+ /**
497
+ * Determine if the browser is the GoogleBot or not (last updated 1.7)
498
+ *
499
+ * @return boolean True if the browser is the GoogletBot otherwise false
500
+ */
501
+ function checkBrowserGoogleBot() {
502
+ if ( stripos( $this->_agent, 'googlebot' ) !== false ) {
503
+ $aresult = explode( '/', stristr( $this->_agent, 'googlebot' ) );
504
+ $aversion = explode( ' ', $aresult[1] );
505
+ $this->setVersion( str_replace( ';', '', $aversion[0] ) );
506
+ $this->_browser_name = $this->BROWSER_GOOGLEBOT;
507
+ $this->setRobot( true );
508
+ return true;
509
+ }
510
+ return false;
511
+ }
512
 
513
+ /**
514
+ * Determine if the browser is the MSNBot or not (last updated 1.9)
515
+ *
516
+ * @return boolean True if the browser is the MSNBot otherwise false
517
+ */
518
+ function checkBrowserMSNBot() {
519
+ if ( stripos( $this->_agent, "msnbot" ) !== false ) {
520
+ $aresult = explode( "/", stristr( $this->_agent, "msnbot" ) );
521
+ $aversion = explode( " ", $aresult[1] );
522
+ $this->setVersion( str_replace( ";", "", $aversion[0] ) );
523
+ $this->_browser_name = $this->BROWSER_MSNBOT;
524
+ $this->setRobot( true );
525
+ return true;
 
526
  }
527
+ return false;
528
+ }
529
 
530
+ /**
531
+ * Determine if the browser is the W3C Validator or not (last updated 1.7)
532
+ *
533
+ * @return boolean True if the browser is the W3C Validator otherwise false
534
+ */
535
+ function checkBrowserW3CValidator() {
536
+ if ( stripos( $this->_agent, 'W3C-checklink' ) !== false ) {
537
+ $aresult = explode( '/', stristr( $this->_agent, 'W3C-checklink' ) );
538
+ $aversion = explode( ' ', $aresult[1] );
539
+ $this->setVersion( $aversion[0] );
540
+ $this->_browser_name = $this->BROWSER_W3CVALIDATOR;
541
+ return true;
542
+ } else if ( stripos( $this->_agent, 'W3C_Validator' ) !== false ) {
543
+ // Some of the Validator versions do not delineate w/ a slash - add it back in
544
+ $ua = str_replace( "W3C_Validator ", "W3C_Validator/", $this->_agent );
545
+ $aresult = explode( '/', stristr( $ua, 'W3C_Validator' ) );
546
+ $aversion = explode( ' ', $aresult[1] );
547
+ $this->setVersion( $aversion[0] );
548
+ $this->_browser_name = $this->BROWSER_W3CVALIDATOR;
549
+ return true;
550
+ }
551
+ return false;
552
+ }
553
 
554
+ /**
555
+ * Determine if the browser is the Yahoo! Slurp Robot or not (last updated 1.7)
556
+ *
557
+ * @return boolean True if the browser is the Yahoo! Slurp Robot otherwise false
558
+ */
559
+ function checkBrowserSlurp() {
560
+ if ( stripos( $this->_agent, 'slurp' ) !== false ) {
561
+ $aresult = explode( '/', stristr( $this->_agent, 'Slurp' ) );
562
+ $aversion = explode( ' ', $aresult[1] );
563
+ $this->setVersion( $aversion[0] );
564
+ $this->_browser_name = $this->BROWSER_SLURP;
565
+ $this->setRobot( true );
566
+ $this->setMobile( false );
567
+ return true;
568
+ }
569
+ return false;
570
+ }
571
 
572
+ /**
573
+ * Determine if the browser is Internet Explorer or not (last updated 1.7)
574
+ *
575
+ * @return boolean True if the browser is Internet Explorer otherwise false
576
+ */
577
+ function checkBrowserInternetExplorer() {
578
 
579
+ // Test for v1 - v1.5 IE
580
+ if ( stripos( $this->_agent, 'microsoft internet explorer' ) !== false ) {
581
+ $this->setBrowser( $this->BROWSER_IE );
582
+ $this->setVersion( '1.0' );
583
+ $aresult = stristr( $this->_agent, '/' );
584
+ if ( preg_match( '/308|425|426|474|0b1/i', $aresult ) ) {
585
+ $this->setVersion( '1.5' );
586
+ }
587
+ return true;
588
+ }
589
+ // Test for versions > 1.5
590
+ else if ( stripos( $this->_agent, 'msie' ) !== false && stripos( $this->_agent, 'opera' ) === false ) {
591
+ // See if the browser is the odd MSN Explorer
592
+ if ( stripos( $this->_agent, 'msnb' ) !== false ) {
593
+ $aresult = explode( ' ', stristr( str_replace( ';', '; ', $this->_agent ), 'MSN' ) );
594
+ $this->setBrowser( $this->BROWSER_MSN );
595
+ $this->setVersion( str_replace( array( '(', ')', ';' ), '', $aresult[1] ) );
596
  return true;
597
+ }
598
+ $aresult = explode( ' ', stristr( str_replace( ';', '; ', $this->_agent ), 'msie' ) );
599
+ $this->setBrowser( $this->BROWSER_IE );
600
+ $this->setVersion( str_replace( array( '(', ')', ';' ), '', $aresult[1] ) );
601
+ return true;
602
+ }
603
+ // Test for Pocket IE
604
+ else if ( stripos( $this->_agent, 'mspie' ) !== false || stripos( $this->_agent, 'pocket' ) !== false ) {
605
+ $aresult = explode( ' ', stristr( $this->_agent, 'mspie' ) );
606
+ $this->setPlatform( $this->PLATFORM_WINDOWS_CE );
607
+ $this->setBrowser( $this->BROWSER_POCKET_IE );
608
+ $this->setMobile( true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
609
 
610
+ if ( stripos( $this->_agent, 'mspie' ) !== false ) {
611
+ $this->setVersion( $aresult[1] );
612
+ } else {
613
+ $aversion = explode( '/', $this->_agent );
614
+ $this->setVersion( $aversion[1] );
615
+ }
616
+ return true;
617
+ }
618
+ return false;
619
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
620
 
621
+ /**
622
+ * Determine if the browser is Opera or not (last updated 1.7)
623
+ *
624
+ * @return boolean True if the browser is Opera otherwise false
625
+ */
626
+ function checkBrowserOpera() {
627
+ if ( stripos( $this->_agent, 'opera mini' ) !== false ) {
628
+ $resultant = stristr( $this->_agent, 'opera mini' );
629
+ if ( preg_match( '/\//', $resultant ) ) {
630
+ $aresult = explode( '/', $resultant );
631
+ $aversion = explode( ' ', $aresult[1] );
632
+ $this->setVersion( $aversion[0] );
633
+ } else {
634
+ $aversion = explode( ' ', stristr( $resultant, 'opera mini' ) );
635
+ $this->setVersion( $aversion[1] );
636
+ }
637
+ $this->_browser_name = $this->BROWSER_OPERA_MINI;
638
+ $this->setMobile( true );
639
+ return true;
640
+ } else if ( stripos( $this->_agent, 'opera' ) !== false ) {
641
+ $resultant = stristr( $this->_agent, 'opera' );
642
+ if ( preg_match( '/Version\/(10.*)$/', $resultant, $matches ) ) {
643
+ $this->setVersion( $matches[1] );
644
+ } else if ( preg_match( '/\//', $resultant ) ) {
645
+ $aresult = explode( '/', str_replace( "(", " ", $resultant ) );
646
+ $aversion = explode( ' ', $aresult[1] );
647
+ $this->setVersion( $aversion[0] );
648
+ } else {
649
+ $aversion = explode( ' ', stristr( $resultant, 'opera' ) );
650
+ $this->setVersion( isset( $aversion[1] )?$aversion[1]:"" );
651
+ }
652
+ $this->_browser_name = $this->BROWSER_OPERA;
653
+ return true;
654
+ }
655
+ return false;
656
+ }
657
 
658
+ /**
659
+ * Determine if the browser is Chrome or not (last updated 1.7)
660
+ *
661
+ * @return boolean True if the browser is Chrome otherwise false
662
+ */
663
+ function checkBrowserChrome() {
664
+ if ( stripos( $this->_agent, 'Chrome' ) !== false ) {
665
+ $aresult = explode( '/', stristr( $this->_agent, 'Chrome' ) );
666
+ $aversion = explode( ' ', $aresult[1] );
667
+ $this->setVersion( $aversion[0] );
668
+ $this->setBrowser( $this->BROWSER_CHROME );
669
+ return true;
670
+ }
671
+ return false;
672
+ }
673
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
674
 
675
+ /**
676
+ * Determine if the browser is WebTv or not (last updated 1.7)
677
+ *
678
+ * @return boolean True if the browser is WebTv otherwise false
679
+ */
680
+ function checkBrowserWebTv() {
681
+ if ( stripos( $this->_agent, 'webtv' ) !== false ) {
682
+ $aresult = explode( '/', stristr( $this->_agent, 'webtv' ) );
683
+ $aversion = explode( ' ', $aresult[1] );
684
+ $this->setVersion( $aversion[0] );
685
+ $this->setBrowser( $this->BROWSER_WEBTV );
686
+ return true;
687
+ }
688
+ return false;
689
+ }
690
 
691
+ /**
692
+ * Determine if the browser is NetPositive or not (last updated 1.7)
693
+ *
694
+ * @return boolean True if the browser is NetPositive otherwise false
695
+ */
696
+ function checkBrowserNetPositive() {
697
+ if ( stripos( $this->_agent, 'NetPositive' ) !== false ) {
698
+ $aresult = explode( '/', stristr( $this->_agent, 'NetPositive' ) );
699
+ $aversion = explode( ' ', $aresult[1] );
700
+ $this->setVersion( str_replace( array( '(', ')', ';' ), '', $aversion[0] ) );
701
+ $this->setBrowser( $this->BROWSER_NETPOSITIVE );
702
+ return true;
703
+ }
704
+ return false;
705
+ }
706
 
707
+ /**
708
+ * Determine if the browser is Galeon or not (last updated 1.7)
709
+ *
710
+ * @return boolean True if the browser is Galeon otherwise false
711
+ */
712
+ function checkBrowserGaleon() {
713
+ if ( stripos( $this->_agent, 'galeon' ) !== false ) {
714
+ $aresult = explode( ' ', stristr( $this->_agent, 'galeon' ) );
715
+ $aversion = explode( '/', $aresult[0] );
716
+ $this->setVersion( $aversion[1] );
717
+ $this->setBrowser( $this->BROWSER_GALEON );
718
+ return true;
719
+ }
720
+ return false;
721
+ }
722
 
723
+ /**
724
+ * Determine if the browser is Konqueror or not (last updated 1.7)
725
+ *
726
+ * @return boolean True if the browser is Konqueror otherwise false
727
+ */
728
+ function checkBrowserKonqueror() {
729
+ if ( stripos( $this->_agent, 'Konqueror' ) !== false ) {
730
+ $aresult = explode( ' ', stristr( $this->_agent, 'Konqueror' ) );
731
+ $aversion = explode( '/', $aresult[0] );
732
+ $this->setVersion( $aversion[1] );
733
+ $this->setBrowser( $this->BROWSER_KONQUEROR );
734
+ return true;
735
+ }
736
+ return false;
737
+ }
738
 
739
+ /**
740
+ * Determine if the browser is iCab or not (last updated 1.7)
741
+ *
742
+ * @return boolean True if the browser is iCab otherwise false
743
+ */
744
+ function checkBrowserIcab() {
745
+ if ( stripos( $this->_agent, 'icab' ) !== false ) {
746
+ $aversion = explode( ' ', stristr( str_replace( '/', ' ', $this->_agent ), 'icab' ) );
747
+ $this->setVersion( $aversion[1] );
748
+ $this->setBrowser( $this->BROWSER_ICAB );
749
+ return true;
750
+ }
751
+ return false;
752
+ }
753
 
754
+ /**
755
+ * Determine if the browser is OmniWeb or not (last updated 1.7)
756
+ *
757
+ * @return boolean True if the browser is OmniWeb otherwise false
758
+ */
759
+ function checkBrowserOmniWeb() {
760
+ if ( stripos( $this->_agent, 'omniweb' ) !== false ) {
761
+ $aresult = explode( '/', stristr( $this->_agent, 'omniweb' ) );
762
+ $aversion = explode( ' ', isset( $aresult[1] )?$aresult[1]:"" );
763
+ $this->setVersion( $aversion[0] );
764
+ $this->setBrowser( $this->BROWSER_OMNIWEB );
765
+ return true;
766
+ }
767
+ return false;
768
+ }
769
 
770
+ /**
771
+ * Determine if the browser is Phoenix or not (last updated 1.7)
772
+ *
773
+ * @return boolean True if the browser is Phoenix otherwise false
774
+ */
775
+ function checkBrowserPhoenix() {
776
+ if ( stripos( $this->_agent, 'Phoenix' ) !== false ) {
777
+ $aversion = explode( '/', stristr( $this->_agent, 'Phoenix' ) );
778
+ $this->setVersion( $aversion[1] );
779
+ $this->setBrowser( $this->BROWSER_PHOENIX );
780
+ return true;
781
+ }
782
+ return false;
783
+ }
784
 
785
+ /**
786
+ * Determine if the browser is Firebird or not (last updated 1.7)
787
+ *
788
+ * @return boolean True if the browser is Firebird otherwise false
789
+ */
790
+ function checkBrowserFirebird() {
791
+ if ( stripos( $this->_agent, 'Firebird' ) !== false ) {
792
+ $aversion = explode( '/', stristr( $this->_agent, 'Firebird' ) );
793
+ $this->setVersion( $aversion[1] );
794
+ $this->setBrowser( $this->BROWSER_FIREBIRD );
795
+ return true;
796
+ }
797
+ return false;
798
+ }
 
 
 
 
799
 
800
+ /**
801
+ * Determine if the browser is Netscape Navigator 9+ or not (last updated 1.7)
802
+ * NOTE: (http://browser.netscape.com/ - Official support ended on March 1st, 2008)
803
+ *
804
+ * @return boolean True if the browser is Netscape Navigator 9+ otherwise false
805
+ */
806
+ function checkBrowserNetscapeNavigator9Plus() {
807
+ if ( stripos( $this->_agent, 'Firefox' ) !== false && preg_match( '/Navigator\/([^ ]*)/i', $this->_agent, $matches ) ) {
808
+ $this->setVersion( $matches[1] );
809
+ $this->setBrowser( $this->BROWSER_NETSCAPE_NAVIGATOR );
810
+ return true;
811
+ } else if ( stripos( $this->_agent, 'Firefox' ) === false && preg_match( '/Netscape6?\/([^ ]*)/i', $this->_agent, $matches ) ) {
812
+ $this->setVersion( $matches[1] );
813
+ $this->setBrowser( $this->BROWSER_NETSCAPE_NAVIGATOR );
814
+ return true;
815
+ }
816
+ return false;
817
+ }
818
 
819
+ /**
820
+ * Determine if the browser is Shiretoko or not (https://wiki.mozilla.org/Projects/shiretoko) (last updated 1.7)
821
+ *
822
+ * @return boolean True if the browser is Shiretoko otherwise false
823
+ */
824
+ function checkBrowserShiretoko() {
825
+ if ( stripos( $this->_agent, 'Mozilla' ) !== false && preg_match( '/Shiretoko\/([^ ]*)/i', $this->_agent, $matches ) ) {
826
+ $this->setVersion( $matches[1] );
827
+ $this->setBrowser( $this->BROWSER_SHIRETOKO );
828
+ return true;
829
+ }
830
+ return false;
831
+ }
832
 
833
+ /**
834
+ * Determine if the browser is Ice Cat or not (http://en.wikipedia.org/wiki/GNU_IceCat) (last updated 1.7)
835
+ *
836
+ * @return boolean True if the browser is Ice Cat otherwise false
837
+ */
838
+ function checkBrowserIceCat() {
839
+ if ( stripos( $this->_agent, 'Mozilla' ) !== false && preg_match( '/IceCat\/([^ ]*)/i', $this->_agent, $matches ) ) {
840
+ $this->setVersion( $matches[1] );
841
+ $this->setBrowser( $this->BROWSER_ICECAT );
842
+ return true;
843
+ }
844
+ return false;
845
+ }
 
 
 
 
 
846
 
847
+ /**
848
+ * Determine if the browser is Nokia or not (last updated 1.7)
849
+ *
850
+ * @return boolean True if the browser is Nokia otherwise false
851
+ */
852
+ function checkBrowserNokia() {
853
+ if ( preg_match( "/Nokia([^\/]+)\/([^ SP]+)/i", $this->_agent, $matches ) ) {
854
+ $this->setVersion( $matches[2] );
855
+ if ( stripos( $this->_agent, 'Series60' ) !== false || strpos( $this->_agent, 'S60' ) !== false ) {
856
+ $this->setBrowser( $this->BROWSER_NOKIA_S60 );
857
+ } else {
858
+ $this->setBrowser( $this->BROWSER_NOKIA );
 
 
 
 
859
  }
860
+ $this->setMobile( true );
861
+ return true;
862
+ }
863
+ return false;
864
+ }
865
 
866
+ /**
867
+ * Determine if the browser is Firefox or not (last updated 1.7)
868
+ *
869
+ * @return boolean True if the browser is Firefox otherwise false
870
+ */
871
+ function checkBrowserFirefox() {
872
+ if ( stripos( $this->_agent, 'safari' ) === false ) {
873
+ if ( preg_match( "/Firefox[\/ \(]([^ ;\)]+)/i", $this->_agent, $matches ) ) {
874
+ $this->setVersion( $matches[1] );
875
+ $this->setBrowser( $this->BROWSER_FIREFOX );
876
+ return true;
877
+ } else if ( preg_match( "/Firefox$/i", $this->_agent, $matches ) ) {
878
+ $this->setVersion( "" );
879
+ $this->setBrowser( $this->BROWSER_FIREFOX );
880
  return true;
881
  }
 
882
  }
883
+ return false;
884
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
885
 
886
+ /**
887
+ * Determine if the browser is Firefox or not (last updated 1.7)
888
+ *
889
+ * @return boolean True if the browser is Firefox otherwise false
890
+ */
891
+ function checkBrowserIceweasel() {
892
+ if ( stripos( $this->_agent, 'Iceweasel' ) !== false ) {
893
+ $aresult = explode( '/', stristr( $this->_agent, 'Iceweasel' ) );
894
+ $aversion = explode( ' ', $aresult[1] );
895
+ $this->setVersion( $aversion[0] );
896
+ $this->setBrowser( $this->BROWSER_ICEWEASEL );
897
+ return true;
898
+ }
899
+ return false;
900
+ }
901
+ /**
902
+ * Determine if the browser is Mozilla or not (last updated 1.7)
903
+ *
904
+ * @return boolean True if the browser is Mozilla otherwise false
905
+ */
906
+ function checkBrowserMozilla() {
907
+ if ( stripos( $this->_agent, 'mozilla' ) !== false && preg_match( '/rv:[0-9].[0-9][a-b]?/i', $this->_agent ) && stripos( $this->_agent, 'netscape' ) === false ) {
908
+ $aversion = explode( ' ', stristr( $this->_agent, 'rv:' ) );
909
+ preg_match( '/rv:[0-9].[0-9][a-b]?/i', $this->_agent, $aversion );
910
+ $this->setVersion( str_replace( 'rv:', '', $aversion[0] ) );
911
+ $this->setBrowser( $this->BROWSER_MOZILLA );
912
+ return true;
913
+ } else if ( stripos( $this->_agent, 'mozilla' ) !== false && preg_match( '/rv:[0-9]\.[0-9]/i', $this->_agent ) && stripos( $this->_agent, 'netscape' ) === false ) {
914
+ $aversion = explode( '', stristr( $this->_agent, 'rv:' ) );
915
+ $this->setVersion( str_replace( 'rv:', '', $aversion[0] ) );
916
+ $this->setBrowser( $this->BROWSER_MOZILLA );
917
+ return true;
918
+ } else if ( stripos( $this->_agent, 'mozilla' ) !== false && preg_match( '/mozilla\/([^ ]*)/i', $this->_agent, $matches ) && stripos( $this->_agent, 'netscape' ) === false ) {
919
+ $this->setVersion( $matches[1] );
920
+ $this->setBrowser( $this->BROWSER_MOZILLA );
921
+ return true;
922
+ }
923
+ return false;
924
+ }
925
 
926
+ /**
927
+ * Determine if the browser is Lynx or not (last updated 1.7)
928
+ *
929
+ * @return boolean True if the browser is Lynx otherwise false
930
+ */
931
+ function checkBrowserLynx() {
932
+ if ( stripos( $this->_agent, 'lynx' ) !== false ) {
933
+ $aresult = explode( '/', stristr( $this->_agent, 'Lynx' ) );
934
+ $aversion = explode( ' ', ( isset( $aresult[1] )?$aresult[1]:"" ) );
935
+ $this->setVersion( $aversion[0] );
936
+ $this->setBrowser( $this->BROWSER_LYNX );
937
+ return true;
938
+ }
939
+ return false;
940
+ }
941
 
942
+ /**
943
+ * Determine if the browser is Amaya or not (last updated 1.7)
944
+ *
945
+ * @return boolean True if the browser is Amaya otherwise false
946
+ */
947
+ function checkBrowserAmaya() {
948
+ if ( stripos( $this->_agent, 'amaya' ) !== false ) {
949
+ $aresult = explode( '/', stristr( $this->_agent, 'Amaya' ) );
950
+ $aversion = explode( ' ', $aresult[1] );
951
+ $this->setVersion( $aversion[0] );
952
+ $this->setBrowser( $this->BROWSER_AMAYA );
953
+ return true;
954
+ }
955
+ return false;
956
+ }
 
 
 
 
957
 
958
+ /**
959
+ * Determine if the browser is Safari or not (last updated 1.7)
960
+ *
961
+ * @return boolean True if the browser is Safari otherwise false
962
+ */
963
+ function checkBrowserSafari() {
964
+ if ( stripos( $this->_agent, 'Safari' ) !== false && stripos( $this->_agent, 'iPhone' ) === false && stripos( $this->_agent, 'iPod' ) === false ) {
965
+ $aresult = explode( '/', stristr( $this->_agent, 'Version' ) );
966
+ if ( isset( $aresult[1] ) ) {
967
+ $aversion = explode( ' ', $aresult[1] );
968
+ $this->setVersion( $aversion[0] );
969
+ } else {
970
+ $this->setVersion( $this->VERSION_UNKNOWN );
971
+ }
972
+ $this->setBrowser( $this->BROWSER_SAFARI );
973
+ return true;
974
+ }
975
+ return false;
976
+ }
 
977
 
978
+ /**
979
+ * Determine if the browser is iPhone or not (last updated 1.7)
980
+ *
981
+ * @return boolean True if the browser is iPhone otherwise false
982
+ */
983
+ function checkBrowseriPhone() {
984
+ if ( stripos( $this->_agent, 'iPhone' ) !== false ) {
985
+ $aresult = explode( '/', stristr( $this->_agent, 'Version' ) );
986
+ if ( isset( $aresult[1] ) ) {
987
+ $aversion = explode( ' ', $aresult[1] );
988
+ $this->setVersion( $aversion[0] );
989
+ } else {
990
+ $this->setVersion( $this->VERSION_UNKNOWN );
991
+ }
992
+ $this->setMobile( true );
993
+ $this->setBrowser( $this->BROWSER_IPHONE );
994
+ return true;
995
+ }
996
+ return false;
997
+ }
998
 
999
+ /**
1000
+ * Determine if the browser is iPod or not (last updated 1.7)
1001
+ *
1002
+ * @return boolean True if the browser is iPod otherwise false
1003
+ */
1004
+ function checkBrowseriPad() {
1005
+ if ( stripos( $this->_agent, 'iPad' ) !== false ) {
1006
+ $aresult = explode( '/', stristr( $this->_agent, 'Version' ) );
1007
+ if ( isset( $aresult[1] ) ) {
1008
+ $aversion = explode( ' ', $aresult[1] );
1009
+ $this->setVersion( $aversion[0] );
1010
+ } else {
1011
+ $this->setVersion( $this->VERSION_UNKNOWN );
1012
+ }
1013
+ $this->setMobile( true );
1014
+ $this->setBrowser( $this->BROWSER_IPAD );
1015
+ return true;
1016
+ }
1017
+ return false;
1018
+ }
1019
 
1020
+ /**
1021
+ * Determine if the browser is iPod or not (last updated 1.7)
1022
+ *
1023
+ * @return boolean True if the browser is iPod otherwise false
1024
+ */
1025
+ function checkBrowseriPod() {
1026
+ if ( stripos( $this->_agent, 'iPod' ) !== false ) {
1027
+ $aresult = explode( '/', stristr( $this->_agent, 'Version' ) );
1028
+ if ( isset( $aresult[1] ) ) {
1029
+ $aversion = explode( ' ', $aresult[1] );
1030
+ $this->setVersion( $aversion[0] );
1031
+ } else {
1032
+ $this->setVersion( $this->VERSION_UNKNOWN );
1033
+ }
1034
+ $this->setMobile( true );
1035
+ $this->setBrowser( $this->BROWSER_IPOD );
1036
+ return true;
1037
+ }
1038
+ return false;
1039
+ }
1040
 
1041
+ /**
1042
+ * Determine if the browser is Android or not (last updated 1.7)
1043
+ *
1044
+ * @return boolean True if the browser is Android otherwise false
1045
+ */
1046
+ function checkBrowserAndroid() {
1047
+ if ( stripos( $this->_agent, 'Android' ) !== false ) {
1048
+ $aresult = explode( ' ', stristr( $this->_agent, 'Android' ) );
1049
+ if ( isset( $aresult[1] ) ) {
1050
+ $aversion = explode( ' ', $aresult[1] );
1051
+ $this->setVersion( $aversion[0] );
1052
+ } else {
1053
+ $this->setVersion( $this->VERSION_UNKNOWN );
1054
+ }
1055
+ $this->setMobile( true );
1056
+ $this->setBrowser( $this->BROWSER_ANDROID );
1057
+ return true;
1058
+ }
1059
+ return false;
1060
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1061
 
1062
+ /**
1063
+ * Determine the user's platform (last updated 1.7)
1064
+ */
1065
+ function checkPlatform() {
1066
+ if ( stripos( $this->_agent, 'windows' ) !== false ) {
1067
+ $this->_platform = $this->PLATFORM_WINDOWS;
1068
+ } else if ( stripos( $this->_agent, 'iPad' ) !== false ) {
1069
+ $this->_platform = $this->PLATFORM_IPAD;
1070
+ } else if ( stripos( $this->_agent, 'iPod' ) !== false ) {
1071
+ $this->_platform = $this->PLATFORM_IPOD;
1072
+ } else if ( stripos( $this->_agent, 'iPhone' ) !== false ) {
1073
+ $this->_platform = $this->PLATFORM_IPHONE;
1074
+ } elseif ( stripos( $this->_agent, 'mac' ) !== false ) {
1075
+ $this->_platform = $this->PLATFORM_APPLE;
1076
+ } elseif ( stripos( $this->_agent, 'android' ) !== false ) {
1077
+ $this->_platform = $this->PLATFORM_ANDROID;
1078
+ } elseif ( stripos( $this->_agent, 'linux' ) !== false ) {
1079
+ $this->_platform = $this->PLATFORM_LINUX;
1080
+ } else if ( stripos( $this->_agent, 'Nokia' ) !== false ) {
1081
+ $this->_platform = $this->PLATFORM_NOKIA;
1082
+ } else if ( stripos( $this->_agent, 'BlackBerry' ) !== false ) {
1083
+ $this->_platform = $this->PLATFORM_BLACKBERRY;
1084
+ } elseif ( stripos( $this->_agent, 'FreeBSD' ) !== false ) {
1085
+ $this->_platform = $this->PLATFORM_FREEBSD;
1086
+ } elseif ( stripos( $this->_agent, 'OpenBSD' ) !== false ) {
1087
+ $this->_platform = $this->PLATFORM_OPENBSD;
1088
+ } elseif ( stripos( $this->_agent, 'NetBSD' ) !== false ) {
1089
+ $this->_platform = $this->PLATFORM_NETBSD;
1090
+ } elseif ( stripos( $this->_agent, 'OpenSolaris' ) !== false ) {
1091
+ $this->_platform = $this->PLATFORM_OPENSOLARIS;
1092
+ } elseif ( stripos( $this->_agent, 'SunOS' ) !== false ) {
1093
+ $this->_platform = $this->PLATFORM_SUNOS;
1094
+ } elseif ( stripos( $this->_agent, 'OS\/2' ) !== false ) {
1095
+ $this->_platform = $this->PLATFORM_OS2;
1096
+ } elseif ( stripos( $this->_agent, 'BeOS' ) !== false ) {
1097
+ $this->_platform = $this->PLATFORM_BEOS;
1098
+ } elseif ( stripos( $this->_agent, 'win' ) !== false ) {
1099
+ $this->_platform = $this->PLATFORM_WINDOWS;
1100
+ }
1101
 
1102
+ }
1103
+ }
includes/libraries/class-recursive-arrayaccess.php CHANGED
@@ -10,6 +10,9 @@
10
  * @since 3.6.0
11
  */
12
 
 
 
 
13
  /**
14
  * Recursive array class to allow multidimensional array access.
15
  *
@@ -69,7 +72,7 @@ class Recursive_ArrayAccess implements ArrayAccess {
69
  }
70
 
71
  /**
72
- * ArrayAccess Implementation
73
  **/
74
 
75
  /**
10
  * @since 3.6.0
11
  */
12
 
13
+ // Exit if accessed directly
14
+ if ( ! defined( 'ABSPATH' ) ) exit;
15
+
16
  /**
17
  * Recursive array class to allow multidimensional array access.
18
  *
72
  }
73
 
74
  /**
75
+ * ArrayAccess Implementation
76
  **/
77
 
78
  /**
includes/libraries/class-wp-session.php CHANGED
@@ -10,6 +10,9 @@
10
  * @since 3.7.0
11
  */
12
 
 
 
 
13
  /**
14
  * WordPress Session class for managing user session data.
15
  *
10
  * @since 3.7.0
11
  */
12
 
13
+ // Exit if accessed directly
14
+ if ( ! defined( 'ABSPATH' ) ) exit;
15
+
16
  /**
17
  * WordPress Session class for managing user session data.
18
  *
includes/libraries/fpdf/edd_pdf.php CHANGED
@@ -7,6 +7,9 @@
7
  * @since 1.1.4.0
8
  */
9
 
 
 
 
10
  class edd_pdf extends FPDF {
11
 
12
  var $widths;
7
  * @since 1.1.4.0
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( ! defined( 'ABSPATH' ) ) exit;
12
+
13
  class edd_pdf extends FPDF {
14
 
15
  var $widths;
includes/libraries/fpdf/fpdf.php CHANGED
@@ -7,6 +7,9 @@
7
  * @since 1.1.3.2
8
  */
9
 
 
 
 
10
  define( 'FPDF_VERSION', '1.7' );
11
 
12
  class FPDF {
@@ -860,7 +863,7 @@ class FPDF {
860
  $this->Error( 'This version of PHP is not supported' );
861
  if ( ini_get( 'mbstring.func_overload' ) & 2 )
862
  $this->Error( 'mbstring overloading must be disabled' );
863
- if ( get_magic_quotes_runtime() )
864
  @set_magic_quotes_runtime( 0 );
865
  }
866
 
7
  * @since 1.1.3.2
8
  */
9
 
10
+ // Exit if accessed directly
11
+ if ( ! defined( 'ABSPATH' ) ) exit;
12
+
13
  define( 'FPDF_VERSION', '1.7' );
14
 
15
  class FPDF {
863
  $this->Error( 'This version of PHP is not supported' );
864
  if ( ini_get( 'mbstring.func_overload' ) & 2 )
865
  $this->Error( 'mbstring overloading must be disabled' );
866
+ if ( get_magic_quotes_runtime() && version_compare( phpversion(), '5.4', '<' ) )
867
  @set_magic_quotes_runtime( 0 );
868
  }
869
 
includes/libraries/wp-session.php CHANGED
@@ -10,6 +10,9 @@
10
  * @since 3.7.0
11
  */
12
 
 
 
 
13
  /**
14
  * Return the current cache expire setting.
15
  *
@@ -141,6 +144,10 @@ function wp_session_cleanup() {
141
  // Get the session ID by parsing the option_name
142
  $session_id = substr( $expiration->option_name, 20 );
143
 
 
 
 
 
144
  $expired_sessions[] = $expiration->option_name;
145
  $expired_sessions[] = "_wp_session_$session_id";
146
  }
10
  * @since 3.7.0
11
  */
12
 
13
+ // Exit if accessed directly
14
+ if ( ! defined( 'ABSPATH' ) ) exit;
15
+
16
  /**
17
  * Return the current cache expire setting.
18
  *
144
  // Get the session ID by parsing the option_name
145
  $session_id = substr( $expiration->option_name, 20 );
146
 
147
+ if( (int) -1 === (int) $session_id ) {
148
+ continue;
149
+ }
150
+
151
  $expired_sessions[] = $expiration->option_name;
152
  $expired_sessions[] = "_wp_session_$session_id";
153
  }
includes/login-register.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Functions/Login
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -16,13 +16,12 @@ if ( ! defined( 'ABSPATH' ) ) exit;
16
  * Login Form
17
  *
18
  * @since 1.0
19
- * @global $edd_options
20
  * @global $post
21
  * @param string $redirect Redirect page URL
22
  * @return string Login form
23
  */
24
  function edd_login_form( $redirect = '' ) {
25
- global $edd_options, $edd_login_redirect;
26
 
27
  if ( empty( $redirect ) ) {
28
  $redirect = edd_get_current_page_url();
@@ -41,13 +40,12 @@ function edd_login_form( $redirect = '' ) {
41
  * Registration Form
42
  *
43
  * @since 2.0
44
- * @global $edd_options
45
  * @global $post
46
  * @param string $redirect Redirect page URL
47
  * @return string Register form
48
  */
49
  function edd_register_form( $redirect = '' ) {
50
- global $edd_options, $edd_register_redirect;
51
 
52
  if ( empty( $redirect ) ) {
53
  $redirect = edd_get_current_page_url();
@@ -191,4 +189,4 @@ function edd_process_register_form( $data ) {
191
  edd_die();
192
  }
193
  }
194
- add_action( 'edd_user_register', 'edd_process_register_form' );
4
  *
5
  * @package EDD
6
  * @subpackage Functions/Login
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
16
  * Login Form
17
  *
18
  * @since 1.0
 
19
  * @global $post
20
  * @param string $redirect Redirect page URL
21
  * @return string Login form
22
  */
23
  function edd_login_form( $redirect = '' ) {
24
+ global $edd_login_redirect;
25
 
26
  if ( empty( $redirect ) ) {
27
  $redirect = edd_get_current_page_url();
40
  * Registration Form
41
  *
42
  * @since 2.0
 
43
  * @global $post
44
  * @param string $redirect Redirect page URL
45
  * @return string Register form
46
  */
47
  function edd_register_form( $redirect = '' ) {
48
+ global $edd_register_redirect;
49
 
50
  if ( empty( $redirect ) ) {
51
  $redirect = edd_get_current_page_url();
189
  edd_die();
190
  }
191
  }
192
+ add_action( 'edd_user_register', 'edd_process_register_form' );
includes/mime-types.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
includes/misc-functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -16,14 +16,10 @@ if ( ! defined( 'ABSPATH' ) ) exit;
16
  * Is Test Mode
17
  *
18
  * @since 1.0
19
- * @global $edd_options
20
  * @return bool $ret True if return mode is enabled, false otherwise
21
  */
22
  function edd_is_test_mode() {
23
- global $edd_options;
24
-
25
- $ret = ! empty( $edd_options['test_mode'] );
26
-
27
  return (bool) apply_filters( 'edd_is_test_mode', $ret );
28
  }
29
 
@@ -31,14 +27,10 @@ function edd_is_test_mode() {
31
  * Checks if Guest checkout is enabled
32
  *
33
  * @since 1.0
34
- * @global $edd_options
35
  * @return bool $ret True if guest checkout is enabled, false otherwise
36
  */
37
  function edd_no_guest_checkout() {
38
- global $edd_options;
39
-
40
- $ret = ! empty ( $edd_options['logged_in_only'] );
41
-
42
  return (bool) apply_filters( 'edd_no_guest_checkout', $ret );
43
  }
44
 
@@ -46,14 +38,10 @@ function edd_no_guest_checkout() {
46
  * Checks if users can only purchase downloads when logged in
47
  *
48
  * @since 1.0
49
- * @global $edd_options
50
  * @return bool $ret Whether or not the logged_in_only setting is set
51
  */
52
  function edd_logged_in_only() {
53
- global $edd_options;
54
-
55
- $ret = ! empty( $edd_options['logged_in_only'] );
56
-
57
  return (bool) apply_filters( 'edd_logged_in_only', $ret );
58
  }
59
 
@@ -64,8 +52,7 @@ function edd_logged_in_only() {
64
  * @return bool $ret True is redirect is enabled, false otherwise
65
  */
66
  function edd_straight_to_checkout() {
67
- global $edd_options;
68
- $ret = isset( $edd_options['redirect_on_add'] );
69
  return (bool) apply_filters( 'edd_straight_to_checkout', $ret );
70
  }
71
 
@@ -74,14 +61,10 @@ function edd_straight_to_checkout() {
74
  *
75
  * @access public
76
  * @since 1.0.8.2
77
- * @global $edd_options
78
  * @return bool True if redownloading of files is disabled, false otherwise
79
  */
80
  function edd_no_redownload() {
81
- global $edd_options;
82
-
83
- $ret = isset( $edd_options['disable_redownload'] );
84
-
85
  return (bool) apply_filters( 'edd_no_redownload', $ret );
86
  }
87
 
@@ -89,12 +72,9 @@ function edd_no_redownload() {
89
  * Verify credit card numbers live?
90
  *
91
  * @since 1.4
92
- * @global $edd_options
93
  * @return bool $ret True is verify credit cards is live
94
  */
95
  function edd_is_cc_verify_enabled() {
96
- global $edd_options;
97
-
98
  $ret = true;
99
 
100
  /*
@@ -181,13 +161,16 @@ function edd_string_is_image_url( $str ) {
181
  * @return string $ip User's IP address
182
  */
183
  function edd_get_ip() {
 
 
 
184
  if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
185
  //check ip from share internet
186
  $ip = $_SERVER['HTTP_CLIENT_IP'];
187
  } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
188
  //to check ip is pass from proxy
189
  $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
190
- } else {
191
  $ip = $_SERVER['REMOTE_ADDR'];
192
  }
193
  return apply_filters( 'edd_get_ip', $ip );
@@ -225,6 +208,11 @@ function edd_get_host() {
225
  $host = 'Rackspace Cloud';
226
  } elseif( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
227
  $host = 'SysFix.eu Power Hosting';
 
 
 
 
 
228
  }
229
 
230
  return $host;
@@ -287,6 +275,10 @@ function edd_is_host( $host = false ) {
287
  if( strpos( DB_HOST, '.sysfix.eu' ) !== false )
288
  $return = true;
289
  break;
 
 
 
 
290
  default:
291
  $return = false;
292
  }
@@ -296,7 +288,6 @@ function edd_is_host( $host = false ) {
296
  }
297
 
298
 
299
-
300
  /**
301
  * Get Currencies
302
  *
@@ -337,7 +328,6 @@ function edd_get_currencies() {
337
  return apply_filters( 'edd_currencies', $currencies );
338
  }
339
 
340
-
341
  /**
342
  * Get the store's set currency
343
  *
@@ -345,11 +335,66 @@ function edd_get_currencies() {
345
  * @return string The currency code
346
  */
347
  function edd_get_currency() {
348
- global $edd_options;
349
- $currency = isset( $edd_options['currency'] ) ? $edd_options['currency'] : 'USD';
350
  return apply_filters( 'edd_currency', $currency );
351
  }
352
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
  /**
354
  * Month Num To Name
355
  *
@@ -357,7 +402,7 @@ function edd_get_currency() {
357
  *
358
  * @since 1.0
359
  *
360
- * @param unknown $n
361
  * @return string Short month name
362
  */
363
  function edd_month_num_to_name( $n ) {
@@ -396,7 +441,7 @@ function edd_get_current_page_url() {
396
 
397
  $page_url .= "://";
398
 
399
- if ( $_SERVER["SERVER_PORT"] != "80" )
400
  $page_url .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
401
  else
402
  $page_url .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
@@ -560,20 +605,14 @@ add_action( 'edd_cleanup_file_symlinks', 'edd_cleanup_file_symlinks' );
560
  * Checks if SKUs are enabled
561
  *
562
  * @since 1.6
563
- * @global $edd_options
564
  * @author Daniel J Griffiths
565
  * @return bool $ret True if SKUs are enabled, false otherwise
566
  */
567
  function edd_use_skus() {
568
- global $edd_options;
569
-
570
- $ret = isset( $edd_options['enable_skus'] );
571
-
572
  return (bool) apply_filters( 'edd_use_skus', $ret );
573
  }
574
 
575
-
576
-
577
  /**
578
  * Retrieve timezone
579
  *
@@ -665,3 +704,33 @@ if ( ! function_exists( 'cal_days_in_month' ) ) {
665
  return date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
666
  }
667
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  *
5
  * @package EDD
6
  * @subpackage Functions
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
16
  * Is Test Mode
17
  *
18
  * @since 1.0
 
19
  * @return bool $ret True if return mode is enabled, false otherwise
20
  */
21
  function edd_is_test_mode() {
22
+ $ret = edd_get_option( 'test_mode', false );
 
 
 
23
  return (bool) apply_filters( 'edd_is_test_mode', $ret );
24
  }
25
 
27
  * Checks if Guest checkout is enabled
28
  *
29
  * @since 1.0
 
30
  * @return bool $ret True if guest checkout is enabled, false otherwise
31
  */
32
  function edd_no_guest_checkout() {
33
+ $ret = edd_get_option( 'logged_in_only', false );
 
 
 
34
  return (bool) apply_filters( 'edd_no_guest_checkout', $ret );
35
  }
36
 
38
  * Checks if users can only purchase downloads when logged in
39
  *
40
  * @since 1.0
 
41
  * @return bool $ret Whether or not the logged_in_only setting is set
42
  */
43
  function edd_logged_in_only() {
44
+ $ret = edd_get_option( 'logged_in_only', false );
 
 
 
45
  return (bool) apply_filters( 'edd_logged_in_only', $ret );
46
  }
47
 
52
  * @return bool $ret True is redirect is enabled, false otherwise
53
  */
54
  function edd_straight_to_checkout() {
55
+ $ret = edd_get_option( 'redirect_on_add', false );
 
56
  return (bool) apply_filters( 'edd_straight_to_checkout', $ret );
57
  }
58
 
61
  *
62
  * @access public
63
  * @since 1.0.8.2
 
64
  * @return bool True if redownloading of files is disabled, false otherwise
65
  */
66
  function edd_no_redownload() {
67
+ $ret = edd_get_option( 'disable_redownload', false );
 
 
 
68
  return (bool) apply_filters( 'edd_no_redownload', $ret );
69
  }
70
 
72
  * Verify credit card numbers live?
73
  *
74
  * @since 1.4
 
75
  * @return bool $ret True is verify credit cards is live
76
  */
77
  function edd_is_cc_verify_enabled() {
 
 
78
  $ret = true;
79
 
80
  /*
161
  * @return string $ip User's IP address
162
  */
163
  function edd_get_ip() {
164
+
165
+ $ip = '127.0.0.1';
166
+
167
  if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
168
  //check ip from share internet
169
  $ip = $_SERVER['HTTP_CLIENT_IP'];
170
  } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
171
  //to check ip is pass from proxy
172
  $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
173
+ } elseif( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
174
  $ip = $_SERVER['REMOTE_ADDR'];
175
  }
176
  return apply_filters( 'edd_get_ip', $ip );
208
  $host = 'Rackspace Cloud';
209
  } elseif( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
210
  $host = 'SysFix.eu Power Hosting';
211
+ } elseif( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false ) {
212
+ $host = 'Flywheel';
213
+ } else {
214
+ // Adding a general fallback for data gathering
215
+ $host = 'DBH: ' . DB_HOST . ', SRV: ' . $_SERVER['SERVER_NAME'];
216
  }
217
 
218
  return $host;
275
  if( strpos( DB_HOST, '.sysfix.eu' ) !== false )
276
  $return = true;
277
  break;
278
+ case 'flywheel':
279
+ if( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false )
280
+ $return = true;
281
+ break;
282
  default:
283
  $return = false;
284
  }
288
  }
289
 
290
 
 
291
  /**
292
  * Get Currencies
293
  *
328
  return apply_filters( 'edd_currencies', $currencies );
329
  }
330
 
 
331
  /**
332
  * Get the store's set currency
333
  *
335
  * @return string The currency code
336
  */
337
  function edd_get_currency() {
338
+ $currency = edd_get_option( 'currency', 'USD' );
 
339
  return apply_filters( 'edd_currency', $currency );
340
  }
341
 
342
+ /**
343
+ * Given a currency determine the symbol to use. If no currency given, site default is used.
344
+ * If no symbol is determine, the currency string is returned.
345
+ *
346
+ * @since 2.2
347
+ * @param string $currency The currency string
348
+ * @return string The symbol to use for the currency
349
+ */
350
+ function edd_currency_symbol( $currency = '' ) {
351
+ if ( empty( $currency ) ) {
352
+ $currency = edd_get_currency();
353
+ }
354
+
355
+ switch ( $currency ) :
356
+ case "GBP" :
357
+ $symbol = '&pound;';
358
+ break;
359
+ case "BRL" :
360
+ $symbol = 'R&#36;';
361
+ break;
362
+ case "EUR" :
363
+ $symbol = '&euro;';
364
+ break;
365
+ case "USD" :
366
+ case "AUD" :
367
+ case "NZD" :
368
+ case "CAD" :
369
+ case "HKD" :
370
+ case "MXN" :
371
+ case "SGD" :
372
+ $symbol = '&#36;';
373
+ break;
374
+ case "JPY" :
375
+ $symbol = '&yen;';
376
+ break;
377
+ default :
378
+ $symbol = $currency;
379
+ break;
380
+ endswitch;
381
+
382
+ return apply_filters( 'edd_currency_symbol', $symbol, $currency );
383
+ }
384
+
385
+ /**
386
+ * Get the name of a currency
387
+ *
388
+ * @since 2.2
389
+ * @param string $code The currency code
390
+ * @return string The currency's name
391
+ */
392
+ function edd_get_currency_name( $code = 'USD' ) {
393
+ $currencies = edd_get_currencies();
394
+ $name = isset( $currencies[ $code ] ) ? $currencies[ $code ] : $code;
395
+ return apply_filters( 'edd_currency_name', $name );
396
+ }
397
+
398
  /**
399
  * Month Num To Name
400
  *
402
  *
403
  * @since 1.0
404
  *
405
+ * @param integer $n
406
  * @return string Short month name
407
  */
408
  function edd_month_num_to_name( $n ) {
441
 
442
  $page_url .= "://";
443
 
444
+ if ( isset( $_SERVER["SERVER_PORT"] ) && $_SERVER["SERVER_PORT"] != "80" )
445
  $page_url .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
446
  else
447
  $page_url .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
605
  * Checks if SKUs are enabled
606
  *
607
  * @since 1.6
 
608
  * @author Daniel J Griffiths
609
  * @return bool $ret True if SKUs are enabled, false otherwise
610
  */
611
  function edd_use_skus() {
612
+ $ret = edd_get_option( 'enable_skus', false );
 
 
 
613
  return (bool) apply_filters( 'edd_use_skus', $ret );
614
  }
615
 
 
 
616
  /**
617
  * Retrieve timezone
618
  *
704
  return date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
705
  }
706
  }
707
+
708
+
709
+ if ( ! function_exists( 'hash_equals' ) ) :
710
+ /**
711
+ * Compare two strings in constant time.
712
+ *
713
+ * This function was added in PHP 5.6.
714
+ * It can leak the length of a string.
715
+ *
716
+ * @since 2.2.1
717
+ *
718
+ * @param string $a Expected string.
719
+ * @param string $b Actual string.
720
+ * @return bool Whether strings are equal.
721
+ */
722
+ function hash_equals( $a, $b ) {
723
+ $a_length = strlen( $a );
724
+ if ( $a_length !== strlen( $b ) ) {
725
+ return false;
726
+ }
727
+ $result = 0;
728
+
729
+ // Do not attempt to "optimize" this.
730
+ for ( $i = 0; $i < $a_length; $i++ ) {
731
+ $result |= ord( $a[ $i ] ) ^ ord( $b[ $i ] );
732
+ }
733
+
734
+ return $result === 0;
735
+ }
736
+ endif;
includes/payments/actions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Payments
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -32,42 +32,50 @@ function edd_complete_purchase( $payment_id, $new_status, $old_status ) {
32
  if ( $new_status != 'publish' && $new_status != 'complete' )
33
  return;
34
 
 
35
  $completed_date = edd_get_payment_completed_date( $payment_id );
36
  $user_info = edd_get_payment_meta_user_info( $payment_id );
 
37
  $amount = edd_get_payment_amount( $payment_id );
38
  $cart_details = edd_get_payment_meta_cart_details( $payment_id );
 
39
 
40
  do_action( 'edd_pre_complete_purchase', $payment_id );
41
 
42
  if ( is_array( $cart_details ) ) {
43
 
44
  // Increase purchase count and earnings
45
- foreach ( $cart_details as $download ) {
46
 
47
  // "bundle" or "default"
48
  $download_type = edd_get_download_type( $download['id'] );
49
- $price_id = isset( $download['options']['price_id'] ) ? (int) $download['options']['price_id'] : false;
50
-
51
- $price_id = isset( $download['options']['price_id'] ) ? (int) $download['options']['price_id'] : false;
52
-
53
  // Increase earnings and fire actions once per quantity number
54
  for( $i = 0; $i < $download['quantity']; $i++ ) {
55
 
56
- if ( ! edd_is_test_mode() || apply_filters( 'edd_log_test_payment_stats', false ) ) {
 
57
 
58
- edd_record_sale_in_log( $download['id'], $payment_id, $price_id );
59
- edd_increase_purchase_count( $download['id'] );
60
- edd_increase_earnings( $download['id'], $download['price'] );
61
 
62
- }
 
 
 
 
63
 
64
- if( empty( $completed_date ) ) {
65
- // Ensure this action only runs once ever
66
- do_action( 'edd_complete_download_purchase', $download['id'], $payment_id, $download_type, $download );
67
  }
68
 
69
  }
70
 
 
 
 
 
 
 
 
 
71
  }
72
 
73
  // Clear the total earnings cache
@@ -77,8 +85,19 @@ function edd_complete_purchase( $payment_id, $new_status, $old_status ) {
77
  delete_transient( md5( 'edd_earnings_todaytoday' ) );
78
  }
79
 
 
 
 
 
 
 
 
 
 
 
 
80
  // Check for discount codes and increment their use counts
81
- if ( isset( $user_info['discount'] ) && $user_info['discount'] != 'none' ) {
82
 
83
  $discounts = array_map( 'trim', explode( ',', $user_info['discount'] ) );
84
 
@@ -93,13 +112,12 @@ function edd_complete_purchase( $payment_id, $new_status, $old_status ) {
93
  }
94
  }
95
 
96
- edd_increase_total_earnings( $amount );
97
 
98
  // Ensure this action only runs once ever
99
  if( empty( $completed_date ) ) {
100
 
101
  // Save the completed date
102
- update_post_meta( $payment_id, '_edd_completed_date', current_time( 'mysql' ) );
103
 
104
  do_action( 'edd_complete_purchase', $payment_id );
105
  }
@@ -158,29 +176,23 @@ function edd_undo_purchase_on_refund( $payment_id, $new_status, $old_status ) {
158
  $amount = edd_get_payment_amount( $payment_id );
159
  edd_decrease_total_earnings( $amount );
160
 
 
 
 
 
 
 
 
 
 
 
 
161
  // Clear the This Month earnings (this_monththis_month is NOT a typo)
162
  delete_transient( md5( 'edd_earnings_this_monththis_month' ) );
163
  }
164
  add_action( 'edd_update_payment_status', 'edd_undo_purchase_on_refund', 100, 3 );
165
 
166
 
167
- /**
168
- * Trigger a Purchase Deletion
169
- *
170
- * @since 1.3.4
171
- * @param $data Arguments passed
172
- * @return void
173
- */
174
- function edd_trigger_purchase_delete( $data ) {
175
- if ( wp_verify_nonce( $data['_wpnonce'], 'edd_payment_nonce' ) ) {
176
- $payment_id = absint( $data['purchase_id'] );
177
- edd_delete_purchase( $payment_id );
178
- wp_redirect( admin_url( '/edit.php?post_type=download&page=edd-payment-history&edd-message=payment_deleted' ) );
179
- edd_die();
180
- }
181
- }
182
- add_action( 'edd_delete_payment', 'edd_trigger_purchase_delete' );
183
-
184
  /**
185
  * Flushes the current user's purchase history transient when a payment status
186
  * is updated
@@ -224,7 +236,7 @@ function edd_update_old_payments_with_totals( $data ) {
224
  if ( $payments ) {
225
  foreach ( $payments as $payment ) {
226
  $meta = edd_get_payment_meta( $payment->ID );
227
- update_post_meta( $payment->ID, '_edd_payment_total', $meta['amount'] );
228
  }
229
  }
230
 
@@ -241,8 +253,7 @@ add_action( 'edd_upgrade_payments', 'edd_update_old_payments_with_totals' );
241
  function edd_mark_abandoned_orders() {
242
  $args = array(
243
  'status' => 'pending',
244
- 'number' => -1,
245
- 'fields' => 'ids'
246
  );
247
 
248
  add_filter( 'posts_where', 'edd_filter_where_older_than_week' );
@@ -253,8 +264,75 @@ function edd_mark_abandoned_orders() {
253
 
254
  if( $payments ) {
255
  foreach( $payments as $payment ) {
256
- edd_update_payment_status( $payment, 'abandoned' );
 
 
257
  }
258
  }
259
  }
260
  add_action( 'edd_weekly_scheduled_events', 'edd_mark_abandoned_orders' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  *
5
  * @package EDD
6
  * @subpackage Payments
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
32
  if ( $new_status != 'publish' && $new_status != 'complete' )
33
  return;
34
 
35
+ $creation_date = get_post_field( 'post_date', $payment_id, 'raw' );
36
  $completed_date = edd_get_payment_completed_date( $payment_id );
37
  $user_info = edd_get_payment_meta_user_info( $payment_id );
38
+ $customer_id = edd_get_payment_customer_id( $payment_id );
39
  $amount = edd_get_payment_amount( $payment_id );
40
  $cart_details = edd_get_payment_meta_cart_details( $payment_id );
41
+ $increase_stats = ! edd_is_test_mode() || apply_filters( 'edd_log_test_payment_stats', false );
42
 
43
  do_action( 'edd_pre_complete_purchase', $payment_id );
44
 
45
  if ( is_array( $cart_details ) ) {
46
 
47
  // Increase purchase count and earnings
48
+ foreach ( $cart_details as $cart_index => $download ) {
49
 
50
  // "bundle" or "default"
51
  $download_type = edd_get_download_type( $download['id'] );
52
+ $price_id = isset( $download['item_number']['options']['price_id'] ) ? (int) $download['item_number']['options']['price_id'] : false;
 
 
 
53
  // Increase earnings and fire actions once per quantity number
54
  for( $i = 0; $i < $download['quantity']; $i++ ) {
55
 
56
+ // Ensure these actions only run once, ever
57
+ if( empty( $completed_date ) ) {
58
 
59
+ if ( $increase_stats ) {
 
 
60
 
61
+ edd_record_sale_in_log( $download['id'], $payment_id, $price_id, $creation_date );
62
+
63
+ }
64
+
65
+ do_action( 'edd_complete_download_purchase', $download['id'], $payment_id, $download_type, $download, $cart_index );
66
 
 
 
 
67
  }
68
 
69
  }
70
 
71
+ if( $increase_stats ) {
72
+
73
+ // Increase the earnings for this download ID
74
+ edd_increase_earnings( $download['id'], $download['price'] );
75
+ edd_increase_purchase_count( $download['id'], $download['quantity'] );
76
+
77
+ }
78
+
79
  }
80
 
81
  // Clear the total earnings cache
85
  delete_transient( md5( 'edd_earnings_todaytoday' ) );
86
  }
87
 
88
+ if( $increase_stats ) {
89
+
90
+ // Increase the customer's purchase stats
91
+ $customer = new EDD_Customer( $customer_id );
92
+ $customer->increase_purchase_count();
93
+ $customer->increase_value( $amount );
94
+
95
+ edd_increase_total_earnings( $amount );
96
+
97
+ }
98
+
99
  // Check for discount codes and increment their use counts
100
+ if ( ! empty( $user_info['discount'] ) && $user_info['discount'] !== 'none' ) {
101
 
102
  $discounts = array_map( 'trim', explode( ',', $user_info['discount'] ) );
103
 
112
  }
113
  }
114
 
 
115
 
116
  // Ensure this action only runs once ever
117
  if( empty( $completed_date ) ) {
118
 
119
  // Save the completed date
120
+ edd_update_payment_meta( $payment_id, '_edd_completed_date', current_time( 'mysql' ) );
121
 
122
  do_action( 'edd_complete_purchase', $payment_id );
123
  }
176
  $amount = edd_get_payment_amount( $payment_id );
177
  edd_decrease_total_earnings( $amount );
178
 
179
+ // Decrement the stats for the customer
180
+ $customer_id = edd_get_payment_customer_id( $payment_id );
181
+
182
+ if( $customer_id ) {
183
+
184
+ $customer = new EDD_Customer( $customer_id );
185
+ $customer->decrease_value( $amount );
186
+ $customer->decrease_purchase_count();
187
+
188
+ }
189
+
190
  // Clear the This Month earnings (this_monththis_month is NOT a typo)
191
  delete_transient( md5( 'edd_earnings_this_monththis_month' ) );
192
  }
193
  add_action( 'edd_update_payment_status', 'edd_undo_purchase_on_refund', 100, 3 );
194
 
195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  /**
197
  * Flushes the current user's purchase history transient when a payment status
198
  * is updated
236
  if ( $payments ) {
237
  foreach ( $payments as $payment ) {
238
  $meta = edd_get_payment_meta( $payment->ID );
239
+ edd_update_payment_meta( $payment->ID, '_edd_payment_total', $meta['amount'] );
240
  }
241
  }
242
 
253
  function edd_mark_abandoned_orders() {
254
  $args = array(
255
  'status' => 'pending',
256
+ 'number' => -1
 
257
  );
258
 
259
  add_filter( 'posts_where', 'edd_filter_where_older_than_week' );
264
 
265
  if( $payments ) {
266
  foreach( $payments as $payment ) {
267
+ if( 'pending' === $payment->post_status ) {
268
+ edd_update_payment_status( $payment->ID, 'abandoned' );
269
+ }
270
  }
271
  }
272
  }
273
  add_action( 'edd_weekly_scheduled_events', 'edd_mark_abandoned_orders' );
274
+
275
+ /**
276
+ * Listens to the updated_postmeta hook for our backwards compatible payment_meta updates, and runs through them
277
+ *
278
+ * @since 2.3
279
+ * @param int $meta_id The Meta ID that was updated
280
+ * @param int $object_id The Object ID that was updated (post ID)
281
+ * @param string $meta_key The Meta key that was updated
282
+ * @param string|int|float $meta_value The Value being updated
283
+ * @return bool|int If successful the number of rows updated, if it fails, false
284
+ */
285
+ function edd_update_payment_backwards_compat( $meta_id, $object_id, $meta_key, $meta_value ) {
286
+
287
+ $meta_keys = array( '_edd_payment_meta', '_edd_payment_tax' );
288
+
289
+ if ( ! in_array( $meta_key, $meta_keys ) ) {
290
+ return;
291
+ }
292
+
293
+ global $wpdb;
294
+ switch( $meta_key ) {
295
+
296
+ case '_edd_payment_meta':
297
+ $meta_value = maybe_unserialize( $meta_value );
298
+
299
+ if( !isset( $meta_value['tax'] ) ){
300
+ return;
301
+ }
302
+
303
+ $tax_value = $meta_value['tax'];
304
+
305
+ $data = array( 'meta_value' => $tax_value );
306
+ $where = array( 'post_id' => $object_id, 'meta_key' => '_edd_payment_tax' );
307
+ $data_format = array( '%f' );
308
+ $where_format = array( '%d', '%s' );
309
+ break;
310
+
311
+ case '_edd_payment_tax':
312
+ $tax_value = ! empty( $meta_value ) ? $meta_value : 0;
313
+ $current_meta = edd_get_payment_meta( $object_id, '_edd_payment_meta', true );
314
+
315
+ $current_meta['tax'] = $tax_value;
316
+ $new_meta = maybe_serialize( $current_meta );
317
+
318
+ $data = array( 'meta_value' => $new_meta );
319
+ $where = array( 'post_id' => $object_id, 'meta_key' => '_edd_payment_meta' );
320
+ $data_format = array( '%s' );
321
+ $where_format = array( '%d', '%s' );
322
+
323
+ break;
324
+
325
+ }
326
+
327
+ $updated = $wpdb->update( $wpdb->postmeta, $data, $where, $data_format, $where_format );
328
+
329
+ if ( ! empty( $updated ) ) {
330
+ // Since we did a direct DB query, clear the postmeta cache.
331
+ wp_cache_delete( $object_id, 'post_meta' );
332
+ }
333
+
334
+ return $updated;
335
+
336
+
337
+ }
338
+ add_action( 'updated_postmeta', 'edd_update_payment_backwards_compat', 10, 4 );
includes/payments/class-payment-stats.php CHANGED
@@ -4,11 +4,13 @@
4
  *
5
  * @package EDD
6
  * @subpackage Classes/Stats
7
- * @copyright Copyright (c) 2012, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8
10
  */
11
 
 
 
12
 
13
  /**
14
  * EDD_Stats Class
@@ -186,7 +188,7 @@ class EDD_Payment_Stats extends EDD_Stats {
186
 
187
  remove_filter( 'posts_where', array( $this, 'payments_where' ) );
188
 
189
- return round( $earnings, 2 );
190
 
191
  }
192
 
4
  *
5
  * @package EDD
6
  * @subpackage Classes/Stats
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
 
15
  /**
16
  * EDD_Stats Class
188
 
189
  remove_filter( 'posts_where', array( $this, 'payments_where' ) );
190
 
191
+ return round( $earnings, edd_currency_decimal_filter() );
192
 
193
  }
194
 
includes/payments/class-payments-query.php CHANGED
@@ -4,11 +4,13 @@
4
  *
5
  * @package EDD
6
  * @subpackage Classes/Stats
7
- * @copyright Copyright (c) 2012, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8
10
  */
11
 
 
 
12
 
13
  /**
14
  * EDD_Payments_Query Class
@@ -60,7 +62,7 @@ class EDD_Payments_Query extends EDD_Stats {
60
  'orderby' => 'ID',
61
  'order' => 'DESC',
62
  'user' => null,
63
- 'status' => 'any',
64
  'meta_key' => null,
65
  'year' => null,
66
  'month' => null,
@@ -141,7 +143,7 @@ class EDD_Payments_Query extends EDD_Stats {
141
 
142
  $query = new WP_Query( $this->args );
143
 
144
- if ( 'payments' != $this->args[ 'output' ] ) {
145
  return $query->posts;
146
  }
147
 
@@ -171,6 +173,8 @@ class EDD_Payments_Query extends EDD_Stats {
171
 
172
  $this->payments[] = apply_filters( 'edd_payment', $details, $payment_id, $this );
173
  }
 
 
174
  }
175
 
176
  do_action( 'edd_post_get_payments', $this );
@@ -186,11 +190,11 @@ class EDD_Payments_Query extends EDD_Stats {
186
  * @return void
187
  */
188
  public function date_filter_pre() {
189
- if( ! ( $this->args[ 'start_date' ] || $this->args[ 'end_date' ] ) ) {
190
  return;
191
  }
192
 
193
- $this->setup_dates( $this->args[ 'start_date' ], $this->args[ 'end_date' ] );
194
 
195
  add_filter( 'posts_where', array( $this, 'payments_where' ) );
196
  }
@@ -204,7 +208,7 @@ class EDD_Payments_Query extends EDD_Stats {
204
  * @return void
205
  */
206
  public function date_filter_post() {
207
- if ( ! ( $this->args[ 'start_date' ] || $this->args[ 'end_date' ] ) ) {
208
  return;
209
  }
210
 
@@ -219,11 +223,11 @@ class EDD_Payments_Query extends EDD_Stats {
219
  * @return void
220
  */
221
  public function status() {
222
- if ( ! isset ( $this->args[ 'status' ] ) ) {
223
  return;
224
  }
225
 
226
- $this->__set( 'post_status', $this->args[ 'status' ] );
227
  $this->__unset( 'status' );
228
  }
229
 
@@ -235,11 +239,11 @@ class EDD_Payments_Query extends EDD_Stats {
235
  * @return void
236
  */
237
  public function page() {
238
- if ( ! isset ( $this->args[ 'page' ] ) ) {
239
  return;
240
  }
241
 
242
- $this->__set( 'paged', $this->args[ 'page' ] );
243
  $this->__unset( 'page' );
244
  }
245
 
@@ -252,15 +256,15 @@ class EDD_Payments_Query extends EDD_Stats {
252
  */
253
  public function per_page() {
254
 
255
- if( ! isset( $this->args[ 'number' ] ) ){
256
  return;
257
  }
258
 
259
- if ( $this->args[ 'number' ] == -1 ) {
260
  $this->__set( 'nopaging', true );
261
  }
262
  else{
263
- $this->__set( 'posts_per_page', $this->args[ 'number' ] );
264
  }
265
 
266
  $this->__unset( 'number' );
@@ -274,11 +278,11 @@ class EDD_Payments_Query extends EDD_Stats {
274
  * @return void
275
  */
276
  public function month() {
277
- if ( ! isset ( $this->args[ 'month' ] ) ) {
278
  return;
279
  }
280
 
281
- $this->__set( 'monthnum', $this->args[ 'month' ] );
282
  $this->__unset( 'month' );
283
  }
284
 
@@ -290,13 +294,13 @@ class EDD_Payments_Query extends EDD_Stats {
290
  * @return void
291
  */
292
  public function orderby() {
293
- switch ( $this->args[ 'orderby' ] ) {
294
  case 'amount' :
295
  $this->__set( 'orderby', 'meta_value_num' );
296
  $this->__set( 'meta_key', '_edd_payment_total' );
297
  break;
298
  default :
299
- $this->__set( 'orderby', $this->args[ 'orderby' ] );
300
  break;
301
  }
302
  }
@@ -309,11 +313,11 @@ class EDD_Payments_Query extends EDD_Stats {
309
  * @return void
310
  */
311
  public function user() {
312
- if ( is_null( $this->args[ 'user' ] ) ) {
313
  return;
314
  }
315
 
316
- if ( is_numeric( $this->args[ 'user' ] ) ) {
317
  $user_key = '_edd_payment_user_id';
318
  } else {
319
  $user_key = '_edd_payment_user_email';
@@ -321,7 +325,7 @@ class EDD_Payments_Query extends EDD_Stats {
321
 
322
  $this->__set( 'meta_query', array(
323
  'key' => $user_key,
324
- 'value' => $this->args[ 'user' ]
325
  ) );
326
  }
327
 
@@ -334,11 +338,11 @@ class EDD_Payments_Query extends EDD_Stats {
334
  */
335
  public function search() {
336
 
337
- if( ! isset( $this->args[ 's' ] ) ) {
338
  return;
339
  }
340
-
341
- $search = trim( $this->args[ 's' ] );
342
 
343
  if( empty( $search ) ) {
344
  return;
@@ -347,7 +351,7 @@ class EDD_Payments_Query extends EDD_Stats {
347
  $is_email = is_email( $search ) || strpos( $search, '@' ) !== false;
348
  $is_user = strpos( $search, strtolower( 'user:' ) ) !== false;
349
 
350
- if ( ! empty( $this->args[ 'search_in_notes' ] ) ) {
351
 
352
  $notes = edd_get_payment_notes( 0, $search );
353
 
@@ -397,11 +401,11 @@ class EDD_Payments_Query extends EDD_Stats {
397
 
398
  $this->__unset( 's' );
399
 
400
- } elseif (
401
- edd_get_option( 'enable_sequential' ) &&
402
  (
403
  false !== strpos( $search, edd_get_option( 'sequential_prefix' ) ) ||
404
- false !== strpos( $search, edd_get_option( 'sequential_postfix' ) )
405
  )
406
  ) {
407
 
@@ -419,7 +423,7 @@ class EDD_Payments_Query extends EDD_Stats {
419
  $post = get_post( $search );
420
 
421
  if( is_object( $post ) && $post->post_type == 'edd_payment' ) {
422
-
423
  $arr = array();
424
  $arr[] = $search;
425
  $this->__set( 'post__in', $arr );
@@ -446,14 +450,14 @@ class EDD_Payments_Query extends EDD_Stats {
446
  * @return void
447
  */
448
  public function mode() {
449
- if ( empty( $this->args[ 'mode' ] ) || $this->args[ 'mode' ] == 'all' ) {
450
  $this->__unset( 'mode' );
451
  return;
452
  }
453
 
454
  $this->__set( 'meta_query', array(
455
  'key' => '_edd_payment_mode',
456
- 'value' => $this->args[ 'mode' ]
457
  ) );
458
  }
459
 
@@ -465,7 +469,7 @@ class EDD_Payments_Query extends EDD_Stats {
465
  * @return void
466
  */
467
  public function children() {
468
- if ( empty( $this->args[ 'children' ] ) ) {
469
  $this->__set( 'post_parent', 0 );
470
  }
471
  $this->__unset( 'children' );
@@ -480,13 +484,13 @@ class EDD_Payments_Query extends EDD_Stats {
480
  */
481
  public function download() {
482
 
483
- if ( empty( $this->args[ 'download' ] ) )
484
  return;
485
 
486
  global $edd_logs;
487
 
488
  $args = array(
489
- 'post_parent' => $this->args[ 'download' ],
490
  'log_type' => 'sale',
491
  'post_status' => array( 'publish' ),
492
  'nopaging' => true,
@@ -497,9 +501,9 @@ class EDD_Payments_Query extends EDD_Stats {
497
  'fields' => 'ids'
498
  );
499
 
500
- if ( is_array( $this->args[ 'download' ] ) ) {
501
- unset( $args[ 'post_parent' ] );
502
- $args[ 'post_parent__in' ] = $this->args[ 'download' ];
503
  }
504
 
505
  $sales = $edd_logs->get_connected_logs( $args );
4
  *
5
  * @package EDD
6
  * @subpackage Classes/Stats
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.8
10
  */
11
 
12
+ // Exit if accessed directly
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
 
15
  /**
16
  * EDD_Payments_Query Class
62
  'orderby' => 'ID',
63
  'order' => 'DESC',
64
  'user' => null,
65
+ 'status' => edd_get_payment_status_keys(),
66
  'meta_key' => null,
67
  'year' => null,
68
  'month' => null,
143
 
144
  $query = new WP_Query( $this->args );
145
 
146
+ if ( 'payments' != $this->args['output'] ) {
147
  return $query->posts;
148
  }
149
 
173
 
174
  $this->payments[] = apply_filters( 'edd_payment', $details, $payment_id, $this );
175
  }
176
+
177
+ wp_reset_postdata();
178
  }
179
 
180
  do_action( 'edd_post_get_payments', $this );
190
  * @return void
191
  */
192
  public function date_filter_pre() {
193
+ if( ! ( $this->args['start_date'] || $this->args['end_date'] ) ) {
194
  return;
195
  }
196
 
197
+ $this->setup_dates( $this->args['start_date'], $this->args['end_date'] );
198
 
199
  add_filter( 'posts_where', array( $this, 'payments_where' ) );
200
  }
208
  * @return void
209
  */
210
  public function date_filter_post() {
211
+ if ( ! ( $this->args['start_date'] || $this->args['end_date'] ) ) {
212
  return;
213
  }
214
 
223
  * @return void
224
  */
225
  public function status() {
226
+ if ( ! isset ( $this->args['status'] ) ) {
227
  return;
228
  }
229
 
230
+ $this->__set( 'post_status', $this->args['status'] );
231
  $this->__unset( 'status' );
232
  }
233
 
239
  * @return void
240
  */
241
  public function page() {
242
+ if ( ! isset ( $this->args['page'] ) ) {
243
  return;
244
  }
245
 
246
+ $this->__set( 'paged', $this->args['page'] );
247
  $this->__unset( 'page' );
248
  }
249
 
256
  */
257
  public function per_page() {
258
 
259
+ if( ! isset( $this->args['number'] ) ){
260
  return;
261
  }
262
 
263
+ if ( $this->args['number'] == -1 ) {
264
  $this->__set( 'nopaging', true );
265
  }
266
  else{
267
+ $this->__set( 'posts_per_page', $this->args['number'] );
268
  }
269
 
270
  $this->__unset( 'number' );
278
  * @return void
279
  */
280
  public function month() {
281
+ if ( ! isset ( $this->args['month'] ) ) {
282
  return;
283
  }
284
 
285
+ $this->__set( 'monthnum', $this->args['month'] );
286
  $this->__unset( 'month' );
287
  }
288
 
294
  * @return void
295
  */
296
  public function orderby() {
297
+ switch ( $this->args['orderby'] ) {
298
  case 'amount' :
299
  $this->__set( 'orderby', 'meta_value_num' );
300
  $this->__set( 'meta_key', '_edd_payment_total' );
301
  break;
302
  default :
303
+ $this->__set( 'orderby', $this->args['orderby'] );
304
  break;
305
  }
306
  }
313
  * @return void
314
  */
315
  public function user() {
316
+ if ( is_null( $this->args['user'] ) ) {
317
  return;
318
  }
319
 
320
+ if ( is_numeric( $this->args['user'] ) ) {
321
  $user_key = '_edd_payment_user_id';
322
  } else {
323
  $user_key = '_edd_payment_user_email';
325
 
326
  $this->__set( 'meta_query', array(
327
  'key' => $user_key,
328
+ 'value' => $this->args['user']
329
  ) );
330
  }
331
 
338
  */
339
  public function search() {
340
 
341
+ if( ! isset( $this->args['s'] ) ) {
342
  return;
343
  }
344
+
345
+ $search = trim( $this->args['s'] );
346
 
347
  if( empty( $search ) ) {
348
  return;
351
  $is_email = is_email( $search ) || strpos( $search, '@' ) !== false;
352
  $is_user = strpos( $search, strtolower( 'user:' ) ) !== false;
353
 
354
+ if ( ! empty( $this->args['search_in_notes'] ) ) {
355
 
356
  $notes = edd_get_payment_notes( 0, $search );
357
 
401
 
402
  $this->__unset( 's' );
403
 
404
+ } elseif (
405
+ edd_get_option( 'enable_sequential' ) &&
406
  (
407
  false !== strpos( $search, edd_get_option( 'sequential_prefix' ) ) ||
408
+ false !== strpos( $search, edd_get_option( 'sequential_postfix' ) )
409
  )
410
  ) {
411
 
423
  $post = get_post( $search );
424
 
425
  if( is_object( $post ) && $post->post_type == 'edd_payment' ) {
426
+
427
  $arr = array();
428
  $arr[] = $search;
429
  $this->__set( 'post__in', $arr );
450
  * @return void
451
  */
452
  public function mode() {
453
+ if ( empty( $this->args['mode'] ) || $this->args['mode'] == 'all' ) {
454
  $this->__unset( 'mode' );
455
  return;
456
  }
457
 
458
  $this->__set( 'meta_query', array(
459
  'key' => '_edd_payment_mode',
460
+ 'value' => $this->args['mode']
461
  ) );
462
  }
463
 
469
  * @return void
470
  */
471
  public function children() {
472
+ if ( empty( $this->args['children'] ) ) {
473
  $this->__set( 'post_parent', 0 );
474
  }
475
  $this->__unset( 'children' );
484
  */
485
  public function download() {
486
 
487
+ if ( empty( $this->args['download'] ) )
488
  return;
489
 
490
  global $edd_logs;
491
 
492
  $args = array(
493
+ 'post_parent' => $this->args['download'],
494
  'log_type' => 'sale',
495
  'post_status' => array( 'publish' ),
496
  'nopaging' => true,
501
  'fields' => 'ids'
502
  );
503
 
504
+ if ( is_array( $this->args['download'] ) ) {
505
+ unset( $args['post_parent'] );
506
+ $args['post_parent__in'] = $this->args['download'];
507
  }
508
 
509
  $sales = $edd_logs->get_connected_logs( $args );
includes/payments/functions.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * @package EDD
6
  * @subpackage Payments
7
- * @copyright Copyright (c) 2014, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
@@ -80,6 +80,19 @@ function edd_get_payment_by( $field = '', $value = '' ) {
80
 
81
  break;
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  default:
84
  return false;
85
  }
@@ -117,7 +130,7 @@ function edd_insert_payment( $payment_data = array() ) {
117
  $discount = edd_get_discount_by( 'code', $payment_data['user_info']['discount'] );
118
  }
119
 
120
- // Find the next payment number, if enabled
121
  if( edd_get_option( 'enable_sequential' ) ) {
122
  $number = edd_get_next_payment_number();
123
  }
@@ -128,7 +141,7 @@ function edd_insert_payment( $payment_data = array() ) {
128
  'post_type' => 'edd_payment',
129
  'post_parent' => isset( $payment_data['parent'] ) ? $payment_data['parent'] : null,
130
  'post_date' => isset( $payment_data['post_date'] ) ? $payment_data['post_date'] : null,
131
- 'post_date_gmt' => isset( $payment_data['post_date'] ) ? $payment_data['post_date'] : null
132
  ), $payment_data );
133
 
134
  // Create a blank payment
@@ -136,15 +149,19 @@ function edd_insert_payment( $payment_data = array() ) {
136
 
137
  if ( $payment ) {
138
 
139
- $taxes = wp_list_pluck( $payment_data['cart_details'], 'tax' );
140
- $cart_tax = array_sum( $taxes );
 
 
 
 
 
141
 
142
  $payment_meta = array(
143
  'currency' => $payment_data['currency'],
144
  'downloads' => $payment_data['downloads'],
145
  'user_info' => $payment_data['user_info'],
146
  'cart_details' => $payment_data['cart_details'],
147
- 'tax' => $cart_tax,
148
  );
149
 
150
  $mode = edd_is_test_mode() ? 'test' : 'live';
@@ -156,21 +173,46 @@ function edd_insert_payment( $payment_data = array() ) {
156
  $payment_data['price'] = '0.00';
157
  }
158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  // Record the payment details
160
- update_post_meta( $payment, '_edd_payment_meta', apply_filters( 'edd_payment_meta', $payment_meta, $payment_data ) );
161
- update_post_meta( $payment, '_edd_payment_user_id', $payment_data['user_info']['id'] );
162
- update_post_meta( $payment, '_edd_payment_user_email', $payment_data['user_email'] );
163
- update_post_meta( $payment, '_edd_payment_user_ip', edd_get_ip() );
164
- update_post_meta( $payment, '_edd_payment_purchase_key', $payment_data['purchase_key'] );
165
- update_post_meta( $payment, '_edd_payment_total', $payment_data['price'] );
166
- update_post_meta( $payment, '_edd_payment_mode', $mode );
167
- update_post_meta( $payment, '_edd_payment_gateway', $gateway );
 
 
 
 
168
  if ( ! empty( $discount ) ) {
169
- update_post_meta( $payment, '_edd_payment_discount_id', $discount->ID );
170
  }
171
 
172
  if( edd_get_option( 'enable_sequential' ) ) {
173
- update_post_meta( $payment, '_edd_payment_number', $number );
174
  }
175
 
176
  // Clear the user's purchased cache
@@ -193,19 +235,26 @@ function edd_insert_payment( $payment_data = array() ) {
193
  * @return void
194
  */
195
  function edd_update_payment_status( $payment_id, $new_status = 'publish' ) {
 
196
  if ( $new_status == 'completed' || $new_status == 'complete' ) {
197
  $new_status = 'publish';
198
  }
199
 
 
 
 
 
200
  $payment = get_post( $payment_id );
201
 
202
- if ( is_wp_error( $payment ) || !is_object( $payment ) )
203
  return;
 
204
 
205
  $old_status = $payment->post_status;
206
 
207
- if ( $old_status === $new_status )
208
  return; // Don't permit status changes that aren't changes
 
209
 
210
  $do_change = apply_filters( 'edd_should_update_payment_status', true, $payment_id, $new_status, $old_status );
211
 
@@ -227,13 +276,24 @@ function edd_update_payment_status( $payment_id, $new_status = 'publish' ) {
227
  *
228
  * @since 1.0
229
  * @global $edd_logs
 
230
  * @uses EDD_Logging::delete_logs()
 
231
  * @param int $payment_id Payment ID (default: 0)
 
 
 
232
  * @return void
233
  */
234
- function edd_delete_purchase( $payment_id = 0 ) {
235
  global $edd_logs;
236
 
 
 
 
 
 
 
237
  $downloads = edd_get_payment_meta_downloads( $payment_id );
238
 
239
  if ( is_array( $downloads ) ) {
@@ -243,18 +303,37 @@ function edd_delete_purchase( $payment_id = 0 ) {
243
  }
244
  }
245
 
246
- $amount = edd_get_payment_amount( $payment_id );
247
- $status = get_post( $payment_id )->post_status;
 
 
 
 
248
 
249
  if( $status == 'revoked' || $status == 'publish' ) {
250
  // Only decrease earnings if they haven't already been decreased (or were never increased for this payment)
251
  edd_decrease_total_earnings( $amount );
252
  // Clear the This Month earnings (this_monththis_month is NOT a typo)
253
  delete_transient( md5( 'edd_earnings_this_monththis_month' ) );
 
 
 
 
 
 
 
 
254
  }
255
 
256
  do_action( 'edd_payment_delete', $payment_id );
257
 
 
 
 
 
 
 
 
258
  // Remove the payment
259
  wp_delete_post( $payment_id, true );
260
 
@@ -270,6 +349,19 @@ function edd_delete_purchase( $payment_id = 0 ) {
270
  )
271
  );
272
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  do_action( 'edd_payment_deleted', $payment_id );
274
  }
275
 
@@ -283,25 +375,27 @@ function edd_delete_purchase( $payment_id = 0 ) {
283
  * @return void
284
  */
285
  function edd_undo_purchase( $download_id, $payment_id ) {
286
- if ( edd_is_test_mode() )
287
- return;
 
288
 
289
- $payment = get_post( $payment_id );
290
  $cart_details = edd_get_payment_meta_cart_details( $payment_id );
 
291
 
292
  if ( is_array( $cart_details ) ) {
 
293
  foreach ( $cart_details as $item ) {
 
 
 
 
294
  // Decrease earnings/sales and fire action once per quantity number
295
  for( $i = 0; $i < $item['quantity']; $i++ ) {
296
- $user_info = edd_get_payment_meta_user_info( $payment_id );
297
-
298
- // get the item's price
299
- $amount = isset( $item['price'] ) ? $item['price'] : false;
300
 
301
  // variable priced downloads
302
- if ( edd_has_variable_prices( $download_id ) ) {
303
- $price_id = isset( $item['item_number']['options']['price_id'] ) ? $item['item_number']['options']['price_id'] : null;
304
- $amount = ! isset( $item['price'] ) && 0 !== $item['price'] ? edd_get_price_option_amount( $download_id, $price_id ) : $item['price'];
305
  }
306
 
307
  if ( ! $amount ) {
@@ -309,14 +403,18 @@ function edd_undo_purchase( $download_id, $payment_id ) {
309
  $amount = edd_get_download_final_price( $download_id, $user_info, $amount );
310
  }
311
 
312
- // decrease earnings
313
- edd_decrease_earnings( $download_id, $amount );
314
-
315
- // decrease purchase count
316
- edd_decrease_purchase_count( $download_id );
317
  }
 
 
 
 
 
 
 
318
  }
 
319
  }
 
320
  }
321
 
322
 
@@ -422,12 +520,24 @@ function edd_count_payments( $args = array() ) {
422
 
423
  $count = $wpdb->get_results( $query, ARRAY_A );
424
 
425
- $stats = array();
426
- foreach ( get_post_stati() as $state )
 
 
 
 
 
427
  $stats[$state] = 0;
 
 
 
 
 
 
 
428
 
429
- foreach ( (array) $count as $row )
430
  $stats[$row['post_status']] = $row['num_posts'];
 
431
 
432
  $stats = (object) $stats;
433
  wp_cache_set( $cache_key, $stats, 'counts' );
@@ -501,6 +611,19 @@ function edd_get_payment_statuses() {
501
  return apply_filters( 'edd_payment_statuses', $payment_statuses );
502
  }
503
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
  /**
505
  * Get Earnings By Date
506
  *
@@ -584,9 +707,9 @@ function edd_get_sales_by_date( $day = null, $month_num = null, $year = null, $h
584
 
585
  if ( ! empty( $hour ) )
586
  $args['hour'] = $hour;
587
-
588
  $args = apply_filters( 'edd_get_sales_by_date_args', $args );
589
-
590
  $key = md5( serialize( $args ) );
591
  $count = get_transient( $key, 'edd' );
592
 
@@ -689,7 +812,7 @@ function edd_get_total_earnings() {
689
  $total = 0; // Don't ever show negative earnings
690
  }
691
 
692
- return apply_filters( 'edd_total_earnings', round( $total, 2 ) );
693
  }
694
 
695
  /**
@@ -728,22 +851,73 @@ function edd_decrease_total_earnings( $amount = 0 ) {
728
  *
729
  * @since 1.2
730
  * @param int $payment_id Payment ID
731
- * @return array $meta Payment Meta
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
732
  */
733
- function edd_get_payment_meta( $payment_id ) {
734
- $meta = get_post_meta( $payment_id, '_edd_payment_meta', true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
735
 
736
- // Payment meta was simplified in EDD v1.5, so these are here for backwards compatibility
737
- if ( ! isset( $meta['key'] ) )
738
- $meta['key'] = edd_get_payment_key( $payment_id );
739
 
740
- if ( ! isset( $meta['email'] ) )
741
- $meta['email'] = edd_get_payment_user_email( $payment_id );
742
 
743
- if ( ! isset( $meta['date'] ) )
744
- $meta['date'] = get_post_field( 'post_date', $payment_id );
745
 
746
- return apply_filters( 'edd_get_payment_meta', $meta, $payment_id );
747
  }
748
 
749
  /**
@@ -786,7 +960,7 @@ function edd_get_payment_meta_cart_details( $payment_id, $include_bundle_files =
786
  $payment_meta = edd_get_payment_meta( $payment_id );
787
  $cart_details = ! empty( $payment_meta['cart_details'] ) ? maybe_unserialize( $payment_meta['cart_details'] ) : array();
788
 
789
- if( ! empty( $cart_details ) ) {
790
 
791
  foreach( $cart_details as $key => $cart_item ) {
792
 
@@ -817,10 +991,10 @@ function edd_get_payment_meta_cart_details( $payment_id, $include_bundle_files =
817
  'quantity' => 1,
818
  'tax' => 0,
819
  'in_bundle' => 1,
820
- 'parent' => array(
821
- 'id' => $cart_item['id'],
822
- 'options' => isset( $cart_item['item_number']['options'] ) ? $cart_item['item_number']['options'] : array()
823
- )
824
  );
825
  }
826
  }
@@ -828,7 +1002,7 @@ function edd_get_payment_meta_cart_details( $payment_id, $include_bundle_files =
828
 
829
  }
830
 
831
- return apply_filters( 'edd_payment_meta_cart_details', $cart_details );
832
  }
833
 
834
  /**
@@ -839,7 +1013,7 @@ function edd_get_payment_meta_cart_details( $payment_id, $include_bundle_files =
839
  * @return string $email User Email
840
  */
841
  function edd_get_payment_user_email( $payment_id ) {
842
- $email = get_post_meta( $payment_id, '_edd_payment_user_email', true );
843
 
844
  return apply_filters( 'edd_payment_user_email', $email );
845
  }
@@ -852,11 +1026,24 @@ function edd_get_payment_user_email( $payment_id ) {
852
  * @return string $user_id User ID
853
  */
854
  function edd_get_payment_user_id( $payment_id ) {
855
- $user_id = get_post_meta( $payment_id, '_edd_payment_user_id', true );
856
 
857
  return apply_filters( 'edd_payment_user_id', $user_id );
858
  }
859
 
 
 
 
 
 
 
 
 
 
 
 
 
 
860
  /**
861
  * Get the status of the unlimited downloads flag
862
  *
@@ -865,7 +1052,7 @@ function edd_get_payment_user_id( $payment_id ) {
865
  * @return bool $unlimited
866
  */
867
  function edd_payment_has_unlimited_downloads( $payment_id ) {
868
- $unlimited = (bool) get_post_meta( $payment_id, '_edd_payment_unlimited_downloads', true );
869
 
870
  return apply_filters( 'edd_payment_unlimited_downloads', $unlimited );
871
  }
@@ -878,7 +1065,7 @@ function edd_payment_has_unlimited_downloads( $payment_id ) {
878
  * @return string $ip User IP
879
  */
880
  function edd_get_payment_user_ip( $payment_id ) {
881
- $ip = get_post_meta( $payment_id, '_edd_payment_user_ip', true );
882
  return apply_filters( 'edd_payment_user_ip', $ip );
883
  }
884
 
@@ -897,7 +1084,7 @@ function edd_get_payment_completed_date( $payment_id = 0 ) {
897
  return false; // This payment was never completed
898
  }
899
 
900
- $date = ( $date = get_post_meta( $payment_id, '_edd_completed_date', true ) ) ? $date : $payment->modified_date;
901
 
902
  return apply_filters( 'edd_payment_completed_date', $date, $payment_id );
903
  }
@@ -910,11 +1097,36 @@ function edd_get_payment_completed_date( $payment_id = 0 ) {
910
  * @return string $gateway Gateway
911
  */
912
  function edd_get_payment_gateway( $payment_id ) {
913
- $gateway = get_post_meta( $payment_id, '_edd_payment_gateway', true );
914
 
915
  return apply_filters( 'edd_payment_gateway', $gateway );
916
  }
917
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
918
  /**
919
  * Get the purchase key for a purchase
920
  *
@@ -923,7 +1135,7 @@ function edd_get_payment_gateway( $payment_id ) {
923
  * @return string $key Purchase key
924
  */
925
  function edd_get_payment_key( $payment_id = 0 ) {
926
- $key = get_post_meta( $payment_id, '_edd_payment_purchase_key', true );
927
  return apply_filters( 'edd_payment_key', $key, $payment_id );
928
  }
929
 
@@ -942,16 +1154,16 @@ function edd_get_payment_number( $payment_id = 0 ) {
942
 
943
  if( edd_get_option( 'enable_sequential' ) ) {
944
 
945
- $number = get_post_meta( $payment_id, '_edd_payment_number', true );
946
 
947
  if( ! $number ) {
948
-
949
  $number = $payment_id;
950
-
951
  }
952
-
953
  }
954
-
955
  return apply_filters( 'edd_payment_number', $number, $payment_id );
956
  }
957
 
@@ -975,10 +1187,10 @@ function edd_get_next_payment_number() {
975
 
976
  $payments = new EDD_Payments_Query( array( 'number' => 1, 'order' => 'DESC', 'orderby' => 'ID', 'output' => 'posts', 'fields' => 'ids' ) );
977
 
978
- $last_payment = $payments->get_payments();
979
 
980
  if( $last_payment ) {
981
-
982
  $number = edd_get_payment_number( $last_payment[0] );
983
 
984
  if( empty( $number ) ) {
@@ -1022,7 +1234,7 @@ function edd_get_next_payment_number() {
1022
  */
1023
  function edd_payment_amount( $payment_id = 0 ) {
1024
  $amount = edd_get_payment_amount( $payment_id );
1025
- return edd_currency_filter( edd_format_amount( $amount ) );
1026
  }
1027
  /**
1028
  * Get the amount associated with a payment
@@ -1033,10 +1245,10 @@ function edd_payment_amount( $payment_id = 0 ) {
1033
  */
1034
  function edd_get_payment_amount( $payment_id ) {
1035
 
1036
- $amount = get_post_meta( $payment_id, '_edd_payment_total', true );
1037
 
1038
  if ( empty( $amount ) && '0.00' != $amount ) {
1039
- $meta = get_post_meta( $payment_id, '_edd_payment_meta', true );
1040
  $meta = maybe_unserialize( $meta );
1041
 
1042
  if ( isset( $meta['amount'] ) ) {
@@ -1063,7 +1275,7 @@ function edd_get_payment_amount( $payment_id ) {
1063
  function edd_payment_subtotal( $payment_id = 0 ) {
1064
  $subtotal = edd_get_payment_subtotal( $payment_id );
1065
 
1066
- return edd_currency_filter( edd_format_amount( $subtotal ) );
1067
  }
1068
 
1069
  /**
@@ -1071,17 +1283,34 @@ function edd_payment_subtotal( $payment_id = 0 ) {
1071
  * returns a non formatted amount.
1072
  *
1073
  * @since 1.3.3
1074
- * @global $edd_options Array of all the EDD Options
1075
  * @param int $payment_id Payment ID
1076
  * @return float $subtotal Subtotal for payment (non formatted)
1077
  */
1078
  function edd_get_payment_subtotal( $payment_id = 0) {
1079
- global $edd_options;
1080
 
1081
- $subtotal = edd_get_payment_amount( $payment_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1082
 
1083
- $tax = edd_use_taxes() ? edd_get_payment_tax( $payment_id ) : 0;
1084
- $subtotal -= $tax;
1085
 
1086
  return apply_filters( 'edd_get_payment_subtotal', $subtotal, $payment_id );
1087
  }
@@ -1099,7 +1328,7 @@ function edd_get_payment_subtotal( $payment_id = 0) {
1099
  function edd_payment_tax( $payment_id = 0, $payment_meta = false ) {
1100
  $tax = edd_get_payment_tax( $payment_id, $payment_meta );
1101
 
1102
- return edd_currency_filter( edd_format_amount( $tax ) );
1103
  }
1104
 
1105
  /**
@@ -1108,13 +1337,22 @@ function edd_payment_tax( $payment_id = 0, $payment_meta = false ) {
1108
  * @since 1.3.3
1109
  * @param int $payment_id Payment ID
1110
  * @param bool $payment_meta Get payment meta?
1111
- * @return float $subtotal Subtotal for payment (non formatted)
1112
  */
1113
  function edd_get_payment_tax( $payment_id = 0, $payment_meta = false ) {
1114
- if ( ! $payment_meta )
1115
- $payment_meta = edd_get_payment_meta( $payment_id );
1116
 
1117
- $tax = isset( $payment_meta['tax'] ) ? $payment_meta['tax'] : 0;
 
 
 
 
 
 
 
 
 
 
 
1118
 
1119
  return apply_filters( 'edd_get_payment_tax', $tax, $payment_id );
1120
  }
@@ -1134,7 +1372,7 @@ function edd_get_payment_fees( $payment_id = 0, $type = 'all' ) {
1134
  $fees = array();
1135
  $payment_fees = isset( $payment_meta['fees'] ) ? $payment_meta['fees'] : false;
1136
 
1137
- if ( ! empty( $payment_fees ) ) {
1138
 
1139
  foreach ( $payment_fees as $fee_id => $fee ) {
1140
 
@@ -1157,6 +1395,46 @@ function edd_get_payment_fees( $payment_id = 0, $type = 'all' ) {
1157
  return apply_filters( 'edd_get_payment_fees', $fees, $payment_id );
1158
  }
1159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  *
5
  * @package EDD
6
  * @subpackage Payments
7
+ * @copyright Copyright (c) 2015, Pippin Williamson
8
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
  * @since 1.0
10
  */
80
 
81
  break;
82
 
83
+ case 'payment_number':
84
+ $payment = edd_get_payments( array(
85
+ 'meta_key' => '_edd_payment_number',
86
+ 'meta_value' => $value,
87
+ 'posts_per_page' => 1
88
+ ) );
89
+
90
+ if( $payment ) {
91
+ $payment = $payment[0];
92
+ }
93
+
94
+ break;
95
+
96
  default:
97
  return false;
98
  }
130
  $discount = edd_get_discount_by( 'code', $payment_data['user_info']['discount'] );
131
  }
132
 
133
+ // Find the next payment number, if enabled
134
  if( edd_get_option( 'enable_sequential' ) ) {
135
  $number = edd_get_next_payment_number();
136
  }
141
  'post_type' => 'edd_payment',
142
  'post_parent' => isset( $payment_data['parent'] ) ? $payment_data['parent'] : null,
143
  'post_date' => isset( $payment_data['post_date'] ) ? $payment_data['post_date'] : null,
144
+ 'post_date_gmt' => isset( $payment_data['post_date'] ) ? get_gmt_from_date( $payment_data['post_date'] ) : null
145
  ), $payment_data );
146
 
147
  // Create a blank payment
149
 
150
  if ( $payment ) {
151
 
152
+ if ( isset( $payment_data['tax'] ) ){
153
+ $cart_tax = $payment_data['tax'];
154
+ } else {
155
+ $taxes = $payment_data['cart_details'] ? wp_list_pluck( $payment_data['cart_details'], 'tax' ) : array();
156
+ $cart_tax = array_sum( $taxes );
157
+ $cart_tax += edd_get_cart_fee_tax();
158
+ }
159
 
160
  $payment_meta = array(
161
  'currency' => $payment_data['currency'],
162
  'downloads' => $payment_data['downloads'],
163
  'user_info' => $payment_data['user_info'],
164
  'cart_details' => $payment_data['cart_details'],
 
165
  );
166
 
167
  $mode = edd_is_test_mode() ? 'test' : 'live';
173
  $payment_data['price'] = '0.00';
174
  }
175
 
176
+ // Create or update a customer
177
+ $customer = new EDD_Customer( $payment_data['user_email'] );
178
+ $customer_data = array(
179
+ 'name' => $payment_data['user_info']['first_name'] . ' ' . $payment_data['user_info']['last_name'],
180
+ 'email' => $payment_data['user_email'],
181
+ 'user_id' => $payment_data['user_info']['id']
182
+ );
183
+
184
+ if ( empty( $customer->id ) ) {
185
+ $customer->create( $customer_data );
186
+ } else {
187
+ // Only update the customer if their name or email has changed
188
+ if ( $customer_data['email'] !== $customer->email || $customer_data['name'] !== $customer->name ) {
189
+ // We shouldn't be updating the User ID here, that is an admin task
190
+ unset( $customer_data['user_id'] );
191
+ $customer->update( $customer_data );
192
+ }
193
+ }
194
+
195
+ $customer->attach_payment( $payment, false );
196
+
197
  // Record the payment details
198
+ edd_update_payment_meta( $payment, '_edd_payment_meta', apply_filters( 'edd_payment_meta', $payment_meta, $payment_data ) );
199
+ edd_update_payment_meta( $payment, '_edd_payment_user_id', $payment_data['user_info']['id'] );
200
+ edd_update_payment_meta( $payment, '_edd_payment_customer_id', $customer->id );
201
+ edd_update_payment_meta( $payment, '_edd_payment_user_email', $payment_data['user_email'] );
202
+ edd_update_payment_meta( $payment, '_edd_payment_user_ip', edd_get_ip() );
203
+ edd_update_payment_meta( $payment, '_edd_payment_purchase_key', $payment_data['purchase_key'] );
204
+ edd_update_payment_meta( $payment, '_edd_payment_total', $payment_data['price'] );
205
+ edd_update_payment_meta( $payment, '_edd_payment_mode', $mode );
206
+ edd_update_payment_meta( $payment, '_edd_payment_gateway', $gateway );
207
+ edd_update_payment_meta( $payment, '_edd_payment_tax', $cart_tax );
208
+
209
+
210
  if ( ! empty( $discount ) ) {
211
+ edd_update_payment_meta( $payment, '_edd_payment_discount_id', $discount->ID );
212
  }
213
 
214
  if( edd_get_option( 'enable_sequential' ) ) {
215
+ edd_update_payment_meta( $payment, '_edd_payment_number', $number );
216
  }
217
 
218
  // Clear the user's purchased cache
235
  * @return void
236
  */
237
  function edd_update_payment_status( $payment_id, $new_status = 'publish' ) {
238
+
239
  if ( $new_status == 'completed' || $new_status == 'complete' ) {
240
  $new_status = 'publish';
241
  }
242
 
243
+ if( empty( $payment_id ) ) {
244
+ return;
245
+ }
246
+
247
  $payment = get_post( $payment_id );
248
 
249
+ if ( is_wp_error( $payment ) || ! is_object( $payment ) ) {
250
  return;
251
+ }
252
 
253
  $old_status = $payment->post_status;
254
 
255
+ if ( $old_status === $new_status ) {
256
  return; // Don't permit status changes that aren't changes
257
+ }
258
 
259
  $do_change = apply_filters( 'edd_should_update_payment_status', true, $payment_id, $new_status, $old_status );
260
 
276
  *
277
  * @since 1.0
278
  * @global $edd_logs
279
+ *
280
  * @uses EDD_Logging::delete_logs()
281
+ *
282
  * @param int $payment_id Payment ID (default: 0)
283
+ * @param bool $update_customer If we should update the customer stats (default:true)
284
+ * @param bool $delete_download_logs If we should remove all file download logs associated with the payment (default:false)
285
+ *
286
  * @return void
287
  */
288
+ function edd_delete_purchase( $payment_id = 0, $update_customer = true, $delete_download_logs = false ) {
289
  global $edd_logs;
290
 
291
+ $post = get_post( $payment_id );
292
+
293
+ if( !$post ) {
294
+ return;
295
+ }
296
+
297
  $downloads = edd_get_payment_meta_downloads( $payment_id );
298
 
299
  if ( is_array( $downloads ) ) {
303
  }
304
  }
305
 
306
+
307
+ $amount = edd_get_payment_amount( $payment_id );
308
+ $status = $post->post_status;
309
+ $customer_id = edd_get_payment_customer_id( $payment_id );
310
+
311
+ $customer = new EDD_Customer( $customer_id );
312
 
313
  if( $status == 'revoked' || $status == 'publish' ) {
314
  // Only decrease earnings if they haven't already been decreased (or were never increased for this payment)
315
  edd_decrease_total_earnings( $amount );
316
  // Clear the This Month earnings (this_monththis_month is NOT a typo)
317
  delete_transient( md5( 'edd_earnings_this_monththis_month' ) );
318
+
319
+ if( $customer->id && $update_customer ) {
320
+
321
+ // Decrement the stats for the customer
322
+ $customer->decrease_purchase_count();
323
+ $customer->decrease_value( $amount );
324
+
325
+ }
326
  }
327
 
328
  do_action( 'edd_payment_delete', $payment_id );
329
 
330
+ if( $customer->id && $update_customer ) {
331
+
332
+ // Remove the payment ID from the customer
333
+ $customer->remove_payment( $payment_id );
334
+
335
+ }
336
+
337
  // Remove the payment
338
  wp_delete_post( $payment_id, true );
339
 
349
  )
350
  );
351
 
352
+ if ( $delete_download_logs ) {
353
+ $edd_logs->delete_logs(
354
+ null,
355
+ 'file_download',
356
+ array(
357
+ array(
358
+ 'key' => '_edd_log_payment_id',
359
+ 'value' => $payment_id
360
+ )
361
+ )
362
+ );
363
+ }
364
+
365
  do_action( 'edd_payment_deleted', $payment_id );
366
  }
367
 
375
  * @return void
376
  */
377
  function edd_undo_purchase( $download_id, $payment_id ) {
378
+ if ( edd_is_test_mode() ) {
379
+ return;
380
+ }
381
 
 
382
  $cart_details = edd_get_payment_meta_cart_details( $payment_id );
383
+ $user_info = edd_get_payment_meta_user_info( $payment_id );
384
 
385
  if ( is_array( $cart_details ) ) {
386
+
387
  foreach ( $cart_details as $item ) {
388
+
389
+ // get the item's price
390
+ $amount = isset( $item['price'] ) ? $item['price'] : false;
391
+
392
  // Decrease earnings/sales and fire action once per quantity number
393
  for( $i = 0; $i < $item['quantity']; $i++ ) {
 
 
 
 
394
 
395
  // variable priced downloads
396
+ if ( false === $amount && edd_has_variable_prices( $download_id ) ) {
397
+ $price_id = isset( $item['item_number']['options']['price_id'] ) ? $item['item_number']['options']['price_id'] : null;
398
+ $amount = ! isset( $item['price'] ) && 0 !== $item['price'] ? edd_get_price_option_amount( $download_id, $price_id ) : $item['price'];
399
  }
400
 
401
  if ( ! $amount ) {
403
  $amount = edd_get_download_final_price( $download_id, $user_info, $amount );
404
  }
405
 
 
 
 
 
 
406
  }
407
+
408
+ // decrease earnings
409
+ edd_decrease_earnings( $download_id, $amount );
410
+
411
+ // decrease purchase count
412
+ edd_decrease_purchase_count( $download_id, $item['quantity'] );
413
+
414
  }
415
+
416
  }
417
+
418
  }
419
 
420
 
520
 
521
  $count = $wpdb->get_results( $query, ARRAY_A );
522
 
523
+ $stats = array();
524
+ $statuses = get_post_stati();
525
+ if( isset( $statuses['private'] ) && empty( $args['s'] ) ) {
526
+ unset( $statuses['private'] );
527
+ }
528
+
529
+ foreach ( $statuses as $state ) {
530
  $stats[$state] = 0;
531
+ }
532
+
533
+ foreach ( (array) $count as $row ) {
534
+
535
+ if( 'private' == $row['post_status'] && empty( $args['s'] ) ) {
536
+ continue;
537
+ }
538
 
 
539
  $stats[$row['post_status']] = $row['num_posts'];
540
+ }
541
 
542
  $stats = (object) $stats;
543
  wp_cache_set( $cache_key, $stats, 'counts' );
611
  return apply_filters( 'edd_payment_statuses', $payment_statuses );
612
  }
613
 
614
+ /**
615
+ * Retrieves keys for all available statuses for payments
616
+ *
617
+ * @since 2.3
618
+ * @return array $payment_status All the available payment statuses
619
+ */
620
+ function edd_get_payment_status_keys() {
621
+ $statuses = array_keys( edd_get_payment_statuses() );
622
+ asort( $statuses );
623
+
624
+ return array_values( $statuses );
625
+ }
626
+
627
  /**
628
  * Get Earnings By Date
629
  *
707
 
708
  if ( ! empty( $hour ) )
709
  $args['hour'] = $hour;
710
+
711
  $args = apply_filters( 'edd_get_sales_by_date_args', $args );
712
+
713
  $key = md5( serialize( $args ) );
714
  $count = get_transient( $key, 'edd' );
715
 
812
  $total = 0; // Don't ever show negative earnings
813
  }
814
 
815
+ return apply_filters( 'edd_total_earnings', round( $total, edd_currency_decimal_filter() ) );
816
  }
817
 
818
  /**
851
  *
852
  * @since 1.2
853
  * @param int $payment_id Payment ID
854
+ * @param string $meta_key The meta key to pull
855
+ * @param bool $single Pull single meta entry or as an object
856
+ * @return mixed $meta Payment Meta
857
+ */
858
+ function edd_get_payment_meta( $payment_id = 0, $meta_key = '_edd_payment_meta', $single = true ) {
859
+
860
+ $meta = get_post_meta( $payment_id, $meta_key, $single );
861
+
862
+ if ( $meta_key === '_edd_payment_meta' ) {
863
+
864
+ // Payment meta was simplified in EDD v1.5, so these are here for backwards compatibility
865
+ if ( empty( $meta['key'] ) ) {
866
+ $meta['key'] = edd_get_payment_key( $payment_id );
867
+ }
868
+
869
+ if ( empty( $meta['email'] ) ) {
870
+ $meta['email'] = edd_get_payment_user_email( $payment_id );
871
+ }
872
+
873
+ if ( empty( $meta['date'] ) ) {
874
+ $meta['date'] = get_post_field( 'post_date', $payment_id );
875
+ }
876
+ }
877
+
878
+ $meta = apply_filters( 'edd_get_payment_meta_' . $meta_key, $meta, $payment_id );
879
+
880
+ return apply_filters( 'edd_get_payment_meta', $meta, $payment_id, $meta_key );
881
+ }
882
+
883
+ /**
884
+ * Update the meta for a payment
885
+ * @param integer $payment_id Payment ID
886
+ * @param string $meta_key Meta key to update
887
+ * @param string $meta_value Value to udpate to
888
+ * @param string $prev_value Previous value
889
+ * @return mixed Meta ID if successful, false if unsuccessful
890
  */
891
+ function edd_update_payment_meta( $payment_id = 0, $meta_key = '', $meta_value = '', $prev_value = '' ) {
892
+
893
+ if ( empty( $payment_id ) || empty( $meta_key ) ) {
894
+ return;
895
+ }
896
+
897
+ if ( $meta_key == 'key' || $meta_key == 'date' ) {
898
+
899
+ $current_meta = edd_get_payment_meta( $payment_id );
900
+ $current_meta[$meta_key] = $meta_value;
901
+
902
+ $meta_key = '_edd_payment_meta';
903
+ $meta_value = $current_meta;
904
+
905
+ } else if ( $meta_key == 'email' || $meta_key == '_edd_payment_user_email' ) {
906
+
907
+ $meta_value = apply_filters( 'edd_edd_update_payment_meta_' . $meta_key, $meta_value, $payment_id );
908
+ update_post_meta( $payment_id, '_edd_payment_user_email', $meta_value );
909
+
910
+ $current_meta = edd_get_payment_meta( $payment_id );
911
+ $current_meta['user_info']['email'] = $meta_value;
912
 
913
+ $meta_key = '_edd_payment_meta';
914
+ $meta_value = $current_meta;
 
915
 
916
+ }
 
917
 
918
+ $meta_value = apply_filters( 'edd_update_payment_meta_' . $meta_key, $meta_value, $payment_id );
 
919
 
920
+ return update_post_meta( $payment_id, $meta_key, $meta_value, $prev_value );
921
  }
922
 
923
  /**
960
  $payment_meta = edd_get_payment_meta( $payment_id );
961
  $cart_details = ! empty( $payment_meta['cart_details'] ) ? maybe_unserialize( $payment_meta['cart_details'] ) : array();
962
 
963
+ if( ! empty( $cart_details ) && is_array( $cart_details ) ) {
964
 
965
  foreach( $cart_details as $key => $cart_item ) {
966
 
991
  'quantity' => 1,
992
  'tax' => 0,
993
  'in_bundle' => 1,
994
+ 'parent' => array(
995
+ 'id' => $cart_item['id'],
996
+ 'options' => isset( $cart_item['item_number']['options'] ) ? $cart_item['item_number']['options'] : array()
997
+ )
998
  );
999
  }
1000
  }
1002
 
1003
  }
1004
 
1005
+ return apply_filters( 'edd_payment_meta_cart_details', $cart_details, $payment_id );
1006
  }
1007
 
1008
  /**
1013
  * @return string $email User Email
1014
  */
1015
  function edd_get_payment_user_email( $payment_id ) {
1016
+ $email = edd_get_payment_meta( $payment_id, '_edd_payment_user_email', true );
1017
 
1018
  return apply_filters( 'edd_payment_user_email', $email );
1019
  }
1026
  * @return string $user_id User ID
1027
  */
1028
  function edd_get_payment_user_id( $payment_id ) {
1029
+ $user_id = edd_get_payment_meta( $payment_id, '_edd_payment_user_id', true );
1030
 
1031
  return apply_filters( 'edd_payment_user_id', $user_id );
1032
  }
1033
 
1034
+ /**
1035
+ * Get the customer ID associated with a payment
1036
+ *
1037
+ * @since 2.1
1038
+ * @param int $payment_id Payment ID
1039
+ * @return string $customer_id Customer ID
1040
+ */
1041
+ function edd_get_payment_customer_id( $payment_id ) {
1042
+ $customer_id = get_post_meta( $payment_id, '_edd_payment_customer_id', true );
1043
+
1044
+ return apply_filters( 'edd_payment_customer_id', $customer_id );
1045
+ }
1046
+
1047
  /**
1048
  * Get the status of the unlimited downloads flag
1049
  *
1052
  * @return bool $unlimited
1053
  */
1054
  function edd_payment_has_unlimited_downloads( $payment_id ) {
1055
+ $unlimited = (bool) edd_get_payment_meta( $payment_id, '_edd_payment_unlimited_downloads', true );
1056
 
1057
  return apply_filters( 'edd_payment_unlimited_downloads', $unlimited );
1058
  }
1065
  * @return string $ip User IP
1066
  */
1067
  function edd_get_payment_user_ip( $payment_id ) {
1068
+ $ip = edd_get_payment_meta( $payment_id, '_edd_payment_user_ip', true );
1069
  return apply_filters( 'edd_payment_user_ip', $ip );
1070
  }
1071
 
1084
  return false; // This payment was never completed
1085
  }
1086
 
1087
+ $date = ( $date = edd_get_payment_meta( $payment_id, '_edd_completed_date', true ) ) ? $date : $payment->modified_date;
1088
 
1089
  return apply_filters( 'edd_payment_completed_date', $date, $payment_id );
1090
  }
1097
  * @return string $gateway Gateway
1098
  */
1099
  function edd_get_payment_gateway( $payment_id ) {
1100
+ $gateway = edd_get_payment_meta( $payment_id, '_edd_payment_gateway', true );
1101
 
1102
  return apply_filters( 'edd_payment_gateway', $gateway );
1103
  }
1104
 
1105
+ /**
1106
+ * Get the currency code a payment was made in
1107
+ *
1108
+ * @since 2.2
1109
+ * @param int $payment_id Payment ID
1110
+ * @return string $currency The currency code
1111
+ */
1112
+ function edd_get_payment_currency_code( $payment_id = 0 ) {
1113
+ $meta = edd_get_payment_meta( $payment_id );
1114
+ $currency = isset( $meta['currency'] ) ? $meta['currency'] : edd_get_currency();
1115
+ return apply_filters( 'edd_payment_currency_code', $currency, $payment_id );
1116
+ }
1117
+
1118
+ /**
1119
+ * Get the currency name a payment was made in
1120
+ *
1121
+ * @since 2.2
1122
+ * @param int $payment_id Payment ID
1123
+ * @return string $currency The currency name
1124
+ */
1125
+ function edd_get_payment_currency( $payment_id = 0 ) {
1126
+ $currency = edd_get_payment_currency_code( $payment_id );
1127
+ return apply_filters( 'edd_payment_currency', edd_get_currency_name( $currency ), $payment_id );
1128
+ }
1129
+
1130
  /**
1131
  * Get the purchase key for a purchase
1132
  *
1135
  * @return string $key Purchase key
1136
  */
1137
  function edd_get_payment_key( $payment_id = 0 ) {
1138
+ $key = edd_get_payment_meta( $payment_id, '_edd_payment_purchase_key', true );
1139
  return apply_filters( 'edd_payment_key', $key, $payment_id );
1140
  }
1141
 
1154
 
1155
  if( edd_get_option( 'enable_sequential' ) ) {
1156
 
1157
+ $number = edd_get_payment_meta( $payment_id, '_edd_payment_number', true );
1158
 
1159
  if( ! $number ) {
1160
+
1161
  $number = $payment_id;
1162
+
1163
  }
1164
+
1165
  }
1166
+
1167
  return apply_filters( 'edd_payment_number', $number, $payment_id );
1168
  }
1169
 
1187
 
1188
  $payments = new EDD_Payments_Query( array( 'number' => 1, 'order' => 'DESC', 'orderby' => 'ID', 'output' => 'posts', 'fields' => 'ids' ) );
1189
 
1190
+ $last_payment = $payments->get_payments();
1191
 
1192
  if( $last_payment ) {
1193
+
1194
  $number = edd_get_payment_number( $last_payment[0] );
1195
 
1196
  if( empty( $number ) ) {
1234
  */
1235
  function edd_payment_amount( $payment_id = 0 ) {
1236
  $amount = edd_get_payment_amount( $payment_id );
1237
+ return edd_currency_filter( edd_format_amount( $amount ), edd_get_payment_currency_code( $payment_id ) );
1238
  }
1239
  /**
1240
  * Get the amount associated with a payment
1245
  */
1246
  function edd_get_payment_amount( $payment_id ) {
1247
 
1248
+ $amount = edd_get_payment_meta( $payment_id, '_edd_payment_total', true );
1249
 
1250
  if ( empty( $amount ) && '0.00' != $amount ) {
1251
+ $meta = edd_get_payment_meta( $payment_id, '_edd_payment_meta', true );
1252
  $meta = maybe_unserialize( $meta );
1253
 
1254
  if ( isset( $meta['amount'] ) ) {
1275
  function edd_payment_subtotal( $payment_id = 0 ) {
1276
  $subtotal = edd_get_payment_subtotal( $payment_id );
1277
 
1278
+ return edd_currency_filter( edd_format_amount( $subtotal ), edd_get_payment_currency_code( $payment_id ) );
1279
  }
1280
 
1281
  /**
1283
  * returns a non formatted amount.
1284
  *
1285
  * @since 1.3.3
 
1286
  * @param int $payment_id Payment ID
1287
  * @return float $subtotal Subtotal for payment (non formatted)
1288
  */
1289
  function edd_get_payment_subtotal( $payment_id = 0) {
 
1290
 
1291
+ $subtotal = 0;
1292
+ $cart_details = edd_get_payment_meta_cart_details( $payment_id );
1293
+
1294
+ if( is_array( $cart_details ) ) {
1295
+
1296
+ foreach ( $cart_details as $item ) {
1297
+
1298
+ if( isset( $item['subtotal'] ) ) {
1299
+
1300
+ $subtotal += $item['subtotal'];
1301
+
1302
+ }
1303
+
1304
+ }
1305
+
1306
+ } else {
1307
+
1308
+ $subtotal = edd_get_payment_amount( $payment_id );
1309
+ $tax = edd_use_taxes() ? edd_get_payment_tax( $payment_id ) : 0;
1310
+ $subtotal -= $tax;
1311
+
1312
+ }
1313
 
 
 
1314
 
1315
  return apply_filters( 'edd_get_payment_subtotal', $subtotal, $payment_id );
1316
  }
1328
  function edd_payment_tax( $payment_id = 0, $payment_meta = false ) {
1329
  $tax = edd_get_payment_tax( $payment_id, $payment_meta );
1330
 
1331
+ return edd_currency_filter( edd_format_amount( $tax ), edd_get_payment_currency_code( $payment_id ) );
1332
  }
1333
 
1334
  /**
1337
  * @since 1.3.3
1338
  * @param int $payment_id Payment ID
1339
  * @param bool $payment_meta Get payment meta?
1340
+ * @return float $tax Tax for payment (non formatted)
1341
  */
1342
  function edd_get_payment_tax( $payment_id = 0, $payment_meta = false ) {
 
 
1343
 
1344
+ $tax = edd_get_payment_meta( $payment_id, '_edd_payment_tax', true );
1345
+
1346
+ // We don't have tax as it's own meta and no meta was passed
1347
+ if ( '' === $tax ) {
1348
+
1349
+ if ( ! $payment_meta ) {
1350
+ $payment_meta = edd_get_payment_meta( $payment_id );
1351
+ }
1352
+
1353
+ $tax = isset( $payment_meta['tax'] ) ? $payment_meta['tax'] : 0;
1354
+
1355
+ }
1356
 
1357
  return apply_filters( 'edd_get_payment_tax', $tax, $payment_id );
1358
  }
1372
  $fees = array();
1373
  $payment_fees = isset( $payment_meta['fees'] ) ? $payment_meta['fees'] : false;
1374
 
1375
+ if ( ! empty( $payment_fees ) && is_array( $payment_fees ) ) {
1376
 
1377
  foreach ( $payment_fees as $fee_id => $fee ) {
1378
 
1395
  return apply_filters( 'edd_get_payment_fees', $fees, $payment_id );
1396
  }
1397
 
1398
+ /**
1399
+ * Retrieves the transaction ID for the given payment
1400
+ *
1401
+ * @since 2.1
1402
+ * @param int payment_id Payment ID
1403
+ * @return string The Transaction ID
1404
+ */
1405
+ function edd_get_payment_transaction_id( $payment_id = 0 ) {
1406
+
1407
+ $transaction_id = false;
1408
+ $transaction_id = edd_get_payment_meta( $payment_id, '_edd_payment_transaction_id', true );
1409
+
1410
+ if ( empty( $