3DD – Easy Digital Downloads Development https://easydigitaldownloads.com/development Official development blog for Easy Digital Downloads Sun, 10 Jul 2022 03:51:34 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.2 https://easydigitaldownloads.com/development/files/2015/11/icon-256x256-150x150.png 3DD – Easy Digital Downloads Development https://easydigitaldownloads.com/development 32 32 Easy Digital Downloads 3.0 – Release Update https://easydigitaldownloads.com/development/2022/07/09/easy-digital-downloads-3-0-release-update/ https://easydigitaldownloads.com/development/2022/07/09/easy-digital-downloads-3-0-release-update/#comments Sun, 10 Jul 2022 03:51:33 +0000 https://easydigitaldownloads.com/development/?p=1146

Continue reading →

]]>
Well the time has arrived! We are tagging our final release candidate for EDD 3.0. Many of you have been following along on our GitHub repository over the last several months, helping test and finding things that need to be addressed. We’re very thankful for your help getting to this point.

As we approach the final release date of July 13th, 2022 here are the changes since the last major tag we gave you all.

There have been a significant number of bug fixes, but we wanted to call attention to some of the larger changes that might pose an issue for developers as they integrate with EDD.

Reporting Changes

We’ve made a few changes related to the reports to help give store owners an actionable set of information on the ‘Dashboard’ of reports. Many of these changes came after we’ve had a chance to use Easy Digital Downloads 3.0 on our own site, for our daily business operations.

The first thing you’ll notice is that we’ve consolidated some of the ’tiles’. We reduced the number of tiles in this Dashboard to make the overall view much more useful.

Updated Reports Dashboard tiles with improved styles for relational data.

We’ve also been focused on fixing some issues around reporting with Timezones. As of EDD 3.0 all dates recorded in the database are in UTC. By doing this we gave ourselves a point of reference, so that we can always show the store’s reports based on the Timezone setting defined in the general WordPress settings.

Order status helper functions

As we started focusing on not just reporting on Gross and Net stats, we also found it necessary to define some ‘grouped’ order status keys. The following functions are helper functions to get specific order status that should be grouped. Each of these functions also contains a similar filter to allow extensions and customizations to add their own statuses.

edd_get_gross_order_statuses()

Returns an array of order status keys that should be used when wanting orders that should be considered part of a ‘gross’ report.


edd_get_net_order_statuses()

Returns an array of order status keys that should be used when wanting orders that should be considered part of a ‘net’ report.


edd_recoverable_order_statuses()

Returns an array of order status keys that can be used in the core payment recovery feature.


edd_get_complete_order_statuses()

Returns an array of order status keys that are considered ‘complete’. This means they have hit the end of any automated purchase process and no further action needs to be taken at this time.


edd_get_incomplete_order_statuses()

Returns an array of order status keys that are incomplete. This includes things like pending, abandoned, processing, failed or cancelled.


edd_get_refundable_order_statuses()

Returns an array of order status keys that can be refunded.


edd_get_deliverable_order_item_statuses()

Returns an array of order item status keys that should be considered when delivering files. Note that in EDD 3.0, deliverability should be handled at the individual order item level, since one order can contain multiple items with different statuses.

Enabled block editor on Download post type

The download custom post type is now available in the REST API, so your product pages can now be edited with the block editor.

Language files removed

We’ve removed all of our translation files from our package, in order to rely on the WordPress Translation community. We found a number of translation files that were out of date and causing fatal errors due to being incorrectly translated, so we felt it was best to remove them from our plugin entirely, and allow them to be downloaded from translate.wordpress.org.

On-the-fly Backwards Compatibility

We know that keeping stores accepting payments is important, and from day one of EDD 3.0’s development, we wanted to allow new purchases to be able to be completed, while the site was migrating existing payment data.

We’ve taken this a step further, so that when renewals are processed with Recurring Payments or licenses keys are interacted with (checking for updates, activating, deactivating, or checking), that these actions complete successfully with a ‘semi-backwards compatible’ layer of EDD that ensures critical functionality will still work.

We’ve also added the edd_v3_migration_pending option so that you can identify when a migration is either pending start or running. For instance, you may have seen this on our site a few weeks back while we were running this migration ourselves:

We displayed this message to users during the migration, using the edd_v3_migration_pending option.

Other Bug Fixes and Changes

  • Order details will now always show quantities for items.
  • Improved performance getting cart total, by making tax calculations more efficient.
  • Added a new Currency class, to help support multi-currency stores.
  • Filters were added to the discount list table.
  • Added a new edd_is_cart_empty() helper function.
  • Improved performance of status calculations for downloads.

So what is next?

Well, now that we’ve tagged our final release, we’re going to be pushing this to WordPress.org as a ‘development version’ in order to allow translators to start translating all the new strings.

Shortly after that we will tag our final release on WordPress.org and we’ll go live on July 13, 2022!

As always with large releases like this, especially ones that are moving data around, we would suggest making backups of your site and database prior to any changes being made, as well as testing this out on a staging or local copy of your site first! We’ve tested it extensively and are already running this on our site, but it is always good practice to try it in staging first.

Thanks for your help and support!

]]>
https://easydigitaldownloads.com/development/2022/07/09/easy-digital-downloads-3-0-release-update/feed/ 7
Easy Digital Downloads 3.0-beta3 now available https://easydigitaldownloads.com/development/2021/07/13/edd-3-0-beta3/ https://easydigitaldownloads.com/development/2021/07/13/edd-3-0-beta3/#comments Tue, 13 Jul 2021 09:06:37 +0000 https://easydigitaldownloads.com/development/?p=1091

Continue reading →

]]>
Our beta3 release is fairly small compared to the other two, but it contains some pretty important bug fixes, which is why we wanted to make it available to anyone testing 3.0.

Important Note: This beta release is NOT production ready. It should only be tested on development sites. Do not install it on your live site.

Migration fixes

We discovered that migrated order totals could be incorrect if the order had a fee applied that affected the entire order (as opposed to being linked to an individual item). This has now been resolved.

While fixing the fee issue, we also found a few problems when migrating data from very old versions of Easy Digital Downloads — we’re talking back to 2013. Back then, individual payments didn’t even store things like the subtotal or exact discount amount, and that led to unexpected results when the data was migrated to the 3.0 format.

