No more `showsource.php`

Some 250 people (this month alone) have tried to access my old script to show the source of [PHP][] scripts. Showing the source of a PHP script in a colorful way is trivial using the highlight_file() function, which is a built-in PHP function.

My little script had just a small amount of extra functionality: it tried to find URLs and file names and substituted them with links. Unfortunately this is such a crude hack that I’ve removed the file.

For much better replacements, please see the PEAR Text_Highlighter class (support for 11 languages) or the Generic Syntax Highlighter (support for 35 languages).

Hmm, all this reminds me that I still haven’t installed a plugin to let me do syntax highlighting in my own posts…

Global variables in WordPress

[WordPress logo][wordpress] In my critique of the code in WordPress I talked about the frequent use of global variables, something this I think it a bad practice. In response Owen Winkler writes that:

Global variables are used in WordPress in many places to make things simpler for a novice end-user to design. [...]

The point is that novice plugin and template designers shouldn’t have to worry about object-oriented syntax, and therefore lots of object members are put into the global scope.

It might be easy, but I still find this a poor way to pass information around in an application. The global variables obscure the relationship between functions. Take my example from the original rant, the mysql2date() function — it’s the second function (or third, depending on whether or not you expect Gettext to be active) in wp-includes/functions.php.

The first line in the body declares four global variables named $month, $weekday, $month_abbrev, and $weekday_abbrev. So this function is obviously somehow dependent on those variables being initialized. So the first question is: can I always call mysql2date()? Do I first have to call some initialization function, or is this guaranteed to be done for me when I want to use mysql2date() in some plugin or template?

It’s not such a big mystery to figure out where the variables come from: a quick grep reveals that they are defined in locale.php. But who takes care of including locale.php? Another grep, and one sees that this is done by wp-settings.php — I guess that file is always loaded, and thus one can be sure that $month and the other globals are indeed initialized before a call to mysql2date().

No wait! On close inspection of wp-settings.php one sees that locale.php is loaded after the active plugins are loaded, and after a call to do_action('plugins_loaded'). So does this mean that a

plugin that attaches itself to the plugins_loaded action cannot call mysql2date()? I believe it does!

In my installation I found no other references to the plugins_loaded action, and so this could explain why this bug wasn’t found earlier. But in any case — if the developers had taken the time to properly document this dependency between locale.php and functions.php, then the problem should never have occurred in the first place.

This potential bug wasn’t the reason for my initial worries about the use of global variables: I had been trying to get the Smart link plugin working. It uses a global $comments variable to know which comments to process, but the comments.php template doesn’t define it to be global — in fact the $comments variable is a local variable in the comments_template() function in comment-functions.php. This function includes comments.php, and thus $comments has the local scope in that file. (These scope rule games in PHP are just so annoying!)

I now see that the problem that triggered my anger against the global variables was in fact a use of a non-global variable, expecting it to be global. A bit ironic that I were to find a problem with a totally different function, mysql2date(), while initially being started by a mistake in a plugin…

Feedback on my rant

My rant about the quality of the WordPress code caused some discussion, both here and on the WP hackers mailinglist.

I understand if my comments seemed harsh, especially because I’m quite new to [WordPress][], but I still think they were justified. Especially the point about having comments in the code, where I think that (I’m quoting myself here):

[...] the idea that there can be such a thing as well-written code containing no comments is bogus: it is only in small toy examples that the function and argument names are enough to determine what a function does.

Comments are very important in a weakly-typed language like [PHP][] where you cannot tell anything at all from looking at the function.

Fix your Markdown comments

If you — like me — are using the [PHP Markdown][] plugin to make it easy and fast to write posts without dealing with heavy-duty [XHTML][] markup, then you’ll need an additional plugin: Denis de Bernardy’s Markdown fix plugin.

Even with the latest version of PHP Markdown this plugin is needed to ensure that comments are treated properly. Without the fix all comments will be treated as a single paragraph, lists and verbatim sections wont work, and people will generally have a hard time of making coherent comments in your blog!

WordPress code quality

WordPress logo WordPress calls itself a “state-of-the-art semantic personal publishing platform” — but the engine that lies beneath this shiny, smooth-looking CSS-styled surface is not that nice.

I find the coding standard in the current (version 1.5.1.1) code to be below what I would expect from a piece of software as popular as WordPress:

  • Global variables are used all over the place! Global variables should be used sparsely, if at all, for they often make the code more difficult to understand. Other people agree that Global Variables are Bad.

    From looking through the code I’ve found a $wpdb variable which is used as a global handle to the database. That’s fair enough — such a handle is needed, and lots of different pieces of the code need access to it. But still it could be handled better if one consistently used $GLOBALS['wpdb'] instead of global $wpdb followed by a later use of just $wpdb — by using the $GLOBALS array one precisely describes that this variable is just that: global.

    There are also lots of other global variables in the code, and they are often used in a much more subtle way than the $wpdb variable. A simple count of the (unique) variables declared global in the wp-includes directory gives no less than 108 variables!

  • Lack of comments! The core files such as functions.php contains tons of functions, but no comments. Take a random function like mysql2date() with a signature of

    function mysql2date($dateformatstring, $mysqlstring, $translate = true)

    is hard to understand without reading the code. The source has no doc comments which describe the arguments or the result type.

    The online documentation website, the Codex, is still very incomplete when it comes to information about the internals, and I would much prefer to have the documentation right there where it’s needed: in the code.

  • Duplicated code! Why does the code in post.php not use the wp_insert_post() function declared in functions-post.php? Instead it seems to duplicate the logic in wp_insert_post(), something which will sooner or later lead to problems.

  • Incredibly long lines! It is clear that there has been made no attempt to break the code into lines at a reasonable site (that is, less than 80 characters per line).

    Those long lines makes the code annoying to read unless I make my terminal or Emacs huge and it makes diffs cryptic when one has to compare two 200 character lines to figure out a change. For someone who would like to look into the code those things make a real difference and should not be neglected because it is “just cosmetics”.

  • Mixed XHTML and PHP code. The themes in WordPress use no page template system what so ever, they just output the raw XHTML to the user — making it easy to create invalid XHTML output.

    To defend this choice, then I must say that I’ve never been impressed by template systems like Smarty which claims to separate the application code from the presentation. To do this they give you a template language in which you can program your pages — if you look more closely at it, then this template language ends up being simply a reimplementation of the original language. So instead of if ($foo || $bar) ... you write {if $foo or $bar} .... Has this bought you anything, except requiring you to learn another language with its possible quirks and limitations?

    If that was what the WordPress developers asked themselves, then I can understand why they simply went with normal PHP code mixed with XHTML. But it can be done better than that: PhpWiki uses a cool system where all the XHTML code is generated using a set of classes and functions. Using such a high-level interface automatically makes the produced XHTML code compliant and it makes the source so much cleaner. With some proper caching the performance shouldn’t be affected, but the long term quality of WordPress would improve.

I hope that the WordPress developers take steps to fix and improve some of the things I’ve described above. Apparently, there are others who agree with me about the quality of the WordPress code. Despite my complains, I’ll keep using it, for even though I can find lots of things to complain about, I still think it’s the best software for what it does.