Welcome Guest, Not a member yet? Register   Sign In
Auto detecting urls inside text - urls have some arabic letters
#1
Bug 
(This post was last modified: 03-09-2017, 07:30 AM by khashabawy.)

lets say i have an article :


Code:
an article text is just like this and we are inside the body of the article and there is a url inside the text with some arabic letters like this one

https://soundeals.com/community/tag/ميكروفون

i tried to use the auto_url($text) to get the urls converted to < a >tags but it fails as folloing


and we applied auto_url($text) from the url helper , 

instead of catching the whole link like this :
https://soundeals.com/community/tag/ميكروفون

it appears like this :
https://soundeals.com/community/tag/ميكروفون


how can i fix this ?
Reply
#2

You need to URL encode the tag to get it to work with auto_link. It looks like this works, at least for this simple example.


Code:
$this->load->helper('url');
$url = "https://soundeals.com/community/tag/";
$tag = "ميكروفون";
echo urldecode(auto_link($url . urlencode($tag)));
Reply
#3

(This post was last modified: 03-09-2017, 11:51 AM by khashabawy.)

(03-09-2017, 10:52 AM)zploskey Wrote: You need to URL encode the tag to get it to work with auto_link. It looks like this works, at least for this simple example.


Code:
$this->load->helper('url');
$url = "https://soundeals.com/community/tag/";
$tag = "ميكروفون";
echo urldecode(auto_link($url . urlencode($tag)));

i have the following code please focus :

PHP Code:
$text "an article text is just like this and we are inside the body of the article and there is a url inside the text with some arabic letters like this one

https://soundeals.com/community/tag/ميكروفون

i tried to use the auto_url to get the urls converted to < a >tags but it fails as folloing"
;

echo 
auto_link($text); 

i do not have a url in a variable i have it inside a text !!
Reply
#4

(This post was last modified: 03-09-2017, 12:41 PM by ivantcholakov. Edit Reason: the second suggestion )

A quick modification without much thinking - see this line: https://github.com/bcit-ci/CodeIgniter/b...r.php#L396

Change it in the following way and make a test:

Code:
if ($type !== 'email' && preg_match_all('#(\w*://|www\.)[^\s()<>;]+\w#ui', $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER))

If you are satisfied revert this change, make application/helpers/MY_url_helper.php file and put the whole modified function there.

Edit: You may try also the following modification:
Code:
if ($type !== 'email' && preg_match_all('#(\w*://|www\.)[^\s()<>;]+\w#i'.(UTF8_ENABLED ? 'u' : ''), $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER))
Reply
#5

(03-09-2017, 11:50 AM)khashabawy Wrote: i do not have a url in a variable i have it inside a text !!

If you would rather not overide the helper, you can can replace the non-ASCII characters with urlencoded versions.

PHP Code:
function urlencode_first($match)
{
    return 
urlencode($match[0]);
}

function 
urlencode_utf8chars($text)
{
    return 
preg_replace_callback('/[^\x20-\x7f]/''urlencode_first'$text);
}

// then in your controller
$this->load->helper('url');
$url "https://soundeals.com/community/tag/";
$tag "ميكروفون";
$text "text before $url$tag and after";
echo 
urldecode(auto_link(urlencode_utf8chars($text))); 

which produces the following html

Code:
text before <a href="https://soundeals.com/community/tag/ميكروفون">https://soundeals.com/community/tag/ميكروفون</a> and after

You could even wrap last line in its own function for brevity if you prefer.
Reply
#6

(03-09-2017, 12:01 PM)ivantcholakov Wrote: A quick modification without much thinking - see this line: https://github.com/bcit-ci/CodeIgniter/b...r.php#L396

Change it in the following way and make a test:

Code:
if ($type !== 'email' && preg_match_all('#(\w*://|www\.)[^\s()<>;]+\w#ui', $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER))

If you are satisfied revert this change, make application/helpers/MY_url_helper.php file and put the whole modified function there.

