<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BigSmoke &#187; PHP</title>
	<atom:link href="http://blog.bigsmoke.us/tag/php/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.bigsmoke.us</link>
	<description>Smokes your problems, coughs fresh air.</description>
	<lastBuildDate>Sat, 04 Feb 2012 11:10:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Executing system commands from PHP with SUID executable.</title>
		<link>http://blog.bigsmoke.us/2011/02/02/executing-system-commands-from-php-with-suid-executable</link>
		<comments>http://blog.bigsmoke.us/2011/02/02/executing-system-commands-from-php-with-suid-executable#comments</comments>
		<pubDate>Wed, 02 Feb 2011 14:05:05 +0000</pubDate>
		<dc:creator>halfgaar</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[sudo]]></category>
		<category><![CDATA[suid]]></category>

		<guid isPermaLink="false">http://blog.bigsmoke.us/?p=1866</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>If you want to execute system commands from something like PHP, you need a SUID executable which you can call from your PHP scripts. This is such a script. It could be extended to support parameters for the commands you want to execute, but that would be an enormous security risk, because then anybody can execute any command. If you need something as flexible as that, you need to think about adding some kind of security restrictions, like a list of allowed commands.</p>
<p>When writing this, it occurred to me how unnecessary this all is. I will explain below. First, I will describe the old way.</p>
<p>Here is the c source code, as written for our backup script, bsbackup.sh:</p>
<p><pre class="php"><span style="color: #808080; font-style: italic;">// Wrapper for the bsbackup.sh shell script, to be able to run it as root when</span>
<span style="color: #808080; font-style: italic;">// started from a webserver, for example. Set the resulting executable to SUID</span>
<span style="color: #808080; font-style: italic;">// root.</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#include &lt;stdlib.h&gt;</span>
<span style="color: #808080; font-style: italic;">#include &lt;stdio.h&gt;</span>
<span style="color: #808080; font-style: italic;">#include &lt;unistd.h&gt;</span>
<span style="color: #808080; font-style: italic;">#include &lt;errno.h&gt;</span>
<span style="color: #808080; font-style: italic;">#include &lt;error.h&gt;</span>
&nbsp;
int main<span style="color: #66cc66;">&#40;</span>int argc, char *argv<span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span>, char *envp<span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    int set_uid_result;
    int effective_user_id;
    int execute_script_error;
    char* script;
&nbsp;
    effective_user_id = geteuid<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// Set real and effective user ID</span>
    set_uid_result = setreuid<span style="color: #66cc66;">&#40;</span>effective_user_id, effective_user_id<span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>set_uid_result != <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        <a href="http://www.php.net/printf"><span style="color: #000066;">printf</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Failed to set user id<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #b1b100;">return</span> <span style="color: #cc66cc;">1</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;
    script = <span style="color: #ff0000;">&quot;/usr/local/sbin/bsbackup.sh&quot;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// This does not return on success.</span>
    execve<span style="color: #66cc66;">&#40;</span>script, argv, envp<span style="color: #66cc66;">&#41;</span>;
    execute_script_error = errno;
&nbsp;
    <span style="color: #808080; font-style: italic;">// Show a fancy error message.</span>
    error<span style="color: #66cc66;">&#40;</span>execute_script_error, execute_script_error, script<span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// Shouldn't be necceary, but you never know.</span>
    <span style="color: #b1b100;">return</span> <span style="color: #cc66cc;">1</span>;
<span style="color: #66cc66;">&#125;</span></pre></p>
<p>To compile:</p>
<p><pre class="php">gcc -o bsbackup bsbackup.c</pre></p>
<p>You can then run this inside PHP:</p>
<p><pre class="php"><span style="color: #808080; font-style: italic;">// The 2&gt;&amp;1 makes all error messages appear on stdout, for easy capturing.</span>
<a href="http://www.php.net/passthru"><span style="color: #000066;">passthru</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/usr/local/sbin/bsbackup usb_backup 2&gt;&amp;1'</span><span style="color: #66cc66;">&#41;</span>;</pre></p>
<p>As I said, when writing this, it all became very clear to me that it is quite useless. One can also install sudo, run visudo and put this in (assuming your webserver runs as www-data, like on (Debian and Ubuntu):</p>
<p><pre class="php">www-data ALL = NOPASSWD: /usr/local/sbin/bsbackup.sh</pre></p>
<p>Then in PHP, just run this:</p>
<p><pre class="php"><a href="http://www.php.net/passthru"><span style="color: #000066;">passthru</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'sudo /usr/local/sbin/bsbackup.sh usb_backup 2&gt;&amp;1'</span><span style="color: #66cc66;">&#41;</span>;</pre></p>
<p>I haven&#8217;t tested whether specifying the parameters after the script in the passthru actually works, but I think so. If not, you can just write a wrapper script around the command you&#8217;re going to execute. </p>
<p>See what you like best <img src='http://blog.bigsmoke.us/wp-factory/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.bigsmoke.us/2011/02/02/executing-system-commands-from-php-with-suid-executable/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Taking control of the wpautop filter</title>
		<link>http://blog.bigsmoke.us/2010/12/09/wpautop</link>
		<comments>http://blog.bigsmoke.us/2010/12/09/wpautop#comments</comments>
		<pubDate>Wed, 08 Dec 2010 22:14:59 +0000</pubDate>
		<dc:creator>Rowan Rodrik</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[wpautop]]></category>
		<category><![CDATA[wpautop-control]]></category>

		<guid isPermaLink="false">http://blog.bigsmoke.us/?p=1108</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>WordPress does automatic paragraph formatting using the <a href="http://codex.wordpress.org/Function_Reference/wpautop"><tt>wpautop</tt></a> filter, some PHP code <a href="http://ma.tt/scripts/autop/">originally developed</a> by Matt Mullenweg. For most of the time that this blog has existed, I&#8217;ve disabled the <tt>wpautop</tt> filter  using the following two lines in my theme&#8217;s <tt>functions.php</tt> file:</p>

<pre class="php">remove_filter<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'the_content'</span>, <span style="color: #ff0000;">'wpautop'</span><span style="color: #66cc66;">&#41;</span>;
remove_filter<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'the_excerpt'</span>, <span style="color: #ff0000;">'wpautop'</span><span style="color: #66cc66;">&#41;</span>;</pre>

<p>I&#8217;m <a href="http://www.studiograsshopper.ch/code-snippets/wordpress-editor-disabling-wpautop/">not</a> the only one to do this. But, I&#8217;m tired of having to manually type <tt>&lt;p&gt;</tt>s for every paragraph in every post that I write.</p>

<p>I&#8217;d like to be able have it back on, but preferably a bit smarter so that you don&#8217;t get all that crap (also common on bulletin boards with empty paragraphs around undetected block-level elements, especially if these are non-standard, related to plugins.</p>

<p>At the very least I want to be able to turn it off for when it does annoy me, on these moments that I don&#8217;t want auto-anything. Also, I need this if I don&#8217;t want to break the nearly 300 posts that I formatted manually. So, I want to use a custom field to turn the filter on or off.</p>

<p>I found an <a href="http://wordpress.org/support/topic/202980">unpublished plugin</a> (unpublished in the sense that the source isn&#8217;t hosted somewhere proper such as <tt>wordpress.org/extend/plugins/</tt>) which does some of what I want in a somewhat messy unmaintained manner. After years of just entering those damn <tt>&lt;p&gt;</tt>s (and over a year since this draft was in the making), I decided to do my own plugin for post-by-post (<em>and</em> global) control of the <tt>wpautop</tt> filter. It&#8217;s called wpautop-control:</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #808080; font-style: italic;">/*
Plugin Name: wpautop-control
Plugin URI: http://blog.bigsmoke.us/tag/wpautop-control/
Description: This plugin allows you fine control of when and when not to enable the wpautop filter on posts.
Author: Rowan Rodrik van der Molen
Author URI: http://blog.bigsmoke.us/
Version: 1.0
*/</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> is_admin<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  add_action<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'admin_menu'</span>, <span style="color: #ff0000;">'wpautop_control_menu'</span><span style="color: #66cc66;">&#41;</span>;
  add_action<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'admin_init'</span>, <span style="color: #ff0000;">'wpautop_control_settings'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #000000; font-weight: bold;">function</span> wpautop_control_menu<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    add_submenu_page<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'options-general.php'</span>, <span style="color: #ff0000;">'wpautop-control'</span>, <span style="color: #ff0000;">'wpautop control'</span>, <span style="color: #ff0000;">'manage_options'</span>, <span style="color: #ff0000;">'wpautop-control-menu'</span>, <span style="color: #ff0000;">'wpautop_control_options'</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">function</span> wpautop_control_options<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>!current_user_can<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'manage_options'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>  <span style="color: #66cc66;">&#123;</span>
      wp_die<span style="color: #66cc66;">&#40;</span> __<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'You do not have sufficient permissions to access this page.'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">?&gt;</span>
  &lt;div <span style="color: #000000; font-weight: bold;">class</span>=<span style="color: #ff0000;">&quot;wrap&quot;</span>&gt;
    &lt;h2&gt;wpautop control options&lt;/h2&gt;
&nbsp;
    &lt;form method=<span style="color: #ff0000;">&quot;post&quot;</span> action=<span style="color: #ff0000;">&quot;options.php&quot;</span>&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> settings_fields<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'wpautop-control'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      &lt;table <span style="color: #000000; font-weight: bold;">class</span>=<span style="color: #ff0000;">&quot;form-table&quot;</span>&gt;
        &lt;tr valign=<span style="color: #ff0000;">&quot;top&quot;</span>&gt;
          &lt;th scope=<span style="color: #ff0000;">&quot;row&quot;</span>&gt;wpautop filter on by <span style="color: #000000; font-weight: bold;">default</span>?&lt;/th&gt;
          &lt;td&gt;
            &lt;label&gt;&lt;input type=<span style="color: #ff0000;">&quot;radio&quot;</span> name=<span style="color: #ff0000;">&quot;wpautop_on_by_default&quot;</span> value=<span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> get_option<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'wpautop_on_by_default'</span><span style="color: #66cc66;">&#41;</span> == <span style="color: #ff0000;">'1'</span> <span style="color: #66cc66;">&#41;</span> <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">'checked=&quot;1&quot;'</span> ?&gt;&gt; yes&lt;/label&gt;
            &lt;label&gt;&lt;input type=<span style="color: #ff0000;">&quot;radio&quot;</span> name=<span style="color: #ff0000;">&quot;wpautop_on_by_default&quot;</span> value=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> get_option<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'wpautop_on_by_default'</span><span style="color: #66cc66;">&#41;</span> == <span style="color: #ff0000;">'0'</span> <span style="color: #66cc66;">&#41;</span> <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">'checked=&quot;1&quot;'</span> ?&gt;&gt; no&lt;/label&gt;
          &lt;/td&gt;
      &lt;/table&gt;
&nbsp;
      &lt;p <span style="color: #000000; font-weight: bold;">class</span>=<span style="color: #ff0000;">&quot;submit&quot;</span>&gt;
      &lt;input type=<span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000000; font-weight: bold;">class</span>=<span style="color: #ff0000;">&quot;button-primary&quot;</span> value=<span style="color: #ff0000;">&quot;Save Changes&quot;</span> /&gt;
      &lt;/p&gt;
    &lt;/form&gt;
  &lt;/div&gt;
  <span style="color: #000000; font-weight: bold;">&lt;?php</span>
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">function</span> wpautop_control_settings<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    register_setting<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'wpautop-control'</span>, <span style="color: #ff0000;">'wpautop_on_by_default'</span>, <span style="color: #ff0000;">'intval'</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #808080; font-style: italic;">// ! is_admin()</span>
  add_filter<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'the_content'</span>, <span style="color: #ff0000;">'wpautop_control_filter'</span>, <span style="color: #cc66cc;">9</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #000000; font-weight: bold;">function</span> wpautop_control_filter<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$content</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <a href="http://www.php.net/global"><span style="color: #000066;">global</span></a> <span style="color: #0000ff;">$post</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">// Get the keys and values of the custom fields:</span>
    <span style="color: #0000ff;">$post_wpautop_value</span> = get_post_meta<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$post</span>-&gt;<span style="color: #006600;">ID</span>, <span style="color: #ff0000;">'wpautop'</span>, <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #0000ff;">$default_wpautop_value</span> = get_option<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'wpautop_on_by_default'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #0000ff;">$remove_filter</span> = <span style="color: #000000; font-weight: bold;">false</span>;
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/empty"><span style="color: #000066;">empty</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$post_wpautop_value</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
      <span style="color: #0000ff;">$remove_filter</span> = ! <span style="color: #0000ff;">$default_wpautop_value</span>;
    <span style="color: #b1b100;">elseif</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$post_wpautop_value</span> == <span style="color: #ff0000;">'true'</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #0000ff;">$remove_filter</span> = <span style="color: #000000; font-weight: bold;">false</span>;
    <span style="color: #b1b100;">elseif</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$post_wpautop_value</span> == <span style="color: #ff0000;">'false'</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #0000ff;">$remove_filter</span> = <span style="color: #000000; font-weight: bold;">true</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$remove_filter</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
      remove_filter<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'the_content'</span>, <span style="color: #ff0000;">'wpautop'</span><span style="color: #66cc66;">&#41;</span>;
      remove_filter<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'the_excerpt'</span>, <span style="color: #ff0000;">'wpautop'</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$content</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre>

<p>(I&#8217;ve requested the plugin to be <a href="http://wordpress.org/extend/plugins/wpautop-control/">added</a> to the <a href="http://wordpress.org/extend/plugins/">WordPress plugin repository</a>, so that it won&#8217;t have to be reinvented another 20 times in the next year or so.) <img src='http://blog.bigsmoke.us/wp-factory/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>

<p>After installing the plugin, you can choose whether to enable or disable wpautop by default. Then, for every post where you want to deviate from the default, you can set the wpautop custom field to ‘true’ or ‘false’.</p>

<p>I want the new default to be to enable the filter, but since all my old posts have been manually formatted, I want all these to have the wpautop field added and set to ‘false’.</p>

<p>Adding the appropriate custom field values to all existing posts is easy thanks to MySQL&#8217;s <tt><a href="http://dev.mysql.com/doc/refman/5.1/en/insert-select.html">INSERT … SELECT</a></tt> syntax:</p>

<pre class="mysql"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> wp_postmeta <span style="color: #66cc66;">&#40;</span>post_id, meta_key, meta_value<span style="color: #66cc66;">&#41;</span>
     <span style="color: #993333; font-weight: bold;">SELECT</span> wp_posts.ID, <span style="color: #ff0000;">'wpautop'</span>, <span style="color: #ff0000;">'false'</span>
       <span style="color: #993333; font-weight: bold;">FROM</span> wp_posts
      <span style="color: #993333; font-weight: bold;">WHERE</span> post_type = <span style="color: #ff0000;">'post'</span>;</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.bigsmoke.us/2010/12/09/wpautop/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP include exploits</title>
		<link>http://blog.bigsmoke.us/2010/11/14/php-include-exploits</link>
		<comments>http://blog.bigsmoke.us/2010/11/14/php-include-exploits#comments</comments>
		<pubDate>Sun, 14 Nov 2010 17:19:10 +0000</pubDate>
		<dc:creator>Rowan Rodrik</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[exploit]]></category>
		<category><![CDATA[include]]></category>
		<category><![CDATA[nfsn]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://blog.bigsmoke.us/?p=1711</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>A year ago, my web host thoroughly explained <a href="http://blog.nearlyfreespeech.net/2009/11/05/a-php-include-exploit-explained/">how PHP include vulnerabilities can be exploited</a>, hoping that better user education would leave less member-sites vulnerable to automated attacks by spammer scum.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigsmoke.us/2010/11/14/php-include-exploits/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ytec, WordPress and Aihato.nl</title>
		<link>http://blog.bigsmoke.us/2010/11/09/www.aihato.nl</link>
		<comments>http://blog.bigsmoke.us/2010/11/09/www.aihato.nl#comments</comments>
		<pubDate>Tue, 09 Nov 2010 15:29:26 +0000</pubDate>
		<dc:creator>Rowan Rodrik</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Aihato]]></category>
		<category><![CDATA[ContentFlow]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[FancyBox]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Make]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[XML-RPC]]></category>

		<guid isPermaLink="false">http://blog.bigsmoke.us/?p=1632</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>On Oktober, the 25th, in what will be known to future generations as a historical move, Wiebe changed the A record of <a href="http://www.aihato.nl/">www.aihato.nl</a> to point to the new production site running at Ytec. The new site, a collaboration by <a href="http://www.ytec.nl/">Ytec</a> and <a href="http://www.bigsmoke.us/">me</a>, based on WordPress, has been in development since May. At least, that&#8217;s when I started <a href="http://blog.bigsmoke.us/2010/05/04/aihato-wordpress-dev-notes">taking notes</a>. There had been some discussion, wire-framing and design done before that time.</p>

