Feb 22 2007

Found the Culprit of the Pacman’s Effect

Tag: FixingAndrea Ercolino @ 13:22:50

Some time ago I wrote Entity enzyme, or The pacman effect strikes back. It was an article about the pacman effect of the ampersand in WordPress and how to try to solve it with a simple enzyme. Recently I’ve discovered that it’s an escaping / unescaping issue still unresolved in WordPress 2.1, and it’s somewhat nastier than I initially thought.

If you want to write HTML entity codes in a post, and you need to represent that of an ampersand for example (it’s &), then there is no way to get it right. In fact, WordPress will always resolve an entity code.

Thus, if you write &, you’ll get & after the first save roundtrip, and if you try to escape the & into & with &, obtaining & (this looks weird but it’s the way to do it in plain HTML), then the first time you save the post you get & back, and the second time you save the post you get & back.

In general if you write & followed by any number of amp; (like &) then WordPress will make the & eat up an amp; at each saving roundtrip, hence the pacman effect.

But the title of my previous post about this issue was “the pacman effect strikes back.” In fact it’s not only a problem of the post content but also of the custom fields, thus corrupting the last resort we WordPress bloggers have for content AS IS. And this is where I get really upset.

Last tuesday I found the culprit and asked the wp-hackers list wether they considered it a bug or not. I’m still waiting for an answer, so I hope this post will help me to broaden the question and understand if I need to submit it to WordPress Trac or go in for a hack myself.


Feb 16 2007

How to Highlight Mixed Language Source Code

Tag: Chili, EnzymesAndrea Ercolino @ 16:35:29

Web pages contain many snippets from different languages, like HTML, PHP, CSS, and JavaScript. Chili 1.x cannot highlight mixed language source code automatically, but the forthcoming released Chili 2.0 will be is able to do that.

Meanwhile, if you are using a Chili + Enzymes setup, then it’s possible to write an Enzymes template capable of making Chili 1.x highlight a web page perfectly (expanding on my previous php template).

Here is the new updated (2007/02/19) chili-web.php Enzymes template. At the moment it supports XHTML, and embedded CSS, JavaScript, and PHP snippets.

<?php 
if( ! function_exists( 'format_code' ) ) {

	function snippet_wrap( $class, $code ) {
		return '' == $code ? '' : '<code class="'.$class.'">'.htmlentities( $code ).'</code>';
	}

	function snippet_php( $open, $code, $close ) {
		return snippet_wrap( 'html', $open ).snippet_wrap( 'php', $code ).snippet_wrap( 'html', $close );
	}

	function php_inside_html( $matches ) {
		list( $all, $before, $open, $code, $close ) = $matches;

		if( '' == $open ) 
			return snippet_wrap( 'html', $all );
		else 
			return snippet_wrap( 'html', $before ).snippet_php( $open, $code, $close );
	}

	function php_inside_css( $matches ) {
		list( $all, $before, $open, $code, $close ) = $matches;

		if( '' == $open ) 
			return snippet_wrap( 'css', $all );
		else 
			return snippet_wrap( 'css', $before ).snippet_php( $open, $code, $close );
	}

	function php_inside_javascript( $matches ) {
		list( $all, $before, $open, $code, $close ) = $matches;

		if( '' == $open ) 
			return snippet_wrap( 'javascript', $all );
		else 
			return snippet_wrap( 'javascript', $before ).snippet_php( $open, $code, $close );
	}

	function php_inside( $class, $code ) {
		return preg_replace_callback( '/(?:(.*?)(\<\?php\s)(.*?)(\?\>))|(?:.+)/si', "php_inside_$class", $code );
	}

	function snippet_web( $class, $open, $code, $close ) {
		return snippet_wrap( 'html', $open ).php_inside( $class, $code ).snippet_wrap( 'html', $close );
	}

	function format_code( $matches ) {
		list( $all, $before, $open, $tag, $code, $close ) = $matches;

		if( '' == $open ) {
			return php_inside( 'html', $all );
		}
		else {
			switch( $tag ) {
				case 'script': $class = 'javascript'; break;
				case 'style' : $class = 'css';        break;
				default      : $class = 'html';
			}
			return php_inside( 'html', $before ).snippet_web( $class, $open, $code, $close );
		}
	}

	function format_clean( $out ) {
		do {
			$len = strlen( $out );
			$out = preg_replace( '/(\<code class="(\w+)"\>[^<]*)\<\/code\>\<code class="\2"\>/is', '$1', $out );
		} while( $len != strlen( $out ) );
		return $out;
	}
}

