Problem/Motivation
If a donation item is not present on the order, then DonationItemPaneBase chokes. I don't know whether or not this would be an issue in the provided donation checkout flow, but it's likely that you could encounter a situation where the donation pane is present on a custom checkout flow with an optional donation for an order without a donation item.
This may be related to https://www.drupal.org/project/commerce_donation_flow/issues/3239498. Don't know whether you want to roll these together or not. I think the issue of operating on a null/missing donationItem could be fairly omnipresent given the initial intended use case of the module.
Proposed resolution
Attaching a very simple patch that just returns an empty array if a donation item isn't present, which essentially just results in no markup being rendered for the pane.
Issue fork commerce_donation_flow-3243886
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- issue-3243886-1.1.x
changes, plain diff MR !12
- 3243886-error-call-to
changes, plain diff MR !9
Comments
Comment #2
mrweiner commentedEDIT: Whoops, may not be applying
Comment #3
mrweiner commentedThis one doesn't reorder the use statements.
Comment #4
mrweiner commentedNot my day, ha. This is an error on bool not on null. Guess I forgot how to read.
Comment #5
mrweiner commentedAlright, just a simple
!check instead of issetComment #6
fathershawnLet's figure out the general plan to access and update Donation OrderItems in #3243454: DonationItemPaneBase::submitPaneForm needs to update its internal state to reflect up to date donation order item and then circle back here.
Comment #7
fathershawnComment #9
mrweiner commented@FatherSean I think this updated approach makes sense. I just made some small changes to simplify the logic in initDonationItem(). What do you think? Also, do you think this bit is needed anymore?
If the there are no items on the order then I think the while loop will handle that on its own by creating one.
Comment #10
mrweiner commentedAnd actually a question about submitPaneForm().
I don't know if we necessarily want to throw an error. If the orderItem was deleted/unset before this method fires, wouldn't it be valid to just not save the item? The exception might problematic because I don't think it could be caught by any logic other than an extending pane. If somebody is using the default pane, they don't really have a way to catch the exception. Actually, if this is a problem here, then the LengthException I added in validatePaneForm could be problematic as well.
Comment #11
fathershawn@mrweiner your feedback over all and most recently in #9 prompted me to take another step back and refactor some more. This latest iteration removes storing the donation item and allows these panes, I hope, to live in any checkout flow.
As to #10, that submission method is in the base plugin class, which cannot be a pane on it's own. Since the purpose of these panes is to edit the donation order item, it seems valid to me to normally expect the order item to persist to the submit method so it can be saved. If an extending pane is removing it on purpose, this allows that extending pane to handle the issue.
Comment #12
fathershawnIf this works for your use case, I'll add another pane that simply provides a configurable checkbox element, which when checked will add a donation order item to the order on submission. When placed in an earlier step than our donation panes, such a pane would essentially enable our panes as optional panes if a donation was added.
Comment #13
mrweiner commentedOh right, I forgot that this was a Base class so yes, those exceptions do make sense. I'll need to do some testing to see how the latest changes work with our flow, but they all look like they should work out fine.
One thing I notice is that a null
$donationItemcould be passed intobuildDonationItem()and I'm not sure if there's handling for that. Might need to add a guard tobuildDonationItem()to ensure we aren't trying to call methods on aNULLitem.Re #12, not sure I'm totally understanding what you mean. That said, at the moment we are using the default checkout flow with the donation pane on the "Order Information" step, which is the first pane that a customer encounters unless they are anonymous and hit the Login step. In the case of a logged in user, I don't know that they would have the chance to encounter this proposed new pane before hitting the step with the donation pane. I'm happy to test things out, though.
Comment #14
mrweiner commentedOh just one other thought. It's certainly preference so could go either way, but I wonder if
getDonationItem()might be a better name thandonationItem()now that it's acting as a getter method instead of a property?Comment #15
mrweiner commentedOh for #12, if the idea is to make the donation optional, we are actually handling that on our own by adding a checkbox to the donation pane itself to keep or remove a donation and apply the user's desired pricing. When the order is created, we are using
NewOrder::addDonationItem()to create a $0 donation item and just hiding it in the order summary. Then when they submit that pane and continue to review the order, the donation item price is updated or the item removed based on their selections.It would probably be more graceful to not need to add the $0 donation item on order creation. I don't think this was possible with the current alpha/dev, but might be possible with all of these updates.
Comment #16
fathershawnI believe this is fixed in 1.1.x
Comment #17
fathershawnComment #18
fathershawnI should have read #3243454: DonationItemPaneBase::submitPaneForm needs to update its internal state to reflect up to date donation order item before closing - having a second look against 1.1.x
Comment #20
fathershawnMoved this work to 1.1.x, added a patch to capture the MR for use in composer.json
Comment #22
fathershawnAll tests passing - ready to merge
Comment #24
fathershawnComment #25
fathershawn