SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    SitePoint Member
    Join Date
    Jan 2007
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Converting URLs to Links

    Hi there,

    Unless it was buried in search result 539, I didn't find some good, complete code to convert a plain URL to a live link -- e.g., for posts on a message board -- that also clips long URLs so that they don't require horizontal scrolling. I came up with a working function (with a little help from php.net), but it causes a problem if there are two links in the same message.

    If the URL is long (over 60 characters in the example below) it takes the first 25 characters and the last 25 characters and puts an ellipsis between them and displays that, while using the full URL for the link, of course.

    However, if there are two or more URLs, then the clipped text displayed for all URLs is the text of the first URL. For example:

    This is a link to http://www.example.COM and this is a link to http://www.example.NET
    If these URLs were long enough to be clipped, they would display thus:

    This is a link to http://www.e...e.COM and this is a link to http://www.e...e.COM
    Note that the second link will correctly link to http://www.example.NET, but it will display .COM.

    I understand why it's doing this, but I can't figure out a way to make it work properly. Anyone have any suggestions? Thanks.


    Craig


    PHP Code:
    function hyperlink($message)

        {

        
    // If the message contains the string "<a" at all, then don't process it:
        
    if (eregi("<a"$message))
            {
            return (
    $message);
            }

        
    // Match protocol://address/path/
        
    if (ereg("([a-zA-Z]+://([-]*[.]?[a-zA-Z0-9_/-?&%])*)($| |<br />)"$message$regs))
            {
            
    $url_http $regs[1];
            }
        
    $url_length strlen($url_http);
        if (
    $url_length 60)
            {
            
    $url_http substr($url_http025) . "..." substr($url_http, -25);
            }

        
    $message ereg_replace("([a-zA-Z]+://([-]*[.]?[a-zA-Z0-9_/-?&%])*)($| |<br />)""<a href=\"\\1\" target=\"_new\" title=\"External link.\">$url_http</a>\\3"$message);

        return (
    $message);

        } 
    Last edited by craig0612; Mar 19, 2007 at 05:59. Reason: Fix placeholder.

  2. #2
    SitePoint Wizard
    Join Date
    Mar 2007
    Posts
    1,211
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Some message boards use UBC code. The site will have examples of it.

  3. #3
    SitePoint Member
    Join Date
    Jan 2007
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by rcj662 View Post
    Some message boards use UBC code. The site will have examples of it.
    Hi there,

    Thanks for your reply. Not sure what "UBC code" is, unless it's something like BB code. However, I think you missed my point. I'm not trying to post a message on a message board as a user, I am actually writing the code for the message board.


    Craig

  4. #4
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  5. #5
    SitePoint Enthusiast
    Join Date
    Jun 2006
    Posts
    87
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The above post is the way to go, but just to clarify: There is nothing in your posted code that would translate .net to .com
    Soren Beck Jensen

    http://www.automaticbacklinks.com - Free link exchange network
    http://www.notwebdesign.com - Joomla web design in Spain

  6. #6
    SitePoint Member
    Join Date
    Jan 2007
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by CT Internet View Post
    The above post is the way to go, but just to clarify: There is nothing in your posted code that would translate .net to .com
    Thanks. No, nothing translates it, but it's not cycling through the links to come up with the corresponding clipped display for the second and subsequent links. It just reuses the clipped URL from the first link it finds. As I say, I can see why the code does this, and there probably needs to be a "while" in there somewhere to get it to work properly, but I haven't been able to figure out how to do something like a "while" on a string as I would if I was cycling through database records or an array.

    The code above is not working for me at all, but I'll post on that in a minute.

  7. #7
    SitePoint Member
    Join Date
    Jan 2007
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    Thanks for that. I kinda liked my code and hate to throw it all away but, as they say, "Why reinvent the wheel?"

    But PHP chokes on the third line of code:

    Parse error: parse error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in E:\web\dev_server\htdocs\tagster_lib.php on line 43

    (Testing on a Windows machine, but final code to run on Linux.)

    Line 43 (the third line after the comment block) is:

    protected $target;

    Here is my script:

    PHP Code:
    <?php

    include("tagster_lib.php");

    $message1 "There are multiple links in this message: http://www.example.com and http://www.example.net";

    $tagster = new Tagster("_blank""mystyle");
    $message1_modified $tagster->transform($message1);
    print 
    "message1: $message1_modified<br /><br />\n\n";

    ?>
    The only thing I changed in tagster_lib.php was the add opening and closing PHP declarations -- i.e., <?php and ?>.

    Any ideas?

  8. #8
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You're probably using PHP4 then. Either upgrade to PHP5, or try replacing the word "protected" with "var", remove all instances of the word "public" and replace "__construct" with "Tagster".

  9. #9
    SitePoint Member
    Join Date
    Jan 2007
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    You're probably using PHP4 then. Either upgrade to PHP5, or try replacing the word "protected" with "var", remove all instances of the word "public" and replace "__construct" with "Tagster".
    Yes, that would be it. Sorry, should have included the version. in there. I'll give this a go and let you know how it goes.

  10. #10
    SitePoint Member
    Join Date
    Jan 2007
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    You're probably using PHP4 then. Either upgrade to PHP5, or try replacing the word "protected" with "var", remove all instances of the word "public" and replace "__construct" with "Tagster".
    Well, that made the script work, but the script isn't very functional as it exists. It won't clip a URL so that long URLs won't cause a horizontal scrolling problem, it doesn't ignore a message if it already contains HTML markup, and if there is a break tag right after the URL (as would be the case if a message is inserted into the database with nl2br), then it breaks.

    I'll have a go at fixing the above and if I'm successful I'll post the results here.

    Thanks.

  11. #11
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You can pass a third argument to the constructor, which denotes a max length of words. This will create a soft linebreak (­) at X characters for words exceeding - including the body of a-tags.

    As for the last two problems, tagster assumes that input is text, and output HTML. If you feed it with HTML, you get unpredictable results. I suggest that you save content as text in the database, and apply HTML-formatting when outputting.

  12. #12
    SitePoint Member
    Join Date
    Jan 2007
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, I noticed the "fixlongword" argument after I posted my last message, but (right or wrong) ­ doesn't do anything in Firefox so the problem remains. As for the other two -- for a message board that allows some HTML tags in the messages posted, it isn't an option to store only plain text in the database.

    This is my inelegant solution, although it's rather frustrating because it doesn't solve the problem I hoped to solve (clipping only long URLs) and I could have achieved the same result with a slight modification to the code in my original post:

    • Instead of displaying the URL, I've just replaced it with the word "LINK".
    • I've also added the extra check to see if the message already includes anchor tags, in which case it is not parsed.
    • Also, by setting the "replace_entities" argument to "FALSE", break tags right after a URL are not mangled.
    • Added a couple of other visual refinements.
    • I've also made the changes you suggested above to get this to work in PHP 4.


    Thanks for your help. Hopefully others will find this useful.

    In the main PHP file where the message is displayed:

    PHP Code:
    $message hyperlink($message); 
    Then the function (in either an external PHP file or in the same PHP file):

    PHP Code:
    function hyperlink($message)

        {

        
    // If the message contains the string "<a" at all, then don't process it:
        
    if (eregi("<a"$message))
            {
            return (
    $message);
            }

        
    $tagster = new Tagster("_new","",60,FALSE);
        
    $message $tagster->transform($message);

        return (
    $message);

        }


    /**
      * File : tagster_lib.php
      * Version : 3.0
      * Date : September 22nd, 2002
      * Author : Lars B. Jensen, lars.jensen@ljweb.com
      *
      * Module Description
      * Module to transform URL and E-Mail addresses into clickable links.
      *
      * Instruction
      * To utilize the tagster_lib library, copy this file to a location on your server. Include the
      * library into your php document or template.
      * Use the function $tagster->transform to extract and modify all links and emails in a given string.
      * The parameters $target handling the target for links and $class for handling css on <a tags are
      * both optional.
      *
      * Example
      * include('lib/tagster_lib.php');
      * $tagster = new Tagster("_blank", "mystyle");
      * $str = $tagster->transform($str);
      *
      * Note
      * This module library has support for the scandinavian specialchars ,  and .
      *
      *
      * Public Functions
      * --------------------------------------------------------------
      * function Tagster::format($str)
      * function Tagster::url($str, $target, $class)
      * function Tagster::email($str, $class)
      *
      * Private Functions
      * --------------------------------------------------------------
      * function Tagster::fix_endchar($str)
      * function Tagster::expand($str)
      * function Tagster::reduce($str)
      * function Tagster::fix_longword($str, $maxlen)
      */

    class Tagster
    {
      var 
    $target;
      var 
    $css_class;
      var 
    $fixlongword;
      var 
    $replace_entities;

      function 
    Tagster($target="_blank"$css_class=""$fixlongword 0$replace_entities TRUE) {
        
    $this->target $target;
        
    $this->css_class $css_class;
        
    $this->fixlongword $fixlongword;
        
    $this->replace_entities $replace_entities;
      }

      function 
    transform($str) {
        if (
    $this->replace_entities) {
          
    $str str_replace("&""&amp;"$str);
          
    $str str_replace("<""&lt;"$str);
          
    $str str_replace(">""&gt;"$str);
        }
        
    $str $this->url($str$this->target$this->css_class);
        
    $str $this->email($str$this->css_class);
        
    $str $this->fix_endchar($str);
        if (
    $this->replace_entities) {
          
    $str str_replace("  ""&nbsp; "$str);
          
    $str str_replace("\t""&nbsp;&nbsp;&nbsp; "$str);
          
    $str str_replace("\r"""$str);
          
    $str str_replace("\n""<br />"$str);
        }
        if (
    $this->fixlongword != 0) {
          
    $str $this->fix_longword($str$this->fixlongword);
        }
        return 
    $str;
      }


      function 
    url($str$target$css_class) {
        
    $ins_str "";
        if (
    $css_class$ins_str .= " class=\"".$css_class."\"";
        if (
    $target$ins_str .= " target=\"".$target."\"";
        
    $str $this->expand($str);
        
    $str preg_replace ("/(ftp|http|https|telnet|news|nntp|file|irc):\/\/([a-z0-9~#%@&:;=!',_\(\)\?\/\.\-\+\[\]\|\*\$\^\{\}]+)/i""<b><a href=\"\\1://\\2\"".$ins_str." title=\"External link.\">LINK</a></b>"$str);
        
    $str preg_replace ("/(\s|tp\:|\(|\[|\&gt;)(www\.)([a-z0-9~#%@&:;=!',_\(\)\?\/\.\-\+\[\]\|\*\$\^\{\}]+)/i""\\1<b><a href=\"http://\\2\\3\"".$ins_str." title=\"External link.\">LINK</a></b>"$str);
        
    $str preg_replace ("/(\s|tp\:|\(|\[|\&gt;)(ftp\.)([a-z0-9~#%@&:;=!',_\(\)\?\/\.\-\+\[\]\|\*\$\^\{\}]+)/i""\\1<b><a href=\"ftp://\\2\\3\"".$ins_str." title=\"External link.\">LINK</a></b>"$str);
        return 
    $this->reduce($str);
      }

      function 
    email($str$css_class="") {
        
    $ins_class "";
        if (
    $css_class$ins_class " class=\"".$css_class."\"";
        
    $str $this->expand($str);
        
    $str preg_replace ("/([\s\"])([\w\.\-_]+)@([\w\-_]+)\.([\w\.\-_]+)/i""\\1<a href=\"mailto:\\2@\\3.\\4\"".$ins_class.">\\2@\\3.\\4</a>"$str);
        return 
    $this->reduce($str);
      }


      function 
    fix_endchar($str) {
        
    $str preg_replace ("/([\'\"\)\]\.\,\?\!]+)\">/i""\">"$str);
        
    $str preg_replace ("/([\'\"\)\]\.\,\?\!]+)\" (target|class)=\"/i""\" \\2=\""$str);
        
    $str preg_replace ("/([\'\"\)\]\.\,\?\!]+)<\/a>/i""</a>\\1"$str);
        return 
    $str;
      }

      function 
    fix_longword($str$maxlen 10) {
        
    $sw 0;
        
    $in_tag false;
        
    $str_size strlen($str);
        
    $res "";

        for (
    $i=0$i<$str_size$i++){
          if (
    $str[$i] == '<'$in_tag true;
          else if (
    $str[$i] == ' '$sw 0;

          if (!
    $in_tag && (($sw++) > $maxlen)) {
            
    $res .= '&shy;';
            
    $sw 0;
          }

          if (
    $str[$i] == '>'$in_tag false;
          
    $res .= $str[$i];
        }

        return 
    $res;
      }

      function 
    expand($str) {
        return 
    " ".$str." ";
      }

      function 
    reduce($str) {
        return 
    substr($str1, -1);
      }


  13. #13
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm ... You're absolutely right about the ­ entity. I think it was a bug in older browsers, which this code obviously relies on. Not that good.

    You could replace the preg_replace calls with preg_replace_callback, and let the callback function shorten the contents of the a tag. This could probably work with your original code as well.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •