Problem/Motivation

Drupal_url not support external links.
Used drupal_link twig function to render link url,When I enter the external link, the page reports an error.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Issue fork twig_tweak-3223186

Command icon 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

ZhiLing Chen created an issue. See original summary.

cherrol’s picture

Title: drupal_url not support external links » You are not allowed to specify an external URL together with internal:/
Issue summary: View changes
cherrol’s picture

tammycao’s picture

StatusFileSize
new745 bytes
smustgrave’s picture

Status: Active » Needs review
StatusFileSize
new791 bytes

Took a different approach to it.

The patch in #4 still rendered external links as internal. Example https://ddev-drupal/https://www.google.com

Not sure if this is the intended use of this function. Says on https://www.drupal.org/docs/contributed-modules/twig-tweak-2x/cheat-shee... it should be internal

but will let the maintainer decide that.

chi’s picture

What's the use case for this? Why do you pass ready to print URL to drupal_url()?

chi’s picture

Status: Needs review » Postponed (maintainer needs more info)
silverham’s picture

Hi @Chi,

In built Drupal url/link in twig has limitations. such as ['#url'].setOption('fragment', html_id) due to twig sandbox policy. So instead I can use twig tweak to recreate the link of the url in Entity's link field. However if the link is external the code crashes :-(

e.g.
Assuming a link with text "products" and I want html with custom icon / text prefix. <a><span class="prefix">For more information, go to </span><span class="text">products</span></span class="icon"><span></span></a>

So field twig could be (if external only):

{% for key, item in items %}
  {% set html_id = 'my-anchor' %}

  {% set link_title %}
    {% verbatim  %}
      <span class="prefix">{{ 'For more information, go to'|t }}</span><span class="text">{{ item.content['#title'] }}</span><span class="icon" aria-hidden="true"></span>
    {% endverbatim %}
  {% endset %}

  {% set item = item|merge({
    'content':
     item.content|merge({
      '#title': {
        '#type': 'inline_template',
        '#template': link_title,
        '#context': {'item' : item},
      },
      '#url': drupal_url(
        item.content['#url'].getUri(),
        item.content['#url'].getOptions()|merge({
          'fragment': html_id|clean_id,
        })
      )
    })
  }) %}
  {% set items = ( {(key): item} + items ) %}
{% endfor %}
silverham’s picture

Status: Postponed (maintainer needs more info) » Needs review
chi’s picture

Status: Needs review » Active

@silverham, I think such cases should not be handled in Twig.

Though you could just append the anchor to the generated URL.

{% for item in items %}
  <div>
    <a href="{{ item.content['#url'] }}#my-anchor">
      <span class="prefix">{{ 'For more information, go to'|t }}</span>
      <span class="text">{{ item.content['#title'] }}</span>
      <span class="icon" aria-hidden="true"></span>
    </a>
  </div>
{% endfor %}
silverham’s picture

Hi @Chi That is very true. Good point!
But we can not be sure that the user will input a hashtag there already so it must be removed initially, if it exists, at least haha.

<a href="{{ item.content['#url']|render|preg_replace('/#.*$/', '') ~ '#my-anchor' }}">[...]</a>

prashant.c’s picture

Status: Active » Needs work

The solution provided to check the external path
if (UrlHelper::isExternal($user_input)) { in the patch provided by #5 seems fine but shouldn't this condition come after the

     if (!in_array($user_input[0], ['/', '#', '?'])) {
       $user_input = '/' . $user_input;
     }

Apart from this, the function doc block should also be modified because currently it says

/**
   * Generates a URL from an internal path.
   *
   * @param string $user_input
   *   User input for a link or path.
   * @param array $options
   *   (optional) An array of options.
   * @param bool $check_access
   *   (optional) Indicates that access check is required.
   *
   * @return \Drupal\Core\Url|null
   *   A new Url object or null if the URL is not accessible.
   *
   * @see \Drupal\Core\Url::fromUserInput()
   */
pradhumanjain2311’s picture

Status: Needs work » Needs review
StatusFileSize
new1.09 KB
new914 bytes

I made changes as per comment #12.
Please review.

simon georges’s picture

Version: 3.1.2 » 3.x-dev
Category: Support request » Bug report

The previous patch cannot work, considering it will add a "/" on external urls before testing them for externality, so the patch in #5 is the correct one, and still applies cleanly on current version.

simon georges’s picture

(in our case, we wanted to add a custom class on the link to be able to style it specifically)

prashant.c’s picture

Created MR from the patch provided by #5. Could not find any issues while testing locally.

Thanks!

  • Chi committed ce34d528 on 3.x
    Issue #3223186: Add a test for external URL
    
chi’s picture

Status: Needs review » Fixed

Thank you.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

cherrol’s picture