<?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>A Tasty Pixel » Blog &#187; Web</title>
	<atom:link href="http://atastypixel.com/blog/tag/web/feed/" rel="self" type="application/rss+xml" />
	<link>http://atastypixel.com/blog</link>
	<description></description>
	<lastBuildDate>Mon, 19 Jul 2010 10:22:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Keeping blog visitors by showing meaningful search results in WordPress</title>
		<link>http://atastypixel.com/blog/keeping-blog-visitors-by-showing-meaningful-search-results-in-wordpress/</link>
		<comments>http://atastypixel.com/blog/keeping-blog-visitors-by-showing-meaningful-search-results-in-wordpress/#comments</comments>
		<pubDate>Sat, 05 Jun 2010 14:43:45 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1927</guid>
		<description><![CDATA[By default, Wordpress will show you full, confusing posts when searching.  Keep your visitors happy by providing contextual search results like a proper search engine.  This post explains how to do it, in just a few minutes.]]></description>
			<content:encoded><![CDATA[<p>I recently became disgruntled with the way my blogs displayed search results.  By default, WordPress blogs will show searched posts exactly as they might appear on an index or archives page: Typically as an extract, or perhaps even as the full entry.</p>

<p>This doesn&#8217;t help at all if you&#8217;re looking for something in particular &#8211; It&#8217;s a much better idea to show the post within the context of the search query, as real search engines do.</p>

<p>See it in practice <a href="http://atastypixel.com/blog/?s=talkie">here</a>.</p>

<p>This is a fairly easy thing to actually get working in WordPress.  It&#8217;ll take just a couple of minutes, and will make a big difference to blog visitors.  Here&#8217;s how I did it.</p>

<p><span id="more-1927"></span></p>

<h2>Creating a search result page</h2>

<p>If your theme doesn&#8217;t already have one, you&#8217;ll need to construct a template within your theme that WordPress will use for search results.  By default, WordPress will use your <code>index.php</code> template, so that&#8217;s usually a good place to start with, for normal themes.</p>

<p>Duplicate <code>index.php</code>, and call it <code>search.php</code>.</p>

<p>If you already have a <code>search.php</code>, you&#8217;re all set.</p>

<h3>A note about theme engines</h3>

<p>A special case here is for theme engines like Thematic (which I use for this blog).  For Thematic, it&#8217;s a matter of un-hooking the provided search &#8216;loop&#8217; from within your child theme, and replacing it with your own.</p>

<p>In my case, with a Thematic child theme, this takes place within <code>functions.php</code>.  First, one needs an &#8216;init&#8217; action, to remove the existing hooks.</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> mytheme_init<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   remove_action<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'thematic_searchloop'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'thematic_search_loop'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #339933;">...</span>
add_action<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'init'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'mytheme_init'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<p>Then, it needs a replacement function to perform the search result loop:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">function mytheme_search_loop() {
  while ( have_posts() ) : the_post(); ?&gt;
&nbsp;
    &lt;div id=&quot;post-<span style="color: #000000; font-weight: bold;">&lt;?php</span> the_ID<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; class=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> thematic_post_class<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> thematic_postheader<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      &lt;div class=&quot;entry-content&quot;&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> thematic_content<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">/* We will replace this next */</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
      &lt;/div&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> thematic_postfooter<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  &lt;/div&gt;&lt;!-- .post --&gt;
&nbsp;
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endwhile</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #339933;">...</span>
add_action<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'thematic_searchloop'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'mytheme_search_loop'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<h2>Some smarts to show context</h2>

<p>What I did was replace the content of each post displayed with some code that constructs and displays some context around the search terms found in the post.</p>

<p>In your <code>search.php</code> (or your search loop function, if you&#8217;re using a theme engine), look for the line that inserts the post content.  Chances are, it&#8217;ll look something like <code>&lt;?php the_content('Keep reading'); ?&gt;</code>.  In the case of the Thematic child theme above, it&#8217;s <code>&lt;php thematic_content(); ?&gt;</code>.</p>

<p>Delete that line, and replace it with the following (here&#8217;s a <a href="http://atastypixel.com/blog/wp-content/uploads/2010/06/search_snippet.txt" title="search_snippet.txt">plain-text version</a>, if that&#8217;s easier):</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">// Configuration</span>
<span style="color: #000088;">$max_length</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">400</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Max length in characters</span>
<span style="color: #000088;">$min_padding</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">30</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Min length in characters of the context to place around found search terms</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Load content as plain text</span>
<span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$wp_query</span><span style="color: #339933;">,</span> <span style="color: #000088;">$post</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$content</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>post_password_required<span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #009900;">&#41;</span> ? <span style="color: #990000;">strip_tags</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/<span style="color: #000099; font-weight: bold;">\r</span>?<span style="color: #000099; font-weight: bold;">\n</span>/&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'@&lt;\s*(p|br\s*/?)\s*&gt;@'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> apply_filters<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'the_content'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post_content</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Search content for terms</span>
<span style="color: #000088;">$terms</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$wp_query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query_vars</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'search_terms'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">preg_match_all</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">.</span><span style="color: #990000;">str_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'\/'</span><span style="color: #339933;">,</span> <span style="color: #990000;">join</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'|'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$terms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/i'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$content</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #339933;">,</span> PREG_OFFSET_CAPTURE<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$padding</span> <span style="color: #339933;">=</span> <span style="color: #990000;">max</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$min_padding</span><span style="color: #339933;">,</span> <span style="color: #000088;">$max_length</span> <span style="color: #339933;">/</span> <span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">*</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Construct extract containing context for each term</span>
  <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$last_offset</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$match</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">list</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #339933;">,</span> <span style="color: #000088;">$offset</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$match</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$start</span>  <span style="color: #339933;">=</span> <span style="color: #000088;">$offset</span><span style="color: #339933;">-</span><span style="color: #000088;">$padding</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$end</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$offset</span><span style="color: #339933;">+</span><span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #000088;">$padding</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// Preserve whole words</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$start</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/[A-Za-z0-9\'&quot;-]/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$content</span><span style="color: #009900;">&#123;</span><span style="color: #000088;">$start</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #000088;">$start</span><span style="color: #339933;">--;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$end</span> <span style="color: #339933;">&lt;</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$content</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/[A-Za-z0-9\'&quot;-]/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$content</span><span style="color: #009900;">&#123;</span><span style="color: #000088;">$end</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #000088;">$end</span><span style="color: #339933;">++;</span>
    <span style="color: #000088;">$start</span> <span style="color: #339933;">=</span> <span style="color: #990000;">max</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$start</span><span style="color: #339933;">,</span> <span style="color: #000088;">$last_offset</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$content</span><span style="color: #339933;">,</span> <span style="color: #000088;">$start</span><span style="color: #339933;">,</span> <span style="color: #000088;">$end</span><span style="color: #339933;">-</span><span style="color: #000088;">$start</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$start</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$last_offset</span> <span style="color: #009900;">&#41;</span> <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'...'</span><span style="color: #339933;">.</span><span style="color: #000088;">$context</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$context</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$last_offset</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$end</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$last_offset</span> <span style="color: #339933;">!=</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$content</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span> <span style="color: #000088;">$output</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'...'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$content</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$max_length</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$end</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$max_length</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$end</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/[A-Za-z0-9\'&quot;-]/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #009900;">&#123;</span><span style="color: #000088;">$end</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #000088;">$end</span><span style="color: #339933;">--;</span>
  <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #000088;">$end</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'...'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Highlight matches</span>
<span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #990000;">nl2br</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">.</span><span style="color: #990000;">str_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'\/'</span><span style="color: #339933;">,</span> <span style="color: #990000;">join</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'|'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$terms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/i'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;strong&gt;$0&lt;/strong&gt;'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
&lt;p class=&quot;search_result_context&quot;&gt;
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$context</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/p&gt;
&lt;p&gt;
  &lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> the_permalink<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; rel=&quot;bookmark&quot;&gt;Read this entry&lt;/a&gt;
&lt;/p&gt;</pre></div></div>


<p>Save, and search for something on your blog &#8212; you should see contextual search results, now.</p>

<h2>One final tweak: Results per page</h2>

<p>WordPress has a setting for the number of posts to show per page.  You may want to use a different number of <em>search results</em> per page, given that each result is now shorter than a full post.</p>

<p>To override this &#8216;posts per page&#8217; setting, you&#8217;ll want to find the line just before the search loop.  It&#8217;ll probably look like <code>&lt;?php if (have_posts()) : ?&gt;</code>, or, if your theme doesn&#8217;t bother with that part, <code>&lt;?php while ( have_posts() ) : the_post(); ?&gt;</code>.</p>

<p>Before that line, insert the following:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$wp_query</span><span style="color: #339933;">;</span> <span style="color: #000088;">$v</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$wp_query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query_vars</span><span style="color: #339933;">;</span> <span style="color: #000088;">$v</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'posts_per_page'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">;</span> query_posts<span style="color: #009900;">&#40;</span><span style="color: #000088;">$v</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>


<p>This will take the current query (including the search phrase, page number, etc.), add a &#8216;posts per page&#8217; parameter, then pass it back to WordPress&#8217;s query engine.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1927" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/keeping-blog-visitors-by-showing-meaningful-search-results-in-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DIY Twitter image hosting</title>
		<link>http://atastypixel.com/blog/diy-twitter-image-hosting/</link>
		<comments>http://atastypixel.com/blog/diy-twitter-image-hosting/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 14:16:07 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1757</guid>
		<description><![CDATA[Twitter doesn&#8217;t yet come with its own inline image support, so we tend to be limited to using image hosting services, and linking to them with short URLs. So, services like Tweetpic host the image, and we direct traffic to them in return. Thinking it&#8217;s better to keep things in the family, and take better [...]]]></description>
			<content:encoded><![CDATA[<p>Twitter doesn&#8217;t yet come with its own inline image support, so we tend to be limited to using image hosting services, and linking to them with short URLs.  So, services like Tweetpic host the image, and we direct traffic to them in return.</p>

<p>Thinking it&#8217;s better to keep things in the family, and take better advantage of that traffic, I put together an image hosting setup of my own.  Now viewers come to my own site, instead of someone else&#8217;s!</p>

<p>It looks like <a href="http://twitter.com/ATastyPixel/status/7478572775">this</a></p>

<p>The setup consists of an Automator service, and some PHP smarts on the site.</p>

<p><img src="http://atastypixel.com/blog/wp-content/michaelangelo-images/c7c164a7e7460cdbb5c7fbdc86cd77bf.jpg" width="250" height="133" alt="Send Image to Image Hosting" class="alignright polaroid rotation" />Under Snow Leopard, I can right-click on an image in Finder, click &#8216;Send Image to Image Hosting&#8217;, type in a title,  then paste the URL that&#8217;s automatically been put onto my clipboard into a tweet.</p>

<p>Here&#8217;s how it works &#8211; this assumes a moderate level of understanding of PHP and assorted web administration.<span id="more-1757"></span>
<em>Update</em>: I couldn&#8217;t help myself; I made a <a href="http://atastypixel.com/blog/wordpress/plugins/twitter-image-host">WordPress plugin</a> for this, with some extra nice features.</p>

<h2>Presentation</h2>

<p>First, we need to put together a script that will display the image.  What&#8217;s more, it would be nice to give the image a title, and link it back to the Twitter account.</p>

<p>So, we&#8217;ll want a place to put images, and a way to store the corresponding title and account name.</p>

<p>I opted to store the latter in a file alongside the image called <code>(imagename).meta</code>.  I store the title, then a newline, then the Twitter account name.</p>

<p>Lets create <code>image.php</code> &#8212; it should take an <code>image name</code> parameter, excluding the file extension, and display the corresponding image, with any corresponding meta data.</p>

<p>Here&#8217;s a sample:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$MEDIA_DIR</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;twitter-images&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Get the image name, but avoid any path shenanigans by just grabbing the 'basename' of the file</span>
<span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #990000;">basename</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_REQUEST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Make sure it exists, or report a 404 error</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$image</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #990000;">is_file</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$MEDIA_DIR</span>/<span style="color: #006699; font-weight: bold;">$image</span>.jpg&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;404.php&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Grab the meta data</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">file_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$MEDIA_DIR</span>/<span style="color: #006699; font-weight: bold;">$image</span>.meta&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">list</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #339933;">,</span> <span style="color: #000088;">$source</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">$MEDIA_DIR</span>/<span style="color: #006699; font-weight: bold;">$image</span>.meta&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Set a default title if we don't have any meta data</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #000088;">$title</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$title</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ucwords</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Include the page header, if you like</span>
<span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;header.inc.php&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
&lt;div class=&quot;content&quot;&gt;
&nbsp;
    &lt;img src=&quot;/<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> MEDIA_DIR <span style="color: #000000; font-weight: bold;">?&gt;</span>/<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$image</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>.jpg&quot; alt=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #990000;">htmlspecialchars</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$title</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; class=&quot;image&quot; /&gt;
&nbsp;
    &lt;h1&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$title</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/h1&gt;
&nbsp;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$source</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;p&gt;
            From &lt;a href=&quot;http://twitter.com/<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$source</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;
                &lt;img src=&quot;/media/images/twitter.png&quot; width=&quot;14&quot; height=&quot;14&quot; alt=&quot;Follow us on Twitter!&quot;&gt;
                <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$source</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
            &lt;/a&gt;
        &lt;/p&gt;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
&lt;/div&gt;
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;footer.inc.php&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>


<p>Make sure it works by making a sample image called, say, <code>IMG.jpg</code>, and an accompanying metadata file, called <code>IMG.meta</code> with a title on the first line and a twitter account name on the second, and opening up <code>http://yoursite.com/image.php?name=IMG</code></p>

<p>Now, we want to keep URLs short, so they don&#8217;t take up too much valuable space in a tweet, so we need to use some tricks here.</p>

<p>We&#8217;ll set up a <code>.htaccess</code> file that uses <code>mod_rewrite</code> to keep the URL short.</p>

<p>Something like this should do the trick:</p>

<blockquote>
<pre>
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/([^/]+)$
RewriteCond %{DOCUMENT_ROOT}/twitter-images/%1.jpg -f
RewriteRule (.*) /image.php?name=$1 [L]
&lt;/IfModule&gt;
</pre>
</blockquote>

<p>Note on the fifth line we are checking inside our Twitter images folder &#8212; make sure that matches your storage path.</p>

<p>This will take any requests that:</p>

<ul>
<li>Are located in the web-root (<em>start with a slash, followed by anything but a slash until the end</em>)</li>
<li>Have a corresponding file within the directory we&#8217;ll store images in</li>
</ul>

<p>Then, it&#8217;ll rewrite the request silently to use <code>image.php</code>.</p>

<p>Save the <code>.htaccess</code> file, and open <code>http://yoursite.com/IMG</code>.  It should bring up the image, just as before.</p>

<p>Set up some CSS to make it look good, and you&#8217;re set.  Here&#8217;s mine:</p>


<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">&nbsp;
<span style="color: #808080; font-style: italic;">/* @group Twitter images */</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> <span style="color: #6666ff;">.content</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">margin-top</span><span style="color: #00AA00;">:</span> <span style="color: #933;">50px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin-bottom</span><span style="color: #00AA00;">:</span> <span style="color: #933;">50px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> <span style="color: #6666ff;">.content</span> img<span style="color: #6666ff;">.image</span> <span style="color: #00AA00;">&#123;</span>
	-moz-border-radius<span style="color: #00AA00;">:</span> <span style="color: #933;">20px</span><span style="color: #00AA00;">;</span>
	-webkit-border-radius<span style="color: #00AA00;">:</span> <span style="color: #933;">20px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#f1f1f1</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#aaa</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span>  <span style="color: #933;">40px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin-right</span><span style="color: #00AA00;">:</span> <span style="color: #933;">60px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">display</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">block</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333;">auto</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> <span style="color: #6666ff;">.content</span> h1 <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">padding-top</span><span style="color: #00AA00;">:</span> <span style="color: #933;">60px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">text-align</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">center</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> <span style="color: #6666ff;">.content</span> p <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">text-align</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">center</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> <span style="color: #6666ff;">.content</span> a <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">text-decoration</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.twitter-image</span> <span style="color: #6666ff;">.content</span> a img <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">vertical-align</span><span style="color: #3333ff;">:text-</span>bottom<span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* @end */</span></pre></div></div>


<h2>Automator</h2>

<p>Now, with the web side set up, we need to set up an easy way to send content there.</p>

<p>I opted for an Automator service, which uses <code>scp</code> to upload the content.  If your web host doesn&#8217;t provide for <code>scp</code>, you may want to use something else like <a href="http://www.ncftp.com/download/">ncftpput</a>, or even an Applescript-able application.  You&#8217;ll need to modify the Automator action&#8217;s shell script accordingly.</p>

<p>Here&#8217;s the Automator service I set up: <a href="http://atastypixel.com/blog/wp-content/uploads/2010/01/Send-Image-to-Image-Hosting.zip" title="Send Image to Image Hosting.zip">Send Image to Image Hosting.zip</a>.</p>

<p>For those interested, it contains the following shell script:</p>


<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">APPSUPPORT=~/&quot;Library/Application Support/Image Hosting&quot;
TMPDIR='/tmp/image-hosting.tmp'
DEST='me@mywebsite.com:www/mywebsite/twitter-images/'
URLPREFIX='http://mywebsite.com/'
UPLOADRETRIES=3
# GROWL=&quot;/usr/local/bin/growlnotify&quot; # Uncomment this if you have Growl and growlnotify
&nbsp;
[ ! -e &quot;$APPSUPPORT&quot; ] &amp;&amp; mkdir &quot;$APPSUPPORT&quot;
&nbsp;
for f in &quot;$@&quot;
do
  if [ ! -e &quot;$f&quot; ]; then
    osascript -e 'tell application &quot;Finder&quot;' -e 'activate' -e 'display dialog &quot;Input file '&quot;$f&quot;' does not exist&quot; with title &quot;Image Hosting&quot; buttons {&quot;OK&quot;} with icon Stop' -e 'end tell'
    exit
  fi
&nbsp;
  # Generate random name
  while true; do
      name=`perl -e 'use MIME::Base64; $s=encode_base64(rand()); $s =~ s/=|\n//g; $s = substr($s, -5); print $s'`
      if ! grep &quot;$name&quot; &quot;$APPSUPPORT/Taken Names&quot; &amp;&gt;/dev/null; then break; fi;
  done;
&nbsp;
  # Gather info
  default=`php -r '$s = basename(&quot;'&quot;$f&quot;'&quot;); echo ucwords(strtolower(substr($s, 0, strpos($s, &quot;.&quot;))));'`
  title=`osascript -e 'tell application &quot;Finder&quot;' -e 'activate' -e 'text returned of (display dialog &quot;Enter image title&quot; with title &quot;Image Hosting&quot; default answer &quot;'&quot;$default&quot;'&quot; buttons {&quot;Cancel&quot;, &quot;Continue&quot;} default button 2)' -e 'end tell'`
  [ ! &quot;$title&quot; ] &amp;&amp; exit
  defaulttwitter=`cat &quot;$APPSUPPORT/Default Twitter Account&quot; 2&gt;/dev/null`
  twitter=`osascript -e 'tell application &quot;Finder&quot;' -e 'activate' -e 'text returned of (display dialog &quot;Enter Twitter account&quot; with title &quot;Image Hosting&quot; default answer &quot;'&quot;$defaulttwitter&quot;'&quot; buttons {&quot;Cancel&quot;, &quot;Continue&quot;} default button 2)' -e 'end tell'`
  [ ! &quot;$twitter&quot; ] &amp;&amp; exit
  echo $twitter &gt; &quot;$APPSUPPORT/Default Twitter Account&quot;
&nbsp;
  # Create temp files
  [ -e &quot;$TMPDIR&quot; ] &amp;&amp; rm -rf &quot;$TMPDIR&quot;
  mkdir &quot;$TMPDIR&quot;
  cp &quot;$f&quot; &quot;$TMPDIR/$name.jpg&quot;
  echo &quot;$title
$twitter&quot; &gt; &quot;$TMPDIR/$name.meta&quot;
&nbsp;
  [ -f &quot;$GROWL&quot; ] &amp;&amp; $GROWL -n 'Image Hosting' &quot;Image Hosting: `basename &quot;$f&quot;`&quot; -m &quot;Image Hosting is uploading '$name'&quot;
&nbsp;
  # Upload
  retries=0
  while [ $retries -lt $UPLOADRETRIES ]; do
    result=`scp &quot;$TMPDIR&quot;/* &quot;$DEST&quot; 2&gt;&amp;1` &amp;&amp; break;
    [ -f &quot;$GROWL&quot; ] &amp;&amp; $GROWL -n &quot;Image Hosting: `basename &quot;$f&quot;`&quot; 'Image Hosting' -m 'Upload failed: Retrying'
    retries=$((retries+1))
  done
&nbsp;
  if [ $retries -ge $UPLOADRETRIES ]; then
    osascript -e 'tell application &quot;Finder&quot;' -e 'activate' -e 'display dialog &quot;Could not upload image.  Scp said: '&quot;$result&quot;'&quot; with title &quot;Image Hosting&quot; with icon Stop' -e 'end tell'
    exit
  fi
&nbsp;
  echo $name &gt;&gt; &quot;$APPSUPPORT/Taken Names&quot;
&nbsp;
  osascript -e 'tell application &quot;Finder&quot; to set the clipboard to &quot;'&quot;$URLPREFIX$name&quot;'&quot;'
&nbsp;
  [ -f &quot;$GROWL&quot; ] &amp;&amp; $GROWL -n 'Image Hosting' &quot;Image Hosting: `basename &quot;$f&quot;`&quot; -m &quot;Upload complete.  Available at $URLPREFIX/$name (copied to clipboard)&quot;
done</pre></div></div>


<p>To use it:</p>

<ol>
<li>Unzip it, </li>
<li>Put it into <code>Library/Services</code>, </li>
<li>Double-click on it to open it in Automator,</li>
<li>Change the settings at the top of the &#8216;Shell Script&#8217; segment &#8212; 

<ul>
<li>Set <code>DEST</code> to the <code>scp</code> destination</li>
<li>Set up <a href="http://www.google.com/search?q=ssh%20authorized_keys">key-based SSH authentication</a>, so you don&#8217;t have to enter the password to upload, or, if you&#8217;d prefer to use something other than <code>scp</code> to upload the file, you can change the upload command further down in the script, underneath the &#8216;Upload&#8217; comment (look for <code>scp</code>)</li>
<li>Set <code>URLPREFIX</code> to <code>http://yoursite.com</code></li>
<li>If you have Growl and <code>growlnotify</code> installed, then set <code>GROWL</code> to the location of <code>growlnotify</code> (highly recommended)</li>
</ul></li>
<li>Save</li>
</ol>

<h2>Usage</h2>

<p>If you&#8217;re using Leopard, you may need to log out, then log back in to see the service &#8212; I&#8217;m not entirely certain.  If you&#8217;re on Snow Leopard, you should hopefully be set.  Right-click on an image file in Finder, and click &#8216;<em>Send Image to Image Hosting</em>&#8216;.</p>

<p>You should be asked for a title, then asked for a Twitter account name (this will be remembered for next time), then the upload will happen, and when it completes, the URL to the uploaded image will be put onto the clipboard so you can paste straight into Twitter.</p>

<p>Voila.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1757" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/diy-twitter-image-hosting/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Links for June 3rd through June 18th</title>
		<link>http://atastypixel.com/blog/links-june-3rd-june-18th/</link>
		<comments>http://atastypixel.com/blog/links-june-3rd-june-18th/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 00:00:26 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1631</guid>
		<description><![CDATA[Links for June 3rd through June 18th: Ten logo design tips from the field &#124; Logo Design Love 10 astonishing CSS hacks and techniques Adaptive CSS-Layouts: New Era In Fluid Layouts? effective techniques to create 100%-functional adaptive CSS-layouts WordPress Theme Development Frameworks If you build and develop WordPress themes often, you will probably be fed [...]]]></description>
			<content:encoded><![CDATA[<p>Links for June 3rd through June 18th:</p>

<ul class="delicious-bookmarks">
<li><a href="http://www.logodesignlove.com/logo-design-tips">Ten logo design tips from the field | Logo Design Love</a> </li>
<li><a href="http://www.catswhocode.com/blog/10-astonishing-css-hacks-and-techniques">10 astonishing CSS hacks and techniques</a> </li>
<li><a href="http://www.smashingmagazine.com/2009/06/09/smart-fixes-for-fluid-layouts/">Adaptive CSS-Layouts: New Era In Fluid Layouts?</a> effective techniques to create 100%-functional adaptive CSS-layouts</li>
<li><a href="http://www.smashingmagazine.com/2009/05/27/wordpress-theme-development-frameworks/">WordPress Theme Development Frameworks</a> If you build and develop WordPress themes often, you will probably be fed up of all the repetitive code writing, the constantly checking of your mark-up and all you really want to do is focus on the design and the project-specific features. The answer is a WordPress development framework</li>
<li><a href="http://steveweller.com/articles/toolbar-icons/">How to Draw Pixel-Perfect iPhone Toolbar Icons</a> Using OmniGraffle</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1631" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-june-3rd-june-18th/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Links for May 21st through June 2nd</title>
		<link>http://atastypixel.com/blog/links-may-21st-june-2nd/</link>
		<comments>http://atastypixel.com/blog/links-may-21st-june-2nd/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 07:01:25 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Lifestyle]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1613</guid>
		<description><![CDATA[Links for May 21st through June 2nd: 49 Decent Virtual Assistant &#38; Personal Outsourcing Resources PHP: Display Adobe PSD files on a web page &#34;Any webdesigner know the PSD filetype, which is the Adobe Photoshop format. PSDs have a lot of great features, as such as layers, but they can&#8217;t being read by a browser. [...]]]></description>
			<content:encoded><![CDATA[<p>Links for May 21st through June 2nd:</p>

<ul class="delicious-bookmarks">
<li><a href="http://thegrowinglife.com/2008/04/49-decent-virtual-assistant-personal-outsourcing-resources/">49 Decent Virtual Assistant &amp; Personal Outsourcing Resources</a> </li>
<li><a href="http://www.catswhocode.com/blog/php-display-adobe-psd-files-on-a-web-page">PHP: Display Adobe PSD files on a web page</a> &quot;Any webdesigner know the PSD filetype, which is the Adobe Photoshop format. PSDs have a lot of great features, as such as layers, but they can&rsquo;t being read by a browser. Unless you use this great PHP class!&quot;</li>
<li><a href="http://www.iconfinder.net/">Iconfinder &#8211; Icon Search Made Easy</a> </li>
<li><a href="http://www.typetester.org/">Typetester &ndash; Compare fonts for the screen</a> </li>
<li><a href="http://www.kennettnet.co.uk/code/knappguide/">KNAppGuide</a> KNAppGuide is a Cocoa framework for embedding &ldquo;guides&rdquo; into your application, visually inspired by Apple Guide from the System 7 and 8 era</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1613" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-may-21st-june-2nd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Links for March 17th through April 24th</title>
		<link>http://atastypixel.com/blog/links-march-17th-april-24th/</link>
		<comments>http://atastypixel.com/blog/links-march-17th-april-24th/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 00:00:41 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1514</guid>
		<description><![CDATA[Links for March 17th through April 24th: XSD Schema XML Validator A XSD Schema validator in Java, provides lots of useful information; use it with a schema and an xml instance Three20 Three20 is a collection of iPhone UI classes, like a photo viewer, and general utilities, like an HTTP disk cache. Three20 is derived [...]]]></description>
			<content:encoded><![CDATA[<p>Links for March 17th through April 24th:</p>

<ul class="delicious-bookmarks">
<li><a href="http://www.herongyang.com/XML-Schema/JAXP-XSD-Schema-XML-Validator-Final-Version.html">XSD Schema XML Validator</a> A XSD Schema validator in Java, provides lots of useful information; use it with a schema and an xml instance</li>
<li><a href="http://github.com/joehewitt/three20/tree/master">Three20</a> Three20 is a collection of iPhone UI classes, like a photo viewer, and general utilities, like an HTTP disk cache. Three20 is derived from the Facebook iPhone app, which is one of the most downloaded iPhone apps ever.</li>
<li><a href="http://www.webdesignerwall.com/tutorials/css-decorative-gallery/">CSS Decorative Gallery</a> &#8230;How to decorate your images and photo galleries without editing the source images. The trick is very simple. All you need is an extra &lt;span&gt; tag and apply a background image to create the overlaying effect.</li>
<li><a href="http://en.wikipedia.org/wiki/Comet_(programming)">Comet (programming) &#8211; Wikipedia, the free encyclopedia</a> Comet is a neologism to describe a web application model in which a long-held HTTP request allows a web server to push data to a browser, without the browser explicitly requesting it</li>
<li><a href="http://www.cimgf.com/2008/03/26/cocoa-tutorial-awakefromnib-vs-applicationdidfinishlaunching/">Cocoa Is My Girlfriend &raquo; Cocoa Tutorial: awakeFromNib vs applicationDidFinishLaunching</a> A very good overview of the &#39;startup&#39; procedure for objects stored in IB nib/xibs.</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1514" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-march-17th-april-24th/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Private Tags WordPress Plugin</title>
		<link>http://atastypixel.com/blog/wordpress/plugins/private-tags/</link>
		<comments>http://atastypixel.com/blog/wordpress/plugins/private-tags/#comments</comments>
		<pubDate>Fri, 10 Apr 2009 09:23:17 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[Wordpress Plugins]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2009/04/10/private-tags-wordpress-plugin/</guid>
		<description><![CDATA[The &#8220;Private Tags&#8221; WordPress plugin allows users to specify a list of tags or categories to keep hidden from the public &#8211; all posts within the specified tags/categories, and the tags/categories themselves, will not be visible to anyone but the original author. Alternatively, in &#8216;inclusive&#8217; mode specify a list of tags/categories to make public &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>The &#8220;Private Tags&#8221; WordPress plugin allows users to specify a list of tags or categories to keep hidden from the public &#8211; all posts within the specified tags/categories, and the tags/categories themselves, will not be visible to anyone but the original author.</p>

<p>Alternatively, in &#8216;inclusive&#8217; mode specify a list of tags/categories to make public &#8211; all other tags/categories will remain hidden.</p>

<p><span id="more-1586"></span></p>

<h2>Download</h2>

<p>Download the Private Tags plugin at the <a href="http://wordpress.org/extend/plugins/private-tags/">WordPress plugin page</a></p>

<p>If you like Private Tags, please consider buying one of my <a href="http://atastypixel.com/products">products</a>.</p>

<h3>Installation</h3>

<ol>
<li>Unzip the package, and upload <code>private-tags</code> to the <code>/wp-content/plugins/</code> directory</li>
<li>Activate the plugin through the &#8216;Plugins&#8217; menu in WordPress</li>
<li>Visit &#8216;Private Tags&#8217; settings underneath WordPress settings to configure</li>
</ol>

<h3>Changes</h3>

<p><em>0.1</em> &#8211; Initial release</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1586" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/wordpress/plugins/private-tags/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Sneak preview of my new web framework Michaelangelo</title>
		<link>http://atastypixel.com/blog/sneak-preview-of-my-new-web-framework-michaelangelo/</link>
		<comments>http://atastypixel.com/blog/sneak-preview-of-my-new-web-framework-michaelangelo/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 14:39:22 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2009/03/28/sneak-preview-of-my-new-web-framework-michaelangelo/</guid>
		<description><![CDATA[I&#8217;ve been working on a new web framework which provides image theming &#8211; a little like what Elegant Grunge does with its image frames, but much more sophisticated. For example: This is a PHP framework that uses the common GD library to manipulate images. It&#8217;s main interface is a content filter &#8211; give it HTML, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a new web framework which provides image theming &#8211; a little like what <a href="http://atastypixel.com/blog/wordpress/themes/elegant-grunge">Elegant Grunge</a> does with its image frames, but much more sophisticated.</p>

<p>For example:
<img src="http://atastypixel.com/blog/wp-content/michaelangelo-images/be8dc62a1730cbd98d16f2f8dedfb147.jpg" width="449" height="245" alt="boathouse.jpg" title="boathouse.jpg" class="aligncenter sticky-tape tape-corners noframe" /></p>

<p><img src="http://atastypixel.com/blog/wp-content/michaelangelo-images/d63aad7828e8d537818261cf4dfc9927.jpg" width="471" alt="A dynamic caption" title="A dynamic caption" class="aligncenter polaroid rotation frame-title noframe" height="293" /></p>

<p><img src="http://atastypixel.com/blog/wp-content/michaelangelo-images/f6dc80edccaa4b113042bd2074f187f5.jpg" width="286" height="414" alt="thailand.jpg" title="thailand.jpg" class="alignright wood-frame noframe" /></p>

<p>This is a PHP framework that uses the common GD library to manipulate images.</p>

<p>It&#8217;s main interface is a content filter &#8211; give it HTML, containing images, and it will return the same HTML modified so that the images are now the converted versions, according to their &#8216;class&#8217; attributes, with appropriate width/height attributes, etc.  This makes it super easy to work with.</p>

<p>It stands alone, but it is also going to be a WordPress plugin (as you can see on this site, it&#8217;s already operational), a Joomla plugin, and I&#8217;m considering establishing a web service too, so those who don&#8217;t have adequate software on their server can still use it.</p>

<p><img src="http://atastypixel.com/blog/wp-content/michaelangelo-images/6815f5612dc94ea010b01cc3c0266b98.jpg" width="415" height="314" alt="IMG_1773.jpg" title="IMG_1773.jpg" class="aligncenter wood-frame noframe" /></p>

<p>It has a plugin-based architecture so anyone can add new &#8216;themes&#8217; (<em>props to my partner Katherine for that beautiful wooden frame, by the way</em>).  I&#8217;m going to also implement a simple XML-based plugin schema, and possibly an interface to it, so that it&#8217;s easy to do so.  I&#8217;m planning a &#8216;community&#8217; style directory site to host contributed styles.</p>

<p>The base frame rendering code is such that it is trivially easy to add a new &#8216;theme&#8217;.  It extracts segments from a single frame image, and handles seamless tiling to make the frame the right dimensions, so you don&#8217;t even have to worry about overlapping regions.</p>

<p>I will release it soon, after adding a little more content &#8211; keep your eyes peeled.</p>

<p>For now, check out the <a href="http://atastypixel.com/blog/wp-content/plugins/michaelangelo/Michaelangelo/Sample">Michaelangelo showcase</a>, which gives an idea of the different styles, and contains an interactive sampler to play with styles (<em>IE users should stop being IE users to view this</em>).</p>

<p>Doing my bit to beautify the web.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1566" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/sneak-preview-of-my-new-web-framework-michaelangelo/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Links for March 6th through March 16th</title>
		<link>http://atastypixel.com/blog/links-march-6th-march-16th/</link>
		<comments>http://atastypixel.com/blog/links-march-6th-march-16th/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 08:00:30 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Travel]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1488</guid>
		<description><![CDATA[Links for March 6th through March 16th: CSS Code Snippets : 15 Wicked Tricks Some useful CSS tricks; of particular interest: cross-platform min-height, a trick to clear floats (without needing a &#39;clearing&#39; div), and page breaks 45+ New jQuery Techniques For Good User Experience Here are over 45 impressive jQuery plug-ins and techniques that have [...]]]></description>
			<content:encoded><![CDATA[<p>Links for March 6th through March 16th:</p>

<ul class="delicious-bookmarks">
<li><a href="http://devsnippets.com/reviews/css-code-snippets-15-wicked-tricks.html">CSS Code Snippets : 15 Wicked Tricks</a> Some useful CSS tricks; of particular interest: cross-platform min-height, a trick to clear floats (without needing a &#39;clearing&#39; div), and page breaks</li>
<li><a href="http://www.smashingmagazine.com/2009/01/15/45-new-jquery-techniques-for-a-good-user-experience/">45+ New jQuery Techniques For Good User Experience</a> Here are over 45 impressive jQuery plug-ins and techniques that have been recently created and that could make the development of your next website an easier and more interesting experience than the last.</li>
<li><a href="http://digital-sushi.org/entry/how-to-create-a-disk-image-installer-for-apple-mac-os-x/">How to Create a Disk Image Installer for Apple Mac OS X</a> </li>
<li><a href="http://th30z.netsons.org/2009/03/cocoa-sidebar-with-badges-take-2/">Cocoa: Sidebar with Badges, Take 2</a> &#39;Source list&#39;-esque sidebar with support for badges</li>
<li><a href="http://www.soultravelers3.com/">soultravelers3</a> A family of three from Santa Cruz, California on an epic odyssey: open-ended, years long slow trip around the world as a family adventure, unschool, spiritual journey and lifestyle.</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1488" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-march-6th-march-16th/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Links for February 28th through March 3rd</title>
		<link>http://atastypixel.com/blog/links-february-28th-march-3rd/</link>
		<comments>http://atastypixel.com/blog/links-february-28th-march-3rd/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 03:00:23 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1455</guid>
		<description><![CDATA[Links for February 28th through March 3rd: Lifehacker readers: Most Popular Reliable and Affordable Web Hosts Top seven hosts as voted by readers (DreamHost, Blue Host, NearlyFreeSpeech.NET, 1&#38;1, GoDaddy, HostGator and A Small Orange) Domainr, the domain name search engine Given a name, suggests a variety of different domain name possibilities, and reports on availability [...]]]></description>
			<content:encoded><![CDATA[<p>Links for February 28th through March 3rd:</p>

<ul class="delicious-bookmarks">
<li><a href="http://lifehacker.com/5124856/most-popular-reliable-and-affordable-web-hosts">Lifehacker readers: Most Popular Reliable and Affordable Web Hosts</a> Top seven hosts as voted by readers (DreamHost, Blue Host, NearlyFreeSpeech.NET, 1&amp;1, GoDaddy, HostGator and A Small Orange)</li>
<li><a href="http://domai.nr/">Domainr, the domain name search engine</a> Given a name, suggests a variety of different domain name possibilities, and reports on availability</li>
<li><a href="http://www.schillmania.com/content/projects/even-more-rounded-corners/">Even More Rounded Corners With CSS &#8211; Schillmania.com</a> Single-image, PNG-based, fluid rounded corner dialogs with support for borders, alpha transparency throughout, gradients, patterns and whatever else you (or your designer) could want</li>
<li><a href="http://www.smashingmagazine.com/2009/02/04/50-beautiful-and-user-friendly-navigation-menus/">50 Beautiful And User-Friendly Navigation Menus</a> Navigation inspiration</li>
<li><a href="http://ocrterminal.com/">OCR Terminal</a> OCR Terminal is a free online Optical Character Recognition service that allows you to convert scanned images and PDF&#39;s into editable and text searchable documents. It accurately preserves formatting and layout of documents.</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1455" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-february-28th-march-3rd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Website maintenance with Textmate and FTP/SSH Bundle</title>
		<link>http://atastypixel.com/blog/website-maintenance-with-textmate-and-ftpssh-bundle/</link>
		<comments>http://atastypixel.com/blog/website-maintenance-with-textmate-and-ftpssh-bundle/#comments</comments>
		<pubDate>Wed, 28 Jan 2009 00:54:21 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2009/01/28/website-maintenance-with-textmate-and-ftpssh-bundle/</guid>
		<description><![CDATA[I tend to work on local copies of my websites, which have either corresponding vhost entries in my local Apache configuration, or are simply symlinked to my ~/Sites folder. That way, I can test to make sure everything&#8217;s 100% before I make changes live. This has typically been a bit of a messy workflow &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>I tend to work on local copies of my websites, which have either corresponding <em>vhost</em> entries in my local Apache configuration, or are simply symlinked to my <em>~/Sites</em> folder.  That way, I can test to make sure everything&#8217;s 100% before I make changes live.</p>

<p>This has typically been a bit of a messy workflow &#8211; I make changes, and then when happy, either open up a terminal and <em>rsync</em> the whole lot over, or open up Flow/Transmit and manually copy the changed files over.  The whole thing makes me disinclined to make changes at all!</p>

<p>That is, until on a whim, I did a google search for a Textmate FTP bundle, and found Bernhard Fürst&#8217;s <a href="http://fuerstnet.de/en/ftpssh-bundle-textmate">FTP/SSH Bundle for Textmate</a>. This little gem lets you configure FTP settings for a project, then hit Option-S to save to the remote server, or Option-R to reload from the remote server.  This way, when I&#8217;m happy with the changes, I just whack Option-S to send them to the server straight from Textmate.</p>

<p>That makes me happy.</p>

<p>One little caveat &#8211; the bundle does an odd thing with the project directory, opting to use the parent folder of the Textmate project file, something which won&#8217;t work for ad hoc projects, when one just drags a folder into Textmate (one of my favourite features).  A quick fix:</p>

<ol>
<li>Find <em>Library/Application Support/TextMate/Bundles/FTP-SSH</em> and open its contents</li>
<li>Open up <em>Support/lib/helper_functions.php</em></li>
<li>Change the <code>$PROJECT_DIR</code> definition on line 15 to:

<p><code>$PROJECT_DIR = $_ENV['TM_PROJECT_DIRECTORY'];</code></p></li>
</ol>

<p>Voila!</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1323" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/website-maintenance-with-textmate-and-ftpssh-bundle/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Elegant Grunge 1.0 released</title>
		<link>http://atastypixel.com/blog/elegant-grunge-10-released/</link>
		<comments>http://atastypixel.com/blog/elegant-grunge-10-released/#comments</comments>
		<pubDate>Mon, 29 Dec 2008 11:12:06 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[Wordpress Themes]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2008/12/29/elegant-grunge-10-released/</guid>
		<description><![CDATA[A significant update to my WordPress theme, Elegant Grunge, has been released. New features and fixes include: Configurable sidebars! Choose from no sidebar, a sidebar on the right (the standard layout), or a double sidebar on the right! Support for WP 2.7 paginated and threaded comments Support for a custom header image &#8211; just enter [...]]]></description>
			<content:encoded><![CDATA[<p>A significant update to my WordPress theme, <a href="http://atastypixel.com/blog/wordpress/themes/elegant-grunge/">Elegant Grunge</a>, has been released. New features and fixes include:</p>

<ul>
<li>Configurable sidebars! Choose from no sidebar, a sidebar on the right (the standard layout), or a double sidebar on the right!</li>
<li>Support for WP 2.7 paginated and threaded comments</li>
<li>Support for a custom header image &#8211; just enter a URL to an image, typically a transparent PNG, and it will appear in the header instead of the text (SEO friendly)</li>
<li>Some bug, compatibility and i18n fixes</li>
</ul>

<p>&lt;</p>

<p>p>Note: If you have problems with this theme, please post your question at the <a href="http://wordpress.org/tags/elegant-grunge">WordPress forums</a>.  Please don&#8217;t contact me directly, as I don&#8217;t have the resources to help you.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1249" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/elegant-grunge-10-released/feed/</wfw:commentRss>
		<slash:comments>66</slash:comments>
		</item>
		<item>
		<title>Links for November 24th through December 9th</title>
		<link>http://atastypixel.com/blog/links-%datestart-december-9th/</link>
		<comments>http://atastypixel.com/blog/links-%datestart-december-9th/#comments</comments>
		<pubDate>Tue, 09 Dec 2008 01:00:02 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Geocoding]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Location]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1173</guid>
		<description><![CDATA[Links for November 24th through December 9th: Creating libraries for the iPhone Discussion on creating static libraries for the iPhone Photoshop Tutorials &#8211; Layered HDR Tone Mapping Learn how to tone map with Photoshop CS3 to create beautiful high dynamic range (HDR) photos. The final result is exceedingly better than Photoshop&#39;s local adaptation and similar [...]]]></description>
			<content:encoded><![CDATA[<p>Links for November 24th through December 9th:</p>

<ul class="delicious-bookmarks">
<li><a href="https://devforums.apple.com/message/5389">Creating libraries for the iPhone</a> Discussion on creating static libraries for the iPhone</li>
<li><a href="http://photoshoptutorials.ws/photoshop-tutorials/photo-manipulation/layered-hdr-tone-mapping.html">Photoshop Tutorials &#8211; Layered HDR Tone Mapping</a> Learn how to tone map with Photoshop CS3 to create beautiful high dynamic range (HDR) photos. The final result is exceedingly better than Photoshop&#39;s local adaptation and similar to Photomatix&#39;s tone mapping.</li>
<li><a href="http://www.ajaxload.info/">Ajaxload &#8211; Ajax loading gif generator</a> Generate loading animation images, given type, background and foreground.</li>
<li><a href="http://www.bittbox.com/freebies/free-texture-tuesday-inaugural/">Free Texture Tuesday  |  BittBox</a> &quot;Jay over at Bittbox has just announced that he will be giving away five high resolution textures (3,000 x 2,000 pixels) every Tuesday of the year, absolutely free!&quot;</li>
<li><a href="http://www.geonames.org/">GeoNames</a> Free service (including webservice) to search for place names, yielding co-ordinates and a feature class.</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1173" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-%datestart-december-9th/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RSS aggregation for PHP</title>
		<link>http://atastypixel.com/blog/php-rss-aggregator/</link>
		<comments>http://atastypixel.com/blog/php-rss-aggregator/#comments</comments>
		<pubDate>Thu, 27 Nov 2008 14:44:16 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2008/11/27/rss-aggregation-for-php/</guid>
		<description><![CDATA[I have written a mechanism in PHP that can take several RSS feeds, filter and manipulate them, and re-display them in either RSS or straight HTML. This can also manipulate content (through the preg_replace function, and configurable per-feed), such as removing names from Twitter entries. I&#8217;m using it on loopyapp.com to show all relevant items [...]]]></description>
			<content:encoded><![CDATA[<p>I have written a mechanism in PHP that can take several RSS feeds, filter and manipulate them, and re-display them in either RSS or straight HTML.</p>

<p>This can also manipulate content (through the <em>preg_replace</em> function, and configurable per-feed), such as removing names from Twitter entries.  I&#8217;m using it on <a href="http://loopyapp.com">loopyapp.com</a> to show all relevant items from both this blog and my Twitter feed automatically, as an alternative to creating a separate blog.  I&#8217;m also using it on <a href="http://atastypixel.com/blog/aggregate/rss.php">this blog</a>, to incorporate blog entries and Twitter postings.</p>

<p>It uses the <a href="http://magpierss.sourceforge.net/">MagpieRSS</a> RSS parser for PHP, which provides some nice functionality, including caching.</p>

<p>Here&#8217;s the code: <a href="http://atastypixel.com/blog/wp-content/uploads/2009/03/aggregate.zip" title="aggregate.zip">aggregate.zip</a>
</p>

<p>To use it, unzip it to somewhere in your webroot, then edit <em>aggregate.php</em> and possibly <em>rss.php</em> to set your configuration.  Make sure that either the aggregate directory is writable, or create a &#8216;cache&#8217; directory within and make that writeable, to enable caching.  Point your web browser to the <em>rss.php</em> file to immediately view an RSS feed aggregating your supplied feeds. To add a link to the RSS from a website, add it in the header:</p>


<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;link rel=&quot;alternate&quot; type=&quot;application/rss+xml&quot; title=&quot;RSS Feed&quot; href=&quot;http://mysite.com/aggregate/rss.php&quot; /&gt;</pre></div></div>


<p>To include content in a website, the provided <tt>render_aggregate_items</tt> function will do most of the work, or you can write your own rendering code. You just have to include the file, use the functions to obtain and draw the content, and then provide your own CSS styling.  Example:</p>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;div class=&quot;items&quot;&gt;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;aggregate.php&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
render_aggregate_items<span style="color: #009900;">&#40;</span>aggregate_items<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/div&gt;</pre></div></div>


<p>A more comprehensive example is in <em>sample.php</em>.</p>

<p>The code is GPL, so use it however you want &#8211; keep the header comments there, though.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1191" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/php-rss-aggregator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom Permalinks</title>
		<link>http://atastypixel.com/blog/wordpress/plugins/custom-permalinks/</link>
		<comments>http://atastypixel.com/blog/wordpress/plugins/custom-permalinks/#comments</comments>
		<pubDate>Sat, 01 Nov 2008 07:48:51 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[Wordpress Plugins]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2008/11/01/custom-permalinks/</guid>
		<description><![CDATA[Custom Permalinks is a Wordpress plugin that gives you ultimate control over your site structure by freely configuring URLs for posts, tags and categories.]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://atastypixel.com/blog/wp-content/uploads/2008/11/200811011939.jpg" rel="lightbox[1042]"><img src="http://atastypixel.com/blog/wp-content/uploads/2008/11/200811011939-tm.jpg" width="300" height="164" alt="200811011939.jpg" title="200811011939.jpg" /></a></p>

<p>Custom Permalinks is a WordPress plugin that gives you ultimate control over your site structure.</p>

<p>Lay out your site the way <em>you</em> want it. Set the URL of any post, tag or category to anything you want. Old permalinks will redirect properly to the new address.</p>

<p><span id="more-1042"></span></p>

<h3>Download</h3>

<p>Download Custom Permalinks for WordPress from the <a href="http://wordpress.org/extend/plugins/custom-permalinks/">Custom Permalinks WordPress plugin</a> page.</p>

<p>If you like Custom Permalinks, please consider buying one of my <a href="http://atastypixel.com/products">products</a>.</p>

<h3>Installation</h3>

<ol>
  <li>Unzip the package, and upload &#8216;custom-permalinks&#8217; to the &#8216;/wp-content/plugins/&#8217; directory</li>

  <li>Activate the plugin through the &#8216;Plugins&#8217; menu in WordPress</li>

  <li>Edit any post, tag or category to set a custom permalink.</li>
</ol>

<h3>Configuration</h3>

<ul>
  <li>Open or create a post, tag, or category.</li>

  <li>Under &#8216;Custom Permalink&#8217;, type in a URL, not including the http://domain part of the address.<br /></li>

  <li>Save</li>
</ul>

<p>Now, the post/tag/category will be accessible at the custom address.</p>

<p>Incoming visitors from old links will be redirected via a 301 redirect to the new address.</p>

<p>See Custom Permalinks in action right here! (See the address you&#8217;re currently at?)</p>

<h3>Notes</h3>

<h4>Interacting with other plugins which modify the URL</h4>

<p>If you notice that some plugins, such as Keyvan Minoukadeh&#8217;s <a href="http://www.keyvan.net/code/paged-comments/">Paged Comments</a> plugin, are not operating correctly, then ensure that your custom permalinks have a trailing slash (or not, if your standard permalinks do not have trailing slashes).</p>

<p>The Paged Comments plugin, and possibly others, work by adding a path component to the URL to signify state (eg. /comment-page-1), then hiding that path component from WordPress.</p>

<p>If you have a custom permalink with a different trailing / configuration to your normal permalinks (i.e., your custom permalink has a trailing / when others don&#8217;t, or vice versa),  you will notice that these plugins no longer work, because Custom Permalinks is correcting the URL, which overwrites the plugin&#8217;s changes.</p>

<p>If you notice this happening, make sure you have a trailing / on your permalink, or remove the trailing slash if your standard permalinks do not have a trailing /.</p>

<h4>Hiding the custom_permalinks custom field</h4>

<p>A user recently asked for this; I&#8217;m not going to include it in the plugin (some people, including me, want to see this field, because we set it manually sometimes), but I&#8217;m happy to make a plugin-let to make it happen.</p>

<p>Here it is: <a href="http://atastypixel.com/blog/wp-content/uploads/2010/01/hide_custom_permalink_field.php_.zip" title="hide_custom_permalink_field.php.zip">hide_custom_permalink_field.php.zip</a></p>

<p>Put it in your <code>wp-content/plugins</code> folder and turn it on in Plugins under WP admin.</p>

<h3>FAQ</h3>

<h4>I just get a &#8220;404 error&#8221; message when I try to visit a custom permalink</h4>

<p>Have you configured your default permalinks to be other than the default &#8220;?p=123&#8243; style?  If not, you probably haven&#8217;t got URL rewriting enabled.  Either set your permalinks to one of the other options (or a custom layout), or add the following to your <code>.htaccess</code> file in your webroot, creating this file if necessary:</p>

<p><pre>
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
&lt;/IfModule&gt;
</pre></p>

<h3>History</h3>

<p><strong>Version 0.6.1:</strong> Fix bug causing incorrect link from &#8220;View Post&#8221;/&#8221;View Page&#8221; button in post/page editor</p>

<p><strong>Version 0.6:</strong> Fix infinite redirect for permalinks ending in a / (critical fix), and moved post/page permalinks settings to top of edit form, replacing prior permalink display</p>

<p><strong>Version 0.5.3:</strong> Fix for invalid URL redirect (eg. http://domain.comfolder/file.html instead of http://domain.com/folder/file.html) when using permalinks without a trailing slash (like &#8230;/%postname%.html)</p>

<p><strong>Version 0.5.2:</strong> Bugfix for matching posts when there are multiple posts that match parts of the query</p>

<p><strong>Version 0.5.1:</strong> Compatibility fix for WP 2.7&#8242;s tag/category pages</p>

<p><strong>Version 0.5:</strong> Support for installations in subdirectories (i.e. not located at the webroot). This should make Custom Permalinks start working for many people.</p>

<p><strong>Version 0.4.1:</strong> WP 2.7 compatability fixes; fix for bug encountered when publishing a draft, or reverting to draft status, and fix for placeholder permalink value for pages</p>

<p><strong>Version 0.4:</strong> Added support for pages, and fixed a bug concerning post drafts.</p>

<p><strong>Version 0.3:</strong> Largely rewritten to provide more robust handling of trailing slashes, proper support for trailing URL components (eg. paging)</p>

<p><strong>Version 0.2:</strong> Added management page to display all custom permalinks, with an option to revert selected items</p>

<p><strong>Version 0.1.1</strong>: Fixed problem with categories</p>

<p><strong>Version 0.1</strong>: Initial release</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1042" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/wordpress/plugins/custom-permalinks/feed/</wfw:commentRss>
		<slash:comments>130</slash:comments>
		</item>
		<item>
		<title>Some useful mini-plugins for WordPress</title>
		<link>http://atastypixel.com/blog/some-useful-mini-plugins-for-wordpress/</link>
		<comments>http://atastypixel.com/blog/some-useful-mini-plugins-for-wordpress/#comments</comments>
		<pubDate>Sat, 18 Oct 2008 00:06:47 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2008/10/18/some-useful-mini-plugins-for-wordpress/</guid>
		<description><![CDATA[Three simple Wordpress plugins that provide shortcode-based functionality: Simple Google adsense insertion, a FLV media player, and a music list with flash players.]]></description>
			<content:encoded><![CDATA[<p>Originally for my own use, I put together a couple of WordPress plugins, which I thought I&#8217;d make available in case they were useful to anyone else.</p>

<h3>Google AdSense shortcode</h3>

<p>This is the simplest plugin, which provides an &#8216;adsense&#8217; shortcode to output a Google ad. To use it, use Google&#8217;s tools to create the ad, then paste it into the php file where indicated, then put <tt>{adsense}</tt> <small>(replace the curly braces with square brackets)</small> in posts/pages where you want the ad to appear (remove the spaces around the square brackets).</p>

<p><a href="http://atastypixel.com/blog/wp-content/uploads/2008/10/adsensephp.zip" title="adsense.php.zip">adsense.php.zip</a></p>

<p>And now for a demo + shameless attempt at monetization:</p>

<p></p>

<h3>Media player</h3>

<p>This one is useful if you occasionally post a video file on your blog, and host it locally. If you use video more frequently, there are plugins that probably are more suited, but I personally didn&#8217;t want the overhead, and I wanted to store videos in the standard upload locations, instead of having a separate repository, which seems to be what other plugins do.</p>

<p>This one uses the <a href="http://www.jeroenwijering.com/?item=JW_FLV_Player">JW FLV player</a>, provided in the plugin. Use something like:</p>

<p><tt>{media source="http://my.site.com/path/to/video.flv" width="400" height="308" preview="http://my.site.com/path/to/preview.jpg"}</tt><br /></p>

<p><span style="line-height: 16px;"><small>(replace the curly braces with square brackets)</small><br /></span></p>

<p><a href="http://atastypixel.com/blog/wp-content/uploads/2008/10/mediaplayer.zip" title="mediaplayer.zip">mediaplayer.zip</a></p>

<p>I used this just the other day on a post demonstrating the <a href="http://atastypixel.com/blog/2008/10/13/rpea-mapping-algorithm-clip/">output of the simulator I&#8217;ve written for my PhD</a>.</p>

<h3>Music player</h3>

<p>This is the plugin that renders the content for my <a href="http://atastypixel.com/blog/music">music</a> page, as well as providing mini-players for other posts. Give it a path to a directory, and it will display all mp3 files in that directory with flash players based on the <a href="http://musicplayer.sourceforge.net/">XSPF Web Music Player</a>. Recently-added mp3 files will be marked as &#8216;New&#8217;. Use something like:</p>

<p><tt>{musiclist path="path/to/my/music"}</tt><br /></p>

<p><small>(replace the curly braces with square brackets; add optional nolink=&#8221;true&#8221; parameter to avoid linking to the mp3 files from their titles)</small><br /></p>

<p>For just one track, use:</p>

<p><tt>{audio source="path/to/audio.mp3"}</tt></p>

<p><a href="http://atastypixel.com/blog/wp-content/uploads/2008/11/musicplayer.zip" title="musicplayer.zip">musicplayer.zip</a></p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=972" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/some-useful-mini-plugins-for-wordpress/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>
