<?xml version="1.0" encoding="utf-8"?>
<!-- generator="FeedCreator 1.7.6(BH)" -->
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:georss="http://www.georss.org/georss"
 xml:lang="en">
    <title>Henri Bergius</title>
    <subtitle>Motorcycle Adventures and Free Software from Henri Bergius</subtitle>
    <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/"/>
    <id>http://bergie.iki.fi/blog/</id>
    <updated>2012-05-16T23:58:30+00:00</updated>
    <author>
        <name>henri.bergius@iki.fi</name>
    </author>
    <generator>FeedCreator 1.7.6(BH) (info@mypapit.net)</generator>
    <link rel="self" type="application/atom+xml" href="http://bergie.iki.fi/blog/atom.xml" />
    <entry>
        <title>Using Composer to manage dependencies in Heroku PHP apps</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/using_composer_to_manage_dependencies_in_heroku_php_apps/"/>
        <published>2012-05-08T10:18:54+00:00</published>
        <updated>2012-05-08T10:18:54+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e198f736f0935498f711e18df361a7dd80c9d7c9d7</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="midgard" />
        <content type="html"><![CDATA[
<p><a href="http://www.heroku.com/">Heroku</a> is a very nice <a href="http://en.wikipedia.org/wiki/Platform_as_a_service">Platform-as-a-Service</a> provider that allows you to focus on writing applications instead of managing servers. If your application code is already managed in Git, in most cases you only need to create a Heroku app setup, and then <code>git push</code> to deploy it on Heroku. <a href="http://www.heroku.com/how/scale">Scaling your app</a> is easy and there are many <a href="https://addons.heroku.com/">useful add-ons</a> available in their "app store".</p>

<p>While Heroku <a href="http://www.flourish.org/blog/?p=687">got its start</a> from hosting Ruby on Rails applications, it nowadays supports <a href="https://devcenter.heroku.com/articles/cedar">many different environments</a> in the Cedar stack. Node.js is what many use, but they also <a href="http://www.gravitywell.co.uk/blog/post/deploying-php-apps-to-heroku">do support PHP</a>.</p>

<p>Dependency management is easy for Node.js applications as Heroku recognizes your <code>package.json</code> files and <a href="https://devcenter.heroku.com/articles/nodejs#declare_dependencies_with_npm">automatically installs</a> the libraries needed via <a href="http://search.npmjs.org/">NPM</a>.</p>

<p>Until now PHP developers haven't had this convenience, but as <a href="http://packagist.org/">Composer</a> is emerging as the <a href="http://bergie.iki.fi/blog/composer_solves_the_php_code-sharing_problem/">default PHP package manager</a>, I've now <a href="https://github.com/heroku/heroku-buildpack-php/pull/10">added support</a> for it. Before the <a href="https://github.com/heroku/heroku-buildpack-php/pull/10">pull request</a> gets accepted, Composer dependency handling can already be used by specifying <a href="https://github.com/bergie/heroku-buildpack-php">my custom PHP buildpack</a> when creating Heroku apps.</p>

<p>I've written <a href="https://github.com/bergie/urlizer_service">a simple example app</a> to show how this works.</p>

<p>First you need to create the folder for your app and make it a Git repository:</p>

<pre><code>$ mkdir myapp
$ cd myapp
$ git init
</code></pre>

<p>Then create the Heroku app using a custom buildpack (when the pull request is accepted you can skip the buildpack definition):</p>

<pre><code>$ heroku create -s cedar --buildpack https://github.com/bergie/heroku-buildpack-php.git my-cool-app
</code></pre>

<p>Then it is time to write your <a href="http://packagist.org/">composer.json</a> file. In this case we'll only depend on the <a href="http://packagist.org/packages/midgard/midgardmvc-helper-urlize">urlize library</a>:</p>

<pre><code>{
    "require": {
        "php": "&gt;=5.2.0",
        "midgard/midgardmvc-helper-urlize": "*"
    }
}
</code></pre>

<p>For Heroku to recognize the app as a PHP one, you also need to have an <code>index.php</code>. In this case with the following code:</p>

<pre><code>&lt;?php
// URLizer service
require 'vendor/midgard/midgardmvc-helper-urlize/interface.php';
if (isset($_GET['urlize'])) {
    $data = array();
    $data['from'] = $_GET['urlize'];
    $data['to'] = midgardmvc_helper_urlize::string($_GET['urlize']);
    header('Content-type: application/json; charset=utf-8');
    die(json_encode($data));
}
header('Content-Type: text/html; charset=utf-8');
?&gt;
&lt;h1&gt;Urlizer service&lt;/h1&gt;
&lt;form method="GET"&gt;
    &lt;label&gt;
        String to URLize
        &lt;input name="urlize" type="text" /&gt;
    &lt;/label&gt;
    &lt;input type="submit" value="URLize" /&gt;
&lt;/form&gt;
</code></pre>

<p>Now add and commit these files, and then deploy to Heroku:</p>

<pre><code>$ git push heroku master
</code></pre>

<p>You should see that Heroku notices the Composer dependencies and installs them:</p>

<pre><code>-----&gt; Heroku receiving push
-----&gt; Fetching custom buildpack... done
-----&gt; PHP app detected
-----&gt; Bundling Apache version 2.2.22
-----&gt; Bundling PHP version 5.3.10
-----&gt; Installing Composer dependencies
Installing dependencies
  - Package phptal/phptal (dev-master)
    Cloning e146361f25b8672d364695b757eddf1c169e05d2

  - Package midgard/midgardmvc-core (dev-master)
    Cloning 2b00d38cb2fea42c8f9791c5ecc7270dc81182e8

  - Package midgard/midgardmvc-helper-urlize (dev-master)
    Cloning 92d0c8c638c389b7be1887ca67cd334f51932912

midgard/midgardmvc-core suggests installing ext-midgard2 (&gt;=10.05.5)
Writing lock file
Generating autoload files
-----&gt; Discovering process types
       Procfile declares types -&gt; (none)
       Default types for PHP   -&gt; web
-----&gt; Compiled slug size is 13.2MB
-----&gt; Launching... done, v13
</code></pre>

<p>And that is it! You can see an example of this app at <a href="http://urlizer-service.herokuapp.com/">http://urlizer-service.herokuapp.com/</a>.</p>
]]></content>
        <summary type="html"><![CDATA[
<p><a href="http://www.heroku.com/">Heroku</a> is a very nice <a href="http://en.wikipedia.org/wiki/Platform_as_a_service">Platform-as-a-Service</a> provider that allows you to focus on writing applications instead of managing servers. If your application code is already managed in Git, in most cases you only need to create a Heroku app setup, and then <code>git push</code> to deploy it on Heroku. <a href="http://www.heroku.com/how/scale">Scaling your app</a> is easy and there are many <a href="https://addons.heroku.com/">useful add-ons</a> available in their "app store".</p>

<p>While Heroku <a href="http://www.flourish.org/blog/?p=687">got its start</a> from hosting Ruby on Rails applications, it nowadays supports <a href="https://devcenter.heroku.com/articles/cedar">many different environments</a> in the Cedar stack. Node.js is what many use, but they also <a href="http://www.gravitywell.co.uk/blog/post/deploying-php-apps-to-heroku">do support PHP</a>.</p>

<p>Dependency management is easy for Node.js applications as Heroku recognizes your <code>package.json</code> files and <a href="https://devcenter.heroku.com/articles/nodejs#declare_dependencies_with_npm">automatically installs</a> the libraries needed via <a href="http://search.npmjs.org/">NPM</a>.</p>

<p>Until now PHP developers haven't had this convenience, but as <a href="http://packagist.org/">Composer</a> is emerging as the <a href="http://bergie.iki.fi/blog/composer_solves_the_php_code-sharing_problem/">default PHP package manager</a>, I've now <a href="https://github.com/heroku/heroku-buildpack-php/pull/10">added support</a> for it. Before the <a href="https://github.com/heroku/heroku-buildpack-php/pull/10">pull request</a> gets accepted, Composer dependency handling can already be used by specifying <a href="https://github.com/bergie/heroku-buildpack-php">my custom PHP buildpack</a> when creating Heroku apps.</p>

<p>I've written <a href="https://github.com/bergie/urlizer_service">a simple example app</a> to show how this works.</p>

<p>First you need to create the folder for your app and make it a Git repository:</p>

<pre><code>$ mkdir myapp
$ cd myapp
$ git init
</code></pre>

<p>Then create the Heroku app using a custom buildpack (when the pull request is accepted you can skip the buildpack definition):</p>

<pre><code>$ heroku create -s cedar --buildpack https://github.com/bergie/heroku-buildpack-php.git my-cool-app
</code></pre>

<p>Then it is time to write your <a href="http://packagist.org/">composer.json</a> file. In this case we'll only depend on the <a href="http://packagist.org/packages/midgard/midgardmvc-helper-urlize">urlize library</a>:</p>

<pre><code>{
    "require": {
        "php": "&gt;=5.2.0",
        "midgard/midgardmvc-helper-urlize": "*"
    }
}
</code></pre>

<p>For Heroku to recognize the app as a PHP one, you also need to have an <code>index.php</code>. In this case with the following code:</p>

<pre><code>&lt;?php
// URLizer service
require 'vendor/midgard/midgardmvc-helper-urlize/interface.php';
if (isset($_GET['urlize'])) {
    $data = array();
    $data['from'] = $_GET['urlize'];
    $data['to'] = midgardmvc_helper_urlize::string($_GET['urlize']);
    header('Content-type: application/json; charset=utf-8');
    die(json_encode($data));
}
header('Content-Type: text/html; charset=utf-8');
?&gt;
&lt;h1&gt;Urlizer service&lt;/h1&gt;
&lt;form method="GET"&gt;
    &lt;label&gt;
        String to URLize
        &lt;input name="urlize" type="text" /&gt;
    &lt;/label&gt;
    &lt;input type="submit" value="URLize" /&gt;
&lt;/form&gt;
</code></pre>

<p>Now add and commit these files, and then deploy to Heroku:</p>

<pre><code>$ git push heroku master
</code></pre>

<p>You should see that Heroku notices the Composer dependencies and installs them:</p>

<pre><code>-----&gt; Heroku receiving push
-----&gt; Fetching custom buildpack... done
-----&gt; PHP app detected
-----&gt; Bundling Apache version 2.2.22
-----&gt; Bundling PHP version 5.3.10
-----&gt; Installing Composer dependencies
Installing dependencies
  - Package phptal/phptal (dev-master)
    Cloning e146361f25b8672d364695b757eddf1c169e05d2

  - Package midgard/midgardmvc-core (dev-master)
    Cloning 2b00d38cb2fea42c8f9791c5ecc7270dc81182e8

  - Package midgard/midgardmvc-helper-urlize (dev-master)
    Cloning 92d0c8c638c389b7be1887ca67cd334f51932912

midgard/midgardmvc-core suggests installing ext-midgard2 (&gt;=10.05.5)
Writing lock file
Generating autoload files
-----&gt; Discovering process types
       Procfile declares types -&gt; (none)
       Default types for PHP   -&gt; web
-----&gt; Compiled slug size is 13.2MB
-----&gt; Launching... done, v13
</code></pre>

<p>And that is it! You can see an example of this app at <a href="http://urlizer-service.herokuapp.com/">http://urlizer-service.herokuapp.com/</a>.</p>
]]></summary>
        <georss:point>53.3139 13.8626</georss:point>
    </entry>
    <entry>
        <title>Decoupled Content Management on tour</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/decoupled_content_management_on_tour/"/>
        <published>2012-04-13T10:14:30+00:00</published>
        <updated>2012-04-13T10:14:30+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e18551750a6566855111e1be427376ab5e96ec96ec</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="midgard" />
        <content type="html"><![CDATA[
<p>It seems the idea of <a href="http://bergie.iki.fi/blog/decoupling_content_management/">Decoupling Content Management</a> is gaining momentum. On the user interface side, many projects have already adopted the <a href="http://viejs.org/">VIE</a> interaction framework and widgets from <a href="http://createjs.org/">Create</a>, and in the content repository space projects like <a href="http://phpcr.github.com/">PHPCR</a> move forward and there are also interesting new ideas like <a href="http://svn.apache.org/repos/asf/labs/oak/README.txt">Apache Oak</a>.</p>
<p>While much of this has been made possible by the <a href="http://www.iks-project.eu/">IKS project</a>, it is also great to see the wider CMS community getting more active in the space. Part of this momentum is also apparent in how many communities want to learn more about these ideas.</p>
<p>Here are some upcoming events where decoupled CMS will be present:</p>
<ul><li><strong><a href="http://t3dd12.typo3.org/">Typo3 Developer Days</a></strong>, April 12-15 in Munich, Germany. No official session, but I was invited to participate and chat with people</li>
<li><strong><a href="http://www2012.wwwconference.org/">World Wide Web Conference</a></strong>, April 16-20 in Lyon, France. We will present our paper on decoupled content management with Szaby Grünwald on <a href="http://www2012.wwwconference.org/wwwprogram/getinfo.php?type=developers">Friday in the Developers track</a></li>
<li><strong><a href="http://berlinjs.org/">BerlinJS</a></strong>, May in Berlin, Germany. I will talk about Create</li>
<li><strong><a href="http://paris2012.live.symfony.com/">Symfony Live</a></strong>, June 6-9 in Paris, France. I <a href="http://paris2012.live.symfony.com/speakers">will talk about</a> decoupling content management with Create and PHPCR, and Lukas Smith will talk about Symfony2 CMF</li>
<li><strong><a href="http://wiki.iks-project.eu/index.php/Workshops/Salzburg2012">IKS Technology in Action</a></strong>, June 12-13 in Salzburg, Austria. Lots of sessions about the different IKS tools</li>
<li><strong><a href="http://munich2012.drupal.org/">DrupalCon</a></strong>, August 20-24 in Munich, Germany. My talk on decoupling content management is a <a href="http://munich2012.drupal.org/program/sessions/featured">featured session</a></li>
</ul><p>If your community is interested in learning more, <a href="http://www.linkedin.com/in/bergie">get in touch</a> or follow <a href="http://twitter.com/bergie">my tweets</a> from these events. And obviously I'm looking forward to meeting many of you in these events.</p>
<p></p>]]></content>
        <summary type="html"><![CDATA[
<p>It seems the idea of <a href="http://bergie.iki.fi/blog/decoupling_content_management/">Decoupling Content Management</a> is gaining momentum. On the user interface side, many projects have already adopted the <a href="http://viejs.org/">VIE</a> interaction framework and widgets from <a href="http://createjs.org/">Create</a>, and in the content repository space projects like <a href="http://phpcr.github.com/">PHPCR</a> move forward and there are also interesting new ideas like <a href="http://svn.apache.org/repos/asf/labs/oak/README.txt">Apache Oak</a>.</p>
<p>While much of this has been made possible by the <a href="http://www.iks-project.eu/">IKS project</a>, it is also great to see the wider CMS community getting more active in the space. Part of this momentum is also apparent in how many communities want to learn more about these ideas.</p>
<p>Here are some upcoming events where decoupled CMS will be present:</p>
<ul><li><strong><a href="http://t3dd12.typo3.org/">Typo3 Developer Days</a></strong>, April 12-15 in Munich, Germany. No official session, but I was invited to participate and chat with people</li>
<li><strong><a href="http://www2012.wwwconference.org/">World Wide Web Conference</a></strong>, April 16-20 in Lyon, France. We will present our paper on decoupled content management with Szaby Grünwald on <a href="http://www2012.wwwconference.org/wwwprogram/getinfo.php?type=developers">Friday in the Developers track</a></li>
<li><strong><a href="http://berlinjs.org/">BerlinJS</a></strong>, May in Berlin, Germany. I will talk about Create</li>
<li><strong><a href="http://paris2012.live.symfony.com/">Symfony Live</a></strong>, June 6-9 in Paris, France. I <a href="http://paris2012.live.symfony.com/speakers">will talk about</a> decoupling content management with Create and PHPCR, and Lukas Smith will talk about Symfony2 CMF</li>
<li><strong><a href="http://wiki.iks-project.eu/index.php/Workshops/Salzburg2012">IKS Technology in Action</a></strong>, June 12-13 in Salzburg, Austria. Lots of sessions about the different IKS tools</li>
<li><strong><a href="http://munich2012.drupal.org/">DrupalCon</a></strong>, August 20-24 in Munich, Germany. My talk on decoupling content management is a <a href="http://munich2012.drupal.org/program/sessions/featured">featured session</a></li>
</ul><p>If your community is interested in learning more, <a href="http://www.linkedin.com/in/bergie">get in touch</a> or follow <a href="http://twitter.com/bergie">my tweets</a> from these events. And obviously I'm looking forward to meeting many of you in these events.</p>
<p></p>]]></summary>
        <georss:point>53.3139 13.8626</georss:point>
    </entry>
    <entry>
        <title>Open Advice</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/open_advice/"/>
        <published>2012-03-19T10:51:12+00:00</published>
        <updated>2012-03-19T10:51:12+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e171b17152429471b111e1a582e78e1e97125b125b</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="business" />
        <content type="html"><![CDATA[
<p><img src="http://bergie.iki.fi/static/1/1e171b06217a15871b011e1bc5b5d4704468fc08fc0_openadvice-small.jpg" border="0" alt="Open Advice cover" title="Open Advice" style="float:right;margin-left:10px;" />I seem to have not blogged about this, but <strong><a href="http://open-advice.org/">Open Advice</a></strong>, our book on <em>Free and Open Source Software: what we wish we had known when we started</em>, was published last month.</p>
<p>The book was edited by <a href="http://www.lydiapintscher.de/book.php">Lydia Pintscher</a> and includes essays from <a href="http://open-advice.org/author.html">42 authors</a>, many of whom you'll recognize if you tend to go to FOSS conferences. The <a href="http://lwn.net/Articles/481222/">LWN book review</a> concludes:</p>
<blockquote>Open Advice is a book that will be helpful to those who are new to FOSS, but, because of the individual voices, styles, and tones, it doesn't read like a "how to". It could even be recommended to those who aren't necessarily interested in contributing, but are curious about what this "free software thing" is all about. It is, in short, a great book for a variety of audiences and the (mostly) two or three page essays make it easy to read, while the anecdotes and recollections personalize it. The authors, editor, and everyone else who helped should be very pleased with the result. Readers will be too.</blockquote>
<p>I probably shouldn't give the ending away, but my essay on cross-project collaboration, a subject I've <a href="http://bergie.iki.fi/blog/on_cross-project_collaboration/">also blogged about</a>, ends with:</p>
<blockquote>Good luck with breaking down the project boundaries! In most cases it works if your ideas are good and presented with an open mind. But even if you do not find a common ground, as long as your implementation solves the use case for you it has not been in vain. After all, delivering software, and delivering great user experience is what counts.</blockquote>
<p>The book is licensed under <a href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>, and is available as free download in <a href="http://open-advice.org/Open-Advice.epub">ePub</a>, <a href="http://open-advice.org/Open-Advice.mobi">mobi</a> and <a href="http://open-advice.org/Open-Advice.pdf">PDF</a> formats, and <a href="http://www.lulu.com/shop/lydia-pintscher/open-advice/paperback/product-18889265.html">as paperback from Lulu</a>. The book sources are <a href="https://github.com/lydiapintscher/Open-Advice">available on GitHub</a>, patches welcome!</p>]]></content>
        <summary type="html"><![CDATA[
<p><img src="http://bergie.iki.fi/static/1/1e171b06217a15871b011e1bc5b5d4704468fc08fc0_openadvice-small.jpg" border="0" alt="Open Advice cover" title="Open Advice" style="float:right;margin-left:10px;" />I seem to have not blogged about this, but <strong><a href="http://open-advice.org/">Open Advice</a></strong>, our book on <em>Free and Open Source Software: what we wish we had known when we started</em>, was published last month.</p>
<p>The book was edited by <a href="http://www.lydiapintscher.de/book.php">Lydia Pintscher</a> and includes essays from <a href="http://open-advice.org/author.html">42 authors</a>, many of whom you'll recognize if you tend to go to FOSS conferences. The <a href="http://lwn.net/Articles/481222/">LWN book review</a> concludes:</p>
<blockquote>Open Advice is a book that will be helpful to those who are new to FOSS, but, because of the individual voices, styles, and tones, it doesn't read like a "how to". It could even be recommended to those who aren't necessarily interested in contributing, but are curious about what this "free software thing" is all about. It is, in short, a great book for a variety of audiences and the (mostly) two or three page essays make it easy to read, while the anecdotes and recollections personalize it. The authors, editor, and everyone else who helped should be very pleased with the result. Readers will be too.</blockquote>
<p>I probably shouldn't give the ending away, but my essay on cross-project collaboration, a subject I've <a href="http://bergie.iki.fi/blog/on_cross-project_collaboration/">also blogged about</a>, ends with:</p>
<blockquote>Good luck with breaking down the project boundaries! In most cases it works if your ideas are good and presented with an open mind. But even if you do not find a common ground, as long as your implementation solves the use case for you it has not been in vain. After all, delivering software, and delivering great user experience is what counts.</blockquote>
<p>The book is licensed under <a href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>, and is available as free download in <a href="http://open-advice.org/Open-Advice.epub">ePub</a>, <a href="http://open-advice.org/Open-Advice.mobi">mobi</a> and <a href="http://open-advice.org/Open-Advice.pdf">PDF</a> formats, and <a href="http://www.lulu.com/shop/lydia-pintscher/open-advice/paperback/product-18889265.html">as paperback from Lulu</a>. The book sources are <a href="https://github.com/lydiapintscher/Open-Advice">available on GitHub</a>, patches welcome!</p>]]></summary>
        <georss:point>52.490002 13.4212</georss:point>
    </entry>
    <entry>
        <title>VIE and Create: an update</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/vie_and_create-an_update/"/>
        <published>2012-03-16T17:55:39+00:00</published>
        <updated>2012-03-16T17:55:39+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e16f913dd2e9226f9111e1ae0901b9e95ffe06fe06</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="midgard" />
        <content type="html"><![CDATA[
<p>It is again time to write an update on the state of <a href="http://www.iks-project.eu/">IKS's</a> two main components for the semantic editing part of <a href="../../decoupling_content_management/">Decoupled Content Management</a>:</p>
<ul><li> <a href="http://viejs.org/">VIE</a> is the base semantic interaction library that handles the site's  content model through RDFa annotations and Backbone.js synchronization</li>
<li><a href="http://createjs.org/">Create</a> is a new kind of web editing interface built on top of that.</li>
</ul><p>As the IKS project has <a href="http://blog.iks-project.eu/iks-2011-in-review/">entered its fourth year</a>, both of these projects have gained maturity and contributions from many IKS partners and early adopters.</p>
<h2>New UI for Create</h2>
<p>While Create can be used for building any sort of custom user  experiences (as seen in the CMS integration examples below), it also  ships with a default user interface. <a href="http://nemein.com/en/">Nemein's</a> Riku Virta has designed a new UI concept that is <a href="https://groups.google.com/d/topic/createjs/bYEiF1hWvXk/discussion">currently being discussed</a> on the CreateJS mailing list.</p>
<p>This interface builds on top of the <a href="../../introducing_the_midgard_create_user_interface/">original Create UI</a> and <a href="http://blog.iks-project.eu/what-liip-did-after-winning-the-iks-semantics-ux-contest/">Liip's</a> UX work, and aims to provide more area for CMS-specific functionality and better touchscreen support:</p>
<p><img src="http://bergie.iki.fi/static/1/1e16f90efc34dc66f9011e18c62b75b842496939693_create_new_ui.png" border="0" alt="create_new_ui.png" title="create_new_ui.png" /></p>
<p>See the full UI concept in <a href="https://plus.google.com/photos/113896057721233278902/albums/5717131156654359985/5717131206194261362">the slideshow on Google Plus</a>.</p>
<p>We hope that we will be able to land this new UI still within the March-April timeframe.</p>
<h2>VIE: 2.0 and onwards</h2>
<p>VIE is now <a href="http://blog.iks-project.eu/vie-towards-v2-0-update/">nearing the 2.0 release</a>,  with the first RC expected for the end of this month. After that we'll  have a hackathon in Saarbrucken, Germany where the plan is to focus on  things that we've targeted for a 2.1.</p>
<p>The main feature of VIE 2.1 is a new way of handling RDF literals. This will make it easier to interface with services like <a href="http://dbpedia.org/About">DBpedia</a> that give us data in multiple different languages. This will enable you to do things like:</p>
<pre><code>var eiffel = vie.entities.get('dbp:Eiffel_Tower');
console.log(eiffel.get('label')); // Eiffel Tower

vie.setLanguage('fi');
console.log(eiffel.get('label')); // Eiffel-torni
</code></pre>
<p>The final API for this is <a href="https://groups.google.com/d/topic/viejs/bXK3Xg-rrLA/discussion">still being discussed</a> on the VIE mailing list.</p>
<h2>Create and Hallo are now easier to integrate</h2>
<p>Both Create and <a href="http://bergie.github.com/hallo">Hallo</a>,  our minimalist rich text editing tool now provide merged JavaScript  files for easier integration. You can find the merged files, and also  minified versions in:</p>
<ul><li><a href="https://github.com/bergie/hallo/blob/master/examples/hallo.js">hallo.js</a></li>
<li><a href="https://github.com/bergie/create/blob/master/examples/create.js">create.js</a></li>
</ul><p>Thanks to contributions from <a href="http://www.alkacon.com/en/">Alkacon</a>,  Create's widget selection mechanism is now much more configurable. This  allows CMS developers to provide different editing tools for different  types of information.</p>
<p>The currently bundled editing interfaces provide integration with Hallo, and also with the 0.20 version of <a href="http://aloha-editor.org/">Aloha Editor</a> (though you will need to install Aloha separately to use it due to licensing restrictions).</p>
<p>CMS developers will also benefit from <a href="https://github.com/bergie/blogsiple">Blogsiple</a>,  the new integration testbed for Create and VIE. Blogsiple aims to be a  very simple blog system built on top of Node.js that shows all the  necessary integration points for supporting the whole range of VIE and  Create features.</p>
<h2>CMS adoption</h2>
<p>As both VIE and Create improve, so does their adoption in different Content Management Systems. For example, here is the new <a href="http://www.opencms.org/en/">OpenCms</a> user interface <a href="http://blog.iks-project.eu/alkacons-new-acacia-editor-based-on-iks-semantic-web-technology/">built on these tools</a>:</p>
<p><iframe width="399" height="203" src="http://www.youtube.com/embed/21QSPSKPs6I" frameborder="0" allowfullscreen></iframe></p>
<p>Polymedia's <a href="http://blog.iks-project.eu/polymedia-video-with-iks-semantic-annotation/">video annotation example</a> is also interesting demonstration of VIE in a completely different kind of CMS environment, as is <a href="http://blog.iks-project.eu/keen-onwordlift-a-short-story-how-we-plan-to-make-wordpress-a-semantic-cms/">WordLift</a> by InSideOut10.</p>
<p>The <a href="http://www.iks-project.eu/community/funding/early-adopters-programme">IKS Early Adopter program</a> is still open if you're interested in getting support for using these tools in your CMS. There will also be an IKS event <a href="http://wiki.iks-project.eu/index.php/Workshops/Salzburg2012">in Salzburg on June 12-13</a> where we will be able to show more.</p>]]></content>
        <summary type="html"><![CDATA[
<p>It is again time to write an update on the state of <a href="http://www.iks-project.eu/">IKS's</a> two main components for the semantic editing part of <a href="../../decoupling_content_management/">Decoupled Content Management</a>:</p>
<ul><li> <a href="http://viejs.org/">VIE</a> is the base semantic interaction library that handles the site's  content model through RDFa annotations and Backbone.js synchronization</li>
<li><a href="http://createjs.org/">Create</a> is a new kind of web editing interface built on top of that.</li>
</ul><p>As the IKS project has <a href="http://blog.iks-project.eu/iks-2011-in-review/">entered its fourth year</a>, both of these projects have gained maturity and contributions from many IKS partners and early adopters.</p>
<h2>New UI for Create</h2>
<p>While Create can be used for building any sort of custom user  experiences (as seen in the CMS integration examples below), it also  ships with a default user interface. <a href="http://nemein.com/en/">Nemein's</a> Riku Virta has designed a new UI concept that is <a href="https://groups.google.com/d/topic/createjs/bYEiF1hWvXk/discussion">currently being discussed</a> on the CreateJS mailing list.</p>
<p>This interface builds on top of the <a href="../../introducing_the_midgard_create_user_interface/">original Create UI</a> and <a href="http://blog.iks-project.eu/what-liip-did-after-winning-the-iks-semantics-ux-contest/">Liip's</a> UX work, and aims to provide more area for CMS-specific functionality and better touchscreen support:</p>
<p><img src="http://bergie.iki.fi/static/1/1e16f90efc34dc66f9011e18c62b75b842496939693_create_new_ui.png" border="0" alt="create_new_ui.png" title="create_new_ui.png" /></p>
<p>See the full UI concept in <a href="https://plus.google.com/photos/113896057721233278902/albums/5717131156654359985/5717131206194261362">the slideshow on Google Plus</a>.</p>
<p>We hope that we will be able to land this new UI still within the March-April timeframe.</p>
<h2>VIE: 2.0 and onwards</h2>
<p>VIE is now <a href="http://blog.iks-project.eu/vie-towards-v2-0-update/">nearing the 2.0 release</a>,  with the first RC expected for the end of this month. After that we'll  have a hackathon in Saarbrucken, Germany where the plan is to focus on  things that we've targeted for a 2.1.</p>
<p>The main feature of VIE 2.1 is a new way of handling RDF literals. This will make it easier to interface with services like <a href="http://dbpedia.org/About">DBpedia</a> that give us data in multiple different languages. This will enable you to do things like:</p>
<pre><code>var eiffel = vie.entities.get('dbp:Eiffel_Tower');
console.log(eiffel.get('label')); // Eiffel Tower

vie.setLanguage('fi');
console.log(eiffel.get('label')); // Eiffel-torni
</code></pre>
<p>The final API for this is <a href="https://groups.google.com/d/topic/viejs/bXK3Xg-rrLA/discussion">still being discussed</a> on the VIE mailing list.</p>
<h2>Create and Hallo are now easier to integrate</h2>
<p>Both Create and <a href="http://bergie.github.com/hallo">Hallo</a>,  our minimalist rich text editing tool now provide merged JavaScript  files for easier integration. You can find the merged files, and also  minified versions in:</p>
<ul><li><a href="https://github.com/bergie/hallo/blob/master/examples/hallo.js">hallo.js</a></li>
<li><a href="https://github.com/bergie/create/blob/master/examples/create.js">create.js</a></li>
</ul><p>Thanks to contributions from <a href="http://www.alkacon.com/en/">Alkacon</a>,  Create's widget selection mechanism is now much more configurable. This  allows CMS developers to provide different editing tools for different  types of information.</p>
<p>The currently bundled editing interfaces provide integration with Hallo, and also with the 0.20 version of <a href="http://aloha-editor.org/">Aloha Editor</a> (though you will need to install Aloha separately to use it due to licensing restrictions).</p>
<p>CMS developers will also benefit from <a href="https://github.com/bergie/blogsiple">Blogsiple</a>,  the new integration testbed for Create and VIE. Blogsiple aims to be a  very simple blog system built on top of Node.js that shows all the  necessary integration points for supporting the whole range of VIE and  Create features.</p>
<h2>CMS adoption</h2>
<p>As both VIE and Create improve, so does their adoption in different Content Management Systems. For example, here is the new <a href="http://www.opencms.org/en/">OpenCms</a> user interface <a href="http://blog.iks-project.eu/alkacons-new-acacia-editor-based-on-iks-semantic-web-technology/">built on these tools</a>:</p>
<p><iframe width="399" height="203" src="http://www.youtube.com/embed/21QSPSKPs6I" frameborder="0" allowfullscreen></iframe></p>
<p>Polymedia's <a href="http://blog.iks-project.eu/polymedia-video-with-iks-semantic-annotation/">video annotation example</a> is also interesting demonstration of VIE in a completely different kind of CMS environment, as is <a href="http://blog.iks-project.eu/keen-onwordlift-a-short-story-how-we-plan-to-make-wordpress-a-semantic-cms/">WordLift</a> by InSideOut10.</p>
<p>The <a href="http://www.iks-project.eu/community/funding/early-adopters-programme">IKS Early Adopter program</a> is still open if you're interested in getting support for using these tools in your CMS. There will also be an IKS event <a href="http://wiki.iks-project.eu/index.php/Workshops/Salzburg2012">in Salzburg on June 12-13</a> where we will be able to show more.</p>]]></summary>
        <georss:point>52.490002 13.4212</georss:point>
    </entry>
    <entry>
        <title>Hacker-nomadism</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/hacker-nomadism/"/>
        <published>2012-03-16T17:40:39+00:00</published>
        <updated>2012-03-16T17:40:39+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e16f8f256adb626f8f11e198f1570eec0a20b220b2</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="desktop" />
        <content type="html"><![CDATA[
<p>I <a href="https://github.com/bergie">build software</a> for a living. This means creating the new generation of Content Management interfaces in the <a href="http://www.iks-project.eu/">IKS Project</a>, developing custom client applications at <a href="http://nemein.com/en/">Nemein</a>, and building the first cloud-based record label at <a href="http://musickickstarter.com/">Music Kickstarter</a>.</p>
<p>As my office is where <a href="http://bergie.iki.fi/blog/11-macbook_air-the_best_computer_i-ve_ever_had/">my laptop</a> is, none of this work is particularly tied to a physical location. And  as much of the work is communicating, I end up spending quite a lot of  time <a href="http://www.dopplr.com/traveller/bergie">traveling</a> between meetings and conferences.</p>
<p>For this my previous home town of Helsinki, Finland wasn't quite  ideal. From an European perspective, Finland is an island. And so I've  accumulated airmiles instead of being able to travel more comfortably (and  productively) on the <a href="http://www.rfi.it/cms/v/index.jsp?vgnextoid=8cf40c85eb02b110VgnVCM1000003f16f90aRCRD">European railway network</a>.</p>
<p>I've previously dabbled with living in other <a href="http://bergie.iki.fi/blog/part-time_istanbullu/">locations like Istanbul</a> and Saint Petersburg, but this time I hope the move will be more  permanent: in the beginning of this month we packed our stuff, got rid of <a href="http://bergie.iki.fi/blog/time_to_pack/">the Helsinki flat</a> and hopped on a plane to <a href="http://en.wikipedia.org/wiki/Berlin">Berlin</a>.</p>
<p><img src="http://bergie.iki.fi/static/1/1e16f8ea1c662f46f8e11e1bfb55fc7b79894649464_berlin-bears.png" border="0" alt="berlin-bears.png" title="berlin-bears.png" /></p>
<p>The modern world makes this easy: my whole library fits on a Kindle  and music collection on Spotify, version control and testing happens in  the cloud, and banking and invoices are on the web. And thanks to EU  there is minimal red tape in setting yourself up anywhere in Europe.</p>
<p>My current setup is such: I'm traveling with about two weeks' worth of clothes, my trusty work laptop, and tablet with an <a href="http://en.wikipedia.org/wiki/Asus_Eee_Pad_Transformer_Prime">amazing 18 hour battery life</a>.  Accommodation happens in furnished, short-term rental apartments, and  Internet comes from an old N900 serving as a WiFi access point via  prepaid 3G.</p>
<p>While Berlin has <a href="http://co-up.de/">excellent co-working spaces</a>, I'm currently sharing office with <a href="http://www.contentcontrol-berlin.de/">Content Control</a>,  the local Midgard shop. Though at the time of writing my office is  temporarily relocated to the nearby Hasenheide park where there is a  nice sunny spring day.</p>
<p><img src="http://bergie.iki.fi/static/1/1e16f8ef8fdea6a6f8e11e1b19243e3378f8ab58ab5_hasenheide-park-hacking.png" border="0" alt="hasenheide-park-hacking.png" title="hasenheide-park-hacking.png" /></p>
<p>I'm still planning on popping into Helsinki every now and then. With  Air Berlin, the travel cost and distance is almost the same as if I  lived in the Finnish city of Tampere (yeah, VR is expensive). Once the  snows there melt, I'll also ride my motorcycle over.</p>
<p>If things work out, I may be eventually able to say: <em><a href="http://en.wikipedia.org/wiki/Ich_bin_ein_Berliner">ich bin ein Berliner</a></em>. This city is quite amazing - the amount of cultural activities and hacker meetups probably beats any other place in Europe right now. If you're around, ping <a href="http://twitter.com/bergie">me</a>!</p>
<p>And if Berlin doesn't work, then there are lots of other interesting places for a working nomad...</p>]]></content>
        <summary type="html"><![CDATA[
<p>I <a href="https://github.com/bergie">build software</a> for a living. This means creating the new generation of Content Management interfaces in the <a href="http://www.iks-project.eu/">IKS Project</a>, developing custom client applications at <a href="http://nemein.com/en/">Nemein</a>, and building the first cloud-based record label at <a href="http://musickickstarter.com/">Music Kickstarter</a>.</p>
<p>As my office is where <a href="http://bergie.iki.fi/blog/11-macbook_air-the_best_computer_i-ve_ever_had/">my laptop</a> is, none of this work is particularly tied to a physical location. And  as much of the work is communicating, I end up spending quite a lot of  time <a href="http://www.dopplr.com/traveller/bergie">traveling</a> between meetings and conferences.</p>
<p>For this my previous home town of Helsinki, Finland wasn't quite  ideal. From an European perspective, Finland is an island. And so I've  accumulated airmiles instead of being able to travel more comfortably (and  productively) on the <a href="http://www.rfi.it/cms/v/index.jsp?vgnextoid=8cf40c85eb02b110VgnVCM1000003f16f90aRCRD">European railway network</a>.</p>
<p>I've previously dabbled with living in other <a href="http://bergie.iki.fi/blog/part-time_istanbullu/">locations like Istanbul</a> and Saint Petersburg, but this time I hope the move will be more  permanent: in the beginning of this month we packed our stuff, got rid of <a href="http://bergie.iki.fi/blog/time_to_pack/">the Helsinki flat</a> and hopped on a plane to <a href="http://en.wikipedia.org/wiki/Berlin">Berlin</a>.</p>
<p><img src="http://bergie.iki.fi/static/1/1e16f8ea1c662f46f8e11e1bfb55fc7b79894649464_berlin-bears.png" border="0" alt="berlin-bears.png" title="berlin-bears.png" /></p>
<p>The modern world makes this easy: my whole library fits on a Kindle  and music collection on Spotify, version control and testing happens in  the cloud, and banking and invoices are on the web. And thanks to EU  there is minimal red tape in setting yourself up anywhere in Europe.</p>
<p>My current setup is such: I'm traveling with about two weeks' worth of clothes, my trusty work laptop, and tablet with an <a href="http://en.wikipedia.org/wiki/Asus_Eee_Pad_Transformer_Prime">amazing 18 hour battery life</a>.  Accommodation happens in furnished, short-term rental apartments, and  Internet comes from an old N900 serving as a WiFi access point via  prepaid 3G.</p>
<p>While Berlin has <a href="http://co-up.de/">excellent co-working spaces</a>, I'm currently sharing office with <a href="http://www.contentcontrol-berlin.de/">Content Control</a>,  the local Midgard shop. Though at the time of writing my office is  temporarily relocated to the nearby Hasenheide park where there is a  nice sunny spring day.</p>
<p><img src="http://bergie.iki.fi/static/1/1e16f8ef8fdea6a6f8e11e1b19243e3378f8ab58ab5_hasenheide-park-hacking.png" border="0" alt="hasenheide-park-hacking.png" title="hasenheide-park-hacking.png" /></p>
<p>I'm still planning on popping into Helsinki every now and then. With  Air Berlin, the travel cost and distance is almost the same as if I  lived in the Finnish city of Tampere (yeah, VR is expensive). Once the  snows there melt, I'll also ride my motorcycle over.</p>
<p>If things work out, I may be eventually able to say: <em><a href="http://en.wikipedia.org/wiki/Ich_bin_ein_Berliner">ich bin ein Berliner</a></em>. This city is quite amazing - the amount of cultural activities and hacker meetups probably beats any other place in Europe right now. If you're around, ping <a href="http://twitter.com/bergie">me</a>!</p>
<p>And if Berlin doesn't work, then there are lots of other interesting places for a working nomad...</p>]]></summary>
        <georss:point>52.490002 13.4212</georss:point>
    </entry>
    <entry>
        <title>CreateJS is moving forward</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/createjs_is_moving_forward/"/>
        <published>2012-02-13T12:40:56+00:00</published>
        <updated>2012-02-13T12:40:56+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e1563ff972dc02563f11e19117e798ca2acd66cd66</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="midgard" />
        <content type="html"><![CDATA[
<p>As you probably know, we at <a href="http://www.iks-project.eu/">IKS</a> have been working to <a href="http://bergie.iki.fi/blog/decoupling_content_management/">decoupled content management</a> through semantic technologies. <a href="http://createjs.org/">CreateJS</a>, together with the <a href="http://viejs.org/">VIE</a> library provide the user-facing part of this approach.</p>

<p>Traditional content management has been very monolithic, meaning that by choosing a particular editing interface, CMS users also have to take the web framework, programming language and content storage mechanism mandated by the developers of their system. By splitting the CMS to the separate concepts of user interface, web framework, and content repository we can provide implementers a greater degree of freedom, and allow CMS developers to focus on the functionality where they can best make a difference.</p>

<h2>What is Create?</h2>

<p>With CreateJS, content management system developers can provide a simple, fast, and modern editing interface to their end-users. The UI is completely built in JavaScript, and can be integrated with three easy steps:</p>

<ol><li>Mark up your pages with <a href="http://www.w3.org/TR/xhtml-rdfa-primer/#id84624">RDFa annotations</a></li>
<li>Include <a href="http://viejs.org/">VIE</a> and <a href="http://createjs.org/">Create</a> into the pages</li>
<li>Implement <a href="http://documentcloud.github.com/backbone/#Sync">Backbone.sync</a> with your CMS back-end</li>
</ol><p>Create provides functionality like in-page content editing, managing of content collections (like article lists), running workflows for content, and handling images and content tagging. The jQuery UI plugin -based structure allows CMS developers also to implement their own additional functionality. This also makes it possible to either use the whole Create UI as-is, or just to take the parts of it that fit the UX concept of a system.</p>

<p>The <a href="http://bergie.iki.fi/blog/introducing_the_midgard_create_user_interface/">Create UI</a> was initially made for <a href="http://new.midgard-project.org/">Midgard CMS</a>, but has since been generalized so that it works anywhere. This approach has already <a href="https://twitter.com/bergie/status/146885794940993536">gained some popularity</a>, with CreateJS widgets being used in projects like <a href="http://cmf.symfony.com/">Symfony CMF</a>, <a href="http://drupal.org/sandbox/dominikb1888/1388900">Drupal</a>, and <a href="http://blog.iks-project.eu/viegwt-hackathon-at-alkacon/">OpenCMS</a>.</p>

<h2>The January hackathon</h2>

<p>To push CreateJS forward we organized <a href="http://lanyrd.com/2012/createjs-hackathon/">a hackathon in Zurich, Switzerland</a> in the early January. Participants came from different <a href="http://www.iks-project.eu/community/partners">IKS project partners</a> and CreateJS early adopters.</p>

<p>Some of the results were:</p>

<ul><li><a href="https://github.com/bergie/create/blob/master/src/jquery.Midgard.midgardWorkflows.js">Workflow support</a>, allowing CMSs to define per-content actions like publish/unpublish</li>
<li><a href="https://github.com/bergie/create/blob/master/src/jquery.Midgard.midgardNotifications.js">UI notifications</a>, including the possibility to build scripted tutorials for site editors</li>
<li><a href="https://github.com/bergie/createMarkdown">WYSIWYG editing of Markdown documents</a></li>
<li>Much more flexible <a href="https://github.com/bergie/create/blob/master/src/jquery.Midgard.midgardEditable.js#L9">handling of editing widgets</a>, for example to choose whether some content should be edited with a rich text editor, or a date picker</li>
<li>Smart <a href="https://github.com/bergie/hallo/blob/master/plugins/image.coffee">image insertion</a> when using the <a href="http://bergie.github.com/hallo/">Hallo editor</a></li>
<li><a href="https://github.com/bergie/create/pull/37">Content tagging</a> support</li>
<li><a href="https://github.com/bergie/blogsiple">Blogsiple</a>, a CreateJS CMS integration testbed written for Node.js</li>
</ul><p>Image insertion, link management, and content tagging have been designed to work together so that they can find about annotated entities thanks to the <a href="http://incubator.apache.org/stanbol/">Apache Stanbol</a> engine and provide intelligent suggestions on related content.</p>

<h2>Moving forward</h2>

<p>The important next step is to consolidate all these changes into the CreateJS codebase and to ensure that everything works smoothly together. Our <a href="http://travis-ci.org/bergie/create">continuous integration setup</a> would also benefit from a larger number of tests.</p>

<p>After that we can consider new features, including things <a href="https://github.com/bergie/create/issues">currently under discussion</a>.</p>

<p>Helping CMSs to integrate this common user interface (or parts of it) is also a major task for this year. If you're interested in using CreateJS for your system, be sure to <a href="http://groups.google.com/group/createjs">let us know</a>! And also <a href="https://github.com/bergie/create">follow the progress</a> on GitHub.</p>
]]></content>
        <summary type="html"><![CDATA[
<p>As you probably know, we at <a href="http://www.iks-project.eu/">IKS</a> have been working to <a href="http://bergie.iki.fi/blog/decoupling_content_management/">decoupled content management</a> through semantic technologies. <a href="http://createjs.org/">CreateJS</a>, together with the <a href="http://viejs.org/">VIE</a> library provide the user-facing part of this approach.</p>

<p>Traditional content management has been very monolithic, meaning that by choosing a particular editing interface, CMS users also have to take the web framework, programming language and content storage mechanism mandated by the developers of their system. By splitting the CMS to the separate concepts of user interface, web framework, and content repository we can provide implementers a greater degree of freedom, and allow CMS developers to focus on the functionality where they can best make a difference.</p>

<h2>What is Create?</h2>

<p>With CreateJS, content management system developers can provide a simple, fast, and modern editing interface to their end-users. The UI is completely built in JavaScript, and can be integrated with three easy steps:</p>

<ol><li>Mark up your pages with <a href="http://www.w3.org/TR/xhtml-rdfa-primer/#id84624">RDFa annotations</a></li>
<li>Include <a href="http://viejs.org/">VIE</a> and <a href="http://createjs.org/">Create</a> into the pages</li>
<li>Implement <a href="http://documentcloud.github.com/backbone/#Sync">Backbone.sync</a> with your CMS back-end</li>
</ol><p>Create provides functionality like in-page content editing, managing of content collections (like article lists), running workflows for content, and handling images and content tagging. The jQuery UI plugin -based structure allows CMS developers also to implement their own additional functionality. This also makes it possible to either use the whole Create UI as-is, or just to take the parts of it that fit the UX concept of a system.</p>

<p>The <a href="http://bergie.iki.fi/blog/introducing_the_midgard_create_user_interface/">Create UI</a> was initially made for <a href="http://new.midgard-project.org/">Midgard CMS</a>, but has since been generalized so that it works anywhere. This approach has already <a href="https://twitter.com/bergie/status/146885794940993536">gained some popularity</a>, with CreateJS widgets being used in projects like <a href="http://cmf.symfony.com/">Symfony CMF</a>, <a href="http://drupal.org/sandbox/dominikb1888/1388900">Drupal</a>, and <a href="http://blog.iks-project.eu/viegwt-hackathon-at-alkacon/">OpenCMS</a>.</p>

<h2>The January hackathon</h2>

<p>To push CreateJS forward we organized <a href="http://lanyrd.com/2012/createjs-hackathon/">a hackathon in Zurich, Switzerland</a> in the early January. Participants came from different <a href="http://www.iks-project.eu/community/partners">IKS project partners</a> and CreateJS early adopters.</p>

<p>Some of the results were:</p>

<ul><li><a href="https://github.com/bergie/create/blob/master/src/jquery.Midgard.midgardWorkflows.js">Workflow support</a>, allowing CMSs to define per-content actions like publish/unpublish</li>
<li><a href="https://github.com/bergie/create/blob/master/src/jquery.Midgard.midgardNotifications.js">UI notifications</a>, including the possibility to build scripted tutorials for site editors</li>
<li><a href="https://github.com/bergie/createMarkdown">WYSIWYG editing of Markdown documents</a></li>
<li>Much more flexible <a href="https://github.com/bergie/create/blob/master/src/jquery.Midgard.midgardEditable.js#L9">handling of editing widgets</a>, for example to choose whether some content should be edited with a rich text editor, or a date picker</li>
<li>Smart <a href="https://github.com/bergie/hallo/blob/master/plugins/image.coffee">image insertion</a> when using the <a href="http://bergie.github.com/hallo/">Hallo editor</a></li>
<li><a href="https://github.com/bergie/create/pull/37">Content tagging</a> support</li>
<li><a href="https://github.com/bergie/blogsiple">Blogsiple</a>, a CreateJS CMS integration testbed written for Node.js</li>
</ul><p>Image insertion, link management, and content tagging have been designed to work together so that they can find about annotated entities thanks to the <a href="http://incubator.apache.org/stanbol/">Apache Stanbol</a> engine and provide intelligent suggestions on related content.</p>

<h2>Moving forward</h2>

<p>The important next step is to consolidate all these changes into the CreateJS codebase and to ensure that everything works smoothly together. Our <a href="http://travis-ci.org/bergie/create">continuous integration setup</a> would also benefit from a larger number of tests.</p>

<p>After that we can consider new features, including things <a href="https://github.com/bergie/create/issues">currently under discussion</a>.</p>

<p>Helping CMSs to integrate this common user interface (or parts of it) is also a major task for this year. If you're interested in using CreateJS for your system, be sure to <a href="http://groups.google.com/group/createjs">let us know</a>! And also <a href="https://github.com/bergie/create">follow the progress</a> on GitHub.</p>
]]></summary>
        <georss:point>52.504101 13.3303</georss:point>
    </entry>
    <entry>
        <title>Open Mobile Linux, this Saturday in FOSDEM</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/open_mobile_linux_this_saturday_in_fosdem/"/>
        <published>2012-02-02T08:55:37+00:00</published>
        <updated>2012-02-02T08:55:37+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e14d7bacade7584d7b11e1a0e5ffab0d83f6f9f6f9</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="desktop" />
        <content type="html"><![CDATA[
<p>As mentioned in the earlier <a href="http://bergie.iki.fi/blog/call_for_presentations-open_mobile_linux_at_fosdem_2012/">call for presentations</a>, we're running a <a href="http://fosdem.org/2012/schedule/track/open_mobile_linux_devroom">track on Open Mobile Linux</a> in FOSDEM this Saturday. <a href="http://fosdem.org/2012/schedule/room/aw1120">Room AW1.120</a> at the ULB campus in Brussels. From the CfP:</p>
<blockquote>
<p>Our primary goal is to facilitate meetups, collaboration and awareness  between different projects and communities within Open Mobile Linux and  provide a place to present directions, ideas and your projects  themselves.<br /><br /> By Open Mobile Linux we mean any open source  projects revolving around typical non-desktop/server Linux, such as  handsets, tablets, netbooks or other creative uses. Examples of such  projects could be <a href="http://qt.nokia.com/">Qt5</a>, <a href="http://merproject.org/">Mer</a>, <a href="https://meego.com/">MeeGo</a>, <a href="http://www.android.com/">Android</a>, <a href="http://en.wikipedia.org/wiki/WebOS">webOS</a>, <a href="http://plasma-active.org/">Plasma Active</a>, <a href="https://www.tizen.org/">Tizen</a>, <a href="https://wiki.mozilla.org/B2G">Boot to Gecko</a>, <a href="http://shr-project.org/trac">SHR</a> and other related efforts.</p>
</blockquote>
<p>There are several exciting things happening in this space, including the recently announced <a href="http://www.slashgear.com/spark-plasma-active-7-inch-tablet-revealed-set-to-take-on-android-30211264/">Spark tablet</a>, open sourcing of <a href="http://arstechnica.com/gadgets/news/2012/01/hp-publishes-webos-enyo-framework-under-open-source-apache-license.ars">webOS's Enyo framework</a> and <a href="http://talk.maemo.org/showthread.php?t=82019">continuing interest in the Maemo</a> platform. Saturday's program includes:</p>
<ul><li><a href="http://fosdem.org/2012/schedule/event/mer_and_what_you_can_do_with_it">Mer ... and what you can do with it</a> (David Greaves, 11:30-12:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/openmoko_freerunner_present_and_future">Openmoko Freerunner - Present and Future</a> (Niels Heyvaert, 12:00-12:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/towards_accelerated_uis_on_mobile_linux_qt5">Towards Accelerated UI's on Mobile Linux With Power of Qt5</a> (Saija Eteläniemi, 12:30-13:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/tizen_and_the_future_of_community">Intro to Tizen and the Future of the Community</a> (Dawn Foster, 13:00-13:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/buildroot_flexible_building_of_a_custom_embedded_system">buildroot: flexible building of a custom embedded system</a> (Arnout Vandecappelle, 13:30-14:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/deep_dive_into_kde_mobile_development">Deep Dive into KDE Mobile development on N9/N950</a> (Laszlo Papp, 14:00-14:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/community_qt_apps_repository">Community Qt apps repository - way forward</a> (Jukka Eklund, 14:30-15:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/maliit_the_open_mobile_text_input_project">Maliit - the open mobile text input project</a> (Jon Nordby, 15:00-15:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/nemo_mobile">Nemo Mobile - How to contribute to the project</a> (Marko Saukko, 15:30-16:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/intro_to_qtonpi_project">Introduction to the QtOnPi project</a> (Rajiv Ranganath, 16:00-16:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/syncevolution_update">An update on PIM storage and sync: SyncEvolution</a> (Patrick Ohly, 16:30-17:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/os_in_the_mobile_app_stores">OS in the Mobile App Stores</a> (Thomas Bonte, 17:00-17:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/rygel_mobile_dlna">Rygel: Free and Open Mobile DLNA</a> (Jens Georg, 17:30-18:00)</li>
</ul><p>If there are any last-minute announcements or happenings that people want to discuss, we may be a ble to squeeze in a talk or two. Contact <a href="mailto:carsten.munk@gmail.com">Carsten</a> about this.</p>
<p>Also, if you want to chat other things (like <a href="http://phpcr.github.com/">PHPCR</a> or <a href="http://createjs.org/">CreateJS</a>), I'll be around the whole weekend including the <a href="http://fosdem.org/2012/beerevent">beer event</a>. Drop me <a>an SMS</a>.</p>
<p>Looking forward to seeing as many of you there as possible!</p>]]></content>
        <summary type="html"><![CDATA[
<p>As mentioned in the earlier <a href="http://bergie.iki.fi/blog/call_for_presentations-open_mobile_linux_at_fosdem_2012/">call for presentations</a>, we're running a <a href="http://fosdem.org/2012/schedule/track/open_mobile_linux_devroom">track on Open Mobile Linux</a> in FOSDEM this Saturday. <a href="http://fosdem.org/2012/schedule/room/aw1120">Room AW1.120</a> at the ULB campus in Brussels. From the CfP:</p>
<blockquote>
<p>Our primary goal is to facilitate meetups, collaboration and awareness  between different projects and communities within Open Mobile Linux and  provide a place to present directions, ideas and your projects  themselves.<br /><br /> By Open Mobile Linux we mean any open source  projects revolving around typical non-desktop/server Linux, such as  handsets, tablets, netbooks or other creative uses. Examples of such  projects could be <a href="http://qt.nokia.com/">Qt5</a>, <a href="http://merproject.org/">Mer</a>, <a href="https://meego.com/">MeeGo</a>, <a href="http://www.android.com/">Android</a>, <a href="http://en.wikipedia.org/wiki/WebOS">webOS</a>, <a href="http://plasma-active.org/">Plasma Active</a>, <a href="https://www.tizen.org/">Tizen</a>, <a href="https://wiki.mozilla.org/B2G">Boot to Gecko</a>, <a href="http://shr-project.org/trac">SHR</a> and other related efforts.</p>
</blockquote>
<p>There are several exciting things happening in this space, including the recently announced <a href="http://www.slashgear.com/spark-plasma-active-7-inch-tablet-revealed-set-to-take-on-android-30211264/">Spark tablet</a>, open sourcing of <a href="http://arstechnica.com/gadgets/news/2012/01/hp-publishes-webos-enyo-framework-under-open-source-apache-license.ars">webOS's Enyo framework</a> and <a href="http://talk.maemo.org/showthread.php?t=82019">continuing interest in the Maemo</a> platform. Saturday's program includes:</p>
<ul><li><a href="http://fosdem.org/2012/schedule/event/mer_and_what_you_can_do_with_it">Mer ... and what you can do with it</a> (David Greaves, 11:30-12:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/openmoko_freerunner_present_and_future">Openmoko Freerunner - Present and Future</a> (Niels Heyvaert, 12:00-12:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/towards_accelerated_uis_on_mobile_linux_qt5">Towards Accelerated UI's on Mobile Linux With Power of Qt5</a> (Saija Eteläniemi, 12:30-13:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/tizen_and_the_future_of_community">Intro to Tizen and the Future of the Community</a> (Dawn Foster, 13:00-13:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/buildroot_flexible_building_of_a_custom_embedded_system">buildroot: flexible building of a custom embedded system</a> (Arnout Vandecappelle, 13:30-14:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/deep_dive_into_kde_mobile_development">Deep Dive into KDE Mobile development on N9/N950</a> (Laszlo Papp, 14:00-14:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/community_qt_apps_repository">Community Qt apps repository - way forward</a> (Jukka Eklund, 14:30-15:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/maliit_the_open_mobile_text_input_project">Maliit - the open mobile text input project</a> (Jon Nordby, 15:00-15:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/nemo_mobile">Nemo Mobile - How to contribute to the project</a> (Marko Saukko, 15:30-16:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/intro_to_qtonpi_project">Introduction to the QtOnPi project</a> (Rajiv Ranganath, 16:00-16:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/syncevolution_update">An update on PIM storage and sync: SyncEvolution</a> (Patrick Ohly, 16:30-17:00)</li>
<li><a href="http://fosdem.org/2012/schedule/event/os_in_the_mobile_app_stores">OS in the Mobile App Stores</a> (Thomas Bonte, 17:00-17:30)</li>
<li><a href="http://fosdem.org/2012/schedule/event/rygel_mobile_dlna">Rygel: Free and Open Mobile DLNA</a> (Jens Georg, 17:30-18:00)</li>
</ul><p>If there are any last-minute announcements or happenings that people want to discuss, we may be a ble to squeeze in a talk or two. Contact <a href="mailto:carsten.munk@gmail.com">Carsten</a> about this.</p>
<p>Also, if you want to chat other things (like <a href="http://phpcr.github.com/">PHPCR</a> or <a href="http://createjs.org/">CreateJS</a>), I'll be around the whole weekend including the <a href="http://fosdem.org/2012/beerevent">beer event</a>. Drop me <a>an SMS</a>.</p>
<p>Looking forward to seeing as many of you there as possible!</p>]]></summary>
        <georss:point>60.1632 24.9277</georss:point>
    </entry>
    <entry>
        <title>Midgard2 PHPCR provider hits 1.0</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/midgard2_phpcr_provider_hits_1-0/"/>
        <published>2011-12-23T10:03:14+00:00</published>
        <updated>2011-12-23T10:03:14+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e12d4d5457ea202d4d11e19fc8b9739d85f14cf14c</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="midgard" />
        <content type="html"><![CDATA[
<p>I'm happy to announce that we were able to release the <a href="http://packagist.org/packages/midgard/phpcr">first stable version</a> of the <a href="https://github.com/midgardproject/phpcr-midgard2">Midgard2 PHPCR provider </a>yesterday.<br /><br />Simply put, <a href="http://phpcr.github.com/">PHPCR</a> is the future of Midgard's PHP API. Instead of having our own repository APIs, we follow the <a href="http://phpcr.github.com/doc/html/index.html">well-documented</a> and <a href="https://github.com/phpcr/phpcr-api-tests">tested</a> PHP Content Repository specification. This allows much better compatibility with other projects, and for example the possibility to choose whether to store contents in <a href="http://www.midgard-project.org/midgard2/">Midgard2</a> or <a href="http://jackrabbit.apache.org/">Apache Jackrabbit</a> on per-deployment basis. This obviously doesn't mean that the current Midgard2 API is going away, but just that there is something better and more compatible available on top of that.<br /><br />PHPCR provides a nice set of capabilities that are either <a href="http://bergie.iki.fi/blog/what_is_a_content_repository/">similar to, or surpass</a> the traditional Midgard features:</p>
<ul><li>Your content model is constructed out of a <a href="http://www.day.com/specs/jcr/2.0/3_Repository_Model.html">tree of Nodes</a> that can contain other Nodes or Properties</li>
<li>Properties can be of many different types, including the typical strings and floats, but also binaries (similar to our blobs) and dates</li>
<li>Properties can be <a href="http://www.day.com/specs/jcr/1.0/6.4.2.5_Multi-value_Properties.html">multivalued</a> (think of multiple images in same property, or a person having multiple emails)</li>
<li>Queries can be either constructed with <a href="http://docs.jboss.org/modeshape/latest/manuals/reference/html/jcr-query-and-search.html#jcr-qom-query-language">Query Object Model</a> or <a href="http://docs.jboss.org/modeshape/latest/manuals/reference/html/jcr-query-and-search.html#jcr-sql2-query-language">SQL2</a></li>
<li>Queries support tree constraints (ISDESCENDANTNODE, ISCHILDNODE) and joins</li>
<li>Content can be exported and imported via a standard XML format</li>
<li>There is a comprehensive <a href="http://www.day.com/specs/jcr/2.0/8_Node_Type_Discovery.html">Node Type system</a> that allows you to define your content model. The full definitions can be read and introspected via PHP</li>
<li>Nodes also <a href="http://www.ibm.com/developerworks/java/library/j-jcr/#1">support mixins</a>, allowing you to add per-object metadata</li>
<li>There are also the <a href="http://dev.day.com/content/ddc/blog/2010/05/you_do_not_have_toc.html">unstructured nodes</a> (<em>nt:unstructured</em>) for cases where you don't want to have constraints on what to store and how</li>
</ul><p>On top of PHPCR, there is also <a href="https://github.com/doctrine/phpcr-odm#readme">a Doctrine ODM</a> that the Midgard2 provider also supports. That gives you more capabilities, like:</p>
<ul><li>More traditional object access with getters and setters to the repository</li>
<li><a href="http://blog.liip.ch/archive/2011/12/18/multilanguage-support-for-doctrine-phpcr-odm.html">Multilingual content storage</a></li>
</ul><p>Some code examples: <a href="https://github.com/bergie/phpcr-midgard2/tree/master/examples">https://github.com/bergie/phpcr-midgard2/tree/master/examples</a><br /><br />You can see Midgard's test status for both SQLite and MySQL storage back-ends <a href="http://travis-ci.org/#!/bergie/phpcr-midgard2">in our Continuous Integration environment</a>: <img src="https://secure.travis-ci.org/bergie/phpcr-midgard2.png" border="0" alt="phpcr-midgard2.png" /><br /><br />Once you have Midgard2 and our PHP extension available, installation is easy. Add a <em>composer.json</em> file into the root folder of your project:</p>
<pre>{<br />  "require": {
    "midgard/phpcr": "&gt;=1.0"
  }<br />}</pre>
<p>Install with <a href="http://packagist.org/">Composer</a>:</p>
<pre>$ wget http://getcomposer.org/composer.phar<br />$ php composer.phar install</pre>
<p>Copy MgdSchemas:</p>
<pre>$ sudo cp vendor/midgard/phpcr/data/share/schema/* /usr/share/midgard2/schema/<br />$ sudo cp vendor/midgard/phpcr/data/share/views/* /usr/share/midgard2/views/</pre>
<p>...and then just start using the repository in your application. PHPCR can obviously be used side-by-side with traditional Midgard2 or other PHP code.<br /><br />What will happen next:</p>
<ul><li>Support for PHP 5.4 and Postgres (needs work on Midgard2 level)</li>
<li>Performance optimization</li>
<li>Features work, including <a href="http://www.day.com/specs/jcr/2.0/15_Versioning.html">versioning</a></li>
<li>More tools for PHPCR. Think of <a href="http://bergie.iki.fi/blog/building_a_new_admin_interface_for_midgard/">Asgard</a> that would allow you to work with any repositories!</li>
<li>PHPCR support built-in for <a href="http://new.midgard-project.org/midcom">MidCOM</a> and <a href="http://new.midgard-project.org/midgardmvc/">MVC</a>?</li>
</ul><p>For those interested in learning more about PHPCR, there will also be a <a href="http://lanyrd.com/2012/phpcr-meetup-paris/">Paris meetup in mid-January</a>.</p>]]></content>
        <summary type="html"><![CDATA[
<p>I'm happy to announce that we were able to release the <a href="http://packagist.org/packages/midgard/phpcr">first stable version</a> of the <a href="https://github.com/midgardproject/phpcr-midgard2">Midgard2 PHPCR provider </a>yesterday.<br /><br />Simply put, <a href="http://phpcr.github.com/">PHPCR</a> is the future of Midgard's PHP API. Instead of having our own repository APIs, we follow the <a href="http://phpcr.github.com/doc/html/index.html">well-documented</a> and <a href="https://github.com/phpcr/phpcr-api-tests">tested</a> PHP Content Repository specification. This allows much better compatibility with other projects, and for example the possibility to choose whether to store contents in <a href="http://www.midgard-project.org/midgard2/">Midgard2</a> or <a href="http://jackrabbit.apache.org/">Apache Jackrabbit</a> on per-deployment basis. This obviously doesn't mean that the current Midgard2 API is going away, but just that there is something better and more compatible available on top of that.<br /><br />PHPCR provides a nice set of capabilities that are either <a href="http://bergie.iki.fi/blog/what_is_a_content_repository/">similar to, or surpass</a> the traditional Midgard features:</p>
<ul><li>Your content model is constructed out of a <a href="http://www.day.com/specs/jcr/2.0/3_Repository_Model.html">tree of Nodes</a> that can contain other Nodes or Properties</li>
<li>Properties can be of many different types, including the typical strings and floats, but also binaries (similar to our blobs) and dates</li>
<li>Properties can be <a href="http://www.day.com/specs/jcr/1.0/6.4.2.5_Multi-value_Properties.html">multivalued</a> (think of multiple images in same property, or a person having multiple emails)</li>
<li>Queries can be either constructed with <a href="http://docs.jboss.org/modeshape/latest/manuals/reference/html/jcr-query-and-search.html#jcr-qom-query-language">Query Object Model</a> or <a href="http://docs.jboss.org/modeshape/latest/manuals/reference/html/jcr-query-and-search.html#jcr-sql2-query-language">SQL2</a></li>
<li>Queries support tree constraints (ISDESCENDANTNODE, ISCHILDNODE) and joins</li>
<li>Content can be exported and imported via a standard XML format</li>
<li>There is a comprehensive <a href="http://www.day.com/specs/jcr/2.0/8_Node_Type_Discovery.html">Node Type system</a> that allows you to define your content model. The full definitions can be read and introspected via PHP</li>
<li>Nodes also <a href="http://www.ibm.com/developerworks/java/library/j-jcr/#1">support mixins</a>, allowing you to add per-object metadata</li>
<li>There are also the <a href="http://dev.day.com/content/ddc/blog/2010/05/you_do_not_have_toc.html">unstructured nodes</a> (<em>nt:unstructured</em>) for cases where you don't want to have constraints on what to store and how</li>
</ul><p>On top of PHPCR, there is also <a href="https://github.com/doctrine/phpcr-odm#readme">a Doctrine ODM</a> that the Midgard2 provider also supports. That gives you more capabilities, like:</p>
<ul><li>More traditional object access with getters and setters to the repository</li>
<li><a href="http://blog.liip.ch/archive/2011/12/18/multilanguage-support-for-doctrine-phpcr-odm.html">Multilingual content storage</a></li>
</ul><p>Some code examples: <a href="https://github.com/bergie/phpcr-midgard2/tree/master/examples">https://github.com/bergie/phpcr-midgard2/tree/master/examples</a><br /><br />You can see Midgard's test status for both SQLite and MySQL storage back-ends <a href="http://travis-ci.org/#!/bergie/phpcr-midgard2">in our Continuous Integration environment</a>: <img src="https://secure.travis-ci.org/bergie/phpcr-midgard2.png" border="0" alt="phpcr-midgard2.png" /><br /><br />Once you have Midgard2 and our PHP extension available, installation is easy. Add a <em>composer.json</em> file into the root folder of your project:</p>
<pre>{<br />  "require": {
    "midgard/phpcr": "&gt;=1.0"
  }<br />}</pre>
<p>Install with <a href="http://packagist.org/">Composer</a>:</p>
<pre>$ wget http://getcomposer.org/composer.phar<br />$ php composer.phar install</pre>
<p>Copy MgdSchemas:</p>
<pre>$ sudo cp vendor/midgard/phpcr/data/share/schema/* /usr/share/midgard2/schema/<br />$ sudo cp vendor/midgard/phpcr/data/share/views/* /usr/share/midgard2/views/</pre>
<p>...and then just start using the repository in your application. PHPCR can obviously be used side-by-side with traditional Midgard2 or other PHP code.<br /><br />What will happen next:</p>
<ul><li>Support for PHP 5.4 and Postgres (needs work on Midgard2 level)</li>
<li>Performance optimization</li>
<li>Features work, including <a href="http://www.day.com/specs/jcr/2.0/15_Versioning.html">versioning</a></li>
<li>More tools for PHPCR. Think of <a href="http://bergie.iki.fi/blog/building_a_new_admin_interface_for_midgard/">Asgard</a> that would allow you to work with any repositories!</li>
<li>PHPCR support built-in for <a href="http://new.midgard-project.org/midcom">MidCOM</a> and <a href="http://new.midgard-project.org/midgardmvc/">MVC</a>?</li>
</ul><p>For those interested in learning more about PHPCR, there will also be a <a href="http://lanyrd.com/2012/phpcr-meetup-paris/">Paris meetup in mid-January</a>.</p>]]></summary>
        <georss:point>60.1632 24.9277</georss:point>
    </entry>
    <entry>
        <title>Using CoffeeScript for GNOME development</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/using_coffeescript_for_gnome_development/"/>
        <published>2011-12-16T16:04:16+00:00</published>
        <updated>2011-12-16T16:04:16+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e127ff9aa5e51627ff11e186bea967a20cfaecfaec</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="desktop" />
        <content type="html"><![CDATA[
<p>In <a href="http://cannonerd.wordpress.com/">Suski's blog</a> I saw <a href="http://cannonerd.wordpress.com/2011/12/14/gnome-and-javascript/#comment-112">a question</a> on whether developing GNOME apps would be possible in <a href="http://coffeescript.org/">CoffeeScript</a>. The answer is yes. I wrote a quick example <a href="https://twitter.com/bergie/status/100116112649355264">back in Desktop Summit</a>:</p>
<pre># GObject Introspection APIs are available from imports.gi.Modulename<br />Gtk = imports.gi.Gtk<br /><br /># For GNOME 3.2+ this should be Gtk.init null, 0<br />Gtk.init 0, null<br /><br />win = new Gtk.Window<br />    type: Gtk.WindowType.TOPLEVEL<br />win.set_border_width 10<br />win.connect "destroy", (widget) -&gt;<br />    Gtk.main_quit()<br /><br />button = new Gtk.Button<br />    label: "Hello, world"<br />button.connect "clicked", -&gt;<br />    button.set_label "Bar"<br />win.add button<br /><br />button.show()<br />win.show()<br /><br />Gtk.main()</pre>
<p><a href="http://live.gnome.org/Gjs">Gjs</a> doesn't run CoffeeScript directly, so you need to convert this before running:</p>
<pre>$ coffee -c window.coffee <br />$ gjs window.js</pre>
<p>You should see something similar to:</p>
<p><img src="http://bergie.iki.fi/static/1/1e127ff79e185ba27ff11e1ba9bc75aa947665f665f_gjs-coffee-example.png" border="0" alt="gjs-coffee-example.png" title="gjs-coffee-example.png" /></p>]]></content>
        <summary type="html"><![CDATA[
<p>In <a href="http://cannonerd.wordpress.com/">Suski's blog</a> I saw <a href="http://cannonerd.wordpress.com/2011/12/14/gnome-and-javascript/#comment-112">a question</a> on whether developing GNOME apps would be possible in <a href="http://coffeescript.org/">CoffeeScript</a>. The answer is yes. I wrote a quick example <a href="https://twitter.com/bergie/status/100116112649355264">back in Desktop Summit</a>:</p>
<pre># GObject Introspection APIs are available from imports.gi.Modulename<br />Gtk = imports.gi.Gtk<br /><br /># For GNOME 3.2+ this should be Gtk.init null, 0<br />Gtk.init 0, null<br /><br />win = new Gtk.Window<br />    type: Gtk.WindowType.TOPLEVEL<br />win.set_border_width 10<br />win.connect "destroy", (widget) -&gt;<br />    Gtk.main_quit()<br /><br />button = new Gtk.Button<br />    label: "Hello, world"<br />button.connect "clicked", -&gt;<br />    button.set_label "Bar"<br />win.add button<br /><br />button.show()<br />win.show()<br /><br />Gtk.main()</pre>
<p><a href="http://live.gnome.org/Gjs">Gjs</a> doesn't run CoffeeScript directly, so you need to convert this before running:</p>
<pre>$ coffee -c window.coffee <br />$ gjs window.js</pre>
<p>You should see something similar to:</p>
<p><img src="http://bergie.iki.fi/static/1/1e127ff79e185ba27ff11e1ba9bc75aa947665f665f_gjs-coffee-example.png" border="0" alt="gjs-coffee-example.png" title="gjs-coffee-example.png" /></p>]]></summary>
        <georss:point>47.809502 13.055</georss:point>
    </entry>
    <entry>
        <title>Call for presentations: Open Mobile Linux at FOSDEM 2012</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/call_for_presentations-open_mobile_linux_at_fosdem_2012/"/>
        <published>2011-12-14T09:46:57+00:00</published>
        <updated>2011-12-14T09:46:57+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e126388fecbab4263811e19e0dff56c9d520002000</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="desktop" />
        <content type="html"><![CDATA[
<p>At <a href="http://fosdem.org/2012/">FOSDEM 2012</a> we will have a <a href="http://fosdem.org/2012/devrooms_for_2012">devroom</a> related to <em>Open Mobile Linux</em>. Our primary goal is to facilitate meetups, collaboration and awareness between different projects and communities within Open Mobile Linux and provide a place to present directions, ideas and your projects themselves.<br /><br /> By Open Mobile Linux we mean any open source projects revolving around typical non-desktop/server Linux, such as handsets, tablets, netbooks or other creative uses. Examples of such projects could be <a href="http://qt.nokia.com/">Qt5</a>, <a href="http://merproject.org/">Mer</a>, <a href="https://meego.com/">MeeGo</a>, <a href="http://www.android.com/">Android</a>, <a href="http://en.wikipedia.org/wiki/WebOS">webOS</a>, <a href="http://plasma-active.org/">Plasma Active</a>, <a href="https://www.tizen.org/">Tizen</a>, <a href="https://wiki.mozilla.org/B2G">Boot to Gecko</a>, <a href="http://shr-project.org/trac">SHR</a> and other related efforts.<br /><br /> We have the room AW1.120 with 74 seats, a video projector (VGA), wireless internet on Saturday 4th February for a total of 8 hours.<br /><br /> The format we will be utilizing is <a href="http://en.wikipedia.org/wiki/Lightning_Talk">lightning talks</a> of length 15 minutes with 10 minutes of questions, 5 minute changeover to next speaker. Our goal is about 15 talks during the day.<br /><br /> The motivation is that after each talk, you and your project will be visible to the rest of the Open Mobile Linux community and further deeper discussions into your topic with your peers can continue outside the devroom.</p>
<p>Please send a short biography and an abstract for your talk to <a href="mailto:carsten.munk@gmail.com">carsten.munk@gmail.com</a> by Dec 31st 2011, and we'll get back to you at latest January 7th.</p>
<p>We're also grateful for volunteers helping to run the devroom. Contact Carsten if you're interested.</p>]]></content>
        <summary type="html"><![CDATA[
<p>At <a href="http://fosdem.org/2012/">FOSDEM 2012</a> we will have a <a href="http://fosdem.org/2012/devrooms_for_2012">devroom</a> related to <em>Open Mobile Linux</em>. Our primary goal is to facilitate meetups, collaboration and awareness between different projects and communities within Open Mobile Linux and provide a place to present directions, ideas and your projects themselves.<br /><br /> By Open Mobile Linux we mean any open source projects revolving around typical non-desktop/server Linux, such as handsets, tablets, netbooks or other creative uses. Examples of such projects could be <a href="http://qt.nokia.com/">Qt5</a>, <a href="http://merproject.org/">Mer</a>, <a href="https://meego.com/">MeeGo</a>, <a href="http://www.android.com/">Android</a>, <a href="http://en.wikipedia.org/wiki/WebOS">webOS</a>, <a href="http://plasma-active.org/">Plasma Active</a>, <a href="https://www.tizen.org/">Tizen</a>, <a href="https://wiki.mozilla.org/B2G">Boot to Gecko</a>, <a href="http://shr-project.org/trac">SHR</a> and other related efforts.<br /><br /> We have the room AW1.120 with 74 seats, a video projector (VGA), wireless internet on Saturday 4th February for a total of 8 hours.<br /><br /> The format we will be utilizing is <a href="http://en.wikipedia.org/wiki/Lightning_Talk">lightning talks</a> of length 15 minutes with 10 minutes of questions, 5 minute changeover to next speaker. Our goal is about 15 talks during the day.<br /><br /> The motivation is that after each talk, you and your project will be visible to the rest of the Open Mobile Linux community and further deeper discussions into your topic with your peers can continue outside the devroom.</p>
<p>Please send a short biography and an abstract for your talk to <a href="mailto:carsten.munk@gmail.com">carsten.munk@gmail.com</a> by Dec 31st 2011, and we'll get back to you at latest January 7th.</p>
<p>We're also grateful for volunteers helping to run the devroom. Contact Carsten if you're interested.</p>]]></summary>
        <georss:point>47.809502 13.055</georss:point>
    </entry>
    <entry>
        <title>Composer solves the PHP code-sharing problem</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/composer_solves_the_php_code-sharing_problem/"/>
        <published>2011-11-02T00:01:06+00:00</published>
        <updated>2011-11-02T00:01:06+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e104e5c359986404e511e198f2110c4696fb13fb13</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="midgard" />
        <content type="html"><![CDATA[
<p>In PHP we've had <a href="http://bergie.iki.fi/blog/php-finally_getting_an_ecosystem/">a lousy culture</a> of code-sharing. Because depending on code from others as been tricky, every major PHP application or framework has practically had to reimplement the whole world. Only some tools, like <a href="https://github.com/sebastianbergmann/phpunit/">PHPUnit</a>, have managed to break over this barrier and become de-facto standards across project boundaries. But for the rest: just write it yourself.</p>

<p>But now <a href="http://packagist.org/about-composer">Composer</a>, and its repository counterpart <a href="http://packagist.org/">Packagist</a>, promise to change all that. And obviously new conventions like PHP's <a href="http://www.php.net/manual/en/language.namespaces.rationale.php">namespacing support</a> and the <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md">PSR-0</a> standard autoloader help.</p>

<p>Composer is heavily inspired by <a href="http://npmjs.org/">NPM</a> which has built a strong culture of code-sharing and easy deployment in the Node.js community.</p>

<h2>Easy for users</h2>

<p>With Composer, managing dependencies in your project is very easy. Simply create a <code>composer.json</code> file where you state your dependencies, and let the package management system worry about the rest.</p>

<p>Packages that are registered with packagist.org are obviously easiest to depend on, but you can also state packages coming from custom repositories (like your company's internal version control system), or PHP extensions that you need.</p>

<p>Here is for example the <code>composer.json</code> from the <a href="https://github.com/bergie/phpcr-midgard2">Midgard PHPCR provider</a>:</p>

<pre><code>{
    "name": "midgard/phpcr",
    "type": "library",
    "require": {
        "php": "&gt;=5.3.0",
        "ext-midgard2": "&gt;=10.05.5",
        "phpcr/phpcr": "&gt;=2.1.0-beta1"
    }
}
</code></pre>

<p>With this file, Composer knows that our PHPCR provider runs only on PHP 5.3 or newer (as it uses namespaces), and that it needs the <a href="http://new.midgard-project.org/midgard2/">Midgard PHP extension</a> and the <a href="http://phpcr.github.com/">PHPCR interface classes</a> to be available.</p>

<p>Now installing the project is easy:</p>

<pre><code>$ wget http://getcomposer.org/composer.phar 
$ php composer.phar install
</code></pre>

<p>How about autoloading? Traditionally PHP required you to manually <code>include</code> or <code>require</code> all files you wanted to use in your code, with the possibility to <a href="http://php.net/manual/en/language.oop5.autoload.php">write an autoloader</a> to handle it automatically when you call an undefined class. But managing these autoloaders is also a chore.</p>

<p>Composer helps here too, by automatically generating an autoloader that will be able to load your own code, and the code from all your dependencies. So you can get rid of your own autoloaders and <code>include</code> statements, and just include the Composer-generated autoloader in your code:</p>

<pre><code>require 'vendor/.composer/autoload.php';
</code></pre>

<p>After this all the classes you've stated your application needing will be available.</p>

<h2>Easy for developers</h2>

<p>While ease-of-installation is important, it isn't enough to build an ecosystem. The other thing that has to be easy is publishing code. Basically: <em>if you've written a piece of functionality in PHP that you could see yourself using in another project, it should be effortless to publish it as a library.</em></p>

<p>This is where approaches like PEAR mostly failed, by making it too cumbersome to define your packages, to build them, and to upload them to the repository.</p>

<p>With Composer <a href="http://packagist.org/about">this is very easy</a>. You again define a <code>composer.json</code> for your package, and push that to your project's Git repository. Then just <a href="http://packagist.org/packages/submit">register</a> the Git repository URL with packagist.org.</p>

<p>After this Packagist will spider your repository and make it available as a package.</p>

<p>Publishing new versions is very easy: simply keep your <code>composer.json</code> up-to-date, and <a href="http://learn.github.com/p/tagging.html">tag your releases</a> in Git.</p>

<h2>Where are we now?</h2>

<p>It is still early days for Composer, and <a href="https://github.com/composer/composer">the project</a> is being worked on at a hectic pace. However, it is already good enough for managing dependencies to modern, PSR-0 compatible libraries.</p>

<p>What I would like to see happen next is support for custom package roles and autoloaders. This would allow us to handle more specific cases, like for example installation of <a href="http://new.midgard-project.org/midgardmvc/#structure_of_a_component">Midgard MVC components</a> and their non-namespaced autoloading needs. After that we should be able to get rid of our custom installer code and just join the Composer crowd.</p>

<p>But if your code is already fully namespaced, this is a great time to get started with <a href="http://packagist.org/about-composer">Composer</a>.</p>
]]></content>
        <summary type="html"><![CDATA[
<p>In PHP we've had <a href="http://bergie.iki.fi/blog/php-finally_getting_an_ecosystem/">a lousy culture</a> of code-sharing. Because depending on code from others as been tricky, every major PHP application or framework has practically had to reimplement the whole world. Only some tools, like <a href="https://github.com/sebastianbergmann/phpunit/">PHPUnit</a>, have managed to break over this barrier and become de-facto standards across project boundaries. But for the rest: just write it yourself.</p>

<p>But now <a href="http://packagist.org/about-composer">Composer</a>, and its repository counterpart <a href="http://packagist.org/">Packagist</a>, promise to change all that. And obviously new conventions like PHP's <a href="http://www.php.net/manual/en/language.namespaces.rationale.php">namespacing support</a> and the <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md">PSR-0</a> standard autoloader help.</p>

<p>Composer is heavily inspired by <a href="http://npmjs.org/">NPM</a> which has built a strong culture of code-sharing and easy deployment in the Node.js community.</p>

<h2>Easy for users</h2>

<p>With Composer, managing dependencies in your project is very easy. Simply create a <code>composer.json</code> file where you state your dependencies, and let the package management system worry about the rest.</p>

<p>Packages that are registered with packagist.org are obviously easiest to depend on, but you can also state packages coming from custom repositories (like your company's internal version control system), or PHP extensions that you need.</p>

<p>Here is for example the <code>composer.json</code> from the <a href="https://github.com/bergie/phpcr-midgard2">Midgard PHPCR provider</a>:</p>

<pre><code>{
    "name": "midgard/phpcr",
    "type": "library",
    "require": {
        "php": "&gt;=5.3.0",
        "ext-midgard2": "&gt;=10.05.5",
        "phpcr/phpcr": "&gt;=2.1.0-beta1"
    }
}
</code></pre>

<p>With this file, Composer knows that our PHPCR provider runs only on PHP 5.3 or newer (as it uses namespaces), and that it needs the <a href="http://new.midgard-project.org/midgard2/">Midgard PHP extension</a> and the <a href="http://phpcr.github.com/">PHPCR interface classes</a> to be available.</p>

<p>Now installing the project is easy:</p>

<pre><code>$ wget http://getcomposer.org/composer.phar 
$ php composer.phar install
</code></pre>

<p>How about autoloading? Traditionally PHP required you to manually <code>include</code> or <code>require</code> all files you wanted to use in your code, with the possibility to <a href="http://php.net/manual/en/language.oop5.autoload.php">write an autoloader</a> to handle it automatically when you call an undefined class. But managing these autoloaders is also a chore.</p>

<p>Composer helps here too, by automatically generating an autoloader that will be able to load your own code, and the code from all your dependencies. So you can get rid of your own autoloaders and <code>include</code> statements, and just include the Composer-generated autoloader in your code:</p>

<pre><code>require 'vendor/.composer/autoload.php';
</code></pre>

<p>After this all the classes you've stated your application needing will be available.</p>

<h2>Easy for developers</h2>

<p>While ease-of-installation is important, it isn't enough to build an ecosystem. The other thing that has to be easy is publishing code. Basically: <em>if you've written a piece of functionality in PHP that you could see yourself using in another project, it should be effortless to publish it as a library.</em></p>

<p>This is where approaches like PEAR mostly failed, by making it too cumbersome to define your packages, to build them, and to upload them to the repository.</p>

<p>With Composer <a href="http://packagist.org/about">this is very easy</a>. You again define a <code>composer.json</code> for your package, and push that to your project's Git repository. Then just <a href="http://packagist.org/packages/submit">register</a> the Git repository URL with packagist.org.</p>

<p>After this Packagist will spider your repository and make it available as a package.</p>

<p>Publishing new versions is very easy: simply keep your <code>composer.json</code> up-to-date, and <a href="http://learn.github.com/p/tagging.html">tag your releases</a> in Git.</p>

<h2>Where are we now?</h2>

<p>It is still early days for Composer, and <a href="https://github.com/composer/composer">the project</a> is being worked on at a hectic pace. However, it is already good enough for managing dependencies to modern, PSR-0 compatible libraries.</p>

<p>What I would like to see happen next is support for custom package roles and autoloaders. This would allow us to handle more specific cases, like for example installation of <a href="http://new.midgard-project.org/midgardmvc/#structure_of_a_component">Midgard MVC components</a> and their non-namespaced autoloading needs. After that we should be able to get rid of our custom installer code and just join the Composer crowd.</p>

<p>But if your code is already fully namespaced, this is a great time to get started with <a href="http://packagist.org/about-composer">Composer</a>.</p>
]]></summary>
        <georss:point>60.1698 24.9382</georss:point>
    </entry>
    <entry>
        <title>DNode: Make PHP and Node.js talk to each other</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/dnode-make_php_and_node-js_talk_to_each_other/"/>
        <published>2011-10-31T11:50:50+00:00</published>
        <updated>2011-10-31T11:50:50+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e103b6941bc15603b611e1bebb99c996e30f990f99</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="midgard" />
        <content type="html"><![CDATA[
<p>If you've been following my blog, you might have noticed that lately I've started doing quite a lot of <a href="http://nodejs.org/">Node.js</a> development alongside PHP. Based on conversations I've had in various conferences, I'm by far not alone in this situation - using Node.js for real-time functionality, and PHP (or Django, or Rails) for the more traditional CRUD stuff.</p>

<p>Both environments have their strong points. Node.js is very fast and flexible, but PHP has a lot more mature tools and libraries available. So in a lot of projects it is hard to choose between the two. But now you might not have to.</p>

<h2>Enter DNode</h2>

<p><a href="http://substack.net/posts/85e1bd/DNode-Asynchronous-Remote-Method-Invocation-for-Node-js-and-the-Browser">DNode</a> is a <em>remote method invocation</em> protocol originally written for Node.js, as the name probably tells. But as <a href="https://github.com/substack/dnode-protocol#readme">the protocol</a> itself is quite simple, just sending newline-terminated JSON packets over TCP connections, implementations have started popping up in other languages. You can talk DNode in <a href="https://github.com/substack/dnode-ruby">Ruby</a>, <a href="https://github.com/substack/dnode-perl">Perl</a>, <a href="https://github.com/jesusabdullah/dnode-python">Python</a>, <a href="https://github.com/aslakhellesoy/dnode-java">Java</a>, and now <a href="https://github.com/bergie/dnode-php">PHP</a>.</p>

<p>I started working on the PHP DNode implementation in the <a href="http://blog.liip.ch/archive/2011/09/30/symfony-cmf-hackday-october-22nd-in-cologne.html">Symfony CMF hackday</a> in Cologne a week ago, and got it into a running stage on a train ride from there to Paris. The implementation isn't yet complete, but works already quite well.</p>

<p>With DNode you can expose Node.js functions to be available on PHP, and PHP class methods to be available on Node.</p>

<p>Like most Node.js functionality, DNode works asynchronously. So instead of waiting for return values you supply a callback function that will be called when the method completes.</p>

<h2>PHP as client</h2>

<p>Here is a simple DNode service for Node.js:</p>

<pre><code>var dnode = require('dnode');
var server = dnode({
    zing: function (n, cb) { cb(n * 100) }
});
server.listen(7070);
</code></pre>

<p>This creates a DNode service running in TCP port 7070 that provides one method: <em>zing</em> that multiplies the value given to it by 100 and sends the result to the callback provided.</p>

<p>Calling this with PHP is easy:</p>

<pre><code>// Connect to DNode server running in port 7070 and call 
// Zing with argument 33
$dnode = new DNode\DNode();
$dnode-&gt;connect(7070, function($remote, $connection) {
    // Remote is a proxy object that provides us all methods
    // from the server
    $remote-&gt;zing(33, function($n) use ($connection) {
        echo "n = {$n}\n";
        // Once we have the result we can close the connection
        $connection-&gt;end();
    });
});
</code></pre>

<p>Now just start the server:</p>

<pre><code>$ node simple/server.js
</code></pre>

<p>And run the client. As you can see from the PHP code above, once we get the result the client will end the connection automatically:</p>

<pre><code>$ php examples/simple/client.php 
n = 3300
</code></pre>

<p>Because only simple TCP connections and JSON packets are used, this is quite fast. Here are time results for the client on my MacBook Air:</p>

<pre><code>real    0m0.064s
user    0m0.050s
sys     0m0.010s
</code></pre>

<h2>PHP as a server</h2>

<p>PHP can also act as a DNode server. You instantiate the DNode class and pass it the object you want to expose via DNode. All public methods of the object will be made available to the DNode clients:</p>

<pre><code>// This is the class we're exposing to DNode
class Zinger
{
    // Public methods are made available to the network
    public function zing($n, $cb)
    {
        // Dnode is async, so we return via callback
        $cb($n * 100);
    }
}

// Create a DNode server
$server = new DNode\DNode(new Zinger());
$server-&gt;listen(7070);
</code></pre>

<p>This DNode service will obviously be visible for both Node.js and PHP clients.</p>

<h2>Bidirectional communications</h2>

<p>A DNode client can also expose methods to the server. In this example the server provides functionality for converting temperatures from Celsius to Fahrenheit, but actually gets the current Celsius temperature by asking it from a client.</p>

<p>Server:</p>

<pre><code>// This is the class we're exposing to DNode
class Converter
{
    // Poll the client's own temperature() in celsius
    // and convert that value to fahrenheit in the supplied 
    // callback
    public function clientTempF($cb)
    {
        // The other side of DNode connection is exposed via
        // $this-&gt;remote proxy object
        $this-&gt;remote-&gt;temperature(function($degC) use ($cb) {
            $degF = round($degC * 9 / 5 + 32);
            $cb($degF);
        });
    }
}

// Create a DNode server that listens to port 6060
$server = new DNode\DNode(new Converter());
$server-&gt;listen(6060);
</code></pre>

<p>Client:</p>

<pre><code>// This is the class we're exposing to DNode
class Temp
{
    // Compute the client's temperature and stuff that value
    // into the callback
    public function temperature($cb)
    {
        $degC = rand(-20, 50);
        echo "{$degC}° C\n";
        $cb($degC);
    }
}

$dnode = new DNode\DNode(new Temp());
$dnode-&gt;connect(6060, function($remote, $connection) {
    // Ask server for temperature in Fahrenheit
    $remote-&gt;clientTempF(function($degF) use ($connection) {
        echo "{$degF}° F\n";
        // Close the connection
        $connection-&gt;end();
    });
});
</code></pre>

<p>Then just start the server:</p>

<pre><code>$ php examples/bidirectional/server.php
</code></pre>

<p>And run the client:</p>

<pre><code>$ php examples/bidirectional/client.php 
28° C
82° F
</code></pre>

<p>The same will obviously work with a Node.js client:</p>

<pre><code>$ node bidirectional/client.js 
23° C
73° F
</code></pre>

<h2>Installing DNode</h2>

<p>dnode-php can be installed using the <a href="http://packagist.org/">Composer</a> tool. You can either add <code>dnode/dnode</code> to your package dependencies, or if you want to install dnode-php as standalone, go to the main directory of its repository and run:</p>

<pre><code>$ wget http://getcomposer.org/composer.phar 
$ php composer.phar install
</code></pre>

<p>You can then use the composer-generated autoloader to access the DNode classes:</p>

<pre><code>require 'vendor/.composer/autoload.php';
</code></pre>

<p>Some DNode examples can be found from the <code>examples</code> folder. They are compatible with the similarly-named examples from <a href="https://github.com/substack/dnode">Node.js DNode</a>.</p>

<h2>Contributing</h2>

<p><a href="https://github.com/bergie/dnode-php">php-dnode</a> is developed under the MIT license in GitHub. If you're interested in it, please watch the repository and send issues or pull requests.</p>
]]></content>
        <summary type="html"><![CDATA[
<p>If you've been following my blog, you might have noticed that lately I've started doing quite a lot of <a href="http://nodejs.org/">Node.js</a> development alongside PHP. Based on conversations I've had in various conferences, I'm by far not alone in this situation - using Node.js for real-time functionality, and PHP (or Django, or Rails) for the more traditional CRUD stuff.</p>

<p>Both environments have their strong points. Node.js is very fast and flexible, but PHP has a lot more mature tools and libraries available. So in a lot of projects it is hard to choose between the two. But now you might not have to.</p>

<h2>Enter DNode</h2>

<p><a href="http://substack.net/posts/85e1bd/DNode-Asynchronous-Remote-Method-Invocation-for-Node-js-and-the-Browser">DNode</a> is a <em>remote method invocation</em> protocol originally written for Node.js, as the name probably tells. But as <a href="https://github.com/substack/dnode-protocol#readme">the protocol</a> itself is quite simple, just sending newline-terminated JSON packets over TCP connections, implementations have started popping up in other languages. You can talk DNode in <a href="https://github.com/substack/dnode-ruby">Ruby</a>, <a href="https://github.com/substack/dnode-perl">Perl</a>, <a href="https://github.com/jesusabdullah/dnode-python">Python</a>, <a href="https://github.com/aslakhellesoy/dnode-java">Java</a>, and now <a href="https://github.com/bergie/dnode-php">PHP</a>.</p>

<p>I started working on the PHP DNode implementation in the <a href="http://blog.liip.ch/archive/2011/09/30/symfony-cmf-hackday-october-22nd-in-cologne.html">Symfony CMF hackday</a> in Cologne a week ago, and got it into a running stage on a train ride from there to Paris. The implementation isn't yet complete, but works already quite well.</p>

<p>With DNode you can expose Node.js functions to be available on PHP, and PHP class methods to be available on Node.</p>

<p>Like most Node.js functionality, DNode works asynchronously. So instead of waiting for return values you supply a callback function that will be called when the method completes.</p>

<h2>PHP as client</h2>

<p>Here is a simple DNode service for Node.js:</p>

<pre><code>var dnode = require('dnode');
var server = dnode({
    zing: function (n, cb) { cb(n * 100) }
});
server.listen(7070);
</code></pre>

<p>This creates a DNode service running in TCP port 7070 that provides one method: <em>zing</em> that multiplies the value given to it by 100 and sends the result to the callback provided.</p>

<p>Calling this with PHP is easy:</p>

<pre><code>// Connect to DNode server running in port 7070 and call 
// Zing with argument 33
$dnode = new DNode\DNode();
$dnode-&gt;connect(7070, function($remote, $connection) {
    // Remote is a proxy object that provides us all methods
    // from the server
    $remote-&gt;zing(33, function($n) use ($connection) {
        echo "n = {$n}\n";
        // Once we have the result we can close the connection
        $connection-&gt;end();
    });
});
</code></pre>

<p>Now just start the server:</p>

<pre><code>$ node simple/server.js
</code></pre>

<p>And run the client. As you can see from the PHP code above, once we get the result the client will end the connection automatically:</p>

<pre><code>$ php examples/simple/client.php 
n = 3300
</code></pre>

<p>Because only simple TCP connections and JSON packets are used, this is quite fast. Here are time results for the client on my MacBook Air:</p>

<pre><code>real    0m0.064s
user    0m0.050s
sys     0m0.010s
</code></pre>

<h2>PHP as a server</h2>

<p>PHP can also act as a DNode server. You instantiate the DNode class and pass it the object you want to expose via DNode. All public methods of the object will be made available to the DNode clients:</p>

<pre><code>// This is the class we're exposing to DNode
class Zinger
{
    // Public methods are made available to the network
    public function zing($n, $cb)
    {
        // Dnode is async, so we return via callback
        $cb($n * 100);
    }
}

// Create a DNode server
$server = new DNode\DNode(new Zinger());
$server-&gt;listen(7070);
</code></pre>

<p>This DNode service will obviously be visible for both Node.js and PHP clients.</p>

<h2>Bidirectional communications</h2>

<p>A DNode client can also expose methods to the server. In this example the server provides functionality for converting temperatures from Celsius to Fahrenheit, but actually gets the current Celsius temperature by asking it from a client.</p>

<p>Server:</p>

<pre><code>// This is the class we're exposing to DNode
class Converter
{
    // Poll the client's own temperature() in celsius
    // and convert that value to fahrenheit in the supplied 
    // callback
    public function clientTempF($cb)
    {
        // The other side of DNode connection is exposed via
        // $this-&gt;remote proxy object
        $this-&gt;remote-&gt;temperature(function($degC) use ($cb) {
            $degF = round($degC * 9 / 5 + 32);
            $cb($degF);
        });
    }
}

// Create a DNode server that listens to port 6060
$server = new DNode\DNode(new Converter());
$server-&gt;listen(6060);
</code></pre>

<p>Client:</p>

<pre><code>// This is the class we're exposing to DNode
class Temp
{
    // Compute the client's temperature and stuff that value
    // into the callback
    public function temperature($cb)
    {
        $degC = rand(-20, 50);
        echo "{$degC}° C\n";
        $cb($degC);
    }
}

$dnode = new DNode\DNode(new Temp());
$dnode-&gt;connect(6060, function($remote, $connection) {
    // Ask server for temperature in Fahrenheit
    $remote-&gt;clientTempF(function($degF) use ($connection) {
        echo "{$degF}° F\n";
        // Close the connection
        $connection-&gt;end();
    });
});
</code></pre>

<p>Then just start the server:</p>

<pre><code>$ php examples/bidirectional/server.php
</code></pre>

<p>And run the client:</p>

<pre><code>$ php examples/bidirectional/client.php 
28° C
82° F
</code></pre>

<p>The same will obviously work with a Node.js client:</p>

<pre><code>$ node bidirectional/client.js 
23° C
73° F
</code></pre>

<h2>Installing DNode</h2>

<p>dnode-php can be installed using the <a href="http://packagist.org/">Composer</a> tool. You can either add <code>dnode/dnode</code> to your package dependencies, or if you want to install dnode-php as standalone, go to the main directory of its repository and run:</p>

<pre><code>$ wget http://getcomposer.org/composer.phar 
$ php composer.phar install
</code></pre>

<p>You can then use the composer-generated autoloader to access the DNode classes:</p>

<pre><code>require 'vendor/.composer/autoload.php';
</code></pre>

<p>Some DNode examples can be found from the <code>examples</code> folder. They are compatible with the similarly-named examples from <a href="https://github.com/substack/dnode">Node.js DNode</a>.</p>

<h2>Contributing</h2>

<p><a href="https://github.com/bergie/dnode-php">php-dnode</a> is developed under the MIT license in GitHub. If you're interested in it, please watch the repository and send issues or pull requests.</p>
]]></summary>
        <georss:point>60.1698 24.9382</georss:point>
    </entry>
    <entry>
        <title>Where is the future for openness in mobile?</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/where_is_the_future_for_openness_in_mobile/"/>
        <published>2011-10-03T17:53:42+00:00</published>
        <updated>2011-10-03T17:53:42+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e0ede8a212ffd8ede811e098785935b0ecf71ef71e</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="desktop" />
        <content type="html"><![CDATA[
<p>These are tough times for fans of open mobile environments. Android is <a href="http://www.zdnet.com/blog/google/google-android-30-honeycomb-open-source-no-more/2845">less and less open</a>, Symbian <a href="http://symbian.nokia.com/blog/2011/04/04/not-open-source-just-open-for-business/">was closed again</a>, HP <a href="http://www.wired.com/gadgetlab/2011/08/hp-webos-tablet-touchpad">stopped making webOS devices</a>, and now Intel <a href="https://meego.com/community/blogs/imad/2011/whats-next-meego">abandoned MeeGo</a> to work with Samsung and operators instead. So, what is the community to do?</p>
<p>One option is to follow the lead of the big companies, hoping that <a href="https://www.tizen.org/">Tizen</a> works, or that Google again sees the benefit of working with others in the open.</p>
<p>The other is to take the matters in our own hands. There is precedent for this. Much of early Linux activity came from the efforts of the community, not on the initiative of corporate interests. And there have been <a href="http://wiki.openmoko.org/wiki/Main_Page">OpenMoko</a> and <a href="http://wiki.maemo.org/Mer">Mer</a>, the latter an attempt to make a fully open version of Nokia's Maemo environment, suspended when <a href="http://mer-project.blogspot.com/2010/02/mer-project-just-bunch-of-redshirts.html">MeeGo promised to bring the same benefits</a>.</p>
<p>Well, now <a href="http://lists.meego.com/pipermail/meego-dev/2011-October/484215.html">Mer is back</a>.</p>
<p><img src="http://bergie.iki.fi/static/1/1e0ede7a7914e20ede711e09b9da90a21eb97ea97ea_mer-400.jpg" border="0" alt="mer-400.jpg" title="mer-400.jpg" /></p>
<p>The goals for <a href="http://www.merproject.org/">Mer</a> align pretty well with what the community would need:</p>
<ul><li>To be openly developed and openly governed as a meritocracy</li>
<li>That primary customers of the platform are device vendors - not end-users.</li>
<li>To provide a device manufacturer oriented structure, processes and tools: make life easy for them</li>
<li>To have a device oriented architecture</li>
<li>To be inclusive of technologies (such as MeeGo/Tizen/Qt/EFL/HTML5)</li>
<li>To innovate in the mobile OS space</li>
</ul><p>There have also been some other invitations to new potential homes for the community, ranging from <a href="http://blog.jospoortvliet.com/2011/09/meego-and-opensuse-invitation.html">openSUSE</a> to <a href="http://losca.blogspot.com/2011/10/from-meego-to-tizen-debian.html">Debian</a>.</p>
<p>It will be interesting to see how this works out. But whatever we as a community do, we should ensure we look at <a href="http://bergie.iki.fi/blog/open_source-free_software-what_we_need_is_open_projects/">more than just licensing</a>.</p>]]></content>
        <summary type="html"><![CDATA[
<p>These are tough times for fans of open mobile environments. Android is <a href="http://www.zdnet.com/blog/google/google-android-30-honeycomb-open-source-no-more/2845">less and less open</a>, Symbian <a href="http://symbian.nokia.com/blog/2011/04/04/not-open-source-just-open-for-business/">was closed again</a>, HP <a href="http://www.wired.com/gadgetlab/2011/08/hp-webos-tablet-touchpad">stopped making webOS devices</a>, and now Intel <a href="https://meego.com/community/blogs/imad/2011/whats-next-meego">abandoned MeeGo</a> to work with Samsung and operators instead. So, what is the community to do?</p>
<p>One option is to follow the lead of the big companies, hoping that <a href="https://www.tizen.org/">Tizen</a> works, or that Google again sees the benefit of working with others in the open.</p>
<p>The other is to take the matters in our own hands. There is precedent for this. Much of early Linux activity came from the efforts of the community, not on the initiative of corporate interests. And there have been <a href="http://wiki.openmoko.org/wiki/Main_Page">OpenMoko</a> and <a href="http://wiki.maemo.org/Mer">Mer</a>, the latter an attempt to make a fully open version of Nokia's Maemo environment, suspended when <a href="http://mer-project.blogspot.com/2010/02/mer-project-just-bunch-of-redshirts.html">MeeGo promised to bring the same benefits</a>.</p>
<p>Well, now <a href="http://lists.meego.com/pipermail/meego-dev/2011-October/484215.html">Mer is back</a>.</p>
<p><img src="http://bergie.iki.fi/static/1/1e0ede7a7914e20ede711e09b9da90a21eb97ea97ea_mer-400.jpg" border="0" alt="mer-400.jpg" title="mer-400.jpg" /></p>
<p>The goals for <a href="http://www.merproject.org/">Mer</a> align pretty well with what the community would need:</p>
<ul><li>To be openly developed and openly governed as a meritocracy</li>
<li>That primary customers of the platform are device vendors - not end-users.</li>
<li>To provide a device manufacturer oriented structure, processes and tools: make life easy for them</li>
<li>To have a device oriented architecture</li>
<li>To be inclusive of technologies (such as MeeGo/Tizen/Qt/EFL/HTML5)</li>
<li>To innovate in the mobile OS space</li>
</ul><p>There have also been some other invitations to new potential homes for the community, ranging from <a href="http://blog.jospoortvliet.com/2011/09/meego-and-opensuse-invitation.html">openSUSE</a> to <a href="http://losca.blogspot.com/2011/10/from-meego-to-tizen-debian.html">Debian</a>.</p>
<p>It will be interesting to see how this works out. But whatever we as a community do, we should ensure we look at <a href="http://bergie.iki.fi/blog/open_source-free_software-what_we_need_is_open_projects/">more than just licensing</a>.</p>]]></summary>
        <georss:point>60 24</georss:point>
    </entry>
    <entry>
        <title>Business analytics with CouchDB and NoFlo</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/business_analytics_with_couchdb_and_noflo/"/>
        <published>2011-09-21T17:52:53+00:00</published>
        <updated>2011-09-21T17:52:53+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e0e47a87c9e4f6e47a11e099aa3595f995ab22ab22</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="business" />
        <content type="html"><![CDATA[
<p>The purpose of <a href="http://37signals.com/svn/posts/3002-the-three-secrets-of-business-analytics-no-rocket-science-here">business analytics</a> is to find data from the company's information systems that can be used to support decision making. What customers buy most? What do they do before a buying decision? What are the signs that a customer may be leaving?</p>

<p>For the last month we've been working in Salzburg to build such a system, the <a href="http://www.iks-project.eu/resources/intelligent-project-controlling-tool">Intelligent Project Controlling Tool</a> needed for running large collaborative research projects like <a href="http://www.iks-project.eu/">IKS</a>. Since the design we went with can be reused for other business analytics needs, I wanted to write a bit about it.</p>

<p>But first, here is how our system looks like:</p>

<p><img src="http://bergie.iki.fi/midcom-serveattachmentguid-1e0e47ad96fbfcee47a11e08d46e7126c9836c236c2/proggis-iks-projectplan-500.png" alt="Proggis displaying IKS project plan" title="" /></p>

<h2>Where does the data come from?</h2>

<p>There are many ways to gather business data. Often the information systems already contain the data needed. But it may also be hidden in a jungle of spreadsheets. Or maybe some data is simply not available, and has to be filled in manually.</p>

<p>Handling all these cases in one system is a tricky question. To solve it, we went with a two-layered strategy:</p>

<ul><li>All data used for analytics is stored as <a href="http://en.wikipedia.org/wiki/Linked_Data">Linked Data</a> in a CouchDB system</li>
<li>NoFlo workflows are used for gathering data from the diverse sources and convert it to the format needed</li>
</ul><p>In IKS's case, much of the data was available in a series of spreadsheets. With these, we built the necessary workflows for first converting the spreadsheets into XML with <a href="http://tika.apache.org/">Apache Tika</a>, and then extracting the information from them in a sensible subset of JSON-LD.</p>

<p>Because IKS is a collaborative project, information needs to be gathered from a diverse group of partner organizations. Some of them have systems that provide the needed APIs (like <a href="http://basecamphq.com/">Basecamp</a>, which <a href="http://nemein.com/en/">we</a> use), and we can just periodically import the data. But with many we decided on a simple data interchange approach: spreadsheets handled over email.</p>

<p>In this approach, user files a data request into the system. This gets picked up by NoFlo, which sends an email with the appropriate spreadsheet template to the partner. Then it starts waiting for a reply. When a reply arrives, it extracts the data from the attached spreadsheet and imports it to the system.</p>

<p>Our NoFlo processes are mostly initiated by the <a href="http://guide.couchdb.org/draft/notifications.html">CouchDB change notification API</a>. We keep them running persistently using <a href="http://blog.nodejitsu.com/keep-a-nodejs-server-up-with-forever">forever Node</a>, so whenever some operation needs to be run it happens nearly immediately.</p>

<h2>Ensuring data consistency</h2>

<p>With any automation, and especially with the email-based data interchange, things can go wrong. Because of this we tag all data that we receive with its origin, whether it was some automated operation or an imported spreadsheet. These origins are called <em>execution documents</em>. Users can browse all completed workflow executions and see what data came in from them. These can then be either accepted or rejected.</p>

<p>This way if some partner accidentally sends faulty data, or something else breaks, the incorrect information received can be easily removed. CouchDB's versioning capabilities help here.</p>

<h2>Analyzing the data</h2>

<p>CouchDB is built on top of the concept of map/reduce. Here you can modify and combine the data in lots of different ways using <a href="http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views">simple JavaScript functions</a>. In our case we elected to write all our CouchDB code in CoffeeScript for simplicity. For example, here is the reduce function in CoffeeScript that counts totals of time planned, time used, and time left per task or partner in a project:</p>

<pre><code>(keys, values, rereduce) -&gt;
    roundNumber = (rnum, rlength) -&gt;
        Math.round(parseFloat(rnum) * Math.pow(10, rlength)) / Math.pow(10, rlength)
    data =
        planned: 0.0
        spent: 0.0
        left: 0.0

    if rereduce
        for reducedData in values
            data.planned += reducedData.planned
            data.spent += reducedData.spent
        data.left = data.planned - data.spent
        return data

    for doc in values
        if doc['@type'] is 'effortallocation'
            data.planned += roundNumber doc.value, 1
        if doc['@type'] is 'effort'
            data.spent += roundNumber doc.value, 1
    data.left = roundNumber data.planned - data.spent, 1
    return data
</code></pre>

<p>If you figure out a new way to look at the data you have, simply write the needed map and reduce functions and save them into the database. CouchDB will then run them against existing data and produce numbers.</p>

<h2>Data visualizations</h2>

<p>Numbers are good, but to really see the information buried in them you need some visualizations. For this we decided to follow the <a href="http://couchapp.org/page/what-is-couchapp">CouchApp</a> idea where the user interface code is stored in the database together with the data itself. This way no application servers are needed, and you can take the whole system with you just by <a href="http://guide.couchdb.org/draft/replication.html">replicating the database</a>. Think of the possibility of doing some analysis on your company while flying to a meeting!</p>

<p>The visuals are in our case provided by <a href="http://thejit.org/">JavaScript InfoVis Toolkit</a>, a nice, MIT-licensed interactive graph library.</p>

<p>CouchDB views handle the number crunching, then CouchDB <a href="http://guide.couchdb.org/draft/transforming.html">list functions</a> process the numbers into the format needed for visualization. This leaves only a minimal amount of work for the client side.</p>

<p>For consistency <a href="https://github.com/IKS/Proggis">our application</a> has been built with <a href="https://github.com/andrzejsliwa/coffeeapp">CoffeeApp</a>, so all the database and user interface code is in <a href="http://jashkenas.github.com/coffee-script/">CoffeeScript</a>.</p>

<h2>In a nutshell</h2>

<p>Any business analytics system dealing with moderate amounts of data can be built following this approach.</p>

<ul><li><a href="http://couchdb.apache.org/">Apache CouchDB</a> is the central data store</li>
<li>All data is stored as <a href="http://json-ld.org/">JSON-LD</a> entities</li>
<li><a href="https://github.com/bergie/noflo#readme">NoFlo</a> handles all data imports</li>
<li>Analytics based on the data are done with CouchDB map/reduce</li>
<li>Visualization happens with a CouchApp using <a href="http://thejit.org/">JavaScript InfoVis Toolkit</a></li>
</ul><p><img src="http://bergie.iki.fi/midcom-serveattachmentguid-1e0e47b247c04d2e47b11e08d46e7126c9836c236c2/proggis-architecture.png" alt="Simple architecture for a business analytics system" title="" /></p>

<p>This way you have a business analytics environment that is easy to extend with more data when it becomes available. New analysis can be done by writing reasonably simple map/reduce functions, and CouchDB's replication capabilities allow you to take the system and data with you.</p>

<p>Using JSON-LD for the data storage makes a lot of sense, as this way the relations between different pieces of information are easy to handle. And using URIs for data identifiers means you can easily mash up information coming from different sources together.</p>

<p>The two-layered approach of using NoFlo for data imports, and CouchDB for analysis also allows for clean separation of concerns. In our case, I did the workflow part of things, and <a href="https://github.com/szabyg">Szaby</a> built the visualizations.</p>
]]></content>
        <summary type="html"><![CDATA[
<p>The purpose of <a href="http://37signals.com/svn/posts/3002-the-three-secrets-of-business-analytics-no-rocket-science-here">business analytics</a> is to find data from the company's information systems that can be used to support decision making. What customers buy most? What do they do before a buying decision? What are the signs that a customer may be leaving?</p>

<p>For the last month we've been working in Salzburg to build such a system, the <a href="http://www.iks-project.eu/resources/intelligent-project-controlling-tool">Intelligent Project Controlling Tool</a> needed for running large collaborative research projects like <a href="http://www.iks-project.eu/">IKS</a>. Since the design we went with can be reused for other business analytics needs, I wanted to write a bit about it.</p>

<p>But first, here is how our system looks like:</p>

<p><img src="http://bergie.iki.fi/midcom-serveattachmentguid-1e0e47ad96fbfcee47a11e08d46e7126c9836c236c2/proggis-iks-projectplan-500.png" alt="Proggis displaying IKS project plan" title="" /></p>

<h2>Where does the data come from?</h2>

<p>There are many ways to gather business data. Often the information systems already contain the data needed. But it may also be hidden in a jungle of spreadsheets. Or maybe some data is simply not available, and has to be filled in manually.</p>

<p>Handling all these cases in one system is a tricky question. To solve it, we went with a two-layered strategy:</p>

<ul><li>All data used for analytics is stored as <a href="http://en.wikipedia.org/wiki/Linked_Data">Linked Data</a> in a CouchDB system</li>
<li>NoFlo workflows are used for gathering data from the diverse sources and convert it to the format needed</li>
</ul><p>In IKS's case, much of the data was available in a series of spreadsheets. With these, we built the necessary workflows for first converting the spreadsheets into XML with <a href="http://tika.apache.org/">Apache Tika</a>, and then extracting the information from them in a sensible subset of JSON-LD.</p>

<p>Because IKS is a collaborative project, information needs to be gathered from a diverse group of partner organizations. Some of them have systems that provide the needed APIs (like <a href="http://basecamphq.com/">Basecamp</a>, which <a href="http://nemein.com/en/">we</a> use), and we can just periodically import the data. But with many we decided on a simple data interchange approach: spreadsheets handled over email.</p>

<p>In this approach, user files a data request into the system. This gets picked up by NoFlo, which sends an email with the appropriate spreadsheet template to the partner. Then it starts waiting for a reply. When a reply arrives, it extracts the data from the attached spreadsheet and imports it to the system.</p>

<p>Our NoFlo processes are mostly initiated by the <a href="http://guide.couchdb.org/draft/notifications.html">CouchDB change notification API</a>. We keep them running persistently using <a href="http://blog.nodejitsu.com/keep-a-nodejs-server-up-with-forever">forever Node</a>, so whenever some operation needs to be run it happens nearly immediately.</p>

<h2>Ensuring data consistency</h2>

<p>With any automation, and especially with the email-based data interchange, things can go wrong. Because of this we tag all data that we receive with its origin, whether it was some automated operation or an imported spreadsheet. These origins are called <em>execution documents</em>. Users can browse all completed workflow executions and see what data came in from them. These can then be either accepted or rejected.</p>

<p>This way if some partner accidentally sends faulty data, or something else breaks, the incorrect information received can be easily removed. CouchDB's versioning capabilities help here.</p>

<h2>Analyzing the data</h2>

<p>CouchDB is built on top of the concept of map/reduce. Here you can modify and combine the data in lots of different ways using <a href="http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views">simple JavaScript functions</a>. In our case we elected to write all our CouchDB code in CoffeeScript for simplicity. For example, here is the reduce function in CoffeeScript that counts totals of time planned, time used, and time left per task or partner in a project:</p>

<pre><code>(keys, values, rereduce) -&gt;
    roundNumber = (rnum, rlength) -&gt;
        Math.round(parseFloat(rnum) * Math.pow(10, rlength)) / Math.pow(10, rlength)
    data =
        planned: 0.0
        spent: 0.0
        left: 0.0

    if rereduce
        for reducedData in values
            data.planned += reducedData.planned
            data.spent += reducedData.spent
        data.left = data.planned - data.spent
        return data

    for doc in values
        if doc['@type'] is 'effortallocation'
            data.planned += roundNumber doc.value, 1
        if doc['@type'] is 'effort'
            data.spent += roundNumber doc.value, 1
    data.left = roundNumber data.planned - data.spent, 1
    return data
</code></pre>

<p>If you figure out a new way to look at the data you have, simply write the needed map and reduce functions and save them into the database. CouchDB will then run them against existing data and produce numbers.</p>

<h2>Data visualizations</h2>

<p>Numbers are good, but to really see the information buried in them you need some visualizations. For this we decided to follow the <a href="http://couchapp.org/page/what-is-couchapp">CouchApp</a> idea where the user interface code is stored in the database together with the data itself. This way no application servers are needed, and you can take the whole system with you just by <a href="http://guide.couchdb.org/draft/replication.html">replicating the database</a>. Think of the possibility of doing some analysis on your company while flying to a meeting!</p>

<p>The visuals are in our case provided by <a href="http://thejit.org/">JavaScript InfoVis Toolkit</a>, a nice, MIT-licensed interactive graph library.</p>

<p>CouchDB views handle the number crunching, then CouchDB <a href="http://guide.couchdb.org/draft/transforming.html">list functions</a> process the numbers into the format needed for visualization. This leaves only a minimal amount of work for the client side.</p>

<p>For consistency <a href="https://github.com/IKS/Proggis">our application</a> has been built with <a href="https://github.com/andrzejsliwa/coffeeapp">CoffeeApp</a>, so all the database and user interface code is in <a href="http://jashkenas.github.com/coffee-script/">CoffeeScript</a>.</p>

<h2>In a nutshell</h2>

<p>Any business analytics system dealing with moderate amounts of data can be built following this approach.</p>

<ul><li><a href="http://couchdb.apache.org/">Apache CouchDB</a> is the central data store</li>
<li>All data is stored as <a href="http://json-ld.org/">JSON-LD</a> entities</li>
<li><a href="https://github.com/bergie/noflo#readme">NoFlo</a> handles all data imports</li>
<li>Analytics based on the data are done with CouchDB map/reduce</li>
<li>Visualization happens with a CouchApp using <a href="http://thejit.org/">JavaScript InfoVis Toolkit</a></li>
</ul><p><img src="http://bergie.iki.fi/midcom-serveattachmentguid-1e0e47b247c04d2e47b11e08d46e7126c9836c236c2/proggis-architecture.png" alt="Simple architecture for a business analytics system" title="" /></p>

<p>This way you have a business analytics environment that is easy to extend with more data when it becomes available. New analysis can be done by writing reasonably simple map/reduce functions, and CouchDB's replication capabilities allow you to take the system and data with you.</p>

<p>Using JSON-LD for the data storage makes a lot of sense, as this way the relations between different pieces of information are easy to handle. And using URIs for data identifiers means you can easily mash up information coming from different sources together.</p>

<p>The two-layered approach of using NoFlo for data imports, and CouchDB for analysis also allows for clean separation of concerns. In our case, I did the workflow part of things, and <a href="https://github.com/szabyg">Szaby</a> built the visualizations.</p>
]]></summary>
        <georss:point>47 13</georss:point>
    </entry>
    <entry>
        <title>VIE 2.0 is starting to emerge</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/vie_2-0_is_starting_to_emerge/"/>
        <published>2011-09-21T15:01:28+00:00</published>
        <updated>2011-09-21T15:01:28+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e0e462954fa70ee46211e091068b54f0dad597d597</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="midgard" />
        <content type="html"><![CDATA[
<p><a href="https://github.com/bergie/VIE#readme">VIE</a> is a JavaScript library that makes RDFa-annotated entities on web pages editable. We started the work towards the next major version of it, codenamed <a href="https://github.com/IKS/zart.js">Zart</a> (for Mozart) in a Salzburg IKS hackathon couple of weeks ago.</p>

<p><img src="https://github.com/bergie/VIE/raw/master/vie_logo_100.png" alt="VIE" title="" /></p>

<p>Yesterday I merged the Zart codebase into the <a href="https://github.com/bergie/VIE">VIE repository</a>. This blog post describes some of the improvements it brings.</p>

<h2>VIE now has an instance</h2>

<p>For VIE 1.x users the first visible change (and probably the only necessary API change) is that now VIE needs to be instantiated before being used. <a href="http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx">Singletons are evil</a>, and so we are not a singleton any longer.</p>

<p>So, for existing VIE code, you need to:</p>

<pre><code>var vie = new VIE();
// and then any traditional VIE calls, like:
var entities = vie.RDFaEntities.getInstances('div.article');
console.log("There are " + entities.length + " RDFa entities in your articles");
</code></pre>

<p>The VIE 1.0 API can be disabled by passing a setting when instantiating VIE:</p>

<pre><code>var vie = new VIE({classic: false});
</code></pre>

<h2>Services and VIE</h2>

<p>The other big change in VIE is that now the API has been built in a service-oriented manner. This means that for example reading and writing RDFa is just a service you can enable and disable at will.</p>

<p>The benefit here is that we can easily add support for other formats and capabilities without having to touch VIE internals. Thanks to the <a href="http://manu.sporny.org/2011/false-choice/">schema.org situation</a>, <a href="http://www.w3.org/TR/microdata/">Microdata</a> is getting more use, and so at some point we'll probably add a service for it.</p>

<p>Registering and accessing services is easy:</p>

<pre><code>// Instantiate VIE
var vie = new VIE();

// Pass the service instance and a name you want to use for it
vie.use(new vie.RdfaService, 'rdfa');

// Call a method from the service using the name
// this one would give us the RDF subject of the
// element matched by the jQuery selector
vie.service('rdfa').getElementSubject('div.article');
</code></pre>

<p>An immediate benefit here is that we can have two RDFa parsing implementations. If you have problems with our own custom jQuery-based RDFa parser, then you can use the more strict <a href="http://code.google.com/p/rdfquery/">rdfQuery</a> powered implementation instead:</p>

<pre><code>vie.use(new RdfaRdfQueryService, 'rdfa');
</code></pre>

<h2>Using deferreds</h2>

<p>For the new main VIE API we created a sort of a <a href="http://en.wikipedia.org/wiki/Domain-specific_language">Domain-Specific Language</a> for handling semantic entities. A core part of it is that now all operations utilize <a href="http://www.erichynds.com/jquery/using-deferreds-in-jquery/">jQuery's Deferred</a> objects. With them you can attach different callbacks to the results of your operation, and they will fire either when the operation completes, or immediately if the operation has already been run.</p>

<p>This gives a lot of flexibility in using the API, and allows us to provide same API for services that deal with the DOM, and services that talk to external APIs like <a href="http://incubator.apache.org/stanbol/">Stanbol</a>.</p>

<p>For example, parsing RDFa from a given DOM element (provided with a jQuery selector) happens like this:</p>

<pre><code>vie.load({
        element: 'div.article'
    }).
    from('rdfa').
    execute().
    done(function(entities) {
        console.log(entities);
    });
</code></pre>

<p>The chain here is: <em>operation</em> (in this case, load), <em>from service</em> (rdfa), <em>execute</em> operation, then when <em>done</em>, do <em>callback</em>.</p>

<p>With the RDFa service we register Backbone Views for the elements our entities came from, so just like with VIE 1.x, they will update automatically when you change the contents of your entities. But manual writing is also available in case you need it. Here is how it works:</p>

<pre><code>vie.save({
        element: 'div.article',
        entity: someBackboneModel
    }).
    to('rdfa').
    execute().
    done(function() {
        console.log("Saved!");
    });
</code></pre>

<p>In addition to <em>done</em>, which fires if the operation succeeds, you have <em>fail</em> for failed operations, and <em>then</em> which fires regardless of success or failure.</p>

<h2>Accessing external services</h2>

<p>The new VIE is not just about RDFa. In addition to working with the entities you have on a page, you can also access external repositories of semantic information, like <a href="http://dbpedia.org/About">DBpedia</a>.</p>

<p>For example, to find out everything that Wikipedia knows about Salzburg, you could run:</p>

<pre><code>vie.use(new vie.DBPediaService, 'dbpedia');
vie.load({
        entity: '&lt;http://dbpedia.org/resource/Salzburg&gt;'
    }).
    using('dbpedia').
    execute().
    done(function(entity) {
        console.log("This is what we know of Salzburg");
        console.log(entity);
    });
</code></pre>

<p>In browser usage these calls to external services are subject to cross-domain AJAX limitations. A way to work around those is to set up a proxy, and tell the DBpedia service to use that. To do this, pass the proxy URL to the service when instantiating:</p>

<pre><code>vie.use(new vie.DBPediaService({proxyUrl: 'http://localhost:8080'});
</code></pre>

<p>With this, all the factual information from Wikipedia will be at your disposal. The size of every city, the height of every mountain. Birthdates and places of birth for famous people. Your web app can do quite a bit with this information.</p>

<h3>Finding entities from text</h3>

<p><a href="http://incubator.apache.org/stanbol/">Apache Stanbol</a> is a semantic engine that can extract all kinds of entities from text documents. It can be used for auto-tagging and other things.</p>

<p>Here is how you can use it with VIE:</p>

<pre><code>vie.use(new vie.StanbolService, 'stanbol');
vie.analyze({
        element: 'div.article'
    }).
    using('stanbol').
    execute().
    done(function(entities) {
        console.log("We got the following enhancements for article content");
        console.log(entities);
    });
</code></pre>

<p>Stanbol can tell you what a piece of content talks about. People mentioned, places, concepts. It will also give you the language of the text.</p>

<h2>Moving forward</h2>

<p>The new version of VIE is still under heavy development. Most of the thngs work, but some details may still change. It is a good idea to start taking a look at it now, but before a beta release at least, <a href="https://github.com/bergie/VIE/tree/1.0.0">VIE 1.0</a> is the recommended tool to use.</p>

<p>If you already use VIE 1.0 for making your content editable, VIE 2.x will give you a lot of additional power. Enhancements, data queries, namespace handling, and much more.</p>

<p>Thanks to <a href="https://github.com/szabyg">Szaby</a> and <a href="https://github.com/neogermi">Sebastian</a> for helping to make this happen!</p>
]]></content>
        <summary type="html"><![CDATA[
<p><a href="https://github.com/bergie/VIE#readme">VIE</a> is a JavaScript library that makes RDFa-annotated entities on web pages editable. We started the work towards the next major version of it, codenamed <a href="https://github.com/IKS/zart.js">Zart</a> (for Mozart) in a Salzburg IKS hackathon couple of weeks ago.</p>

<p><img src="https://github.com/bergie/VIE/raw/master/vie_logo_100.png" alt="VIE" title="" /></p>

<p>Yesterday I merged the Zart codebase into the <a href="https://github.com/bergie/VIE">VIE repository</a>. This blog post describes some of the improvements it brings.</p>

<h2>VIE now has an instance</h2>

<p>For VIE 1.x users the first visible change (and probably the only necessary API change) is that now VIE needs to be instantiated before being used. <a href="http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx">Singletons are evil</a>, and so we are not a singleton any longer.</p>

<p>So, for existing VIE code, you need to:</p>

<pre><code>var vie = new VIE();
// and then any traditional VIE calls, like:
var entities = vie.RDFaEntities.getInstances('div.article');
console.log("There are " + entities.length + " RDFa entities in your articles");
</code></pre>

<p>The VIE 1.0 API can be disabled by passing a setting when instantiating VIE:</p>

<pre><code>var vie = new VIE({classic: false});
</code></pre>

<h2>Services and VIE</h2>

<p>The other big change in VIE is that now the API has been built in a service-oriented manner. This means that for example reading and writing RDFa is just a service you can enable and disable at will.</p>

<p>The benefit here is that we can easily add support for other formats and capabilities without having to touch VIE internals. Thanks to the <a href="http://manu.sporny.org/2011/false-choice/">schema.org situation</a>, <a href="http://www.w3.org/TR/microdata/">Microdata</a> is getting more use, and so at some point we'll probably add a service for it.</p>

<p>Registering and accessing services is easy:</p>

<pre><code>// Instantiate VIE
var vie = new VIE();

// Pass the service instance and a name you want to use for it
vie.use(new vie.RdfaService, 'rdfa');

// Call a method from the service using the name
// this one would give us the RDF subject of the
// element matched by the jQuery selector
vie.service('rdfa').getElementSubject('div.article');
</code></pre>

<p>An immediate benefit here is that we can have two RDFa parsing implementations. If you have problems with our own custom jQuery-based RDFa parser, then you can use the more strict <a href="http://code.google.com/p/rdfquery/">rdfQuery</a> powered implementation instead:</p>

<pre><code>vie.use(new RdfaRdfQueryService, 'rdfa');
</code></pre>

<h2>Using deferreds</h2>

<p>For the new main VIE API we created a sort of a <a href="http://en.wikipedia.org/wiki/Domain-specific_language">Domain-Specific Language</a> for handling semantic entities. A core part of it is that now all operations utilize <a href="http://www.erichynds.com/jquery/using-deferreds-in-jquery/">jQuery's Deferred</a> objects. With them you can attach different callbacks to the results of your operation, and they will fire either when the operation completes, or immediately if the operation has already been run.</p>

<p>This gives a lot of flexibility in using the API, and allows us to provide same API for services that deal with the DOM, and services that talk to external APIs like <a href="http://incubator.apache.org/stanbol/">Stanbol</a>.</p>

<p>For example, parsing RDFa from a given DOM element (provided with a jQuery selector) happens like this:</p>

<pre><code>vie.load({
        element: 'div.article'
    }).
    from('rdfa').
    execute().
    done(function(entities) {
        console.log(entities);
    });
</code></pre>

<p>The chain here is: <em>operation</em> (in this case, load), <em>from service</em> (rdfa), <em>execute</em> operation, then when <em>done</em>, do <em>callback</em>.</p>

<p>With the RDFa service we register Backbone Views for the elements our entities came from, so just like with VIE 1.x, they will update automatically when you change the contents of your entities. But manual writing is also available in case you need it. Here is how it works:</p>

<pre><code>vie.save({
        element: 'div.article',
        entity: someBackboneModel
    }).
    to('rdfa').
    execute().
    done(function() {
        console.log("Saved!");
    });
</code></pre>

<p>In addition to <em>done</em>, which fires if the operation succeeds, you have <em>fail</em> for failed operations, and <em>then</em> which fires regardless of success or failure.</p>

<h2>Accessing external services</h2>

<p>The new VIE is not just about RDFa. In addition to working with the entities you have on a page, you can also access external repositories of semantic information, like <a href="http://dbpedia.org/About">DBpedia</a>.</p>

<p>For example, to find out everything that Wikipedia knows about Salzburg, you could run:</p>

<pre><code>vie.use(new vie.DBPediaService, 'dbpedia');
vie.load({
        entity: '&lt;http://dbpedia.org/resource/Salzburg&gt;'
    }).
    using('dbpedia').
    execute().
    done(function(entity) {
        console.log("This is what we know of Salzburg");
        console.log(entity);
    });
</code></pre>

<p>In browser usage these calls to external services are subject to cross-domain AJAX limitations. A way to work around those is to set up a proxy, and tell the DBpedia service to use that. To do this, pass the proxy URL to the service when instantiating:</p>

<pre><code>vie.use(new vie.DBPediaService({proxyUrl: 'http://localhost:8080'});
</code></pre>

<p>With this, all the factual information from Wikipedia will be at your disposal. The size of every city, the height of every mountain. Birthdates and places of birth for famous people. Your web app can do quite a bit with this information.</p>

<h3>Finding entities from text</h3>

<p><a href="http://incubator.apache.org/stanbol/">Apache Stanbol</a> is a semantic engine that can extract all kinds of entities from text documents. It can be used for auto-tagging and other things.</p>

<p>Here is how you can use it with VIE:</p>

<pre><code>vie.use(new vie.StanbolService, 'stanbol');
vie.analyze({
        element: 'div.article'
    }).
    using('stanbol').
    execute().
    done(function(entities) {
        console.log("We got the following enhancements for article content");
        console.log(entities);
    });
</code></pre>

<p>Stanbol can tell you what a piece of content talks about. People mentioned, places, concepts. It will also give you the language of the text.</p>

<h2>Moving forward</h2>

<p>The new version of VIE is still under heavy development. Most of the thngs work, but some details may still change. It is a good idea to start taking a look at it now, but before a beta release at least, <a href="https://github.com/bergie/VIE/tree/1.0.0">VIE 1.0</a> is the recommended tool to use.</p>

<p>If you already use VIE 1.0 for making your content editable, VIE 2.x will give you a lot of additional power. Enhancements, data queries, namespace handling, and much more.</p>

<p>Thanks to <a href="https://github.com/szabyg">Szaby</a> and <a href="https://github.com/neogermi">Sebastian</a> for helping to make this happen!</p>
]]></summary>
        <georss:point>47 13</georss:point>
    </entry>
    <entry>
        <title>GObject Introspection is coming to Node.js</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/gobject_introspection_is_coming_to_node-js/"/>
        <published>2011-09-12T00:27:13+00:00</published>
        <updated>2011-09-12T00:27:13+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e0dcd5f5cffabedcd511e098e2996b57000c6e0c6e</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="desktop" />
        <content type="html"><![CDATA[
<p><a href="https://live.gnome.org/GObjectIntrospection">GObject Introspection</a> (GIR) is a way to create automatic bindings to <a href="http://developer.gnome.org/">GNOME libraries</a> for various different programming languages. I've written before about the <a href="http://bergie.iki.fi/blog/php_and_gobject_introspection/">benefits of bringing GIR to PHP</a>, and now it seems something similar is happening on <a href="http://nodejs.org/">Node.js</a>.</p>

<p><a href="https://github.com/creationix/node-gir">node-gir</a> has been written by <a href="https://github.com/creationix">Tim Caswell</a>, with help from <a href="https://github.com/swick">Sebastian Wick</a> and <a href="https://github.com/piotras">Piotr Pokora</a>.</p>

<p>I've been following the progress for a while, and today, during a flight from Helsinki to Salzburg, I was finally able to open a <a href="http://www.midgard-project.org/midgard2/">Midgard</a> repository connection with it. The API still is a bit weird, and lacks support for <a href="http://shinetech.com/thoughts/thought-articles/139-asynchronous-code-design-with-nodejs-">the asynchronous nature</a> of Node, but those will hopefully change soon. Quick example:</p>

<pre><code>var Midgard, gir, config, mgd;
gir = require("../gir");
gir.init();
Midgard = gir.load("Midgard");
Midgard.init();

// Use a local SQLite database file
config = new Midgard.Config();
config.__set_property__("dbdir", __dirname);
config.__set_property__("dbtype", "SQLite");
config.__set_property__("database", "midgard");

// Open connection to the database
mgd = new Midgard.Connection();
if (!mgd.__call__("open_config", config)) {
    console.error("Failed to open connection");
    process.exit();
}
</code></pre>

<p><a href="https://github.com/creationix/node-gir">node-gir is being developed on GitHub</a> if you want to lend a hand or try it out. To build it, run <code>npm install</code> and you should be able to run the <a href="https://github.com/swick/node-gir/tree/master/examples">code examples</a>.</p>

<p>Having GIR support for Node would make it a full-fledged GNOME environment, and mean that there would be proper GObject Introspection in all three major JavaScript runtimes - <a href="https://live.gnome.org/Gjs">SpiderMonkey</a>, <a href="https://live.gnome.org/Seed">JavaScriptCore</a> and <a href="https://github.com/creationix/node-gir">V8</a>. And this way GNOME JavaScript developers could also utilize the wealth of <a href="https://github.com/joyent/node/wiki/modules">existing Node.js modules</a>.</p>
]]></content>
        <summary type="html"><![CDATA[
<p><a href="https://live.gnome.org/GObjectIntrospection">GObject Introspection</a> (GIR) is a way to create automatic bindings to <a href="http://developer.gnome.org/">GNOME libraries</a> for various different programming languages. I've written before about the <a href="http://bergie.iki.fi/blog/php_and_gobject_introspection/">benefits of bringing GIR to PHP</a>, and now it seems something similar is happening on <a href="http://nodejs.org/">Node.js</a>.</p>

<p><a href="https://github.com/creationix/node-gir">node-gir</a> has been written by <a href="https://github.com/creationix">Tim Caswell</a>, with help from <a href="https://github.com/swick">Sebastian Wick</a> and <a href="https://github.com/piotras">Piotr Pokora</a>.</p>

<p>I've been following the progress for a while, and today, during a flight from Helsinki to Salzburg, I was finally able to open a <a href="http://www.midgard-project.org/midgard2/">Midgard</a> repository connection with it. The API still is a bit weird, and lacks support for <a href="http://shinetech.com/thoughts/thought-articles/139-asynchronous-code-design-with-nodejs-">the asynchronous nature</a> of Node, but those will hopefully change soon. Quick example:</p>

<pre><code>var Midgard, gir, config, mgd;
gir = require("../gir");
gir.init();
Midgard = gir.load("Midgard");
Midgard.init();

// Use a local SQLite database file
config = new Midgard.Config();
config.__set_property__("dbdir", __dirname);
config.__set_property__("dbtype", "SQLite");
config.__set_property__("database", "midgard");

// Open connection to the database
mgd = new Midgard.Connection();
if (!mgd.__call__("open_config", config)) {
    console.error("Failed to open connection");
    process.exit();
}
</code></pre>

<p><a href="https://github.com/creationix/node-gir">node-gir is being developed on GitHub</a> if you want to lend a hand or try it out. To build it, run <code>npm install</code> and you should be able to run the <a href="https://github.com/swick/node-gir/tree/master/examples">code examples</a>.</p>

<p>Having GIR support for Node would make it a full-fledged GNOME environment, and mean that there would be proper GObject Introspection in all three major JavaScript runtimes - <a href="https://live.gnome.org/Gjs">SpiderMonkey</a>, <a href="https://live.gnome.org/Seed">JavaScriptCore</a> and <a href="https://github.com/creationix/node-gir">V8</a>. And this way GNOME JavaScript developers could also utilize the wealth of <a href="https://github.com/joyent/node/wiki/modules">existing Node.js modules</a>.</p>
]]></summary>
        <georss:point>60.163898 24.9289</georss:point>
    </entry>
    <entry>
        <title>Embrace and extend</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/embrace_and_extend/"/>
        <published>2011-09-11T23:14:02+00:00</published>
        <updated>2011-09-11T23:14:02+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e0dccbbd08e7aedccb11e0a500e7540c8d14af14af</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="desktop" />
        <content type="html"><![CDATA[
<p>I'm getting worried about Google. Long one of the champions of <a href="http://www.mozilla.org/about/manifesto.en.html">the open web</a> alongside Mozilla, the rise of <a href="http://www.facebook.com/">social networking silos</a> and the <a href="http://www.apple.com/iphone/apps-for-iphone/">app economy</a> seem to have scared them. And like any scared organism, they lash out.</p>

<p>Many of their plans to make web competitive against native development environments are good, there is indeed much to improve in the stack. But what I'm uneasy with is the unilateral way they go about it, preferring "big reveals" and post-facto standardization instead of <a href="http://www.wired.com/wired/archive/3.10/ietf.html">the open conversation</a> that built most of the Internet we have today. This is not the way <a href="http://bergie.iki.fi/blog/on_cross-project_collaboration/">to collaborate</a>.</p>

<p>Consider some of their recent efforts:</p>

<ul><li><a href="http://www.chromium.org/spdy/spdy-whitepaper">SPDY</a>, a protocol to replace HTTP which Web is built on. Currently only supported by Chrome, which uses it to talk to several Google services</li>
<li><a href="http://www.2ality.com/2011/09/google-dart.html">Dart</a>, their JavaScript-killer which recently surfaced through a <a href="http://news.ycombinator.com/item?id=2980267">leaked email</a></li>
<li><a href="http://manu.sporny.org/2011/false-choice/">Microdata and Schema.org</a> that seek to replace last ten years of semantic web development with a spec cooked up by couple of big vendors in secret</li>
</ul><p>These - together with <a href="http://en.wikipedia.org/wiki/Web_SQL_Database">WebSQL</a>, <a href="http://code.google.com/p/nativeclient/wiki/NativeClientInGoogleChrome">NaCl</a>, <a href="http://www.webmproject.org/">WebM</a> and <a href="http://code.google.com/speed/webp/">WebP</a> - mean that Google has active efforts to replace practically every layer of the web (except HTML itself) with something of their own design.</p>

<p>The way all of these were introduced bears strong reminders of how Microsoft tried to <a href="http://en.wikipedia.org/wiki/Embrace,_extend_and_extinguish">embrace, extend, and extinguish</a> the web in late 90s. That period brought horrors like ActiveX and the awful, unkillable IE6. Though, for the sake of fairness, it also brought us XmlHttpRequest which was the enabler of the AJAX revolution.</p>

<p>Google's new technologies may end up being beneficial for web developers, but they also threaten to fragment the platform. After all, as the competition in the <a href="http://bergie.iki.fi/blog/why_the_tablet_form_factor_is_winning/">"post-PC"</a> space heats up, the competitors are unlikely to embrace Google's extensions of the web stack. That would be a loss to all.</p>

<p><a href="http://brendaneich.com/">Brendan Eich</a>, the original author of JavaScript <a href="http://news.ycombinator.com/item?id=2982949">comments on Hacker News</a>:</p>

<blockquote>
  <p>So "Works best in Chrome" and even "Works only in Chrome" are new norms promulgated intentionally by Google. We see more of this fragmentation every day. As a user of Chrome and Firefox (and Safari), I find it painful to experience, never mind the political bad taste.</p>
  
  <p>Ok, counter-arguments. What's wrong with playing hardball to advance the web, you say? As my blog tries to explain, the standards process requires good social relations and philosophical balance among the participating competitors.</p>
  
  <p>Google's approach with Dart is thus pretty much all wrong and doomed to leave Dart in excellent yet non-standardized and non-interoperable implementation status. Dart is GBScript to NaCl/Pepper's ActiveG.</p>
</blockquote>

<p><em>Disclaimer: I've been a long-time fan of many of Google's services, and have visited some of their offices a few times. I like the company. Which is exactly why I'm so concerned about this unilateral approach at standards. I am also involved in some standards processes through the IKS Project.</em></p>
]]></content>
        <summary type="html"><![CDATA[
<p>I'm getting worried about Google. Long one of the champions of <a href="http://www.mozilla.org/about/manifesto.en.html">the open web</a> alongside Mozilla, the rise of <a href="http://www.facebook.com/">social networking silos</a> and the <a href="http://www.apple.com/iphone/apps-for-iphone/">app economy</a> seem to have scared them. And like any scared organism, they lash out.</p>

<p>Many of their plans to make web competitive against native development environments are good, there is indeed much to improve in the stack. But what I'm uneasy with is the unilateral way they go about it, preferring "big reveals" and post-facto standardization instead of <a href="http://www.wired.com/wired/archive/3.10/ietf.html">the open conversation</a> that built most of the Internet we have today. This is not the way <a href="http://bergie.iki.fi/blog/on_cross-project_collaboration/">to collaborate</a>.</p>

<p>Consider some of their recent efforts:</p>

<ul><li><a href="http://www.chromium.org/spdy/spdy-whitepaper">SPDY</a>, a protocol to replace HTTP which Web is built on. Currently only supported by Chrome, which uses it to talk to several Google services</li>
<li><a href="http://www.2ality.com/2011/09/google-dart.html">Dart</a>, their JavaScript-killer which recently surfaced through a <a href="http://news.ycombinator.com/item?id=2980267">leaked email</a></li>
<li><a href="http://manu.sporny.org/2011/false-choice/">Microdata and Schema.org</a> that seek to replace last ten years of semantic web development with a spec cooked up by couple of big vendors in secret</li>
</ul><p>These - together with <a href="http://en.wikipedia.org/wiki/Web_SQL_Database">WebSQL</a>, <a href="http://code.google.com/p/nativeclient/wiki/NativeClientInGoogleChrome">NaCl</a>, <a href="http://www.webmproject.org/">WebM</a> and <a href="http://code.google.com/speed/webp/">WebP</a> - mean that Google has active efforts to replace practically every layer of the web (except HTML itself) with something of their own design.</p>

<p>The way all of these were introduced bears strong reminders of how Microsoft tried to <a href="http://en.wikipedia.org/wiki/Embrace,_extend_and_extinguish">embrace, extend, and extinguish</a> the web in late 90s. That period brought horrors like ActiveX and the awful, unkillable IE6. Though, for the sake of fairness, it also brought us XmlHttpRequest which was the enabler of the AJAX revolution.</p>

<p>Google's new technologies may end up being beneficial for web developers, but they also threaten to fragment the platform. After all, as the competition in the <a href="http://bergie.iki.fi/blog/why_the_tablet_form_factor_is_winning/">"post-PC"</a> space heats up, the competitors are unlikely to embrace Google's extensions of the web stack. That would be a loss to all.</p>

<p><a href="http://brendaneich.com/">Brendan Eich</a>, the original author of JavaScript <a href="http://news.ycombinator.com/item?id=2982949">comments on Hacker News</a>:</p>

<blockquote>
  <p>So "Works best in Chrome" and even "Works only in Chrome" are new norms promulgated intentionally by Google. We see more of this fragmentation every day. As a user of Chrome and Firefox (and Safari), I find it painful to experience, never mind the political bad taste.</p>
  
  <p>Ok, counter-arguments. What's wrong with playing hardball to advance the web, you say? As my blog tries to explain, the standards process requires good social relations and philosophical balance among the participating competitors.</p>
  
  <p>Google's approach with Dart is thus pretty much all wrong and doomed to leave Dart in excellent yet non-standardized and non-interoperable implementation status. Dart is GBScript to NaCl/Pepper's ActiveG.</p>
</blockquote>

<p><em>Disclaimer: I've been a long-time fan of many of Google's services, and have visited some of their offices a few times. I like the company. Which is exactly why I'm so concerned about this unilateral approach at standards. I am also involved in some standards processes through the IKS Project.</em></p>
]]></summary>
        <georss:point>60.163898 24.9289</georss:point>
    </entry>
    <entry>
        <title>Why the tablet form factor is winning</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/why_the_tablet_form_factor_is_winning/"/>
        <published>2011-09-05T15:30:31+00:00</published>
        <updated>2011-09-05T15:30:31+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e0d7d3fd72dc0cd7d311e0943acb88fa4c7a467a46</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="desktop" />
        <content type="html"><![CDATA[
<p>The press is writing a lot about a "post-PC ecosystem" these days, and while many dismiss tablets as simple toys, I think the world of computing is undergoing a major shift. Tablets may not be good for writing, but they are good, probably better than PCs for a lot of other things. And it turns out, people want to be doing these other things.</p>
<p>MG Siegler from TechCrunch has <a href="http://techcrunch.com/2011/09/02/post-pc-has-nothing-to-do-with-windows/">a great post on the subject</a>:</p>
<blockquote>
<p>...I’ve been trained over time to think that the traditional PC is the way to do these things whether it’s for work or play. That’s simply not true. The tablet form factor is so. much. better. when you don’t have to do an excessive amount of typing. And during downtime, when I use a computer like a more regular human being, I’ve found that’s often...</p>
<p>Computing is changing. That’s just about the most obvious statement ever. We’ve been seeing this for years with the rise of the smartphones. But <em>traditional</em> computing is changing as well. As in, people are abandoning PCs for these newer devices. And this will keep happening.</p>
</blockquote>
<p>My experience conforms with this. I rarely use my laptop outside of the work context of <em>writing code</em>, instead preferring to use the tablet with its great ergonomics, portability and long battery life. On some of my previous trips I noticed that already more than half of people sitting in airport lounges use a tablet instead of a laptop. Not bad for a product category that has existed in a mainstream manner for less than two years. <a href="http://bergie.iki.fi/blog/the_universal_communicator/">Nokia's internet tablets</a> blazed the trail years earlier, but were never marketed outside the geekdom.</p>
<p>Now, much of the attention in the tablet world has been focused on the couple of platforms that are winning in popularity, and therefore have most of the apps. But regardless of how well Apple and Google play their cards, <a href="http://www.asymco.com/2011/07/06/the-post-pc-era-will-be-a-multi-platform-era/">the post-PC world will be a multiplatform one</a>.</p>
<p>About a week after I got my webOS-powered TouchPad, HP went and <a href="http://www.wired.com/gadgetlab/2011/08/hp-webos-tablet-touchpad">killed the product</a>. Yet this hasn't made the device useless. As <a href="http://paulrouget.com/e/mobilewebapps/">Paul Rouget recently found out</a>, <em>as long as you have a good browser, your device will be relevant</em>.</p>
<blockquote>
<p>Some people can't or don't want to use Native Apps. Because their phones don't have Apps, or because there is just no good Apps for what they want to do, or because, well, because they don't need to...</p>
<p>While in the Western world we were looking at Apple bringing pretty Apps in an expensive device, in the Eastern world, Opera was bringing a working web browser to all the existing devices.</p>
</blockquote>
<p>This is the big opportunity for free software to remain relevant in an environment of highly-locked devices. Much of the web already runs on free components, and by using the web as <a href="http://bergie.iki.fi/blog/the_universal_runtime/">a universal runtime</a> we can bypass almost any platform restrictions. <a href="http://www.paulgraham.com/road.html">As Paul Graham wrote</a> back in 2001, <em>no one can break web applications without breaking browsing</em>.</p>
<p>The world of publishing is starting to understand this. Their revenue models can't take the heavy control that vendors like Apple imposes, and so <a href="https://read.amazon.com/about">Amazon's Kindle</a> is a web app, and <a href="http://apps.ft.com/ftwebapp/">so is Financial Times</a>. That<em> "Next year HTML5 will replace native apps" is the new "Next year will be the year of Linux on the desktop"</em> is <a href="https://twitter.com/jonlech/status/110598881049452545">already a Twitter joke</a>, but there is certainly some movement in this direction. And interestingly, the Linux desktop is actually <a href="http://blogs.gnome.org/xan/2011/08/31/web-application-mode-in-gnome-3-2/">becoming more web-savvy</a> and <a href="http://www.jonnor.com/2011/04/introducing-maliit-on-screen-keyboard-in-gnome-3/">touch-friendly</a>.</p>
<p>There are clearly sweet spots for something to be a web app, or for it to be a native application. Similarly, there are different situations where tablets will be the appropriate tool, and where PCs are. The tablet context will be more like this:</p>
<p><img src="http://bergie.iki.fi/static/1/1e0d7d53922345ed7d511e0af7669d1946e55d455d4_tablet-breakfast.jpg" border="0" alt="tablet-breakfast.jpg" title="tablet-breakfast.jpg" /></p>
<p>Than this:</p>
<p><img src="http://bergie.iki.fi/static/1/1e0d7d2eeae653ed7d211e0ad084b49cc799d7c9d7c_ipad-workstation.jpg" border="0" alt="ipad-workstation.jpg" title="ipad-workstation.jpg" /></p>
<p>The heavy lifting is a better fit for a system designed for that. As Steve Jobs said, <a href="http://lirneasia.net/2010/06/the-pc-is-a-truck-steve-jobs/">the PC will be the truck</a>.</p>]]></content>
        <summary type="html"><![CDATA[
<p>The press is writing a lot about a "post-PC ecosystem" these days, and while many dismiss tablets as simple toys, I think the world of computing is undergoing a major shift. Tablets may not be good for writing, but they are good, probably better than PCs for a lot of other things. And it turns out, people want to be doing these other things.</p>
<p>MG Siegler from TechCrunch has <a href="http://techcrunch.com/2011/09/02/post-pc-has-nothing-to-do-with-windows/">a great post on the subject</a>:</p>
<blockquote>
<p>...I’ve been trained over time to think that the traditional PC is the way to do these things whether it’s for work or play. That’s simply not true. The tablet form factor is so. much. better. when you don’t have to do an excessive amount of typing. And during downtime, when I use a computer like a more regular human being, I’ve found that’s often...</p>
<p>Computing is changing. That’s just about the most obvious statement ever. We’ve been seeing this for years with the rise of the smartphones. But <em>traditional</em> computing is changing as well. As in, people are abandoning PCs for these newer devices. And this will keep happening.</p>
</blockquote>
<p>My experience conforms with this. I rarely use my laptop outside of the work context of <em>writing code</em>, instead preferring to use the tablet with its great ergonomics, portability and long battery life. On some of my previous trips I noticed that already more than half of people sitting in airport lounges use a tablet instead of a laptop. Not bad for a product category that has existed in a mainstream manner for less than two years. <a href="http://bergie.iki.fi/blog/the_universal_communicator/">Nokia's internet tablets</a> blazed the trail years earlier, but were never marketed outside the geekdom.</p>
<p>Now, much of the attention in the tablet world has been focused on the couple of platforms that are winning in popularity, and therefore have most of the apps. But regardless of how well Apple and Google play their cards, <a href="http://www.asymco.com/2011/07/06/the-post-pc-era-will-be-a-multi-platform-era/">the post-PC world will be a multiplatform one</a>.</p>
<p>About a week after I got my webOS-powered TouchPad, HP went and <a href="http://www.wired.com/gadgetlab/2011/08/hp-webos-tablet-touchpad">killed the product</a>. Yet this hasn't made the device useless. As <a href="http://paulrouget.com/e/mobilewebapps/">Paul Rouget recently found out</a>, <em>as long as you have a good browser, your device will be relevant</em>.</p>
<blockquote>
<p>Some people can't or don't want to use Native Apps. Because their phones don't have Apps, or because there is just no good Apps for what they want to do, or because, well, because they don't need to...</p>
<p>While in the Western world we were looking at Apple bringing pretty Apps in an expensive device, in the Eastern world, Opera was bringing a working web browser to all the existing devices.</p>
</blockquote>
<p>This is the big opportunity for free software to remain relevant in an environment of highly-locked devices. Much of the web already runs on free components, and by using the web as <a href="http://bergie.iki.fi/blog/the_universal_runtime/">a universal runtime</a> we can bypass almost any platform restrictions. <a href="http://www.paulgraham.com/road.html">As Paul Graham wrote</a> back in 2001, <em>no one can break web applications without breaking browsing</em>.</p>
<p>The world of publishing is starting to understand this. Their revenue models can't take the heavy control that vendors like Apple imposes, and so <a href="https://read.amazon.com/about">Amazon's Kindle</a> is a web app, and <a href="http://apps.ft.com/ftwebapp/">so is Financial Times</a>. That<em> "Next year HTML5 will replace native apps" is the new "Next year will be the year of Linux on the desktop"</em> is <a href="https://twitter.com/jonlech/status/110598881049452545">already a Twitter joke</a>, but there is certainly some movement in this direction. And interestingly, the Linux desktop is actually <a href="http://blogs.gnome.org/xan/2011/08/31/web-application-mode-in-gnome-3-2/">becoming more web-savvy</a> and <a href="http://www.jonnor.com/2011/04/introducing-maliit-on-screen-keyboard-in-gnome-3/">touch-friendly</a>.</p>
<p>There are clearly sweet spots for something to be a web app, or for it to be a native application. Similarly, there are different situations where tablets will be the appropriate tool, and where PCs are. The tablet context will be more like this:</p>
<p><img src="http://bergie.iki.fi/static/1/1e0d7d53922345ed7d511e0af7669d1946e55d455d4_tablet-breakfast.jpg" border="0" alt="tablet-breakfast.jpg" title="tablet-breakfast.jpg" /></p>
<p>Than this:</p>
<p><img src="http://bergie.iki.fi/static/1/1e0d7d2eeae653ed7d211e0ad084b49cc799d7c9d7c_ipad-workstation.jpg" border="0" alt="ipad-workstation.jpg" title="ipad-workstation.jpg" /></p>
<p>The heavy lifting is a better fit for a system designed for that. As Steve Jobs said, <a href="http://lirneasia.net/2010/06/the-pc-is-a-truck-steve-jobs/">the PC will be the truck</a>.</p>]]></summary>
        <georss:point>47 13</georss:point>
    </entry>
    <entry>
        <title>Nemein and Infigo merge to create a digital agency focused on web and mobile</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/nemein_and_infigo_merge/"/>
        <published>2011-09-02T11:15:37+00:00</published>
        <updated>2011-09-02T11:15:37+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e0d554e2c051e0d55411e0807513cb0e9005fb05fb</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="business" />
        <content type="html"><![CDATA[
<p>Yesterday the contracts were signed to acquire <a href="http://infigo.fi/en/">Infigo</a> as part of <a href="http://nemein.com/en/">Nemein</a>. Infigo, is a consulting company focused on mobile development and web using open source tools. You'll probably at least know their CTO, <a href="http://bergie.iki.fi/blog/on_usb_fingers_and_world_news/">Jerry of the USB finger fame</a>.</p>
<p>Even in the <a href="http://bergie.iki.fi/blog/ten_years_of_nemein/">ten years of history</a> of our company this is quite a significant move - it allows us to combine Nemein's traditional expertise on content management with Infigo's mobile offerings. As smartphones and tablets are becoming popular, more and more services we build will have a mobile element, which is now easier with lots of in-house expertise.</p>
<p>This also means more focus on the interplay between the <a href="http://www.midgard-project.org/">Midgard</a> content repository, <a href="https://github.com/bergie/noflo">NoFlo</a> workflows, <a href="http://nodejs.org/">Node.js</a> and <a href="http://symfony.com/">Symfony</a> web services, and mobile applications built in <a href="http://qt.nokia.com/">Qt</a>.</p>
<p><img src="http://bergie.iki.fi/static/1/1e0d55317b0f154d55311e0a7e177ab46dbbff1bff1_nemein-infigo.jpg" border="0" alt="nemein-infigo.jpg" title="nemein-infigo.jpg" /></p>
<p><a href="http://infigo.fi/en/page/company/team">Petri Rajahalme</a> (with me in the photo) will be the CEO of the merged company, and I will focus on leading the R&amp;D efforts.</p>]]></content>
        <summary type="html"><![CDATA[
<p>Yesterday the contracts were signed to acquire <a href="http://infigo.fi/en/">Infigo</a> as part of <a href="http://nemein.com/en/">Nemein</a>. Infigo, is a consulting company focused on mobile development and web using open source tools. You'll probably at least know their CTO, <a href="http://bergie.iki.fi/blog/on_usb_fingers_and_world_news/">Jerry of the USB finger fame</a>.</p>
<p>Even in the <a href="http://bergie.iki.fi/blog/ten_years_of_nemein/">ten years of history</a> of our company this is quite a significant move - it allows us to combine Nemein's traditional expertise on content management with Infigo's mobile offerings. As smartphones and tablets are becoming popular, more and more services we build will have a mobile element, which is now easier with lots of in-house expertise.</p>
<p>This also means more focus on the interplay between the <a href="http://www.midgard-project.org/">Midgard</a> content repository, <a href="https://github.com/bergie/noflo">NoFlo</a> workflows, <a href="http://nodejs.org/">Node.js</a> and <a href="http://symfony.com/">Symfony</a> web services, and mobile applications built in <a href="http://qt.nokia.com/">Qt</a>.</p>
<p><img src="http://bergie.iki.fi/static/1/1e0d55317b0f154d55311e0a7e177ab46dbbff1bff1_nemein-infigo.jpg" border="0" alt="nemein-infigo.jpg" title="nemein-infigo.jpg" /></p>
<p><a href="http://infigo.fi/en/page/company/team">Petri Rajahalme</a> (with me in the photo) will be the CEO of the merged company, and I will focus on leading the R&amp;D efforts.</p>]]></summary>
        <georss:point>47 13</georss:point>
    </entry>
    <entry>
        <title>Flow-based programming for PHP</title>
        <link rel="alternate" type="text/html" href="http://bergie.iki.fi/blog/flow-based_programming_for_php/"/>
        <published>2011-08-18T13:07:34+00:00</published>
        <updated>2011-08-18T13:07:34+00:00</updated>
        <id>http://bergie.iki.fi/midcom-permalink-1e0c99b09aec9b4c99b11e0af65a93f4d4c58225822</id>
        <author>
            <name>henri.bergius@iki.fi (Henri Bergius)</name>
        </author>
        <category  term="midgard" />
        <content type="html"><![CDATA[
<p>You may have seen my earlier <a href="http://bergie.iki.fi/blog/desktop_summit_flow-based_programming/">post about NoFlo</a>, the <a href="http://en.wikipedia.org/wiki/Flow-based_programming">flow-based programming</a> tool I've written for Node.js. It allows you to do quite cool stuff, like <a href="http://universalruntime.tumblr.com/post/8998693776/node-js-powered-web-server-written-with-the-noflo">a visually controlled web server</a>:</p>

<p><img src="http://27.media.tumblr.com/tumblr_lq12x0Sf481qies3uo1_500.png" alt="NoFlo-powered web server" title="" /></p>

<p>Yesterday Igor Wiedler published <a href="https://github.com/igorw/Evenement">Evenement</a>, a PHP port of the EventEmitter class from Node.js. As <a href="https://github.com/bergie/noflo">NoFlo</a> builds quite heavily on EventEmitter, I decided to see how far the PHP port could be taken.</p>

<p>As result, there is now <a href="https://github.com/bergie/phpflo">PhpFlo</a>, a flow-based programming environment for PHP.</p>

<p>Example of how to define and run a flow (you can also use <a href="https://github.com/bergie/phpflo/blob/master/examples/linecount/count.json">a JSON format</a> for this):</p>

<pre><code>// Add nodes to the graph
$graph = new PhpFlo\Graph("linecount");
$graph-&gt;addNode("Read File", "ReadFile");
$graph-&gt;addNode("Split by Lines", "SplitStr");
$graph-&gt;addNode("Count Lines", "Counter");
$graph-&gt;addNode("Display", "Output");

// Add connections between nodes
$graph-&gt;addEdge("Read File", "out", "Split by Lines", "in");
$graph-&gt;addEdge("Read File", "error", "Display", "in");
$graph-&gt;addEdge("Split by Lines", "out", "Count Lines", "in");
$graph-&gt;addEdge("Count Lines", "count", "Display", "in");

// Kick-start the process by sending filename to Read File
$graph-&gt;addInitial($fileName, "Read File", "source");

// Make the graph "live"
$network = PhpFlo\Network::create($graph);
</code></pre>

<p>The flow consists of processes, or instances simple "black box" components that have their own defined input and output ports. Program logic is defined by making connections between them. Here is a simple component that reads the contents of a file:</p>

<pre><code>namespace PhpFlo\Component;
use PhpFlo\Component;
use PhpFlo\Port;
class ReadFile extends Component
{
    public function __construct()
    {
        $this-&gt;inPorts['source'] = new Port();
        $this-&gt;outPorts['out'] = new Port();
        $this-&gt;outPorts['error'] = new Port();

        $this-&gt;inPorts['source']-&gt;on('data', array($this, 'readFile'));
    }

    public function readFile($data)
    {
        if (!file_exists($data)) {
            $this-&gt;outPorts['error']-&gt;send("File {$data} doesn't exist");
            return;
        }

        $this-&gt;outPorts['out']-&gt;send(file_get_contents($data));
        $this-&gt;outPorts['out']-&gt;disconnect();
    }
}
</code></pre>

<p>I hope people find this system useful. If you're interested in FBP, then <a href="http://www.jpaulmorrison.com/fbp/#More">J. Paul Morrison's book</a> is a good place to start.</p>

<p>And if you're in <a href="http://froscon.de/">FrOSCon</a>, feel free to come and chat with me :-)</p>
]]></content>
        <summary type="html"><![CDATA[
<p>You may have seen my earlier <a href="http://bergie.iki.fi/blog/desktop_summit_flow-based_programming/">post about NoFlo</a>, the <a href="http://en.wikipedia.org/wiki/Flow-based_programming">flow-based programming</a> tool I've written for Node.js. It allows you to do quite cool stuff, like <a href="http://universalruntime.tumblr.com/post/8998693776/node-js-powered-web-server-written-with-the-noflo">a visually controlled web server</a>:</p>

<p><img src="http://27.media.tumblr.com/tumblr_lq12x0Sf481qies3uo1_500.png" alt="NoFlo-powered web server" title="" /></p>

<p>Yesterday Igor Wiedler published <a href="https://github.com/igorw/Evenement">Evenement</a>, a PHP port of the EventEmitter class from Node.js. As <a href="https://github.com/bergie/noflo">NoFlo</a> builds quite heavily on EventEmitter, I decided to see how far the PHP port could be taken.</p>

<p>As result, there is now <a href="https://github.com/bergie/phpflo">PhpFlo</a>, a flow-based programming environment for PHP.</p>

<p>Example of how to define and run a flow (you can also use <a href="https://github.com/bergie/phpflo/blob/master/examples/linecount/count.json">a JSON format</a> for this):</p>

<pre><code>// Add nodes to the graph
$graph = new PhpFlo\Graph("linecount");
$graph-&gt;addNode("Read File", "ReadFile");
$graph-&gt;addNode("Split by Lines", "SplitStr");
$graph-&gt;addNode("Count Lines", "Counter");
$graph-&gt;addNode("Display", "Output");

// Add connections between nodes
$graph-&gt;addEdge("Read File", "out", "Split by Lines", "in");
$graph-&gt;addEdge("Read File", "error", "Display", "in");
$graph-&gt;addEdge("Split by Lines", "out", "Count Lines", "in");
$graph-&gt;addEdge("Count Lines", "count", "Display", "in");

// Kick-start the process by sending filename to Read File
$graph-&gt;addInitial($fileName, "Read File", "source");

// Make the graph "live"
$network = PhpFlo\Network::create($graph);
</code></pre>

<p>The flow consists of processes, or instances simple "black box" components that have their own defined input and output ports. Program logic is defined by making connections between them. Here is a simple component that reads the contents of a file:</p>

<pre><code>namespace PhpFlo\Component;
use PhpFlo\Component;
use PhpFlo\Port;
class ReadFile extends Component
{
    public function __construct()
    {
        $this-&gt;inPorts['source'] = new Port();
        $this-&gt;outPorts['out'] = new Port();
        $this-&gt;outPorts['error'] = new Port();

        $this-&gt;inPorts['source']-&gt;on('data', array($this, 'readFile'));
    }

    public function readFile($data)
    {
        if (!file_exists($data)) {
            $this-&gt;outPorts['error']-&gt;send("File {$data} doesn't exist");
            return;
        }

        $this-&gt;outPorts['out']-&gt;send(file_get_contents($data));
        $this-&gt;outPorts['out']-&gt;disconnect();
    }
}
</code></pre>

<p>I hope people find this system useful. If you're interested in FBP, then <a href="http://www.jpaulmorrison.com/fbp/#More">J. Paul Morrison's book</a> is a good place to start.</p>

<p>And if you're in <a href="http://froscon.de/">FrOSCon</a>, feel free to come and chat with me :-)</p>
]]></summary>
        <georss:point>60 24</georss:point>
    </entry>
</feed>

