0

I'm having an issue with SilverStripe treating external URLs as relative links.

I have a DataObject:

class Artist extends DataObject {
  private static $db = array(
    'Title' => 'Varchar(255)',
    'Content' => 'HTMLText',
    'Website' => 'Varchar(255)',
  );
}

Artist websites are rendered via <a href="$Website" target="_blank">. The problem is that the URLs are being appended to the base URL of the website, so we end up with something like:

<a href="mysite.com/www.artistsite.com" target="_blank">

instead of the desired:

<a href="www.artistsite.com" target="_blank">

However, if $Website includes the protocol (http or https) then the link works as expected. So if $Website is http://www.artistsite.com then we get:

<a href="http://www.artistsite.com" target="_blank">

This site contains hundreds, and eventually thousands, of client-maintained artist records. Ideally the client would be able to paste in URLs without having to worry about appending http or https to each one.

Anyone have any ideas? It's the same issue as described on the SilverStripe forums but no solution has been posted.

This site on SilverStripe 3.6.

scrowler
  • 24,273
  • 9
  • 60
  • 92
JustinTBrown
  • 157
  • 1
  • 10
  • There are modules available for handling this problem, e.g. https://github.com/restruct/silverstripe-namedlinkfield for SS3.0+ and https://github.com/burnbright/silverstripe-externalurlfield for SS4. You basically need to validate the `Website` content and modify it before saving. – wmk Nov 21 '17 at 06:50
  • yeah, either `onBeforeWrite` to ensure the protocol is there, or a custom getter that adds the protocol if it doesn't exist… the former would be the better option performance-wise, but it'll alter the text in the textfield. – bummzack Nov 21 '17 at 07:58

2 Answers2

5

This isn't a SilverStripe issue directly.

Given a html document with the following:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<a href="google.com" target="_blank">test</a>
<a href="www.google.com" target="_blank">test</a>

</body>
</html>

All of them open as relative links to the site, not the external url.

See html - links without http protocol

To help the admin paste functional links is to add an onBeforeWrite to test does the url contain a valid protocol, and if it doesn't, add automatically http:// at least. Or use the modules what @wmk suggested in the comment that does that automatically.

Olli Tyynelä
  • 586
  • 3
  • 14
1

Since records have already been established and I didn't want to have to convert all the Website fields to a different field type, I opted for adding an onBeforeWrite as per @olli-tyynelä's and @bummzack's recommendation:

public function onBeforeWrite() {
  $url = $this->Website;
  if  ( $ret = parse_url($url) ) {

    if ( !isset($ret["scheme"]) ) {
      $url = "http://{$url}";
      $this->Website = $url;
      $this->write();
    }
  }
  parent::onBeforeWrite();
}

Thanks :)

JustinTBrown
  • 157
  • 1
  • 10