<?xml version="1.0"?>
<?xml-stylesheet 
 href="http://www.w3.org/2000/08/w3c-synd/style.css" type="text/css"
?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel rdf:about="http://planet-php.net"><title>Planet PHP</title><link>http://planet-php.net</link><description>People blogging about PHP</description><dc:language>en</dc:language><dc:date>2010-07-30T17:52:00Z</dc:date><dc:creator>NN</dc:creator><admin:generatorAgent rdf:resource="http://planet-php.net"/><admin:errorReportsTo rdf:resource="mailto:chregu@bitflux.ch"/><sy:updatePeriod>hourly</sy:updatePeriod><sy:updateFrequency>1</sy:updateFrequency><sy:updateBase>2000-01-01T12:00+00:00</sy:updateBase><items><rdf:Seq><rdf:li rdf:resource="http://devzone.zend.com/article/12367-Zend-Framework-1.10.7-Released"/><rdf:li rdf:resource="http://www.thespanner.co.uk/2010/07/30/sandboxed-dom-api/"/><rdf:li rdf:resource="http://shiflett.org/blog/2010/jul/auto-increment-with-mongodb"/><rdf:li rdf:resource="http://seancoates.com/blogs/a-case-of-mistaken-iterator"/><rdf:li rdf:resource="http://www.leftontheweb.com/message/Open_Source_Your_Career_my_story"/><rdf:li rdf:resource="http://www.brandonsavage.net/july-slides/"/><rdf:li rdf:resource="http://blog.phpdeveloper.org/?p=274"/><rdf:li rdf:resource="http://seancoates.com/blogs/beer-alchemy-integration"/><rdf:li rdf:resource="http://bergie.iki.fi/blog/aloha_and_the_art_of_semantic_web_content/"/><rdf:li rdf:resource="http://sebastian-bergmann.de/archives/894-Using-HipHop-for-Static-Analysis.html"/></rdf:Seq></items></channel><item rdf:about="http://devzone.zend.com/article/12367-Zend-Framework-1.10.7-Released"><title>Zend Framework 1.10.7 Released</title><link>http://devzone.zend.com/article/12367-Zend-Framework-1.10.7-Released</link><dc:date>2010-07-30T17:52:00Z</dc:date><dc:creator>Zend Developer Zone</dc:creator><description><![CDATA[
                  
    The Zend Framework team announces the immediate availability of Zend
    Framework 1.10.7, our seventh maintenance release in the 1.10 series.  This
    release includes around 60 bug fixes.
 

 
    For those uses of  Zend_Service_Twitter , please ensure you
    upgrade to 1.10.6 or 1.10.7 ASAP. These releases introduce a change in the
     Zend_Service_TWitter  API that enforces the use of OAuth by
    default when using methods that require authentication. The change was
    introduced to help prepare Zend Framework users for the  Twitter
    OAuthcalypse  in mid-August. (If you cannot upgrade,  there
    are other ways to integrate  Zend_Oauth  with
     Zend_Service_Twitter  .)
 

            ]]></description><content:encoded><![CDATA[
                  
    The Zend Framework team announces the immediate availability of Zend
    Framework 1.10.7, our seventh maintenance release in the 1.10 series.  This
    release includes around 60 bug fixes.
 

 
    For those uses of  Zend_Service_Twitter , please ensure you
    upgrade to 1.10.6 or 1.10.7 ASAP. These releases introduce a change in the
     Zend_Service_TWitter  API that enforces the use of OAuth by
    default when using methods that require authentication. The change was
    introduced to help prepare Zend Framework users for the  Twitter
    OAuthcalypse  in mid-August. (If you cannot upgrade,  there
    are other ways to integrate  Zend_Oauth  with
     Zend_Service_Twitter  .)
 

            ]]></content:encoded></item><item rdf:about="http://www.thespanner.co.uk/2010/07/30/sandboxed-dom-api/"><title>Sandboxed DOM API</title><link>http://www.thespanner.co.uk/2010/07/30/sandboxed-dom-api/</link><dc:date>2010-07-30T10:52:00Z</dc:date><dc:creator>Gareth Heyes</dc:creator><description><![CDATA[Description
