2

I honestly have little clue what facts are relevant to this issue, so I'll go from the beginning.

I have bits of text that I'd like to format Markdown-style urls in before plugging into a template, but I don't want them to be wrapped in <p>'s or any other block-level tags.

To do this, I worked my way through the PHP Markdown code, isolated the stuff needed for the url formatting and threw the functions together into a file called 'MarkdownUrl.php' in a folder called 'functions' at my include path.

I'll post that code at the bottom.

For now, let's test it:

<?php
require_once 'functions/MarkdownUrl.php';
$text = "Hello, world. [This is a link.](http://www.google.com)";
echo MarkdownUrl($text);
?>

Output:

Hello, world. This is a link.

So far so good.

I also have a file called 'loader.php' at the include path. It contains a class autoloading function which it registers with spl_autoload_register() and another function called loadFunc() which will require_once a php file from the 'functions' directory according to the name it's passed. The latter is what matters here.

<?php
function loadFunc($funcName)
{
 if (!function_exists($funcName)) {
 require_once 'functions/' . $funcName . '.php';
 }
}
function loadClass($className)
{
 if (!class_exists($className, false)) {
 $classPath = str_replace('_', '/', $className);
 require_once 'classes/' . $classPath . '.php';
 }
}
spl_autoload_register('loadClass');
?>

Ignoring the 'whys' and 'wherefores' of including code in this manner for the moment, the following should be effectively equivalent to the test code I posted earlier, right?

<?php
require_once 'loader.php';
loadFunc('MarkdownUrl');
$text = "Hello, world. [This is a link.](http://www.google.com)";
echo MarkdownUrl($text);
?>

And, yet... output:

Hello, world. [This is a link.](http://www.google.com)

No errors are issued on running the above.

And, I have confirmed that the function MarkdownUrl() is being called (at least, a test echo I inserted at the top of the function fired).

Yet, the output is unformatted. WTF?

A couple I'm-not-sure-if-these-matter-at-all details: shared web host, include path specified via php.ini file in directory the test script runs in.


Contents of MarkdownUrl.php:

<?php
$nested_brackets_depth = 6;
$nested_url_parenthesis_depth = 4;
$no_entities = false;
function doAnchors_inline_callback($matches) {
 $whole_match = $matches[1];
 $link_text = $matches[2];
 $url = $matches[3] == '' ? $matches[4] : $matches[3];
 $title =& $matches[7];
 $url = encodeAttribute($url);
 $result = "<a href=\"$url\"";
 if (isset($title)) {
 $title = encodeAttribute($title);
 $result .= " title=\"$title\"";
 }
 $result .= ">$link_text</a>";
 return $result;
}
function encodeAttribute($text) {
#
# Encode text for a double-quoted HTML attribute. This function
# is *not* suitable for attributes enclosed in single quotes.
#
 $text = encodeAmpsAndAngles($text);
 $text = str_replace('"', '&quot;', $text);
 return $text;
}
function encodeAmpsAndAngles($text) {
 global $no_entities;
#
# Smart processing for ampersands and angle brackets that need to 
# be encoded. Valid character entities are left alone unless the
# no-entities mode is set.
#
 if ($no_entities) {
 $text = str_replace('&', '&amp;', $text);
 } else {
 # Ampersand-encoding based entirely on Nat Irons's Amputator
 # MT plugin: <http://bumppo.net/projects/amputator/>
 $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', 
 '&amp;', $text);;
 }
 # Encode remaining <'s
 $text = str_replace('<', '&lt;', $text);
 return $text;
}
function MarkdownUrl($text) {
 global $nested_brackets_depth, $nested_url_parenthesis_depth;
 $nested_brackets_re = 
 str_repeat('(?>[^\[\]]+|\[', $nested_brackets_depth).
 str_repeat('\])*', $nested_brackets_depth);
 $nested_url_parenthesis_re = 
 str_repeat('(?>[^()\s]+|\(', $nested_url_parenthesis_depth).
 str_repeat('(?>\)))*', $nested_url_parenthesis_depth);
 $text = preg_replace_callback('{
 ( # wrap whole match in 1ドル
 \[
 ('.$nested_brackets_re.') # link text = 2ドル
 \]
 \( # literal paren
 [ \n]*
 (?:
 <(.+?)> # href = 3ドル
 |
 ('.$nested_url_parenthesis_re.') # href = 4ドル
 )
 [ \n]*
 ( # 5ドル
 ([\'"]) # quote char = 6ドル
 (.*?) # Title = 7ドル
 6円 # matching quote
 [ \n]* # ignore any spaces/tabs between closing quote and )
 )? # title is optional
 \)
 )
 }xs','doAnchors_inline_callback', $text);
 return $text;
}
?>
asked Aug 16, 2011 at 0:09

1 Answer 1

1

That happens because you have different variable scopes in your cases.

In first case your variables are defined in global scope, thus $nested_brackets_depth = 6; and other vars defined in MarkdownUrl.php are visible for markdown functions

In other case - that variables are defined in function that includes the file scope, so they are not visible inside the functions.

The solution: change markdown file header to

global $nested_brackets_depth = 6;
global $nested_url_parenthesis_depth = 4;
global $no_entities = false;

Btw, it is a great sample why global is evil and why defining/accessing the variables in global scope is evil too.

answered Aug 16, 2011 at 0:13
2
  • Of course! Well, with a minor change (inserting global $nested_brackets_depth, $nested_url_parenthesis_depth, $no_entities; rather than attempting to initialize values in the global declarations). Commented Aug 16, 2011 at 0:30
  • Adding that this would probably be avoidable if I'd kept it encapsulated in a class rather than lazily hacking it together into procedural code. Commented Aug 16, 2011 at 0:39

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.