Problem/Motivation

This was forked from #2573635: Url::fromUri() should accept protocol-relative URLs, which is where this very same thing was originally being solved. It was descoped to only add API support.

Link field only accepts external URLs with "http://" or "https://". It should also support protocol-relative URLs e.g "//example.com". Otherwise we're limiting URLs for no good reason, which is simply a Drupalism. See #2573635-44: Url::fromUri() should accept protocol-relative URLs for a longer rationale.

Proposed resolution

Allow any valid URL to be linked.

Remaining tasks

  • Discuss how to handle the HTML5 validation, which by default does not accept URLs without a protocol.
  • Discuss the need of the double slash at the beginning of protocol relative URLs, accepting "example.com" as a valid external URL.

User interface changes

None.

API changes

None.

Data model changes

None.

Comments

Wim Leers created an issue. See original summary.

wim leers’s picture

Title: Link field should accept protocol-relative URLs » [PP-1] Link field should accept protocol-relative URLs
Status: Active » Postponed

This is blocked on #2573635: Url::fromUri() should accept protocol-relative URLs, which will add API support, so that this issue/patch will indeed only have to change the Link field implementation, and nothing else.

wim leers’s picture

Issue summary: View changes
mac_weber’s picture

I really would like to see "example.com" as a valid external URL, yet the implementation with the validation we have today for internal URLs would not be so easy. We need to discuss the validation strategy for that.

mac_weber’s picture

Status: Postponed » Active
mac_weber’s picture

Title: [PP-1] Link field should accept protocol-relative URLs » Link field should accept protocol-relative URLs
Status: Active » Needs review
StatusFileSize
new3.56 KB

Patch to accept URLs starting with //. I still think we should accept "example.com".
I did not change the help messages, as in the original issue some people said it could be confusing for end users.
Add credit for dawehner, lluvigne.

dawehner’s picture

This works for me. Do you think we need something on top of that?

wim leers’s picture