I finally sat down and started work on a sandboxed DOM API. Originally I was just going to develop a new framework because the DOM is messy but instead I decided it would be cool to have a safe simulated DOM instead and build a framework on top of that.
It isn’t complete yet and there’s [...]]]></description><content:encoded><![CDATA[<h3>Description</h3>
<p>I finally sat down and started work on a sandboxed DOM API. Originally I was just going to develop a new framework because the DOM is messy but instead I decided it would be cool to have a safe simulated DOM instead and build a framework on top of that.</p>
<p>It isn’t complete yet and there’s still a lot of work to do but it’s working pretty good. I still need to run some tests on it and try to break it but I don’t have time at the moment as I need to do other stuff.</p>
<p>One of the problems making a DOM API is that IE doesn’t have setter support even in IE8 it doesn’t allow you to define setters on normal objects. Because I spend most of my time hacking stuff it was a fun challenge to make IE support setters on DOM objects and keep my sandboxed whitelists.</p>
<p>It’s quite complicated and quite ugly in parts but it works and I think it’s the only way to support legacy browsers like IE7.</p>
<h3>How it works</h3>
<p>I have to test for the various setter support including defineSetter, Object.defineProperty and revert to the legacy onpropertychange. Object.defineProperty works fine in IE8 when using a DOM object but I encountered problems when I needed to assign to a sandboxed normal object. Here it gets ugly, I had to create a DOM object for any styles used by a node, this way both Object.defineProperty and onpropertychange allow me to monitor any assignments to the fake style object.</p>
<pre lang="javascript">
var styles = document.createElement('span');
node.$style$ = styles;
Object.defineProperty(node.$style$, '$'+cssProp+'$', {});
document.getElementById('styleObjs').appendChild(styles);
node.$style$ = styles;
node.$style$.onpropertychange = function(){}
</pre>
<p>As you can see with the code sample above I have to append the fake style DOM object for onpropertychange otherwise it won’t be called on assignments.</p>
<p>You can see this working by using the following test code:-</p>
<pre lang="javascript">
document.getElementById('x').style.color='#ccc';
</pre>
<p>So I proxy off all these functions and make the root node any html object, I use CSSReg and htmlReg to sandbox each modification to a property. Finally where it got complicated was supporting events, currently I only support “onclick” as I’m still testing but what happens is because the code is already sandboxed I don’t need to perform a rewrite so I pass this to JSReg as it’s already been converted, I supply the “this” object as the html element this allows the triggered event to call “this” as the current element.</p>
<p>That’s it! I’ve donated the code to OWASP and it will be free to use in your projects, any help testing or suggestions are most welcome, enjoy the demo!</p>
<p><a href="http://www.businessinfo.co.uk/labs/DomAPI/DomAPI.html">Sandboxed DOM API</a></p>
]]></content:encoded></item><item rdf:about="http://shiflett.org/blog/2010/jul/auto-increment-with-mongodb"><title>Auto Increment with MongoDB</title><link>http://shiflett.org/blog/2010/jul/auto-increment-with-mongodb</link><dc:date>2010-07-29T19:52:00Z</dc:date><dc:creator>Chris Shiflett</dc:creator><description><![CDATA[We are currently working on an app that uses a number of technologies, including PHP, Python, and MongoDB. Recently, a need arose to use sequential identifiers for users, similar to an auto_increment column in MySQL.

If you've used MongoDB, you migh...]]></description><content:encoded><![CDATA[<p><a href="http://analog.coop/">We</a> are currently working on an app that uses a number of technologies, including PHP, Python, and <a href="http://mongodb.org/">MongoDB</a>. Recently, a need arose to use sequential identifiers for users, similar to an <code>auto_increment</code> column in MySQL.</p>

<div class="note"><p>If you've used MongoDB, you might be familiar with the default behavior of using a <a href="http://en.wikipedia.org/wiki/Universally_unique_identifier"><abbr title="universally unique identifier">UUID</abbr></a> as the primary key. This is convenient, especially if you partition your database across servers, because you don't have to coordinate the primary key in any way. If you use sequential identifiers (as I demonstrate in this post), you can use multiple servers and interleave identifiers by advancing each server's sequence by the total number of servers. (For example, with two servers, advance each sequence by two, so one server generates even identifiers, and the other generates odd.)</p>
<p>I'd rather not discuss the advantages and disadvantages of either approach, because it's exactly this debate that makes it very difficult to find any useful information on using sequential identifiers with MongoDB. Instead, I'm just going to explain how I did it, and hope this is helpful to someone. :-)</p></div>

<p>First, create a sequence collection that you can use to determine the next identifier in the sequence. The following creates a collection called <code>seq</code> that has a single sequence in it (for <code>users</code>), but you can add as many as you need:</p>

<pre class="code">
<code>db.seq.insert({"_id":"users", "seq":new NumberLong(1)});</code>
</pre>

