Easy Digital Downloads 3.0 Development Update

Work has been underway for Easy Digital Downloads 3.0 since January 1 of this year. We’d like to take this opportunity to provide updates on how far we are in the development cycle, some of the bigger changes that are coming, and what’s left for us to do.

Before we proceed, it’s important to note that this version of Easy Digital Downloads will bring significant changes and it is highly advised that all developers read through these changes thoroughly. We’ve made every effort to ensure backwards compatibility throughout the entire codebase, but any change has the potential to break some custom code, and we want to make everything go as smoothly as we can for everyone.

Custom Database Tables

A significant aspect of EDD 3.0 is the migration to custom database tables, to allow for store data to be better structured and increase performance when querying for that data. Components like Discounts, Orders, Logs, Notes, and Customers will all no longer be custom post types in 3.0 and beyond.

Due to the large number of database tables being introduced, we invented a new set of core APIs to make interacting with them easy and familiar. We’ve built a query interface which follows similar architectural principles to that of WP_Query for each of the custom database tables, and their meta-data pairs. A hidden benefit of this new approach is that objects and queries now internally manage their own caches, bringing big performance gains for all users and store managers alike.

Throughout the codebase, we’ve labelled each of these core objects (that have custom database tables) to be called a “component”. All of our components are registered very early in the instantiation of EDD which ensures that the custom database tables (and any future upgrades to the schemas) are done as early as possible during bootstrap before any other utility methods occur on them. Each custom database table continues to be independently versioned, which allows future versions of EDD to iterate on single components without requiring an upgrade to all of them.

Each component consists of five attributes:

  • Schema – This class is in charge of maintaining the schema of the table, and everything else that follows is derived from this.
    • This class is used by the query class when performing input validation
    • The data in this class also specifies what queries are allowed on each database column (i.e. id__in, id__not_in)
    • We’ve hugged tightly to WordPress database table conventions for our schemas, so columns and queries will look familiar, and have ranges and boundaries like you’d find elsewhere in WordPress
  • Table – This class is in charge of creating and managing the database table itself, using the schema above.
    • These classes are mostly magic, and you will not need to interact with them
    • Table classes include their own upgrade methods between EDD versions, to keep themselves up-to-date
    • All tables in EDD 3.0 are per-site, though it’s possible to make global tables in multisite environments using more advanced configuration
  • Query – The query class is used to query each custom database table. Subclasses to this query are specifically designed to provide performance & reliability when querying our custom database tables.
    • All queries are cached with an MD5 hash of the parameters used
    • All objects are keyed by their unique ID
    • All meta is primed for all queried objects
    • Multiple cache-keys can be specified in custom schemas, to allow for speedy lookups on specific columns
    • A date_query parameter is available for datetime column types
  • Object – This class defines the shape of the component item.
    • Each core object has a corresponding class that the query class will construct for each row returned from the database
    • EDD_Discount and EDD_Customer have been modified to work with the new classes introduced, and backwards compatibility has been maintained for them
  • Meta (Optional) – This points to a class that will handle creation of a meta data table, if a core object requires one.
    • When meta is available, Query classes can use the meta_query parameter to JOIN between the two tables

The new tables that have been introduced are:

  • edd_discounts
  • edd_discountmeta
  • edd_logs
  • edd_logmeta
  • edd_logs_api_requests
  • edd_logs_file_downloads
  • edd_notes
  • edd_notemeta
  • edd_orders
  • edd_ordermeta
  • edd_order_items
  • edd_order_itemmeta
  • edd_order_adjustments
  • edd_order_adjustmentmeta

All of EDD’s data (except downloads) will live in one of the above tables. As part of EDD 3.0, we decided to rename “payments” to “orders”; semantically, an “order” is the record of items (products) & adjustments (taxes, fees, discounts) and a “payment” is the acknowledgement & confirmation of that order. We introduced multiple tables for orders as a way to provide more granular detail into every transaction. Our new database tables & schemas allow for easier & faster querying, which is pivotal for the new reporting tools that will be introduced.