?>
<pre class="chili-<?php 
	$tmp = preg_split( '/(?:\r?\n)+/', $this->result );
	if( count( $tmp ) > 28 ) echo 'clip';
	else echo 'all'; 
?>"><?php

	$out = preg_replace_callback( '/(?:(.*?)(\<(script|style)\b.*?\>)(.*?)(\<\/\3\>))|(?:.+)/is', 'format_code', $this->result );
	echo format_clean( $out );
?></pre>

The WordPress file /wp-content /themes /default /comments-popup.php is a page that uses all the supported languages, so it’s a good test for the previous template:

<?php

/* Don't remove these lines. */
add_filter('comment_text', 'popuplinks');
while ( have_posts()) : the_post();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
     <title><?php echo get_option('blogname'); ?> - Comments on <?php the_title(); ?></title>

	<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php echo get_option('blog_charset'); ?>" />
	<style type="text/css" media="screen">
		@import url( <?php bloginfo('stylesheet_url'); ?> );
		body { margin: 3px; }
	</style>

</head>
<body id="commentspopup">

<h1 id="header"><a href="" title="<?php echo get_option('blogname'); ?>"><?php echo get_option('blogname'); ?></a></h1>

<h2 id="comments">Comments</h2>

<p><a href="<?php echo get_option('siteurl'); ?>/wp-commentsrss2.php?p=<?php echo $post->ID; ?>"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a></p>

<?php if ('open' == $post->ping_status) { ?>
<p>The <abbr title="Universal Resource Locator">URL</abbr> to TrackBack this entry is: <em><?php trackback_url() ?></em></p>
<?php } ?>

<?php

// this line is WordPress' motor, do not delete it.
$commenter = wp_get_current_commenter();
extract($commenter);
$comments = get_approved_comments($id);
$post = get_post($id);
if (!empty($post->post_password) && $_COOKIE['wp-postpass_'. COOKIEHASH] != $post->post_password) {  // and it doesn't match the cookie
	echo(get_the_password_form());
} else { ?>

<?php if ($comments) { ?>
<ol id="commentlist">
<?php foreach ($comments as $comment) { ?>
	<li id="comment-<?php comment_ID() ?>">
	<?php comment_text() ?>
	<p><cite><?php comment_type('Comment', 'Trackback', 'Pingback'); ?> by <?php comment_author_link() ?> Ã¢â‚¬â€ť <?php comment_date() ?> @ <a href="#comment-<?php comment_ID() ?>"><?php comment_time() ?></a></cite></p>
	</li>

<?php } // end for each comment ?>
</ol>
<?php } else { // this is displayed if there are no comments so far ?>
	<p>No comments yet.</p>
<?php } ?>

<?php if ('open' == $post->comment_status) { ?>
<h2>Leave a comment</h2>
<p>Line and paragraph breaks automatic, e-mail address never displayed, <acronym title="Hypertext Markup Language">HTML</acronym> allowed: <code><?php echo allowed_tags(); ?></code></p>

<form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform">
	<p>
	  <input type="text" name="author" id="author" class="textarea" value="<?php echo $comment_author; ?>" size="28" tabindex="1" />
	   <label for="author">Name</label>
	<input type="hidden" name="comment_post_ID" value="<?php echo $id; ?>" />
	<input type="hidden" name="redirect_to" value="<?php echo attribute_escape($_SERVER["REQUEST_URI"]); ?>" />
	</p>

	<p>
	  <input type="text" name="email" id="email" value="<?php echo $comment_author_email; ?>" size="28" tabindex="2" />
	   <label for="email">E-mail</label>
	</p>

	<p>
	  <input type="text" name="url" id="url" value="<?php echo $comment_author_url; ?>" size="28" tabindex="3" />
	   <label for="url"><abbr title="Universal Resource Locator">URL</abbr></label>
	</p>

	<p>
	  <label for="comment">Your Comment</label>
	<br />
	  <textarea name="comment" id="comment" cols="70" rows="4" tabindex="4"></textarea>
	</p>

	<p>
	  <input name="submit" type="submit" tabindex="5" value="Say It!" />
	</p>
	<?php do_action('comment_form', $post->ID); ?>
</form>
<?php } else { // comments are closed ?>
<p>Sorry, the comment form is closed at this time.</p>
<?php }
} // end password check
?>