Orders with discounts from that period still may not be perfect, but we’re confident we’ve done the best we can given the limited data from that era. It won’t be any worse than EDD 2.10, it’s just that EDD 3.0 exposes the problems that exist in 2.10 and are simply hidden. For example: if a discount amount wasn’t saved with an old EDD order, EDD 3.0 will show the discount amount as $0.00. That’s not technically correct; there was a discount amount, but because EDD never stored it we don’t know what it is.

Other migration fixes include:

  • Undefined index errors when migrating some order addresses.
  • When migrating tax rates via the CLI we now show the before and after count.
  • Some very old PayPal orders didn’t have their transaction IDs migrated. This is because old orders didn’t store transaction IDs the way we do now, and they only existed in order notes. These are now migrated over.
  • Some currency codes were saved (and thus also migrated) in lowercase, which caused unexpected results in our UIs. We now ensure all currency codes are uppercase when migrated.

The sales log has been removed

The sales log has historically existed because it was too difficult for us to query on payments directly, due to storing data in post meta. EDD 3.0 has made the sales log no longer necessary, as we can now very easily query order data. However, the UI still existed.

We made the decision to remove it when we found a bug: refund records were being included in the sales log incorrectly. Fixing that issue actually proved to be more complicated than expected, to the point where it would take less time to just remove the sales log and instead add the one missing feature to the main orders page: the ability to filter by download (product).

Product filter on the admin orders page

So there’s a shiny new feature for you!

Other bug fixes

  • EDD_Payments_Stats methods returning unexpected results.
  • edd_store_discount() had the default value for its second parameter changed from null to 0, which broke backwards compatibility. This has now been reverted.
  • The edd_post_insert_discount hook wasn’t firing after adding a discount code from the admin UI. This caused at least one add-on to stop working with EDD 3.0.
  • The Discount API endpoint wasn’t 3.0-ready.
  • Negative fees were showing as positive on the admin orders UI.
  • Adding a manual order now supports inclusive taxes.
  • Several methods in the EDD_Discount class were missing compared to 2.x. (Such as the get_name() method.)
  • The tool for re-counting download stats was incorrectly including refunds. It now counts gross earnings, and the label has been updated to better clarify that.
  • Reports: Manually adding an invalid date to the custom range field could cause a fatal error.
  • A few discount note functions that were introduced in 3.0 and ultimately never used (due to later refactoring) have been removed. Those functions are: edd_ajax_add_discount_note(), edd_delete_discount_note(), and edd_ajax_delete_discount_note(). These were all AJAX callback functions and were never designed for public use.
  • Order item meta arrays were incorrectly being double serialized.

Installing and testing 3.0-beta3

The 3.0-beta3 release can be downloaded from GitHub and installed as normal. If you encounter any bugs, please search through our existing issues. If there’s not already an open issue, you may create a new one (after reading our Contributor Guidelines).

]]>
https://easydigitaldownloads.com/development/2021/07/13/edd-3-0-beta3/feed/ 21
Easy Digital Downloads 3.0-beta2 now available https://easydigitaldownloads.com/development/2021/05/20/edd-3-0-beta2/ https://easydigitaldownloads.com/development/2021/05/20/edd-3-0-beta2/#comments Thu, 20 May 2021 14:30:26 +0000 https://easydigitaldownloads.com/development/?p=1062

Continue reading →

]]>
Since releasing 3.0-beta1 back in February, we’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 release is now available for testing, and in this blog post we’ll go over three of the major changes.

  1. The new refunds API has been finalized
  2. Templates have been reworked
  3. The migration now has step recovery

Important Note: This beta release is NOT production ready. It should only be tested on development sites. Do not install it on your live site.

The new refunds API has been finalized

When we released 3.0-beta1, we made it clear that refunds were still a work in progress, but they have now been completed!

Modal for submitting a refund, with a checkbox to "Refund transaction in PayPal".

Here are a few notable changes:

  • Each order item and fee will have a listing in the modal, and you can select which items to refund. It’s possible to refund a fee without refunding the order items, and vice versa.
  • 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.
  • We have added a hook to the modal, which you can use to output custom fields below the table. You can see how we’ve added a checkbox that gives you the option to “Refund transaction in PayPal.”

Let’s talk about that last item for a moment. If you’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’s our implementation for PayPal:

Adding the checkbox to the UI

Here’s what the code looks like to add a checkbox to the UI:

/**
 * Shows a checkbox to automatically refund payments in PayPal.
 *
 * @param \EDD\Orders\Order $order
 *
 * @since 3.0
 * @return void
 */
function edd_paypal_refund_checkbox( \EDD\Orders\Order $order ) {
	if ( 'paypal' !== $order->gateway ) {
		return;
	}

	// If our credentials are not set, return early.
	$key       = $order->mode;
	$username  = edd_get_option( 'paypal_' . $key . '_api_username' );
	$password  = edd_get_option( 'paypal_' . $key . '_api_password' );
	$signature = edd_get_option( 'paypal_' . $key . '_api_signature' );

	if ( empty( $username ) || empty( $password ) || empty( $signature ) ) {
		return;
	}
	?>
	<div class="edd-form-group edd-paypal-refund-transaction">
		<div class="edd-form-group__control">
			<input type="checkbox" id="edd-paypal-refund" name="edd-paypal-refund" class="edd-form-group__input" value="1">
			<label for="edd-paypal-refund" class="edd-form-group__label">
				<?php esc_html_e( 'Refund transaction in PayPal', 'easy-digital-downloads' ); ?>
			</label>
		</div>
	</div>
	<?php
}
add_action( 'edd_after_submit_refund_table', 'edd_paypal_refund_checkbox' );
  • Hook into edd_after_submit_refund_table. This hook provides one parameter: the \EDD\Orders\Order object.
  • Be sure to check that the order is using your gateway.
  • We only show the option if the API keys have been configured.
  • Then output markup to show the custom field.

The next step is to actually process the refund. Here’s the code to make that happen:

/**
 * If selected, refunds a transaction in PayPal when creating a new refund record.
 *
 * @param int $order_id ID of the order we're processing a refund for.
 * @param int $refund_id ID of the newly created refund record.
 * @param bool $all_refunded Whether or not this was a full refund.
 *
 * @since 3.0
 */