<div class="note"><p>If you assign <code>seq</code> to <code>1</code> instead of <code>new NumberLong(1)</code>, it will be interpreted as a float due to a JavaScript quirk.</p></div>

<p>Before adding a new user, you need to increment the sequence by one and fetch the next identifier. Fortunately, the <a href="http://mongodb.org/display/DOCS/findandmodify+Command">findandmodify() command</a> provides an atomic way to do this. Using the MongoDB shell, the command would look something like this:</p>

<pre class="code">
<code>db.seq.findAndModify({</code>
<code>    query: {"_id":"users"},</code>
<code>    update: {$inc: {"seq":1}},</code>
<code>    new: true</code>
<code>});</code>
</pre>

<p>Because I'm using <a href="http://lithify.me/">Lithium</a>, I added a method for fetching the next identifier to my <code>User</code> model:</p>

<pre class="code">
<code><span class="default">&lt;?php</span></code>
<code><span class="default"> </span></code>
<code><span class="keyword">namespace </span><span class="default">app</span><span class="keyword">\</span><span class="default">models</span><span class="keyword">;</span></code>
<code><span class="keyword"> </span></code>
<code><span class="keyword">class </span><span class="default">User </span><span class="keyword">extends \</span><span class="default">lithium</span><span class="keyword">\</span><span class="default">data</span><span class="keyword">\</span><span class="default">Model </span><span class="keyword">{</span></code>
<code><span class="keyword"> </span></code>
<code><span class="keyword">    static public function </span><span class="default">seq</span><span class="keyword">() {</span></code>
<code><span class="keyword">        </span><span class="default">$seq </span><span class="keyword">= static::</span><span class="default">_connection</span><span class="keyword">()-></span><span class="default">connection</span><span class="keyword">-></span><span class="default">command</span><span class="keyword">(</span></code>
<code><span class="keyword">            array(</span><span class="string">'findandmodify' </span><span class="keyword">=> </span><span class="string">'seq'</span><span class="keyword">,</span></code>
<code><span class="keyword">                  </span><span class="string">'query' </span><span class="keyword">=> array(</span><span class="string">'_id' </span><span class="keyword">=> </span><span class="string">'users'</span><span class="keyword">),</span></code>
<code><span class="keyword">                  </span><span class="string">'update' </span><span class="keyword">=> array(</span><span class="string">'$inc' </span><span class="keyword">=> array(</span><span class="string">'seq' </span><span class="keyword">=> </span><span class="default">1</span><span class="keyword">)),</span></code>
<code><span class="keyword">                  </span><span class="string">'new' </span><span class="keyword">=> </span><span class="default">TRUE</span></code>
<code><span class="default">            </span><span class="keyword">)</span></code>
<code><span class="keyword">        );</span></code>
<code><span class="keyword"> </span></code>
<code><span class="keyword">        return </span><span class="default">$seq</span></code></pre><p><i>Truncated by Planet PHP, read more at <a href="http://shiflett.org/blog/2010/jul/auto-increment-with-mongodb">the original</a> (another 2980 bytes)</i></p>]]></content:encoded></item><item rdf:about="http://seancoates.com/blogs/a-case-of-mistaken-iterator"><title>A Case of Mistaken Iterator</title><link>http://seancoates.com/blogs/a-case-of-mistaken-iterator</link><dc:date>2010-07-29T15:30:00Z</dc:date><dc:creator>Sean Coates</dc:creator><description><![CDATA[]]></description><content:encoded><![CDATA[<p>Earlier this week, I spent most of a day tracing through code in search of
the source of a bug that was causing part of our application to fail in
strange ways.</p>

<p>In the back end, we have models that connect to <a href="http://couchdb.apache.org/">CouchDB</a>. These models implement the <a href="http://en.wikipedia.org/wiki/Iterator">Iterator</a> pattern to allow easy traversal of a record’s keys.</p>

<p>When I wrote the code to implement <code>Iterator</code> several months
ago, I dutifully checked the <a href="http://www.php.net/manual/">PHP
 Manual</a> and adapted the reference example that I found there:</p>

<pre class="highlight php">
&lt;?php
class Record implements Iterator
{
    // (partial class, showing the iterator implementation only)

	public $_data = array();

	public function rewind()
	{
		reset($this->_data);
	}
 
	public function current()
	{
		return current($this->_data);
	}
 
	public function key()
	{
		return key($this->_data);
	}
 
	public function next()
	{
		return next($this->_data);
	}
 