<div><strong><a href="javascript:window.close()">Close this window.</a></strong></div>

<?php // if you delete this the sky will fall on your head
endwhile;
?>

<!-- // this is just the end of the motor - don't touch that line either :) -->
<?php //} ?>
<p class="credit"><?php timer_stop(1); ?> <cite>Powered by <a href="http://wordpress.org/" title="Powered by WordPress, state-of-the-art semantic personal publishing platform"><strong>Wordpress</strong></a></cite></p>
<?php // Seen at http://www.mijnkopthee.nl/log2/archive/2003/05/28/esc(18) ?>
<script type="text/javascript">
<!--
document.onkeypress = function esc(e) {
	if(typeof(e) == "undefined") { e=event; }
	if (e.keyCode == 27) { self.close(); }
}
// -->
</script>
</body>
</html>

Chili & Enzymes confirm to be a perfect match.


Feb 13 2007

WordPress Custom Fields Restyling

Tag: UncategorizedAndrea Ercolino @ 00:20:44

I use Custom Fields a lot, always by means of Enzymes, for managing the code snippets I’m going to comment about.

The Custom Fields section inside the post editing page shows added custom fields in a table whose columns change their width to fit the content, but the rows don’t change their height. I do not like that design: a definition list is much better than a table there. The key is the definition term and the value is the definition data.

Here are some pictures about the results of my experiment. The first row is my restyling, and the second row is how the same data appear in the usual design. There are three custom fields already added to this post: snippet1, snippet2, and snippet3; in the right picture, a new google custom field is going to be added

customfields1.png , customfields2.png , customfieldsnew.png

customfieldsold.png

Features of my restyling
  • added fields and the new field are evenly represented by the classical definition list style, where definition data is indented below the definition term; this provides a powerful clue for identifying the key / value roles, thus making all the labels superfluous
  • space usage is smarter; the key spans all the available width; the value almost all of it, and its height is greater than usual too, thus allowing for a convenient inspection, for viewing and editing purposes; the vertical scrollbar is much more useful than the horizontal one
  • by clicking its key, a custom field gets expanded, thus showing its value and its two editing buttons, while the rest of the custom fields gets collapsed; showing only one custom field at a time helps keeping user’s attention focused
  • the selection box for chosing an already known-to-the-system key is replaced by a list of buttons, located above the key field; by clicking any of them, the key gets copied into the key field, so that the user can leave it alone or change it, if needed; the overall design is more coherent

Feb 12 2007

How to reset a WordPress password

Tag: otherAndrea Ercolino @ 15:53:53

I’ve found this method today, and it works very well. I’ve just used it to reset my admin access password to a localhost installation. In fact it’s impossible to recover a password by means of an email if your system cannot send emails. This method is also very easy, and without email delivery delays in between.

  1. Open phpMyAdmin (a different MySQL web access tool should be fine, too)
  2. You should see the welcome page. Find the Database selection box and select your WordPress database
  3. You should see a list of tables, many with a common prefix, organized as links on the left and as rows on the right. Click the link wp_users (instead of wp you’ll use the prefix you chose when installing WordPress, if different)
  4. You should see the wp_users table structure, but you’re looking for its contents, so find the Browse link and click it
  5. You shoud see the wp_users table contents, one row for each registered user. Select the one with the admin value under the user_login column header and click on the Change link (with a pen icon, right below the last row)
  6. You should see a classical data entry form. In the row which has the user_pass value under the Field column header, select the MD5 value from the selection box under the Function column header, and write your new password in the text field under the Value column header. Then click Go
  7. Close phpMyAdmin
  8. Done