<p>The graphical design for the new Aihato website was created in Photoshop by a Ytec employee, building on a wire-frame created by Ying Hao (good friend and owner of Ytec). Another Ytec employee freed me of the burden of slicing the design into HTML/CSS, so that I could concentrate on the WordPress programming work involved. I liked not having to worry too much about design for once.</p>

<div id="attachment_1652" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/comfortably-installed-at-ytec1.jpg"><img src="http://blog.bigsmoke.us/uploads/2010/11/comfortably-installed-at-ytec1-300x225.jpg" alt="Comfortably Installed at Ytec" title="Comfortably Installed at Ytec" width="300" height="225" class="size-medium wp-image-1652" /></a><p class="wp-caption-text">Comfortably Installed at Ytec</p></div>

<h2>Initial development setup</h2>

<p>Because I had decided to put WordPress in its <a href="http://blog.bigsmoke.us/2009/01/30/separating-wordpress-factory-files-from-custom-files">own subdirectory</a> to keep my custom stuff separate from the factory default stuff, I needed my own vhost at Ytec, something I had gotten used to with all my previous web development projects. Initially, I tried to make things work in my own ~subdirectory on a shared vhost, but this wreaked havoc with the rewrite voodoo that I needed to make WordPress live comfortably in its own subdir. Maybe, it would have been better to use <a href="http://blog.bigsmoke.us/2009/09/20/svn-vendor-branches-wordpress">vendor branches</a>; but decisions, decisions&#8230;</p>

<h2 id="makefile">A Makefile for deployment, sychronisation and backups</h2>

<p>On many of my recent projects, I&#8217;ve used Rake instead of GNU Make. This time, I took it oldschool to pimp up my Make skills a bit. This proved pretty necessary, because I&#8217;ve spent ages on a bug in a previous version of the Makefile were I defined a variable after a make target without realizing that I had to put this in a separate rule from the instructions to make that target.</p>

<p>Why I even need a Makefile? Because when you&#8217;ve had your fair share of deployment, synchronisation and backup problems, you like to define rules to avoid these problems. Makefiles are ideal for that purpose, because they consist of <em>rules</em>.</p>

<p>I&#8217;m publishing the Makefile here because it&#8217;s one of the prettier Makefiles I&#8217;ve made and I like to brag and remember myself of some of the new things that I learned during its creation.</p>

<pre class="php">RSYNC_OPTIONS := --verbose --progress --recursive --delete --links --times --filter=<span style="color: #ff0000;">'merge ./rsync-upload-filters'</span>
WORKING_COPY_ROOT := $<span style="color: #66cc66;">&#123;</span>HOME<span style="color: #66cc66;">&#125;</span>/www.aihato.nl/
LIVE_PRODUCTION_ROOT := ytec.nl:/too/much/info/aihato.nl/
LIVE_DEVELOPMENT_ROOT := ytec.nl:/too/much/info/aihato-dev/
MYSQL_LOGIN := --user=aihato --password=InYourDreamsIdForgetToChangeThis
&nbsp;
&nbsp;
deploy-production:
    <span style="color: #808080; font-style: italic;"># First, I sync everything except the symlink to the current WP version</span>
    rsync $<span style="color: #66cc66;">&#40;</span>RSYNC_OPTIONS<span style="color: #66cc66;">&#41;</span> --filter=<span style="color: #ff0000;">&quot;exclude /wp&quot;</span>  $<span style="color: #66cc66;">&#40;</span>WORKING_COPY_ROOT<span style="color: #66cc66;">&#41;</span> $<span style="color: #66cc66;">&#40;</span>LIVE_PRODUCTION_ROOT<span style="color: #66cc66;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># Now, if the symlink's target has changed, we've atomically upgraded all WP files</span>
    rsync $<span style="color: #66cc66;">&#40;</span>RSYNC_OPTIONS<span style="color: #66cc66;">&#41;</span> $<span style="color: #66cc66;">&#40;</span>WORKING_COPY_ROOT<span style="color: #66cc66;">&#41;</span> $<span style="color: #66cc66;">&#40;</span>LIVE_PRODUCTION_ROOT<span style="color: #66cc66;">&#41;</span>
&nbsp;
backup-production: 
    rsync $<span style="color: #66cc66;">&#123;</span>RSYNC_OPTIONS<span style="color: #66cc66;">&#125;</span> $<span style="color: #66cc66;">&#40;</span>LIVE_PRODUCTION_ROOT<span style="color: #66cc66;">&#41;</span>uploads/ $<span style="color: #66cc66;">&#40;</span>HOME<span style="color: #66cc66;">&#41;</span>/aihato-uploads/
    ssh ytec.nl <span style="color: #ff0000;">&quot;mysqldump $(MYSQL_LOGIN) aihato&quot;</span> &gt; aihato.sql
&nbsp;
update-development: 
    rsync $<span style="color: #66cc66;">&#40;</span>RSYNC_OPTIONS<span style="color: #66cc66;">&#41;</span> $<span style="color: #66cc66;">&#40;</span>WORKING_COPY_ROOT<span style="color: #66cc66;">&#41;</span> $<span style="color: #66cc66;">&#40;</span>LIVE_DEVELOPMENT_ROOT<span style="color: #66cc66;">&#41;</span>
    rsync $<span style="color: #66cc66;">&#40;</span>RSYNC_OPTIONS<span style="color: #66cc66;">&#41;</span> $<span style="color: #66cc66;">&#40;</span>LIVE_PRODUCTION_ROOT<span style="color: #66cc66;">&#41;</span>uploads/ $<span style="color: #66cc66;">&#40;</span>LIVE_DEVELOPMENT_ROOT<span style="color: #66cc66;">&#41;</span>uploads/
    ssh ytec.nl <span style="color: #ff0000;">&quot;mysqldump $(MYSQL_LOGIN) aihato | mysql $(MYSQL_LOGIN) dev_aihato&quot;</span>
&nbsp;
backup-development: mysql-dump-development
    rsync $<span style="color: #66cc66;">&#123;</span>RSYNC_OPTIONS<span style="color: #66cc66;">&#125;</span> $<span style="color: #66cc66;">&#40;</span>LIVE_DEVELOPMENT_ROOT<span style="color: #66cc66;">&#41;</span>uploads/ $<span style="color: #66cc66;">&#40;</span>HOME<span style="color: #66cc66;">&#41;</span>/aihato-uploads/
&nbsp;
mysql-dump-development:
    ssh ytec.nl <span style="color: #ff0000;">&quot;mysqldump $(MYSQL_LOGIN) dev_aihato&quot;</span> &gt; dev_aihato.sql
&nbsp;
.PHONY: update-development backup-production deploy-production mysql-dump-development</pre>

<div id="attachment_1645" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-front-page-top.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-front-page-top-300x170.png" alt="www.aihato.nl – Front page – top portion" title="www.aihato.nl – Front page – top portion" width="300" height="170" class="size-medium wp-image-1645" /></a><p class="wp-caption-text">Top portion of the front page</p></div>

<div id="attachment_1664" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-instellingen-lezen.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-instellingen-lezen-300x168.png" alt="www.aihato.nl – Settings – Reading" title="www.aihato.nl – Settings – Reading" width="300" height="168" class="size-medium wp-image-1664" /></a><p class="wp-caption-text">www.aihato.nl – Settings – Reading</p></div>

<h2>Front page</h2>

<p>The front page, after the header with the navigation and logo, starts with of a little snippet of text to welcome visitors. The rest of the page is filled with some selected stuff from the rest of the website: the latest news excerpts (plus a link to the full archive and the news feed and the Aihato hyve), clickable sponsor logos, some upcoming agenda items, a promotional movie clip, the latest video from the video gallery, a carousel with the latest photos, another carousel with all the fighter profiles and the latest fight results.</p>

<p>In WordPress, when you want the home page to be a static page, you have to change a setting in the <cite><a href="http://codex.wordpress.org/Settings_Reading_SubPanel">Settings / Reading</a></cite> subpanel. You will then have to choose another page to be the “posts” page. The other page will than use the template hierarchy the same way the home page would without this setting. The only custom page template you can use for it is <tt>home.php</tt>, which might cause confusion with the <em>actual</em> home page.</p>

<h2>Template entanglement</h2>