	public function valid()
	{
		return (current($this->_data) !== false);
	}

}
</pre>

<p>Little did I realize that this implementation is very broken. I’ll explain
why, below.</p>

<p>Over the past few years, I’ve implemented <em>many</em> iterators in
this way, using PHP’s implicit array manipulation functions
(<code>reset()</code>, <code>current()</code>, <code>key()</code>,
<code>next()</code>). These functions are very convenient because PHP
arrays are so powerful — arrays in PHP work like ordered hash tables in other
languages.</p>

<p>PHP’s implicit management of an array’s iteration index
(the value that is incremented by <code>next()</code> and
referenced by <code>key()</code>) is indeed convenient, but the convenience
can sometimes be offset by its very implicitness — the value is hidden from
you, the PHP programmer.</p>

<p>In PHP, generic array iteration (without the implicit iterator) isn’t
actually as simple as it sounds. Remember that arrays aren’t arrays in the
traditional sense, but ordered hash tables. Consider this:</p>

<pre class="highlight php">
$data = array('zero','one','two','three');
for ($i=0; $i&lt;count($data); $i++) {
    // yeah, don't calculate count() on every iteration
    echo "{$data[$i]}\n";
}
</pre>

<p>Output:</p>

<pre><code>zero
one
two
three</code></pre>

<p>This first example is easy to iterate — the array contains sequential,
numeric, zero-based keys. It gets more complicated when using
non-sequential, and non-numeric keys:</p>

<pre class="highlight php">
$data = array(
    'apple',
    'cow' => 'moo',
    'pig' => 'oink',
    'orange'
);
for ($i=0; $i&lt;count($data); $i++) {
    echo "{$data[$i]}\n";
}
</pre>

<p>Output:</p>

<pre><code>apple
orange
Notice: Undefined offset: 2 in - on line 10
Notice: Undefined offset: 3 in - on line 10</code></pre>

<p>I <em>could</em> use <code>foreach</code>, but because a numeric loop illustrates the point more clearly, here’s how I might implement the above code so that it works:</p>

<pre class="highlight php">
$data = array(
    'apple',
    'cow' => 'moo',
    'pig' => 'oink',
    'orange'
);
$k = array_keys($data);
for ($i=0; $i&lt;count($data); $i++) {
    echo "{$data[$k[$i]]}\n";
}
</pre>

<p>Output:</p>

<pre><code>apple
moo
oink
orange</code></pre>

<p>This brings us back to the <code>Iterator</code> implementation. Why
isn’t the code above correct? Take a closer look at this:</p>

<pre class="highlight php">
public function valid()
{
    return (current($this->_data) !== false);
}
</pre>

<p>A value of <code>false</code> in the array is indistinguishable from a
<code>false</code> value returned by <code>current()</code>. Using the
above implementation with the following array would cause it to bail after
<code>orange</code> (and subsequently might cause you to waste a day
tracking down the cause):</p>

<pre class="highlight php">
array(
    'apple',
    'orange',
    false,
    'banana',
);
</pre>

<p>On Tuesday night, I
<a href="http://svn.php.net/viewvc?view=revision&revision=301637">updated the manual</a>
to use an
<a href="http://docs.php.net/iterator">improved <code>Iterator</code> implementation</a>.
It’s probably a bit slower (so you
can use the internal-indexing implementation if you’re sure your arrays
will never contain <code>false</code>), but my implementation is more
robust.</p>

<pre class="highlight php">
&lt;?php
/**
 * A mixed-key iterator implementation
 *
 * Note: these array_keys() calls are slow. The array keys could be cached
 * as long as the cache value is invalidated when $_data is changed.
 */
class It implements Iterator
{
	public $_data = array();
	protected $_index = 0;

	public function rewind()
	{
		$this->_index = 0;
	}
 
