Reputation: 115
I am not that good with regex and stuff. I know how to change http://google.com and www.google.com into links. However, I want my script to get links around the following strings:
Hello. Have you visited [link goes here]google.com[/link goes here] today?
Hello. Have you visited [link goes here]www.google.com[/link goes here] today?
Hello. Have you visited [link goes here]http://google.com[/link goes here] today?
Hello. Have you visited [link goes here]https://google.com[/link goes here] today?
Of course, I would really like the expression to allow as many characters as possible. But for the first link to work, I can only think of one explanation (I don't want people to start writing text.text and it will become a link):
<?php
$tlds = array("com", "net", "org", "info", "no", "dk", "se");
foreach($tlds as $tld){
$string = preg_replace("something", "something", $string);
}
?>
Do any of you know what to do? :P
I want it to be similar to Autolinker.js, only in PHP: https://github.com/gregjacobs/Autolinker.js
Upvotes: 1
Views: 3147
Reputation: 98961
$template = <<< EOF
Hello. Have you visited google.com today?
Hello. Have you visited www.google.com today?
Hello. Have you visited http://google.com today?
Hello. Have you visited https://google.com today?
EOF;
$template = preg_replace_callback('/(?=(([\w\/\/:.]+)\.(?:com|net|org|info|no|dk|se)))\b(?:(?:https?|ftp|file):\/\/|(?:www\.|ftp\.)?)
(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*
(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$])/ix','my_callback',$template);
function my_callback($matches) {
//check it the link has the protocol if not adds it.
if (preg_match('/https?/ix', $matches[1])) {
$link = $matches[1];
return "<a href=\"$link\">$link</a>";
} else {
$link = $matches[1];
return "<a href=\"http://$link\">http://$link</a>";
}
}
echo $template;
Upvotes: 0
Reputation: 728
I just skimmed previous questions for a semi-decent regular expression to match domains and tweaked it a little - there are probably better out there if you keep looking.
<?php
$test = 'Hello. Have you visited google.com today?
Hello. Have you visited www.google.com today?
Hello. Have you visited http://google.com today?
Hello. Have you visited https://google.com today?';
$func = function ($match) {
$text = trim($match[0]);
$pieces = parse_url($text);
$scheme = array_key_exists('scheme', $pieces) ? $pieces['scheme'] : 'http';
$host = isset($pieces['host']) ? $pieces['host'] : $pieces['path'];
$link = sprintf('%s://%s', $scheme, $host);
return sprintf('<a href="%s">%s</a>', $link, $text);
};
echo preg_replace_callback('/((http[s]?:\/\/)?(?>[a-z\-0-9]{2,}\.){1,}[a-z]{2,8})(?:\s|\/)/m', $func, $test);
Output for me is as follows:
Hello. Have you visited <a href="http://google.com">google.com</a>today?
Hello. Have you visited <a href="http://www.google.com">www.google.com</a>today?
Hello. Have you visited <a href="http://google.com">http://google.com</a>today?
Hello. Have you visited <a href="https://google.com">https://google.com</a>today?
I hope this was what you were after.
(I don't want people to start writing text.text and it will become a link)
Agreed, that would be annoying :-) - you should probably unit test this method, once you have settled on your solution. Use PHPUnit to write a test, and define an array of test data for it using a data provider - it'll give you confidence that your solution is sound.
Upvotes: 1