<p>The start page is one of a number of pages for www.aihato.nl that needed a custom template. To associate a custom template with the start page, I had two choices: I could either name the template file <tt>page-3.php</tt>, according to the <cite><a href="http://codex.wordpress.org/Template_Hierarchy">Template Hierarchy</a></cite>, or I could create a <cite><a href="http://codex.wordpress.org/Pages#Page_Templates">Page Template</a></cite>. The difference between the two options is that with the latter option, the association with the custom template happens from the Edit Page screen, whereas the first option relies on the naming of a template file in my theme. I chose the first option, which is a bit ugly, because after setting a page as start page, editing the page slug is no longer possible. (Normally you can name the template file <tt>page-&lt;slug&gt;.php</tt>, which is clearer and doesn&#8217;t depend on database state.) Both solutions are ugly in a sense because there&#8217;s just too much stuff in the database to my taste, but that&#8217;s another story which I&#8217;ll probably tell in reference to Drupal one day, since Drupal is way uglier than WordPress in this sense.</p>

<p>I&#8217;ve ended up with a bit of a random mix of page-targeted templates and templates targeted from pages. The highlight is a template which does both: <tt>page-sportschool.php</tt> targets the page with the “sportschool” slug, but also has the following comment so that I can select it from the Page Edit screen for the subpages of “sportschool”:</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #808080; font-style: italic;">/*
Template Name: Sportschool 
 */</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre>

<div id="attachment_1665" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-events.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-events-300x170.png" alt="Aihato Events mangement interface" title="Aihato Events mangement interface" width="300" height="170" class="size-medium wp-image-1665" /></a><p class="wp-caption-text">Aihato Events mangement interface</p></div>

<h2>Events</h2>

<p>It was decided that the new website, like the old website, would have an agenda. The old website&#8217;s agenda was never up-to-date, so the new agenda should be easier to edit. To that end, I created an aihato-events plugin.</p>

<p>The plugin is quite simple. It adds two tables to the database – one to record (and announce) events and another to store fight results for these events (wins, losses, etc.). The second table links to a fighter profile by post ID (but more about that later). </p>

<div id="attachment_1666" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-events-contestants.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-events-contestants-300x170.png" alt="Aihato Event Contestants" title="Aihato Events – Contestants" width="300" height="170" class="size-medium wp-image-1666" /></a><p class="wp-caption-text">Aihato Event Contestants</p></div>

<div id="attachment_1667" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-agenda.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-agenda-300x170.png" alt="Agenda page" title="Aihato – Agenda" width="300" height="170" class="size-medium wp-image-1667" /></a><p class="wp-caption-text">Agenda page</p></div>

<p>The event management interface is pretty decent. It includes a few darlings, which I wouldn&#8217;t like to kill, except that I <em>will</em> probably overhaul the whole Aihato Events UI at some unspecified time in the future. The darlings are small touches such as the “Add new” buttons above and below the table which add a new row through AJAX at the top or the bottom of the table depending on which button is clicked. I&#8217;m also always a sucker for the in-place AJAX editing of the rows. The reason why I&#8217;ll probably still overhaul the UI at some future time is that I don&#8217;t like the same simple tabular interface for the Contestants panel. I had predicted that fight events would generally first be placed in the agenda before the event takes place, untill after the event, the results would be added. So far, nothing has been placed in the agenda before it takes place. Only after, to be able to link it to the results to be added. And even if this wasn&#8217;t true, the two screens should still become one I think.</p>

<p>The homepage contains the first few upcoming events. Sadly, there aren&#8217;t any yet. <img src='http://blog.bigsmoke.us/wp-factory/wp-includes/images/smilies/icon_confused.gif' alt=':-?' class='wp-smiley' />  Below that short (and empty) list, there&#8217;s a big button which links to the complete agenda. This page has a design that somewhat deviates from the rest. Of course, it also has some custom template programming (in a template called <tt>page-agenda.php</tt>).</p>

<div id="attachment_1668" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-uitslagen.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-uitslagen-300x170.png" alt="Page with fight results" title="Aihato – Uitslagen" width="300" height="170" class="size-medium wp-image-1668" /></a><p class="wp-caption-text">Page with fight results</p></div>

<h2>Event results</h2>

<p>The homepage also contains all the fight results for the latest event in a nice little table at the bottom right. Consistent with all the other areas on the homepage, this one is also followed by a link to the results for all recorded events in the form of a nice big button. The page with the complete results is powered by <tt>page-uitslagen.php</tt>.</p>

<p>This is one of the templates which I should really clean up by moving some code into nice and clean helper functions that live in the theme&#8217;s <tt>functions.php</tt> instead of all over the place.</p>

<h2>I18n</h2>

<p>My interest in internationalization for this website extends only as far as that I want the visitor to be talked to in Dutch as much as possible. For the rest, I don&#8217;t really care. How much I don&#8217;t care can be summed up by the total absence of <tt>__()</tt>-encapsulated strings in my theme. What&#8217;s worse: my custom plugins also lack these l10n hooks, although, because I always feel like a sinner when working directly in what is considered a translation <em>target</em> by me and the rest of the English-oriented development world, the event management stuff that I added to the management interface is in English (although, again, without l10n hooks, so what&#8217;s the point?).</p>

<div id="attachment_1670" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-profiel-tobias.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-profiel-tobias-300x170.png" alt="Aihato – Profile – Tobias" title="Aihato – Profile – Tobias" width="300" height="170" class="size-medium wp-image-1670" /></a><p class="wp-caption-text">Fighter profile for Tobias</p></div>

<div id="attachment_1674" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-profiel-bewerken.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-profiel-bewerken-300x170.png" alt="Aihato – Edit fighter profile" title="Aihato – Edit fighter profile" width="300" height="170" class="size-medium wp-image-1674" /></a><p class="wp-caption-text">Editing a fighter profile now</p></div>

<div id="attachment_1672" class="wp-caption alignright" style="width: 243px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-profiel-djura.jpg"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-profiel-djura-233x300.jpg" alt="Aihato – Profile – Djura" title="Aihato – Profile – Djura" width="233" height="300" class="size-medium wp-image-1672" /></a><p class="wp-caption-text">Fighter profile for Djura</p></div>

<h2>Fighter profiles</h2>

<p>Fighter profiles play a dominant role in the new design. Implementation took some time, and still I&#8217;m not entirely satisfied. During development, <a href="http://codex.wordpress.org/Custom_Post_Types">custom post types</a> were introduced in WordPress. I had already implemented the fighter profiles using a page template and a whole heap of <a href="http://codex.wordpress.org/Custom_Fields">custom fields</a>. Adding new profiles this way, however, is far from user-friendly. The user has to:</p>

<ul>
<li>Set the page parent to “Vechters” (Dutch for “Fighters”);</li>
<li>set the page template to “Vechter”;</li>
<li>add new custom fields for Discipline, Fight record, Weight, Class, Age, Length and City while making sure that the values are entered correctly since these don&#8217;t have a type;</li>
<li>and set a featured image for display in the fighter carousel on the front page and above the profiles.</li>
</ul>

<p>This is a lot of work, none of which is very obvious, so I hoped that custom post types would save the day. Theoretically they could, but there were a few issues, some of which I only encountered when I was quite far with development of an aihato-profiles plugin which implemented the <tt>aihato_fighter</tt> custom post type.</p>

<p>I started out by fooling with some plugins to do some of the heavy lifting. I wasn&#8217;t particularly charmed by these for reasons which I&#8217;ve sadly forgotten because I haven&#8217;t commented on it at the time. One reason I <em>can</em> think of is that I never like defining stuff in the database which I feel belongs in a file.</p>

<p>There seemed to be a bug in the custom post type admin interface created by WordPress in that, even though I had enabled thumbnail support for my post type, the UI for this was lacking. Another bug related to images was that clicking the <i>Insert image</i> button replaced the current page with the upload dialog instead of loading it in a modal dialog through AJAX. These two bugs were show-stoppers. I won&#8217;t comment any further on the whole custom post type development process until I actually continue this process.</p>

<p>Anyway, it all works now and I don&#8217;t mind doing some work on new fighter profiles myself. Editing existing ones is easy enough, and at the visitor end, it all looks sexy enough. <img src='http://blog.bigsmoke.us/wp-factory/wp-includes/images/smilies/icon_cool.gif' alt='8-)' class='wp-smiley' /> </p>

<h2>Guest-book</h2>

<p>Implementing the guest book was pretty easy. What was less easy was importing all the entries from the old guest-book. Although, even that was incredibly easy compared with extracting (exporting is too expensive a verb) the entries from the old guest-book. The old guest-book was basically impossible to spider, because the pagination depended on <tt>POST</tt>. If it were only the page number in the <tt>POST</tt> request, it wouldn&#8217;t have been too bad (and quite hackable for my purpose), but there was all sorts of session-related crap and other ugly stuff that smelled like a bunch of Microsoft Monkeys had gone all out in a HTTP obfuscation contest.</p>

<p>My initial import strategy consisted of a simple PHP script (with a function adapted from <a href="http://wordpress.org/extend/plugins/facebook-comments/">some plugin</a>) to be ran from the command-line, that accepted the author and date as arguments and the post body over STDIN.</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #b1b100;">require_once</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'wp-config.php'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> guestbook_new_comment <span style="color: #66cc66;">&#40;</span> <span style="color: #0000ff;">$commentdata</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'comment_post_ID'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #cc66cc;">19</span> <span style="color: #808080; font-style: italic;"># This is the Aihato guestbook page</span>
  <span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'user_ID'</span><span style="color: #66cc66;">&#93;</span>         = <span style="color: #cc66cc;">0</span> <span style="color: #808080; font-style: italic;"># These people don't have accounts</span>
&nbsp;
  <span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'comment_author_IP'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">'127.0.0.1'</span> <span style="color: #0000ff;">$_SERVER</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'REMOTE_ADDR'</span><span style="color: #66cc66;">&#93;</span>;
  <span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'comment_agent'</span><span style="color: #66cc66;">&#93;</span>     = <span style="color: #ff0000;">'Hacked together import scripts (by BigSmoke)'</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">// We want to use the original comment date, not the time now.</span>
  <span style="color: #808080; font-style: italic;">//$commentdata['comment_date']     = current_time('mysql');</span>
  <span style="color: #808080; font-style: italic;">//$commentdata['comment_date_gmt'] = current_time('mysql', 1);</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">// Automatically approve these comments.</span>
  <span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'comment_approved'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #cc66cc;">1</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">// Actually add to the database</span>
  <span style="color: #0000ff;">$comment_ID</span> = wp_insert_comment<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  do_action<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'comment_post'</span>, <span style="color: #0000ff;">$comment_ID</span>, <span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'comment_approved'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$comment_ID</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'comment_author'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$ARGV</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#93;</span>;
<span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'comment_date'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'comment_date_gmt'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$ARGV</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#93;</span>;
<span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'comment_content'</span><span style="color: #66cc66;">&#93;</span> = <a href="http://www.php.net/trim"><span style="color: #000066;">trim</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/readfile"><span style="color: #000066;">readfile</span></a><span style="color: #66cc66;">&#40;</span>STDIN<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #0000ff;">$new_comment_id</span> = guestbook_new_comment<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$commentdata</span><span style="color: #66cc66;">&#41;</span>;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;Inserted new comment $new_comment_id to post 19.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre>

<p>The script would be called from a Ruby script that parsed the ugly-ass HTML-like tag soup also known as the old guest-book. I have to admit that the script is as ugly as the shit it&#8217;s supposed to make sense of. Fuck it! One-of scripts don&#8217;t need to look good; it&#8217;s already been deleted from svn 75 revisions ago.</p>

<p>However, I never could call the PHP script from the Ruby script because I <a href="http://blog.bigsmoke.us/2010/06/21/rubygems">couldn&#8217;t</a> get the necessary gems to install on the development server where the import needed to happen, so I ran the script locally and modified it to use WordPress&#8217; XML-RPC interface. To make this work, I only had to install a <a href="http://www.thepicklingjar.com/code/anonymous-xmlrpc-comments/">WordPress plugin to allow anonymous comments through XML-RPC</a>. (See my <a href="http://blog.bigsmoke.us/2010/05/04/aihato-wordpress-dev-notes#comment-95789">previous notes</a> on this subject, if you&#8217;re interested.)</p>

<p>[By the way, I just copied this script to the clipboard using “<tt>svn cat https://svn.ytec.nl/svn/aihato/trunk/import-guestbook.rb@37|xsel --clipboard</tt>”; see my <a href="http://blog.bigsmoke.us/2010/01/31/xsel">post on xsel</a> if you want to learn more.]</p>

<div id="attachment_1681" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-gastenboek.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-gastenboek-300x170.png" alt="Aihato - Guestbook" title="Aihato - Guestbook" width="300" height="170" class="size-medium wp-image-1681" /></a><p class="wp-caption-text">The finished guestbook, complete with all the old and new enties</p></div>

<pre class="ruby"><span style="color:#008000; font-style:italic;">#!/usr/bin/ruby</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">require</span> 'scrapi'
<span style="color:#CC0066; font-weight:bold;">require</span> 'open3'
<span style="color:#CC0066; font-weight:bold;">require</span> 'xmlrpc/client'
&nbsp;
&nbsp;
guestbook_entry = Scraper.<span style="color:#9900CC;">define</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  process <span style="color:#996600;">&quot;td &gt; div.GB_Head &gt; div.GB_Date&quot;</span>, :date =&gt; :text
  process <span style="color:#996600;">&quot;td &gt; div.GB_Head &gt; div.GB_Name&quot;</span>, :name =&gt; :text
  process <span style="color:#996600;">&quot;td &gt; div.GB_Body &gt; div.GB_BodyText&quot;</span>, :body =&gt; :element
&nbsp;
  result :date, :name, :body
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
guestbook = Scraper.<span style="color:#9900CC;">define</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  <span style="color:#CC0066; font-weight:bold;">array</span> :entries
&nbsp;
  process <span style="color:#996600;">&quot;table.GB_MainGrid tr&quot;</span>, :entries =&gt; guestbook_entry
&nbsp;
  result :entries
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># I need to do this because the document has at least 3 &lt;html&gt; tags,</span>
<span style="color:#008000; font-style:italic;"># so it's impossible to parse, even for Tidy</span>
fake_document = <span style="color:#996600;">&quot;&lt;html&gt;&lt;body&gt;&quot;</span>
reading_guestbook_table = <span style="color:#0000FF; font-weight:bold;">false</span>
STDIN.<span style="color:#CC0066; font-weight:bold;">readlines</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> |line|
  <span style="color:#9966CC; font-weight:bold;">if</span> line =~ /&lt;table <span style="color:#9966CC; font-weight:bold;">class</span>=<span style="color:#996600;">&quot;GB_MainGrid&quot;</span>/
    reading_guestbook_table = <span style="color:#0000FF; font-weight:bold;">true</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  
  <span style="color:#9966CC; font-weight:bold;">if</span> reading_guestbook_table
    fake_document += line
    reading_guestbook_table = <span style="color:#0000FF; font-weight:bold;">false</span> <span style="color:#9966CC; font-weight:bold;">if</span> line =~ %r<span style="color:#006600; font-weight:bold;">&#123;</span>&lt;/table&gt;<span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
fake_document += <span style="color:#996600;">&quot;&lt;/body&gt;&lt;/html&gt;&quot;</span>
&nbsp;
entries = guestbook.<span style="color:#9900CC;">scrape</span><span style="color:#006600; font-weight:bold;">&#40;</span>fake_document<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
entries.<span style="color:#9900CC;">delete_at</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
entries.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> |entry|
  <span style="color:#9966CC; font-weight:bold;">next</span> <span style="color:#9966CC; font-weight:bold;">unless</span> entry<span style="color:#006600; font-weight:bold;">&#91;</span>'body'<span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
  date_parts_in_proper_order = entry<span style="color:#006600; font-weight:bold;">&#91;</span>'date'<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span>/-/<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">reverse</span>
  date_string_with_proper_zeroes = <span style="color:#996600;">&quot;%d%02d%02dT00:00:00&quot;</span> % date_parts_in_proper_order
  entry<span style="color:#006600; font-weight:bold;">&#91;</span>'date'<span style="color:#006600; font-weight:bold;">&#93;</span> = XMLRPC::Convert.<span style="color:#9900CC;">dateTime</span><span style="color:#006600; font-weight:bold;">&#40;</span> date_string_with_proper_zeroes <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  server = XMLRPC::Client.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;aihato.dev.ytec.nl&quot;</span>, <span style="color:#996600;">&quot;/wp/xmlrpc.php&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  entry<span style="color:#006600; font-weight:bold;">&#91;</span>'body'<span style="color:#006600; font-weight:bold;">&#93;</span> = entry<span style="color:#006600; font-weight:bold;">&#91;</span>'body'<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_s</span>
  entry<span style="color:#006600; font-weight:bold;">&#91;</span>'body'<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span>!<span style="color:#006600; font-weight:bold;">&#40;</span>%r<span style="color:#006600; font-weight:bold;">&#123;</span>&lt;div <span style="color:#9966CC; font-weight:bold;">class</span>='GB_BodyText'&gt;<span style="color:#006600; font-weight:bold;">&#40;</span>.<span style="color:#9900CC;">*</span><span style="color:#006600; font-weight:bold;">&#41;</span>&lt;/div&gt;<span style="color:#006600; font-weight:bold;">&#125;</span>m, '\<span style="color:#006666;">1</span>'<span style="color:#006600; font-weight:bold;">&#41;</span>
  entry<span style="color:#006600; font-weight:bold;">&#91;</span>'body'<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span>!<span style="color:#006600; font-weight:bold;">&#40;</span>%r<span style="color:#006600; font-weight:bold;">&#123;</span>&lt;/p&gt;\s*&lt;p&gt;<span style="color:#006600; font-weight:bold;">&#125;</span>, <span style="color:#996600;">&quot;<span style="color:#000099;">\n</span><span style="color:#000099;">\n</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  entry<span style="color:#006600; font-weight:bold;">&#91;</span>'body'<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span>!<span style="color:#006600; font-weight:bold;">&#40;</span>%r<span style="color:#006600; font-weight:bold;">&#123;</span>&lt;/?p&gt;<span style="color:#006600; font-weight:bold;">&#125;</span>, <span style="color:#996600;">&quot;&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  entry<span style="color:#006600; font-weight:bold;">&#91;</span>'body'<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">chomp</span>!
&nbsp;
  new_comment_id = server.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>'wp.<span style="color:#9900CC;">newComment</span>', <span style="color:#006666;">1</span>, '', '', <span style="color:#006666;">19</span>, <span style="color:#006600; font-weight:bold;">&#123;</span>'comment_parent' =&gt; <span style="color:#006666;">0</span>, 'content' =&gt; entry<span style="color:#006600; font-weight:bold;">&#91;</span>'body'<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_s</span>, 'author' =&gt; entry<span style="color:#006600; font-weight:bold;">&#91;</span>'name'<span style="color:#006600; font-weight:bold;">&#93;</span>, 'author_url' =&gt; '', 'author_email' =&gt; 'dummy@example.<span style="color:#9900CC;">com</span>'<span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  <span style="color:#CC0066; font-weight:bold;">puts</span> new_comment_id.<span style="color:#9900CC;">inspect</span>
  
  <span style="color:#008000; font-style:italic;"># Change date and approval status</span>
  server.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>'wp.<span style="color:#9900CC;">editComment</span>', <span style="color:#006666;">1</span>, 'myuser', 'nottherealpassword', new_comment_id, <span style="color:#006600; font-weight:bold;">&#123;</span>'status' =&gt; 'approve', 'date_created_gmt' =&gt; entry<span style="color:#006600; font-weight:bold;">&#91;</span>'date'<span style="color:#006600; font-weight:bold;">&#93;</span>, 'author' =&gt; entry<span style="color:#006600; font-weight:bold;">&#91;</span>'name'<span style="color:#006600; font-weight:bold;">&#93;</span>, 'author_email' =&gt; 'dummy@example.<span style="color:#9900CC;">com</span>'<span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  <span style="color:#008000; font-style:italic;">#Open3.popen3(&quot;php -q import-guestbook.php '#{entry['name']}' #{entry['date']}&quot;) do |stdin, stdout, stderr|</span>
  <span style="color:#008000; font-style:italic;">#  stdin &lt;&lt; entry['body']</span>
  <span style="color:#008000; font-style:italic;">#end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre>

<p>Because I was too stupid to write a spider function to download the old guest-book, I ended up simply clicking through all the pages and feeding the page source to my import script one page at the time.</p>

<p>The new guest book is the only page on the website with comments enabled. For the rest it&#8217;s like any other page with its own custom template (<tt>page-gastenboek.php</tt>).</p>

<div id="attachment_1682" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-contact.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-contact-300x170.png" alt="Aihato – Contact" title="Aihato – Contact" width="300" height="170" class="size-medium wp-image-1682" /></a><p class="wp-caption-text">The contact form</p></div>

<h2>Contact form</h2>

<p>In my <a href="http://blog.bigsmoke.us/2010/05/04/aihato-wordpress-dev-notes">notes</a> made during the development process, I have made a few comments (<a href="http://blog.bigsmoke.us/2010/05/04/aihato-wordpress-dev-notes#comment-95459">1</a>, <a href="http://blog.bigsmoke.us/2010/05/04/aihato-wordpress-dev-notes#comment-95854">2</a>, <a href="http://blog.bigsmoke.us/2010/05/04/aihato-wordpress-dev-notes#comment-95855">3</a>, <a href="http://blog.bigsmoke.us/2010/05/04/aihato-wordpress-dev-notes#comment-95856">4</a>) about the troubles I had when looking for a simple plugin to create a simple contact form. I would have saved quite some time if I had skipped the search and wrote my own code to handle it. In the end I did use a plug-in. Well, I forked it, but that&#8217;s just another way of using it, isn&#8217;t it?</p>

<div id="attachment_1683" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-nieuws-2010.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-nieuws-2010-300x170.png" alt="Aihato - News - 2010" title="Aihato - News - 2010" width="300" height="170" class="size-medium wp-image-1683" /></a><p class="wp-caption-text">The news archive</p></div>

<h2>News</h2>

<p>The actual news section (where I could use WordPress&#8217; core strength – its blogging engine) is maybe the foremost reason why I let myself be suckered into another web project despite my many vows to never program for money again. (Well, this being a club project, means that I could somewhat sidestep my many promises to myself, because there was hardly money involved in the process. (I train for free for a year.))</p>

<p>The old website&#8217;s news page was just a very long list of all the news since 2003. This was pretty suck-ass. What was much worse, though, was that there was no RSS feed. This new website being WordPress based means that I have a whole slew of feeds to chose from. It gave me quite a kick when the first news item posted by someone else hit my feed reader. Now, there are no longer any sites left that I have to manually check for updates. Yay!</p>

<p>An interesting choice I made for the news archive is that I skipped pagination altogether and instead presented a list of years all the way back to 2003 where you&#8217;d normally expect to see pagination. Personally, I don&#8217;t mind long pages. In fact, I often find clicking “Next” and “Previous” infinitely much more annoying.</p>

<p>Commenting on the news isn&#8217;t allowed by request of the Aihato boys. They gave some pretty good reasons not to do this mostly related to the intentional abuse by club members and members of competing clubs that they&#8217;ve seen on the website of a friendly club.</p>

<p>The news section is just one of the many places where I&#8217;ve made thankful use of WordPress&#8217; new <a href="http://codex.wordpress.org/Post_Thumbnails">Post Thumbnails</a> feature. I like it when stuff that&#8217;s only available through clumsy hacks and plugins makes it into core. By the way: when working with post thumbnails, the <a href="http://wordpress.org/extend/plugins/regenerate-thumbnails/">regenerate-thumbnails</a> plugin proved to be an enormous aid.</p>

<div id="attachment_1684" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-foto-albums.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-foto-albums-300x170.png" alt="Aihato – Photo albums" title="Aihato – Photo albums" width="300" height="170" class="size-medium wp-image-1684" /></a><p class="wp-caption-text">Overview of all photo albums</p></div>

<div id="attachment_1685" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-foto-album-ede.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-foto-album-ede-300x170.png" alt="Aihato – Photo album – Ede" title="Aihato – Photo album – Ede" width="300" height="170" class="size-medium wp-image-1685" /></a><p class="wp-caption-text">Photo album of a grappling competition</p></div>

<h2>Media gallery</h2>

<p>Even on the old website, the foto gallery played an important role. Thinking of the best way how to do this in WordPress was quite a <a href="http://blog.bigsmoke.us/2010/05/04/aihato-wordpress-dev-notes#comment-96142">headache</a>.</p>

<p>To start with, the design requirements were pretty steep. Ying had included a coverflow-like effect in his wire-frame for viewing individual albums. Luckily, the list of photo albums wasn&#8217;t too difficult (a simple grid-view) and made easier still by the HTML/CSS guy. I also skipped a few requirements such as highest rated photos and videos. (I skipped the rating feature altogether.) Still, I spent a lot of time looking through available plug-ins and into different ways to solve the most challenging requirement: there had to be a separate section for the photo albums and the videos, where intuitively I&#8217;d simply include it all in the news as is customary with a blog. In the end, I did exactly this but with a twist.</p>

<p>The process of publishing a new photo album has become extremely straight-forward: the user has to upload the images using the <i>Add image</i> link, insert the gallery in the post (<em>if</em> they want a clear link from the news item view to the gallery) and check the “Fotogalerij” (Dutch for “photo gallery”) category (if they want the album to appear in the list of albums).</p>

<p>Since I&#8217;ve chosen not to make photo albums a separate entity in the back-end, I had to work a little magic to make them appear as such to the visitor. But I didn&#8217;t want to make the separation go too far; I don&#8217;t like websites (such as the old Aihato website) where the photo gallery seems bolted on as an afterthought and the user has to upload an album and then create a link to the album in the news.</p>

<h3>The gallery view</h3>

<p>You know how WordPress makes a comments feed available for every post? It accomplishes this using something it calls a <em>rewrite endpoint</em> (“feed” for feeds). For example:</p>

<pre class="php">http:<span style="color: #808080; font-style: italic;">//www.example.com/blog/2010/11/08/post-with-interesting-comments/feed/atom/</span>
http:<span style="color: #808080; font-style: italic;">//www.example.com/blog/2010/11/08/post-with-interesting-comments/feed/rss/ </span></pre>

<p>You can add such a rewrite endpoint yourself using the <tt><a href="http://codex.wordpress.org/Rewrite_API#add_rewrite_endpoint.28.29">add_rewrite_endpoint()</a></tt> function. The code below shows how I created an alternative view for my posts and pages called “gallery”. It also shows what I need to do to make an extra query variable available with the name of the endpoint. The part after the slash after the endpoint in the URL become the new query variable&#8217;s value.</p>

<pre class="php">add_rewrite_endpoint<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'gallery'</span>, EP_PERMALINK | EP_PAGES<span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$wp_rewrite</span>-&gt;<span style="color: #006600;">flush_rules</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
add_filter<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'query_vars'</span>, <span style="color: #ff0000;">'aihato_queryvars'</span><span style="color: #66cc66;">&#41;</span>;
add_action<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'template_redirect'</span>, <span style="color: #ff0000;">'aihato_special_gallery_template'</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> aihato_special_gallery_template<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <a href="http://www.php.net/global"><span style="color: #000066;">global</span></a> <span style="color: #0000ff;">$wp_query</span>;
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> is_category<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'fotogalerij'</span><span style="color: #66cc66;">&#41;</span> or is_category<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'filmgalerij'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">include</span><span style="color: #66cc66;">&#40;</span>TEMPLATEPATH . <span style="color: #ff0000;">'/galleries.php'</span><span style="color: #66cc66;">&#41;</span>;
    <a href="http://www.php.net/exit"><span style="color: #000066;">exit</span></a>;
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$wp_query</span>-&gt;<span style="color: #006600;">query_vars</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'gallery'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">include</span><span style="color: #66cc66;">&#40;</span>TEMPLATEPATH . <span style="color: #ff0000;">'/gallery.php'</span><span style="color: #66cc66;">&#41;</span>;
    <a href="http://www.php.net/exit"><span style="color: #000066;">exit</span></a>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> aihato_queryvars<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$qvars</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #0000ff;">$qvars</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">'gallery'</span>;
  <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$qvars</span>;
<span style="color: #66cc66;">&#125;</span></pre>

<p>The code above creates an alternative “view” of posts that I can use to view all the images attached to that post. When the user inserts the gallery into a post, the following code makes it so that instead of the images, the visitor will see a link to the gallery view of that post.</p>

<pre class="php">add_filter<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'post_gallery'</span>, <span style="color: #ff0000;">'aihato_gallery_filter'</span>, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">/**
 * Modifies the behaviour of the [gallery] shortcode.
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> aihato_gallery_filter<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$null</span>, <span style="color: #0000ff;">$attr</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
<span style="color: #808080; font-style: italic;">// Snipped: code to generate a nice link</span>
<span style="color: #66cc66;">&#125;</span></pre>

<h3>ContentFlow / FancyBox integration</h3>

<p>To make the gallery view look cool, I implemented the CoverFlow effect using the <a href="http://www.jacksasylum.eu/ContentFlow/index.php">ContentFlow</a> jQuery plugin. It&#8217;s pretty cool. It supports reflection, scrolling with a scroll wheel and it just <em>feels right</em>™. I hooked it up to <a href="http://fancybox.net/">FancyBox</a>, a very slick Lightbox clone for jQuery. The result was, I must say, immensely pleasing. <img src='http://blog.bigsmoke.us/wp-factory/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Both effects support scrolling and the FancyBox effects make it look like the images in the ContentFlow are really blown up and shrunk. (I&#8217;ve made it so that the FancyBox appears when you click the active image in the ContentFlow.)</p>

<p>This is some of the spaghetti code that made the two effects play nicely together:</p>

<pre class="javascript"><span style="color: #009900; font-style: italic;">// Returns the offset of the item to start showing</span>
<span style="color: #003366; font-weight: bold;">function</span> albumFlowStartItem<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> hashNumber = window.<span style="color: #006600;">location</span>.<span style="color: #006600;">hash</span>;
&nbsp;
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span> hashNumber &amp;&amp; hashNumber.<span style="color: #006600;">match</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066FF;">/^#\d+$/</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    hashNumber = hashNumber.<span style="color: #006600;">replace</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066FF;">/^#<span style="color: #66cc66;">&#40;</span>\d+<span style="color: #66cc66;">&#41;</span>$/</span>, <span style="color: #3366CC;">'$1'</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #000066; font-weight: bold;">return</span> jQuery<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'#album_flow a#attachment-'</span>+hashNumber<span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">prevAll</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">size</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">'center'</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #009900; font-style: italic;">// My own custom state variable</span>
jQuery.<span style="color: #006600;">fancybox</span>.<span style="color: #006600;">remainActiveUntilClosed</span> = <span style="color: #003366; font-weight: bold;">false</span>;
&nbsp;
jQuery<span style="color: #66cc66;">&#40;</span>document<span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">ready</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  jQuery<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'#album_flow a'</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">fancybox</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span>
    transitionIn: <span style="color: #3366CC;">'elastic'</span>,
    transitionOut: <span style="color: #3366CC;">'elastic'</span>,
    speedIn: <span style="color: #CC0000;">600</span>,
    speedOut: <span style="color: #CC0000;">200</span>,
    overlayShow: <span style="color: #003366; font-weight: bold;">false</span>,
    cyclic: <span style="color: #003366; font-weight: bold;">true</span>,
    onStart: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>selectedArray, selectedIndex, selectedOpts<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
      element = selectedArray<span style="color: #66cc66;">&#91;</span>selectedIndex<span style="color: #66cc66;">&#93;</span>;
&nbsp;
      <span style="color: #000066; font-weight: bold;">return</span> jQuery.<span style="color: #006600;">fancybox</span>.<span style="color: #006600;">remainActiveUntilClosed</span> || element.<span style="color: #006600;">hasClassName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'active'</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>,
    onComplete: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
      jQuery.<span style="color: #006600;">fancybox</span>.<span style="color: #006600;">remainActiveUntilClosed</span> = <span style="color: #003366; font-weight: bold;">true</span>;
    <span style="color: #66cc66;">&#125;</span>,
    onClosed: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
      jQuery.<span style="color: #006600;">fancybox</span>.<span style="color: #006600;">remainActiveUntilClosed</span> = <span style="color: #003366; font-weight: bold;">false</span>;
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> albumFlow = <span style="color: #003366; font-weight: bold;">new</span> ContentFlow<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'album_flow'</span>, <span style="color: #66cc66;">&#123;</span>
    reflectionHeight: <span style="color: #CC0000;">0.3</span>,
    flowSpeedFactor: <span style="color: #CC0000;">0.7</span>,
    startItem: albumFlowStartItem<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>,
    onclickActiveItem: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
      <span style="color: #003366; font-weight: bold;">var</span> itemOffset = jQuery<span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #006600;">element</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">prevAll</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">size</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
      jQuery.<span style="color: #006600;">fancybox</span>.<span style="color: #006600;">pos</span><span style="color: #66cc66;">&#40;</span>itemOffset<span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>,
  <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</pre>

<h3>Categories for photo/video galleries</h3>

<p>To make a post appear in the photo gallery, you just have to check that category. Making posts appear in the video gallery works the same. These listings are displayed using the <tt>galleries.php</tt> template thanks to a little bit of code in <tt>aihato_special_gallery_template()</tt>. I redirected these archive views to that template because otherwise I&#8217;d have had to make a symlink to use the same file for the video category and the photo category. (I&#8217;d have needed two files: <tt>category-fotogalerij.php</tt> and <tt>category-filmgalerij.php</tt>.)</p>

<p>I like how I simply used a custom view of both a post and of two different category archives to achieve all my media gallery requirements. There&#8217;s no wild database customizations or heavy plug-ins involved. It&#8217;s low-fat and carb-free.</p>

<div id="attachment_1687" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-filmgalerij.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-filmgalerij-300x170.png" alt="Aihato - Film gallery" title="Aihato - Film gallery" width="300" height="170" class="size-medium wp-image-1687" /></a><p class="wp-caption-text">The film gallery</p></div>

<h3>YouTube is king</h3>

<p>Because I was too lazy to find a good playback solution and I&#8217;m a bit reluctant to self-host video files anyway, I decided to put together something that relies solely on embedding videos hosted elsewhere. To be completely honest, although WordPress is quite flexible in this sense, “elsewhere” means just YouTube here.</p>

<p>The idea is simple: WordPress already allows you to just paste a YouTube URL into the post editor and all the embedding code is created for you. Building on this, to show the latest video on the homepage, I just perform a search for posts which contain a YouTube URL. Then I parse the content a bit, and include the YouTube ID in my own low-res embed code. (The latest video area on the homepage is smaller than the default embed created by WordPress.)</p> 

<p>When generating the film gallery overview, my theme goes through all the YouTube URLs in all posts categorized as “Filmgalerij”. For each of these URLs, it uses the YouTube API to retrieve the movie title and the URL of an adequately sized thumbnail. That means that, for thumbnails to appear in the gallery, the associated posts don&#8217;t need a featured image, just one or more YouTube URLs. This approach also makes it so that you can embed as much YouTube URLs in each post as you like, since the gallery will cope beautifully.</p>

<p>When a visitor clicks a movie thumbnail, a YouTube embed pops up using FancyBox. Did I mention how cool FancyBox is? Pretty damn cool:</p>

<pre class="javascript">jQuery<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'a.youtube'</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">click</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span>
  jQuery.<span style="color: #006600;">fancybox</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span>
    <span style="color: #3366CC;">'padding'</span>: <span style="color: #CC0000;">0</span>,
    <span style="color: #3366CC;">'autoScale'</span>: <span style="color: #003366; font-weight: bold;">false</span>,
    <span style="color: #3366CC;">'transitionIn'</span>: <span style="color: #3366CC;">'none'</span>,
    <span style="color: #3366CC;">'transitionOut'</span>: <span style="color: #3366CC;">'none'</span>,
    <span style="color: #3366CC;">'title'</span>: <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">title</span>,
    <span style="color: #3366CC;">'width'</span>: <span style="color: #CC0000;">680</span>,
    <span style="color: #3366CC;">'height'</span>: <span style="color: #CC0000;">495</span>,
    <span style="color: #3366CC;">'href'</span>: <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">href</span>.<span style="color: #006600;">replace</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> RegExp<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">&quot;watch<span style="color: #000099; font-weight: bold;">\\</span>?v=&quot;</span>, <span style="color: #3366CC;">&quot;i&quot;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #3366CC;">'v/'</span><span style="color: #66cc66;">&#41;</span>,
    <span style="color: #3366CC;">'type'</span>: <span style="color: #3366CC;">'swf'</span>,
    <span style="color: #3366CC;">'swf'</span>: <span style="color: #66cc66;">&#123;</span>
      <span style="color: #3366CC;">'wmode'</span>: <span style="color: #3366CC;">'transparent'</span>,
      <span style="color: #3366CC;">'allowfullscreen'</span>: <span style="color: #3366CC;">'true'</span>
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span>;
<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</pre>

<h2>Menus and navigation</h2>

<p id="main-menu-hack">A downside of my view-oriented media gallery solution is the insanely ugly hack I had to do to make the top horizontal menu behave naturally:</p>

<pre class="php"><span style="color: #808080; font-style: italic;">// This is the ultimate in ugly hacks. Enjoy! :-)</span>
<span style="color: #000000; font-weight: bold;">function</span> aihato_main_menu_filter<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$items</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <a href="http://www.php.net/global"><span style="color: #000066;">global</span></a> <span style="color: #0000ff;">$wp_query</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">// menu-item-639 = Nieuws</span>
  <span style="color: #808080; font-style: italic;">// menu-item-643 = Foto/Video (connected to the fotogalerij category)</span>
&nbsp;
  <span style="color: #808080; font-style: italic;">// This conditional makes it the current-menu-item also when we're in the filmgalerij category,</span>
  <span style="color: #808080; font-style: italic;">// and when we're looking at the gallery view of a post (through the gallery rewrite endpoint).</span>
  <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> is_category<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'filmgalerij'</span><span style="color: #66cc66;">&#41;</span> or <a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$wp_query</span>-&gt;<span style="color: #006600;">query_vars</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'gallery'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$items</span> = <a href="http://www.php.net/preg_replace"><span style="color: #000066;">preg_replace</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'!(menu-item-643)!'</span>, <span style="color: #ff0000;">'<span style="color: #000099; font-weight: bold;">\\</span>1 current-menu-item'</span>, <span style="color: #0000ff;">$items</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
  <span style="color: #808080; font-style: italic;">// This conditional ensures that the Nieuws menu item is active when we don't want to be in the gallery.</span>
  <span style="color: #808080; font-style: italic;">// At the same time, it makes sure that the the Foto/Video menu item is inactive.</span>
  <span style="color: #b1b100;">elseif</span> <span style="color: #66cc66;">&#40;</span> !<a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$wp_query</span>-&gt;<span style="color: #006600;">query_vars</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'gallery'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> and <span style="color: #66cc66;">&#40;</span>is_archive<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> or is_single<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$items</span> = <a href="http://www.php.net/preg_replace"><span style="color: #000066;">preg_replace</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'!(menu-item-639)!'</span>, <span style="color: #ff0000;">'<span style="color: #000099; font-weight: bold;">\\</span>1 current-menu-parent'</span>, <span style="color: #0000ff;">$items</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #0000ff;">$items</span> = <a href="http://www.php.net/preg_replace"><span style="color: #000066;">preg_replace</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'!current-menu-parent current-post-parent (menu-item-643)!'</span>, <span style="color: #ff0000;">'<span style="color: #000099; font-weight: bold;">\\</span>1'</span>, <span style="color: #0000ff;">$items</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$items</span>;  
<span style="color: #66cc66;">&#125;</span></pre>

<p>As soon as <a href="http://codex.wordpress.org/Version_3.0">WordPress 3.0</a> was released somewhere during the development of this website, I started to use its new <a href="http://codex.wordpress.org/Appearance_Menus_SubPanel">Custom Menu Management</a> feature.</p>

<p>Before the change:</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span> wp_list_pages<span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'depth'</span> =&gt; <span style="color: #cc66cc;">1</span>, <span style="color: #ff0000;">'title_li'</span> =&gt; <span style="color: #ff0000;">''</span>, <span style="color: #ff0000;">'sort_column'</span> =&gt; <span style="color: #ff0000;">'menu_order, post_title'</span> <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre>

<p>After the change:</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span> wp_nav_menu<span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'menu'</span> =&gt; <span style="color: #ff0000;">'main'</span>, <span style="color: #ff0000;">'depth'</span> =&gt; <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre>

<p>As you can see, the change wasn&#8217;t difficult, but, more importantly, it gave me some useful powers that I could use for good. For the main menu, I could include a category, which I used to add the Fotogalerij category. I could also change the label of that item to be different from the category name so that it also seems to apply to the Filmgalerij category. That, together with the <a href="#main-menu-hack">ugly hack</a> above, gave me my illusionary Photo/Video category.</p>

<div id="attachment_1686" class="wp-caption alignright" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2010/11/aihato-sportschool.png"><img src="http://blog.bigsmoke.us/uploads/2010/11/aihato-sportschool-300x170.png" alt="Aihato – Sportschool" title="Aihato – Sportschool" width="300" height="170" class="size-medium wp-image-1686" /></a><p class="wp-caption-text">Putting custom menus to good use in this section</p></div>

<p>Another place where I could put the custom menus to good use was the Sportschool section. There I had to <em>design</em> a submenu, because designers always forget a few vital pieces in their design, such as how submenus should look. However, the submenu shouldn&#8217;t just include links to pages, but also links to two different subscription forms (uploads). The new menu system allows me to do this quite easily.</p>

<p>So, again, I could replace something that didn&#8217;t do exactly what I wanted:</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span> wp_list_pages<span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'title_li'</span> =&gt; get_the_title<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #ff0000;">'child_of'</span> =&gt; <span style="color: #cc66cc;">11</span>, <span style="color: #ff0000;">'include'</span> =&gt; <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000000; font-weight: bold;">?&gt;</span></pre>

<p>With something simpler that did:</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span> wp_nav_menu<span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'menu'</span> =&gt; <span style="color: #ff0000;">'school'</span> <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre>

<p>It is a curious aspect of this website that every section has its own means of navigating within that section.</p>

<ol>
<li>The fighter profiles section uses a carousel at the top to select fighters. In the future, some form controls to filter the carousel will also be added.</li>
<li>The Photo/Video gallery is divided into two subsections (one for photos and one for videos). These subsections are subsequently navigated using a grid view of the individual photo albums or videos. When viewing a photo album, navigation is further refined using the ContentFlow UI.</li>
<li>The news section is subdivided in yearly archives which are presented as a sort of pagination interface.</li>
<li>The Sportschool (“Over Aihato”) section sports a simple “submenu” in the left column. This is in fact a separate menu defined in the theme and managed using the new menu editor.</li>
<li>Finally, the guestbook uses WordPress&#8217; default comment pagination.</li>
</ol>

<h2>Conclusion</h2>

<p>This turned out to be a pretty long post taking a ridiculous amount of time to write. But, hey, this way I have at least documented the project. I don&#8217;t think that such detailed documentation would have happened otherwise. In my experience, “in-house” documentation sucks donkey ass. It&#8217;s never complete. It&#8217;s never up-to-date and – worst of all – it doesn&#8217;t invite comments. It&#8217;s just not part of big WWW.</p>

<p>I&#8217;m glad that the new website is on-line. I love how it turned out (even though I still hate web development). The enthusiastic reception of this project even compensates for some of my previous web development traumas. <img src='http://blog.bigsmoke.us/wp-factory/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  I find myself quite enjoying the after-work because of the laid-back attitude of the guys. What&#8217;s worse: I&#8217;m actually looking forward to implementing some of the planned improvements. That&#8217;s strange. Maybe it&#8217;s the complete lack of hysterics about the shape of a particular icon (“I want the trash can back!”)  or the phrasing of a particular sentence (“How could this have happened?! You should have quadruple-checked this first! Aaarggh! Now our company will die because we look unprofessional!”). Some people are just more fun to work <del>for</del><ins>with</ins> than other people I guess.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigsmoke.us/2010/11/09/www.aihato.nl/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MediaWiki thumb.php and rewrite rules</title>
		<link>http://blog.bigsmoke.us/2010/03/07/mediawiki-thumb.php-rewrite-rules</link>
		<comments>http://blog.bigsmoke.us/2010/03/07/mediawiki-thumb.php-rewrite-rules#comments</comments>
		<pubDate>Sun, 07 Mar 2010 18:40:26 +0000</pubDate>
		<dc:creator>Rowan Rodrik</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[MediaWiki]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[thumbnail]]></category>

		<guid isPermaLink="false">http://blog.bigsmoke.us/?p=516</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>May, last year, I created an empty draft for this post, because, around that time, I had gone through quite some effort before I got thumbnails for foreign file repos working just right. Now, I&#8217;m taking a dive into my MediaWiki working dirs in preparation of the creation of a separate development environment, so it&#8217;s a good moment to rehash the past experience (almost as good as when I&#8217;d have done it right away).</p>

<p>This is how I configured the <a href="http://www.mediawiki.org/wiki/Manual:$wgForeignFileRepos">foreign file repo</a> to be able to use images uploaded to the English wiki from the Dutch wiki:</p>

<pre class="php"><span style="color: #0000ff;">$wgHashedUploadDirectory</span> = <span style="color: #000000; font-weight: bold;">false</span>;
&nbsp;
<span style="color: #0000ff;">$wgForeignFileRepos</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span>
    <span style="color: #ff0000;">'class'</span> =&gt; <span style="color: #ff0000;">'ForeignDBRepo'</span>,
    <span style="color: #ff0000;">'name'</span> =&gt; <span style="color: #ff0000;">'en'</span>,
    <span style="color: #ff0000;">'url'</span> =&gt; <span style="color: #ff0000;">&quot;http://wiki.hardwood-investments.net/media&quot;</span>,
    <span style="color: #ff0000;">'hashLevels'</span> =&gt; <span style="color: #cc66cc;">0</span>,
    <span style="color: #808080; font-style: italic;">//'thumbScriptUrl' =&gt; &quot;http://wiki.hardwood-investments.net/thumb.php&quot;,</span>
    <span style="color: #ff0000;">'transformVia404'</span> =&gt; <span style="color: #000000; font-weight: bold;">true</span>,<span style="color: #808080; font-style: italic;">//!$wgGenerateThumbnailOnParse,</span>
    <span style="color: #ff0000;">'dbType'</span> =&gt; <span style="color: #0000ff;">$wgDBtype</span>,
    <span style="color: #ff0000;">'dbServer'</span> =&gt; <span style="color: #0000ff;">$wgDBserver</span>,
    <span style="color: #ff0000;">'dbUser'</span> =&gt; <span style="color: #0000ff;">$wgDBuser</span>,
    <span style="color: #ff0000;">'dbPassword'</span> =&gt; <span style="color: #0000ff;">$wgDBpassword</span>,
    <span style="color: #ff0000;">'dbName'</span> =&gt; <span style="color: #ff0000;">'hardwood'</span>,
    <span style="color: #ff0000;">'tablePrefix'</span> =&gt; <span style="color: #ff0000;">'mw_'</span>,
    <span style="color: #ff0000;">'hasSharedCache'</span> =&gt; <span style="color: #000000; font-weight: bold;">false</span>,
    <span style="color: #ff0000;">'descBaseUrl'</span> =&gt; <span style="color: #ff0000;">'http://wiki.hardwood-investments.net/Image:'</span>,
    <span style="color: #ff0000;">'fetchDescription'</span> =&gt; <span style="color: #000000; font-weight: bold;">false</span>
<span style="color: #66cc66;">&#41;</span>;</pre>

<p>To make thumbnails be generated by <a href="http://www.mediawiki.org/wiki/Manual:Thumb.php"><tt>thumb.php</tt></a> on request I added the following to my <tt>.htaccess</tt> at the other end (and visa versa, because the Dutch wiki actually contains most of the images):</p>

<pre class="php">RewriteCond %<span style="color: #66cc66;">&#123;</span>REQUEST_FILENAME<span style="color: #66cc66;">&#125;</span> !-f
RewriteCond %<span style="color: #66cc66;">&#123;</span>REQUEST_FILENAME<span style="color: #66cc66;">&#125;</span> !-d
RewriteRule ^media/thumb/<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#91;</span>^/<span style="color: #66cc66;">&#93;</span>+<span style="color: #66cc66;">&#41;</span>/<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #cc66cc;">-9</span><span style="color: #66cc66;">&#93;</span>+<span style="color: #66cc66;">&#41;</span>px-.*$ /thumb.php?f=$<span style="color: #cc66cc;">1</span>&amp;width=$<span style="color: #cc66cc;">2</span> <span style="color: #66cc66;">&#91;</span>L,QSA<span style="color: #66cc66;">&#93;</span></pre>]]></content:encoded>
			<wfw:commentRss>http://blog.bigsmoke.us/2010/03/07/mediawiki-thumb.php-rewrite-rules/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>www.stichting-ecosafe.org</title>
		<link>http://blog.bigsmoke.us/2009/09/16/www.stichting-ecosafe.org</link>
		<comments>http://blog.bigsmoke.us/2009/09/16/www.stichting-ecosafe.org#comments</comments>
		<pubDate>Wed, 16 Sep 2009 10:19:56 +0000</pubDate>
		<dc:creator>Rowan Rodrik</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[406]]></category>
		<category><![CDATA[AHAH]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[mod_include]]></category>
		<category><![CDATA[mod_negotiation]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SSI]]></category>
		<category><![CDATA[WWW]]></category>
		<category><![CDATA[www.stichting-ecosafe.org]]></category>
		<category><![CDATA[XHTML]]></category>

		<guid isPermaLink="false">http://blog.bigsmoke.us/?p=683</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>Stichting EcoSafe is a Dutch foundation for the safe-keeping of the funds that are necessary for the maintenance of hardwood plantations. In July of 2006, together with Johan Ockels, I created a website for the Foundation. Johan was responsible for the organization of the whole process. This went very smooth and the website ended up being an emblem of simplicity and clarity. That&#8217;s why I wanted to blog a bit about it now, even though there are a few things that I&#8217;d probably end up doing different if I were to start from scratch. [There's actually a disturbing number of things for which this is true, I'm coming to notice.]</p>

