4

I was creating a script and it includes a posting script but I want users to directly copy a link from anywhere else and when they post it the link text should automatically convert the link to link-element (<a>).

So for example this:

Ask this on http://stackoverflow.com now

to become

Ask this on <a href="http://stackoverflow.com">http://stackoverflow.com</a> now

I have tried the str_replace() function but it wasn't the solution.

Can anyone tell me a solution to this?

kapa
  • 77,694
  • 21
  • 158
  • 175

2 Answers2

4

There are several solutions out there for this, most of them being poorly written and incomplete. In this situation I would advise to use an already existing solution of one of the big frameworks, there is no need to reinvent the wheel.

For example, this article on Zenverse describes the way WordPress handles this.

Let me add the snippet here for further reference:

function _make_url_clickable_cb($matches) {
    $ret = '';
    $url = $matches[2];

    if ( empty($url) )
        return $matches[0];
    // removed trailing [.,;:] from URL
    if ( in_array(substr($url, -1), array('.', ',', ';', ':')) === true ) {
        $ret = substr($url, -1);
        $url = substr($url, 0, strlen($url)-1);
    }
    return $matches[1] . "<a href=\"$url\" rel=\"nofollow\">$url</a>" . $ret;
}

function _make_web_ftp_clickable_cb($matches) {
    $ret = '';
    $dest = $matches[2];
    $dest = 'http://' . $dest;

    if ( empty($dest) )
        return $matches[0];
    // removed trailing [,;:] from URL
    if ( in_array(substr($dest, -1), array('.', ',', ';', ':')) === true ) {
        $ret = substr($dest, -1);
        $dest = substr($dest, 0, strlen($dest)-1);
    }
    return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>" . $ret;
}

function _make_email_clickable_cb($matches) {
    $email = $matches[2] . '@' . $matches[3];
    return $matches[1] . "<a href=\"mailto:$email\">$email</a>";
}

function make_clickable($ret) {
    $ret = ' ' . $ret;
    // in testing, using arrays here was found to be faster
    $ret = preg_replace_callback('#([\s>])([\w]+?://[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]*)#is', '_make_url_clickable_cb', $ret);
    $ret = preg_replace_callback('#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]*)#is', '_make_web_ftp_clickable_cb', $ret);
    $ret = preg_replace_callback('#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret);

    // this one is not in an array because we need it to run last, for cleanup of accidental links within links
    $ret = preg_replace("#(<a( [^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i", "$1$3</a>", $ret);
    $ret = trim($ret);
    return $ret;
}

An example usage as written in the linked article:

$string = 'I have some texts here and also links such as http://www.youtube.com , www.haha.com and lol@example.com. They are ready to be replaced.';

echo make_clickable($string);
kapa
  • 77,694
  • 21
  • 158
  • 175
1

What you need is first to find substrings that are links. For that, you could use regexps. Then, you need to add html tags around the link. preg_replace should be your friend.

For example (simplified example):

$linkedtext = preg_replace ( '@\bhttp://([a-zA-Z0-9.%/]+)\b@', '<a href="http://$1">$1</a>', $text)

For better url matching regex, see Regex to match URL

Community
  • 1
  • 1
Charles Brunet
  • 21,797
  • 24
  • 83
  • 124