	public function current()
	{
		$k = array_keys($this</pre><p><i>Truncated by Planet PHP, read more at <a href="http://seancoates.com/blogs/a-case-of-mistaken-iterator">the original</a> (another 765 bytes)</i></p>]]></content:encoded></item><item rdf:about="http://www.leftontheweb.com/message/Open_Source_Your_Career_my_story"><title>Open Source Your Career, my story</title><link>http://www.leftontheweb.com/message/Open_Source_Your_Career_my_story</link><dc:date>2010-07-28T21:06:00Z</dc:date><dc:creator>Stefan Koopmanschap</dc:creator><description><![CDATA[About a month ago my good friend Lorna Mitchell put out a call for stories on how working with Open Source has influenced people's careers. Given that a lot of my recent career has been driven by my involvement in Open Source, I shared my story with Lorna. But I also wanted to share some of my story with everyone. So here is my story and opinion on how Open Source can influence your career in a positive way.]]></description><content:encoded><![CDATA[About a month ago my good friend Lorna Mitchell put out a call for stories on how working with Open Source has influenced people's careers. Given that a lot of my recent career has been driven by my involvement in Open Source, I shared my story with Lorna. But I also wanted to share some of my story with everyone. So here is my story and opinion on how Open Source can influence your career in a positive way.]]></content:encoded></item><item rdf:about="http://www.brandonsavage.net/july-slides/"><title>July Slides</title><link>http://www.brandonsavage.net/july-slides/</link><dc:date>2010-07-28T15:28:00Z</dc:date><dc:creator>Brandon Savage</dc:creator><description><![CDATA[July was a month of talks and travel, including speaking at OSCON and user group talks to DCPHP and PDXPHP. For those who saw the “Micro Optimize This!” talk, you can download the slides here. For those looking for the “Five Tips To Make Good Object Oriented Code Better” slides, those are available here.]]></description><content:encoded><![CDATA[July was a month of talks and travel, including speaking at OSCON and user group talks to DCPHP and PDXPHP. For those who saw the “Micro Optimize This!” talk, you can download the slides here. For those looking for the “Five Tips To Make Good Object Oriented Code Better” slides, those are available here.]]></content:encoded></item><item rdf:about="http://blog.phpdeveloper.org/?p=274"><title>Speaking at Dallas TechFest 2010 &#x2013; Building a Web Service API</title><link>http://blog.phpdeveloper.org/?p=274</link><dc:date>2010-07-27T18:33:00Z</dc:date><dc:creator>blog.phpdeveloper.org &#xC2;&#xBB; PHP</dc:creator><description><![CDATA[Just a heads up for all of those in the Dallas/Ft. Worth area – there’s a great one-day event coming up this Friday (July 31st) blending PHP, .NET, Java, new media, Joomla and WordPress into one packed day of sessions – Dallas TechFest 2010 at the University of Texas at Dallas.
I’ll be giving a session [...]]]></description><content:encoded><![CDATA[<p>Just a heads up for all of those in the Dallas/Ft. Worth area – there’s a great one-day event coming up this Friday (July 31st) blending PHP, .NET, Java, new media, Joomla and WordPress into one packed day of sessions – <a href="http://dallastechfest.com">Dallas TechFest 2010</a> at the University of Texas at Dallas.</p>
<p>I’ll be giving a session called “Building a Web Service API” from 10:30 – 11:45am in the PHP track. Here’s a summary of the session:</p>
<blockquote><p>
When is a web application more than just a web application? Hook up an API and you’ll see! I’ll walk you through the basics of what an API is and the concepts behind it as well as key pieces of technology you can use to create both the client and server. There’s a focus on PHP but other languages and tools will be touched on as well.
</p></blockquote>
<p>There’s still time to register for the event – <a href="http://dallastechfest.eventbrite.com/?ref=ebtn">tickets can be purchased</a> for an early bird price (ending today) of $50 or $60 at the door. You can see the full list of sessions <a href="http://dallastechfest.com/Sessions/tabid/90/Default.aspx">here</a>.</p>
]]></content:encoded></item><item rdf:about="http://seancoates.com/blogs/beer-alchemy-integration"><title>Beer Alchemy Integration</title><link>http://seancoates.com/blogs/beer-alchemy-integration</link><dc:date>2010-07-27T16:48:00Z</dc:date><dc:creator>Sean Coates</dc:creator><description><![CDATA[]]></description><content:encoded><![CDATA[<p>As I mentioned in my <a href="http://seancoates.com/blogs/a-new-seancoatescom">previous post</a>, my <a href="http://seancoates.com/brews">beer recipes</a> are now online.</p>

<p>I've had several people ask me how this is done, so I think a post is in order.</p>

<p>While it's <a href="http://howotobrew.com/">entirely possible</a> to brew beer at home without any fancy gadgets, there are several tools I use (such as my refractometer) that make the process easier, more controlled, or both. Brewing software is one of the few instruments that I'm not sure I'd want to brew without. I use a Mac, primarily, so <a href="http://www.kentplacesoftware.com/products/BeerAlchemy.html">Beer Alchemy</a> (BA) is the obvious choice for recipe formulation, calculation, and logging.</p>