<table class="invisible" style="border: none;"><tr><td valign="top">
<div id="attachment_708" class="wp-caption alignnone" style="width: 310px"><a rel="lightbox-screen" href="http://blog.bigsmoke.us/uploads/2009/07/ecosafe-index-en.png"><img src="http://blog.bigsmoke.us/uploads/2009/07/ecosafe-index-en-300x206.png" alt="The Welcome page of the EcoSafe website" title="www.stichting-ecosafe.org/index.en" width="300" height="206" class="size-medium wp-image-708" /></a><p class="wp-caption-text">The Welcome page of the EcoSafe website</p></div>
</td><td valign="top">
<div id="attachment_794" class="wp-caption alignnone" style="width: 310px"><a rel="lightbox-screen" href="http://blog.bigsmoke.us/uploads/2009/09/ecosafe-plantations-en.png"><img src="http://blog.bigsmoke.us/uploads/2009/09/ecosafe-plantations-en-300x206.png" alt="EcoSafe page for plantations" title="www.stichting-ecosafe.org/plantations.en" width="300" height="206" class="size-medium wp-image-794" /></a><p class="wp-caption-text">EcoSafe page for plantations</p></div>
</td><td valign="top">
<div id="attachment_810" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.bigsmoke.us/uploads/2009/09/ecosafe-cost-structure-en.png"><img src="http://blog.bigsmoke.us/wp-factory/../uploads/2009/09/ecosafe-cost-structure-en-300x205.png" alt="EcoSafe cost structure" title="www.stichting-ecosafe.org/cost-structure.en" width="300" height="205" class="size-medium wp-image-810" /></a><p class="wp-caption-text">EcoSafe cost structure</p></div>
</td></tr></table>

