Forum code that automatically turns urls into clickable links

16 posts by 2 authors in: Forums > CMS Builder
Last Post: December 29, 2018   (RSS)

Hi All,

I’m curious about the code used in the forum to automatically turn urls in a post into clickable links.

Like: http://www.thecmsbcookbook.com

I’d like to include it in the CMSBCookbook recipes to streamline the process.

Thanks,

Jerry Kornbluth

The first CMS Builder reference book is now available on-line!







Take advantage of a free 3 month trial subscription, only for CMSB users, at: http://www.thecmsbcookbook.com/trial.php

By daniel - December 27, 2018 - edited: December 27, 2018

Hi Jerry,

The forums use a PHP library called HTML Purifier (http://htmlpurifier.org/) to - among other things - add links to message bodies in the function sforum_cleanAndFormatHTML(). This library is integrated into the CMSB core with the common function htmlPurify(), so it should be possible to use it to just add links with something like this:

$config = array();
$config['AutoFormat.Linkify'] = true;

$newHtml = htmlPurify($oldHtml, $config);

If you're looking for something standalone that can be used outside of CMSB, here's a short snippet that should be able to handle most simple cases:

$text = preg_replace("|(https?://[\w\-@:%\+.~#?&//=]+)|", '<a href="\\1">\\1</a>', $text);

Let me know any questions!

Thanks,

Daniel
Technical Lead
interactivetools.com

Hi Daniel,

Thanks as always for your expert guidance.

I think that I got both implementations to work on the cookbook recipe details pages, although I want to do a few more tests to see if other things got broken along the way.

(Like what happens if there's a url in the example code of a recipe...)

I do have one more question. Should I be using print, print_r, or echo for the built in version of the code?

Thanks,

Jerry Kornbluth

Here’s what I have so far:

The text for my recipes are pulled from a text box called $table_of_contentsRecord['recipe'].

I've left out any formatting code to simplify the examples as much as possible.

For the code built in to CMSB

<?php $recipe = ($table_of_contentsRecord['recipe']); ?>
<?php

// automatic links using code built in to CMSB
$config = array();
$config['AutoFormat.Linkify'] = true;

$recipe = htmlPurify($recipe, $config);
echo $recipe;
?>

And for the code to use outside of CMSB:

<?php $recipe = ($table_of_contentsRecord['recipe']); ?>
<?php

// standard implementation for use outside of CMSB

$recipe = preg_replace("|(https?://[\w\-@:%\+.~#?&//=]+)|", '<a href="\\1">\\1</a>', $recipe); // Added per Daniel to create links from URLs

echo $recipe;
?>

The first CMS Builder reference book is now available on-line!







Take advantage of a free 3 month trial subscription, only for CMSB users, at: http://www.thecmsbcookbook.com/trial.php

Hi Daniel,

There's still one minor issue that I’d love to solve.

I’d like to exclude htmlPurify() from acting on the code examples within a cookbook recipe.

All code examples are enclosed in block quotes which I accomplish by surrounding each code block with qzl at the beginning and lzq at the end and then using the following code:

$recipe = str_replace('qzl', '<blockquote class="snippet"> ', $recipe);
$recipe = str_replace('lzq', '</blockquote> ', $recipe);

and styling the blockquotes with:

.snippet {font-family: Verdana, sans-serif; color: #000000; font-size: 1em; font-weight:normal;
margin: 0px 0px 0px 15px;
padding: 8px 12px;
border: 1px dashed #305555;
background-color: #54ccf2;
display: block;
overflow-x: auto;
}

I think that if I could wrap the htmlPurify code in an if statement that excludes any blockquoted data in the recipe that might work automatically, but I haven’t been able to figure out how to implement that.

Any ideas?

Complete working page code is attached.

Thanks,

Jerry Kornbluth

The first CMS Builder reference book is now available on-line!







Take advantage of a free 3 month trial subscription, only for CMSB users, at: http://www.thecmsbcookbook.com/trial.php
Attachments:

recipedetail.php 10K

By daniel - December 28, 2018

Hi Jerry,

For echo vs. print vs. print_r; I'd recommend echo for any time you want to output plain text to a page. (For some more specific details, see: https://stackoverflow.com/questions/1647322/whats-the-difference-between-echo-print-and-print-r-in-php)

From what I can see, there's no easy way to exclude the code snippets from being passed through htmlPurify(), as the whole content for the recipe is contained within a single variable. You will need to find a way to split up the content to isolate the parts you want to add links to and run the purifier on those.

A full solution is a bit beyond what I can offer here, but my suggestion would be to try using explode() to split up the content around the code blocks; something like this may work (untested code):

// split on opening blockquote
$chunks = explode('qzl', $recipe);

// loop through each chunk
foreach ($chunks as $chunk) {

  // split chunk on end blockquote
  $tmp = explode('lzq', $chunk);
  
  // did we find an ending blockquote?
  if (count( $tmp ) > 1) {

    // purify content after blockquote
    $chunks[ $chunk ][1] = htmlPurify( $chunks[ $chunk ][1] );
  }
  else {

    // purify only element
    $chunks[ $chunk ][0] = htmlPurify( $chunks[ $chunk ][0] );
  }

  // replace ending blockquote
  $chunks[ $chunk ] = implode('lqz', $tmp);
}

// replace opening blockquote
$recipe = implode('qzl', $chunks);

Let me know any questions!

Thanks,

Daniel
Technical Lead
interactivetools.com

WOW!

Thanks, Daniel,

I'll give it a try and post the results.

Jerry Kornbluth

The first CMS Builder reference book is now available on-line!







Take advantage of a free 3 month trial subscription, only for CMSB users, at: http://www.thecmsbcookbook.com/trial.php

Hi Daniel,

I tried to implemented your code on a simplified version of the detail page but I ‘m getting 2 strange errors and the other anomalies in link 2) below.

Probably a really simple fix, but I’m at a loss as to how to troubleshoot this kind of error.

Here are some links that illustrate the issue:

With the original working simple CMSB htmlPurify code: http://www.thecmsbcookbook.com/recipedetail.php?589
(The links inside and outside the blockquotes are active)

With the code as above: http://www.thecmsbcookbook.com/recipedetailH.php?589
With:

1) The errors as shown below
2) The link outside the qzl and lzq is not active and the one inside is active, and
3) There are 2 jumbled copies of the contents.

