Paid Memberships Pro - Version 2.0

Version Description

  • 2018-12-31 =
  • SECURITY: Fixing how we escape things in the Memberships report SQL queries.
  • BUG FIX: Fixed issue where code in the Stripe gateway was cancelling old subscriptions early if users renewed with a different gateway.
  • BUG FIX: Fixed a warning on the Stripe Webhook service.
  • BUG FIX/ENHANCEMENT: Removing unused images from core plugin.
  • BUG FIX/ENHANCEMENT: Removed unused getTimestamp function.
  • BUG FIX/ENHANCEMENT: Updated Braintree/PHP Library to 3.36.0
  • BUG FIX/ENHANCEMENT: Prefixing Braintree plan name with pmpro_#
  • BUG FIX/ENHANCEMENT: Better table naming in queries for Memberships and Sales reports.
  • BUG FIX/ENHANCEMENT: Changing "blacklist" to "blocklist".
  • BUG FIX/ENHANCEMENT: Changing the appearance of the Discount Code "Apply" button on checkout to look more like a text link.
  • BUG FIX/ENHANCEMENT: Now calculating the next payment date with time, not SQL.
  • BUG FIX/ENHANCEMENT: Updated the pmpro_next_payment method of Stripe to check if a customer is delinquent to avoid returning a next payment date in the future if the last payment failed.
  • BUG FIX/ENHANCEMENT: Saving user ID in MemberOrder when a user already exists and they are checking out via an offsite gateway.
  • BUG FIX/ENHANCEMENT: Updating Stripe Webhook and PayPal IPN Handler to send the cancelled level ID for better cancellation emails.
  • BUG FIX/ENHANCEMENT: Brought back the Stripe Billing limit warnings. Here is a plugin to get billing limits working with Stripe https://github.com/strangerstudios/pmpro-stripe-billing-limits/blob/master/pmpro-stripe-billing-limits.php
  • FEATURE: Gutenberg / v5.0 Editor Blocks for Paid Memberships Pro pages, the Checkout Button and Membership "shortcode" functionality.
  • FEATURE: Added new "Dashboard" page and adjusted the entire menu structure for "Memberships".
  • FEATURE: Created new compatibility checks and included compatability functions for Beaver Builder, Elementor, and SiteOrigin Page Builder.
  • FEATURE: Added REST API routes for post membership access, and user membership level.
  • FEATURE: Added option to include the level's Confirmation Message in the Confirmation Email.
  • FEATURE: Added a filter by discount code to Memberships and Sales reports.
  • FEATURE: Added a filter by discount code to the Orders admin page.
  • FEATURE: Added a "Copy" option to discount codes.
  • FEATURE: Now allowing you to edit or add a discount code to a single Order edit.
  • FEATURE: Added the ability to export orders by discount code used.
  • FEATURE: Added new file for deprecated functions or hooks.
  • ENHANCEMENT: Moved "Memberships" menu page up in sidebar below Comments.
  • ENHANCEMENT: Replaced the Visits, Views, Logins report with the "Better Logins Report" Add On functionality.
  • ENHANCEMENT: Updating reports that use the Google Charts library to use the updated chart library (corechart.js).
  • ENHANCEMENT: Reports admin page is now loading reports via the add_meta_box WordPress function.
  • ENHANCEMENT: Added ability to filter membership reports for free or paid levels only.
  • ENHANCEMENT: Setting a default level at checkout so that the page doesn't redirect to the Levels page.
  • ENHANCEMENT: Showing the discount code used on the All Orders and single Order edit page.
  • ENHANCEMENT: Added ability to filter Orders by Free (Orders equal to $0), Paid (Orders greater than $0)
  • ENHANCEMENT: Now showing the Invoice's Order Status on the Membership Account page for orders (Paid, Pending or Refunded).
  • ENHANCEMENT: Adding additional quick search links when no members are found in members list search.
  • ENHANCEMENT: Added a check on the Add Ons page to hide Add Ons that are no longer supported or recommended.
  • ENHANCEMENT: Improved Responsive layout of the Memberships admin area for smaller devices.
  • ENHANCEMENT: Adding .gitattributes and gitignore. Important now for node stuff in particular.
Download this release

Release Info

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

Code changes from version 1.9.5.6 to 2.0

Files changed (293) hide show
  1. CHANGELOG.txt +41 -0
  2. adminpages/addons.php +53 -38
  3. adminpages/admin_header.php +101 -67
  4. adminpages/dashboard.php +396 -122
  5. adminpages/discountcodes.php +160 -142
  6. adminpages/functions.php +34 -1
  7. adminpages/membershiplevels.php +62 -9
  8. adminpages/memberslist.php +16 -1
  9. adminpages/orders-csv.php +27 -10
  10. adminpages/orders.php +136 -7
  11. adminpages/pagesettings.php +17 -11
  12. adminpages/paymentsettings.php +6 -6
  13. adminpages/reports.php +89 -63
  14. adminpages/reports/login.php +318 -226
  15. adminpages/reports/memberships.php +727 -763
  16. adminpages/reports/sales.php +606 -497
  17. blocks/account-invoices-section/block.js +65 -0
  18. blocks/account-invoices-section/block.php +39 -0
  19. blocks/account-invoices-section/editor.css +19 -0
  20. blocks/account-links-section/block.js +65 -0
  21. blocks/account-links-section/block.php +39 -0
  22. blocks/account-links-section/editor.css +19 -0
  23. blocks/account-membership-section/block.js +65 -0
  24. blocks/account-membership-section/block.php +41 -0
  25. blocks/account-membership-section/editor.css +19 -0
  26. blocks/account-page/block.js +83 -0
  27. blocks/account-page/block.php +58 -0
  28. blocks/account-page/editor.css +19 -0
  29. blocks/account-page/inspector.js +60 -0
  30. blocks/account-profile-section/block.js +66 -0
  31. blocks/account-profile-section/block.php +41 -0
  32. blocks/account-profile-section/editor.css +19 -0
  33. blocks/billing-page/block.js +65 -0
  34. blocks/billing-page/block.php +50 -0
  35. blocks/billing-page/editor.css +19 -0
  36. blocks/blocks.js +21 -0
  37. blocks/blocks.php +87 -0
  38. blocks/cancel-page/block.js +65 -0
  39. blocks/cancel-page/block.php +51 -0
  40. blocks/cancel-page/editor.css +19 -0
  41. blocks/checkout-button/block.js +100 -0
  42. blocks/checkout-button/block.php +64 -0
  43. blocks/checkout-button/editor.css +27 -0
  44. blocks/checkout-button/inspector.js +58 -0
  45. blocks/checkout-page/block.js +76 -0
  46. blocks/checkout-page/block.php +57 -0
  47. blocks/checkout-page/editor.css +22 -0
  48. blocks/checkout-page/inspector.js +41 -0
  49. blocks/confirmation-page/block.js +65 -0
  50. blocks/confirmation-page/block.php +50 -0
  51. blocks/confirmation-page/editor.css +19 -0
  52. blocks/i18n.js +1 -0
  53. blocks/invoice-page/block.js +65 -0
  54. blocks/invoice-page/block.php +50 -0
  55. blocks/invoice-page/editor.css +19 -0
  56. blocks/levels-page/block.js +65 -0
  57. blocks/levels-page/block.php +50 -0
  58. blocks/levels-page/editor.css +19 -0
  59. blocks/membership/block.js +108 -0
  60. blocks/membership/block.php +49 -0
  61. blocks/membership/editor.css +14 -0
  62. classes/class.memberorder.php +53 -2
  63. classes/class.pmproemail.php +8 -0
  64. classes/gateways/class.pmprogateway_authorizenet.php +3 -3
  65. classes/gateways/class.pmprogateway_braintree.php +102 -104
  66. classes/gateways/class.pmprogateway_cybersource.php +178 -178
  67. classes/gateways/class.pmprogateway_payflowpro.php +3 -3
  68. classes/gateways/class.pmprogateway_paypal.php +4 -4
  69. classes/gateways/class.pmprogateway_paypalexpress.php +7 -7
  70. classes/gateways/class.pmprogateway_paypalstandard.php +143 -143
  71. classes/gateways/class.pmprogateway_stripe.php +123 -109
  72. classes/gateways/class.pmprogateway_twocheckout.php +82 -82
  73. css/admin-rtl.css +0 -5
  74. css/admin.css +256 -42
  75. css/blocks.editor.css +13 -0
  76. css/blocks.style.css +27 -0
  77. css/frontend-rtl.css +1 -1
  78. css/frontend.css +27 -1
  79. email/checkout_check.html +2 -0
  80. email/checkout_express.html +1 -0
  81. email/checkout_free.html +1 -0
  82. email/checkout_freetrial.html +1 -0
  83. email/checkout_paid.html +1 -0
  84. email/checkout_trial.html +1 -0
  85. images/PaidMembershipsPro-grey.gif +0 -0
  86. images/PaidMembershipsPro.gif +0 -0
  87. images/bg_grad-chrome.gif +0 -0
  88. images/bg_grad-grey.gif +0 -0
  89. images/credit-card-back.svg +1 -0
  90. images/credit-card-front.svg +1 -0
  91. images/delete.gif +0 -0
  92. images/enlarge.gif +0 -0
  93. images/icon-pmproadmin16-sprite.png +0 -0
  94. images/icon-pmproadmin16-sprite_2x.png +0 -0
  95. images/icon-pmproadmin32.png +0 -0
  96. images/icon-pmproadmin32_2x.png +0 -0
  97. images/icon_alert.gif +0 -0
  98. images/icon_comment.gif +0 -0
  99. images/icon_comments.gif +0 -0
  100. images/icon_continue.gif +0 -0
  101. images/icon_delete.gif +0 -0
  102. images/icon_email.gif +0 -0
  103. images/icon_error.gif +0 -0
  104. images/icon_information.gif +0 -0
  105. images/icon_phone.gif +0 -0
  106. images/icon_search.gif +0 -0
  107. images/icon_success.gif +0 -0
  108. images/menu_users.png +0 -0
  109. images/printer-icon.svg +1 -0
  110. images/spacer.gif +0 -0
  111. images/tag_sale.png +0 -0
  112. includes/admin.php +55 -0
  113. includes/adminpages.php +231 -198
  114. includes/capabilities.php +2 -1
  115. includes/compatibility.php +34 -0
  116. includes/compatibility/beaver-builder.php +10 -0
  117. includes/compatibility/elementor.php +17 -0
  118. includes/compatibility/siteorigin.php +17 -0
  119. includes/deprecated.php +32 -0
  120. includes/functions.php +118 -33
  121. includes/init.php +42 -28
  122. includes/lib/Braintree/CHANGELOG.md +117 -3
  123. includes/lib/Braintree/LICENSE +1 -1
  124. includes/lib/Braintree/README.md +64 -12
  125. includes/lib/Braintree/composer.json +1 -1
  126. includes/lib/Braintree/lib/Braintree.php +8 -9
  127. includes/lib/Braintree/lib/Braintree/AccountUpdaterDailyReport.php +0 -2
  128. includes/lib/Braintree/lib/Braintree/AchMandate.php +0 -3
  129. includes/lib/Braintree/lib/Braintree/Address.php +0 -1
  130. includes/lib/Braintree/lib/Braintree/AddressGateway.php +0 -1
  131. includes/lib/Braintree/lib/Braintree/AmexExpressCheckoutCard.php +0 -2
  132. includes/lib/Braintree/lib/Braintree/AndroidPayCard.php +0 -1
  133. includes/lib/Braintree/lib/Braintree/ApplePayCard.php +1 -1
  134. includes/lib/Braintree/lib/Braintree/ApplePayGateway.php +65 -0
  135. includes/lib/Braintree/lib/Braintree/ApplePayOptions.php +28 -0
  136. includes/lib/Braintree/lib/Braintree/AuthorizationAdjustment.php +35 -0
  137. includes/lib/Braintree/lib/Braintree/Base.php +14 -3
  138. includes/lib/Braintree/lib/Braintree/BinData.php +30 -0
  139. includes/lib/Braintree/lib/Braintree/ClientToken.php +1 -1
  140. includes/lib/Braintree/lib/Braintree/ClientTokenGateway.php +2 -2
  141. includes/lib/Braintree/lib/Braintree/CoinbaseAccount.php +0 -2
  142. includes/lib/Braintree/lib/Braintree/Collection.php +0 -1
  143. includes/lib/Braintree/lib/Braintree/Configuration.php +90 -3
  144. includes/lib/Braintree/lib/Braintree/ConnectedMerchantPayPalStatusChanged.php +37 -0
  145. includes/lib/Braintree/lib/Braintree/ConnectedMerchantStatusTransitioned.php +37 -0
  146. includes/lib/Braintree/lib/Braintree/CredentialsParser.php +0 -1
  147. includes/lib/Braintree/lib/Braintree/CreditCard.php +7 -5
  148. includes/lib/Braintree/lib/Braintree/CreditCardGateway.php +2 -3
  149. includes/lib/Braintree/lib/Braintree/Customer.php +33 -4
  150. includes/lib/Braintree/lib/Braintree/CustomerGateway.php +45 -9
  151. includes/lib/Braintree/lib/Braintree/Digest.php +0 -2
  152. includes/lib/Braintree/lib/Braintree/Disbursement.php +15 -1
  153. includes/lib/Braintree/lib/Braintree/DisbursementDetails.php +0 -1
  154. includes/lib/Braintree/lib/Braintree/Dispute.php +97 -2
  155. includes/lib/Braintree/lib/Braintree/Dispute/EvidenceDetails.php +31 -0
  156. includes/lib/Braintree/lib/Braintree/Dispute/StatusHistoryDetails.php +20 -0
  157. includes/lib/Braintree/lib/Braintree/Dispute/TransactionDetails.php +0 -2
  158. includes/lib/Braintree/lib/Braintree/DisputeGateway.php +274 -0
  159. includes/lib/Braintree/lib/Braintree/DisputeSearch.php +90 -0
  160. includes/lib/Braintree/lib/Braintree/DocumentUpload.php +45 -0
  161. includes/lib/Braintree/lib/Braintree/DocumentUploadGateway.php +81 -0
  162. includes/lib/Braintree/lib/Braintree/EndsWithNode.php +23 -0
  163. includes/lib/Braintree/lib/Braintree/Error/Codes.php +101 -1
  164. includes/lib/Braintree/lib/Braintree/Error/ErrorCollection.php +0 -1
  165. includes/lib/Braintree/lib/Braintree/Error/Validation.php +1 -2
  166. includes/lib/Braintree/lib/Braintree/Error/ValidationErrorCollection.php +1 -2
  167. includes/lib/Braintree/lib/Braintree/EuropeBankAccount.php +0 -1
  168. includes/lib/Braintree/lib/Braintree/Exception.php +0 -1
  169. includes/lib/Braintree/lib/Braintree/Exception/Authentication.php +0 -1
  170. includes/lib/Braintree/lib/Braintree/Exception/Authorization.php +0 -1
  171. includes/lib/Braintree/lib/Braintree/Exception/Connection.php +17 -0
  172. includes/lib/Braintree/lib/Braintree/Exception/DownForMaintenance.php +0 -1
  173. includes/lib/Braintree/lib/Braintree/Exception/ForgedQueryString.php +0 -1
  174. includes/lib/Braintree/lib/Braintree/Exception/NotFound.php +0 -1
  175. includes/lib/Braintree/lib/Braintree/Exception/SSLCaFileNotFound.php +0 -1
  176. includes/lib/Braintree/lib/Braintree/Exception/SSLCertificate.php +0 -1
  177. includes/lib/Braintree/lib/Braintree/Exception/ServerError.php +0 -1
  178. includes/lib/Braintree/lib/Braintree/Exception/TestOperationPerformedInProduction.php +0 -1
  179. includes/lib/Braintree/lib/Braintree/Exception/Timeout.php +0 -1
  180. includes/lib/Braintree/lib/Braintree/Exception/TooManyRequests.php +0 -1
  181. includes/lib/Braintree/lib/Braintree/Exception/Unexpected.php +0 -1
  182. includes/lib/Braintree/lib/Braintree/Exception/UpgradeRequired.php +0 -1
  183. includes/lib/Braintree/lib/Braintree/Exception/ValidationsFailed.php +0 -1
  184. includes/lib/Braintree/lib/Braintree/FacilitatedDetails.php +29 -0
  185. includes/lib/Braintree/lib/Braintree/FacilitatorDetails.php +1 -1
  186. includes/lib/Braintree/lib/Braintree/Gateway.php +71 -1
  187. includes/lib/Braintree/lib/Braintree/GrantedPaymentInstrumentUpdate.php +73 -0
  188. includes/lib/Braintree/lib/Braintree/GraphQL.php +44 -0
  189. includes/lib/Braintree/lib/Braintree/Http.php +98 -22
  190. includes/lib/Braintree/lib/Braintree/IbanBankAccount.php +57 -0
  191. includes/lib/Braintree/lib/Braintree/IdealPayment.php +92 -0
  192. includes/lib/Braintree/lib/Braintree/IdealPaymentGateway.php +104 -0
  193. includes/lib/Braintree/lib/Braintree/Instance.php +0 -1
  194. includes/lib/Braintree/lib/Braintree/LocalPaymentCompleted.php +68 -0
  195. includes/lib/Braintree/lib/Braintree/MasterpassCard.php +141 -0
  196. includes/lib/Braintree/lib/Braintree/OAuthAccessRevocation.php +32 -0
  197. includes/lib/Braintree/lib/Braintree/OAuthCredentials.php +0 -2
  198. includes/lib/Braintree/lib/Braintree/OAuthGateway.php +4 -3
  199. includes/lib/Braintree/lib/Braintree/OAuthResult.php +0 -2
  200. includes/lib/Braintree/lib/Braintree/PaginatedCollection.php +15 -6
  201. includes/lib/Braintree/lib/Braintree/PartnerMerchant.php +0 -1
  202. includes/lib/Braintree/lib/Braintree/PayPalAccount.php +0 -2
  203. includes/lib/Braintree/lib/Braintree/PayPalAccountGateway.php +0 -2
  204. includes/lib/Braintree/lib/Braintree/PaymentInstrumentType.php +4 -0
  205. includes/lib/Braintree/lib/Braintree/PaymentMethod.php +0 -3
  206. includes/lib/Braintree/lib/Braintree/PaymentMethodGateway.php +41 -10
  207. includes/lib/Braintree/lib/Braintree/PaymentMethodNonce.php +4 -3
  208. includes/lib/Braintree/lib/Braintree/PaymentMethodNonceGateway.php +0 -3
  209. includes/lib/Braintree/lib/Braintree/ResourceCollection.php +0 -1
  210. includes/lib/Braintree/lib/Braintree/Result/CreditCardVerification.php +2 -1
  211. includes/lib/Braintree/lib/Braintree/Result/Error.php +0 -1
  212. includes/lib/Braintree/lib/Braintree/Result/Successful.php +1 -2
  213. includes/lib/Braintree/lib/Braintree/Result/UsBankAccountVerification.php +112 -0
  214. includes/lib/Braintree/lib/Braintree/SamsungPayCard.php +138 -0
  215. includes/lib/Braintree/lib/Braintree/Subscription.php +7 -4
  216. includes/lib/Braintree/lib/Braintree/Subscription/StatusDetails.php +0 -1
  217. includes/lib/Braintree/lib/Braintree/SubscriptionGateway.php +16 -5
  218. includes/lib/Braintree/lib/Braintree/Test/CreditCardNumbers.php +11 -1
  219. includes/lib/Braintree/lib/Braintree/Test/MerchantAccount.php +0 -1
  220. includes/lib/Braintree/lib/Braintree/Test/Nonces.php +12 -2
  221. includes/lib/Braintree/lib/Braintree/Test/Transaction.php +0 -2
  222. includes/lib/Braintree/lib/Braintree/Test/TransactionAmounts.php +0 -1
  223. includes/lib/Braintree/lib/Braintree/Test/VenmoSdk.php +0 -1
  224. includes/lib/Braintree/lib/Braintree/Transaction.php +57 -12
  225. includes/lib/Braintree/lib/Braintree/Transaction/AddressDetails.php +0 -1
  226. includes/lib/Braintree/lib/Braintree/Transaction/AmexExpressCheckoutCardDetails.php +0 -2
  227. includes/lib/Braintree/lib/Braintree/Transaction/AndroidPayCardDetails.php +0 -2
  228. includes/lib/Braintree/lib/Braintree/Transaction/ApplePayCardDetails.php +0 -2
  229. includes/lib/Braintree/lib/Braintree/Transaction/CoinbaseDetails.php +0 -2
  230. includes/lib/Braintree/lib/Braintree/Transaction/CreditCardDetails.php +1 -1
  231. includes/lib/Braintree/lib/Braintree/Transaction/CustomerDetails.php +0 -1
  232. includes/lib/Braintree/lib/Braintree/Transaction/EuropeBankAccountDetails.php +0 -1
  233. includes/lib/Braintree/lib/Braintree/Transaction/IdealPaymentDetails.php +23 -0
  234. includes/lib/Braintree/lib/Braintree/Transaction/LineItem.php +4 -0
  235. includes/lib/Braintree/lib/Braintree/Transaction/MasterpassCardDetails.php +51 -0
  236. includes/lib/Braintree/lib/Braintree/Transaction/PayPalDetails.php +0 -2
  237. includes/lib/Braintree/lib/Braintree/Transaction/SamsungPayCardDetails.php +52 -0
  238. includes/lib/Braintree/lib/Braintree/Transaction/StatusDetails.php +5 -6
  239. includes/lib/Braintree/lib/Braintree/Transaction/SubscriptionDetails.php +0 -1
  240. includes/lib/Braintree/lib/Braintree/Transaction/UsBankAccountDetails.php +1 -2
  241. includes/lib/Braintree/lib/Braintree/Transaction/VenmoAccountDetails.php +0 -2
  242. includes/lib/Braintree/lib/Braintree/Transaction/VisaCheckoutCardDetails.php +52 -0
  243. includes/lib/Braintree/lib/Braintree/TransactionGateway.php +30 -10
  244. includes/lib/Braintree/lib/Braintree/TransactionLineItem.php +54 -0
  245. includes/lib/Braintree/lib/Braintree/TransactionLineItemGateway.php +67 -0
  246. includes/lib/Braintree/lib/Braintree/TransactionSearch.php +1 -0
  247. includes/lib/Braintree/lib/Braintree/TransparentRedirect.php +0 -1
  248. includes/lib/Braintree/lib/Braintree/TransparentRedirectGateway.php +0 -1
  249. includes/lib/Braintree/lib/Braintree/UnknownPaymentMethod.php +0 -2
  250. includes/lib/Braintree/lib/Braintree/UsBankAccount.php +22 -2
  251. includes/lib/Braintree/lib/Braintree/UsBankAccountGateway.php +0 -2
  252. includes/lib/Braintree/lib/Braintree/UsBankAccountVerification.php +102 -0
  253. includes/lib/Braintree/lib/Braintree/UsBankAccountVerificationGateway.php +129 -0
  254. includes/lib/Braintree/lib/Braintree/UsBankAccountVerificationSearch.php +64 -0
  255. includes/lib/Braintree/lib/Braintree/Util.php +62 -6
  256. includes/lib/Braintree/lib/Braintree/VenmoAccount.php +0 -1
  257. includes/lib/Braintree/lib/Braintree/Version.php +2 -4
  258. includes/lib/Braintree/lib/Braintree/VisaCheckoutCard.php +154 -0
  259. includes/lib/Braintree/lib/Braintree/WebhookNotification.php +40 -54
  260. includes/lib/Braintree/lib/Braintree/WebhookNotificationGateway.php +77 -0
  261. includes/lib/Braintree/lib/Braintree/WebhookTesting.php +2 -382
  262. includes/lib/Braintree/lib/Braintree/WebhookTestingGateway.php +553 -0
  263. includes/lib/Braintree/lib/Braintree/Xml.php +0 -2
  264. includes/lib/Braintree/lib/Braintree/Xml/Generator.php +0 -4
  265. includes/lib/Braintree/lib/Braintree/Xml/Parser.php +0 -2
  266. includes/lib/Braintree/lib/ssl/api_braintreegateway_com.ca.crt +50 -0
  267. includes/lib/Stripe/CHANGELOG.md +0 -406
  268. includes/lib/Stripe/build.php +0 -36
  269. includes/lib/Stripe/composer.json +0 -36
  270. includes/license.php +1 -1
  271. includes/metaboxes.php +11 -13
  272. includes/notifications.php +8 -8
  273. includes/pointers.php +114 -0
  274. includes/rest-api.php +53 -0
  275. includes/updates.php +23 -0
  276. includes/updates/upgrade_1.php +3 -1
  277. js/corechart.js +231 -0
  278. js/editor.blocks.js +1 -0
  279. js/frontend.blocks.js +83 -0
  280. js/paid-memberships-pro.js +9 -13
  281. languages/paid-memberships-pro.mo +0 -0
  282. languages/paid-memberships-pro.po +1374 -1029
  283. languages/paid-memberships-pro.pot +1374 -1029
  284. pages/popup-cvv.html +2 -2
  285. paid-memberships-pro.php +12 -2
  286. preheaders/checkout.php +5 -0
  287. readme.txt +43 -39
  288. services/braintree-webhook.php +48 -29
  289. services/getfile.php +6 -6
  290. services/ipnhandler.php +1 -1
  291. services/stripe-webhook.php +2 -2
  292. shortcodes/checkout.php +0 -14
  293. shortcodes/pmpro_account.php +13 -2