Discounts, Logs, and Notes have been migrated to use the new custom database tables, and the existing API methods have all been modified to now store data in those tables. We have maintained 100% backwards compatibility with all existing methods. New methods have been introduced for all of the core objects in order to standardise naming conventions, and we have made every effort to maintain backwards compatibility across all of these components.

Backwards Compatibility

We have applied filters to WordPress queries which redirect meta queries to our query classes and fetch the correct data. We have also introduce a set of compatibility classes that allow calls to all of the deprecated APIs as per usual.

Currently in EDD, we have a public class variable that  points to an instance of EDD_DB_Customers. This class has been deprecated and has been replaced with the component classes as described above, however, any calls made to EDD()->customers are still dispatched to the new methods and return the same data as previously. The same applies for EDD_Customer_Query where we have made this class a subclass of EDD\Database\Queries\Customer and converted any legacy arguments in the constructor and made pertinent provisions for any old methods.

We have written a complete set of unit tests to test all of the legacy methods and ensure they are still usable and have not broken due to the big awesome changes introduced.

The last part of the custom database tables involves orders, which we are currently working on. Orders have a complex data structure with a dynamic set of metadata for each order depending on the configuration of a store (e.g. taxes, fees, discounts) so we are spending more time to ensure we get it right.

Reports API

Another major aspect of EDD 3.0 is the complete rebuild of all of the reporting tools that are currently available.

So far we’ve written a lot of new APIs to abstract the creation and handling of all the reports. The new APIs will allow developers to create custom reports at ease, and many of our add-ons will leverage this going forward.

New terminology has been introduced: chart, table, and tile. Tile endpoints handle all of the logic needed to display labels, comparison labels, a variety of tile value “types”, get registered as meta boxes, loading values via Ajax, etc. Table endpoints handle all of the logic needed to retrieve data for and display a list table, pagination, sorting, all of the stuff that goes along with tables. Chart endpoints handle all of the logic needed to set values needed for ChartJS, load data via a batch process as necessary, and display.

A Registry superclass has been introduced for which two subclasses go off and register the reports and endpoints. An API has also been built which creates and renders all reports be that in the form of tables, or charts.

The progress of the new reporting tools can be seen here.  The new tools are nearing completion which will allow for registering reports, tabs, tiles, and generating graphs.

This has been a major development effort that will completely reimagine how reports work for EDD 3.0.

Other Big Changes

  • Introduction of the EDD namespace for which all new classes follow. Existing classes have remained and have been aliased to ensure full backwards compatibility.
  • Introduction of new components and new query classes to interface with the custom database tables.
  • Introduction of notes for discount codes.
  • Changes to the edd_customers table schema which removes the notes and payment_ids columns. The notes will be migrated to wp_notes and payment IDs no longer need a column because there will be a one-to-many relationship from edd_customers to edd_orders.
  • Significant amount of unit tests introduced to ensure the new APIs work as expected and that existing APIs work alongside the new ones.

What’s Left

We are currently working the migration of all orders to the custom database tables and we are progressing with our new reporting tools. We are also smoothing out the “component” API so our add-ons can more easily leverage it from outside of EDD core.

We do suggest you take some time to take a look at the changes to the codebase. We will be making further announcements on this blog to keep everyone updated with progress.

If you wish to follow or contribute to the development of 3.0, you can find the GitHub milestone here.

6 responses... add one

Excellent! I’m excited about:
“All queries are cached with an MD5 hash of the parameters used”.
I have been a fanatic of database query optimisation and leveraging REDIS to store fragments so this is fantastic news!

Introduction of the EDD namespace for which all new classes follow. Existing classes have remained and have been aliased to ensure full backwards compatibility.

Does this means you are dropping support for PHP 5.2?

What will be minimum required PHP version for EDD 3.0?

I appreciate your team’s conscientiousness. It gives me confidence about upgrading. I’m looking forward to the performance and reporting improvements.

Leave a Reply

Your email address will not be published. Required fields are marked *