function edd_paypal_maybe_refund_transaction( $order_id, $refund_id, $all_refunded ) {
	if ( ! current_user_can( 'edit_shop_payments', $order_id ) ) {
		return;
	}

	if ( empty( $_POST['data'] ) ) {
		return;
	}

	$order = edd_get_order( $order_id );
	if ( empty( $order->gateway ) || 'paypal' !== $order->gateway ) {
		return;
	}

	// Get our data out of the serialized string.
	parse_str( $_POST['data'], $form_data );

	if ( empty( $form_data['edd-paypal-refund'] ) ) {
		// Checkbox was not checked.
		return;
	}

	$refund = edd_get_order( $refund_id );
	if ( empty( $refund->total ) ) {
		return;
	}

	edd_refund_paypal_purchase( $order, $refund );
}
add_action( 'edd_refund_order', 'edd_paypal_maybe_refund_transaction', 10, 3 );
  • Hook into edd_refund_order. 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.
  • Be sure to include a permission check.
  • Be sure to check the relevant gateway.
  • To get the data from the form you’ll want to run: parse_str( $_POST['data'], $form_data ); Then the posted data will be available in $form_data.
  • As a sanity check, we make sure the newly created refund total isn’t empty (0.00).
  • Then, finally, you can execute your code to actually process the refund at the gateway. (We call edd_refund_paypal_purchase()).

You can see all our code for this in context in the PayPal Standard gateway file.

Templates have been reworked (but are still backwards compatible!)

We’ve updated the history-downloads.php and history-purchases.php templates to use all new 3.0 functions.

The main motivation behind this change was speed. Working with the legacy EDD_Payment object (and associated edd_get_payment() and edd_get_users_purchases() functions) is a performance hit. We have to navigate through multiple backwards compatibility layers to build up that object.

Prior to making the changes, the purchase history template was running approximately 300-400 queries — sometimes more. That definitely slowed the page down and resulted in a pretty negative experience. After reworking it, we’ve gotten it down to approximately 35 queries. That’s quite an improvement!

So what do these changes actually mean for you?

Every hook executed within those templates that passed through an EDD_Payment object (or array of objects) has been deprecated, and new replacements have been created. For example:

Here’s an example hook in the previous template version:

do_action( 'edd_before_purchase_history', $payments );

This hook has been deprecated because it was built to receive an array of EDD_Payment objects. It has been replaced with this new hook, which instead takes an array of \EDD\Orders\Order objects:

do_action( 'edd_before_order_history', $orders );

That being said, the old hook will still work. We hook into the new action to trigger the old:

add_action( 'edd_before_order_history', function( $orders ) {
	if ( ! has_action( 'edd_before_purchase_history' ) ) {
		return;
	}

	$payments = array();

	if ( ! empty( $orders ) ) {
		$order_ids = wp_list_pluck( $orders, 'id' );
		$payments  = edd_get_payments(
			array(
				'id__in'  => $order_ids,
				'orderby' => 'date',
			)
		);
	}

	do_action( 'edd_before_purchase_history', $payments );
} );

The only thing this means for you is that if you’re hooking into the old action you will see a performance hit, because we will need to load in the EDD_Payment objects for your hook.

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.

For a full list of all deprecated hooks, check out our new deprecated-hooks.php file.

The migration now has step recovery

The 3.0 migration has 8 different steps — 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 within each step could not. This has changed with beta2.

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.

Installing and testing 3.0-beta2

The 3.0-beta2 release can be downloaded from GitHub and installed as normal. If you encounter any bugs, please search through our existing issues. If there’s not already an open issue, you may create a new one (after reading our Contributor Guidelines).

What’s next for 3.0?

Our next major goal is to upgrade to 3.0 on one of our own Sandhills product sites. We’ve been hard at work updating extensions — first prioritizing the ones we use internally — so we can upgrade to 3.0. We will be doing this prior to the official 3.0 release.

We don’t have an exact date for this yet, and there are still a few extensions we need to update first, but I suspect you’ll see us with another blog post when it happens so we can tell you all about how it went!

]]>
https://easydigitaldownloads.com/development/2021/05/20/edd-3-0-beta2/feed/ 2
How to Add Custom Sections to Order Details in EDD 3.0 https://easydigitaldownloads.com/development/2021/03/22/custom-order-sections/ https://easydigitaldownloads.com/development/2021/03/22/custom-order-sections/#respond Mon, 22 Mar 2021 13:58:00 +0000 https://easydigitaldownloads.com/development/?p=1025

Continue reading →

]]>
There is a lot of information stored about every order placed in an Easy Digital Downloads storefront. In 3.0, the Order Details screen has been completely updated to be easier to read and manage.

One big change is the addition of order sections, which allow necessary, but less immediate, data to be hidden on the initial screen load. Core sections included in Easy Digital Downloads are:

  • Customer (default)
  • Email
  • Address
  • Notes
  • Logs

Extension authors may want to add their own data to these sections as well. To do so, start with registering the custom section:

add_filter( 'edd_get_order_details_sections', 'prefix_add_custom_order_section', 10, 2 );
/**
 * Adds the custom details as an order section in EDD 3.0.
 *
 * @since 2.3.9
 * @param array  $sections The array of order sections.
 * @param object $order    The order object.
 * @return array
 */
function prefix_add_custom_order_section( $sections, $order ) {

    $sections[] = array(
        'id'       => 'prefix_order_section',
        'label'    => __( 'Custom Section' ),
        'icon'     => 'admin-multisite',
        'callback' => 'prefix_show_custom_order_section',
    );

    return $sections;
}

This will add your new custom section to the end of the array of sections (after Logs). Each section has four parameters:

  • id: The unique ID of the section
  • label: The label which will show in the navigation menu
  • icon: The dashicon to use with the navigation label
  • callback: the function which will output the section content

The next step is to build your prefix_show_custom_order_section function. This accepts one parameter, the order object. It would begin with something like this:

/** * Shows the custom order section in EDD 3.0.
 *
 * @param \EDD\Orders\Order object $order The order object.
 * @return void
 */
function prefix_show_custom_order_section( $order ) {
    printf( '<h3 class="hndle">%s</h3>', esc_html__( 'Custom Section Heading' ) );
    // Custom code for the section
}

