Skip to content

Instantly share code, notes, and snippets.

@jasny

jasny/linkify.php

Last active Oct 22, 2020
Embed
What would you like to do?
PHP function to turn all URLs in clickable links
<?php
/**
* Turn all URLs in clickable links.
*
* @param string $value
* @param array $protocols http/https, ftp, mail, twitter
* @param array $attributes
* @return string
*/
public function linkify($value, $protocols = array('http', 'mail'), array $attributes = array())
{
// Link attributes
$attr = '';
foreach ($attributes as $key => $val) {
$attr .= ' ' . $key . '="' . htmlentities($val) . '"';
}
$links = array();
// Extract existing links and tags
$value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);
// Extract text links for each protocol
foreach ((array)$protocols as $protocol) {
switch ($protocol) {
case 'http':
case 'https': $value = preg_replace_callback('~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { if ($match[1]) $protocol = $match[1]; $link = $match[2] ?: $match[3]; return '<' . array_push($links, "<a $attr href=\"$protocol://$link\">$link</a>") . '>'; }, $value); break;
case 'mail': $value = preg_replace_callback('~([^\s<]+?@[^\s<]+?\.[^\s<]+)(?<![\.,:])~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"mailto:{$match[1]}\">{$match[1]}</a>") . '>'; }, $value); break;
case 'twitter': $value = preg_replace_callback('~(?<!\w)[@#](\w++)~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"https://twitter.com/" . ($match[0][0] == '@' ? '' : 'search/%23') . $match[1] . "\">{$match[0]}</a>") . '>'; }, $value); break;
default: $value = preg_replace_callback('~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { return '<' . array_push($links, "<a $attr href=\"$protocol://{$match[1]}\">{$match[1]}</a>") . '>'; }, $value); break;
}
}
// Insert all link
return preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) { return $links[$match[1] - 1]; }, $value);
}
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
@jasny

This comment has been minimized.

Copy link
Owner Author

@jasny jasny commented Jun 28, 2015

Turning links like www.example.com and http://twitter.com into clickable links. Sounds like an easy task, right? We’ll there are a few problems that might arise, especially if the text is already HTML formatted.

This function first takes out all potential dangers, by extracting links and tags and replacing them with a placeholder. It than extracts all URLs and replaces them with a placeholder, storing the full HTML link. At the end it replaces all placeholders with the links and tags.

@Hackmastr

This comment has been minimized.

Copy link

@Hackmastr Hackmastr commented Aug 27, 2015

Amazing function! Thanks a ton! I was having a headache trying to make clickable text.

@cferdinandi

This comment has been minimized.

Copy link

@cferdinandi cferdinandi commented Sep 10, 2015

@jasny Will this detect (and skip) urls that are image sources? Example: <img src="http://someurl.com">

@davidgorges

This comment has been minimized.

Copy link

@davidgorges davidgorges commented Sep 10, 2015

Very helpful, thank you!
Quick note: the phpDoc comment has an additional parameter $mode that does not exist in the function.

@acoustika

This comment has been minimized.

Copy link

@acoustika acoustika commented Sep 28, 2015

Hmmm, trying to make this work. But isn't Attr being overwritten in each iterattion so I can only have ONE attribute? og how is it supposed to be input if I wanna have both target="_blank" and rel="nofollow" in my links?

@fabiandev

This comment has been minimized.

Copy link

@fabiandev fabiandev commented Mar 1, 2016

@acoustika I think it may just have been a typo.
Use .= instead of = in the for loop to support multiple attributes:

// Link attributes
$attr = '';
foreach ($attributes as $key => $val) {
    $attr .= ' ' . $key . '="' . htmlentities($val) . '"';
}
@doctorconceptual

This comment has been minimized.

Copy link

@doctorconceptual doctorconceptual commented Oct 12, 2016

this is doing incorrect linking of email addresses with dots.

@acarlson101

This comment has been minimized.

Copy link

@acarlson101 acarlson101 commented Dec 24, 2016

Hello jasny,

This code is very helpful. Is it MIT licensed for open source use?

@will83

This comment has been minimized.

Copy link

@will83 will83 commented Jun 14, 2017

I have problem with accented characters on links. The output of the API is ok, but after linkify(), all my accented characters looks like �

@mhm9002

This comment has been minimized.

Copy link

@mhm9002 mhm9002 commented Nov 20, 2017

You're wonderful!

@willemijns

This comment has been minimized.

Copy link

@willemijns willemijns commented Jan 30, 2018

Hey folks,

What is the input variable ?
How to place the output in anorther variable ?

@umarleadz

This comment has been minimized.

Copy link

@umarleadz umarleadz commented Feb 20, 2018

You did it exactly what I need thank you so much.

have a blessing day

@phasornc

This comment has been minimized.

Copy link

@phasornc phasornc commented Jun 20, 2018

If the URL is in parentheses (www.example.com) this code will include the trailing parenthesis in the URL giving you this (www.example.com)

@papanipapi

This comment has been minimized.

Copy link

@papanipapi papanipapi commented Nov 8, 2018

Thank you. It really works.

@mynukeviet

This comment has been minimized.

Copy link

@mynukeviet mynukeviet commented Feb 13, 2019

@jasny Will this detect (and skip) urls that are image sources? Example: <img src="http://someurl.com">

Me too :)