<p>BA has its own html export mechanism for recipes, and I used this for quite a long time, but I was never really satisfied with the results. The markup was hard to style, contained a lot of clutter (occasionally useful, but often redundant information such as style parameters), and simply didn't fit well with the rest of my site.</p>

<p><img src="http://files.seancoates.com/beer-alchemy-html-output.png" alt="Beer Alchemy html Output" title="Beer Alchemy html Output"/></p>

<p>You can also export from BA in PDF (not suitable for web publishing), <a href="http://www.promash.com/">ProMash</a>'s binary recipe format (a pain to convert, although there do seem to be some <a href="http://www.thebitterbrewer.com/viewtopic.php?f=3&t=66">tools</a> to help with this), BeerXML (normally the most accessible, but in my <a href="https://secure.neap.net/pipermail/montrealers/2010-January/028602.html">opinion</a>, a poorly-designed XML format), or in BA's native <code>.bar</code> ("Beer Alchemy Recipe") format, which is what I chose.</p>

<p><img src="http://files.seancoates.com/ba-recipe-export.png" alt="Beer Alchemy Recipe Export Dialog" title="Beer Alchemy Recipe Export Dialog"/></p>

<p>The <code>bar</code> format contains a <a href="http://en.wikipedia.org/wiki/Property_list">property list</a>, similar to those found throughout Apple systems. Property lists are either binary or XML (but the XML is very difficult to work with using traditional tools because of the way it employs element peering instead of a hierarchy to manage relationships). Luckily, I found a project called <a href="http://code.google.com/p/cfpropertylist/">CFPropertyList</a> that allows for easy plist handling in PHP. (I even <a href="http://www.google.com/codesearch?q=sean+package%3Ahttp%3A%2F%2Fcfpropertylist\.googlecode\.com&origq=sean&btnG=Search+Trunk">contributed a minor change</a> to this project, a while ago.)</p>

<p>Once you've run the <code>.bar</code> file's contents through CFPropertyList, layout is very simple. Here's most of the code I use to generate my recipes:</p>

<pre class="highlight php">
&lt;?php
$beerPath = __DIR__ . '/../resources/beer/';

$recipes = apc_fetch('seancoates_recipes');
$fromCache = true;
if ($recipes === false) {
	$fromCache = false;
	foreach (new DirectoryIterator($beerPath) as $f) {
		if ($f->isDot()) {
			continue;
		}
		if (substr($f->getFilename(), -4) != '.bar') {
			continue;
		}
		$cfpl = new CFPropertyList($beerPath . '/' . $f->getFilename());
		$recipe = $cfpl->toArray();
		$title = $recipe['RecipeTitle'];
		$recipes[self::slugify($title)] = array(
			'title' => $title,
			'content' => $recipe,
		);
	}
	asort($recipes);
	if ($recipes) {
		apc_store('seancoates_recipes', $recipes, 3600); // 1h
	}
}
</pre>

<p>In addition to displaying the recipe's data, I also wanted to show the approximate (calculated) beer colour. Normally, beer recipes declare their colour in "SRM" (<a href="http://en.wikipedia.org/wiki/Standard_Reference_Method">Standard Reference Method</a>). There's no obvious, simple, and direct way to get from SRM (which is a number from 0 to 40—and higher, but above the mid 30s is basically "black") to an html colour.</p>

<p>I found a few tables online, but I wasn't terribly happy with any of them, and keeping a dictionary for lookups was big and ugly. I like the way Beer Alchemy previews its colours, and since it has html output, I emailed the author to see if he'd be willing to share his algorithm. Steve from Kent Place Software graciously sent me an excerpt from his Objective C code, and I translated it to PHP. This might be useful for someone, and since Steve also granted me permission to publish my version of the algorithm, here it is:</p>

<pre class="highlight php">
&lt;?php
/**
 * Calculate html colour from SRM
 * Thanks to Steve from Kent Place Software (Beer Alchemy)
 *
 * @param float $srm the SRM value to turn into html
 * @return string html colour (without leading #)
 */