Custom order data can be varied. EDD Simple Shipping, for example, registers two custom sections: one for the shipping address and one for tracking information. These are displayed as individual metabox style boxes in EDD 2.10, but as order sections in 3.0.

Screenshot of the Shipping order section.
Simple Shipping registers two custom order sections: Shipping and Tracking.

Note that in EDD 2.10, the parameter that’s available to a metabox is just the $payment_id, and in EDD 3.0, the entire order object is available. To be compatible with both versions of EDD, you may want to call a separate function from your prefix_show_custom_order_section function, and just pass the $order->id to it. It’s a little extra work to update the code to work with both the order sections and the edd_view_order_details_billing_after hook, which is what metaboxes in 2.10 would use, but it’s worth doing to seamlessly integrate into the new EDD.

]]>
https://easydigitaldownloads.com/development/2021/03/22/custom-order-sections/feed/ 0
Easy Digital Downloads 3.0-beta1 now ready for testing https://easydigitaldownloads.com/development/2021/02/16/edd-3-0-beta1/ https://easydigitaldownloads.com/development/2021/02/16/edd-3-0-beta1/#comments Tue, 16 Feb 2021 14:20:14 +0000 https://easydigitaldownloads.com/development/?p=963

Continue reading →

]]>
We’re pleased to announce that the first beta for Easy Digital Downloads 3.0 is now available! This has been a long time coming, and we want to thank you all for your patience and understanding while it’s been in development.

Important Note: This beta release is NOT production ready. It should only be tested on development sites. Do not install it on your live site.

Our goals for the first 3.0 beta

Easy Digital Downloads 3.0 is not yet a finished product. The point of this first beta release is not to test the plugin as a whole, but to focus on these key things:

  1. Early testing on our migration process, to ensure all necessary data is migrated to its new place and that there are no issues with the data transfer or backwards compatibility.
  2. Giving third party developers a chance to see how the code base has changed in 3.0, and the opportunity to update their extensions to be compatible.

Official extensions that are compatible with 3.0:

The following extensions have been already updated to work with 3.0 and may be used in testing:

  • Auto Register, version 1.3.11+
  • Braintree Gateway, version 1.1.6+
  • Commissions, version 3.4.11+
  • Gateway Fees
  • PDF Invoices, version 2.2.27+
  • Recurring, version 2.10.1+
  • Software Licensing, version 3.7+
  • Stripe Gateway, version 2.8+
    * When checking out with Stripe, you may see a debug notice about addresses being stored incorrectly. This will be addressed in version 2.8.1.

What’s not ready for testing

Order refunds are still undergoing some changes, particularly with regards to refunding fees, so we do not recommend testing refunds or updating any of your own refund-related code. We hope for this to be ready for the beta2 release.

System requirements

In order to run EDD 3.0 you’ll need to have the following minimum versions:

  • PHP 5.6+
  • WordPress 4.9+

Note: If you installed EDD 3.0 back in 2018 but have not pulled the release branch since then, we recommend starting with an entirely fresh install. This is because we’ve removed some incremental database upgrades from the 3.0 development branch that were introduced in 2018. If you’re installing or upgrading to 3.0 for the first time then this does not affect you.

Installing 3.0-beta1

The 3.0 beta release can be downloaded from GitHub and installed as normal. After installation, new database tables will be installed in the background and you will be prompted to run the 3.0 migration.

Testing the custom tables migration

In 3.0 we migrate the bulk of EDD data out of the WordPress core tables (posts, postmeta, etc.) and into our new custom tables. This includes:

  • Discounts
  • Payments
  • Customer addresses
  • Customer email addresses
  • Logs
  • Order notes
  • Customer notes

The migration can either be performed through an admin UI, or run through WP-CLI using this command:

wp edd v30_migration
EDD 3.0 migration UI

While testing the migration, double check that all your data has been migrated successfully and that none has been lost — this is particularly true of any custom data you may have added.

Custom payment meta to watch out for

_edd_payment_meta

If you’ve added any custom keys to the _edd_payment_meta array then those will be inserted into our new wp_edd_ordermeta table using the key payment_meta. Just like before, this will be saved as a serialized array.

Note: Calls to edd_get_payment_meta( $payment_id, '_edd_payment_meta' ) are still fully backwards compatible and will include your custom keys/values. However, the backwards compatibility layers do mean that this old method will be slower than our newer edd_get_order_meta() functions so we recommend updating if possible.

Cart item options

In 2.9, _edd_payment_meta included an array that looked like this:

array(
    'cart_details' => array(
        array(
            'item_number' => array(
                'options' => array(
                    'price_id' => 1,
                    'quantity' => 1,
                    // More
                )
            )
        )
    )
)

Any keys added to that options array will be migrated to our new wp_edd_order_itemmeta table. This is meta associated with an individual order item, rather than the order as a whole.

Note: Retrieving this information via edd_get_payment_meta() or edd_get_payment_meta_cart_details() is still fully backwards compatible in 3.0. However, the backwards compatibility layers do mean that this old method will be slower than our newer edd_get_order_meta() functions so we recommend updating if possible.

Custom meta keys

Any custom pieces of meta data associated with a payment will be transferred exactly over to our new wp_edd_ordermeta table. Only the storage location has changed; the data and format remains exactly the same.

Updating your integrations for 3.0

Plugins can be compatible with both EDD 2.9 and 3.0 at the same time. However, a few methods are no longer compatible with 3.0 and your code may need to be updated accordingly.

Ensure you’re not using “post” helper functions on payments, discounts, or logs

In 3.0 you can no longer use “post”-related helper functions on payment, log, or discount code objects. This includes get_post(), get_post_meta(), and more. You will need to update your code to use our wrapper functions instead.

Here’s a detailed list of examples:

Payments/orders

Note: in 3.0, payments are now referred to as “orders”, which is reflected in the new function names.

Retrieving a payment/order

// NO LONGER VALID
$payment = get_post( $payment_id );

// Valid in both 2.9 and 3.0
$payment = edd_get_payment( $payment_id );

// Valid in 3.0 only
$payment = edd_get_order( $payment_id );

Retrieving meta attached to a payment/order

// NO LONGER VALID
$meta = get_post_meta( $payment_id, 'your_meta_key_here', true );

// Valid in both 2.9 and 3.0
$meta = edd_get_payment_meta( $payment_id, 'your_meta_key_here', true );

