-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create additional download permissions on product save if needed #28521
Conversation
When a simple product with downloads gets converted into a variable product all the existing download permissions for past orders become invalid. This commit adds an extra verification procedure to the product save code: - Get all the existing download permissions for the product and all the children (variations) - For each download permission for the parent product, if there's a variation that offers the same file for download (same file URL) AND an equivalent download permission doesn't exist (equivalent means same file URL, same order id and same user id), then create it. Additionally, a new WC_Customer_Download_Data_Store::create_from_data method is added.
Also, move all the new code from the 'WC_Product_Data_Store_CPT' class to a new separate 'DownloadPermissionsAdjuster' class.
…load_permissions Also replace direct invocations of functions with usages of the LegacyProxy whenever needed, and code style ajustments.
The DownloadPermissionsAdjuster class hooks to adjust_download_permissions from within its init method. However this method is executed only if the class is resolved, otherwise the hooks doesn't get attached and then the scheduled action is not serviced. To solve this, the class is resolved from WooCommerce::init_hooks. This requires a change in DownloadPermissionsAdjuster::init to use wc_get_container()->get( LegacyProxy::class )->get_instance_of instead of WC()->get_instance_of, since WC() can't be used from WooCommerce::construct (which invokes init_hooks).
Was there no way to separate the product from the order once it was ordered? What about just storing the file URL within the order meta? This way you wouldn't need to re-generate permissions. |
Hi @roykho. Thanks for your suggestion, but unless I'm missing/misunderstanding something that wouldn't help: Downloadable files are ultimately tied to products, not (or not only) orders. If a product ceases to exist or ceases to have the downloadable file then the associated download permissions are no longer valid. That's why the So if we were to store the file id (probably that and not the URL, as in A seconday concern is that we are planning to move towards dedicated tables, so storing yet more stuff in post meta should be avoided whenever possible. Again, unless there's something I'm missing. |
What you're saying is currently how it works and I understand that however I believe that is not the best approach. What I am suggesting is change how WC works in terms of what is ordered and the products. Ideally, after an order is made, I can delete the product completely and the order should still have all the information necessary to fulfill the order obligation. That should include the original price of the product, taxes and any downloadable files attached to that product...etc.
We would not need the product ID because the download permission table has order product id/order id already so it knows which permissions are tied to the order. As I said in the comment of the original issue, I believe to make it work correctly will be a heavy lift. Your PR can be used as an interim however if you feel strongly about getting this in. |
That makes sense but it's also a little bit tricky. I'm thinking of a situation where I want to completely discontinue a software product I used to sell because it's too old and maybe it even has security issues; on one hand if a customer has purchased something it seems logical to give him access to the download "at eternum", on the other hand it may be better to remove access (because you provided an alternative or the product is really useless by now). Although this is already kind of contemplated in the "access expires" field. Anyway, I agree with what you say next:
Yep. This would need some extended discussion.
I think that if this works as I intend it to work, it's indeed a good solution until we can figure out a better mechanism for download permissions in general. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested well, good job! Since this is a pretty big PR, I just skim through the parts and make sure they made sense. I just left some small comments.
* Assumes that all the keys in the passed data are valid. | ||
* | ||
* @param array $data Data to create the permission for. | ||
* @returns int The database id of the created permission, or false if the permission creation failed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be @return
here. Without the s
return $adjusted_date; | ||
} | ||
|
||
throw new Exception( "I don't know how to get a date from a " . is_object( $date ) ? get_class( $date ) : gettype( $date ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this not need to be translatable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding was that since it's an exception message it should rarely be displayed and if it is, the viewer will probably be a developer. But anyway, I see that our convention in the code is to translate the exception messages so I'll do the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks!
All Submissions:
Changes proposed in this Pull Request:
When a simple product with downloads gets converted into a variable product all the existing download permissions for past orders become invalid. This commit adds an extra verification procedure to the product save code:
Additionally, a new
WC_Customer_Download_Data_Store::create_from_data
method is added.Closes #26475.
How to test the changes in this Pull Request:
master
.file1
,file2
andfile3
.file1
and the other onefile2
(use the same file URLs, display names for the files can be different).adjust_download_permissions
. Wait until it runs, or run it yourself.file1
andfile2
again, but not tofile3
.wp_woocommerce_downloadable_product_permissions
table in the database, there should be no duplicate entries.Other information:
Changelog entry