Feb 10 2007

An enzyme for transcluding a web page

Tag: EnzymesAndrea Ercolino @ 17:35:33

Enzymes can be complex PHP scripts, but basic enzymes are also very useful. This one is a oneliner, and it allows to transclude a web page inside a post. Really all the magic is played by an IFRAME element, but Enzymes makes it easy to use the method over and over, without any need to remember: “how did I do it?”

this is got by the statement {[.page(.google)]}

this is got by the statement {[.page(.yahoo)]}

Here is the code for the page field:

echo "<iframe width='450' height='200' src='" . $this->substrate . "'></iframe>";

Here is the code for the google and yahoo fields respectively:

http://www.google.com/
http://www.yahoo.com/

Easy, isn’t it?


Feb 08 2007

TinyMCE extended

Tag: UncategorizedAndrea Ercolino @ 18:06:23

This is great! I always wondered why this TinyMCE editor in WordPress is so poor, but when you go to their web site you see many many useful buttons. Finally there is a simple way to extend the default toolbar.

The thing I probably missed most was the U button. In fact I use to render underlined text with a maroon color by means of the WordPress stylesheet. I always had to add the markup manually, and in WordPress 2.1 it got trickier because I had to make a Visual-Code-Visual roundtrip, due to the escaping facility added to the Visual side.


Feb 01 2007

How to add a PunchCard to each WordPress post

Tag: PunchCardAndrea Ercolino @ 19:25:26

What you find in the PunchCard Manual is valid in general for any html page and blog system, but if you need a 5 minutes guide for adding a properly formatted PunchCard to each WordPress post, here it is.

  1. download PunchCard 1.2, and extract it to a local folder
  2. locate the file jquery-1.1.1.pack.js and upload it to the remote folder / wp-content / jquery /
  3. upload all the other files to the remote folder / wp-content / jquery / punchcard /
  4. edit the remote file / wp-content / themes / default / header.php, 
    locate the </head> tag, add the following code right before it, and then close and save the file:
    <script type="text/javascript" 
    	src="<?php bloginfo('siteurl'); ?>/wp-content/jquery/jquery-1.1.1.pack.js">
    	</script>
    
    <script type="text/javascript" 
    	src="<?php bloginfo('siteurl'); ?>/wp-content/jquery/punchcard/punchcard-1.2.pack.js">
    	</script>
    
    <script type="text/javascript">
    PunchCard.icons = "/aercolino/punchcard/icons/";
    PunchCard.styles = "<?php bloginfo('siteurl'); ?>/wp-content/jquery/punchcard/";
    </script>
  5. edit the remote file / wp-content / themes / default / index.php, 
    locate the <p class="postmetadata"> tag, add the following code right before it, and then close and save the file:
    <?php 
    ob_start();
    the_title();
    $title = ob_get_contents();
    ob_clean();
    the_permalink();
    $permalink = ob_get_contents();
    ob_end_clean();
    ?>
    
    <div style="text-align:center;" class="pc_MINI"><div class="punchcard">
    	<object>
    	<param name="punchcard" value='{
    		title: "<?php echo $title; ?>"
    		, url: "<?php echo $permalink; ?>"
    		, id : "<?php $pieces = explode( "?", $permalink ); echo $pieces[1]; ?>"
    	}'/>
    	</object>
    </div></div>

That’s all.

  • you can repeat step 5. for the file / wp-content / themes / default / single.php
  • if you are not using the default theme, remember to appropriately change the path to the theme folder in the previous steps

Following this fast guide you’ll get a PunchCard at the bottom of each post, like mine. Each PunchCard will reference your post (title and URL).

Feel free to play with the PunchCard stylesheet and setup for customizing your punchcards.


« Previous PageNext Page »