{"id":1062,"date":"2021-05-20T09:30:26","date_gmt":"2021-05-20T14:30:26","guid":{"rendered":"https:\/\/easydigitaldownloads.com\/development\/?p=1062"},"modified":"2021-05-20T09:30:27","modified_gmt":"2021-05-20T14:30:27","slug":"edd-3-0-beta2","status":"publish","type":"post","link":"https:\/\/easydigitaldownloads.com\/development\/2021\/05\/20\/edd-3-0-beta2\/","title":{"rendered":"Easy Digital Downloads 3.0-beta2 now available"},"content":{"rendered":"\n<p>Since <a href=\"https:\/\/easydigitaldownloads.com\/development\/2021\/02\/16\/edd-3-0-beta1\/\">releasing 3.0-beta1 back in February<\/a>, we&#8217;ve been hard at work updating our extensions for 3.0 compatibility and fixing any issues that popped up in core. We have since closed over 100 issues!<\/p>\n\n\n\n<p>The beta2 release is now available for testing, and in this blog post we&#8217;ll go over three of the major changes.<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><a href=\"#refunds-api\">The new refunds API has been finalized<\/a><\/li><li><a href=\"#templates-reworked\">Templates have been reworked<\/a><\/li><li><a href=\"#migration-steps\">The migration now has step recovery<\/a><\/li><\/ol>\n\n\n\n<p><strong>Important Note:<\/strong>&nbsp;This beta release is NOT production ready. It should only be tested on development sites. Do not install it on your live site.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"refunds-api\">The new refunds API has been finalized<\/h2>\n\n\n\n<p>When we released 3.0-beta1, we made it clear that refunds were still a work in progress, but they have now been completed!<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><a href=\"https:\/\/easydigitaldownloads.com\/development\/files\/2021\/05\/edd3-refunds.png\"><img loading=\"lazy\" decoding=\"async\" width=\"914\" height=\"397\" src=\"https:\/\/easydigitaldownloads.com\/development\/files\/2021\/05\/edd3-refunds.png\" alt=\"Modal for submitting a refund, with a checkbox to &quot;Refund transaction in PayPal&quot;.\" class=\"wp-image-1066\" srcset=\"https:\/\/easydigitaldownloads.com\/development\/files\/2021\/05\/edd3-refunds.png 914w, https:\/\/easydigitaldownloads.com\/development\/files\/2021\/05\/edd3-refunds-300x130.png 300w, https:\/\/easydigitaldownloads.com\/development\/files\/2021\/05\/edd3-refunds-768x334.png 768w\" sizes=\"auto, (max-width: 914px) 100vw, 914px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>Here are a few notable changes:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Each order item and fee will have a listing in the modal, and you can select which items to refund. It&#8217;s possible to refund a fee without refunding the order items, and vice versa.<\/li><li>For each item, you can also specify a quantity (if applicable), and how much of that item you want to refund. As an example, for that $10 item I could choose to refund only $5 of it.<\/li><li>We have added a hook to the modal, which you can use to output custom fields below the table. You can see how we&#8217;ve added a checkbox that gives you the option to <em>&#8220;Refund transaction in PayPal.&#8221;<\/em><\/li><\/ul>\n\n\n\n<p>Let&#8217;s talk about that last item for a moment. If you&#8217;ve built a custom gateway, you probably want to know how to add your own checkbox and execute custom code when the refund runs. Here&#8217;s our implementation for PayPal:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Adding the checkbox to the UI<\/h3>\n\n\n\n<p>Here&#8217;s what the code looks like to add a checkbox to the UI:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * Shows a checkbox to automatically refund payments in PayPal.\n *\n * @param \\EDD\\Orders\\Order $order\n *\n * @since 3.0\n * @return void\n *\/\nfunction edd_paypal_refund_checkbox( \\EDD\\Orders\\Order $order ) {\n\tif ( 'paypal' !== $order-&gt;gateway ) {\n\t\treturn;\n\t}\n\n\t\/\/ If our credentials are not set, return early.\n\t$key       = $order-&gt;mode;\n\t$username  = edd_get_option( 'paypal_' . $key . '_api_username' );\n\t$password  = edd_get_option( 'paypal_' . $key . '_api_password' );\n\t$signature = edd_get_option( 'paypal_' . $key . '_api_signature' );\n\n\tif ( empty( $username ) || empty( $password ) || empty( $signature ) ) {\n\t\treturn;\n\t}\n\t?&gt;\n\t&lt;div class=\"edd-form-group edd-paypal-refund-transaction\"&gt;\n\t\t&lt;div class=\"edd-form-group__control\"&gt;\n\t\t\t&lt;input type=\"checkbox\" id=\"edd-paypal-refund\" name=\"edd-paypal-refund\" class=\"edd-form-group__input\" value=\"1\"&gt;\n\t\t\t&lt;label for=\"edd-paypal-refund\" class=\"edd-form-group__label\"&gt;\n\t\t\t\t&lt;?php esc_html_e( 'Refund transaction in PayPal', 'easy-digital-downloads' ); ?&gt;\n\t\t\t&lt;\/label&gt;\n\t\t&lt;\/div&gt;\n\t&lt;\/div&gt;\n\t&lt;?php\n}\nadd_action( 'edd_after_submit_refund_table', 'edd_paypal_refund_checkbox' );<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>Hook into <code>edd_after_submit_refund_table<\/code>. This hook provides one parameter: the <code>\\EDD\\Orders\\Order<\/code> object.<\/li><li>Be sure to check that the order is using your gateway.<\/li><li>We only show the option if the API keys have been configured.<\/li><li>Then output markup to show the custom field.<\/li><\/ul>\n\n\n\n<p>The next step is to actually process the refund. Here&#8217;s the code to make that happen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n * If selected, refunds a transaction in PayPal when creating a new refund record.\n *\n * @param int $order_id ID of the order we're processing a refund for.\n * @param int $refund_id ID of the newly created refund record.\n * @param bool $all_refunded Whether or not this was a full refund.\n *\n * @since 3.0\n *\/\nfunction edd_paypal_maybe_refund_transaction( $order_id, $refund_id, $all_refunded ) {\n\tif ( ! current_user_can( 'edit_shop_payments', $order_id ) ) {\n\t\treturn;\n\t}\n\n\tif ( empty( $_POST&#91;'data'] ) ) {\n\t\treturn;\n\t}\n\n\t$order = edd_get_order( $order_id );\n\tif ( empty( $order-&gt;gateway ) || 'paypal' !== $order-&gt;gateway ) {\n\t\treturn;\n\t}\n\n\t\/\/ Get our data out of the serialized string.\n\tparse_str( $_POST&#91;'data'], $form_data );\n\n\tif ( empty( $form_data&#91;'edd-paypal-refund'] ) ) {\n\t\t\/\/ Checkbox was not checked.\n\t\treturn;\n\t}\n\n\t$refund = edd_get_order( $refund_id );\n\tif ( empty( $refund-&gt;total ) ) {\n\t\treturn;\n\t}\n\n\tedd_refund_paypal_purchase( $order, $refund );\n}\nadd_action( 'edd_refund_order', 'edd_paypal_maybe_refund_transaction', 10, 3 );<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>Hook into <code>edd_refund_order<\/code>. This hook supplies three parameters: the ID of the order being refunded, the ID of the newly created refund object, and a boolean indicating if the entire order was refunded or not.<\/li><li>Be sure to include a permission check.<\/li><li>Be sure to check the relevant gateway.<\/li><li>To get the data from the form you&#8217;ll want to run: <code>parse_str( $_POST['data'], $form_data );<\/code> Then the posted data will be available in <code>$form_data<\/code>.<\/li><li>As a sanity check, we make sure the newly created refund total isn&#8217;t empty (<code>0.00<\/code>).<\/li><li>Then, finally, you can execute your code to actually process the refund at the gateway. (We call <code>edd_refund_paypal_purchase()<\/code>).<\/li><\/ul>\n\n\n\n<p>You can see all our code for this in context in <a href=\"https:\/\/github.com\/easydigitaldownloads\/easy-digital-downloads\/blob\/release\/3.0\/includes\/gateways\/paypal-standard.php#L1126-L1369\" data-type=\"URL\" data-id=\"https:\/\/github.com\/easydigitaldownloads\/easy-digital-downloads\/blob\/release\/3.0\/includes\/gateways\/paypal-standard.php#L1126-L1369\" target=\"_blank\" rel=\"noreferrer noopener\">the PayPal Standard gateway file<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"templates-reworked\">Templates have been reworked (but are still backwards compatible!)<\/h2>\n\n\n\n<p>We&#8217;ve updated the <code>history-downloads.php<\/code> and <code>history-purchases.php<\/code> templates to use all new 3.0 functions.<\/p>\n\n\n\n<p>The main motivation behind this change was speed. Working with the legacy <code>EDD_Payment<\/code> object (and associated <code>edd_get_payment()<\/code> and <code>edd_get_users_purchases()<\/code> functions) is a performance hit. We have to navigate through multiple backwards compatibility layers to build up that object.<\/p>\n\n\n\n<p>Prior to making the changes, the purchase history template was running approximately 300-400 queries &#8212; sometimes more. That definitely slowed the page down and resulted in a pretty negative experience. After reworking it, we&#8217;ve gotten it down to approximately 35 queries. That&#8217;s quite an improvement!<\/p>\n\n\n\n<p>So what do these changes actually mean for you?<\/p>\n\n\n\n<p>Every hook executed within those templates that passed through an <code>EDD_Payment<\/code> object (or array of objects) has been deprecated, and new replacements have been created. For example:<\/p>\n\n\n\n<p>Here&#8217;s an example hook in the previous template version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>do_action( 'edd_before_purchase_history', $payments );<\/code><\/pre>\n\n\n\n<p>This hook has been deprecated because it was built to receive an array of <code>EDD_Payment<\/code> objects. It has been replaced with this new hook, which instead takes an array of <code>\\EDD\\Orders\\Order<\/code> objects:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>do_action( 'edd_before_order_history', $orders );<\/code><\/pre>\n\n\n\n<p>That being said, <strong>the old hook will still work<\/strong>. We hook into the new action to trigger the old:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_action( 'edd_before_order_history', function( $orders ) {\n\tif ( ! has_action( 'edd_before_purchase_history' ) ) {\n\t\treturn;\n\t}\n\n\t$payments = array();\n\n\tif ( ! empty( $orders ) ) {\n\t\t$order_ids = wp_list_pluck( $orders, 'id' );\n\t\t$payments  = edd_get_payments(\n\t\t\tarray(\n\t\t\t\t'id__in'  =&gt; $order_ids,\n\t\t\t\t'orderby' =&gt; 'date',\n\t\t\t)\n\t\t);\n\t}\n\n\tdo_action( 'edd_before_purchase_history', $payments );\n} );<\/code><\/pre>\n\n\n\n<p>The only thing this means for you is that if you&#8217;re hooking into the old action you will see a performance hit, because we will need to load in the <code>EDD_Payment<\/code> objects for your hook.<\/p>\n\n\n\n<p>Right now the old hooks will not trigger any deprecation notices, as it is still easiest to use them if you need to support both EDD 2.x and 3.0 at the same time. We are planning to add deprecation notices in EDD 3.1. We have no plans to stop the hooks from working entirely.<\/p>\n\n\n\n<p>For a full list of all deprecated hooks, <a href=\"https:\/\/github.com\/easydigitaldownloads\/easy-digital-downloads\/blob\/release\/3.0\/includes\/deprecated-hooks.php\" target=\"_blank\" rel=\"noreferrer noopener\">check out our new deprecated-hooks.php file<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"migration-steps\">The migration now has step recovery<\/h2>\n\n\n\n<p>The 3.0 migration has 8 different steps &#8212; or 9 if you include the removal of legacy data. In beta1, if the migration process was interrupted 50% through step 4 and you reloaded the page to start again, you would start over at 0% of step 4. So although your progress through the 8 (or 9) main steps could be recovered, the steps <em>within<\/em> each step could not. This has changed with beta2.<\/p>\n\n\n\n<p>Now, if the migration is interrupted 50% through step 4 and you reload the page to initiate it again, you will resume at 50% through step 4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing and testing 3.0-beta2<\/h2>\n\n\n\n<p>The 3.0-beta2 release can be\u00a0<a href=\"https:\/\/github.com\/easydigitaldownloads\/easy-digital-downloads\/releases\/download\/3.0-beta2\/easy-digital-downloads.zip\" target=\"_blank\" rel=\"noreferrer noopener\">downloaded from GitHub<\/a>\u00a0and installed as normal. If you encounter any bugs, please\u00a0<a href=\"https:\/\/github.com\/easydigitaldownloads\/easy-digital-downloads\/issues\">search through our existing issues<\/a>. If there\u2019s not already an open issue, you may create a new one (after reading our\u00a0<a href=\"https:\/\/github.com\/easydigitaldownloads\/easy-digital-downloads\/blob\/master\/CONTRIBUTING.md\">Contributor Guidelines<\/a>).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s next for 3.0?<\/h2>\n\n\n\n<p>Our next major goal is to upgrade to 3.0 on one of our own Sandhills product sites. We&#8217;ve been hard at work updating extensions &#8212; first prioritizing the ones we use internally &#8212; so we can upgrade to 3.0. We will be doing this prior to the official 3.0 release.<\/p>\n\n\n\n<p>We don&#8217;t have an exact date for this yet, and there are still a few extensions we need to update first, but I suspect you&#8217;ll see us with another blog post when it happens so we can tell you all about how it went!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Since releasing 3.0-beta1 back in February, we&#8217;ve been hard at work updating our extensions for 3.0 compatibility and fixing any issues that popped up in core. We have since closed over 100 issues! The beta2&#8230;<\/p>\n<p class=\"continue-reading\"><a class=\"more-link\" href=\"https:\/\/easydigitaldownloads.com\/development\/2021\/05\/20\/edd-3-0-beta2\/\">Continue reading &rarr;<\/a><\/p>\n","protected":false},"author":2782,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[4],"tags":[17],"class_list":["post-1062","post","type-post","status-publish","format-standard","hentry","category-core","tag-3dd"],"_links":{"self":[{"href":"https:\/\/easydigitaldownloads.com\/development\/wp-json\/wp\/v2\/posts\/1062","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/easydigitaldownloads.com\/development\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/easydigitaldownloads.com\/development\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/easydigitaldownloads.com\/development\/wp-json\/wp\/v2\/users\/2782"}],"replies":[{"embeddable":true,"href":"https:\/\/easydigitaldownloads.com\/development\/wp-json\/wp\/v2\/comments?post=1062"}],"version-history":[{"count":10,"href":"https:\/\/easydigitaldownloads.com\/development\/wp-json\/wp\/v2\/posts\/1062\/revisions"}],"predecessor-version":[{"id":1081,"href":"https:\/\/easydigitaldownloads.com\/development\/wp-json\/wp\/v2\/posts\/1062\/revisions\/1081"}],"wp:attachment":[{"href":"https:\/\/easydigitaldownloads.com\/development\/wp-json\/wp\/v2\/media?parent=1062"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/easydigitaldownloads.com\/development\/wp-json\/wp\/v2\/categories?post=1062"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/easydigitaldownloads.com\/development\/wp-json\/wp\/v2\/tags?post=1062"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}