<h2 id="file-structure">File structure</h2>

<p>Like with most websites, I started with creating an SVN repo so that I wouldn&#8217;t have to be afraid of ever losing anything.</p>

<p>The file structure was pretty standard:</p>

<ul>
<li>a <tt>css</tt> dir for stylesheets;</li>
<li><tt>img</tt> for images;</li>
<li><tt>inc</tt> for shared PHP and mod_include stuff and for AJAX partials;</li>
<li><tt>jot</tt> for to-do&#8217;s and other notes;</li>
<li>and <tt>js</tt> for JavaScript files and libraries.</li>
</ul>

<h3>Possible file structure improvements</h3>

<p>If I were to redesign this file structure, I&#8217;d collapse <tt>css</tt>, <tt>img</tt> and <tt>js</tt> into one directory called <tt>layout</tt>, because these are typically things that require the same <tt>robots.txt</tt> and caching policy. Also, it is meaningless to organize things by file extension. If you want to sort something by file extension, use <q><tt>ls -X</tt></q> (or <q><tt>ls --sort=extension</tt></q> if you&#8217;re on GNU).</p>


<h2 id="ssi">Server-side includes</h2>

<p>The site would be so simple that I felt that any type of CMS or content transformation would be completely unnecessary. Instead, I decided to rely on Apache&#8217;s <a href="http://httpd.apache.org/docs/1.3/mod/mod_include.html">mod_include</a> and just use a few partials for repeating page elements such as the left sidebar containing the logo and the menu.</p>

<p>Also, because I didn&#8217;t need to transform the HTML files, I decided I could use good ol&#8217; HTML 4 instead of XHTML 1 (which I&#8217;d have to send to the browser with the wrong mime-type anyway).</p>

<p>This is the HTML for <tt>contact.nl.shtml</tt>:</p>

<pre class="php">&lt;!DOCTYPE html PUBLIC <span style="color: #ff0000;">&quot;-//W3C//DTD HTML 4.01//EN&quot;</span> <span style="color: #ff0000;">&quot;http://www.w3.org/TR/html4/loose.dtd&quot;</span>&gt;
&nbsp;
&lt;html lang=<span style="color: #ff0000;">&quot;en&quot;</span>&gt;
  &lt;head&gt;
    &lt;title&gt;Contact EcoSafe&lt;/title&gt;
&nbsp;
    &lt;meta http-equiv=<span style="color: #ff0000;">&quot;Content-Type&quot;</span> content=<span style="color: #ff0000;">&quot;text/html; charset=UTF-8&quot;</span> /&gt;
&nbsp;
    &lt;link rel=<span style="color: #ff0000;">&quot;stylesheet&quot;</span> type=<span style="color: #ff0000;">&quot;text/css&quot;</span> href=<span style="color: #ff0000;">&quot;/css/style.css&quot;</span>&gt;&lt;/link&gt;
  &lt;/head&gt;
&nbsp;
  &lt;body&gt;
    &lt;!--<span style="color: #808080; font-style: italic;">#include virtual=&quot;/inc/left-side.en.html&quot;--&gt;</span>
&nbsp;
    &lt;!--<span style="color: #808080; font-style: italic;">#include virtual=&quot;/inc/alt-lang.phtml&quot;--&gt;</span>
&nbsp;
    &lt;div id=<span style="color: #ff0000;">&quot;content&quot;</span>&gt;
      &lt;h1&gt;Contact&lt;/h1&gt;
&nbsp;
      &lt;p&gt;Your email to EcoSafe kan be sent to the following address:
      &lt;a href=<span style="color: #ff0000;">&quot;mailto:service@stichting-ecosafe.org&quot;</span>&gt;service@stichting-ecosafe.org&lt;/a&gt;.
      Or, alternatively, you can fax us at <span style="color: #cc66cc;">+31</span> <span style="color: #cc66cc;">50</span> - <span style="color: #cc66cc;">309</span> <span style="color: #cc66cc;">66</span> <span style="color: #cc66cc;">58</span>.&lt;/p&gt;