CHANGELOG.txt CHANGED
@@ -1,5 +1,46 @@
1
== Changelog ==
2
3
= 1.9.5.6 - 2018-11-15 =
4
* BUG FIX: Fixed issue where Braintree would try to cancel a subscription twice if it was cancelled on the Braintree side.
5
* BUG FIX: Fixed bug in Braintree webhook when using certain versions of PHP.
1
== Changelog ==
2
3
+ = 2.0 - 2018-12-31 =
4
+ * SECURITY: Fixing how we escape things in the Memberships report SQL queries.
5
+ * BUG FIX: Fixed issue where code in the Stripe gateway was cancelling old subscriptions early if users renewed with a different gateway.
6
+ * BUG FIX: Fixed a warning on the Stripe Webhook service.
7
+ * BUG FIX/ENHANCEMENT: Removing unused images from core plugin.
8
+ * BUG FIX/ENHANCEMENT: Removed unused `getTimestamp` function.
9
+ * BUG FIX/ENHANCEMENT: Updated Braintree/PHP Library to 3.36.0
10
+ * BUG FIX/ENHANCEMENT: Prefixing Braintree plan name with `pmpro_#`
11
+ * BUG FIX/ENHANCEMENT: Better table naming in queries for Memberships and Sales reports.
12
+ * BUG FIX/ENHANCEMENT: Changing "blacklist" to "blocklist".
13
+ * BUG FIX/ENHANCEMENT: Changing the appearance of the Discount Code "Apply" button on checkout to look more like a text link.
14
+ * BUG FIX/ENHANCEMENT: Now calculating the next payment date with time, not SQL.
15
+ * BUG FIX/ENHANCEMENT: Updated the pmpro_next_payment method of Stripe to check if a customer is delinquent to avoid returning a next payment date in the future if the last payment failed.
16
+ * BUG FIX/ENHANCEMENT: Saving user ID in MemberOrder when a user already exists and they are checking out via an offsite gateway.
17
+ * BUG FIX/ENHANCEMENT: Updating Stripe Webhook and PayPal IPN Handler to send the cancelled level ID for better cancellation emails.
18
+ * BUG FIX/ENHANCEMENT: Brought back the Stripe Billing limit warnings. Here is a plugin to get billing limits working with Stripe https://github.com/strangerstudios/pmpro-stripe-billing-limits/blob/master/pmpro-stripe-billing-limits.php
19
+ * FEATURE: Gutenberg / v5.0 Editor Blocks for Paid Memberships Pro pages, the Checkout Button and Membership "shortcode" functionality.
20
+ * FEATURE: Added new "Dashboard" page and adjusted the entire menu structure for "Memberships".
21
+ * FEATURE: Created new compatibility checks and included compatability functions for Beaver Builder, Elementor, and SiteOrigin Page Builder.
22
+ * FEATURE: Added REST API routes for post membership access, and user membership level.
23
+ * FEATURE: Added option to include the level's Confirmation Message in the Confirmation Email.
24
+ * FEATURE: Added a filter by discount code to Memberships and Sales reports.
25
+ * FEATURE: Added a filter by discount code to the Orders admin page.
26
+ * FEATURE: Added a "Copy" option to discount codes.
27
+ * FEATURE: Now allowing you to edit or add a discount code to a single Order edit.
28
+ * FEATURE: Added the ability to export orders by discount code used.
29
+ * FEATURE: Added new file for deprecated functions or hooks.
30
+ * ENHANCEMENT: Moved "Memberships" menu page up in sidebar below Comments.
31
+ * ENHANCEMENT: Replaced the Visits, Views, Logins report with the "Better Logins Report" Add On functionality.
32
+ * ENHANCEMENT: Updating reports that use the Google Charts library to use the updated chart library (corechart.js).
33
+ * ENHANCEMENT: Reports admin page is now loading reports via the `add_meta_box` WordPress function.
34
+ * ENHANCEMENT: Added ability to filter membership reports for free or paid levels only.
35
+ * ENHANCEMENT: Setting a default level at checkout so that the page doesn't redirect to the Levels page.
36
+ * ENHANCEMENT: Showing the discount code used on the All Orders and single Order edit page.
37
+ * ENHANCEMENT: Added ability to filter Orders by Free (Orders equal to $0), Paid (Orders greater than $0)
38
+ * ENHANCEMENT: Now showing the Invoice's Order Status on the Membership Account page for orders (Paid, Pending or Refunded).
39
+ * ENHANCEMENT: Adding additional quick search links when no members are found in members list search.
40
+ * ENHANCEMENT: Added a check on the Add Ons page to hide Add Ons that are no longer supported or recommended.
41
+ * ENHANCEMENT: Improved Responsive layout of the Memberships admin area for smaller devices.
42
+ * ENHANCEMENT: Adding .gitattributes and gitignore. Important now for node stuff in particular.
43
+
44
= 1.9.5.6 - 2018-11-15 =
45
* BUG FIX: Fixed issue where Braintree would try to cancel a subscription twice if it was cancelled on the Braintree side.
46
* BUG FIX: Fixed bug in Braintree webhook when using certain versions of PHP.
adminpages/addons.php CHANGED
@@ -37,32 +37,46 @@
37
if(empty($status) || !in_array($status, $approved_statuses))
38
$status = "all";
39
40
- //split addons into groups for filtering
41
- $addons_all = $addons;
42
- $addons_active = array();
43
- $addons_inactive = array();
44
- $addons_update = array();
45
- $addons_uninstalled = array();
46
-
47
- foreach($addons as $addon)
48
- {
49
$plugin_file = $addon['Slug'] . '/' . $addon['Slug'] . '.php';
50
$plugin_file_abs = ABSPATH . 'wp-content/plugins/' . $plugin_file;
51
-
52
- //active?
53
- if(is_plugin_active($plugin_file))
54
- $addons_active[] = $addon;
55
- else
56
- $addons_inactive[] = $addon;
57
-
58
- //has update?
59
- if(isset($plugin_info->response[$plugin_file]))
60
- $addons_update[] = $addon;
61
62
- //not installed?
63
- if(!file_exists($plugin_file_abs))
64
- $addons_uninstalled[] = $addon;
65
}
66
?>
67
<h2><?php _e('Add Ons', 'paid-memberships-pro' ); ?></h2>
68
@@ -76,11 +90,11 @@
76
</p>
77
78
<ul class="subsubsub">
79
- <li class="all"><a href="admin.php?page=pmpro-addons&plugin_status=all" <?php if(empty($status) || $status == "all") { ?>class="current"<?php } ?>><?php _e('All', 'paid-memberships-pro' ); ?> <span class="count">(<?php echo count($addons);?>)</span></a> |</li>
80
- <li class="active"><a href="admin.php?page=pmpro-addons&plugin_status=active" <?php if($status == "active") { ?>class="current"<?php } ?>><?php _e('Active', 'paid-memberships-pro' ); ?> <span class="count">(<?php echo count($addons_active);?>)</span></a> |</li>
81
- <li class="inactive"><a href="admin.php?page=pmpro-addons&plugin_status=inactive" <?php if($status == "inactive") { ?>class="current"<?php } ?>><?php _e('Inactive', 'paid-memberships-pro' ); ?> <span class="count">(<?php echo count($addons_inactive);?>)</span></a> |</li>
82
- <li class="update"><a href="admin.php?page=pmpro-addons&plugin_status=update" <?php if($status == "update") { ?>class="current"<?php } ?>><?php _e('Update Available', 'paid-memberships-pro' ); ?> <span class="count">(<?php echo count($addons_update);?>)</span></a> |</li>
83
- <li class="uninstalled"><a href="admin.php?page=pmpro-addons&plugin_status=uninstalled" <?php if($status == "uninstalled") { ?>class="current"<?php } ?>><?php _e('Not Installed', 'paid-memberships-pro' ); ?> <span class="count">(<?php echo count($addons_uninstalled);?>)</span></a></li>
84
</ul>
85
86
<br /><br />
@@ -101,17 +115,18 @@
101
<tbody id="the-list">
102
<?php
103
//which addons to show?
104
- if($status == "active")
105
- $addons = $addons_active;
106
- elseif($status == "inactive")
107
- $addons = $addons_inactive;
108
- elseif($status == "update")
109
- $addons = $addons_update;
110
- elseif($status == "uninstalled")
111
- $addons = $addons_uninstalled;
112
- else
113
- $addons = $addons_all;
114
-
115
//no addons for this filter?
116
if(count($addons) < 1)
117
{
37
if(empty($status) || !in_array($status, $approved_statuses))
38
$status = "all";
39
40
+ // Split Add Ons into groups for filtering
41
+ $all_visible_addons = array();
42
+ $all_hidden_addons = array();
43
+ $active_addons = array();
44
+ $inactive_addons = array();
45
+ $update_available_addons = array();
46
+ $not_installed_addons = array();
47
+
48
+ // Build array of Visible, Hidden, Active, Inactive, Installed, and Not Installed Add Ons.
49
+ foreach ( $addons as $addon ) {
50
+
51
$plugin_file = $addon['Slug'] . '/' . $addon['Slug'] . '.php';
52
$plugin_file_abs = ABSPATH . 'wp-content/plugins/' . $plugin_file;
53
54
+ // Build Visible and Hidden arrays.
55
+ if ( empty ( $addon['HideFromAddOnsList'] ) || file_exists( $plugin_file_abs ) ) {
56
+ $all_visible_addons[] = $addon;
57
+ } else {
58
+ $all_hidden_addons[] = $addon;
59
+ }
60
+
61
+ // Build Active and Inactive arrays - exclude hidden Add Ons that are not installed.
62
+ if ( is_plugin_active( $plugin_file ) ) {
63
+ $active_addons[] = $addon;
64
+ } elseif ( empty ( $addon['HideFromAddOnsList'] ) || file_exists( $plugin_file_abs ) ) {
65
+ $inactive_addons[] = $addon;
66
+ }
67
+
68
+ // Build array of Add Ons that have an update available.
69
+ if ( isset( $plugin_info->response[$plugin_file] ) ) {
70
+ $update_available_addons[] = $addon;
71
+ }
72
+
73
+ // Build array of Add Ons that are visible and not installed.
74
+ if ( empty ( $addon['HideFromAddOnsList'] ) && ! file_exists( $plugin_file_abs ) ) {
75
+ $not_installed_addons[] = $addon;
76
+ }
77
+
78
}
79
+
80
?>
81
<h2><?php _e('Add Ons', 'paid-memberships-pro' ); ?></h2>
82
90
</p>
91
92
<ul class="subsubsub">
93
+ <li class="all"><a href="admin.php?page=pmpro-addons&plugin_status=all" <?php if(empty($status) || $status == "all") { ?>class="current"<?php } ?>><?php _e('All', 'paid-memberships-pro' ); ?> <span class="count">(<?php echo count($all_visible_addons);?>)</span></a> |</li>
94
+ <li class="active"><a href="admin.php?page=pmpro-addons&plugin_status=active" <?php if($status == "active") { ?>class="current"<?php } ?>><?php _e('Active', 'paid-memberships-pro' ); ?> <span class="count">(<?php echo count($active_addons);?>)</span></a> |</li>
95
+ <li class="inactive"><a href="admin.php?page=pmpro-addons&plugin_status=inactive" <?php if($status == "inactive") { ?>class="current"<?php } ?>><?php _e('Inactive', 'paid-memberships-pro' ); ?> <span class="count">(<?php echo count($inactive_addons);?>)</span></a> |</li>
96
+ <li class="update"><a href="admin.php?page=pmpro-addons&plugin_status=update" <?php if($status == "update") { ?>class="current"<?php } ?>><?php _e('Update Available', 'paid-memberships-pro' ); ?> <span class="count">(<?php echo count($update_available_addons);?>)</span></a> |</li>
97
+ <li class="uninstalled"><a href="admin.php?page=pmpro-addons&plugin_status=uninstalled" <?php if($status == "uninstalled") { ?>class="current"<?php } ?>><?php _e('Not Installed', 'paid-memberships-pro' ); ?> <span class="count">(<?php echo count($not_installed_addons);?>)</span></a></li>
98
</ul>
99
100
<br /><br />
115
<tbody id="the-list">
116
<?php
117
//which addons to show?
118
+ if ( $status == "active" ) {
119
+ $addons = $active_addons;
120
+ } elseif ( $status == "inactive") {
121
+ $addons = $inactive_addons;
122
+ } elseif ( $status == "update" ) {
123
+ $addons = $update_available_addons;
124
+ } elseif ( $status == "uninstalled" ) {
125
+ $addons = $not_installed_addons;
126
+ } else {
127
+ $addons = $all_visible_addons;
128
+ }
129
+
130
//no addons for this filter?
131
if(count($addons) < 1)
132
{
adminpages/admin_header.php CHANGED
@@ -1,16 +1,16 @@
1
<?php
2
require_once(dirname(__FILE__) . "/functions.php");
3
-
4
if(isset($_REQUEST['page']))
5
$view = sanitize_text_field($_REQUEST['page']);
6
else
7
$view = "";
8
-
9
global $pmpro_ready, $msg, $msgt;
10
$pmpro_ready = pmpro_is_ready();
11
if(!$pmpro_ready)
12
{
13
- global $pmpro_level_ready, $pmpro_gateway_ready, $pmpro_pages_ready;
14
if(!isset($edit))
15
{
16
if(isset($_REQUEST['edit']))
@@ -18,23 +18,23 @@
18
else
19
$edit = false;
20
}
21
-
22
if(empty($msg))
23
- $msg = -1;
24
- if(empty($pmpro_level_ready) && empty($edit))
25
$msgt .= " <a href=\"" . admin_url('admin.php?page=pmpro-membershiplevels&edit=-1') . "\">" . __("Add a membership level to get started.", 'paid-memberships-pro' ) . "</a>";
26
elseif($pmpro_level_ready && !$pmpro_pages_ready && $view != "pmpro-pagesettings")
27
- $msgt .= " <a href=\"" . admin_url('admin.php?page=pmpro-pagesettings') . "\">" . __("Set up the membership pages", 'paid-memberships-pro' ) . "</a>.";
28
elseif($pmpro_level_ready && $pmpro_pages_ready && !$pmpro_gateway_ready && $view != "pmpro-paymentsettings")
29
- $msgt .= " <a href=\"" . admin_url('admin.php?page=pmpro-paymentsettings') . "\">" . __("Set up your SSL certificate and payment gateway", 'paid-memberships-pro' ) . "</a>.";
30
-
31
if(empty($msgt))
32
$msg = false;
33
}
34
-
35
//check level compatibility
36
if(!pmpro_checkLevelForStripeCompatibility())
37
- {
38
$msg = -1;
39
$msgt = __("The billing details for some of your membership levels is not supported by Stripe.", 'paid-memberships-pro' );
40
if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
@@ -44,17 +44,17 @@
44
global $pmpro_stripe_error;
45
$pmpro_stripe_error = true;
46
$msg = -1;
47
- $msgt = __("The billing details for this level are not supported by Stripe. Please review the notes in the Billing Details section below.", 'paid-memberships-pro' );
48
- }
49
}
50
elseif($view == "pmpro-membershiplevels")
51
$msgt .= " " . __("The levels with issues are highlighted below.", 'paid-memberships-pro' );
52
else
53
- $msgt .= " <a href=\"" . admin_url('admin.php?page=pmpro-membershiplevels') . "\">" . __("Please edit your levels", 'paid-memberships-pro' ) . "</a>.";
54
}
55
-
56
if(!pmpro_checkLevelForPayflowCompatibility())
57
- {
58
$msg = -1;
59
$msgt = __("The billing details for some of your membership levels is not supported by Payflow.", 'paid-memberships-pro' );
60
if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
@@ -65,18 +65,18 @@
65
$pmpro_payflow_error = true;
66
$msg = -1;
67
$msgt = __("The billing details for this level are not supported by Payflow. Please review the notes in the Billing Details section below.", 'paid-memberships-pro' );
68
- }
69
}
70
elseif($view == "pmpro-membershiplevels")
71
$msgt .= " " . __("The levels with issues are highlighted below.", 'paid-memberships-pro' );
72
else
73
- $msgt .= " <a href=\"" . admin_url('admin.php?page=pmpro-membershiplevels') . "\">" . __("Please edit your levels", 'paid-memberships-pro' ) . "</a>.";
74
}
75
-
76
if(!pmpro_checkLevelForBraintreeCompatibility())
77
{
78
global $pmpro_braintree_error;
79
-
80
if ( false == $pmpro_braintree_error ) {
81
$msg = - 1;
82
$msgt = __( "The billing details for some of your membership levels is not supported by Braintree.", 'paid-memberships-pro' );
@@ -85,14 +85,14 @@
85
{
86
if(!pmpro_checkLevelForBraintreeCompatibility($_REQUEST['edit']))
87
{
88
-
89
// Don't overwrite existing messages
90
if ( false == $pmpro_braintree_error ) {
91
$pmpro_braintree_error = true;
92
$msg = - 1;
93
$msgt = __( "The billing details for this level are not supported by Braintree. Please review the notes in the Billing Details section below.", 'paid-memberships-pro' );
94
}
95
- }
96
}
97
elseif($view == "pmpro-membershiplevels")
98
$msgt .= " " . __("The levels with issues are highlighted below.", 'paid-memberships-pro' );
@@ -102,9 +102,9 @@
102
}
103
}
104
}
105
-
106
if(!pmpro_checkLevelForTwoCheckoutCompatibility())
107
- {
108
$msg = -1;
109
$msgt = __("The billing details for some of your membership levels is not supported by TwoCheckout.", 'paid-memberships-pro' );
110
if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
@@ -113,18 +113,18 @@
113
{
114
global $pmpro_twocheckout_error;
115
$pmpro_twocheckout_error = true;
116
-
117
$msg = -1;
118
- $msgt = __("The billing details for this level are not supported by 2Checkout. Please review the notes in the Billing Details section below.", 'paid-memberships-pro' );
119
- }
120
}
121
elseif($view == "pmpro-membershiplevels")
122
$msgt .= " " . __("The levels with issues are highlighted below.", 'paid-memberships-pro' );
123
else
124
- $msgt .= " <a href=\"" . admin_url('admin.php?page=pmpro-membershiplevels') . "\">" . __("Please edit your levels", 'paid-memberships-pro' ) . "</a>.";
125
}
126
-
127
- //check gateway dependencies
128
$gateway = pmpro_getOption('gateway');
129
if($gateway == "stripe" && version_compare( PHP_VERSION, '5.3.29', '>=' ) ) {
130
PMProGateway_stripe::dependencies();
@@ -136,72 +136,106 @@
136
} elseif($gateway == "braintree" && version_compare( PHP_VERSION, '5.4.45', '<' ) ) {
137
$msg = -1;
138
$msgt = sprintf(__("The Braintree Gateway requires PHP 5.4.45 or greater. We recommend upgrading to PHP %s or greater. Ask your host to upgrade.", "paid-memberships-pro" ), PMPRO_MIN_PHP_VERSION );
139
- }
140
-
141
//if no errors yet, let's check and bug them if < our PMPRO_PHP_MIN_VERSION
142
if( empty($msgt) && version_compare( PHP_VERSION, PMPRO_MIN_PHP_VERSION, '<' ) ) {
143
$msg = 1;
144
- $msgt = sprintf(__("We recommend upgrading to PHP %s or greater. Ask your host to upgrade.", "paid-memberships-pro" ), PMPRO_MIN_PHP_VERSION );
145
}
146
-
147
- if(!empty($msg))
148
- {
149
- ?>
150
<div id="message" class="<?php if($msg > 0) echo "updated fade"; else echo "error"; ?>"><p><?php echo $msgt?></p></div>
151
- <?php
152
- }
153
154
- ?>
155
- <div class="wrap pmpro_admin">
156
<div class="pmpro_banner">
157
- <a class="pmpro_logo" title="Paid Memberships Pro - Membership Plugin for WordPress" target="_blank" href="<?php echo pmpro_https_filter("https://www.paidmembershipspro.com/?utm_source=plugin&utm_medium=banner&utm_campaign=admin_header")?>"><img src="<?php echo PMPRO_URL?>/images/Paid-Memberships-Pro.png" width="350" height="75" border="0" alt="Paid Memberships Pro(c) - All Rights Reserved" /></a>
158
<div class="pmpro_meta">
159
- <span class="pmpro_tag pmpro_tag-grey">v<?php echo PMPRO_VERSION?></span>
160
- <a target="_blank" class="pmpro_tag pmpro_tag-grey" href="<?php echo pmpro_https_filter("https://www.paidmembershipspro.com/documentation?utm_source=plugin&utm_medium=banner&utm_campaign=admin_header")?>"><?php _e('Documentation', 'paid-memberships-pro' );?></a>
161
- <a target="_blank" class="pmpro_tag pmpro_tag-blue" href="https://www.paidmembershipspro.com/pricing/?utm_source=plugin&utm_medium=banner&utm_campaign=admin_header"><span class="dashicons dashicons-star-filled"></span> <?php _e('Get Support', 'paid-memberships-pro' );?></a>
162
</div>
163
- <br style="clear:both;" />
164
- </div>
165
-
166
<div id="pmpro_notifications">
167
</div>
168
<script>
169
jQuery(document).ready(function() {
170
jQuery.get('<?php echo get_admin_url(NULL, "/admin-ajax.php?action=pmpro_notifications"); ?>', function(data) {
171
if(data && data != 'NULL')
172
- jQuery('#pmpro_notifications').html(data);
173
});
174
});
175
</script>
176
-
177
<?php
178
- $settings_tabs = array("pmpro-membershiplevels", "pmpro-pagesettings", "pmpro-paymentsettings", "pmpro-emailsettings", "pmpro-advancedsettings", "pmpro-addons");
179
- if(in_array($view, $settings_tabs))
180
- {
181
- ?>
182
- <h2 class="nav-tab-wrapper">
183
- <?php if(current_user_can('pmpro_membershiplevels')) { ?>
184
- <a href="<?php echo admin_url('admin.php?page=pmpro-membershiplevels');?>" class="nav-tab<?php if($view == 'pmpro-membershiplevels') { ?> nav-tab-active<?php } ?>"><?php _e('Membership Levels', 'paid-memberships-pro' );?></a>
185
<?php } ?>
186
187
- <?php if(current_user_can('pmpro_pagesettings')) { ?>
188
- <a href="<?php echo admin_url('admin.php?page=pmpro-pagesettings');?>" class="nav-tab<?php if($view == 'pmpro-pagesettings') { ?> nav-tab-active<?php } ?>"><?php _e('Pages', 'paid-memberships-pro' );?></a>
189
<?php } ?>
190
191
- <?php if(current_user_can('pmpro_paymentsettings')) { ?>
192
- <a href="<?php echo admin_url('admin.php?page=pmpro-paymentsettings');?>" class="nav-tab<?php if($view == 'pmpro-paymentsettings') { ?> nav-tab-active<?php } ?>"><?php _e('Payment Gateway &amp; SSL', 'paid-memberships-pro' );?></a>
193
<?php } ?>
194
195
- <?php if(current_user_can('pmpro_emailsettings')) { ?>
196
- <a href="<?php echo admin_url('admin.php?page=pmpro-emailsettings');?>" class="nav-tab<?php if($view == 'pmpro-emailsettings') { ?> nav-tab-active<?php } ?>"><?php _e('Email', 'paid-memberships-pro' );?></a>
197
<?php } ?>
198
199
- <?php if(current_user_can('pmpro_advancedsettings')) { ?>
200
- <a href="<?php echo admin_url('admin.php?page=pmpro-advancedsettings');?>" class="nav-tab<?php if($view == 'pmpro-advancedsettings') { ?> nav-tab-active<?php } ?>"><?php _e('Advanced', 'paid-memberships-pro' );?></a>
201
<?php } ?>
202
203
<?php if(current_user_can('pmpro_addons')) { ?>
204
- <a href="<?php echo admin_url('admin.php?page=pmpro-addons');?>" class="nav-tab<?php if($view == 'pmpro-addons') { ?> nav-tab-active<?php } ?>"><?php _e('Add Ons', 'paid-memberships-pro' );?></a>
205
<?php } ?>
206
- </h2>
207
<?php } ?>
1
<?php
2
require_once(dirname(__FILE__) . "/functions.php");
3
+
4
if(isset($_REQUEST['page']))
5
$view = sanitize_text_field($_REQUEST['page']);
6
else
7
$view = "";
8
+
9
global $pmpro_ready, $msg, $msgt;
10
$pmpro_ready = pmpro_is_ready();
11
if(!$pmpro_ready)
12
{
13
+ global $pmpro_level_ready, $pmpro_gateway_ready, $pmpro_pages_ready;
14
if(!isset($edit))
15
{
16
if(isset($_REQUEST['edit']))
18
else
19
$edit = false;
20
}
21
+
22
if(empty($msg))
23
+ $msg = -1;
24
+ if(empty($pmpro_level_ready) && empty($edit) && $view != "pmpro-membershiplevels")
25
$msgt .= " <a href=\"" . admin_url('admin.php?page=pmpro-membershiplevels&edit=-1') . "\">" . __("Add a membership level to get started.", 'paid-memberships-pro' ) . "</a>";
26
elseif($pmpro_level_ready && !$pmpro_pages_ready && $view != "pmpro-pagesettings")
27
+ $msgt .= " <strong>" . __( 'Next step:', 'paid-memberships-pro' ) . "</strong> <a href=\"" . admin_url('admin.php?page=pmpro-pagesettings') . "\">" . __("Set up the membership pages", 'paid-memberships-pro' ) . "</a>.";
28
elseif($pmpro_level_ready && $pmpro_pages_ready && !$pmpro_gateway_ready && $view != "pmpro-paymentsettings")
29
+ $msgt .= " <strong>" . __( 'Next step:', 'paid-memberships-pro' ) . "</strong> <a href=\"" . admin_url('admin.php?page=pmpro-paymentsettings') . "\">" . __("Set up your SSL certificate and payment gateway", 'paid-memberships-pro' ) . "</a>.";
30
+
31
if(empty($msgt))
32
$msg = false;
33
}
34
+
35
//check level compatibility
36
if(!pmpro_checkLevelForStripeCompatibility())
37
+ {
38
$msg = -1;
39
$msgt = __("The billing details for some of your membership levels is not supported by Stripe.", 'paid-memberships-pro' );
40
if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
44
global $pmpro_stripe_error;
45
$pmpro_stripe_error = true;
46
$msg = -1;
47
+ $msgt = __("The billing details for this level are not supported by Stripe. Please review the notes in the Billing Details section below.", 'paid-memberships-pro' );
48
+ }
49
}
50
elseif($view == "pmpro-membershiplevels")
51
$msgt .= " " . __("The levels with issues are highlighted below.", 'paid-memberships-pro' );
52
else
53
+ $msgt .= " <a href=\"" . admin_url('admin.php?page=pmpro-membershiplevels') . "\">" . __("Please edit your levels", 'paid-memberships-pro' ) . "</a>.";
54
}
55
+
56
if(!pmpro_checkLevelForPayflowCompatibility())
57
+ {
58
$msg = -1;
59
$msgt = __("The billing details for some of your membership levels is not supported by Payflow.", 'paid-memberships-pro' );
60
if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
65
$pmpro_payflow_error = true;
66
$msg = -1;
67
$msgt = __("The billing details for this level are not supported by Payflow. Please review the notes in the Billing Details section below.", 'paid-memberships-pro' );
68
+ }
69
}
70
elseif($view == "pmpro-membershiplevels")
71
$msgt .= " " . __("The levels with issues are highlighted below.", 'paid-memberships-pro' );
72
else
73
+ $msgt .= " <a href=\"" . admin_url('admin.php?page=pmpro-membershiplevels') . "\">" . __("Please edit your levels", 'paid-memberships-pro' ) . "</a>.";
74
}
75
+
76
if(!pmpro_checkLevelForBraintreeCompatibility())
77
{
78
global $pmpro_braintree_error;
79
+
80
if ( false == $pmpro_braintree_error ) {
81
$msg = - 1;
82
$msgt = __( "The billing details for some of your membership levels is not supported by Braintree.", 'paid-memberships-pro' );
85
{
86
if(!pmpro_checkLevelForBraintreeCompatibility($_REQUEST['edit']))
87
{
88
+
89
// Don't overwrite existing messages
90
if ( false == $pmpro_braintree_error ) {
91
$pmpro_braintree_error = true;
92
$msg = - 1;
93
$msgt = __( "The billing details for this level are not supported by Braintree. Please review the notes in the Billing Details section below.", 'paid-memberships-pro' );
94
}
95
+ }
96
}
97
elseif($view == "pmpro-membershiplevels")
98
$msgt .= " " . __("The levels with issues are highlighted below.", 'paid-memberships-pro' );
102
}
103
}
104
}
105
+
106
if(!pmpro_checkLevelForTwoCheckoutCompatibility())
107
+ {
108
$msg = -1;
109
$msgt = __("The billing details for some of your membership levels is not supported by TwoCheckout.", 'paid-memberships-pro' );
110
if($view == "pmpro-membershiplevels" && !empty($_REQUEST['edit']) && $_REQUEST['edit'] > 0)
113
{
114
global $pmpro_twocheckout_error;
115
$pmpro_twocheckout_error = true;
116
+
117
$msg = -1;
118
+ $msgt = __("The billing details for this level are not supported by 2Checkout. Please review the notes in the Billing Details section below.", 'paid-memberships-pro' );
119
+ }
120
}
121
elseif($view == "pmpro-membershiplevels")
122
$msgt .= " " . __("The levels with issues are highlighted below.", 'paid-memberships-pro' );
123
else
124
+ $msgt .= " <a href=\"" . admin_url('admin.php?page=pmpro-membershiplevels') . "\">" . __("Please edit your levels", 'paid-memberships-pro' ) . "</a>.";
125
}
126
+
127
+ //check gateway dependencies
128
$gateway = pmpro_getOption('gateway');
129
if($gateway == "stripe" && version_compare( PHP_VERSION, '5.3.29', '>=' ) ) {
130
PMProGateway_stripe::dependencies();
136
} elseif($gateway == "braintree" && version_compare( PHP_VERSION, '5.4.45', '<' ) ) {
137
$msg = -1;
138
$msgt = sprintf(__("The Braintree Gateway requires PHP 5.4.45 or greater. We recommend upgrading to PHP %s or greater. Ask your host to upgrade.", "paid-memberships-pro" ), PMPRO_MIN_PHP_VERSION );
139
+ }
140
+
141
//if no errors yet, let's check and bug them if < our PMPRO_PHP_MIN_VERSION
142
if( empty($msgt) && version_compare( PHP_VERSION, PMPRO_MIN_PHP_VERSION, '<' ) ) {
143
$msg = 1;
144
+ $msgt = sprintf(__("We recommend upgrading to PHP %s or greater. Ask your host to upgrade.", "paid-memberships-pro" ), PMPRO_MIN_PHP_VERSION );
145
}
146
+
147
+ if( ! empty( $msg ) && $view != 'pmpro-dashboard' ) { ?>
148
<div id="message" class="<?php if($msg > 0) echo "updated fade"; else echo "error"; ?>"><p><?php echo $msgt?></p></div>
149
+ <?php } ?>
150
151
+ <div class="wrap pmpro_admin">
152
<div class="pmpro_banner">
153
+ <a class="pmpro_logo" title="Paid Memberships Pro - Membership Plugin for WordPress" target="_blank" href="<?php echo pmpro_https_filter("https://www.paidmembershipspro.com/?utm_source=plugin&utm_medium=banner&utm_campaign=admin_header")?>"><img src="<?php echo PMPRO_URL?>/images/Paid-Memberships-Pro.png" width="350" height="75" border="0" alt="Paid Memberships Pro(c) - All Rights Reserved" /></a>
154
<div class="pmpro_meta">
155
+ <span class="pmpro_version">v<?php echo PMPRO_VERSION?></span>
156
+ <a target="_blank" class="button button-documentation" href="<?php echo pmpro_https_filter("https://www.paidmembershipspro.com/documentation?utm_source=plugin&utm_medium=banner&utm_campaign=admin_header")?>"><?php _e('Documentation', 'paid-memberships-pro' );?></a>
157
+ <a target="_blank" class="button-primary button-support" href="https://www.paidmembershipspro.com/pricing/?utm_source=plugin&utm_medium=banner&utm_campaign=admin_header"><?php _e('Get Support', 'paid-memberships-pro' );?></a>
158
</div>
159
+ </div>
160
<div id="pmpro_notifications">
161
</div>
162
<script>
163
jQuery(document).ready(function() {
164
jQuery.get('<?php echo get_admin_url(NULL, "/admin-ajax.php?action=pmpro_notifications"); ?>', function(data) {
165
if(data && data != 'NULL')
166
+ jQuery('#pmpro_notifications').html(data);
167
});
168
});
169
</script>
170
+ <h2 class="pmpro_wp-notice-fix">&nbsp;</h2>
171
<?php
172
+ $settings_tabs = array(
173
+ 'pmpro-dashboard',
174
+ 'pmpro-membershiplevels',
175
+ 'pmpro-memberslist',
176
+ 'pmpro-reports',
177
+ 'pmpro-orders',
178
+ 'pmpro-discountcodes',
179
+ 'pmpro-pagesettings',
180
+ 'pmpro-paymentsettings',
181
+ 'pmpro-emailsettings',
182
+ 'pmpro-advancedsettings',
183
+ 'pmpro-addons'
184
+ );
185
+ if( in_array( $view, $settings_tabs ) ) { ?>
186
+ <nav class="nav-tab-wrapper">
187
+ <?php if(current_user_can('pmpro_dashboard')) { ?>
188
+ <a href="<?php echo admin_url('admin.php?page=pmpro-dashboard');?>" class="nav-tab<?php if($view == 'pmpro-dashboard') { ?> nav-tab-active<?php } ?>"><?php _e('Dashboard', 'paid-memberships-pro' );?></a>
189
<?php } ?>
190
191
+ <?php if(current_user_can('pmpro_memberslist')) { ?>
192
+ <a href="<?php echo admin_url('admin.php?page=pmpro-memberslist');?>" class="nav-tab<?php if($view == 'pmpro-memberslist') { ?> nav-tab-active<?php } ?>"><?php _e('Members', 'paid-memberships-pro' );?></a>
193
<?php } ?>
194
195
+ <?php if(current_user_can('pmpro_orders')) { ?>
196
+ <a href="<?php echo admin_url('admin.php?page=pmpro-orders');?>" class="nav-tab<?php if($view == 'pmpro-orders') { ?> nav-tab-active<?php } ?>"><?php _e('Orders', 'paid-memberships-pro' );?></a>
197
<?php } ?>
198
199
+ <?php if(current_user_can('pmpro_reports')) { ?>
200
+ <a href="<?php echo admin_url('admin.php?page=pmpro-reports');?>" class="nav-tab<?php if($view == 'pmpro-reports') { ?> nav-tab-active<?php } ?>"><?php _e('Reports', 'paid-memberships-pro' );?></a>
201
<?php } ?>
202
203
+ <?php if(current_user_can('pmpro_membershiplevels')) { ?>
204
+ <a href="<?php echo admin_url('admin.php?page=pmpro-membershiplevels');?>" class="nav-tab<?php if( in_array( $view, array( 'pmpro-membershiplevels', 'pmpro-discountcodes', 'pmpro-pagesettings', 'pmpro-paymentsettings', 'pmpro-emailsettings', 'pmpro-advancedsettings' ) ) ) { ?> nav-tab-active<?php } ?>"><?php _e('Settings', 'paid-memberships-pro' );?></a>
205
<?php } ?>
206
207
<?php if(current_user_can('pmpro_addons')) { ?>
208
+ <a href="<?php echo admin_url('admin.php?page=pmpro-addons');?>" class="nav-tab<?php if($view == 'pmpro-addons') { ?> nav-tab-active<?php } ?>"><?php _e('Add Ons', 'paid-memberships-pro' );?></a>
209
<?php } ?>
210
+ </nav>
211
+
212
+ <?php if( $view == 'pmpro-membershiplevels' || $view == 'pmpro-discountcodes' || $view == 'pmpro-pagesettings' || $view == 'pmpro-paymentsettings' || $view == 'pmpro-emailsettings' || $view == 'pmpro-advancedsettings' ) { ?>
213
+ <ul class="subsubsub">
214
+ <?php if(current_user_can('pmpro_membershiplevels')) { ?>
215
+ <li><a href="<?php echo admin_url('admin.php?page=pmpro-membershiplevels');?>" title="<?php _e('Membership Levels', 'paid-memberships-pro' );?>" class="<?php if($view == 'pmpro-membershiplevels') { ?>current<?php } ?>"><?php _e('Levels', 'paid-memberships-pro' );?></a>&nbsp;|&nbsp;</li>
216
+ <?php } ?>
217
+
218
+ <?php if(current_user_can('pmpro_discountcodes')) { ?>
219
+ <li><a href="<?php echo admin_url('admin.php?page=pmpro-discountcodes');?>" title="<?php _e('Discount Codes', 'paid-memberships-pro' );?>" class="<?php if($view == 'pmpro-discountcodes') { ?>current<?php } ?>"><?php _e('Discount Codes', 'paid-memberships-pro' );?></a>&nbsp;|&nbsp;</li>
220
+ <?php } ?>
221
+
222
+ <?php if(current_user_can('pmpro_pagesettings')) { ?>
223
+ <li><a href="<?php echo admin_url('admin.php?page=pmpro-pagesettings');?>" title="<?php _e('Page Settings', 'paid-memberships-pro' );?>" class="<?php if($view == 'pmpro-pagesettings') { ?>current<?php } ?>"><?php _e('Pages', 'paid-memberships-pro' );?></a>&nbsp;|&nbsp;</li>
224
+ <?php } ?>
225
+
226
+ <?php if(current_user_can('pmpro_paymentsettings')) { ?>
227
+ <li><a href="<?php echo admin_url('admin.php?page=pmpro-paymentsettings');?>" title="<?php _e('Payment Gateway &amp; SSL Settings', 'paid-memberships-pro' );?>" class="<?php if($view == 'pmpro-paymentsettings') { ?>current<?php } ?>"><?php _e('Payment Gateway &amp; SSL', 'paid-memberships-pro' );?></a>&nbsp;|&nbsp;</li>
228
+ <?php } ?>
229
+
230
+ <?php if(current_user_can('pmpro_emailsettings')) { ?>
231
+ <li><a href="<?php echo admin_url('admin.php?page=pmpro-emailsettings');?>" title="<?php _e('Email Settings', 'paid-memberships-pro' );?>" class="<?php if($view == 'pmpro-emailsettings') { ?>current<?php } ?>"><?php _e('Email', 'paid-memberships-pro' );?></a>&nbsp;|&nbsp;</li>
232
+ <?php } ?>
233
+
234
+ <?php if(current_user_can('pmpro_advancedsettings')) { ?>
235
+ <li><a href="<?php echo admin_url('admin.php?page=pmpro-advancedsettings');?>" title="<?php _e('Advanced Settings', 'paid-memberships-pro' );?>" class="<?php if($view == 'pmpro-advancedsettings') { ?>current<?php } ?>"><?php _e('Advanced', 'paid-memberships-pro' );?></a></li>
236
+ <?php } ?>
237
+ </ul>
238
+ <br class="clear" />
239
+ <?php } ?>
240
+
241
<?php } ?>
adminpages/dashboard.php CHANGED
@@ -1,127 +1,401 @@
1
<?php
2
- /*
3
- Much of this code is borroed from yst_plugin_tools.php in the Yoast WordPress SEO plugin. Thanks, Yoast!
4
- */
5
6
- global $pmpro_feed;
7
- $pmpro_feed = "http://feeds.feedburner.com/PaidMembershipsPro";
8
9
- function pmpro_postbox($id, $title, $content)
10
- {
11
- ?>
12
- <div id="<?php echo $id; ?>" class="postbox">
13
- <div class="handlediv" title="Click to toggle"><br /></div>
14
- <h3 class="hndle"><span><?php echo $title; ?></span></h3>
15
- <div class="inside">
16
- <?php echo $content; ?>
17
</div>
18
- </div>
19
<?php
20
- }
21
-
22
- function pmpro_fetch_rss_items( $num )
23
- {
24
- global $pmpro_feed;
25
-
26
- include_once(ABSPATH . WPINC . '/feed.php');
27
- $rss = fetch_feed( $pmpro_feed );
28
-
29
- // Bail if feed doesn't work
30
- if ( is_wp_error($rss) )
31
- return false;
32
-
33
- $rss_items = $rss->get_items( 0, $rss->get_item_quantity( $num ) );
34
-
35
- // If the feed was erroneously
36
- if ( !$rss_items ) {
37
- $md5 = md5( $pmpro_feed );
38
- delete_transient( 'feed_' . $md5 );
39
- delete_transient( 'feed_mod_' . $md5 );
40
- $rss = fetch_feed( $pmpro_feed );
41
- $rss_items = $rss->get_items( 0, $rss->get_item_quantity( $num ) );
42
- }
43
-
44
- return $rss_items;
45
- }
46
-
47
- /**
48
- * Box with latest news from PaidMembershipsPro.com for sidebar
49
- */
50
- function pmpro_news()
51
- {
52
- $rss_items = pmpro_fetch_rss_items( 5 );
53
-
54
- $content = '<ul>';
55
- if ( !$rss_items ) {
56
- $content .= '<li class="pmpro_news">no news items, feed might be broken...</li>';
57
- } else {
58
- foreach ( $rss_items as $item ) {
59
- $content .= '<li class="pmpro_news">';
60
- $content .= '<a class="rsswidget" href="'.esc_url( $item->get_permalink(), $protocolls=null, 'display' ).'">'. esc_html( $item->get_title() ) .'</a> ';
61
- $content .= '</li>';
62
- }
63
- }
64
- $content .= '</ul>';
65
- $pmpro_postbox('pmprolatest', 'Recent Updates from PaidMembershipsPro.com', $content);
66
- }
67
-
68
- /**
69
- * Widget with latest news from PaidMembershipsPro.com for dashbaord
70
- */
71
- function pmpro_db_widget()
72
- {
73
- global $pmpro_feed;
74
-
75
- $options = get_option('pmpro_pmprodbwidget');
76
-
77
- $network = '';
78
- if ( function_exists('is_network_admin') && is_network_admin() )
79
- $network = '_network';
80
-
81
- if (isset($_POST['pmpro_removedbwidget'])) {
82
- $options['removedbwidget'.$network] = true;
83
- update_option('pmpro_pmprodbwidget',$options);
84
- }
85
- if ( isset($options['removedbwidget'.$network]) && $options['removedbwidget'.$network] ) {
86
- echo "If you reload, this widget will be gone and never appear again, unless you decide to delete the database option 'pmpro_pmprodbwidget'.";
87
- return;
88
- }
89
-
90
- $rss_items = pmpro_fetch_rss_items( 3 );
91
-
92
- echo "<ul>";
93
-
94
- if ( !$rss_items ) {
95
- echo '<li class="pmpro_news">no news items, feed might be broken...</li>';
96
- } else {
97
- foreach ( $rss_items as $item ) {
98
- echo '<li class="pmpro_news">';
99
- echo '<a class="rsswidget" href="'.esc_url( $item->get_permalink(), $protocolls=null, 'display' ).'">'. esc_html( $item->get_title() ) .'</a>';
100
- echo ' <span class="rss-date">'. $item->get_date(get_option('date_format')) .'</span>';
101
- echo '<div class="rssSummary">'. esc_html( pmpro_text_limit( strip_tags( $item->get_description() ), 150 ) ).'</div>';
102
- echo '</li>';
103
- }
104
- }
105
-
106
- echo '</ul>';
107
- echo '<br class="clear"/><div style="margin-top:10px;border-top: 1px solid #ddd; padding-top: 10px; text-align:center;">';
108
- echo '<a target="_blank" href="'.$pmpro_feed.'"><img src="'.get_bloginfo('wpurl').'/wp-includes/images/rss.png" alt=""/> Subscribe with RSS</a>';
109
- echo ' &nbsp; &nbsp; &nbsp; ';
110
- echo '<a target="_blank" href="http://www.paidmembershipspro.com/blog/?utm_source=plugin&utm_medium=banner&utm_campaign=admin_dashboard">View Online</a>';
111
- echo '<form class="alignright" method="post"><input type="hidden" name="pmpro_removedbwidget" value="true"/><input title="Remove this widget from all users dashboards" class="button" type="submit" value="X"/></form>';
112
- echo '</div>';
113
- }
114
-
115
- function pmpro_widget_setup()
116
- {
117
- $network = '';
118
- if ( function_exists('is_network_admin') && is_network_admin() )
119
- $network = '_network';
120
-
121
- $options = get_option('pmpro_pmprodbwidget');
122
- if ( !isset($options['removedbwidget'.$network]) || !$options['removedbwidget'.$network] )
123
- wp_add_dashboard_widget( 'pmpro_db_widget' , 'The Latest From PaidMembershipsPro.com' , 'pmpro_db_widget');
124
- }
125
-
126
- add_action( 'wp_dashboard_setup', 'pmpro_widget_setup');
127
- ?>
1
<?php
2
+ /**
3
+ * The Memberships Dashboard admin page for Paid Memberships Pro
4
+ * @since 2.0
5
+ */
6
7
+ /**
8
+ * Add all the meta boxes for the dashboard.
9
+ */
10
+ function pmpro_dashboard_custom_meta_boxes() {
11
+ add_meta_box(
12
+ 'pmpro_dashboard_welcome',
13
+ __( 'Welcome to Paid Memberships Pro' ),
14
+ 'pmpro_dashboard_welcome_callback',
15
+ 'toplevel_page_pmpro-dashboard',
16
+ 'normal'
17
+ );
18
+ add_meta_box(
19
+ 'pmpro_dashboard_report_sales',
20
+ __( 'Sales and Revenue' ),
21
+ 'pmpro_report_sales_widget',
22
+ 'toplevel_page_pmpro-dashboard',
23
+ 'advanced'
24
+ );
25
+ add_meta_box(
26
+ 'pmpro_dashboard_report_membership_stats',
27
+ __( 'Membership Stats' ),
28
+ 'pmpro_report_memberships_widget',
29
+ 'toplevel_page_pmpro-dashboard',
30
+ 'advanced'
31
+ );
32
+ add_meta_box(
33
+ 'pmpro_dashboard_report_logins',
34
+ __( 'Visits, Views, and Logins' ),
35
+ 'pmpro_report_login_widget',
36
+ 'toplevel_page_pmpro-dashboard',
37
+ 'advanced'
38
+ );
39
+ add_meta_box(
40
+ 'pmpro_dashboard_report_recent_members',
41
+ __( 'Recent Members' ),
42
+ 'pmpro_dashboard_report_recent_members_callback',
43
+ 'toplevel_page_pmpro-dashboard',
44
+ 'side'
45
+ );
46
+ add_meta_box(
47
+ 'pmpro_dashboard_report_recent_orders',
48
+ __( 'Recent Orders' ),
49
+ 'pmpro_dashboard_report_recent_orders_callback',
50
+ 'toplevel_page_pmpro-dashboard',
51
+ 'side'
52
+ );
53
+ add_meta_box(
54
+ 'pmpro_dashboard_news_updates',
55
+ __( 'Paid Memberships Pro News and Updates' ),
56
+ 'pmpro_dashboard_news_updates_callback',
57
+ 'toplevel_page_pmpro-dashboard',
58
+ 'side'
59
+ );
60
+ }
61
+ add_action( 'add_meta_boxes', 'pmpro_dashboard_custom_meta_boxes', 10, 2 );
62
63
+ /**
64
+ * Enable add_meta_boxes function in this page.
65
+ */
66
+ do_action( 'add_meta_boxes', 'toplevel_page_pmpro-dashboard' );
67
+
68
+ /**
69
+ * Load the Paid Memberships Pro dashboard-area header
70
+ */
71
+ require_once( dirname( __FILE__ ) . '/admin_header.php' ); ?>
72
+
73
+ <form id="pmpro-dashboard-form" method="post" action="admin-post.php">
74
+
75
+ <div class="dashboard-widgets-wrap">
76
+ <div id="dashboard-widgets" class="metabox-holder">
77
+
78
+ <?php do_meta_boxes( 'toplevel_page_pmpro-dashboard', 'normal', '' ); ?>
79
+
80
+ <div id="postbox-container-1" class="postbox-container">
81
+ <?php do_meta_boxes( 'toplevel_page_pmpro-dashboard', 'advanced', '' ); ?>
82
</div>
83
+
84
+ <div id="postbox-container-2" class="postbox-container">
85
+ <?php do_meta_boxes( 'toplevel_page_pmpro-dashboard', 'side', '' ); ?>
86
+ </div>
87
+
88
+ <br class="clear">
89
+
90
+ </div> <!-- end dashboard-widgets -->
91
+
92
+ <?php wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false ); ?>
93
+ <?php wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false ); ?>
94
+
95
+ </div> <!-- end dashboard-widgets-wrap -->
96
+ </form>
97
+ <script type="text/javascript">
98
+ //<![CDATA[
99
+ jQuery(document).ready( function($) {
100
+ // close postboxes that should be closed
101
+ $('.if-js-closed').removeClass('if-js-closed').addClass('closed');
102
+ // postboxes setup
103
+ postboxes.add_postbox_toggles('toplevel_page_pmpro-dashboard');
104
+ });
105
+ //]]>
106
+ </script>
107
+ <?php
108
+
109
+ /**
110
+ * Callback function for pmpro_dashboard_welcome meta box.
111
+ */
112
+ function pmpro_dashboard_welcome_callback() { ?>
113
+ <div class="pmpro-dashboard-welcome-columns">
114
+ <div class="pmpro-dashboard-welcome-column">
115
+ <?php global $pmpro_level_ready, $pmpro_gateway_ready, $pmpro_pages_ready; ?>
116
+ <h3><?php echo esc_attr_e( 'Initial Setup', 'paid-memberships-pro' ); ?></h3>
117
+ <ul>
118
+ <?php if ( current_user_can( 'pmpro_membershiplevels' ) ) { ?>
119
+ <li>
120
+ <?php if ( empty( $pmpro_level_ready ) ) { ?>
121
+ <a href="<?php echo admin_url( 'admin.php?page=pmpro-membershiplevels&edit=-1' );?>"><i class="dashicons dashicons-admin-users"></i> <?php echo esc_attr_e( 'Create a Membership Level', 'paid-memberships-pro' ); ?></a>
122
+ <?php } else { ?>
123
+ <a href="<?php echo admin_url( 'admin.php?page=pmpro-membershiplevels' );?>"><i class="dashicons dashicons-admin-users"></i> <?php echo esc_attr_e( 'View Membership Levels', 'paid-memberships-pro' ); ?></a>
124
+ <?php } ?>
125
+ </li>
126
+ <?php } ?>
127
+
128
+ <?php if ( current_user_can( 'pmpro_pagesettings' ) ) { ?>
129
+ <li>
130
+ <?php if ( empty( $pmpro_pages_ready ) ) { ?>
131
+ <a href="<?php echo admin_url( 'admin.php?page=pmpro-pagesettings' );?>"><i class="dashicons dashicons-welcome-add-page"></i> <?php echo esc_attr_e( 'Generate Membership Pages', 'paid-memberships-pro' ); ?></a>
132
+ <?php } else { ?>
133
+ <a href="<?php echo admin_url( 'admin.php?page=pmpro-pagesettings' );?>"><i class="dashicons dashicons-welcome-add-page"></i> <?php echo esc_attr_e( 'Manage Membership Pages', 'paid-memberships-pro' ); ?>
134
+ <?php } ?>
135
+ </li>
136
+ <?php } ?>
137
+
138
+ <?php if ( current_user_can( 'pmpro_pagesettings' ) ) { ?>
139
+ <li>
140
+ <?php if ( empty( $pmpro_gateway_ready ) ) { ?>
141
+ <a href="<?php echo admin_url( 'admin.php?page=pmpro-paymentsettings' );?>"><i class="dashicons dashicons-cart"></i> <?php echo esc_attr_e( 'Configure Payment Settings', 'paid-memberships-pro' ); ?></a>
142
+ <?php } else { ?>
143
+ <a href="<?php echo admin_url( 'admin.php?page=pmpro-paymentsettings' );?>"><i class="dashicons dashicons-cart"></i> <?php echo esc_attr_e( 'Configure Payment Settings', 'paid-memberships-pro' ); ?></a>
144
+ <?php } ?>
145
+ </li>
146
+ <?php } ?>
147
+ </ul>
148
+ <h3><?php echo esc_attr_e( 'Other Settings', 'paid-memberships-pro' ); ?></h3>
149
+ <ul>
150
+ <?php if ( current_user_can( 'pmpro_emailsettings' ) ) { ?>
151
+ <li><a href="<?php echo admin_url( 'admin.php?page=pmpro-emailsettings' );?>"><i class="dashicons dashicons-email"></i> <?php echo esc_attr_e( 'Confirm Email Settings', 'paid-memberships-pro' );?></a></li>
152
+ <?php } ?>
153
+
154
+ <?php if ( current_user_can( 'pmpro_advancedsettings' ) ) { ?>
155
+ <li><a href="<?php echo admin_url( 'admin.php?page=pmpro-advancedsettings' );?>"><i class="dashicons dashicons-admin-settings"></i> <?php echo esc_attr_e( 'View Advanced Settings', 'paid-memberships-pro' ); ?></a></li>
156
+ <?php } ?>
157
+
158
+ <?php if ( current_user_can( 'pmpro_addons' ) ) { ?>
159
+ <li><a href="<?php echo admin_url( 'admin.php?page=pmpro-addons' );?>"><i class="dashicons dashicons-admin-plugins"></i> <?php echo esc_attr_e( 'Explore Add Ons for Additional Features', 'paid-memberships-pro' ); ?></a></li>
160
+ <?php } ?>
161
+ </ul>
162
+ <hr />
163
+ <p class="text-center">
164
+ <?php echo esc_html( __( 'For guidance as your begin these steps,', 'paid-memberships-pro' ) ); ?>
165
+ <a href="https://www.paidmembershipspro.com/documentation/initial-plugin-setup/?utm_source=plugin&utm_medium=banner&utm_campaign=welcome" target="_blank"><?php echo esc_attr_e( 'view the Initial Setup Video and Docs.', 'paid-memberships-pro' ); ?></a>
166
+ </p>
167
+ </div> <!-- end pmpro-dashboard-welcome-column -->
168
+ <div class="pmpro-dashboard-welcome-column">
169
+ <h3><?php echo esc_attr_e( 'Support License', 'paid-memberships-pro' ); ?></h3>
170
+ <?php
171
+ // Get saved license.
172
+ $key = get_option( 'pmpro_license_key', '' );
173
+ $pmpro_license_check = get_option( 'pmpro_license_check', array( 'license' => false, 'enddate' => 0 ) );
174
+ ?>
175
+ <?php if ( ! pmpro_license_isValid() && empty( $key ) ) { ?>
176
+ <p class="pmpro_message pmpro_error">
177
+ <strong><?php echo esc_html_e( 'No support license key found.', 'paid-memberships-pro' ); ?></strong><br />
178
+ <?php printf(__( '<a href="%s">Enter your key here &raquo;</a>', 'paid-memberships-pro' ), admin_url( 'options-general.php?page=pmpro_license_settings' ) );?>
179
+ </p>
180
+ <?php } elseif ( ! pmpro_license_isValid() ) { ?>
181
+ <p class="pmpro_message pmpro_alert">
182
+ <strong><?php echo esc_html_e( 'Your license is invalid or expired.', 'paid-memberships-pro' ); ?></strong><br />
183
+ <?php printf(__( '<a href="%s">View your membership account</a> to verify your license key.', 'paid-memberships-pro' ), 'https://www.paidmembershipspro.com/login/?redirect_to=/membership-account/?utm_source=plugin&utm_medium=banner&utm_campaign=welcome' );?>
184
+ <?php } else { ?>
185
+ <p class="pmpro_message pmpro_success"><?php printf(__( '<strong>Thank you!</strong> A valid <strong>%s</strong> license key has been used to activate your support license on this site.', 'paid-memberships-pro' ), ucwords($pmpro_license_check['license']));?></p>
186
+ <?php } ?>
187
+
188
+ <?php if ( ! pmpro_license_isValid() ) { ?>
189
+ <p><?php esc_html_e( 'An annual support license is recommended for websites running Paid Memberships Pro.', 'paid-memberships-pro' ); ?><br /><a href="http://www.paidmembershipspro.com/pricing/?utm_source=plugin&utm_medium=banner&utm_campaign=welcome" target="_blank"><?php esc_html_e( 'View Pricing &raquo;' , 'paid-memberships-pro' ); ?></a></p>
190
+ <p><a href="https://www.paidmembershipspro.com/membership-checkout/?level=20&utm_source=plugin&utm_medium=banner&utm_campaign=welcome" target="_blank" class="button button-action button-hero"><?php esc_attr_e( 'Upgrade', 'paid-memberships-pro' ); ?></a>
191
+ <?php } ?>
192
+ <hr />
193
+ <p><?php echo wp_kses_post( sprintf( __( 'Paid Memberships Pro and our add ons are distributed under the <a target="_blank" href="%s">GPLv2 license</a>. This means, among other things, that you may use the software on this site or any other site free of charge.', 'paid-memberships-pro' ), 'http://www.gnu.org/licenses/gpl-2.0.html' ) ); ?></p>
194
+ </div> <!-- end pmpro-dashboard-welcome-column -->
195
+ <div class="pmpro-dashboard-welcome-column">
196
+ <h3><?php esc_html_e( 'Get Involved', 'paid-memberships-pro' ); ?></h3>
197
+ <p><?php esc_html_e( 'There are many ways you can help support Paid Memberships Pro.', 'paid-memberships-pro' ); ?></p>
198
+ <p><?php esc_html_e( 'Get involved with our plugin development via GitHub.', 'paid-memberships-pro' ); ?> <a href="https://github.com/strangerstudios/paid-memberships-pro" target="_blank"><?php esc_html_e( 'View on GitHub', 'paid-memberships-pro' ); ?></a></p>
199
+ <p><a href="https://twitter.com/pmproplugin" target="_blank"><i class="dashicons dashicons-twitter"></i> <?php esc_html_e( 'Follow @pmproplugin on Twitter.', 'paid-memberships-pro' ); ?></a></p>
200
+ <p><a href="https://wordpress.org/plugins/paid-memberships-pro/#reviews" target="_blank"><i class="dashicons dashicons-wordpress"></i> <?php esc_html_e( 'Share an honest review at WordPress.org.', 'paid-memberships-pro' ); ?></a></p>
201
+ <hr />
202
+ <p><?php esc_html_e( 'Help translate Paid Memberships Pro into your language.', 'paid-memberships-pro' ); ?> <a href="https://translate.wordpress.org/projects/wp-plugins/paid-memberships-pro" target="_blank"><?php esc_html_e( 'Translation Dashboard', 'paid-memberships-pro' ); ?></a></p>
203
+ </div> <!-- end pmpro-dashboard-welcome-column -->
204
+ </div> <!-- end pmpro-dashboard-welcome-columns -->
205
+ <?php
206
+ }
207
+
208
+ /*
209
+ * Callback function for pmpro_dashboard_report_recent_members meta box to show last 5 recent members and a link to the Members List.
210
+ */
211
+ function pmpro_dashboard_report_recent_members_callback() {
212
+ global $wpdb;
213
+
214
+ $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership FROM $wpdb->users u LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id WHERE mu.membership_id > 0 AND mu.status = 'active' GROUP BY u.ID ORDER BY u.user_registered DESC LIMIT 5";
215
+
216
+ $sqlQuery = apply_filters( 'pmpro_members_list_sql', $sqlQuery );
217
+
218
+ $theusers = $wpdb->get_results( $sqlQuery ); ?>
219
+ <span id="pmpro_report_members" class="pmpro_report-holder">
220
+ <table class="wp-list-table widefat fixed striped">
221
+ <thead>
222
+ <tr>
223
+ <th><?php _e( 'Username', 'paid-memberships-pro' );?></th>
224
+ <th><?php _e( 'Membership', 'paid-memberships-pro' );?></th>
225
+ <th><?php _e( 'Joined', 'paid-memberships-pro' );?></th>
226
+ <th><?php _e( 'Expires', 'paid-memberships-pro' ); ?></th>
227
+ </tr>
228
+ </thead>
229
+ <tbody>
230
+ <?php if ( empty( $theusers ) ) { ?>
231
+ <tr>
232
+ <td colspan="4"><p><?php _e( 'No members found.', 'paid-memberships-pro' ); ?></p></td>
233
+ </tr>
234
+ <?php } else {
235
+ foreach ( $theusers as $auser ) {
236
+ $auser = apply_filters( 'pmpro_members_list_user', $auser );
237
+ //get meta
238
+ $theuser = get_userdata( $auser->ID ); ?>
239
+ <tr>
240
+ <td class="username column-username">
241
+ <?php echo get_avatar($theuser->ID, 32)?>
242
+ <strong>
243
+ <?php
244
+ $userlink = '<a href="' . get_edit_user_link( $theuser->ID ) . '">' . esc_attr( $theuser->user_login ) . '</a>';
245
+ $userlink = apply_filters( 'pmpro_members_list_user_link', $userlink, $theuser );
246
+ echo $userlink;
247
+ ?>
248
+ </strong>
249
+ </td>
250
+ <td><?php esc_attr_e( $auser->membership ); ?></td>
251
+ <td><?php echo date_i18n( get_option( 'date_format' ), strtotime( $theuser->user_registered, current_time( 'timestamp' ) ) ); ?></td>
252
+ <td>
253
+ <?php
254
+ if($auser->enddate)
255
+ echo apply_filters("pmpro_memberslist_expires_column", date_i18n(get_option('date_format'), $auser->enddate), $auser);
256
+ else
257
+ echo __(apply_filters("pmpro_memberslist_expires_column", "Never", $auser), "pmpro");
258
+ ?>
259
+ </td>
260
+ </tr>
261
+ <?php
262
+ }
263
+ }
264
+ ?>
265
+ </tbody>
266
+ </table>
267
+ </span>
268
+ <?php if ( ! empty( $theusers ) ) { ?>
269
+ <p class="text-center"><a class="button button-primary" href="<?php echo admin_url( 'admin.php?page=pmpro-memberslist' ); ?>"><?php esc_attr_e( 'View All Members ', 'paid-memberships-pro' ); ?></a></p>
270
+ <?php } ?>
271
<?php
272
+ }
273
+
274
+ /*
275
+ * Callback function for pmpro_dashboard_report_recent_orders meta box to show last 5 recent orders and a link to view all Orders.
276
+ */
277
+ function pmpro_dashboard_report_recent_orders_callback() {
278
+ global $wpdb;
279
+
280
+ $sqlQuery = "SELECT SQL_CALC_FOUND_ROWS id FROM $wpdb->pmpro_membership_orders ORDER BY id DESC, timestamp DESC LIMIT 5";
281
+
282
+ $order_ids = $wpdb->get_col( $sqlQuery );
283
+
284
+ $totalrows = $wpdb->get_var( 'SELECT FOUND_ROWS() as found_rows' );
285
+ ?>
286
+ <span id="pmpro_report_orders" class="pmpro_report-holder">
287
+ <table class="wp-list-table widefat fixed striped">
288
+ <thead>
289
+ <tr class="thead">
290
+ <th><?php _e( 'Code', 'paid-memberships-pro' ); ?></th>
291
+ <th><?php _e( 'User', 'paid-memberships-pro' ); ?></th>
292
+ <th><?php _e( 'Level', 'paid-memberships-pro' ); ?></th>
293
+ <th><?php _e( 'Total', 'paid-memberships-pro' ); ?></th>
294
+ <th><?php _e( 'Status', 'paid-memberships-pro' ); ?></th>
295
+ <th><?php _e( 'Date', 'paid-memberships-pro' ); ?></th>
296
+ </tr>
297
+ </thead>
298
+ <tbody id="orders" class="orders-list">
299
+ <?php
300
+ if ( empty( $order_ids ) ) { ?>
301
+ <tr>
302
+ <td colspan="8"><p><?php _e( 'No orders found.', 'paid-memberships-pro' ); ?></p></td>
303
+ </tr>
304
+ <?php } else {
305
+ foreach ( $order_ids as $order_id ) {
306
+ $order = new MemberOrder();
307
+ $order->nogateway = true;
308
+ $order->getMemberOrderByID( $order_id );
309
+ ?>
310
+ <tr>
311
+ <td>
312
+ <a href="admin.php?page=pmpro-orders&order=<?php echo $order->id; ?>"><?php echo $order->code; ?></a>
313
+ </td>
314
+ <td class="username column-username">
315
+ <?php $order->getUser(); ?>
316
+ <?php if ( ! empty( $order->user ) ) { ?>
317
+ <a href="user-edit.php?user_id=<?php echo $order->user->ID; ?>"><?php echo $order->user->user_login; ?></a>
318
+ <?php } elseif ( $order->user_id > 0 ) { ?>
319
+ [<?php _e( 'deleted', 'paid-memberships-pro' ); ?>]
320
+ <?php } else { ?>
321
+ [<?php _e( 'none', 'paid-memberships-pro' ); ?>]
322
+ <?php } ?>
323
+
324
+ <?php if ( ! empty( $order->billing->name ) ) { ?>
325
+ <br /><?php echo $order->billing->name; ?>
326
+ <?php } ?>
327
+ </td>
328
+ <td><?php echo $order->membership_id; ?></td>
329
+ <td><?php echo pmpro_formatPrice( $order->total ); ?></td>
330
+ <td>
331
+ <?php echo $order->gateway; ?>
332
+ <?php if ( $order->gateway_environment == 'test' ) {
333
+ echo '(test)';
334
+ } ?>
335
+ <?php if ( ! empty( $order->status ) ) {
336
+ echo '<br />(' . $order->status . ')';
337
+ } ?>
338
+ </td>
339
+ <td><?php echo date_i18n( get_option( 'date_format' ), $order->timestamp ); ?></td>
340
+ </tr>
341
+ <?php
342
+ }
343
+ }
344
+ ?>
345
+ </tbody>
346
+ </table>
347
+ </span>
348
+ <?php if ( ! empty( $order_ids ) ) { ?>
349
+ <p class="text-center"><a class="button button-primary" href="<?php echo admin_url( 'admin.php?page=pmpro-orders' ); ?>"><?php esc_attr_e( 'View All Orders ', 'paid-memberships-pro' ); ?></a></p>
350
+ <?php } ?>
351
+ <?php
352
+ }
353
+
354
+ /*
355
+ * Callback function for pmpro_dashboard_news_updates meta box to show RSS Feed from Paid Memberships Pro blog.
356
+ */
357
+ function pmpro_dashboard_news_updates_callback() {
358
+
359
+ // Get RSS Feed(s)
360
+ include_once( ABSPATH . WPINC . '/feed.php' );
361
+
362
+ // Get a SimplePie feed object from the specified feed source.
363
+ $rss = fetch_feed( 'https://www.paidmembershipspro.com/feed/' );
364
+
365
+ $maxitems = 0;
366
+
367
+ if ( ! is_wp_error( $rss ) ) : // Checks that the object is created correctly
368
+
369
+ // Figure out how many total items there are, but limit it to 5.
370
+ $maxitems = $rss->get_item_quantity( 5 );
371
+
372
+ // Build an array of all the items, starting with element 0 (first element).
373
+ $rss_items = $rss->get_items( 0, $maxitems );
374
+
375
+ endif;
376
+ ?>
377
+
378
+ <ul>
379
+ <?php if ( $maxitems == 0 ) : ?>
380
+ <li><?php _e( 'No news found.', 'paid-memberships-pro' ); ?></li>
381
+ <?php else : ?>
382
+ <?php // Loop through each feed item and display each item as a hyperlink. ?>
383
+ <?php foreach ( $rss_items as $item ) : ?>
384
+ <li>
385
+ <a href="<?php echo esc_url( $item->get_permalink() ); ?>"
386
+ title="<?php printf( __( 'Posted %s', 'paid-memberships-pro' ), $item->get_date( get_option( 'date_format' ) ) ); ?>">
387
+ <?php echo esc_html( $item->get_title() ); ?>
388
+ </a>
389
+ <?php echo esc_html( $item->get_date( get_option( 'date_format' ) ) ); ?>
390
+ </li>
391
+ <?php endforeach; ?>
392
+ <?php endif; ?>
393
+ </ul>
394
+ <p class="text-center"><a class="button button-primary" href="<?php echo esc_url( 'https://www.paidmembershipspro.com/blog/' ); ?>"><?php esc_attr_e( 'View More', 'paid-memberships-pro' ); ?></a></p>
395
+ <?php
396
+ }
397
+
398
+ /**
399
+ * Load the Paid Memberships Pro dashboard-area footer
400
+ */
401
+ require_once( dirname( __FILE__ ) . '/admin_footer.php' );
adminpages/discountcodes.php CHANGED
@@ -13,6 +13,9 @@
13
else
14
$edit = false;
15
16
if(isset($_REQUEST['delete']))
17
$delete = intval($_REQUEST['delete']);
18
else
@@ -21,7 +24,7 @@
21
if(isset($_REQUEST['saveid']))
22
$saveid = intval($_POST['saveid']);
23
else
24
- $saveid = false;
25
26
if(isset($_REQUEST['s']))
27
$s = sanitize_text_field($_REQUEST['s']);
@@ -51,14 +54,14 @@
51
52
$end = $pn * $limit;
53
$start = $end - $limit;
54
-
55
//check nonce for saving codes
56
if (!empty($_REQUEST['saveid']) && (empty($_REQUEST['pmpro_discountcodes_nonce']) || !check_admin_referer('save', 'pmpro_discountcodes_nonce'))) {
57
$pmpro_msgt = 'error';
58
$pmpro_msg = __("Are you sure you want to do that? Try again.", 'paid-memberships-pro' );
59
$saveid = false;
60
}
61
-
62
if($saveid)
63
{
64
//get vars
@@ -71,11 +74,11 @@
71
$expires_day = intval($_POST['expires_day']);
72
$expires_year = intval($_POST['expires_year']);
73
$uses = intval($_POST['uses']);
74
-
75
- //fix up dates
76
$starts = date_i18n("Y-m-d", strtotime($starts_month . "/" . $starts_day . "/" . $starts_year, current_time("timestamp")));
77
$expires = date_i18n("Y-m-d", strtotime($expires_month . "/" . $expires_day . "/" . $expires_year, current_time("timestamp")));
78
-
79
//insert/update/replace discount code
80
$wpdb->replace(
81
$wpdb->pmpro_discount_codes,
@@ -84,7 +87,7 @@
84
'code' => $code,
85
'starts' => $starts,
86
'expires' => $expires,
87
- 'uses' => $uses
88
),
89
array(
90
'%d',
@@ -94,7 +97,7 @@
94
'%d'
95
)
96
);
97
-
98
//check for errors and show appropriate message if inserted or updated
99
if(empty($wpdb->last_error)) {
100
if($saveid < 1) {
@@ -120,7 +123,7 @@
120
$pmpro_msg = __("Error updating discount code. That code may already be in use.", 'paid-memberships-pro' );
121
$pmpro_msgt = "error";
122
}
123
- }
124
125
//now add the membership level rows
126
if($saved && $edit > 0)
@@ -132,19 +135,19 @@
132
else
133
$levels_a = array();
134
$initial_payment_a = $_REQUEST['initial_payment'];
135
-
136
if(!empty($_REQUEST['recurring']))
137
- $recurring_a = $_REQUEST['recurring'];
138
$billing_amount_a = $_REQUEST['billing_amount'];
139
$cycle_number_a = $_REQUEST['cycle_number'];
140
$cycle_period_a = $_REQUEST['cycle_period'];
141
$billing_limit_a = $_REQUEST['billing_limit'];
142
-
143
if(!empty($_REQUEST['custom_trial']))
144
$custom_trial_a = $_REQUEST['custom_trial'];
145
$trial_amount_a = $_REQUEST['trial_amount'];
146
$trial_limit_a = $_REQUEST['trial_limit'];
147
-
148
if(!empty($_REQUEST['expiration']))
149
$expiration_a = $_REQUEST['expiration'];
150
$expiration_number_a = $_REQUEST['expiration_number'];
@@ -152,14 +155,14 @@
152
153
//clear the old rows
154
$wpdb->delete($wpdb->pmpro_discount_codes_levels, array('code_id' => $edit), array('%d'));
155
-
156
//add a row for each checked level
157
if(!empty($levels_a))
158
{
159
foreach($levels_a as $level_id)
160
{
161
$level_id = intval($level_id); //sanitized
162
-
163
//get the values ready
164
$n = array_search($level_id, $all_levels_a); //this is the key location of this level's values
165
$initial_payment = sanitize_text_field($initial_payment_a[$n]);
@@ -236,8 +239,10 @@
236
$expiration_period = 'Month';
237
}
238
239
-
240
-
241
//okay, do the insert
242
$wpdb->insert(
243
$wpdb->pmpro_discount_codes_levels,
@@ -268,7 +273,7 @@
268
'%s'
269
)
270
);
271
-
272
if(empty($wpdb->last_error))
273
{
274
//okay
@@ -286,13 +291,13 @@
286
if(!empty($level_errors))
287
{
288
$pmpro_msg = __("There were errors updating the level values: ", 'paid-memberships-pro' ) . implode(" ", $level_errors);
289
- $pmpro_msgt = "error";
290
}
291
else
292
{
293
do_action("pmpro_save_discount_code", $edit);
294
-
295
- //all good. set edit = false so we go back to the overview page
296
$edit = false;
297
}
298
}
@@ -304,7 +309,7 @@
304
$pmpro_msg = __("Are you sure you want to do that? Try again.", 'paid-memberships-pro' );
305
$delete = false;
306
}
307
-
308
//are we deleting?
309
if(!empty($delete))
310
{
@@ -322,7 +327,7 @@
322
{
323
//delete the code
324
$r2 = $wpdb->delete($wpdb->pmpro_discount_codes, array('id'=>$delete), array('%d'));
325
-
326
if($r2 !== false)
327
{
328
$pmpro_msg = sprintf(__("Code %s deleted successfully.", 'paid-memberships-pro' ), $code);
@@ -346,6 +351,14 @@
346
$pmpro_msgt = "error";
347
}
348
}
349
350
require_once(dirname(__FILE__) . "/admin_header.php");
351
?>
@@ -388,29 +401,36 @@
388
WHERE cl.code_id = %s",
389
$code->code
390
) );
391
- $temp_id = $code->id;
392
}
393
elseif(!empty($copy) && $copy > 0)
394
{
395
- $code = $wpdb->get_row( $wpdb->prepare("
396
- SELECT *, UNIX_TIMESTAMP(starts) as starts, UNIX_TIMESTAMP(expires) as expires
397
- FROM $wpdb->pmpro_discount_codes
398
- WHERE id = %d LIMIT 1",
399
- $copy ),
400
- OBJECT
401
- );
402
- $temp_id = $level->id;
403
- $level->id = NULL;
404
}
405
406
// didn't find a discount code, let's add a new one...
407
if(empty($code->id)) $edit = -1;
408
409
//defaults for new codes
410
- if($edit == -1)
411
{
412
$code = new stdClass();
413
$code->code = pmpro_getDiscountCode();
414
}
415
?>
416
<form action="" method="post">
@@ -448,8 +468,8 @@
448
if(!empty($code->expires))
449
$selected_expires_month = date_i18n("m", $code->expires);
450
else
451
- $selected_expires_month = date_i18n("m");
452
-
453
$current_year = date_i18n("Y");
454
if(!empty($code->starts))
455
$selected_starts_year = date_i18n("Y", $code->starts);
@@ -518,7 +538,7 @@
518
foreach($levels as $level)
519
{
520
//if this level is already managed for this discount code, use the code values
521
- if($edit > 0)
522
{
523
$code_level = $wpdb->get_row( $wpdb->prepare("
524
SELECT l.id, cl.*, l.name, l.description, l.allow_signups
@@ -526,7 +546,7 @@
526
LEFT JOIN $wpdb->pmpro_membership_levels l
527
ON cl.level_id = l.id
528
WHERE cl.code_id = %d AND cl.level_id = %d LIMIT 1",
529
- $edit,
530
$level->id )
531
);
532
if($code_level)
@@ -678,15 +698,12 @@
678
<a href="admin.php?page=pmpro-discountcodes&edit=-1" class="add-new-h2"><?php _e('Add New Discount Code', 'paid-memberships-pro' );?></a>
679
</h2>
680
681
- <?php if(!empty($pmpro_msg)) { ?>
682
- <div id="message" class="<?php if($pmpro_msgt == "success") echo "updated fade"; else echo "error"; ?>"><p><?php echo $pmpro_msg?></p></div>
683
- <?php } ?>
684
-
685
<?php
686
$sqlQuery = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(starts) as starts, UNIX_TIMESTAMP(expires) as expires FROM $wpdb->pmpro_discount_codes ";
687
- if(!empty($s))
688
$sqlQuery .= "WHERE code LIKE '%$s%' ";
689
-
690
$sqlQuery .= "ORDER BY id DESC ";
691
692
$sqlQuery .= "LIMIT $start, $limit ";
@@ -695,111 +712,112 @@
695
696
$totalrows = $wpdb->get_var( "SELECT FOUND_ROWS() as found_rows" );
697
698
- if ( !empty($codes) ) {
699
- ?>
700
- <p class="subsubsub"><?php printf( __( "%d discount codes found.", 'paid-memberships-pro' ), $totalrows ); ?></span></p>
701
- <?php
702
- }
703
- ?>
704
-
705
- <form id="posts-filter" method="get" action="">
706
- <p class="search-box">
707
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search Discount Codes', 'paid-memberships-pro' );?>:</label>
708
- <input type="hidden" name="page" value="pmpro-discountcodes" />
709
- <input id="post-search-input" type="text" value="<?php if(!empty($s)) echo $s;?>" name="s" size="30" />
710
- <input class="button" type="submit" value="<?php _e('Search', 'paid-memberships-pro' );?>" id="search-submit "/>
711
- </p>
712
- </form>
713
-
714
- <br class="clear" />
715
-
716
- <table class="widefat">
717
- <thead>
718
- <tr>
719
- <th><?php _e('ID', 'paid-memberships-pro' );?></th>
720
- <th><?php _e('Code', 'paid-memberships-pro' );?></th>
721
- <th><?php _e('Starts', 'paid-memberships-pro' );?></th>
722
- <th><?php _e('Expires', 'paid-memberships-pro' );?></th>
723
- <th><?php _e('Uses', 'paid-memberships-pro' );?></th>
724
- <th><?php _e('Levels', 'paid-memberships-pro' );?></th>
725
- <?php do_action("pmpro_discountcodes_extra_cols_header", $codes);?>
726
- <th></th>
727
- <th></th>
728
- </tr>
729
- </thead>
730
- <tbody>
731
- <?php
732
- if(!$codes)
733
- {
734
- ?>
735
- <tr><td colspan="7" class="pmpro_pad20">
736
- <p><?php _e('Discount codes allow you to offer your memberships at discounted prices to select customers.', 'paid-memberships-pro' );?> <a href="admin.php?page=pmpro-discountcodes&edit=-1"><?php _e('Create your first discount code now', 'paid-memberships-pro' );?></a>.</p>
737
- </td></tr>
738
- <?php
739
- }
740
- else
741
- {
742
- $count = 0;
743
- foreach($codes as $code)
744
- {
745
- ?>
746
- <tr<?php if($count++ % 2 == 1) { ?> class="alternate"<?php } ?>>
747
- <td><?php echo $code->id?></td>
748
- <td>
749
- <a href="?page=pmpro-discountcodes&edit=<?php echo $code->id?>"><?php echo $code->code?></a>
750
- </td>
751
- <td>
752
- <?php echo date_i18n(get_option('date_format'), $code->starts)?>
753
- </td>
754
- <td>
755
- <?php echo date_i18n(get_option('date_format'), $code->expires)?>
756
- </td>
757
- <td>
758
- <?php
759
- $uses = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->pmpro_discount_codes_uses WHERE code_id = %d", $code->id ) );
760
- if($code->uses > 0)
761
- echo "<strong>" . (int)$uses . "</strong>/" . $code->uses;
762
- else
763
- echo "<strong>" . (int)$uses . "</strong>/unlimited";
764
- ?>
765
- </td>
766
- <td>
767
- <?php
768
- $sqlQuery = $wpdb->prepare("
769
- SELECT l.id, l.name
770
- FROM $wpdb->pmpro_membership_levels l
771
- LEFT JOIN $wpdb->pmpro_discount_codes_levels cl
772
- ON l.id = cl.level_id
773
- WHERE cl.code_id = %d",
774
- $code->id
775
- );
776
- $levels = $wpdb->get_results($sqlQuery);
777
-
778
- $level_names = array();
779
- foreach($levels as $level)
780
- $level_names[] = "<a target=\"_blank\" href=\"" . pmpro_url("checkout", "?level=" . $level->id . "&discount_code=" . $code->code) . "\">" . $level->name . "</a>";
781
- if($level_names)
782
- echo implode(", ", $level_names);
783
- else
784
- echo "None";
785
- ?>
786
- </td>
787
- <?php do_action("pmpro_discountcodes_extra_cols_body", $code);?>
788
- <td>
789
- <a href="?page=pmpro-discountcodes&edit=<?php echo $code->id?>"><?php _e('edit', 'paid-memberships-pro' );?></a>
790
- </td>
791
- <td>
792
- <a href="javascript:askfirst('<?php echo str_replace("'", "\'", sprintf(__('Are you sure you want to delete the %s discount code? The subscriptions for existing users will not change, but new users will not be able to use this code anymore.', 'paid-memberships-pro' ), $code->code));?>', '<?php echo wp_nonce_url(admin_url('admin.php?page=pmpro-discountcodes&delete=' . $code->id), 'delete', 'pmpro_discountcodes_nonce');?>'); void(0);"><?php _e('delete', 'paid-memberships-pro' );?></a>
793
- </td>
794
</tr>
795
<?php
796
}
797
}
798
?>
799
</tbody>
800
</table>
801
-
802
- <?php
803
$pagination_url = get_admin_url( null, "/admin.php?page=pmpro-discountcodes&s=" . $s );
804
echo pmpro_getPaginationString( $pn, $totalrows, $limit, 1, $pagination_url, "&limit=$limit&pn=" );
805
?>
13
else
14
$edit = false;
15
16
+ if(isset($_REQUEST['copy']))
17
+ $copy = intval($_REQUEST['copy']);
18
+
19
if(isset($_REQUEST['delete']))
20
$delete = intval($_REQUEST['delete']);
21
else
24
if(isset($_REQUEST['saveid']))
25
$saveid = intval($_POST['saveid']);
26
else
27
+ $saveid = false;
28
29
if(isset($_REQUEST['s']))
30
$s = sanitize_text_field($_REQUEST['s']);
54
55
$end = $pn * $limit;
56
$start = $end - $limit;
57
+
58
//check nonce for saving codes
59
if (!empty($_REQUEST['saveid']) && (empty($_REQUEST['pmpro_discountcodes_nonce']) || !check_admin_referer('save', 'pmpro_discountcodes_nonce'))) {
60
$pmpro_msgt = 'error';
61
$pmpro_msg = __("Are you sure you want to do that? Try again.", 'paid-memberships-pro' );
62
$saveid = false;
63
}
64
+
65
if($saveid)
66
{
67
//get vars
74
$expires_day = intval($_POST['expires_day']);
75
$expires_year = intval($_POST['expires_year']);
76
$uses = intval($_POST['uses']);
77
+
78
+ //fix up dates
79
$starts = date_i18n("Y-m-d", strtotime($starts_month . "/" . $starts_day . "/" . $starts_year, current_time("timestamp")));
80
$expires = date_i18n("Y-m-d", strtotime($expires_month . "/" . $expires_day . "/" . $expires_year, current_time("timestamp")));
81
+
82
//insert/update/replace discount code
83
$wpdb->replace(
84
$wpdb->pmpro_discount_codes,
87
'code' => $code,
88
'starts' => $starts,
89
'expires' => $expires,
90
+ 'uses' => $uses
91
),
92
array(
93
'%d',
97
'%d'
98
)
99
);
100
+
101
//check for errors and show appropriate message if inserted or updated
102
if(empty($wpdb->last_error)) {
103
if($saveid < 1) {
123
$pmpro_msg = __("Error updating discount code. That code may already be in use.", 'paid-memberships-pro' );
124
$pmpro_msgt = "error";
125
}
126
+ }
127
128
//now add the membership level rows
129
if($saved && $edit > 0)
135
else
136
$levels_a = array();
137
$initial_payment_a = $_REQUEST['initial_payment'];
138
+
139
if(!empty($_REQUEST['recurring']))
140
+ $recurring_a = $_REQUEST['recurring'];
141
$billing_amount_a = $_REQUEST['billing_amount'];
142
$cycle_number_a = $_REQUEST['cycle_number'];
143
$cycle_period_a = $_REQUEST['cycle_period'];
144
$billing_limit_a = $_REQUEST['billing_limit'];
145
+
146
if(!empty($_REQUEST['custom_trial']))
147
$custom_trial_a = $_REQUEST['custom_trial'];
148
$trial_amount_a = $_REQUEST['trial_amount'];
149
$trial_limit_a = $_REQUEST['trial_limit'];
150
+
151
if(!empty($_REQUEST['expiration']))
152
$expiration_a = $_REQUEST['expiration'];
153
$expiration_number_a = $_REQUEST['expiration_number'];
155
156
//clear the old rows
157
$wpdb->delete($wpdb->pmpro_discount_codes_levels, array('code_id' => $edit), array('%d'));
158
+
159
//add a row for each checked level
160
if(!empty($levels_a))
161
{
162
foreach($levels_a as $level_id)
163
{
164
$level_id = intval($level_id); //sanitized
165
+
166
//get the values ready
167
$n = array_search($level_id, $all_levels_a); //this is the key location of this level's values
168
$initial_payment = sanitize_text_field($initial_payment_a[$n]);
239
$expiration_period = 'Month';
240
}
241
242
+ if ( ! empty( $expiration ) && ! empty( $recurring ) ) {
243
+ $expiration_warning_flag = true;
244
+ }
245
+
246
//okay, do the insert
247
$wpdb->insert(
248
$wpdb->pmpro_discount_codes_levels,
273
'%s'
274
)
275
);
276
+
277
if(empty($wpdb->last_error))
278
{
279
//okay
291
if(!empty($level_errors))
292
{
293
$pmpro_msg = __("There were errors updating the level values: ", 'paid-memberships-pro' ) . implode(" ", $level_errors);
294
+ $pmpro_msgt = "error";
295
}
296
else
297
{
298
do_action("pmpro_save_discount_code", $edit);
299
+
300
+ //all good. set edit = false so we go back to the overview page
301
$edit = false;
302
}
303
}
309
$pmpro_msg = __("Are you sure you want to do that? Try again.", 'paid-memberships-pro' );
310
$delete = false;
311
}
312
+
313
//are we deleting?
314
if(!empty($delete))
315
{
327
{
328
//delete the code
329
$r2 = $wpdb->delete($wpdb->pmpro_discount_codes, array('id'=>$delete), array('%d'));
330
+
331
if($r2 !== false)
332
{
333
$pmpro_msg = sprintf(__("Code %s deleted successfully.", 'paid-memberships-pro' ), $code);
351
$pmpro_msgt = "error";
352
}
353
}
354
+
355
+ if( ! empty( $pmpro_msg ) && ! empty( $expiration_warning_flag ) ) {
356
+ $pmpro_msg .= ' <strong>' . sprintf( __( 'WARNING: A level was set with both a recurring billing amount and an expiration date. You only need to set one of these unless you really want this membership to expire after a specific time period. For more information, <a target="_blank" href="%s">see our post here</a>.', 'paid-memberships-pro' ), 'https://www.paidmembershipspro.com/important-notes-on-recurring-billing-and-expiration-dates-for-membership-levels/' ) . '</strong>';
357
+
358
+ if( $pmpro_msgt == 'success' ) {
359
+ $pmpro_msgt = 'warning';
360
+ }
361
+ }
362
363
require_once(dirname(__FILE__) . "/admin_header.php");
364
?>
401
WHERE cl.code_id = %s",
402
$code->code
403
) );
404
+ $temp_code = $code;
405
}
406
elseif(!empty($copy) && $copy > 0)
407
{
408
+ $code = $wpdb->get_row(
409
+ $wpdb->prepare("
410
+ SELECT *, UNIX_TIMESTAMP(starts) as starts, UNIX_TIMESTAMP(expires) as expires
411
+ FROM $wpdb->pmpro_discount_codes
412
+ WHERE id = %d LIMIT 1",
413
+ $copy ),
414
+ OBJECT
415
+ );
416
+
417
+ $temp_code = $code;
418
}
419
420
// didn't find a discount code, let's add a new one...
421
if(empty($code->id)) $edit = -1;
422
423
//defaults for new codes
424
+ if ( $edit == -1 )
425
{
426
$code = new stdClass();
427
$code->code = pmpro_getDiscountCode();
428
+
429
+ if( ! empty( $copy ) && $copy > 0 ) {
430
+ $code->starts = $temp_code->starts;
431
+ $code->expires = $temp_code->expires;
432
+ $code->uses = $temp_code->uses;
433
+ }
434
}
435
?>
436
<form action="" method="post">
468
if(!empty($code->expires))
469
$selected_expires_month = date_i18n("m", $code->expires);
470
else
471
+ $selected_expires_month = date_i18n("m");
472
+
473
$current_year = date_i18n("Y");
474
if(!empty($code->starts))
475
$selected_starts_year = date_i18n("Y", $code->starts);
538
foreach($levels as $level)
539
{
540
//if this level is already managed for this discount code, use the code values
541
+ if($edit > 0 || ! empty( $copy ) )
542
{
543
$code_level = $wpdb->get_row( $wpdb->prepare("
544
SELECT l.id, cl.*, l.name, l.description, l.allow_signups
546
LEFT JOIN $wpdb->pmpro_membership_levels l
547
ON cl.level_id = l.id
548
WHERE cl.code_id = %d AND cl.level_id = %d LIMIT 1",
549
+ $temp_code->id,
550
$level->id )
551
);
552
if($code_level)
698
<a href="admin.php?page=pmpro-discountcodes&edit=-1" class="add-new-h2"><?php _e('Add New Discount Code', 'paid-memberships-pro' );?></a>
699
</h2>
700
701
<?php
702
$sqlQuery = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(starts) as starts, UNIX_TIMESTAMP(expires) as expires FROM $wpdb->pmpro_discount_codes ";
703
+ if( ! empty( $s ) ) {
704
$sqlQuery .= "WHERE code LIKE '%$s%' ";
705
+ }
706
+
707
$sqlQuery .= "ORDER BY id DESC ";
708
709
$sqlQuery .= "LIMIT $start, $limit ";
712
713
$totalrows = $wpdb->get_var( "SELECT FOUND_ROWS() as found_rows" );
714
715
+ if( empty( $codes ) ) { ?>
716
+ <div class="pmpro-new-install">
717
+ <h2><?php echo esc_attr_e( 'No Discount Codes Found', 'paid-memberships-pro' ); ?></h2>
718
+ <h4><?php _e( 'Discount codes allow you to override your membership level\'s default pricing.', 'paid-memberships-pro' ); ?></h4>
719
+ <a href="<?php echo esc_url( admin_url( 'admin.php?page=pmpro-discountcodes&edit=-1' ) ) ; ?>" class="button-primary"><?php esc_attr_e( 'Create a Discount Code', 'paid-memberships-pro' );?></a>
720
+ <a href="<?php echo esc_url( 'https://www.paidmembershipspro.com/documentation/discount-codes/' ); ?>" target="_blank" class="button"><?php echo esc_attr_e( 'Documentation: Discount Codes', 'paid-memberships-pro' ); ?></a>
721
+ </div> <!-- end pmpro-new-install -->
722
+ <?php } else { ?>
723
+
724
+ <?php if(!empty($pmpro_msg)) { ?>
725
+ <div id="message" class="<?php if($pmpro_msgt == "success") echo "updated fade"; else echo "error"; ?>"><p><?php echo $pmpro_msg?></p></div>
726
+ <?php } ?>
727
+
728
+ <?php if ( ! empty( $codes ) ) { ?>
729
+ <p class="subsubsub"><?php printf( __( "%d discount codes found.", 'paid-memberships-pro' ), $totalrows ); ?></span></p>
730
+ <?php } ?>
731
+
732
+ <form id="posts-filter" method="get" action="">
733
+ <p class="search-box">
734
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search Discount Codes', 'paid-memberships-pro' );?>:</label>
735
+ <input type="hidden" name="page" value="pmpro-discountcodes" />
736
+ <input id="post-search-input" type="text" value="<?php if(!empty($s)) echo $s;?>" name="s" size="30" />
737
+ <input class="button" type="submit" value="<?php _e('Search', 'paid-memberships-pro' );?>" id="search-submit "/>
738
+ </p>
739
+ </form>
740
+
741
+ <br class="clear" />
742
+
743
+ <table class="widefat">
744
+ <thead>
745
+ <tr>
746
+ <th><?php _e('ID', 'paid-memberships-pro' );?></th>
747
+ <th><?php _e('Code', 'paid-memberships-pro' );?></th>
748
+ <th><?php _e('Starts', 'paid-memberships-pro' );?></th>
749
+ <th><?php _e('Expires', 'paid-memberships-pro' );?></th>
750
+ <th><?php _e('Uses', 'paid-memberships-pro' );?></th>
751
+ <th><?php _e('Levels', 'paid-memberships-pro' );?></th>
752
+ <?php do_action("pmpro_discountcodes_extra_cols_header", $codes);?>
753
+ <th></th>
754
</tr>
755
+ </thead>
756
+ <tbody>
757
+ <?php
758
+ $count = 0;
759
+ foreach($codes as $code) { ?>
760
+ <tr<?php if($count++ % 2 == 1) { ?> class="alternate"<?php } ?>>
761
+ <td><?php echo $code->id?></td>
762
+ <td>
763
+ <a href="?page=pmpro-discountcodes&edit=<?php echo $code->id?>"><?php echo $code->code?></a>
764
+ </td>
765
+ <td>
766
+ <?php echo date_i18n(get_option('date_format'), $code->starts)?>
767
+ </td>
768
+ <td>
769
+ <?php echo date_i18n(get_option('date_format'), $code->expires)?>
770
+ </td>
771
+ <td>
772
+ <?php
773
+ $uses = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->pmpro_discount_codes_uses WHERE code_id = %d", $code->id ) );
774
+ if($code->uses > 0)
775
+ echo "<strong>" . (int)$uses . "</strong>/" . $code->uses;
776
+ else
777
+ echo "<strong>" . (int)$uses . "</strong>/unlimited";
778
+ ?>
779
+ </td>
780
+ <td>
781
+ <?php
782
+ $sqlQuery = $wpdb->prepare("
783
+ SELECT l.id, l.name
784
+ FROM $wpdb->pmpro_membership_levels l
785
+ LEFT JOIN $wpdb->pmpro_discount_codes_levels cl
786
+ ON l.id = cl.level_id
787
+ WHERE cl.code_id = %d",
788
+ $code->id
789
+ );
790
+ $levels = $wpdb->get_results($sqlQuery);
791
+
792
+ $level_names = array();
793
+ foreach($levels as $level)
794
+ $level_names[] = "<a target=\"_blank\" href=\"" . pmpro_url("checkout", "?level=" . $level->id . "&discount_code=" . $code->code) . "\">" . $level->name . "</a>";
795
+ if($level_names)
796
+ echo implode(", ", $level_names);
797
+ else
798
+ echo "None";
799
+ ?>
800
+ </td>
801
+ <?php do_action("pmpro_discountcodes_extra_cols_body", $code);?>
802
+ <td>
803
+ <a title="<?php _e('edit', 'paid-memberships-pro' ); ?>" href="<?php echo add_query_arg( array( 'page' => 'pmpro-discountcodes', 'edit' => $code->id ), admin_url('admin.php' ) ); ?>" class="button-primary"><?php _e( 'edit', 'paid-memberships-pro' ); ?></a>
804
+ <a title="<?php _e('copy', 'paid-memberships-pro' ); ?>" href="<?php echo add_query_arg( array( 'page' => 'pmpro-discountcodes', 'edit' => -1, 'copy' => $code->id ), admin_url('admin.php' ) ); ?>" class="button-secondary"><?php _e( 'copy', 'paid-memberships-pro' ); ?></a>
805
+ <a title="<?php _e('delete', 'paid-memberships-pro' ); ?>" href="javascript:askfirst('<?php echo str_replace("'", "\'", sprintf(__('Are you sure you want to delete the %s discount code? The subscriptions for existing users will not change, but new users will not be able to use this code anymore.', 'paid-memberships-pro' ), $code->code));?>', '<?php echo wp_nonce_url(add_query_arg( array( 'page' => 'pmpro-discountcodes', 'delete' => $code->id), admin_url( 'admin.php' ) ), 'delete', 'pmpro_discountcodes_nonce'); ?>'); void(0);" class="button-secondary"><?php _e('delete', 'paid-memberships-pro' ); ?></a>
806
+ <?php if ( (int)$uses > 0 ) { ?>
807
+ <a title="<?php _e('view orders', 'paid-memberships-pro' ); ?>" href="<?php echo add_query_arg( array( 'page' => 'pmpro-orders', 'discount_code' => $code->id, 'filter' => 'with-discount-code' ), admin_url('admin.php' ) ); ?>" class="button-secondary"><?php _e( 'orders', 'paid-memberships-pro' ); ?></a>
808
+ <?php } else { ?>
809
+ <a title="<?php _e('no orders', 'paid-memberships-pro' ); ?>" href="#" class="button-secondary button-disabled"><?php _e( 'orders', 'paid-memberships-pro' ); ?></a>
810
+ <?php } ?>
811
+ </td>
812
+ </tr>
813
<?php
814
}
815
}
816
?>
817
</tbody>
818
</table>
819
+
820
+ <?php
821
$pagination_url = get_admin_url( null, "/admin.php?page=pmpro-discountcodes&s=" . $s );
822
echo pmpro_getPaginationString( $pn, $totalrows, $limit, 1, $pagination_url, "&limit=$limit&pn=" );
823
?>
adminpages/functions.php CHANGED
@@ -22,10 +22,43 @@
22
Checks if PMPro settings are complete or if there are any errors.
23
24
Stripe currently does not support:
25
- [No current incompatibilities]
26
*/
27
function pmpro_checkLevelForStripeCompatibility($level = NULL)
28
{
29
return true;
30
}
31
22
Checks if PMPro settings are complete or if there are any errors.
23
24
Stripe currently does not support:
25
+ * Billing Limits.
26
*/
27
function pmpro_checkLevelForStripeCompatibility($level = NULL)
28
{
29
+ $gateway = pmpro_getOption("gateway");
30
+ if($gateway == "stripe")
31
+ {
32
+ global $wpdb;
33
+
34
+ //check ALL the levels
35
+ if(empty($level))
36
+ {
37
+ $sqlQuery = "SELECT * FROM $wpdb->pmpro_membership_levels ORDER BY id ASC";
38
+ $levels = $wpdb->get_results($sqlQuery, OBJECT);
39
+ if(!empty($levels))
40
+ {
41
+ foreach($levels as $level)
42
+ {
43
+ if(!pmpro_checkLevelForStripeCompatibility($level))
44
+ return false;
45
+ }
46
+ }
47
+ }
48
+ else
49
+ {
50
+ //need to look it up?
51
+ if(is_numeric($level))
52
+ $level = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->pmpro_membership_levels WHERE id = %d LIMIT 1" , $level ) );
53
+
54
+ //check this level
55
+ if($level->billing_limit > 0)
56
+ {
57
+ return false;
58
+ }
59
+ }
60
+ }
61
+
62
return true;
63
}
64
adminpages/membershiplevels.php CHANGED
@@ -49,6 +49,10 @@
49
$ml_name = wp_kses(wp_unslash($_REQUEST['name']), $allowedposttags);
50
$ml_description = wp_kses(wp_unslash($_REQUEST['description']), $allowedposttags);
51
$ml_confirmation = wp_kses(wp_unslash($_REQUEST['confirmation']), $allowedposttags);
52
53
$ml_initial_payment = sanitize_text_field($_REQUEST['initial_payment']);
54
if(!empty($_REQUEST['recurring']))
@@ -130,7 +134,7 @@
130
'%d', //allow_signups
131
)
132
);
133
-
134
if($saveid < 1) {
135
//added a level
136
$saveid = $wpdb->insert_id;
@@ -157,11 +161,24 @@
157
$msgt = __("Membership level updated successfully.", 'paid-memberships-pro' );
158
} else {
159
$msg = -2;
160
- $msg = true;
161
$msgt = __("Error updating membership level.", 'paid-memberships-pro' );
162
}
163
}
164
165
do_action("pmpro_save_membership_level", $saveid);
166
}
167
elseif($action == "delete_membership_level")
@@ -310,6 +327,11 @@
310
) );
311
if(empty($level->categories))
312
$level->categories = array();
313
314
?>
315
<form action="" method="post" enctype="multipart/form-data">
@@ -363,6 +385,7 @@
363
}
364
?>
365
</div>
366
</td>
367
</tr>
368
</tbody>
@@ -417,9 +440,7 @@
417
</select>
418
<br /><small>
419
<?php _e('The amount to be billed one cycle after the initial payment.', 'paid-memberships-pro' );?>
420
- <?php if($gateway == "stripe") { ?>
421
- <br /><strong <?php if(!empty($pmpro_stripe_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Stripe integration currently only supports billing periods of "Week", "Month" or "Year".', 'paid-memberships-pro' );?>
422
- <?php } elseif($gateway == "braintree") { ?>
423
<br /><strong <?php if(!empty($pmpro_braintree_error)) { ?>class="pmpro_red"<?php } ?>><?php _e('Braintree integration currently only supports billing periods of "Month" or "Year".', 'paid-memberships-pro' );?>
424
<?php } ?>
425
</small>
@@ -429,7 +450,7 @@
429
$has_bt_plan = PMProGateway_braintree::checkLevelForPlan( $level->id );
430
?>
431
<p class="pmpro_message <?php if ( ! $has_bt_plan ) {?>pmpro_error<?php } ?>">
432
- <strong><?php _e('Note', 'paid-memberships-pro' );?>:</strong> <?php printf( __('You will need to create a "Plan" in your Braintree dashboard with the same settings and the "Plan ID" set to %s.', 'paid-memberships-pro' ), $level->id ); ?></p>
433
<?php } ?>
434
</td>
435
</tr>
@@ -440,6 +461,9 @@
440
<input name="billing_limit" type="text" size="20" value="<?php echo $level->billing_limit?>" />
441
<br /><small>
442
<?php _e('The <strong>total</strong> number of recurring billing cycles for this level, including the trial period (if applicable) but not including the initial payment. Set to zero if membership is indefinite.', 'paid-memberships-pro' );?>
443
</small>
444
</td>
445
</tr>
@@ -502,7 +526,7 @@
502
<td><input id="expiration" name="expiration" type="checkbox" value="yes" <?php if(pmpro_isLevelExpiring($level)) { echo "checked='checked'"; } ?> onclick="if(jQuery('#expiration').is(':checked')) { jQuery('.expiration_info').show(); } else { jQuery('.expiration_info').hide();}" /> <label for="expiration"><?php _e('Check this to set when membership access expires.', 'paid-memberships-pro' );?></label></a></td>
503
</tr>
504
505
- <tr class="expiration_info" <?php if(!pmpro_isLevelExpiring($level)) {?>style="display: none;"<?php } ?>>
506
<th scope="row" valign="top"><label for="billing_amount"><?php _e('Expires In', 'paid-memberships-pro' );?>:</label></th>
507
<td>
508
<input id="expiration_number" name="expiration_number" type="text" size="10" value="<?php echo esc_attr($level->expiration_number);?>" />
@@ -517,6 +541,25 @@
517
?>
518
</select>
519
<br /><small><?php _e('Set the duration of membership access. Note that the any future payments (recurring subscription, if any) will be cancelled when the membership expires.', 'paid-memberships-pro' );?></small>
520
</td>
521
</tr>
522
</tbody>
@@ -638,7 +681,14 @@
638
}
639
?>
640
641
- <h2 class="alignleft"><?php _e('Membership Levels', 'paid-memberships-pro' );?> <a href="<?php echo add_query_arg( array( 'page' => 'pmpro-membershiplevels', 'edit' => -1 ), get_admin_url(null, 'admin.php' ) ); ?>" class="add-new-h2"><?php _e('Add New Level', 'paid-memberships-pro' );?></a></h2>
642
<form id="posts-filter" method="get" action="">
643
<p class="search-box">
644
<label class="screen-reader-text" for="post-search-input"><?php _e('Search Levels', 'paid-memberships-pro' );?>:</label>
@@ -647,9 +697,9 @@
647
<input class="button" type="submit" value="<?php _e('Search Levels', 'paid-memberships-pro' );?>" id="search-submit" />
648
</p>
649
</form>
650
651
<?php if(empty($_REQUEST['s']) && count($reordered_levels) > 1) { ?>
652
-