@bradycharron

This comment has been minimized.

Copy link

@bradycharron bradycharron commented Mar 20, 2019

Hello jasny,

This code is very helpful. Is it MIT licensed for open source use?

I am also curious about the licensing for this code.

@AryanKumar

This comment has been minimized.

Copy link

@AryanKumar AryanKumar commented May 11, 2019

Well, it`s a mind-boggling function and very useful. But I face issues here please anyone can suggest http://prntscr.com/nn9bv9.

In case: mailto I am getting any number along with URL like this <49>aryan4983@gmail.com. ScreenCast:- http://prntscr.com/nn9bv9

@AryanKumar

This comment has been minimized.

Copy link

@AryanKumar AryanKumar commented May 11, 2019

write like this:-
aryan4983@gmail.com

Do not prepend any text in mail. If do so it works fine. Well, I think it appends index number of an array

@piep14

This comment has been minimized.

Copy link

@piep14 piep14 commented May 31, 2019

@breakermind

Allow display images and youtube video:
CSS class for links .htmllink and images .htmlimg

public function linkify($showimg = 1, $value, $protocols = array('http', 'mail', 'https'), array $attributes = array('target' => '_blank'))
{       
    // Link attributes
    $attr = '';
    foreach ($attributes as $key => $val) {
        $attr = ' ' . $key . '="' . htmlentities($val) . '"';
    }
    
    $links = array();
    
    // Extract existing links and tags
    $value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);
    
    // Extract text links for each protocol
    foreach ((array)$protocols as $protocol) {
        switch ($protocol) {
            case 'http':
            case 'https':   $value = preg_replace_callback('~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i', 
                function ($match) use ($protocol, &$links, $attr, $showimg) { 
                    if ($match[1]){
                        $protocol = $match[1]; $link = $match[2] ?: $match[3]; 
                        // Youtube
                        if($showimg == 1){                                  
                            if(strpos($link, 'youtube.com')>=0 || strpos($link, 'youtu.be')>=0){                                  
                                $link = '<iframe width="100%" height="315" src="https://www.youtube.com/embed/'.end(explode('=', $link)).'?rel=0&showinfo=0&color=orange&iv_load_policy=3" frameborder="0" allowfullscreen></iframe>';
                                return '<' . array_push($links, $link) . '></a>';
                            }
                            if(strpos($link, '.png')>0 || strpos($link, '.jpg')>0 || strpos($link, '.jpeg')>0 || strpos($link, '.gif')>0 || strpos($link, '.bmp')>0){
                                return '<' . array_push($links, "<a $attr href=\"$protocol://$link\" class=\"htmllink\"><img src=\"$protocol://$link\" class=\"htmlimg\">") . '></a>';
                            }
                        }                           
                        return '<' . array_push($links, "<a $attr href=\"$protocol://$link\" class=\"htmllink\">$link</a>") . '>';                          
                    }                           
            }, $value); break;
            case 'mail':    $value = preg_replace_callback('~([^\s<]+?@[^\s<]+?\.[^\s<]+)(?<![\.,:])~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"mailto:{$match[1]}\" class=\"htmllink\">{$match[1]}</a>") . '>'; }, $value); break;
            case 'twitter': $value = preg_replace_callback('~(?<!\w)[@#](\w++)~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"https://twitter.com/" . ($match[0][0] == '@' ? '' : 'search/%23') . $match[1]  . "\" class=\"htmllink\">{$match[0]}</a>") . '>'; }, $value); break;
            default:        $value = preg_replace_callback('~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { return '<' . array_push($links, "<a $attr href=\"$protocol://{$match[1]}\" class=\"htmllink\">{$match[1]}</a>") . '>'; }, $value); break;
        }
    }
    
    // Insert all link
    return preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) { return $links[$match[1] - 1]; }, $value);
}

I have an error with this code ^^

Only variables should be passed by reference

On this line :

$link = '<iframe width="100%" height="315" src="https://www.youtube.com/embed/'.end(explode('=', $link)).'?rel=0&showinfo=0&color=orange&iv_load_policy=3" frameborder="0" allowfullscreen></iframe>';

My call :

echo TextHelper::linkify(1, 'un lien youtube : https://www.youtube.com/embed/sJeB24OLQis et un lien : https://www.brico.fr/');

Maybe is important, the function "linkify" is static.

public static function linkify($showimg = 1, $value, array $protocols = ['http', 'mail', 'https'], array $attributes = array('target' => '_blank'))

Thank you.

@piep14

This comment has been minimized.

Copy link

@piep14 piep14 commented Jun 3, 2019

The function does not convert multiple types of links?

Example:

a youtube link: https://www.youtube.com/embed/sJeB24OLQis and a link: https://www.brico.fr/

It sends me 2 iframes Youtube which does not make sense to me.

@habibieamrullah

This comment has been minimized.

Copy link

@habibieamrullah habibieamrullah commented Nov 25, 2019

I think I'm the only dummy guy here, I don't even know how to call the "linkify" method.. is it linkify($string) ? or what?

@mhenke64

This comment has been minimized.

Copy link

@mhenke64 mhenke64 commented May 23, 2020

If the URL is in parentheses (www.example.com) this code will include the trailing parenthesis in the URL giving you this (www.example.com)

I have a similar problem. When an exclamation mark appears after the url, it ads the exclamation mark to the link.

@vstelmakh

This comment has been minimized.

Copy link

@vstelmakh vstelmakh commented Jul 29, 2020

have a similar problem. When an exclamation mark appears after the url, it ads the exclamation mark to the link.

@mhenke64 check out Url highlight library, it handles this and much more cases

@montrealks

This comment has been minimized.

Copy link

@montrealks montrealks commented Oct 7, 2020

Is it possible to have a variant whereby the www part of the URL is optional?

@vstelmakh

This comment has been minimized.

Copy link

@vstelmakh vstelmakh commented Oct 22, 2020

Solution from @MoovFun

Working sample:

<?php
function Linkify(string $value, int $img = 1, int $video = 1, array $protocols = array('http', 'mail', 'twitter', 'https'), array $attributes = array('target' => '_blank'), $video_height = 400)
{
	$attr = "";
	foreach ($attributes as $key => $val) {
		$attr .= ' ' . $key . '="' . htmlentities($val) . '"';
	}
	$links = array();
	$value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);
	foreach ((array)$protocols as $protocol) {
		switch ($protocol) {
			case 'http':
			case 'https':   $value = preg_replace_callback('~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i',
				function ($match) use ($protocol, &$links, $attr, $img, $video, $video_height) {
					if ($match[1]){
						$protocol = $match[1]; $link = $match[2] ?: $match[3];
						if($video) {
							if(strpos($link, 'youtube.com') !== false || strpos($link, 'youtu.be') !== false){
								$exp = explode('=', $link);
								$ht = '<iframe width="100%" height="'.$video_height.'" src="https://www.youtube.com/embed/'.end($exp).'?rel=0&showinfo=0&color=orange&iv_load_policy=3" frameborder="0" allowfullscreen></iframe>';
								return '<' . array_push($links, $ht) . '></a>';
							}
							if(strpos($link, 'vimeo.com') !== false){
								$exp = explode('/', $link);
								$ht = '<iframe width="100%" height="'.$video_height.'" src="https://player.vimeo.com/video/'.end($exp).'" frameborder="0" allowfullscreen></iframe>';
								return '<' . array_push($links, $ht) . '></a>';
							}
						}
						if($img) {
							if(strpos($link, '.png') !== false || strpos($link, '.jpg') !== false || strpos($link, '.jpeg') !== false || strpos($link, '.gif') !== false || strpos($link, '.bmp') !== false || strpos($link, '.webp') !== false){
								return '<' . array_push($links, "<a $attr href=\"$protocol://$link\" class=\"htmllink\"><img src=\"$protocol://$link\" class=\"htmlimg\">") . '></a>';
							}
						}
						return '<' . array_push($links, "<a $attr href=\"$protocol://$link\" class=\"htmllink\">$link</a>") . '>';
					}
			}, $value); break;
			case 'mail':    $value = preg_replace_callback('~([^\s<]+?@[^\s<]+?\.[^\s<]+)(?<![\.,:])~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"mailto:{$match[1]}\" class=\"htmllink\">{$match[1]}</a>") . '>'; }, $value); break;
			case 'twitter': $value = preg_replace_callback('~(?<!\w)[@#]([\w\._]+)~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"https://twitter.com/" . ($match[0][0] == '@' ? '' : 'search/%23') . $match[1]  . "\" class=\"htmllink\">{$match[0]}</a>") . '>'; }, $value); break;
			default:        $value = preg_replace_callback('~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { return '<' . array_push($links, "<a $attr href=\"$protocol://{$match[1]}\" class=\"htmllink\">{$match[1]}</a>") . '>'; }, $value); break;
		}
	}
	return preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) { return $links[$match[1] - 1]; }, $value);
}

use it

<?php
echo Linkify('Twitter @twitter Email boomboom@super.mail Youtube https://www.youtube.com/watch?v=1BYrHIBs6ro Vimeo https://vimeo.com/282462734 Url http://google.com Image https://www.google.pl/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png Have a nice day hohoho!!!');

Be aware, this is not working properly with urls enclosed in brackets or quotes and punctuation.

Examples:

@vstelmakh

This comment has been minimized.

Copy link

@vstelmakh vstelmakh commented Oct 22, 2020

New solution from @MoovFun

Working sample:

function Linkify(string $value, int $img = 1, int $video = 1, array $protocols = array('http', 'mail', 'twitter', 'https'), array $attributes = array('target' => '_blank'), $video_height = 400)
{
	$attr = "";
	foreach ($attributes as $key => $val) {
		$attr .= ' ' . $key . '="' . htmlentities($val) . '"';
	}
	$links = array();
	$value = str_replace('(', '( ', $value);
	$value = str_replace(')', ' )', $value);
	$value = str_replace('"', '" ', $value);
	$value = str_replace('"', ' "', $value);
	$value = str_replace('!', ' !', $value);
	$value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);
	foreach ((array)$protocols as $protocol) {
		switch ($protocol) {
			case 'http':
			case 'https':
				$value = preg_replace_callback('~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i',
				function ($match) use ($protocol, &$links, $attr, $img, $video, $video_height) {
					if ($match[1]){
						$protocol = $match[1]; $link = $match[2] ?: $match[3];
						$link = str_replace([')','!','"'],'',$link);

						if($video) {
							if(strpos($link, 'youtube.com') !== false || strpos($link, 'youtu.be') !== false){
								$exp = explode('=', $link);
								$ht = '<iframe width="100%" height="'.$video_height.'" src="https://www.youtube.com/embed/'.end($exp).'?rel=0&showinfo=0&color=orange&iv_load_policy=3" frameborder="0" allowfullscreen></iframe>';
								return '<' . array_push($links, $ht) . '></a>';
							}
							if(strpos($link, 'vimeo.com') !== false){
								$exp = explode('/', $link);
								$ht = '<iframe width="100%" height="'.$video_height.'" src="https://player.vimeo.com/video/'.end($exp).'" frameborder="0" allowfullscreen></iframe>';
								return '<' . array_push($links, $ht) . '></a>';
							}
						}
						if($img) {
							if(strpos($link, '.png') !== false || strpos($link, '.jpg') !== false || strpos($link, '.jpeg') !== false || strpos($link, '.gif') !== false || strpos($link, '.bmp') !== false || strpos($link, '.webp') !== false){
								return '<' . array_push($links, "<a $attr href=\"$protocol://$link\" class=\"htmllink\"><img src=\"$protocol://$link\" class=\"htmlimg\">") . '></a>';
							}
						}
						return '<' . array_push($links, "<a $attr href=\"$protocol://$link\" class=\"htmllink\">$link</a>") . '>';
					}
			}, $value); break;
			case 'mail':    $value = preg_replace_callback('~([^\s<]+?@[^\s<]+?\.[^\s<]+)(?<![\.,:])~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"mailto:{$match[1]}\" class=\"htmllink\">{$match[1]}</a>") . '>'; }, $value); break;
			case 'twitter': $value = preg_replace_callback('~(?<!\w)[@#]([\w\._]+)~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"https://twitter.com/" . ($match[0][0] == '@' ? '' : 'search/%23') . $match[1]  . "\" class=\"htmllink\">{$match[0]}</a>") . '>'; }, $value); break;
			default:        $value = preg_replace_callback('~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { return '<' . array_push($links, "<a $attr href=\"$protocol://{$match[1]}\" class=\"htmllink\">{$match[1]}</a>") . '>'; }, $value); break;
		}
	}
	$s = preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) { return $links[$match[1] - 1]; }, $value);
	$s = str_replace('( ', '(', $s);
	$s = str_replace(' )', ')', $s);
	$s = str_replace('" ', '"', $s);
	$s = str_replace(' "', '"', $s);
	return str_replace(' !', '!', $s);
}

Use it

<?php
$str = '
Brackets: (http://id.iot.com)
Quotes: "http://id.iot.com"
Exclamation: http://id.iot.com!
Youtube https://www.youtube.com/watch?v=tpKCqp9CALQ
Vimeo https://vimeo.com/331653781
Url http://google.com
Image https://www.google.pl/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png
Twitter @twitter 
Email boom@super.mail!
<h2> Have a nice for all !!!</h2>
';

echo Linkify($str);

Be aware, this is still not working properly with brackets, quotes and punctuation.

Examples:

@MoovFun

This comment has been minimized.

Copy link

@MoovFun MoovFun commented Oct 22, 2020

Sample:

<?php
function Linkify(string $value, int $img = 1, int $video = 1, array $protocols = array('http', 'mail', 'twitter', 'https'), array $attributes = array('target' => '_blank'), $video_height = 400)
{
	$links = array();
	$value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);
	foreach ((array)$protocols as $protocol) {
		switch ($protocol) {
			case 'http':
			case 'https':
				$value = preg_replace_callback('~(?:\(?(https?)://([^\s\!]+)(?<![?,:.\"]))~i',
				function ($match) use ($protocol, &$links, $attr, $img, $video, $video_height) {
					if ($match[1]){

						$protocol = $match[1];
						$str = $match[0];
						if($str[0] === '(') { $match[2] = substr($match[2],0,-1); }
						$link = $match[2] ?: $match[3];
						if($video) {
							if(strpos($link, 'youtube.com') !== false || strpos($link, 'youtu.be') !== false){
								$exp = explode('=', $link);
								$ht = '<iframe width="100%" height="'.$video_height.'" src="https://www.youtube.com/embed/'.end($exp).'?rel=0&showinfo=0&color=orange&iv_load_policy=3" frameborder="0" allowfullscreen></iframe>';
								return '<' . array_push($links, $ht) . '></a>';
							}
							if(strpos($link, 'vimeo.com') !== false){
								$exp = explode('/', $link);
								$ht = '<iframe width="100%" height="'.$video_height.'" src="https://player.vimeo.com/video/'.end($exp).'" frameborder="0" allowfullscreen></iframe>';
								return '<' . array_push($links, $ht) . '></a>';
							}
						}
						if($img) {
							if(strpos($link, '.png') !== false || strpos($link, '.jpg') !== false || strpos($link, '.jpeg') !== false || strpos($link, '.gif') !== false || strpos($link, '.bmp') !== false || strpos($link, '.webp') !== false){
								return '<' . array_push($links, "<a $attr href=\"$protocol://$link\" class=\"htmllink\"><img src=\"$protocol://$link\" class=\"htmlimg\">") . '></a>';
							}
						}

						if($str[0] === '(') {
							return '<' . array_push($links, "(<a $attr href=\"$protocol://$link\" class=\"htmllink\">$link</a>)") . '>';
						} else {
							return '<' . array_push($links, "<a $attr href=\"$protocol://$link\" class=\"htmllink\">$link</a>") . '>';
						}
					}
			}, $value); break;
			case 'mail':    $value = preg_replace_callback('~([^\s<]+?@[^\s<]+?\.[^\s<]+)(?<![\.,:])~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"mailto:{$match[1]}\" class=\"htmllink\">{$match[1]}</a>") . '>'; }, $value); break;
			case 'twitter': $value = preg_replace_callback('~(?<!\w)[@#]([\w\._]+)~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"https://twitter.com/" . ($match[0][0] == '@' ? '' : 'search/%23') . $match[1]  . "\" class=\"htmllink\">{$match[0]}</a>") . '>'; }, $value); break;
			default:        $value = preg_replace_callback('~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { return '<' . array_push($links, "<a $attr href=\"$protocol://{$match[1]}\" class=\"htmllink\">{$match[1]}</a>") . '>'; }, $value); break;
		}
	}
	return preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) { return $links[$match[1] - 1]; }, $value);
}

Use it:

<?php
$str = '
<a href="https://boom.doom"> Html LINK </a>
Youtube https://www.youtube.com/watch?v=tpKCqp9CALQ
Vimeo https://vimeo.com/331653781
Image https://www.google.pl/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png
Url http://google.com:
Input: Quotes "http://example.com"
Exlamation: http://example.com!
Exlamation: http://example.com?
Exlamation: http://example.com:
Exlamation: http://example.com.
Exlamation: http://example.com,
Brackets (http://example.com)
Brackets https://en.wikipedia.org/wiki/Chaquicocha_(mountain)
Twitter @twitter
Email boom@super.mail
<h2> html text </h2>
<style>.htmllink { font-weight: 900; color: #ff2255; padding: 10px; }</style>
';

echo Linkify((string) $str);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.