If you have a moment, could you take another look?

Thanks,

Jerry Kornbluth
_____________________________________
The test record ‘recipe’ text box contains only the following as text:

TEXT BEFORE A LINK

http://www.thecmsbcookbook.com

AFTER LINK

qzl
AFTER A QZL
<a href="http://www.thecmsbcookbook.com/css/fonts2019.css.php" />CLICK TO ACCEPT THIS</a>
lzq
AFTER AN LZQ
______________________________________
And the resulting errors are:

#7729 - E_NOTICE: Undefined index:

AFTER A QZL

<a href="http://www.thecmsbcookbook.com/css/fonts2019.css.php" />CLICK TO ACCEPT THIS</a>

lzq

AFTER AN LZQ
/home3/ellescho/public_html/thecmsbcookbook/recipedetailH.php (line 132)
http://www.thecmsbcookbook.com/recipedetailH.php?589

AND

#7728 - E_NOTICE: Undefined index:

TEXT BEFORE A LINK

http://www.thecmsbcookbook.com

AFTER LINK

/home3/ellescho/public_html/thecmsbcookbook/recipedetailH.php (line 137)
http://www.thecmsbcookbook.com/recipedetailH.php?589
__________________________________________

The active code that I’m using on the detail page is:

<?php $recipe = ($table_of_contentsRecord['recipe']); ?>
<?php
/// split on opening blockquote
$chunks = explode('qzl', $recipe);

// loop through each chunk
foreach ($chunks as $chunk) {

// split chunk on end blockquote
$tmp = explode('lzq', $chunk);

// did we find an ending blockquote?
if (count( $tmp ) > 1) {

// purify content after blockquote
$chunks[ $chunk ][1] = htmlPurify( $chunks[ $chunk ][1] );
}
else {

// purify only element
$chunks[ $chunk ][0] = htmlPurify( $chunks[ $chunk ][0] );
}

// replace ending blockquote
$chunks[ $chunk ] = implode('lqz', $tmp);
}

// replace opening blockquote
$recipe = implode('qzl', $chunks);

// reset block quotes
$recipe = str_replace('qzl', '<blockquote class="snippet"> ', $recipe);
$recipe = str_replace('lzq', '</blockquote> ', $recipe);
?>

<table>
<tr>
<td>
<?php echo $recipe; ?>
</td>
</tr>
</table>

The first CMS Builder reference book is now available on-line!







Take advantage of a free 3 month trial subscription, only for CMSB users, at: http://www.thecmsbcookbook.com/trial.php

By daniel - December 28, 2018

Hey Jerry,

Just noticed a couple logic errors in the sample code. Corrected here:

// split on opening blockquote
$chunks = explode('qzl', $recipe);

// loop through each chunk
foreach ($chunks as $key => $chunk) {

  // split chunk on end blockquote
  $tmp = explode('lzq', $chunk);
  
  // did we find an ending blockquote?
  if (count( $tmp ) > 1) {

    // purify content after blockquote
    $tmp[1] = htmlPurify( $tmp[1] );
  }
  else {

    // purify only element
    $tmp[0] = htmlPurify( $tmp[0] );
  }

  // replace ending blockquote
  $chunks[ $key ] = implode('lqz', $tmp);
}

// replace opening blockquote
$recipe = implode('qzl', $chunks);

Let me know if that does any better!

Thanks,

Daniel
Technical Lead
interactivetools.com

By daniel - December 28, 2018

Hi Jerry,

One quick thing: There's a "lzq" written as "lqz" - that should fix item 2, however, I'm not 100% sure why it's reversing the result.  Are you able to provide me with the $recipe content before it gets processed (with the qzl and lzq parts intact) so that I can test it myself?

Thanks,

Daniel
Technical Lead
interactivetools.com