// Valid in 3.0 only
$meta = edd_get_order_meta( $payment_id, 'your_meta_key_here', true );

Adding or updating payment/order meta

// NO LONGER VALID
update_post_meta( $payment_id, 'your_meta_key_here', 'your meta value' );

// Valid in both 2.9 and 3.0
edd_update_payment_meta( $payment_id, 'your_meta_key_here', 'your meta value' );

// Valid in 3.0 only
edd_update_order_meta( $payment_id, 'your_meta_key_here', 'your meta value' );

Querying for payment/order records

// NO LONGER VALID
$payments = get_posts( array(
    'post_type'   => 'edd_payment',
    'post_status' => 'publish'
) );

// NO LONGER VALID
$payments = new WP_Query( ( array(
    'post_type'   => 'edd_payment',
    'post_status' => 'publish'
) );

// Valid in both 2.9 and 3.0
$payments = edd_get_payments( array(
    'status' => 'publish'
) );

// Valid in 3.0 only
$payments = edd_get_orders( array(
    'status' => 'complete'
) );

Discounts

Retrieving a discount code

// NO LONGER VALID
$discount = get_post( $discount_id );

// Valid in both 2.9 and 3.0
// Get by ID
$discount = edd_get_discount( $discount_id );

// Get by code
$discount = edd_get_discount_by_code( 'BFCM2021' );

Querying for discount codes

// NO LONGER VALID
$discounts = get_posts( array(
    'post_type'   => 'edd_discount',
    'post_status' => array( 'active', 'inactive' )
) );

// Valid in both 2.9 and 3.0
$discounts = edd_get_discounts( array(
    'post_status' => array( 'active', 'inactive' )
) );

Retrieving meta attached to a discount

// NO LONGER VALID
$meta = get_post_meta( $discount_id, 'your_meta_key_here', true );

// Valid in both 2.9 and 3.0
$discount = edd_get_discount( $discount_id );
$discount->get_meta( 'your_meta_key_here', true );

// Valid in 3.0 only
edd_get_adjustment_meta( $discount_id, 'your_meta_key_here', true );

Adding or updating meta

// NO LONGER VALID
update_post_meta( $discount_id, 'your_meta_key_here', 'your meta value' );

// Valid in both 2.9 and 3.0
$discount = edd_get_discount( $discount_id );
$discount->update_meta( 'your_meta_key_here', 'your meta value' );

// Valid in 3.0 only
edd_update_adjustment_meta( $discount_id, 'your_meta_key_here', 'your meta value' );

Logs

EDD has a class called EDD_Logging, which is available in 2.9 and fully backwards compatible in 3.0. If your code needs to be compatible with both versions, ensure you use this class for all querying and inserting.

Querying logs:

global $edd_logs;
$edd_logs->get_logs( $object_id, $log_type, $page_number );

Inserting a log:

global $edd_logs;
$edd_logs->insert( array(
    'log_type'    => 'gateway_error',
    'post_parent' => $download_id
) );

EDD 3.0 also comes with several new functions. Logs are split up into different database tables according to type: file download logs, API request logs, and generic logs. Here are the new functions for generic logs:

Querying logs:

$logs = edd_get_logs( array(
    'type'    => 'gateway_error',
    'user_id' => $user_id
) );

Inserting a log:

edd_add_log( array(
    'object_id'   => $object_id,
    'object_type' => $object_type,
    'user_id'     => $user_id,
    'type'        => $log_type,
    'title'       => $log_title,
    'content'     => $log_content
) );

Update raw queries on the wp_posts database table

In 3.0, most data has been migrated out of wp_posts and wp_postmeta. As a result, if you’re performing any raw queries on those tables, you may need to update your integration to query on our new tables instead in 3.0.

Here’s a before and after example of one of our own queries for download logs:

2.9 query on the posts/postmeta tables:

SELECT post_parent as downloaded_product_id, COUNT(post_parent) AS number_of_downloads, COUNT(DISTINCT meta_value) AS unique_passes_used
FROM {$wpdb->posts} p
LEFT JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
WHERE meta_key = '_edd_log_all_access_pass_id'
AND meta_value LIKE '%_{$all_access_product_id}_%'
AND post_date_gmt > %s
AND post_date_gmt < %s
GROUP BY post_parent
ORDER BY COUNT(post_parent) DESC;

3.0 query on the file_downloads/file_downloadmeta tables:

SELECT product_id as downloaded_product_id, COUNT(product_id) as number_of_downloads, COUNT(DISTINCT meta_value) as unique_passes_used
FROM {$wpdb->edd_logs_file_downloads} l
INNER JOIN {$wpdb->edd_logs_file_downloadmeta} lm ON l.id = lm.edd_logs_file_download_id
WHERE meta_key = '_edd_log_all_access_pass_id'
AND meta_value LIKE '%_{$all_access_product_id}_%'
AND date_created > %s
AND date_created < %s
GROUP BY product_id
ORDER BY COUNT(product_id) DESC

With custom queries like this, you will need to load one version if the site is running EDD 2.9 or lower, and another version if the site is running 3.0+.

Reporting issues

EDD 3.0 is still in active development on GitHub. If you encounter any bugs, please search through our existing issues. If there’s not already an open issue, you may create a new one (after reading our Contributor Guidelines). Please prefix all issues with “3.0 -” so we know it pertains to the 3.0 release.

]]>
https://easydigitaldownloads.com/development/2021/02/16/edd-3-0-beta1/feed/ 26
Easy Digital Downloads 3.0 – Development Update https://easydigitaldownloads.com/development/2020/06/30/easy-digital-downloads-3-0-development-update-2/ https://easydigitaldownloads.com/development/2020/06/30/easy-digital-downloads-3-0-development-update-2/#comments Tue, 30 Jun 2020 15:00:00 +0000 https://easydigitaldownloads.com/development/?p=908

Continue reading →

]]>
The most significant update to Easy Digital Downloads is nearing its initial beta phase. The team has been focused on finalizing the last issues related to data integrity, backwards compatibility, and migration accuracy. We’ve made some updates recently that apply significant improvements to performance and compatibility with our extensions and the migration alike.

Taxes

In a previous update we showed some improvements to our Tax UI. Since then we’ve made a few more significant changes and fixes that should be noted.

Deprecated the “Default Tax Rate”