&nbsp;
      &lt;h2&gt;About this website&lt;/h2&gt;
&nbsp;
      &lt;p&gt;For comments and/or suggestions concerning this website,
      you can direct an email message at:
      &lt;a href=<span style="color: #ff0000;">&quot;mailto:webmaster@stichting-ecosafe.org&quot;</span>&gt;webmaster@stichting-ecosafe.org&lt;/a&gt;.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>

<div id="attachment_788" class="wp-caption alignright" style="width: 197px"><img src="http://blog.bigsmoke.us/uploads/2009/09/ecosafe-alt-language.png" alt="Alternative language selection" title="www.stichting-ecosafe.org alternative language selection" width="187" height="38" class="size-full wp-image-788" /><p class="wp-caption-text">Alternative language selection</p></div>

<p>I use <tt>&lt;!--#include virtual--&gt;</tt> to include the repeating parts. <tt>&lt;!--#include virtual--&gt;</tt> has several advantages over <tt>&lt;!--#include file--&gt;</tt> in that it allows for content-negotiation, execution of dynamic content etc., but here the only place were it holds an advantage is in the inclusion of <tt>/inc/alt-lang.phtml</tt>. <tt>alt-lang.phtml</tt> is a messy PHP script that figures out which language variants of a page are available and displays a selection of alternative language versions (variants with a language different from the current).</p>

<h3>SSI and caching</h3>

<p>Without the <A href="http://httpd.apache.org/docs/1.3/mod/mod_include.html#xbithack">XBitHack directive</a> set to <tt>full</tt>, all content handled by <tt>mod_include</tt> is sent without a <tt>Last-Modified</tt> header. However, I don&#8217;t want to use <tt>XBitHack</tt> at all, because I don&#8217;t want just any executable file to be handled by <tt>mod_include</tt>; that just too much of a … hack.</p>

<p>If I were to do something similar now, I&#8217;d use some kind of (sed) substitution to pre-process the includes locally so that more of what I end up uploading is simple static content. The dynamic part of the included PHP script, I would simply replace with JavaScript.</p>

<h2 id="visual">Visual design</h2>

<p>As you can see in the HTML example, there&#8217;s hardly anything layout oriented in the HTML source. This is good, and means that I have to touch only the CSS for most minor and major lay-out modifications. (It is a pipe-dream to think that you only need to change the CSS to make the same HTML page look however you want as long as that HTML is rich enough in meaning, but for a site with pages of such simple structure, it&#8217;s a dream that comes pretty close to reality.)</p>

<p>I&#8217;m not much of a designer, but I think design is overrated anyway. Actually, I think that most website suffer from too much design.</p>

<div id="attachment_692" class="wp-caption alignright" style="width: 275px"><img src="http://blog.bigsmoke.us/uploads/2009/07/ecosafe-logo.jpg" alt="The EcoSafe logo" title="EcoSafe logo" width="265" height="217" class="size-full wp-image-692" /><p class="wp-caption-text">The EcoSafe logo</p></div>

<p>To start the design, I got a logo made by <a href="http://wiki.hardwood-investments.net/Huite_Zijlstra">Huite Zijlstra</a>. Because the logo was pretty big and didn&#8217;t look good scaled down, I decided to put it at the left of the content area instead of at the top. This would still leave enough room for the menu (which actually takes less space horizontally than the logo).</p>

<h3 id="colors">Colors</h3>

<p>For the color scheme, I just picked a few colors from the logo. As always, the base of the scheme would be black text on a white background for maximum readability. The print version hardly uses any colors.</p>

