Problem/Motivation
A LinkItem field is empty if its value is an empty string or NULL. If a NULL value is passed to any of the Link field's constraint validator classes, then the following deprecation warning is produced when they call LinkItemInterface::getUrl().
Deprecated function: preg_match(): Passing null to parameter #2 ($subject) of type string is deprecated in Drupal\Core\Url::fromUri() (line 281 of core/lib/Drupal/Core/Url.php).
Steps to reproduce
See steps in https://www.drupal.org/project/drupal/issues/3348390#comment-15228424 as long as that patch is not applied/committed.
- Install the workspaces module
- Add a link field to the page content type, cardinality unlimited, standards for other settings
- Create a content of type page, adding a link with values and clicking the "Add another item" button not populating the 2nd link item
- Save the node and re-open the edit form
OR
- Go to admin/config/development/logging, select 'All' and save.
- Add a link field with Unlimited cardinality to article content type.
- Create a new article, add one link and save
- Add a form after to article edit form
- Load the node and call
validate()method.[$entity = $form_state->getFormObject()->getEntity(); $entity->validate();] - Now try to edit the previously created node.

Proposed resolution
The constraint validators are heavily dependent on the passed $value being a LinkItemInterface object. Check that the value is an instance of the interface and that it is not empty before validating. Remove the existing if (isset($value)) {...} conditions because they're basically pointless since an object will always pass that check.
Remaining tasks
User interface changes
Introduced terminology
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|
Issue fork drupal-3387013
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:
Comments
Comment #2
s_leu commentedHere a basic patch to illustrate the idea of how to change this. The added code should probably be moved into a base class if this approach makes sense at all.
Comment #3
smustgrave commentedThank you for reporting.
Wonder if we could get a test-only patch showing the issue.
Comment #9
akhil babuComment #10
akhil babuComment #11
akhil babuI was able to recreate this issue, but only with the help of custom code.
The errors appear only when validate() is called on node object when we are in the node edit form. For example
will not trigger any errors when the node is viewd. But will trigger error when edit form is loaded.
When the edit form is loaded after adding a link item to an unlimited cardinality link field, Drupal automatically appends a new link widget below the existing one to add a second link item. Somehow, this second item is also validated when the node is validated from the edit form, and this triggers the NULL warning. This won't happen when the node is loaded from any place other than the node edit form. So, maybe the logic in the validate() method needs to be fixed.
I have created a test to show the bug.
Comment #12
akhil babuComment #13
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #18
dcam commentedI converted the patch in #2 to an MR and added Unit tests.
Comment #19
smustgrave commentedRan test-only change here https://git.drupalcode.org/issue/drupal-3387013/-/jobs/6473897 and got 4 failures that line up with the 4 new tests, create to make a unit test!
Refactoring of the constraints to check instance of LinkItemInterface makes sense.
No feedback.
Comment #20
dcam commentedI wasn't happy with the validators returning if the input wasn't a
LinkItemInterface.So I looked up the Symfony validator docs. They show anUnexpectedValueExceptionbeing thrown in instances just like what we're dealing with. So I'm taking that as a best practice.I played around with the idea of putting this early validation in a base class, but it wasn't working out cleanly. So I scrapped the idea.
Comment #21
dcam commentedSince I made changes I've decided to postpone this on #3077149: Duplicate inline form errors in external Link widgets instead of the other way around like we've been doing. The other issue has a more complete
LinkTypeConstraintValidatorTesttest class. I'd also consider the other issue to be the more serious bug since it can happen simply by enabling Inline Form Errors whereas this one seems like an edge case potentially requiring custom code.Comment #22
dcam commentedThis is unblocked and needs a rebase to integrate the new test that was added by both this issue and the blocker.
Comment #23
dcam commentedComment #24
smustgrave commentedThis may need a manual rebase. Least gitlab is throwing a fit.
Comment #25
dcam commentedI have no idea what was going on with it. The "Update fork" button worked on the branch page. It's reporting as being mergeable now.
Comment #26
smustgrave commentedFeedback for this one appears to be addressed.
Tested following the steps and able to reproduce, test-only has already been ran before the rebase.
Fixes do address the problem and seems to be copied around (which is fine). May be cool eventually to have some trait that can be shared but out of scope of this issue.
LGTM
Comment #27
catchNeeds a rebase, likely due to #3093118: Move link title validation from LinkWidget into a constraint
Comment #28
dcam commentedThe "Update Fork" button on the branch page worked to rebase it.
Comment #29
catchIt looks like the new validator in that issue might also need an isEmpty() check?
Comment #30
dcam commentedI don't think so. This fixes bugs where
getUrl()is called without first checking if there is a URL. The other issue's new validator doesn't callgetUrl()because it's about checking the title subfield.Comment #33
catchOh that makes sense, couldn't see an actual issue in the latest commit but was thinking about short-circuiting other logic, not loads to short-circuit though.
Committed/pushed to 11.x and cherry-picked to 11.3.x, thanks!