easy-digital-downloads
easy-digital-downloads copied to clipboard
Allowing easier/future-proof checkout customisations
I think our /includes/checkout/template.php
file can be improved so it's easier to customize certain aspects of checkout without having to re-hook entire functions.
@cklosowski puts it nicely here (https://github.com/easydigitaldownloads/easy-digital-downloads/issues/6943#issuecomment-423292703)
a lot of people do custom checkout pages for some of the smallest changes, and if we can avoid those by making things like this easier, then 👍 from me.
Use-case
As an example, Themedd v1.1 uses Bootstrap 4 which provides consistent form styling I can use anywhere in the theme. The only way to utilize the existing styling at EDD checkout is to copy each function in template.php
and add the required class names to form elements. I also modified the HTML to my liking to be consistent with the rest of theme. Since every form element needed custom class names it resulted in a large amount of code to maintain.
EDD was subsequently updated to fix a couple of issues with the template.php
file (one related to nonces) and although I updated Themedd to match, I ultimately decided to drop all the functions in case there was anything super important related to checkout that needed to be updated in the future.
Proposal
EDD has a helper class for outputting common HTML elements (class-edd-html-elements.php
) so I think a good start would be to make the checkout utilize the relevant methods.
Some quick example
The select()
method could be used for:
- billing country
- card expiry month
- card expiry year
- card state
The checkbox()
method could be used for
agree to terms
agree to privacy policy
The text()
method could be used for
- any input field
etc
In addition, several key aspects of each method could be filterable so it's easy to change them without re-hooking any functions in template.php. The most notable being the class names of any field type. This would allow me to add the specific class names I need, without ever having to worry about future core updates breaking the theme (if I had chosen to keep all the modified functions).
@easydigitaldownloads/core-team I think this and #6943 should switch milestones and semi-merge ideas. Implementing #6943 will mean any extension that isn't updated before 3.0 that adds fields to the checkout will have not reflect that setting. I would imagine this will impact a lot of payment gateways.
Instead 3.0 can be used as a "best-practices" example on how to upgrade a lot of the hard-coded HTML elements used to build the purchase form in extensions.
This change also has breaking template changes while the "having the descriptions be a key value array to match up with the input name" suggestion #6943 can technically be implemented to default fields without the need for theme updates.
My proposal for this would be to include the field registry aspect of #6943 alongside of using EDD's helper HTML functions. This would result in the default email field looking something like:
<?php
echo EDD()->html->text( array(
'id' => 'edd_email',
'name' => 'edd_email',
'label' => edd_get_purchase_form_field_label( 'edd_email' ),
'desc' => edd_get_purchase_form_field_desc( 'edd_email' ),
'required' => edd_field_is_required( 'edd_email' ),
) );
?>
It requires a few changes to the helper functions (such as an option to show the required indicator) but overall the backwards compatible changes would be relatively minimal.
Once the default fields and as many extensions as possible are updated to use this method then implementing a setting that can globally and easily affect all checkout fields makes more sense.
Proof of concept for the customer info fields: https://github.com/easydigitaldownloads/easy-digital-downloads/compare/release/3.0...test/checkout-modularity
After some discussion in Slack discussion it's clear that we can ditch the "registry" -- feed the strings directly to the helper methods.
Beyond that it's a matter of the best way of supplying the fields to the purchase form.
Implementation of previous discussion: https://github.com/easydigitaldownloads/easy-digital-downloads/compare/release/3.0...test/checkout-modularity
Feels much better. Going to work on converting the other fields.
Latest commits add support for credit card fields and billing address.
I found the HTML generator methods to be inconsistent so I tried to remedy that but introducing a new method that allows creating the markup for the standard wrapped form element that includes a label and description. The text()
method supported this originally, but things like select()
only output the actual <select>
element.
I ended up doing similar with some of our settings functions. Things like checkboxes didn’t allow for description paragraphs underneath them, so a new function was invented. It’s OK. I’ll check it over. Thanks!
I did not feel this needed a separate issue (since it was related), but the way the fields are outputted isn't exactly ideal and makes the checkout page huge which will definitely be reducing conversions and creating checkout friction.
For example, bootstrap suggests this type of layout:
https://getbootstrap.com/docs/4.0/examples/checkout/
At the minute no wrappers are provided around elements that should be (really) be on a single row like the first and last name fields. Other fields like "state" and "country" should be wrapped.
I'm going to remove this from 3.1. Currently we're working on our first implementation of a checkout block, and I want to get that field tested in the live environments before we start refactoring things futher.