public function srm2html($srm)
{
	if ($srm &lt;= 0.1) { // It's water
		$r = 197;
		$g = 232;
		$b = 248;
	} elseif ($srm &lt;= 2) {
		$r = 250;
		$g = 250;
		$b = 60;
	} elseif ($srm &lt;= 12) {
		$r = (250 - (6 * ($sr</pre><p><i>Truncated by Planet PHP, read more at <a href="http://seancoates.com/blogs/beer-alchemy-integration">the original</a> (another 3023 bytes)</i></p>]]></content:encoded></item><item rdf:about="http://bergie.iki.fi/blog/aloha_and_the_art_of_semantic_web_content/"><title>Aloha and the art of semantic web content</title><link>http://bergie.iki.fi/blog/aloha_and_the_art_of_semantic_web_content/</link><dc:date>2010-07-27T16:31:00Z</dc:date><dc:creator>Henri Bergius</dc:creator><description><![CDATA[
<p>To bring CMS editing to the next level, the <a href="http://www.iks-project.eu/">IKS</a> project is <a href="http://www.iks-project.eu/launching-iks-semantic-editor-development-group">working on a semantic html5 editor</a>. This week we had a <a href="http://wiki.iks-project.eu/index.php/Semantic_Editor/Helsinki_hackathon_2010">hackathon in Helsinki</a> focusing on implementing our ideas with the <a href="http://aloha-editor.com/">Aloha Editor</a>. In addition to enjoying the hot summer weather here, we accomplished quite a bit and in the end were able to present the whole pipeline of:</p>
<ul><li>Loading content from Midgard CMS to Aloha Editor</li>
<li>Annotating our content with <a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=146646">Google-compatible Person RDFa</a> elements</li>
<li>Saving the content back to Midgard</li>
<li>...and finally analysing the content with <a href="http://wiki.iks-project.eu/index.php/FISE">FISE</a> to find more semantic information</li>
</ul><p><img src="http://bergie.iki.fi/static/1/1df99b0fbedc9d099b011df9cde59aa729dc602c602_iks_helsinki_hackathon_participants.jpg" border="0" alt="iks_helsinki_hackathon_participants.jpg" title="iks_helsinki_hackathon_participants.jpg" /></p>
<p>The hackathon participants included developers from <a href="http://nemein.com/en/">Nemein</a>, <a href="http://gentics.com/Content.Node/index_en.php">Gentics</a>, <a href="http://infigo.fi/en/">Infigo</a>, <a href="http://www.salzburgresearch.at/company/index_e.php">Salzburg Research</a> and the <a href="http://www.dfki.de/web/welcome?set_language=en&cl=en">German Research Center for Artificial Intelligence</a>. Some screenshots:</p>
<p><img src="http://bergie.iki.fi/static/1/1df99b12c14931e99b111dfb2649b40ceb420042004_aloha-editing-small.png" border="0" alt="aloha-editing-small.png" title="aloha-editing-small.png" /><br />Editing content with Aloha in Midgard</p>
<p><img src="http://bergie.iki.fi/static/1/1df99b152d8fbca99b111df8c291f845ff4792c792c_aloha-editing-rdfa-small.png" border="0" alt="aloha-editing-rdfa-small.png" title="aloha-editing-rdfa-small.png" /><br />Annotating persons with the Aloha RDFa plugin</p>
<p><img src="http://bergie.iki.fi/static/1/1df99b19296459c99b111dfbf84d704b90a3b663b66_aloha-generated-rdfa-small.png" border="0" alt="aloha-generated-rdfa-small.png" title="aloha-generated-rdfa-small.png" /></p>
<p>RDFa annotation created with the semantic editor<br /><img src="http://bergie.iki.fi/static/1/1df99b1bdbd0be899b111dfbf84d704b90a3b663b66_fise-analysed-content-small.png" border="0" alt="fise-analysed-content-small.png" title="fise-analysed-content-small.png" /><br />Additional semantic information suggested by FISE</p>
<p>All the relevant code can be found <a href="http://github.com/alohaeditor/Aloha-Editor">from GitHub</a> (see also the <a href="http://github.com/nemein/eu_iksproject_fise">FISE Midgard integration</a>).</p>]]></description><content:encoded><![CDATA[
<p>To bring CMS editing to the next level, the <a href="http://www.iks-project.eu/">IKS</a> project is <a href="http://www.iks-project.eu/launching-iks-semantic-editor-development-group">working on a semantic html5 editor</a>. This week we had a <a href="http://wiki.iks-project.eu/index.php/Semantic_Editor/Helsinki_hackathon_2010">hackathon in Helsinki</a> focusing on implementing our ideas with the <a href="http://aloha-editor.com/">Aloha Editor</a>. In addition to enjoying the hot summer weather here, we accomplished quite a bit and in the end were able to present the whole pipeline of:</p>
<ul><li>Loading content from Midgard CMS to Aloha Editor</li>
<li>Annotating our content with <a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=146646">Google-compatible Person RDFa</a> elements</li>
<li>Saving the content back to Midgard</li>
<li>...and finally analysing the content with <a href="http://wiki.iks-project.eu/index.php/FISE">FISE</a> to find more semantic information</li>
</ul><p><img src="http://bergie.iki.fi/static/1/1df99b0fbedc9d099b011df9cde59aa729dc602c602_iks_helsinki_hackathon_participants.jpg" border="0" alt="iks_helsinki_hackathon_participants.jpg" title="iks_helsinki_hackathon_participants.jpg" /></p>
<p>The hackathon participants included developers from <a href="http://nemein.com/en/">Nemein</a>, <a href="http://gentics.com/Content.Node/index_en.php">Gentics</a>, <a href="http://infigo.fi/en/">Infigo</a>, <a href="http://www.salzburgresearch.at/company/index_e.php">Salzburg Research</a> and the <a href="http://www.dfki.de/web/welcome?set_language=en&cl=en">German Research Center for Artificial Intelligence</a>. Some screenshots:</p>
<p><img src="http://bergie.iki.fi/static/1/1df99b12c14931e99b111dfb2649b40ceb420042004_aloha-editing-small.png" border="0" alt="aloha-editing-small.png" title="aloha-editing-small.png" /><br />Editing content with Aloha in Midgard</p>
<p><img src="http://bergie.iki.fi/static/1/1df99b152d8fbca99b111df8c291f845ff4792c792c_aloha-editing-rdfa-small.png" border="0" alt="aloha-editing-rdfa-small.png" title="aloha-editing-rdfa-small.png" /><br />Annotating persons with the Aloha RDFa plugin</p>
<p><img src="http://bergie.iki.fi/static/1/1df99b19296459c99b111dfbf84d704b90a3b663b66_aloha-generated-rdfa-small.png" border="0" alt="aloha-generated-rdfa-small.png" title="aloha-generated-rdfa-small.png" /></p>
<p>RDFa annotation created with the semantic editor<br /><img src="http://bergie.iki.fi/static/1/1df99b1bdbd0be899b111dfbf84d704b90a3b663b66_fise-analysed-content-small.png" border="0" alt="fise-analysed-content-small.png" title="fise-analysed-content-small.png" /><br />Additional semantic information suggested by FISE</p>
<p>All the relevant code can be found <a href="http://github.com/alohaeditor/Aloha-Editor">from GitHub</a> (see also the <a href="http://github.com/nemein/eu_iksproject_fise">FISE Midgard integration</a>).</p>]]></content:encoded></item><item rdf:about="http://sebastian-bergmann.de/archives/894-Using-HipHop-for-Static-Analysis.html"><title>Using HipHop for Static Analysis</title><link>http://sebastian-bergmann.de/archives/894-Using-HipHop-for-Static-Analysis.html</link><dc:date>2010-07-27T09:30:00Z</dc:date><dc:creator>Sebastian Bergmann</dc:creator><description><![CDATA[]]></description><content:encoded><![CDATA[
    <p><a href="http://sebastian-bergmann.de/archives/880-My-Take-on-Facebooks-HipHop-for-PHP.html">HipHop for PHP</a>, the source code transformer that turns PHP code into C++ code that can then be compiled with g++, can also be used for <a href="http://en.wikipedia.org/wiki/Static_code_analysis">static code analysis</a> to find problems in PHP source code.</p><dl><dd><pre>sb@vmware Money % hphp -t analyze --input-dir .
running hphp...
creating temporary directory /tmp/hphp_Zz7AXg ...
parsing inputs...
parsing inputs took 0'00" (20 ms) wall time
inferring types...
inferring types took 0'00" (10 ms) wall time
saving code errors, dependency graph and stats...
all files saved in /tmp/hphp_Zz7AXg ...
running hphp took 0'00" (208 ms) wall time</pre></dd></dl><p>The script below takes a <code>CodeErrors.js</code> file (which is generated by <code>hphp</code> and in the example above is saved to <code>/tmp/hphp_Zz7AXg</code>) as its input and print an XML document in <a href="http://checkstyle.sourceforge.net/">Checkstyle</a>'s format (the same XML format that is also used by <a href="http://pear.php.net/package/PHP_CodeSniffer">PHP_CodeSniffer</a>, for instance). This XML logfile can then be used with <a href="http://github.com/sebastianbergmann/php-hudson-template">Hudson</a>, for instance, in a <a href="http://en.wikipedia.org/wiki/Continuous_integration">continuous integration</a> context.</p>&lt;script src="http://gist.github.com/490858.js"></script> 
    ]]></content:encoded></item></rdf:RDF>