<pre class="css"><span style="color: #a1a100;">@media screen {</span>
body            <span style="color: #66cc66;">&#123;</span> <span style="color: #000000; font-weight: bold;">background-color</span>: <span style="color: #993333;">white</span>;  <span style="color: #66cc66;">&#125;</span>
*               <span style="color: #66cc66;">&#123;</span> <span style="color: #000000; font-weight: bold;">color</span>: <span style="color: #000000; font-weight: bold;">black</span>;             <span style="color: #66cc66;">&#125;</span>
a<span style="color: #3333ff;">:link </span>         <span style="color: #66cc66;">&#123;</span> <span style="color: #000000; font-weight: bold;">color</span>: #<span style="color: #cc66cc;">585</span>;              <span style="color: #66cc66;">&#125;</span>
h1              <span style="color: #66cc66;">&#123;</span> <span style="color: #000000; font-weight: bold;">color</span>: #<span style="color: #cc66cc;">880</span>;              <span style="color: #66cc66;">&#125;</span>
h2              <span style="color: #66cc66;">&#123;</span> <span style="color: #000000; font-weight: bold;">color</span>: #<span style="color: #cc66cc;">888</span>;              <span style="color: #66cc66;">&#125;</span>
strong          <span style="color: #66cc66;">&#123;</span> <span style="color: #000000; font-weight: bold;">color</span>: #a62;              <span style="color: #66cc66;">&#125;</span>
#menu li a      <span style="color: #66cc66;">&#123;</span> <span style="color: #000000; font-weight: bold;">color</span>: #<span style="color: #cc66cc;">660</span>;              <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>

<h3 id="underlines">Underlines</h3>

<p>I wanted an underline below the level 1 and 2 headings. Because I didn&#8217;t like the effect of <tt>text-decoration:underline</tt> (too thick for <tt>&lt;h2&gt;</tt>s, too dark for <tt>&lt;h1&gt;</tt>s and different from browser to browser) and because <tt>border-bottom</tt> was set too far from the text, I made two simple PNG images that I could <tt>repeat-x</tt> along the bottom edge.</p>

<pre class="css"><span style="color: #a1a100;">@media screen {</span>
h1 <span style="color: #66cc66;">&#123;</span> <span style="color: #000000; font-weight: bold;">background</span>: <span style="color: #993333;">url</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/img/h1-border-bottom.png'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #000000; font-weight: bold;">bottom</span> <span style="color: #000000; font-weight: bold;">left</span> <span style="color: #993333;">repeat-x</span>; <span style="color: #66cc66;">&#125;</span>
h2 <span style="color: #66cc66;">&#123;</span> <span style="color: #000000; font-weight: bold;">background</span>: <span style="color: #993333;">url</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/img/hx-border-bottom.png'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #000000; font-weight: bold;">bottom</span> <span style="color: #000000; font-weight: bold;">left</span> <span style="color: #993333;">repeat-x</span>; <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>

<h3 id="menu">Menu</h3>

<p>The menu is very simple. The markup is part of <tt>inc/left-side.en.html</tt> for the English version and <tt>inc/left-side.nl.html</tt> for the Dutch version:</p>

<pre class="bash">cat inc/left-side.en.html</pre>
<pre class="php">&lt;div id=<span style="color: #ff0000;">&quot;left&quot;</span> lang=<span style="color: #ff0000;">&quot;en&quot;</span>&gt;
  &lt;a <span style="color: #000000; font-weight: bold;">class</span>=<span style="color: #ff0000;">&quot;logo&quot;</span> href=<span style="color: #ff0000;">&quot;/index.en&quot;</span>&gt;&lt;img <span style="color: #000000; font-weight: bold;">class</span>=<span style="color: #ff0000;">&quot;logo&quot;</span> alt=<span style="color: #ff0000;">&quot;[Logo]&quot;</span> src=<span style="color: #ff0000;">&quot;/img/logo.jpg&quot;</span>&gt;&lt;/img&gt;&lt;/a&gt;
&nbsp;
  &lt;ul id=<span style="color: #ff0000;">&quot;menu&quot;</span> <span style="color: #000000; font-weight: bold;">class</span>=<span style="color: #ff0000;">&quot;menu&quot;</span>&gt;
    &lt;li&gt;&lt;a href=<span style="color: #ff0000;">&quot;/index.en&quot;</span> rel=<span style="color: #ff0000;">&quot;start&quot;</span>&gt;Start page&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=<span style="color: #ff0000;">&quot;/plantations.en&quot;</span>&gt;For plantations&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=<span style="color: #ff0000;">&quot;/investors.en&quot;</span>&gt;For investors&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=<span style="color: #ff0000;">&quot;/history.en&quot;</span>&gt;History&lt;/a&gt;&lt;/li&gt;
    &lt;!--&lt;li&gt;&lt;a href=<span style="color: #ff0000;">&quot;/goals&quot;</span>&gt;Goals&lt;/a&gt;&lt;/li&gt;--&gt;
    &lt;li&gt;&lt;a href=<span style="color: #ff0000;">&quot;/methods.en&quot;</span>&gt;How it works&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=<span style="color: #ff0000;">&quot;/cost-structure.en&quot;</span>&gt;Cost structure&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=<span style="color: #ff0000;">&quot;/cost-calculator.en&quot;</span>&gt;Cost calculator&lt;/a&gt;&lt;/li&gt;
    &lt;!--&lt;li&gt;&lt;a href=<span style="color: #ff0000;">&quot;/clients.en&quot;</span>&gt;Clients&lt;/a&gt;&lt;/li&gt;--&gt;
    &lt;li&gt;&lt;a href=<span style="color: #ff0000;">&quot;/contact.en&quot;</span>&gt;Contact&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&nbsp;
&lt;script type=<span style="color: #ff0000;">&quot;text/javascript&quot;</span> src=<span style="color: #ff0000;">&quot;/js/menu.js&quot;</span>&gt;&lt;/script&gt;</pre>

<div id="attachment_710" class="wp-caption alignright" style="width: 270px"><img src="http://blog.bigsmoke.us/uploads/2009/07/ecosafe-menu-en.png" alt="The EcoSafe menu (in English)" title="EcoSafe menu EN" width="260" height="438" class="size-full wp-image-710" /><p class="wp-caption-text">The EcoSafe menu (in English)</p></div>

<p>As is customary, I started by removing all the default list styles and made the anchors behave as block-level elements. I used the big O from the logo for bullets in the list (using <tt>background-image</tt> instead of <tt>list-style-image</tt> because the latter gives unpredictable cross-browser results and doesn&#8217;t make the bullet clickable).</p>

<pre class="css"><span style="color: #cc00cc;">#menu <span style="color: #66cc66;">&#123;</span></span>
  <span style="color: #000000; font-weight: bold;">margin-top</span>: 2em;
  <span style="color: #000000; font-weight: bold;">margin-left</span>: 2em;
  <span style="color: #000000; font-weight: bold;">list-style-type</span>: <span style="color: #993333;">none</span>;
  <span style="color: #000000; font-weight: bold;">padding</span>: <span style="color: #cc66cc;">0</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
#menu li <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">margin</span>: <span style="color: #cc66cc;">0</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
#menu li a <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">display</span>: <span style="color: #993333;">block</span>;
  <span style="color: #000000; font-weight: bold;">background-image</span>: <span style="color: #993333;">url</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/img/o-21x16.png'</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #000000; font-weight: bold;">background-position</span>: <span style="color: #000000; font-weight: bold;">top</span> <span style="color: #000000; font-weight: bold;">left</span>;
  <span style="color: #000000; font-weight: bold;">background-repeat</span>: <span style="color: #993333;">no-repeat</span>;
  <span style="color: #000000; font-weight: bold;">padding-left</span>: 30px;
  <span style="color: #000000; font-weight: bold;">text-decoration</span>: <span style="color: #993333;">none</span>;
  <span style="color: #000000; font-weight: bold;">font-family</span>: <span style="color: #993333;">sans-serif</span>;
  <span style="color: #000000; font-weight: bold;">font-weight</span>: <span style="color: #993333;">bold</span>;
  <span style="color: #000000; font-weight: bold;">color</span>: #<span style="color: #cc66cc;">660</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
#menu li a:hover,
#menu li<span style="color: #6666ff;">.active </span>a <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">background-image</span>: <span style="color: #993333;">url</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/img/oSafe-21x16.png'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
#menu a<span style="color: #3333ff;">:hover </span><span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">color</span>: #<span style="color: #cc66cc;">787800</span>;
<span style="color: #66cc66;">&#125;</span></pre>

<h4>JavaScript menu item activation</h4>

<p>To add the <tt>active</tt> class to the currently active list item (<tt>&lt;li&gt;</tt>), I used a client-side solution using JavaScript. After all, it&#8217;s proper use of JavaScript to enhance your user interface with it (as long as, as many would say, it isn&#8217;t <em>required</em> for the UI to function (as it is in the Cost Calculator)).</p>

<pre class="javascript"><span style="color: #009900; font-style: italic;">// menu.js</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> menu = document.<span style="color: #006600;">getElementById</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'menu'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #003366; font-weight: bold;">var</span> anchors = menu.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #003366; font-weight: bold;">var</span> locationHref = window.<span style="color: #006600;">location</span>.<span style="color: #006600;">pathname</span>.<span style="color: #006600;">toString</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
  
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span>i = anchors.<span style="color: #006600;">length</span> - <span style="color: #CC0000;">1</span>; i &gt;= <span style="color: #CC0000;">0</span>; i--<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  a = anchors<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>;
  aHref = a.<span style="color: #006600;">href</span>;
    
  <span style="color: #009900; font-style: italic;">// Does this menu item link to the current page?</span>
  <span style="color: #009900; font-style: italic;">// We find out by looking if the window location contains the URL in the anchor</span>
  <span style="color: #009900; font-style: italic;">// or the other way arround. The reason to look at both is content-negotiation.</span>
  <span style="color: #009900; font-style: italic;">// It's also true if the location is just '/' and we're looking at the anchor of</span>
  <span style="color: #009900; font-style: italic;">// the 'start' page.</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #66cc66;">&#40;</span>locationHref === <span style="color: #3366CC;">'/'</span> &amp;&amp; a.<span style="color: #006600;">rel</span> === <span style="color: #3366CC;">'start'</span><span style="color: #66cc66;">&#41;</span> ||
       <span style="color: #66cc66;">&#40;</span>locationHref !== <span style="color: #3366CC;">'/'</span> &amp;&amp; <span style="color: #66cc66;">&#40;</span> locationHref.<span style="color: #006600;">indexOf</span><span style="color: #66cc66;">&#40;</span>aHref<span style="color: #66cc66;">&#41;</span> !== <span style="color: #CC0000;">-1</span> ||
                                  aHref.<span style="color: #006600;">indexOf</span><span style="color: #66cc66;">&#40;</span>locationHref<span style="color: #66cc66;">&#41;</span> !== <span style="color: #CC0000;">-1</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    a.<span style="color: #006600;">parentNode</span>.<span style="color: #006600;">className</span> = <span style="color: #3366CC;">'active'</span>;
    <span style="color: #000066; font-weight: bold;">break</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>

<p>I actually just fixed a long-standing bug that was caused by me not being able to fully rely on HTTP language negotiation for the selection of the appropriate language variant, which made me change all links from being language-neutral to including the language in the link target (e.g.: <tt>http:///history</tt> became <tt>http:///history.en</tt> and <tt>http:///history.nl</tt>), the problem with this being that, instead of being able to link to link to <tt>http:///</tt> (<tt>http://www.stichting-ecosafe.org/</tt>), I had to link to <tt>http:///index.en</tt> or <tt>http:///index.nl</tt>, making it more difficult to detect the active anchor if we&#8217;re requesting the home page through <tt>http:///</tt> instead of on of its language-specific URLs.</p>

<p>The JavaScript rested on the assumption that by reverse iterating through all the anchors in the menu and thus processing the link to <tt>http:///</tt> as last, I&#8217;d know that I had struck the home page and wouldn&#8217;t need to worry that <em>any of the links</em> contain a slash. (I don&#8217;t know if I intended it to work this way, but it sure seems to me now that the only way this could ever have worked was as an apparent side-effect of the looping order; the SVN logs seem to agree.)</p>

<p>I could have solved this by redirecting all requests for <tt>http:///</tt> to the appropriate variant. Maybe I should have (to avoid duplicate content). Instead I chose to add a <tt>rel="start"</tt> attribute to the links to the home page, as can be deduced from the JavaScript above. (To resolve the duplicate content issue, I could also add a <a href="http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html">canonical link</a> to the header of the two language variants.)</p>

<p>Anyway, all this brings me to the messy subject of content negotiation.</p>

<h2 id="content-negotiation">Content and language negotiation</h2>

<p>The EcoSafe website would be bi-lingual (English and Dutch) from the onset. Initially, I wanted to use language negotiation to the extend of having completely language-neutral URLs. For example: <q><tt>http:///cost-calculator</tt></q> instead of <q><tt>http:///cost-calculator.en</tt></q> and <q><tt>http:///cost-calculator.nl</tt></q>. In the end, you can make this work properly in the browser with the help of a cookie, but it&#8217;s still a pipe-dream because nothing else will work if you do not also offer another navigational path to the different variants. Maybe, we&#8217;ll revisit this topic for a later experiment.</p>

<p>Content-type negotiation is almost effortless with Apache thanks to <tt><a href="http://httpd.apache.org/docs/1.3/mod/mod_negotiation.html">mod_negotiation</a></tt>. If, like me, you despise to have <tt>.html</tt>, <tt>.htm</tt>, <tt>.xhtml</tt>, <tt>.phtml</tt>, <tt>.pxhtml</tt>. <tt>.sxhtml</tt>, <tt>.php</tt>, <tt>.xml</tt> in your URL (I actually used all of these at some time or other), you only have to make sure that <tt>MultiViews</tt> is in your options.</p>

<p>I&#8217;ve configured SSI by means of the following instead of a “magic mime-type”:</p>

<pre class="apache"><span style="color: #00007f;">AddType</span>         text/html       .shtml
<span style="color: #00007f;">AddHandler</span>      server-parsed   .shtml
<span style="color: #00007f;">AddCharset</span>      UTF<span style="color: #ff0000;">-8</span>           .shtml
AddOutputFilter <span style="color: #0000ff;">Includes</span>        .shtml</pre>

<p>For PHP I couldn&#8217;t do the same because my web host was still at Apache 1.3. Otherwise, the following should have worked equally well for PHP:</p>

<pre class="apache"><span style="color: #adadad; font-style: italic;"># This doesn't work with Apache 1.3</span>
<span style="color: #00007f;">AddType</span>        text/html       .phtml
<span style="color: #00007f;">AddHandler</span>     php-<span style="color: #00007f;">script</span>      .phtml
<span style="color: #00007f;">AddCharset</span>     UTF<span style="color: #ff0000;">-8</span>           .phtml</pre>

<p>Configuring language priority is easy with Apache:</p>

<h3>Integrating PHP and SSI</h3>

<p>The integration of PHP with all the weirdness that I had configured and created around SSI took some figuring out. Luckily, PHP offers a <a href="http://www.php.net/virtual"><tt>virtual()</tt></a> function that works roughly the same as <tt>mod_include's</tt> <tt>&lt;!--#include virtual--&gt;</tt>. Here&#8217;s an example:</p>

<pre class="php">&lt;body&gt;
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <a href="http://www.php.net/virtual"><span style="color: #000066;">virtual</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'/inc/left-side.en.html'</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #0000ff;">$uri</span> = <span style="color: #ff0000;">'/cost-calculator.en.phtml'</span>; <span style="color: #b1b100;">include</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'inc/alt-lang.phtml'</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #000000; font-weight: bold;">?&gt;</span></pre>

<p>In retrospect, it&#8217;s pretty much bullshit to use it. I could have just as well <tt>require()</tt>d the partials (which I actually did for the alternate language selection), but I probably started out using virtual on a more generic URL without language and content-type selection in it.</p>

<h3>406 handling</h3>

<p>Because I deployed on Apache 1.3 and the <tt><a href="http://httpd.apache.org/docs/2.0/mod/mod_negotiation.html#forcelanguagepriority">ForceLanguagePriority</a></tt> directive was only introduced with Apache 2.0.30, I had to write an ugly hack to avoid visitors getting 406 errors. To that end, I added a 406 handler to my <tt>.htaccess</tt> file:</p>

<pre class="apache"><span style="color: #00007f;">LanguagePriority</span> en nl
ForceLanguagePriority Prefer Fallback <span style="color: #adadad; font-style: italic;"># This doesn't work with 1.3</span>
&nbsp;
<span style="color: #00007f;">ErrorDocument</span> <span style="color: #ff0000;">406</span> /error<span style="color: #ff0000;">-406</span>.php <span style="color: #adadad; font-style: italic;"># Luckily, this does </span></pre>

<p><tt>error-406.php</tt> is a PHP file that figures out the available variants based on <tt>$_SERVER['REQUEST_URI']</tt>. Then, it simply picks the first one (which works because, accidentally, that&#8217;s the one I&#8217;ve given priority using the <tt><a href="http://httpd.apache.org/docs/1.3/mod/mod_negotiation.html#languagepriority">LanguagePriority</a></tt> directive as well), outputs a 200 OK header instead of the 406, and <tt>virtual()</tt>s the file of the variant. The code looks somewhat like this:</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<a href="http://www.php.net/chdir"><span style="color: #000066;">chdir</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$_SERVER</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'DOCUMENT_ROOT'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$filenames</span> = <a href="http://www.php.net/glob"><span style="color: #000066;">glob</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/basename"><span style="color: #000066;">basename</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$_SERVER</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'REQUEST_URI'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">&quot;.*&quot;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #0000ff;">$filename</span> = <span style="color: #0000ff;">$filenames</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span>;
&nbsp;
<a href="http://www.php.net/apache_setenv"><span style="color: #000066;">apache_setenv</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'DOCUMENT_URI'</span>, <span style="color: #ff0000;">&quot;/$filename&quot;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<a href="http://www.php.net/header"><span style="color: #000066;">header</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'HTTP/1.1 200 OK'</span><span style="color: #66cc66;">&#41;</span>;
<a href="http://www.php.net/virtual"><span style="color: #000066;">virtual</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;$filename&quot;</span><span style="color: #66cc66;">&#41;</span>;</pre>

<div id="attachment_807" class="wp-caption alignright" style="width: 310px"><a rel="lightbox-ecosafe" href="http://blog.bigsmoke.us/uploads/2009/09/ecosafe-cost-calculator.png"><img src="http://blog.bigsmoke.us/uploads/2009/09/ecosafe-cost-calculator-300x137.png" alt="EcoSafe Cost Calculator" title="www.stichting-ecosafe.org/cost-calculator" width="300" height="137" class="size-medium wp-image-807" /></a><p class="wp-caption-text">EcoSafe Cost Calculator</p></div>

<div id="attachment_808" class="wp-caption alignright" style="width: 194px"><a href="http://blog.bigsmoke.us/uploads/2009/09/ecosafe-cost-calculation.png"><img src="http://blog.bigsmoke.us/uploads/2009/09/ecosafe-cost-calculation-184x300.png" alt="EcoSafe Cost Calculator results" title="EcoSafe cost calculation" width="184" height="300" class="size-medium wp-image-808" /></a><p class="wp-caption-text">EcoSafe Cost Calculator results</p></div>

<h2>The Cost Calculator</h2>

<p>The EcoSafe Cost Calculator is some of the least neatly contained and most procedurally oriented PHP code I&#8217;ve ever produced while knowing full well what I was doing. It does almost everything it does in global scope. Yet, it does it well.</p>

<p>The thing is designed as a dynamic web page rather than a web application. What I mean by this is that it&#8217;s simply two pages (one for English and one for Dutch) using PHP among a number of pages using SSI. In an application, it&#8217;s usual to have just one ‘view’ that is the same for all languages, but here I chose to put the different language versions in different language pages and then include everything reusable (and language-neutral) from within these files.</p>

<p>Most of the actual processing and calculating is done in <tt>inc/costs-functions.php</tt>.  (The part about gotos is a joke. (Labeled blocks would have been quite sufficient. <img src='http://blog.bigsmoke.us/wp-factory/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ))</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #808080; font-style: italic;"># costs-functions.php - Stuff that's includes by cost-calculator.{nl,en}.phtml</span>
<span style="color: #808080; font-style: italic;">/**
 * Just remember that this code was never meant to be general purpose or anything.
 * So, relaxeeee and keep your OO-axe burried where it belongs.
 * Oh, if only PHP would support GOTO's ... Sigh ...
 */</span></pre>

<p>The rest of the file is just a whole lot of processing of form data and turning it into something that can be easily traversed for display to the user. There are even the function calls without arguments doing all their work on globals. These are actually only added to make it clearer <em>em</em> a piece of code is doing. And—I must say—after a few years it&#8217;s still remarkably clear to me what each part of the code is doing. There&#8217;s no deep, confusing nesting structures or anything. There&#8217;s just a whole lot of very simple code.</p>

<h3>Some simple AHAH increases form interactivity</h3>

<p>Users of the calculator can add any number of plantings and locations. When the user decides to add a planting or a location, the <tt>onClick</tt> event triggers the execution of <tt>addExtraPlanting()</tt> or <tt>addExtraLocation()</tt>. Here&#8217;s how <tt>addExtraPlanting()</tt> looks:</p>

<pre class="javascript"><span style="color: #003366; font-weight: bold;">function</span> addExtraPlanting<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  lang = document.<span style="color: #006600;">documentElement</span>.<span style="color: #006600;">lang</span>;
&nbsp;
  <span style="color: #003366; font-weight: bold;">new</span> Ajax.<span style="color: #006600;">Updater</span><span style="color: #66cc66;">&#40;</span>
    <span style="color: #3366CC;">'plantings'</span>, <span style="color: #3366CC;">'/inc/planting.'</span> + lang, <span style="color: #66cc66;">&#123;</span>
      method: <span style="color: #3366CC;">'get'</span>,
      insertion: Insertion.<span style="color: #006600;">Bottom</span>
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre>

<p><a href="http://api.prototypejs.org/ajax/ajax/updater.html"><tt>Ajax.Updater</tt></a> comes from the <a href="http://www.prototypejs.org/">Prototype JavaScript framework</a>.</p>

<p>Here&#8217;s what <tt>inc/planting.en.phtml</tt> looks like. The same file is also included in a loop to rebuild the form&#8217;s state after submitting.</p>

<pre class="php">&lt;li&gt;
  &lt;input name=<span style="color: #ff0000;">&quot;num_hectares[]&quot;</span> type=<span style="color: #ff0000;">&quot;text&quot;</span> size=<span style="color: #ff0000;">&quot;5&quot;</span> value=<span style="color: #ff0000;">&quot;&lt;?php echo $num_hectares ?&gt;&quot;</span> /&gt;
&nbsp;
  hectares have been planted in
&nbsp;
  &lt;select name=<span style="color: #ff0000;">&quot;plant_years[]&quot;</span>&gt;&lt;?php <span style="color: #b1b100;">require</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'planting_options.php'</span><span style="color: #66cc66;">&#41;</span> ?&gt;&lt;/select&gt;
&nbsp;
  <span style="color: #66cc66;">&#40;</span>&lt;a title=<span style="color: #ff0000;">&quot;Remove this planting&quot;</span> href=<span style="color: #ff0000;">&quot;#&quot;</span> onclick=<span style="color: #ff0000;">&quot;removePlanting(this); return false;&quot;</span>&gt;x&lt;/a&gt;<span style="color: #66cc66;">&#41;</span>
&lt;/li&gt;</pre>

<p>I think that I&#8217;ve gone into small enough detail by now to get to the conclusion. Also showing the contents of <tt>planting_options.php</tt> would be pushing it. Ah, well…</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> !<a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this_year</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #0000ff;">$this_year</span> = <a href="http://www.php.net/intval"><span style="color: #000066;">intval</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/date"><span style="color: #000066;">date</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Y'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> !<a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$plant_year</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #0000ff;">$plant_year</span> = <span style="color: #0000ff;">$this_year</span>;
&nbsp;
<span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$i</span> = <span style="color: #0000ff;">$this_year</span>; <span style="color: #0000ff;">$i</span> &gt;= <span style="color: #0000ff;">$this_year</span> - <span style="color: #cc66cc;">20</span>; <span style="color: #0000ff;">$i</span>--<span style="color: #66cc66;">&#41;</span>
  <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;&lt;option&quot;</span> . <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$i</span> == <span style="color: #0000ff;">$plant_year</span> ? <span style="color: #ff0000;">&quot; selected='1'&quot;</span> : <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">&#41;</span> . <span style="color: #ff0000;">&quot;&gt;$i&lt;/option&gt;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;</pre>

<p>(Yesterday, I couldn&#8217;t resist the temptation of turning this into a simple file to <tt>require()</tt> instead of the function definition it was. I think it&#8217;s funny to refactor something to <em>remove</em> encapsulation.)</p>

<h2>Conclusion</h2>

<p>As is usual when looking at old code, I see many things that I&#8217;d do (even just a little) different today, but I saw a surprising number of solutions that I actually still like now that I see them back after three years. Removing some of the remaining warts probably won&#8217;t do much good besides the masturbatory satisfaction it could give me. (It&#8217;s likely that the website won&#8217;t live much longer, making such extra attention very undeserved.) But, nevertheless, I&#8217;ve enjoyed blogging about it now to recoup the whole experience and to at least <em>look</em> at what I&#8217;d do different now and what I learned in the meantime.</p>

<h2>Some links</h2>

<ul>
  <li><a href="http://www.w3.org/TR/html401/types.html#type-links">The HTML spec. on <cite>Link types</cite></a></li>
  <li><a href="http://www.stichting-ecosafe.org/">The EcoSafe website</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://blog.bigsmoke.us/2009/09/16/www.stichting-ecosafe.org/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP fgetcsv() behavior on empty lines</title>
		<link>http://blog.bigsmoke.us/2009/09/05/php-fgetcsv</link>
		<comments>http://blog.bigsmoke.us/2009/09/05/php-fgetcsv#comments</comments>
		<pubDate>Sat, 05 Sep 2009 08:55:13 +0000</pubDate>
		<dc:creator>Rowan Rodrik</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[CSV]]></category>
		<category><![CDATA[fgetcsv]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.bigsmoke.us/?p=759</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>The PHP documentation for <a href="http://ww.php.net/fgetcsv"><tt>fgetcsv()</tt></a> states that <q cite="http://ww.php.net/fgetcsv">A blank line in a CSV file will be returned as an array comprising a single null field, and will not be treated as an error. </q> Here&#8217;s a quick demonstration of this behavior.</p>

<p><tt>fgetcsv.php</tt>:</p>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #b1b100;">while</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$fields</span> = <a href="http://www.php.net/fgetcsv"><span style="color: #000066;">fgetcsv</span></a><span style="color: #66cc66;">&#40;</span>STDIN, <span style="color: #cc66cc;">0</span>, <span style="color: #ff0000;">';'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
  <a href="http://www.php.net/print_r"><span style="color: #000066;">print_r</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$fields</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<a href="http://www.php.net/exit"><span style="color: #000066;">exit</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>;</pre>

<p>Execute the script and feed it some CSV with empty lines:</p>

<pre class="bash">php -q fgetcsv.php
<span style="color: #ff0000;">&quot;Veld 1&quot;</span>;<span style="color: #ff0000;">&quot;Veld 2&quot;</span>;<span style="color: #ff0000;">&quot;Veld 3&quot;</span>;;<span style="color: #ff0000;">&quot;Veld 5&quot;</span>
&nbsp;
<span style="color: #ff0000;">&quot;Field 1&quot;</span>;;<span style="color: #ff0000;">&quot;Field 3&quot;</span>;<span style="color: #ff0000;">&quot;Field 4&quot;</span>;
;;;;
;<span style="color: #ff0000;">&quot;Campo 2&quot;</span>;;;<span style="color: #ff0000;">&quot;Campo 5&quot;</span></pre>

<p>After pressing <kbd>Ctrl+D</kbd>, I&#8217;m presented with the following output:</p>

<pre>
Array
(
    [0] => Veld 1
    [1] => Veld 2
    [2] => Veld 3
    [3] => 
    [4] => Veld 5
)
Array
(
    [0] => 
)
Array
(
    [0] => Field 1
    [1] => 
    [2] => Field 3
    [3] => Field 4
    [4] => 
)
Array
(
    [0] => 
    [1] => 
    [2] => 
    [3] => 
    [4] => 
)
Array
(
    [0] => 
    [1] => Campo 2
    [2] => 
    [3] => 
    [4] => Campo 5
)
Array
(
    [0] => 
)
</pre>

<p>This behaviour on empty lines is a little bit annoying if you want to test if the line is <tt>empty()</tt>:</p>

<pre class="php"><span style="color: #0000ff;">$a</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">null</span><span style="color: #66cc66;">&#41;</span>;
<a href="http://www.php.net/print_r"><span style="color: #000066;">print_r</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$a</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> <a href="http://www.php.net/empty"><span style="color: #000066;">empty</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$a</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
  <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">'$a is empty'</span>;
<span style="color: #b1b100;">else</span>
  <a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">'$a is not empty'</span>;
&nbsp;
<a href="http://www.php.net/echo"><span style="color: #000066;">echo</span></a> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>;</pre>

<p>This code will print:</p>

<pre>
Array
(
    [0] => 
)
$a is not empty
</pre>

<p>Hence, the following function:</p>

<pre class="php"><span style="color: #808080; font-style: italic;">/**
 * This function tests if the given array (as returned by fgetcsv())
 * is the result of an empty line in the CSV file.
 *
 * It does not work for lines that contain only delimiters.
 * From the POV of this function, these are simply records with
 * many empty fields.
 */</span>
<span style="color: #000000; font-weight: bold;">function</span> fgetcsv_empty_line<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$row_array</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #66cc66;">&#40;</span> !<a href="http://www.php.net/isset"><span style="color: #000066;">isset</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$row_array</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> and <a href="http://www.php.net/empty"><span style="color: #000066;">empty</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$row_array</span><span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre>

<p>Now, if I change the call to <tt>empty()</tt> in my test to a call to <tt>fgetcsv_empty_line()</tt>:</p>

<pre>
$a is empty
</pre>]]></content:encoded>
			<wfw:commentRss>http://blog.bigsmoke.us/2009/09/05/php-fgetcsv/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enforcing Drupal URL aliases</title>
		<link>http://blog.bigsmoke.us/2009/06/10/enforcing-drupal-url-aliases</link>
		<comments>http://blog.bigsmoke.us/2009/06/10/enforcing-drupal-url-aliases#comments</comments>
		<pubDate>Wed, 10 Jun 2009 12:09:07 +0000</pubDate>
		<dc:creator>Rowan Rodrik</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.bigsmoke.us/?p=574</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>I hate modules, especially <em>core modules</em>. I prefer code to be tightly integrated. I want it to work together. Is that too much to ask? In Drupal, most functionality has been stuffed in modules. There&#8217;s a <em>Locale</em> module, a <em>Content Translation</em> module and a <em>Path</em> module. What&#8217;s missing is a <em>Working Together</em> module.</p>

<p>For me, clean, meaningful URLs are a number one, two and three requirement for any website that I do. Drupal considers <tt>/node/54673</tt> to be a cool URL. I don&#8217;t. So, as a kind of afterthought, Drupal comes with the Path module. This module allows you to set URL aliases per node.</p>

<p>The problem is that there&#8217;s no concept of a canonical URL. The URL alias works, but so does the <tt>node/3242</tt> URL. Neither redirects to the other. In many cases this is not much of a problem (because regular visitors will not notice this) but for our current project it is.</p>

<p>We have a lot of blocks with URL dependent visibility settings. For example, for a section about investing we have a menu that is displayed on all URLs starting with <q><tt>/investing</tt></q>, such as <q><tt>/investing/projects</tt></q> and so on.</p>

<p>After editing a page, Drupal helpfully redirects the user to <tt>node/[nodenumber]</tt>. For us, this means that the menu is no longer displayed and even the theme will be wrong. (We use the <a href="http://drupal.org/project/sections">Sections</a> module to select a subtheme based on which section you&#8217;re in.)</p>

<h2>Global Redirect doesn&#8217;t work</h2>

<p>The <a href="http://drupal.org/project/globalredirect">Global Redirect</a> module promises to solve this by allowing you to redirect <tt>node/[nodenumber]</tt> URLs to their alias if available. It kinda does, in some circumstances.</p>

<p>Our Drupal website sports two languages: English (EN) and Dutch (NL). English is the default language (not the fallback language; we don&#8217;t use a fallback) and doesn&#8217;t use a prefix. Dutch uses the <tt>nl</tt> prefix. Two example URLs:</p>

<table>
<tr>
<th>URL alias</th>
<th>Generic URL</th>
</tr>

<tr>
<td><tt>http://www.example.com/investing/projects</tt></td>
<td><tt>http://www.example.com/node/288</tt></td>
</tr>

<tr>
<td><tt>http://www.example.com/nl/beleggen/projecten</tt></td>
<td><tt>http://www.example.com/nl/node/110</tt></td>
</tr>
</table>

<p>When  <tt>/node/288</tt> is requested, the client is correctly redirected to <tt>/investing/projects</tt>, but when <tt>/node/110</tt> is requested, no redirect takes place. It will take place when prefixing <tt>/nl</tt>, but this is completely useless since Drupal&#8217;s built-in actions such as edit don&#8217;t redirect using this prefix, and these actions were what we needed this module for in the first place.</p>

<h2>A very simple hack that does work</h2>

<p>We ended up tearing our hair out trying to fix Global Redirect until we decided that we could just delete the module and replace it with a RewriteRule and a simple PHP script.</p>

<h3>Modify: <tt>.htaccess</tt></h3>

<pre class="apache"><span style="color: #adadad; font-style: italic;"># Put this after RewriteBase and before Drupal's default rewrite rules</span>
<span style="color: #00007f;">RewriteRule</span> ^<span style="color: #66cc66;">&#40;</span>../<span style="color: #66cc66;">&#41;</span>?node/<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">0</span><span style="color: #ff0000;">-9</span><span style="color: #66cc66;">&#93;</span>+<span style="color: #66cc66;">&#41;</span>$ fixurl.php?nid=$<span style="color: #ff0000;">2</span> <span style="color: #66cc66;">&#91;</span>L<span style="color: #66cc66;">&#93;</span></pre>

<h3>Add: <tt>fixurl.php</tt></h3>

<pre class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #b1b100;">require_once</span> <span style="color: #ff0000;">'./includes/bootstrap.inc'</span>;
drupal_bootstrap<span style="color: #66cc66;">&#40;</span>DRUPAL_BOOTSTRAP_DATABASE<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #0000ff;">$result</span> = db_query<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;SELECT * FROM {url_alias} WHERE src = 'node/%d' LIMIT 1&quot;</span>, <span style="color: #0000ff;">$_GET</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'nid'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> db_error<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <a href="http://www.php.net/die"><span style="color: #000066;">die</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;O agony!&quot;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #0000ff;">$url_alias_object</span> = db_fetch_object<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$result</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$destination</span> = <span style="color: #0000ff;">$url_alias_object</span>-&gt;<span style="color: #006600;">dst</span>;
&nbsp;
<span style="color: #0000ff;">$result</span> = db_query<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;SELECT prefix FROM {languages} WHERE language = '%s'&quot;</span>, <span style="color: #0000ff;">$url_alias_object</span>-&gt;<span style="color: #006600;">language</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> db_error<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span> <a href="http://www.php.net/die"><span style="color: #000066;">die</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;O agony!&quot;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #0000ff;">$prefix</span> = db_result<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$result</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span> !<a href="http://www.php.net/empty"><span style="color: #000066;">empty</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$prefix</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#41;</span>
  <span style="color: #0000ff;">$prefix</span> .= <span style="color: #ff0000;">'/'</span>;
&nbsp;
<a href="http://www.php.net/header"><span style="color: #000066;">header</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Location: /$prefix$destination&quot;</span>,<span style="color: #000000; font-weight: bold;">TRUE</span>,<span style="color: #cc66cc;">301</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre>

<h3>Shortcomings in our hack</h3>

<p>The code assumes that every content page has an URL alias. For us, this is okay, because we need these pretty URLs to even have menus show up or to have the right page be displayed with the right theme.</p>

<p>Also, this code is specifically tailored to language code in the URL prefix. For subdomain based language selection, for example, you&#8217;d need to modify it.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigsmoke.us/2009/06/10/enforcing-drupal-url-aliases/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>WordPress feed pagination</title>
		<link>http://blog.bigsmoke.us/2009/02/16/wordpress-feed-pagination</link>
		<comments>http://blog.bigsmoke.us/2009/02/16/wordpress-feed-pagination#comments</comments>
		<pubDate>Mon, 16 Feb 2009 21:52:37 +0000</pubDate>
		<dc:creator>Rowan Rodrik</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Atom]]></category>
		<category><![CDATA[feed]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[URL]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blog.bigsmoke.us/?p=399</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>Wiebe uses his <a href="/author/halfgaar/feed/atom">author Atom feed</a> to generate a list of his blog posts here <a href="http://www.halfgaar.net/articles">on his own website</a>. WordPress feeds only display the latest 10 entries. He has written 16 so far. What he needs is a feed with <strong>all</strong> his entries.</p>

<p>First, I tried if pagination works for feeds. Appending &#8220;<tt>/page/2</tt>&#8221; (as is used an non-feed lists) to a feed URL gives a 404 so I was kind of stuck there. Four days ago, after Googling for some time, unable to find a solution anywhere, I <a href="http://wordpress.org/support/topic/242847">asked</a> on the forum. Still no answer today so I tried to find out which parameters WordPress accepts in the <tt>QUERY_STRING</tt>. The WordPress Codex does explain <a href="http://codex.wordpress.org/Query_Overview">how queries are handled</a> but not which parameters are accepted.</p>

<p>Digging into <tt>wp-includes/query.php</tt>, with much trial and error, I found out that I can append <q><tt>?paged=2</tt></q> to the URL to get the next page. At least I got that sorted then. There are a number of much more promising parameters supported by <tt>get_posts()</tt>, but these don&#8217;t seem to be parsed by <tt>parse_query()</tt>. Next time, I&#8217;d like to find out how how to use two of these: <tt>nopaging</tt> and <tt>posts_per_page</tt>.</p>

<p>Wiebe could complete his list by merging together all the pages of the feed, but I&#8217;d much prefer to find a relatively painless method to produce a feed with an unlimited number of posts.</p>

<h2>Notes</h2>

<ul>
<li>http://codex.wordpress.org/Query_Overview</li>
<li>http://codex.wordpress.org/Function_Reference/WP_Query</li>
<li>http://codex.wordpress.org/Template_Tags/query_posts</li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://blog.bigsmoke.us/2009/02/16/wordpress-feed-pagination/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New theme</title>
		<link>http://blog.bigsmoke.us/2008/07/13/new-theme</link>
		<comments>http://blog.bigsmoke.us/2008/07/13/new-theme#comments</comments>
		<pubDate>Sun, 13 Jul 2008 15:26:45 +0000</pubDate>
		<dc:creator>Rowan Rodrik</dc:creator>
				<category><![CDATA[BigSmoke.US]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Gravatar]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blog.bigsmoke.us/?p=87</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>
After upgrading to WordPress 2.5.x, I had to fall back on a stock theme because my old customization of the <a href="http://www.plaintxt.org/themes/sandbox/">Sandbox</a> theme no longer worked with the upgrade. But, then, it was time to redo my theme anyway. So here you&#8217;re looking at the first version of my new theme. I might have let it stabilize some more before putting it on-line, but who cares? My reader maybe? Let&#8217;s just hope he or she doesn&#8217;t use IE. <img src='http://blog.bigsmoke.us/wp-factory/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>

<a title="The header with a single post below" href='http://blog.bigsmoke.us/uploads/2008/07/new-theme-cap1.jpg' rel='lightbox[theme]'><img src="http://blog.bigsmoke.us/uploads/2008/07/new-theme-cap1-300x193.jpg" alt="Screencap of my new WP theme" title="New WordPress theme for BigSmoke" width="300" height="193" class="alignright size-medium wp-image-89" /></a>

<a title="The oversized footer with all the site-wide navigation" href='http://blog.bigsmoke.us/uploads/2008/07/new-theme-cap4.jpg' rel='lightbox[theme]'><img src="http://blog.bigsmoke.us/uploads/2008/07/new-theme-cap4-300x201.jpg" alt="Screencap of my new WP theme" title="New WordPress theme for BigSmoke" width="300" height="201" class="alignright size-medium wp-image-92" /></a>

<a title="The box of relations below a single post with links to all kinds of lists at the left and some direct links to chronologically related posts" rel='lightbox[theme]' href='http://blog.bigsmoke.us/uploads/2008/07/new-theme-cap3.jpg'><img src="http://blog.bigsmoke.us/uploads/2008/07/new-theme-cap3-300x112.jpg" alt="Screencap of my new WP theme" title="New WordPress theme for BigSmoke" width="300" height="112" class="alignright size-medium wp-image-91" /></a>

<a title="This is how lists of posts look" href='http://blog.bigsmoke.us/uploads/2008/07/new-theme-cap5.jpg' rel='lightbox[theme]'><img src="http://blog.bigsmoke.us/uploads/2008/07/new-theme-cap5-300x207.jpg" alt="Screencap of my new WP theme" title="New WordPress theme for BigSmoke" width="300" height="207" class="alignright size-medium wp-image-93" /></a>

<a title="The bottom part of a single post with some comments below" href='http://blog.bigsmoke.us/uploads/2008/07/new-theme-cap2.jpg' rel='lightbox[theme]'><img src="http://blog.bigsmoke.us/uploads/2008/07/new-theme-cap2-300x193.jpg" alt="Screencap of my new WP theme" title="New WordPress theme for BigSmoke" width="300" height="193" class="alignright size-medium wp-image-90" /></a>

<h2>Vertical navigation</h2>

<p>Ever since the first time that I saw a blog which featured vertical navigation instead of the typical columns, I&#8217;ve wanted to implement this for myself. Well, finally&#8230;</p>

<p>Site-wide elements use the complete width of the page. The page content is centered in the middle at 87.5%.  The identity stuff in the header and the navigation in the footer sits against a back blackground while the content area has the proven black on white for easy reading. I hope that the strong color-contrast as well as the clear difference in with between site-wide elements and page content makes it easy to keep focused on either reading or navigating without distractions.</p>

<h2>&#8230; and a talkative footer</h2>

<p>With this theme, I didn&#8217;t want another footer which consist of the odd logo and some loose copyright statements. I wanted a footer which you can actually read, even understand. And who cares if it takes up a little space? It&#8217;s at the bottom of the page.</p>

<h2>Related posts</h2>

<p>I&#8217;ve written an (unpublished, unpolished) plug-in which can generate a list of posts that are chronologically related. Traditionally, most blogs have a next/previous post link at the top and bottom of each post. This works very well if you limit your blog to one subject (which is really a very good idea anyway), but if, like mine, your blog is a little bit messy, you could say that someone who stumbled here searching for an article about <a href="/tag/subversion">Subversion</a> is not necessarily interested in the next post if this is a <a href="http://blog.bigsmoke.us/2007/07/29/linde-smiling-the-most-amazing-smile">photo of my baby niece</a>.</p>


<p>Hence the chronologically related posts plugin. With this plugin I can say wether I want a link to the first, previous and next post in the blog, within the same category, or matching a given number of tags. (The tag matching isn&#8217;t implemented yet, though. Also, matching on meta fields would be a kick-ass ass way to support explicit sequences.)</p>

<p>I put the list generated by this plug-in on top of a blue background besides the various context links of the post.</p>

<h2>Issues left</h2>

<p>I hope to have the first major revision of my theme ready soon. Here&#8217;s a list of some issues that I might address:</p>

<ul>
<li>The CSS renders a bit psychedelically in MSIE 6 (only version I tested) at the moment. Sigh&#8230; Let&#8217;s just hope that IE 7 will give better results. Then I&#8217;ll gladly drop the IE 6 support.</li>
<li>When viewing a category, the tag cloud in the navigation panel at the bottom only shows tags for that category. This has to do with the use with me calling the <tt>st_tag_cloud()</tt> from within the category template.</li>
<li>Some of the elements that I just showed to you don&#8217;t really look that good and most elements that I <em>didn&#8217;t</em> can be said to be &#8230; hideously ugly. <img src='http://blog.bigsmoke.us/wp-factory/wp-includes/images/smilies/icon_confused.gif' alt=':-?' class='wp-smiley' />  Some highlights: the header (should really be a few cool images), the comment form, and the Next/Previous Page links.</li>
</ul>

<h2>Comment!</h2>

<p>I&#8217;d almost forget all about the clean, new look of the comment list. And, if you register a <a href="http://www.gravatar.com/">Gravatar</a>, your comments will be accompanied by your avatar. Try it. Please!</p>]]></content:encoded>
			<wfw:commentRss>http://blog.bigsmoke.us/2008/07/13/new-theme/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