As we moved forward with the improvements to the tax features of Easy Digital Downloads, we realized that the ‘Default Tax Rate’ was a setting that ultimately caused problems with our new method of reporting on taxes. It also proved to be a concern as taxes should be applied to a region, but a default tax rate has no region. As such, if Easy Digital Downloads detects a ‘Default Tax Rate’, we are letting stores know this is no longer supported and a region specific tax rate should be identified.

Tax rate improvements

We’ve worked towards making managing tax rates easier in 3.0. On top of the new UI for managing taxes we’ve fixed a few cases where users could add multiple active tax rates for an entire country both in the UI as well as during the migration process.

We’re also planning to include auto-saving tax rates, negating the need to ‘save changes’ after each tax rate modification. This will be done in our Post-Alpha phase.

We’ve also identified and fixed a bug in the migration where a tax rate was being incorrectly rounded up or down to meet the currency decimal point defined by the store’s default currency.

Reporting updates

One of the most improved features of Easy Digital Downloads 3.0 is the reporting system. Thanks to a large amount of database changes and custom tables, the team has been able to improve reporting. The most recent focus was finalizing the UI around reports to make things consistent and accurate no matter what report you are viewing.

Gross/Net status functions

To assist in the accurate reporting in all aspects of Easy Digital Downloads, we’ve introduced two functions which return statuses of orders that would be considered to affect gross and net statistics.

edd_get_gross_order_statuses()
edd_get_net_order_statuses()

These two functions also include filters to allow extension developers to include their own statuses in these calculations, if they are needed. The goal with these two functions is to use a Don’t Repeat Yourself (DRY) method of when to include an order when calculating statistics.

Date ranges in reports

As any developer knows, dates can be difficult. We’ve put some significant effort over the last couple months making sure that when viewing reports, that it is clear that the date ranges are clear and match the expected outcomes. This has caused us to make some significant updates to the filter handlers for reporting.

We’ve also worked on fixing some inconsistencies in the reports that caused the edges of date ranges to not be included in the requested reports. This was a bug that presented itself in current versions of EDD, and thanks to the new reporting APIs, was an easy fix with the new 3.0 data structure.

Improved customer statistics

In previous versions of EDD, our customer reporting statistics for lifetime value and lifetime purchase counts were all ledger based. As new orders were placed or refunded we would simply take the existing value, and add or subtract the modified amount. This could lead to inaccurate reporting and forced us to introduce a tool to ‘recalculate stats’ that needed to be used more frequently than we liked to see.

In 3.0, again thanks to the new database structure, it is an insignificant process for us to quickly, and accurately calculate a customer’s statistics without needing a ledger. When an order is modified for a customer, we quickly recalculate the entire lifetime value and purchase count of the customer, avoiding inaccuracies due to ledger inconsistencies.

The above change, however, does remove the ability to directly affect a customer’s lifetime value or purchase count. As of 3.0, the methods to increase a customer’s value or purchase count by an arbitrary amount are deprecated.

Customer updates

One of the most significant changes to the customer feature of Easy Digital Downloads comes in how both physical addresses and email addresses are managed. Both email addresses and physical addresses have custom tables instead of storing this data in meta, which significantly improves the performance of looking up customers.

Physical address improvements

In recent changes, we’ve introduced the concept of physical address ‘types’ as well as a way to identify what the ‘primary’ physical address is. While Easy Digital Downloads core only supports the billing address out of the box, extensions like Simple Shipping can add in shipping addresses, which will allow each customer to have multiple types of primary addresses, for use in future updates to both EDD and extensions.

Avoid duplicate address data

Our previous methods of storing physical address data resulted in a large number of duplicated addresses for customers. We’ve made some drastic improvements to the address validation before inserting new addresses into the customer record so that we don’t fill your database with duplicate data, including during the migration process.

UI and accessibility updates

After all of the work that was done in an effort to improve the performance and data structures, we needed to make some significant updates to the UI to reflect these changes. With that, we took the opportunity to improve not just the overall UI, but the mobile-friendly access, as well as accessibility. While we aren’t done yet we’ll be making further improvements as we near the 3.0 release, and shortly after it. Some of the areas where we’ve put in the most effort to improve the UI are:

  • Order details
  • Order list tables
  • Tax rates
  • Settings
  • Download Post Type Metaboxes

While we aren’t fully done with improving the accessibility of the UI and making things more semantic when it comes to our form inputs, you can follow along here. Note this is a living document and is subject to change.

What is next…

We’ve split the last part of this development into two projects:

  • Pre-Alpha
  • Post-Alpha

At Sandhills development, we like to use our software internally prior to any beta release. This is so we can identify any issues we find internally before releasing them to our customers, even in a beta phase.

Our project for Pre-Alpha are changes that we have to complete prior to when we start internally testing on our sites, and getting all of our extensions updated to support Easy Digital Downloads 3.0. Upon completion of the Pre-Alpha project we’ll shift our focus to extension releases that make them compatible with 3.0 ahead of release, so you shouldn’t have to worry about your extensions working with 3.0 after release.

Once we’re running an alpha on our own data sets, we’ll be shifting our focus to Post-Alpha project issues, after which, we will be publishing our first beta for public testing.

]]>
https://easydigitaldownloads.com/development/2020/06/30/easy-digital-downloads-3-0-development-update-2/feed/ 12
Easy Digital Downloads 3.0 Update – February 13, 2019 https://easydigitaldownloads.com/development/2019/02/13/easy-digital-downloads-3-0-update-february-13-2019/ https://easydigitaldownloads.com/development/2019/02/13/easy-digital-downloads-3-0-update-february-13-2019/#comments Wed, 13 Feb 2019 22:40:26 +0000 https://easydigitaldownloads.com/development/?p=813

Continue reading →

]]>
Another couple weeks have passed, and we’ve got another development update on Version 3.0 of Easy Digital Downloads. Here are your changes since the last update.

New refund UI and APIs

In the past refunding items and orders didn’t quite follow basic tenants of the Generally Accepted Accounting Principles, or GAAP for short. This could create difficult situations in support when coming back to an order weeks, months, or even years later, to determine what was actually done with an order. Refunding an order was an all or nothing experience. If you wanted to remove a single item, it was completely removed from the order. As you may have experienced, this was less than ideal.