Works for me too.

  1. +++ b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
    @@ -179,6 +179,11 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
    +      if ($url->isExternal() && (strpos($url->getUri(), '//') == 0)) {
    

    Let's change this to strict equality. (strpos() not finding a match will return FALSE, which will also match:

    $ drush ev 'var_dump(FALSE == 0);'
    bool(true)
    
  2. +++ b/core/modules/link/src/Plugin/Validation/Constraint/LinkExternalProtocolsConstraintValidator.php
    @@ -40,9 +40,13 @@ public function validate($value, Constraint $constraint) {
    +       $not_protocol_relative = strpos($url->getUri(), '//') != 0;
    

    Again, strict equality please.

mac_weber’s picture

@Wim Leers I thought that being more verbose would be better for code readability. I also improved the code at file LinkExternalProtocolsConstraintValidator.php to be easier to understand at the first look.

@dawehner what I think that needs to be done on top of hat is accept example.com as a valid URL. The problem on that is about the autocomplete and validation. Right now it would be validated as a content title. We need to discuss how we would handle this.

For example, I do not think it would be a good idea to ping an external host in order to validate it. On the other hand, if it is not validated as a content title are we going to just validate it with something like this UrlHelper::isValid() and check if it uses an allowed protocol? How about the scenario of a content title being a valid external URL?

mac_weber’s picture

Sorry, I sent the wrong patch file while doing some tests and it was missing the strict operator.

  1. +++ b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
    @@ -179,6 +179,11 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
    +      if ($url->isExternal() && (strpos($url->getUri(), '//'))) {
    +        $link_title = ltrim($link_title, '//');
    +      }
    

    In fact, we do not need this 'if', as the ltrim() would work fine anyway and I cannot think about another case which a URL could come with leading '//'. Shall we keep it for readability?

  2. +++ b/core/modules/link/src/Plugin/Validation/Constraint/LinkExternalProtocolsConstraintValidator.php
    @@ -39,9 +39,19 @@ public function validate($value, Constraint $constraint) {
    +        // Protocol-relative URLs start with '//'.
    +        $not_protocol_relative = strpos($url->getUri(), '//');
    

    It was interesting to see the tests passing even when it returns 'FALSE' here, but I think we should not worry about it.

Attached patch with the strict operator.

rootwork’s picture

@Mac_Weber I'm just an interested bystander, but it seems to me that given that issues you raised with example.com, that might be worth being a separate parallel or follow-up issue to this one. Given that supporting protocol-relative URLs is semi-controversial (based on the previous issue) it might be worth splitting these two ideas to see if one generates more consensus than the other.

I get the interest in addressing both of these at once given we're talking about updating the same functions here, so this is just a suggestion.

dawehner’s picture

@dawehner what I think that needs to be done on top of hat is accept example.com as a valid URL. The problem on that is about the autocomplete and validation. Right now it would be validated as a content title. We need to discuss how we would handle this.

This is something we should explore in an additinional issue as @rootwork said.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mac_weber’s picture

Rerolled.

Pavan B S’s picture

Made a minor change of short array syntax,for the #15 patch.

dawehner’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests
index b0928b0..34d20cc 100644
--- a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php

--- a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
+++ b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php

+++ b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
@@ -179,6 +179,11 @@ public function viewElements(FieldItemListInterface $items, $langcode) {

@@ -179,6 +179,11 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
       $url = $this->buildUrl($item);
       $link_title = $url->toString();
 
+      // If the external URL starts with '//', trim it.
+      if ($url->isExternal() && (strpos($url->getUri(), '//') === 0)) {
+        $link_title = ltrim($link_title, '//');
+      }
+

We don't have tests for this change.

mac_weber’s picture

@dawehner test was in the patch file. I'm sending it separated.

mac_weber’s picture

Status: Needs work » Needs review

I had forgotten to change the status.

Status: Needs review » Needs work

The last submitted patch, 18: link_field_protocol_relative_ui-2744729-18--test-only.patch, failed testing.

mac_weber’s picture

Status: Needs work » Needs review

Setting the correct status, as the patch on #16 passed the tests.

dawehner’s picture

Setting the correct status, as the patch on #16 passed the tests.

The test is just for the validator, but not for the link formatter.

mac_weber’s picture

Status: Needs review » Needs work

Needs tests as said in #22 and also depending of the field config it displays a form error or it is saved but never displayed in the node view.

mac_weber’s picture

Issue summary: View changes

@dawehner @Wim Leers just a side note: if we really want this feature we should change or get rid of the HTML5 validation.

Related issue about HTML5 validation modifier: #2861316: Display meaningful HTML5 validation error message

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

shenzhuxi’s picture

I just tried today and found that "//example.com" can be saved now.
Did we keep this issue open because we still need to discuss accepting "example.com" without double slash as a valid external URL?

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

liquidcms’s picture

yes, also don't see mention of where accepting example.com was forked to a new issue - so is it still being handled under this one?

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

liquidcms’s picture

Can someone please point me to the issue discussing the fix that allows example.com to be entered?

liquidcms’s picture

For those stumbling upon this trying to figure out why Drupal doesn't have a proper Link field; I posted a fix here: https://drupal.stackexchange.com/questions/300471/how-to-automatically-a...

vakulrai’s picture

Status: Needs work » Needs review

@liquidcms This has been discussed here: https://www.drupal.org/project/drupal/issues/1473220 with no solution to handle HTML5 validation.

The HTML5 url validation is not allowing to enter a url that has a pattern "//example.com" and unless it passes the html5 validation the patch won't work here.

my solution would be to change the type of field from "url" to "text" and add some pattern validation in case the url in external.

liquidcms’s picture

thanks @vakulrai.. yes, my solution (on existing link fields) likely only works as we have applied the patch which disabled html5 form validation (as it doesn't really work very well).

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

joachim’s picture

Status: Needs review » Needs work

Setting to NW because a test is needed.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

nwom’s picture

Is #2195983: Support scheme-relative URLs a duplicate issue?

Edit: Nevermind, it appears that tackles the base component. Hopefully it is still helpful to link here.

rootwork’s picture

Yes, let's add #2195983: Support scheme-relative URLs to the related list.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

liquidcms’s picture

liquidcms’s picture

Yogesh Sahu’s picture

Status: Needs work » Needs review
StatusFileSize
new3.12 KB

Re-rolling patch for 10.1.x.

Status: Needs review » Needs work

The last submitted patch, 47: 2744729-47.patch, failed testing. View results

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

dcam’s picture

There's another duplicate that was filed as a bug report due to protocol-relative URLs being accepted input that were validated as internal URLs, but resulting in malformed links when rendered: #2889658: Handle protocol-relative URLs in LinkWidget.

dcam’s picture

Status: Needs work » Closed (duplicate)

I'm closing this in favor of #2889658: Handle protocol-relative URLs in LinkWidget since this issue evolved into being a bug. The changes in that issue are nearly identical in function. Credit has been granted for this issue.

Now that this issue is closed, please review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, please credit people who helped resolve this issue.