Problem/Motivation
In a certain unusual circumstance. attempting to display a form results in " Call to a member function getTokenUrl() on null in Drupal\webform\WebformMessageManager->get() ". This results in a PHP error.
The problem results when a webform allows multiple drafts. The user has one draft created (saved but not submitted) for a given source entity, such as a particular node. Then the user attempts to display the webform without a source entity. Webform attempts to display the "one draft" message, but the first webform cannot be loaded because it's attached to a different (non-null) source entity.
Internally:
Webform::getSubmissionForm() creates the webform, which, through the submission storage, calls WebformSubmission::preCreate(), which gets the current source entity. Which in this case is null.
WebformSubmissionForm::buildForm() calls WebformSubmissionForm::displayMessages() to build the render array of any messages for the form.
Because this is a GET request and multiple drafts are enabled, displayMessages calls WebformSubmissionStorage::getTotal() with a null source entity. However, it does not set the check_source_entity option to true. This is the bug.
WebformSubmissionStorage()::getTotal() calls WebformSubmissionStorage::addQueryConditions() to limit the query count to the relevant submissions, including the null source entity. The null source entity is ignored in the absence of the check_source_entityoption and return 1, rather than the correct 0.
This causes displayMessages to attempt to display DRAFT_PENDING_SINGLE message, which generates the PHP error when it cannot create the href for the link to the submission (because it can't load the draft for the null source entity, because there isn't one).
Steps to reproduce
Create a webform with a single text element, set for drafts and multiple drafts.
Attach the webform to a node.
Save one draft from the node so that the node is the source entity.
Then view the form from the admin interface where the source entity will be null.
Proposed resolution
Change line 1017 of display messages to:
&& ($previous_draft_total = $this->getStorage()->getTotal($webform, $this->sourceEntity, $this->currentUser(), ['in_draft' => TRUE, 'check_source_entity' => TRUE]))
I have manually tested the above fix. I apologize for not offering a patch. I'm will be away from Drupal for the next week or so. I can offer one when I return, change is small.
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | webform-draft_count-3245016.3.patch | 1.24 KB | danchadwick |
Comments
Comment #2
danchadwick commentedPatch as above.
Comment #3
danchadwick commentedPatch #2 contained an unintended change.
Comment #4
jrockowitz commentedComment #5
jrockowitz commented