Edit: You may try also the following modification:
Code:
if ($type !== 'email' && preg_match_all('#(\w*://|www\.)[^\s()<>;]+\w#i'.(UTF8_ENABLED ? 'u' : ''), $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER))

WOW ! worked like magic , Thanks ivantcholakov
Reply
#7

And this is the full actual code I use, it supports passing HTML attributes as a third argument (while keeping BC):

Code:
if ( ! function_exists('auto_link'))
{
    /**
     * Modifies the auto_link helper (url_helper) by accepting as an optional third
     * argument an array of html attributes for the anchor tags (just like the anchor helper).
     *
     * This array is supplied as the third argument, replacing the
     * optional argument $pop in the original helper.
     *
     * This modified helper attempts to be backward compatible with the use of the
     * original helper by accepting TRUE and FALSE as possible values for the $attributes
     * argument, and giving output identical to the original usage of the helper.
     *
     * use:  auto_link($string, 'url' , array('class' => 'external', 'target'=>'_blank'));
     * use:  auto_link($string, 'email', array('class' => 'email_link' , 'style' => 'color:red;'));
     * use(legacy): auto_link($string, 'url' , TRUE);
     *
     * @link https://github.com/bcit-ci/CodeIgniter/wiki/auto-link
     * @author Derek Jones (original author)
     * @author Ivan Tcholakov (adaptation)
     *
     * @see url_helper
     * @link https://codeigniter.com/user_guide/helpers/url_helper.html
     * @param string $str
     * @param string $type
     * @param mixed $attributes
     * @return string
     */
    function auto_link($str, $type = 'both', $attributes = '')
    {
        // MAKE THE THIRD ARGUMENT BACKWARD COMPATIBLE
        // here we deal with the original third argument $pop
        // which could be TRUE or FALSE, and was FALSE by default.
        if ($attributes === TRUE)
        {
            $attributes = ' target="_blank"';
        }
        elseif ($attributes === FALSE)
        {
            $attributes = '';
        }

        if (!empty($attributes))
        {
            $attributes = _stringify_attributes($attributes);
        }

        // Find and replace any URLs.
        // Modified by Ivan Tcholakov, 19-DEC-2013, 09-MAR-2017.
        //if ($type !== 'email' && preg_match_all('#(\w*://|www\.)[^\s()<>;]+\w#i', $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER))
        if ($type !== 'email' && preg_match_all('#(\w*://|www\.)[^\s()<>;]+(\w|/)#i'.(UTF8_ENABLED ? 'u' : ''), $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER))
        //
        {
            // We process the links in reverse order (last -> first) so that
            // the returned string offsets from preg_match_all() are not
            // moved as we add more HTML.
            foreach (array_reverse($matches) as $match)
            {
                // $match[0] is the matched string/link
                // $match[1] is either a protocol prefix or 'www.'
                //
                // With PREG_OFFSET_CAPTURE, both of the above is an array,
                // where the actual value is held in [0] and its offset at the [1] index.
                $a = '<a href="'.(strpos($match[1][0], '/') ? '' : 'http://').$match[0][0].'"'.$attributes.'>'.$match[0][0].'</a>';
                $str = substr_replace($str, $a, $match[0][1], strlen($match[0][0]));
            }
        }

        // Find and replace any emails.
        if ($type !== 'url' && preg_match_all('#([\w\.\-\+]+@[a-z0-9\-]+\.[a-z0-9\-\.]+[^[:punct:]\s])#i', $str, $matches, PREG_OFFSET_CAPTURE))
        {
            foreach (array_reverse($matches[0]) as $match)
            {
                if (filter_var($match[0], FILTER_VALIDATE_EMAIL) !== FALSE)
                {
                    $str = substr_replace($str, safe_mailto($match[0], '', $attributes), $match[1], strlen($match[0]));
                }
            }
        }

        return $str;
    }
}
Reply




Theme © iAndrew 2016 - Forum software by © MyBB