A challenging WordPress project that I recently worked on required that a WooCommerce no-cost virtual, downloadable product be created each time a PDF was uploaded into a certain section on the screen of certain custom post type.
- A history of the downloads of a PDF product was to be kept for years.
- Only PDFs uploaded in the PDF Product Group section (a section created as part of the solution for this business requirement) were to be converted into WooCommerce PDF products. (PDFs could be uploaded and linked to inside the regular WordPress post content area. Those PDFs were to be handled by WordPress as it normally does, and were NOT to be added as WooCommerce products.)
- The client had multiple custom post types. Some allowed PDF product uploads and others did not.
- On the custom post types that allowed PDF product uploads, a PDF was not required to be uploaded.
- Only one PDF product could be associated with a post at any given time.
- The reason the PDFs were added to WooCommerce as products was so that the client could track which people downloaded which PDF products. (I was not asked for a recommendation on how I would implement this; I was asked to make it happen using WooCommerce as the manager.)
What I did was:
- Make a list of the minimum fields that WooCommerce creates when a virtual, downloadable product is created
- Confirm how WooCommerce handles no-cost products
- Create a custom field group, the PDF Product Group, that contains the Title of the PDF to be used for the Product title, an upload file field (for uploading the PDF), a small description field to be used as the PDF product’s description.
- Added an ‘action’ function in functions.php that runs on ‘save_post’. The function checks whether the post is one of the custom post types that can have a PDF. Then it checks whether a PDF has been successfully uploaded, followed by verifying that a title and a description have been added.
- Once all of those validations have been passed, a WooCommerce virtual, downloadable product is created using those fields and others (defined in the first step above) that are set to default values (like the product category which changes according to the custom post type). In all, 29 postmeta records are added.
- Finally, the one-to-one relationship between this post and the PDF product that was just created is recorded by adding another postmeta record. This effectively defines the post as the ‘parent’ of the product.
Adding the product for the first time (processing above) was the easy part. Deleting the product was the second easiest.
Remember that the PDF product is related to the ‘original‘ post. That original post has a unique identifier, the post ID. When a WordPress post is edited, a new post is created with its own unique ID (the revision) and the original post’s ID is added to the ‘post_parent’ field in the revision’s record, so, I had to be careful about which post ID I was referencing in the PHP programming: the revision’s post ID, the parent’s post ID, the PDF product’s post ID, or one of the postmeta record’s post ID.
Automatically deleting the WooCommerce PDF product
Since this client was tracking who downloaded which PDFs, the PDF products were not deleted. Instead, they were marked as inactive so that the PDF free products would not display as active downloads on any of the pages – and – the download history was preserved for reporting purposes.
The delete process works like this:
- Check to see if one of those postmeta ‘parent-child’ records exists for the ‘parent’ post. (By business requirement, there can be only one…if there is any.)
- Check whether there is a value in the PDF product custom file upload field of the current post.
- If there is no product in the PDF product custom field of the revision post, use the WooCommerce product post ID in the parent-child record of the revision’s parent to retrieve the product information and mark it as inactive.
- If there is a product in the PDF Product custom field of the current post, then maybe the records needed to be updated. (see next section)
Updating the WooCommerce PDF product
The toughest part was trying to decipher whether the PDF had been modified and re-uploaded, and, if so, was it uploaded with the same name or a different one? When updating WooCommerce downloadable products directly, WooCommerce keeps track and knows which version to serve for download. WooCommerce can even send a notice to users who downloaded the previous version that there is a new version available. Updating a WooCommerce downloadable product from outside WooCommerce upped the level of complexity.
One thought was to check the most recent PDF name against the name of the PDF originally uploaded. While this final piece was being coded and unit tested, the program manager decided to change course. The WooCommerce-as-the-manager approach was abandoned. Before that happened, all the other code was unit and system tested, and working – as was the ability to track who downloaded what.
Limited Checkout Fields for Free PDF Downloads
Since the client wanted to know who downloaded which PDF, it was necessary for the person downloading to be logged in.
- If the person downloading did not already have an account at the website, an account needed to be created.
- If they were downloading only the FREE PDFs, it was not necessary to fill in the multiple checkout screens that WooCommerce normally presents. The WooCommerce Checkout for Digital Goods plugin was used to capture minimal contact information and create a WooCommerce account for them.
- If there were pay-for products also in the cart, the purchaser would experience the normal, multi-screen WooCommerce checkout process (if they did not already have an account).
So, what seemed like a simple requirement “use WooCommerce to track who downloads the FREE PDFs” became quite challenging when adding and maintaining WooCommerce records outside of the WooCommerce Products module.