In EDD 3.0, we’ve completely changed how refunds operate. Refunds are now a specific type of ‘order’. Since a refund is similar to an order, they exist in the same database table with a type of ‘refund’. They also have related order items, which are the specific items refunded. You can refund some or all of the items from an order. Refunds can also have their own transaction IDs. We’ve worked up a user experience that I think will highlight this process here:

Next up for the refund process is getting gateway functionality baked in so that this new way of processing refunds works as seamlessly as possible with your enabled gateways.

Other improvements and bug fixes

  • Fixed a bug in the get_average_refund_time method, which caused a MySQL error. (#7148)
  • When creating a new order, tax calculations were failing when quantities were disabled. (#7072)
  • Further improved the view/edit order details Customer information section (#7052)
  • Fixed an issue that resulted in the status counts of orders to be incorrect when filtering the list table. (#7079)
  • Improved the way the product dropdown works with bundles. (#6760)
  • Improved timezone compatibility with PHP 5.5 and lower. (#7130)

Major updates yet to tackle

  • Improve the upgrade routines for stability – A host of improvements are in the works to make the upgrade routines more stable and accurate as well as fault tolerant.
  • Extension testing and compatibility – The time has come, to start working through extensions and make sure we can pre-release any known compatibility issues prior to 3.0 being released.

So those are the major changes since our last update. Keep looking for these posts until we hit the release date in order to make sure your upgrade to Easy Digital Downloads 3.0 is as smooth as possible.

]]>
https://easydigitaldownloads.com/development/2019/02/13/easy-digital-downloads-3-0-update-february-13-2019/feed/ 23
Easy Digital Downloads 3.0 Update – January 28, 2019 https://easydigitaldownloads.com/development/2019/01/28/easy-digital-downloads-3-0-update-january-28-1019/ https://easydigitaldownloads.com/development/2019/01/28/easy-digital-downloads-3-0-update-january-28-1019/#comments Mon, 28 Jan 2019 20:30:58 +0000 https://easydigitaldownloads.com/development/?p=796

Continue reading →

]]>
Easy Digital Downloads 3.0 is getting closer and closer to the beta, and to keep with our commitment, here is another update to help keep developers up to speed with progress and what’s been changed since our last update.

PHP compatibility

Nothing has been changed here, but we wanted to make it a point that in the last couple weeks, we have shored up our unit tests and have fixed everything causing compatibility issues with PHP versions 5.5 and lower. The primary issue we fixed was dealing with the DateTimeZone class in PHP, which underwent some changes in PHP 5.6. While we developed it using PHP 7.2, we were not accounting for versions of PHP lower than 5.6, but have since corrected these. You can read more about it on the GitHub issue.

Currently our goal is still to maintain support for PHP versions 5.3+.

WordPress version compatibility changes

Currently, Easy Digital Downloads version 2.9.x is compatible with WordPress versions all the way back to 4.4. With the release of Easy Digital Downloads 3.0, the required version of WordPress will be 4.7 or greater. Based off our data this will affect a small number of stores, but with WordPress 4.7 being our minimum version, this means we’re supporting nearly 3 years of backwards compatibility with WordPress core.

Status change for ‘completed’ orders

The change from publish to complete for an order that has reached its end state for fulfillment has been merged into release/3.0 and is ready for use. If you’re a developer who has done customization or integration with the order status, this is an area you’ll want to focus on and make sure you’re accounting for both ‘publish’ and ‘complete’ for a completed purchase.

View this issue on GitHub

Other improvements and bug fixes

  • A fatal error was being triggered when manually creating a new customer while manually creating a new order. (#6791)
  • Fixed an issue where the profile editor shortcode was not updating the customer address. (#7124)
  • Improved the reports endpoints registry to be more flexible as well as immutable. (#7120)
  • Fixed an issue causing refund orders not showing on the refunds tab. (#7088)

Upcoming changes (not yet merged)

There are a number of changes that we are currently in the process of testing and merging including the following (more details will be supplied once the issues are finalized and merged)

  • Improving extensibility of reporting APIs.
  • UI/UX improvements to the Bundle product selectors.
  • Fixing up order status counts in the Order List table.
  • View/Edit Order details improvements.
  • Order list table default ordering is being changed to date_created instead of ID.

Major updates yet to tackle

  • Improve the upgrade routines for stability – A host of improvements are in the works to make the upgrade routines more stable and accurate as well as fault tolerant.
  • Refund process – We are in the process of creating a new workflow for generating a refund, which will include some UI changes to make refunds as full-featured as possible.

So those are the major changes since our last update. Keep looking for these posts until we hit the release date in order to make sure your upgrade to Easy Digital Downloads 3.0 is as smooth as possible.

]]>
https://easydigitaldownloads.com/development/2019/01/28/easy-digital-downloads-3-0-update-january-28-1019/feed/ 1
Easy Digital Downloads 3.0 Update – January 14, 1019 https://easydigitaldownloads.com/development/2019/01/14/easy-digital-downloads-3-0-update-january-14-1019/ https://easydigitaldownloads.com/development/2019/01/14/easy-digital-downloads-3-0-update-january-14-1019/#comments Mon, 14 Jan 2019 21:00:45 +0000 https://easydigitaldownloads.com/development/?p=756

Continue reading →

]]>
Welcome back from the holidays, and as we stated before our holiday break we’re back with a bi-weekly Easy Digital Downloads 3.0 progress update. Over the holidays and last few weeks we’ve been working through to get some of the UI bugs fixed. Here are the highlights of the changes since our last update.

Improved AJAX responses for new AJAX actions

Easy Digital Downloads uses AJAX to make for a better user and administrative experience. They are collectively called “EDD Actions” when we use them via AJAX. In our pre-3.0 EDD Actions, we’ve always done our best to do as much error handling as we can. When presented with an error response we have always written the response to be -1. While this functions as a way for us to know that the AJAX response had an error, it doesn’t quite provide us with enough information to provide a better user experience to inform the user of an action that ends in error.

In 3.0, we’ve added some new EDD Actions, but these will respond with a full JSON response when they are presented with an error, instead of the -1, as with our existing actions. These new actions are all centered around the new ‘Add Order’ process. If all works as expected, we’ll investigate on making all our AJAX responses have full JSON responses, which should allow people customizing their EDD Shops to better serve their customers error messages when there is a problem.

View the issue on GitHub.

UI Fixes and improvements

A number of UI improvements and fixes were corrected, mostly centered around the administrative sections of Easy Digital Downloads. Here are some of those fixes:

  • Card icon was no longer showing on checkout when entering the card number (#7087)
  • Improved backwards compatibility of the ‘card’ view for extensions (#6773)
  • Improved reports compatibility on larger screens (#7080)
  • Updated tax settings to only show the rates subsection when taxes are enabled (#7109)

Status change for ‘completed’ orders

In the past, orders (previously called payments) were stored in the same table as Posts and Pages. Therefore, we made the decision to take a ‘completed’ order and mark it with a status of ‘publish’ in the database. On the front end, this was output as ‘Completed’, but all of the code and database records referenced ‘publish’ as the end state of an order that was in good standing. In Easy Digital Downloads 3.0 we’re changing this. Thanks to our new database tables we no longer feel the need to adhere to this status and have switched a ‘completed’ order to have a status of ‘complete’ in the database. This just brings our code and visual output into a more cohesive state, which makes Easy Digital Downloads easier to work with from a development perspective.

While not yet merged into the release/3.0 branch, the changes are code-complete and ready for testing. If you want to follow along, you can view this issue on GitHub.

Other improvements and bug fixes

  • Fixed an issue where pasting in a URL for a file download would still deliver the old file that had been uploaded using the File Upload Dialog. (#6713)
  • Improved the [downloads] shortcode to not fatal error when it is used on a single download page. (#6072)
  • Corrected inconsistencies in the new Order Adjustments section of the Add Order screen. (#7108)
  • Fixed a bug that caused a fatal error when creating a new customer while editing an existing order. (#7096)
]]>
https://easydigitaldownloads.com/development/2019/01/14/easy-digital-downloads-3-0-update-january-14-1019/feed/ 3
Easy Digital Downloads 3.0 Update – UI Changes, Introducing Webpack, and remaining focuses. https://easydigitaldownloads.com/development/2018/12/18/easy-digital-downloads-3-0-update-ui-changes-introducing-webpack-and-remaining-focuses/ https://easydigitaldownloads.com/development/2018/12/18/easy-digital-downloads-3-0-update-ui-changes-introducing-webpack-and-remaining-focuses/#comments Tue, 18 Dec 2018 15:00:32 +0000 https://easydigitaldownloads.com/development/?p=709 It’s been a while since we’ve given you an update on the progress of Easy Digital Downloads 3.0. While this update is taking longer than we expected, stability, performance, and backwards compatibility are driving our focus while in the final phases of development. We are down to the last remaining issues before we ship a beta, and felt it was time to give you a sneak peek of what’s to come. In the past we’ve talked about the major focuses and possible breaking changes that we needed to make to move forward.

All new reports

In one of our earlier updates we discussed the new Reports API. We’ve made some great progress on these APIs and have introduced a brand new Reports View for Easy Digital Downloads. It includes many of the same features you enjoyed before, with the added benefit of better filters, more in-depth reports for products and categories, improved gateway reports, relative data, and a new concept called ‘Tiles’.

Tiles are a away of displaying small amounts of information in your reports overview that give store owners a snapshot of metrics, and in some cases give relative data to the previous date range, in order to help store owners identify trends in their stores. Below are some screenshots of our new Reports views.

Preview of Reports Overview for Easy Digital Downloads 3.0 Preview of Product Overview Report for Easy Digital Downloads 3.0 Preview of Refunds Report for Easy Digital Downloads 3.0 Preview of Gateways Report for Easy Digital Downloads 3.0 Preview of Taxes Report for Easy Digital Downloads 3.0 Preview of File Downloads Report for Easy Digital Downloads 3.0 Preview of Discounts Report for Easy Digital Downloads 3.0 Preview of Customer Report for Easy Digital Downloads 3.0

 

Enhancements to the UI

We’ve made some minor enhancements to other user interfaces within Easy Digital Downloads 3.0. While mostly cosmetic, they should provide a much more consistent and functional experience. You’ll notice updates to our admin sidebar menu that make it easier to find what you are looking for, updates to the ‘card’ view for customers (and by proxy licenses, commissions, and other object management interfaces), and improved settings interfaces.

Preview of the Customer Management UI in Easy Digital Downloads 3.0

Introducing Webpack

With Easy Digital Downloads 3.0, we’re happy to be introducing Webpack to our development process. In the past, we’ve used Grunt to perform tasks like minifying our CSS and JavaScript, building out our translation files, and making our build for preparing to release new versions. Webpack is a more modern and flexible way to do this, that also gives us the ability to further isolate our JavaScript into much more manageable files during development. This means that features that are reliant on JavaScript will become easier to maintain and debug.

So what does this mean for developers who contribute to Easy Digital Downloads? For the most part, not much. We’re starting off still keeping up-to-date and compiled versions of our Assets (Javascript and CSS) in our major branches. These would be things like releases and the master branch. This means for the most part you can just clone Easy Digital Downloads from GitHub and go right on your way contributing. The only time you’ll need to interact with Webpack is if you are contributing CSS or JavaScript changes. A couple of quick notes about using Webpack during development.

  • If you have SCRIPT_DEBUG set to true, you’ll continue to use the full source versions (non-minified versions) of the assets.
  • Before you start editing CSS and JavaScript, be sure to run npm install so that all the proper dependencies are installed.
  • If you do plan to make any changes to the CSS or JavaScript, you’ll need to run npm run dev. This will start listening to the assets for changes and rebuild the minified sources as you make changes.

What is left?

We’re striving to complete the final touches on Easy Digital Downloads 3.0. We have a few things needed before we ship off the first public beta.

  • Finalize the View, Edit, and Refund Order experience — With the new APIs for orders and refunds will come some changes to the user interface around orders.
  • Continue to do extensive testing with our extensions — This will ensure that we don’t have any major issues on as we release these updates.
  • Keep you updated — We’re committing to publishing an update on the progress of Easy Digital Downloads 3.0 every 2 weeks from here on out. This will hopefully keep developers in the loop so they also can reduce the possibility of bugs once the release is live.
]]>
https://easydigitaldownloads.com/development/2018/12/18/easy-digital-downloads-3-0-update-ui-changes-introducing-webpack-and-remaining-focuses/feed/ 12