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

<channel>
	<title>Sébastien Barbieri's blog</title>
	<atom:link href="http://blog.sbw.be/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.sbw.be</link>
	<description>My life, my work, my projects</description>
	<lastBuildDate>Sat, 24 Dec 2011 00:12:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Bière Ommegang</title>
		<link>http://blog.sbw.be/2011/12/24/biere-ommegang/</link>
		<comments>http://blog.sbw.be/2011/12/24/biere-ommegang/#comments</comments>
		<pubDate>Sat, 24 Dec 2011 00:12:13 +0000</pubDate>
		<dc:creator>Sébastien Barbieri</dc:creator>
				<category><![CDATA[cuisine]]></category>
		<category><![CDATA[biere]]></category>
		<category><![CDATA[ommegang]]></category>

		<guid isPermaLink="false">http://blog.sbw.be/?p=518</guid>
		<description><![CDATA[Au début je n&#8217;y ai cru qu&#8217;a moitié. Puis j&#8217;ai oublié&#8230; Il y a quelques jours j&#8217;ai reçu un mail pour me dire que le brassin était pret et que dès que l&#8217;embouteillage aurait lieu, la bouteille serait envoyée. Là je me suis dit: &#8220;ça doit être une erreur, ils ont envoyé un mail à [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://lh3.googleusercontent.com/-7nJ9gGceZkM/TvUWi7KqUDI/AAAAAAAAKv0/LrGpwObFGzI/s800/IMG_1514.JPG"><img class="alignright" title="Ommegang biere" src="https://lh3.googleusercontent.com/-7nJ9gGceZkM/TvUWi7KqUDI/AAAAAAAAKv0/LrGpwObFGzI/s800/IMG_1514.JPG" alt="" width="192" height="374" /></a><br />
Au début je n&#8217;y ai cru qu&#8217;a moitié. Puis j&#8217;ai oublié&#8230;<br />
Il y a quelques jours j&#8217;ai reçu un mail pour me dire que le brassin était pret et que dès que l&#8217;embouteillage aurait lieu, la bouteille serait envoyée.<br />
Là je me suis dit: &#8220;ça doit être une erreur, ils ont envoyé un mail à tout le monde alors qu&#8217;ils ne ciblait que les acheteurs&#8221;.<br />
Mais, je dois me rendre à l&#8217;évidence, car c&#8217;est bien arrivé. Aujourd&#8217;hui j&#8217;ai été chercher au point poste ma bouteille d&#8217;Ommegang édition limitée.<br />
Waw&#8230; ça c&#8217;est du marketing!<br />
Pas de spam, un message pour dire que ça va arriver et puis le cadeau. Propre, simple efficace.<br />
Bon, il ne reste plus qu&#8217;à gouter.<br />
<a href="http://blog.sbw.be/wp-content/uploads/2011/12/IMG_1516.jpg"><img class="alignleft size-medium wp-image-520" title="ommegang close up" src="http://blog.sbw.be/wp-content/uploads/2011/12/IMG_1516-300x200.jpg" alt="" width="300" height="200" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sbw.be/2011/12/24/biere-ommegang/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calling XmlRpc of WordPress with Zend Framework (Zend_XmlRpc_Client) and adding the default thumbnail to a post</title>
		<link>http://blog.sbw.be/2011/07/19/calling-xmlrpc-of-wordpress-with-zend-framework-zend_xmlrpc_client-and-adding-the-default-thumbnail-to-a-post/</link>
		<comments>http://blog.sbw.be/2011/07/19/calling-xmlrpc-of-wordpress-with-zend-framework-zend_xmlrpc_client-and-adding-the-default-thumbnail-to-a-post/#comments</comments>
		<pubDate>Tue, 19 Jul 2011 19:13:44 +0000</pubDate>
		<dc:creator>Sébastien Barbieri</dc:creator>
				<category><![CDATA[D'alpha du centaure]]></category>
		<category><![CDATA[OpenDojo]]></category>
		<category><![CDATA[truc de g33k]]></category>
		<category><![CDATA[metaWeblog.newMediaObjec]]></category>
		<category><![CDATA[metaWeblog.newPost]]></category>
		<category><![CDATA[Zend_XmlRpc_Client]]></category>
		<category><![CDATA[Zend_XmlRpc_Value_Base64]]></category>
		<category><![CDATA[Zend_XmlRpc_Value_Struct]]></category>

		<guid isPermaLink="false">http://blog.sbw.be/?p=504</guid>
		<description><![CDATA[This code is in 2 parts First part, we download an image somewhere using Zend_Http_Client Second part, we use xmlrpc to upload the image into wordpress as a media and to create a post using this media as featured image or default image of main thumbnail, whatever the name is Let&#8217;s have a look at [...]]]></description>
			<content:encoded><![CDATA[<p>This code is in 2 parts</p>
<p>First part, we download an image somewhere using Zend_Http_Client</p>
<p>Second part, we use xmlrpc to upload the image into wordpress as a media and to create a post using this media as featured image or default image of main thumbnail, whatever the name is</p>
<p>Let&#8217;s have a look at the first part:<br />
<strong>Downloading an image with Zend_Http_Client</strong><br />
this is quite simple</p>
<pre class="brush: php; title: ;">
				require_once 'Zend/Http/Client.php';
				$config=array(
					'adapter'=&gt;'Zend_Http_Client_Adapter_Curl'
				);
				$Zend_Http_Client = new Zend_Http_Client($imageUrl,$config);
				try{
					$result = $Zend_Http_Client-&gt;request('GET');
				}catch(Exception $e){
					print_r($e);
				}
				$data = $result-&gt;getBody();
				//file_put_contents('/tmp/test.jpg',$data); // this is just to test the image if you are unsure
</pre>
<p>second part, storing the image in wordpress and creating a post with custom field: <strong>_thumbnail_id</strong> set to this image</p>
<p>To store a media object we will use the <strong>metaWeblog.newMediaObject</strong> XmlRpc method</p>
<pre class="brush: php; title: ;">
				require_once 'Zend/XmlRpc/Client.php';
				require_once 'Zend/XmlRpc/Value/Base64.php';
				require_once 'Zend/XmlRpc/Value/Struct.php';
				require_once 'Zend/XmlRpc/Value/Array.php';
				$xmlRpcClient = new Zend_XmlRpc_Client('http://www.example.com/myblog/xmlrpc.php');
				try{
					$thumbnail = $xmlRpcClient-&gt;call(
						'metaWeblog.newMediaObject',
						array(0,
							'login',
							'pass',
							array(
								'name'=&gt;'test.jpg',
								'type'=&gt;'image/jpeg',
								'bits'=&gt;new Zend_XmlRpc_Value_Base64($data),
							)
						)
					);
// ...
</pre>
<p>in the thumbnail object we don&#8217;t get the id&#8230; because it&#8217;s not possible to get the id unless you hack wordpress</p>
<blockquote><p>
<strong>WP file</strong>: wp-include/class-wp-xml-rpc.php</p>
<p><strong>method</strong>: function mw_newMediaObject($args) {</p>
<p>modification: add the id in the return:</p>
<pre class="brush: php; title: ;">
return apply_filters(
	'wp_handle_upload',
	array( 'file' =&gt; $name, 'url' =&gt; $upload[ 'url' ], 'type' =&gt; $type )
	, 'upload'
	);
</pre>
<p>by:</p>
<pre class="brush: php; title: ;">
return apply_filters(
	'wp_handle_upload',
	array( 'file' =&gt; $name, 'url' =&gt; $upload[ 'url' ], 'type' =&gt; $type, 'id'=&gt;$id )
	, 'upload'
	);
</pre>
</blockquote>
<pre class="brush: php; title: ;">
// ...
		$struct = new Zend_XmlRpc_Value_Struct(
					array('key'=&gt;'_thumbnail_id', 'value'=&gt;$thumbnail['id'])
				);
		$result = $xmlRpcClient-&gt;call(
			'metaWeblog.newPost',
			array(0,
			'login',
			'pass',
			array(
				'post_type'=&gt;'post',
				'title'=&gt;'New article with thumb',
				'description'=&gt;'Article text',
				'custom_fields'=&gt;array($struct),
			),
			false)
		);
	}catch(Exception $e){
		print_r($e);
	}
</pre>
<p>Of course, this won&#8217;t work&#8230; because no one is allowed to access private custom_fields such as _thumbnail_id &#8230;</p>
<p>A second WP hack is necessary here:</p>
<p><strong>file</strong>: wp-includes/meta.php<br />
<strong>function</strong>: is_protected_meta</p>
<p>add an exception for _thumbnail_id</p>
<pre class="brush: php; title: ;">
function is_protected_meta( $meta_key, $meta_type = null ) {
        if($meta_key == '_thumbnail_id'){
                $protected=false;
        }else{
                $protected = (  '_' == $meta_key[0] );
        }
        return apply_filters( 'is_protected_meta', $protected, $meta_key, $meta_type );
}
</pre>
<p>Without a nice documentation that was the best I could do in few time.</p>
<p>Another approach could be to create a new XmlRpc method, which do both in once avoiding the weakness of reusing an internal id in a second call, but still XmlRpc use add_meta which is a really ugly way to add meta in a post as everything has to be put in $_POST &#8230; </p>
<p>If anyone has a better approach (using xmlrpc) feel free to submit the suggestion.</p>
<p>A third approach could be to write a plugin&#8230; that&#8217;s next step</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sbw.be/2011/07/19/calling-xmlrpc-of-wordpress-with-zend-framework-zend_xmlrpc_client-and-adding-the-default-thumbnail-to-a-post/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>All the assumption I want to remember in PHP</title>
		<link>http://blog.sbw.be/2011/05/26/all-the-assumption-i-want-to-remember-about-php/</link>
		<comments>http://blog.sbw.be/2011/05/26/all-the-assumption-i-want-to-remember-about-php/#comments</comments>
		<pubDate>Thu, 26 May 2011 09:33:00 +0000</pubDate>
		<dc:creator>Sébastien Barbieri</dc:creator>
				<category><![CDATA[truc de g33k]]></category>
		<category><![CDATA[empty]]></category>
		<category><![CDATA[false]]></category>
		<category><![CDATA[NULL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.sbw.be/?p=491</guid>
		<description><![CDATA[Probably linked to some alcohol I drank to young, I always forget some key assumption in PHP. NULL is NULL NULL is EMPTY NULL is FALSE NULL has a sizeof 0 BUT FALSE is not NULL FALSE is EMPTY FALSE is FALSE FALSE has a sizeof 1 AND empty ARRAY is not NULL empty ARRAY [...]]]></description>
			<content:encoded><![CDATA[<p>Probably linked to some alcohol I drank to young, I always forget some key assumption in PHP.</p>
<p>NULL is NULL<br />
NULL is EMPTY<br />
NULL is FALSE<br />
NULL has a sizeof 0</p>
<p><strong>BUT</strong></p>
<p>FALSE is not NULL<br />
FALSE is EMPTY<br />
FALSE is FALSE<br />
FALSE has a sizeof 1</p>
<p><strong>AND</strong></p>
<p>empty ARRAY is not NULL<br />
empty ARRAY is EMPTY<br />
empty ARRAY is FALSE<br />
empty ARRAY has a sizeof 0</p>
<pre class="brush: php; title: ;">
$test=NULL;
if(is_null($test)){print(&quot;NULL is NULL&quot;);}else{print(&quot;NULL is not NULL&quot;);}
// NULL is NULL
if(empty($test)){print(&quot;NULL is EMPTY&quot;);}else{print(&quot;NULL is not EMPTY&quot;);}
// NULL is empty
if($test){print(&quot;NULL is TRUE&quot;);}else{print(&quot;NULL is FALSE&quot;);}
// NULL is FALSE
print(count($test));
// 0
$test=false;
if(is_null($test)){print(&quot;FALSE is NULL&quot;);}else{print(&quot;FALSE is not NULL&quot;);}
// FALSE is not NULL
if(empty($test)){print(&quot;FALSE is EMPTY&quot;);}else{print(&quot;FALSE is not EMPTY&quot;);}
// FALSE is EMPTY
if($test){print(&quot;FALSE is TRUE&quot;);}else{print(&quot;FALSE is FALSE&quot;);}
// FALSE is FALSE
print(count($test));
// 1
$test=array();
if(is_null($test)){print(&quot;empty ARRAY is NULL&quot;);}else{print(&quot;empty ARRAY is not NULL&quot;);}
// empty ARRAY is not NULL
if(empty($test)){print(&quot;empty ARRAY is EMPTY&quot;);}else{print(&quot;empty ARRAY is not EMPTY&quot;);}
// empty ARRAY is EMPTY
if($test){print(&quot;empty ARRAY is TRUE&quot;);}else{print(&quot;empty ARRAY is FALSE&quot;);}
// empty ARRAY is FALSE
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.sbw.be/2011/05/26/all-the-assumption-i-want-to-remember-about-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Run 20km and give them water</title>
		<link>http://blog.sbw.be/2011/05/03/run-20km-and-give-them-water/</link>
		<comments>http://blog.sbw.be/2011/05/03/run-20km-and-give-them-water/#comments</comments>
		<pubDate>Tue, 03 May 2011 20:00:08 +0000</pubDate>
		<dc:creator>Sébastien Barbieri</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Questions existentielles]]></category>
		<category><![CDATA[20km]]></category>
		<category><![CDATA[bruxelles]]></category>
		<category><![CDATA[croix-rouge]]></category>
		<category><![CDATA[dons]]></category>
		<category><![CDATA[rwanda]]></category>

		<guid isPermaLink="false">http://blog.sbw.be/?p=485</guid>
		<description><![CDATA[Avec 425 autres coureurs nous allons nous lancer dans la course afin de récolter 30 000 € pour le croix-rouge. Run and Give them water est un projet d&#8217;approvisionnement en eau potable au Rwanda Pour faire un don: suivez le lien: http://www.croix-rouge.be/20km/parrainage_don.htm et rajouter SEBASTIEN BARBIERI à la fin de la zone d&#8217;édition. 20 KM [...]]]></description>
			<content:encoded><![CDATA[<p><img alt="Run and Give them water" src="http://www.croix-rouge.be/20km/img/20km_logo_crb.png" title="Croix rouge run and give them water 20 km bruxelles" class="alignleft" width="350" height="199" />Avec 425 autres coureurs nous allons nous lancer dans la course afin de récolter 30 000 € pour le croix-rouge.</p>
<p><a href="http://www.croix-rouge.be/20km/">Run and Give them water</a> est un projet d&#8217;approvisionnement en eau potable au Rwanda</p>
<p>Pour faire un don: suivez le lien: <a href="http://www.croix-rouge.be/20km/parrainage_don.htm">http://www.croix-rouge.be/20km/parrainage_don.htm</a> et rajouter SEBASTIEN BARBIERI à la fin de la zone d&#8217;édition.</p>
<blockquote><p>20 KM PARRAINAGE &#8211; SEBASTIEN BARBIERI</p></blockquote>
<p>Ou faites un versemment au compte: 000-0000016-16 avec la mention &#8220;20 KM PARRAINAGE + SEBASTIEN BARBIERI&#8221;</p>
<p>Pour me parrainer vous pouvez décider par exemple de donner 50 cents/km, et pour chaque kilomètres que je parcours, vous versez 50 cents soit 10€ pour les 20km.</p>
<p>Je m&#8217;engage pour ma part à courir pour 5€/Km => 100€.</p>
<p>Soutenez-moi, par vos encouragement ou par un don.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sbw.be/2011/05/03/run-20km-and-give-them-water/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>baladodiffusion</title>
		<link>http://blog.sbw.be/2011/04/20/baladodiffusion/</link>
		<comments>http://blog.sbw.be/2011/04/20/baladodiffusion/#comments</comments>
		<pubDate>Wed, 20 Apr 2011 12:08:26 +0000</pubDate>
		<dc:creator>Sébastien Barbieri</dc:creator>
				<category><![CDATA[8th chakra]]></category>
		<category><![CDATA[je bosse là]]></category>
		<category><![CDATA[Mon blog]]></category>
		<category><![CDATA[baladodiffusion]]></category>
		<category><![CDATA[podcast]]></category>

		<guid isPermaLink="false">http://blog.sbw.be/?p=479</guid>
		<description><![CDATA[Adieu podcasts, bienvenue Baladodiffusion! Quel est le principe? La radio propose sur un site des liens vers des fichiers audio permettant de réécouter une émission radio de manière diférrée. Avantages Pouvoir écouter quand on veut et où l&#8217;on veut une émission. Bon mais c&#8217;est la même chose que le podcast jusque là. Alors quel est [...]]]></description>
			<content:encoded><![CDATA[<p>Adieu podcasts, bienvenue Baladodiffusion!</p>
<p><strong>Quel est le principe?</strong></p>
<p>La radio propose sur un site des liens vers des fichiers audio permettant de réécouter une émission radio de manière diférrée.</p>
<p><strong>Avantages</strong></p>
<p>Pouvoir écouter quand on veut et où l&#8217;on veut une émission.</p>
<p><strong>Bon mais c&#8217;est la même chose que le podcast jusque là. Alors quel est la différence ?</strong></p>
<p>La différence est déjà dans le mot BALADO-DIFFUSION, la diffusion en balade.<br />
<a href="http://fr.wiktionary.org/wiki/balade">Balade</a>: Selon le wiktionnaire: </p>
<blockquote><p><strong>Etymologie:</strong> Du verbe balader, lui-même venant de ballade (« poème chanté ») en raison des saltimbanques qui se déplaçaient sans destination particulière et qui chantaient des ballades pour demander l’aumône.</p></blockquote>
<p>C&#8217;est ici toute l&#8217;idée: Balade, poème chanté, déplacement, mobilité. A notre époque il s&#8217;agit de pouvoir se promener avec de la musique. Totalement différent de Podcast, qui n&#8217;est qu&#8217;un mot commercial contraction de iPod(R) et de broadcast ==> diffusion sur iPod&#8230;</p>
<p><strong>WTF?</strong></p>
<p>Oui, je sais&#8230;</p>
<p>Faites comme moi, adieu podcast, bienvenue baladodiffusion et m&#8230;. à l&#8217;envahisseur (Pomme (R) )</p>
<p>TAG: #baladodiffusion #jeBosseSurMusiq3 #vivelamusiqueclassique</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sbw.be/2011/04/20/baladodiffusion/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Open Dojo v1.0</title>
		<link>http://blog.sbw.be/2011/04/06/open-dojo-v1-0/</link>
		<comments>http://blog.sbw.be/2011/04/06/open-dojo-v1-0/#comments</comments>
		<pubDate>Wed, 06 Apr 2011 17:03:53 +0000</pubDate>
		<dc:creator>Sébastien Barbieri</dc:creator>
				<category><![CDATA[OpenDojo]]></category>
		<category><![CDATA[opendojo]]></category>
		<category><![CDATA[phing]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://blog.sbw.be/?p=475</guid>
		<description><![CDATA[Subject list for an open dojo / bbq session As Jedi phpunit and code coverage phing deployment svn and continuous integration As Padawan Working agile Scrum Now let&#8217;s decide a timeline]]></description>
			<content:encoded><![CDATA[<p>Subject list for an open dojo / bbq session</p>
<p>As Jedi</p>
<ul>
<li>phpunit and code coverage</li>
<li>phing deployment</li>
<li>svn and continuous integration</li>
</ul>
<p>As Padawan</p>
<ul>
<li>Working agile</li>
<li>Scrum</li>
</ul>
<p>Now let&#8217;s decide a timeline</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sbw.be/2011/04/06/open-dojo-v1-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Couteau &#8220;Chef&#8221; Evercut</title>
		<link>http://blog.sbw.be/2010/12/06/couteau-chef-evercut/</link>
		<comments>http://blog.sbw.be/2010/12/06/couteau-chef-evercut/#comments</comments>
		<pubDate>Mon, 06 Dec 2010 21:28:29 +0000</pubDate>
		<dc:creator>Sébastien Barbieri</dc:creator>
				<category><![CDATA[cuisine]]></category>
		<category><![CDATA[chef]]></category>
		<category><![CDATA[couteau]]></category>
		<category><![CDATA[evercut]]></category>
		<category><![CDATA[Tarrerias Bonjean]]></category>

		<guid isPermaLink="false">http://blog.sbw.be/?p=465</guid>
		<description><![CDATA[Ca y est! J&#8217;ai reçu mon couteau Evercut! Terrible packaging! Ultra sharp, il coupe super bien. Pour l&#8217;instant je n&#8217;ai testé que quelques légumes (oignons, échalotes, courgettes) mais c&#8217;est vraiment nickel. Une très grand précision pour les petits détails. En plus il fait un bruit terrible quand il coupe&#8230; j&#8217;adore. C&#8217;est mon auto-cadeau de Noël [...]]]></description>
			<content:encoded><![CDATA[<p>Ca y est!</p>
<p>J&#8217;ai reçu mon couteau Evercut!<br />
<div class="wp-caption alignnone" style="width: 277px"><img alt="" src="http://lh5.ggpht.com/_aC4Q0Pd7gZM/TP1Q27bQtHI/AAAAAAAAJTo/MAvMpRsjC54/s400/IMG_9358.JPG" title="Evercut Collect&#038;Go Delivery" width="267" height="400" /><p class="wp-caption-text">Couteau Chef Evercut </p></div><br />
Terrible packaging!<br />
<img alt="" src="http://lh3.ggpht.com/_aC4Q0Pd7gZM/TP1Q3tbfviI/AAAAAAAAJTs/5gKUuw9z-tA/s640/IMG_9359.JPG" title="Evercut Text" class="alignnone" width="640" height="427" /><br />
<img alt="" src="http://lh4.ggpht.com/_aC4Q0Pd7gZM/TP1Q4_rnO5I/AAAAAAAAJT0/pfCNAqrM1E4/s640/IMG_9364.JPG" title="Evercut packaging" class="alignnone" width="640" height="427" /></p>
<p>Ultra sharp, il coupe super bien.</p>
<p>Pour l&#8217;instant je n&#8217;ai testé que quelques légumes (oignons, échalotes, courgettes) mais c&#8217;est vraiment nickel.<br />
Une très grand précision pour les petits détails.</p>
<p>En plus il fait un bruit terrible quand il coupe&#8230; j&#8217;adore. C&#8217;est mon auto-cadeau de Noël !!!</p>
<table style="width:auto;">
<tr>
<td><a href="http://picasaweb.google.com/lh/photo/YflsT_jpopupkbP6Jw7VIw?feat=embedwebsite"><img src="http://lh4.ggpht.com/_aC4Q0Pd7gZM/TP1Q5RdZznI/AAAAAAAAJT4/R8PbnojBdvA/s144/IMG_9368.JPG" height="96" width="144" /></a></td>
<td><a href="http://picasaweb.google.com/lh/photo/bKpBD2TnD8bIK0QlH3r1HQ?feat=embedwebsite"><img src="http://lh4.ggpht.com/_aC4Q0Pd7gZM/TP1Q6aRBjWI/AAAAAAAAJT8/Kblmm1z44oE/s144/IMG_9369.JPG" height="144" width="96" /></a></td>
<td><a href="http://picasaweb.google.com/lh/photo/iSKSf1mb-RTV60QJx6GjeQ?feat=embedwebsite"><img src="http://lh5.ggpht.com/_aC4Q0Pd7gZM/TP1Q7UUyGUI/AAAAAAAAJUA/EU5K01WUIm8/s144/IMG_9375.JPG" height="96" width="144" /></a></td>
</tr>
<tr>
<td style="font-family:arial,sans-serif; font-size:11px; text-align:right" colspan="3">From <a href="http://picasaweb.google.com/sebastien.barbieri/Evercut?feat=embedwebsite">Evercut</a></td>
</tr>
</table>
<p>Le site du couteau: <a href="http://www.evercut.fr/">http://www.evercut.fr/</a> &#8211; Le concepteur: <a href="http://www.tb-groupe.fr/">http://www.tb-groupe.fr/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sbw.be/2010/12/06/couteau-chef-evercut/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Continuous Integration phpunit code coverage use a bit less than 2 Gigs !!!</title>
		<link>http://blog.sbw.be/2010/11/30/continuous-integration-phpunit-code-coverage-use-a-bit-less-than-2-gigs/</link>
		<comments>http://blog.sbw.be/2010/11/30/continuous-integration-phpunit-code-coverage-use-a-bit-less-than-2-gigs/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 18:28:08 +0000</pubDate>
		<dc:creator>Sébastien Barbieri</dc:creator>
				<category><![CDATA[freelance]]></category>
		<category><![CDATA[je bosse là]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[truc de g33k]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[zend]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://blog.sbw.be/?p=450</guid>
		<description><![CDATA[2 gigs !!! gasp&#8230; I had several: Generating code coverage report, this may take a moment.PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 21503527 bytes) in /usr/share/php/PHPUnit/Util/Report/Node/File.php on line 406 And here is how it started: At work we are using phpunit to test our framework, we flew from SimpleTest [...]]]></description>
			<content:encoded><![CDATA[<p><strong>2 gigs !!!</strong> <em>gasp</em>&#8230; </p>
<p>I had several:</p>
<p><strong>Generating code coverage report, this may take a moment.PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 21503527 bytes) in /usr/share/php/PHPUnit/Util/Report/Node/File.php on line 406<br />
</strong></p>
<p>And here is how it started:</p>
<p>At work we are using <a href="http://www.phpunit.de/">phpunit</a> to test our framework, we flew from <a href="http://www.simpletest.org/">SimpleTest</a> as there was no real integration with our tools and no real followup of the the product.</p>
<p>So to automate the test, as there is no &#8220;build&#8221; in php (interpreted vs compiled remember?) we ran it after each commit &#8230;</p>
<p>Until it tooks 30 minutes to run throught the whole set of tests&#8230;</p>
<p><span id="more-450"></span><br />
Then we decided to run it locally before comitting&#8230; until it tooks up to 2 hours to run tests (yes we have slow laptops I know, at least 4 times slower than the servers).</p>
<p>Actually we use phpunit for recipe test, including database change, third parties, providers&#8230; everything from A to Z&#8230; and that needs a lot of time and CPU power&#8230;</p>
<p>So we solved the problem by running test in a cronjob, hourly on the integration server.</p>
<p>This was done running phpunit in command line</p>
<p><code lang="bash"><br />
&gt; phpunit --include-path ../code/ MyTestSuite.php<br />
</code></p>
<p>Of course as we had several tests suites and we had to put them all in one bigger testsuite&#8230; but that was not easy so we moved to the Phpunit config file, added code coverage reporting and send a mail everytime sometimes goes wrong</p>
<p><strong>PhpunitConfig.xml</strong></p>
<p><code lang="xml"></p>
<pre class="brush: xml; title: ;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;phpunit
         colors=&quot;true&quot;
         &gt;
         &lt;testsuites&gt;
         	&lt;testsuite name=&quot;RTBF_Service&quot;&gt;
         		&lt;file&gt;RTBF/Service/Rating/Adapter/AbstractPhpunittest.php&lt;/file&gt;
         		&lt;file&gt;RTBF/Service/Rating/Adapter/MediaPhpunittest.php&lt;/file&gt;
         	&lt;--! ... --&gt;
         	&lt;/testsuite&gt;
         	&lt;testsuite name=&quot;RTBF&quot;&gt;
         		&lt;file&gt;RTBF/AclPhpunittest.php&lt;/file&gt;
         	&lt;/testsuite&gt;
         	&lt;testsuite name=&quot;RTBF_Utility&quot;&gt;
         		&lt;file&gt;RTBF/Utility/AjaxConnectorPhpunittest.php&lt;/file&gt;
	         	&lt;--! ... --&gt;
         	&lt;/testsuite&gt;
         	&lt;--! ... --&gt;
	&lt;/testsuites&gt;
	&lt;listeners&gt;
  		&lt;listener class=&quot;SimpleTestListener&quot; file=&quot;PhpunitTestListener.php&quot;&gt;
  		&lt;/listener&gt;
  	&lt;/listeners&gt;
  	&lt;!--
	&lt;logging&gt;
		&lt;log type=&quot;coverage-html&quot; target=&quot;/reporting/phpunit/library/&quot; charset=&quot;UTF-8&quot; /&gt;
	&lt;/logging&gt;
	--&gt;
	&lt;php&gt;
		&lt;ini name=&quot;memory_limit&quot; value=&quot;2047M&quot; /&gt;
	&lt;/php&gt;
	&lt;filter&gt;
	  &lt;blacklist&gt;
	    &lt;directory suffix=&quot;.php&quot;&gt;library/code/Zend&lt;/directory&gt;
	  &lt;/blacklist&gt;
	&lt;/filter&gt;
&lt;/phpunit&gt;
</pre>
<p></code></p>
<p><strong>PhpunitTestListener.php</strong></p>
<p><code lang="php"></p>
<pre class="brush: php; title: ;">
class SimpleTestListener implements PHPUnit_Framework_TestListener
{
	private $emailContent=array(self::Error=&gt;&quot;&quot;,self::Failure=&gt;&quot;&quot;,self::Incomplete=&gt;&quot;&quot;,self::Skipped=&gt;&quot;&quot;);
	private $assertions=0;
	private $itemCount=array(self::Error=&gt;0,self::Failure=&gt;0,self::Incomplete=&gt;0,self::Skipped=&gt;0);
	private $totalItems=0;

	const Error=&quot;Error&quot;;
	const Failure=&quot;Failure&quot;;
	const Incomplete=&quot;Incomplete&quot;;
	const Skipped=&quot;Skipped&quot;;

	private function addEmailContent($severity,$test,$e){
		$result = $test-&gt;getResult();
		$traces = $e-&gt;getTrace();
		$continue=true;
		$tracingMessage=&quot;&quot;;
		for($i=1;$i&lt;count($traces)&amp;&amp;$continue;$i++){
			if(isset($traces[$i]['file'])){
				$tracingMessage.=$traces[$i]['file'].&quot;:(&quot;.$traces[$i]['line'].&quot;)\n\t&quot;;
			}else{
				$continue=false;
			}
		}
		$this-&gt;itemCount[$severity]++;
		$this-&gt;emailContent[$severity].=$this-&gt;itemCount[$severity].&quot;)\t&quot;.get_class($test).'::'.$test-&gt;getName(TRUE).&quot;\n\t&quot;.str_replace(&quot;\n&quot;,&quot;\n\t&quot;,PHPUnit_Framework_TestFailure::exceptionToString($e)).&quot;&quot;.$tracingMessage.&quot;\n\n&quot;;
		$this-&gt;totalItems++;
	}

	public function addError(PHPUnit_Framework_Test $test,Exception $e,$time){
		$this-&gt;addEmailContent(self::Error,$test,$e);
	}

	public function addFailure(PHPUnit_Framework_Test $test,PHPUnit_Framework_AssertionFailedError $e,$time){
		$this-&gt;addEmailContent(self::Failure,$test,$e);
	}

	public function addIncompleteTest(PHPUnit_Framework_Test $test,Exception $e,$time){
		$this-&gt;addEmailContent(self::Incomplete,$test,$e);
	}

	public function addSkippedTest(PHPUnit_Framework_Test $test,Exception $e,$time){
		$this-&gt;addEmailContent(self::Skipped,$test,$e);
	}

	public function startTest(PHPUnit_Framework_Test $test){
	}

	public function endTest(PHPUnit_Framework_Test $test, $time){
	}

	public function startTestSuite(PHPUnit_Framework_TestSuite $suite){
	}

	public function endTestSuite(PHPUnit_Framework_TestSuite $suite){
	}

	public function __destruct(){
		if($this-&gt;totalItems&gt;0){
			// HIDDEN but concat everything from $this-&gt;emailContent nicely and send the mail
			//print(&quot;\n\nMail sent: &quot;.$text.&quot;\n&quot;);
		}
	}
}
</pre>
<p></code></p>
<p>That&#8217;s it for the big picture&#8230;</p>
<p>And as you can see there are several point in the XML that are quite important:</p>
<p><strong>memory limit 2047MB</strong>that&#8217;s huge&#8230; but this is the price to pay to have a fully working code-coverage HTML report. As we are using <a href="http://www.hardened-php.net/suhosin/">suhosin</a> we had to change the memory limit in suhosin too&#8230; and yes when the limit is 2048 MB don&#8217;t try to set the memory to 2048 MB it really means this is a limit you have to be under that limit (here 2047 MB).</p>
<p><strong>2 Gigs!!!</strong> I know this is huge but believe me I went through several tries and 128 MB was not enought, nor 256 MB, nor 512 MB, not even 1 GB &#8230; I didn&#8217;t try to see where is my limit &#8230; I put 2 gigs and then it worked&#8230; we have about 30% of lines covered so I think that if we shift to 100% we will have to give more memory&#8230; I&#8217;m pretty sure, there is something leaking somewhere&#8230; but according to phpunit.de site&#8230; I have the answer remains: <a href="https://github.com/sebastianbergmann/php-code-coverage/issues/closed/#issue/26">Give more memory</a></p>
<p><strong>/etc/php5/conf.d/suhosin.ini</strong><br />
<code></p>
<p>...<br />
suhosin.memory_limit = 2048M<br />
...</p>
<p></code></p>
<p><strong>logging</strong> is commented out because logging needs xdebug and while we stay with ZendServer CE we do not have xdebug&#8230; (see my previous post for more info). </p>
<p>But the server which is not running Zend Server CE does!</p>
<p>So I commented out the line in the config to let developers run the unit test and pasted it as command line argument on the server&#8217;s cronjob.</p>
<p><code lang="bash"></p>
<pre class="brush: bash; title: ;">
phpunit --include-path ../code/ --coverage-html /reporting/phpunit/library/ --configuration PhpunitConfig.xml
</pre>
<p></code></p>
<p><strong>the listener</strong> This is a simple easy listener. It&#8217;s always useful to have one sample so I pasted here above, feel free to copy, enhance&#8230; The only &#8216;hack&#8217; we use it to call the send email on listener destruction, so the email will be sent at the end. But there is a drawback&#8230; if there is a php error somewhere, nothing is sent. And as nothing is sent when everythign goes well&#8230; we dont know if everythings goes well or if there is a real bug&#8230;<br />
This problem will be addressed later. Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sbw.be/2010/11/30/continuous-integration-phpunit-code-coverage-use-a-bit-less-than-2-gigs/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>installing xdebug on ubuntu with Zend Server CE (not solved yet)</title>
		<link>http://blog.sbw.be/2010/11/12/installing-xdebug-on-ubuntu/</link>
		<comments>http://blog.sbw.be/2010/11/12/installing-xdebug-on-ubuntu/#comments</comments>
		<pubDate>Fri, 12 Nov 2010 10:16:09 +0000</pubDate>
		<dc:creator>Sébastien Barbieri</dc:creator>
				<category><![CDATA[freelance]]></category>
		<category><![CDATA[truc de g33k]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[xdebug]]></category>
		<category><![CDATA[zend server ce]]></category>

		<guid isPermaLink="false">http://blog.sbw.be/?p=439</guid>
		<description><![CDATA[You need to sudo user@laptop:~$ sudo bash 1st be sre to have the pecl, pear available as root in command line root@laptop:~# PATH=$PATH:/usr/local/zend/bin trying to install root@laptop:~# pecl install xdebug downloading xdebug-2.1.0.tgz ... Starting to download xdebug-2.1.0.tgz (301,354 bytes) .....................................................done: 301,354 bytes 66 source files, building running: phpize Configuring for: PHP Api Version: 20041225 Zend [...]]]></description>
			<content:encoded><![CDATA[<p>You need to sudo</p>
<p><code>user@laptop:~$ sudo bash</code></p>
<p>1st be sre to have the pecl,  pear available as root in command line</p>
<p><code>root@laptop:~# PATH=$PATH:/usr/local/zend/bin</code></p>
<p>trying to install</p>
<p><code>root@laptop:~# pecl install xdebug<br />
downloading xdebug-2.1.0.tgz ...<br />
Starting to download xdebug-2.1.0.tgz (301,354 bytes)<br />
.....................................................done: 301,354 bytes<br />
66 source files, building<br />
running: phpize<br />
Configuring for:<br />
PHP Api Version:         20041225<br />
Zend Module Api No:      20060613<br />
Zend Extension Api No:   220060519<br />
Cannot find autoconf. Please check your autoconf installation and the<br />
$PHP_AUTOCONF environment variable. Then, rerun this script.</p>
<p>ERROR: `phpize' failed<br />
</code><br />
Argl it seems to be failing&#8230;</p>
<p>looks like autoconf is missing</p>
<p><code>root@laptop:~# autoconf<br />
The program 'autoconf' can be found in the following packages:<br />
 * autoconf<br />
 * autoconf2.13<br />
Try: apt-get install &lt;selected package&gt;<br />
</code></p>
<p>ok let&#8217;s add it:</p>
<p><code><br />
root@laptop:~# apt-get install autoconf<br />
</code></p>
<p>and now let&#8217;s try again</p>
<p><code><br />
root@laptop:~# pecl install xdebug<br />
downloading xdebug-2.1.0.tgz ...<br />
Starting to download xdebug-2.1.0.tgz (301,354 bytes)<br />
.............................................................done: 301,354 bytes<br />
66 source files, building<br />
running: phpize<br />
Configuring for:<br />
PHP Api Version:         20041225<br />
Zend Module Api No:      20060613<br />
Zend Extension Api No:   220060519<br />
configure.in:3: warning: prefer named diversions<br />
configure.in:3: warning: prefer named diversions<br />
building in /var/tmp/pear-build-root/xdebug-2.1.0<br />
running: /tmp/pear/temp/xdebug/configure<br />
checking for grep that handles long lines and -e... /bin/grep<br />
checking for egrep... /bin/grep -E<br />
checking for a sed that does not truncate output... /bin/sed<br />
checking for cc... cc<br />
...<br />
Build process completed successfully<br />
Installing '/usr/local/zend/lib/php_extensions/xdebug.so'<br />
install ok: channel://pecl.php.net/xdebug-2.1.0<br />
configuration option "php_ini" is not set to php.ini location<br />
You should add "extension=xdebug.so" to php.ini<br />
</code></p>
<p>Great!</p>
<p>Don&#8217;t forget to add the librairy in the php.ini</p>
<p>create the xdebug.ini in the ext.d directory and the symlink in the conf.d directory</p>
<p><code><br />
root@laptop:/usr/local/zend/etc/ext.d# more xdebug.ini<br />
zend_extension=/usr/local/zend/lib/php_extensions/xdebug.so<br />
; You may put any extension-specific directives here</p>
<p>root@laptop:/usr/local/zend/etc/conf.d# ln -s ../ext.d/xdebug.ini xdebug.ini<br />
</code></p>
<p>Now let&#8217;s try PHP:</p>
<p><code>scips@laptop:~$ php<br />
Segmentation fault<br />
</code></p>
<p>Looks like I need to investigate deeper&#8230;</p>
<p>Ok problem solved:</p>
<blockquote><p><strong>Instructions</strong></p>
<p><em><strong>Warning: You seem to be using Zend Server, which is known to cause issues with Xdebug. It might work, but you&#8217;re on your own.</strong></em></p>
<p>Download xdebug-2.1.0.tgz<br />
Unpack the downloaded file with tar -xvzf xdebug-2.1.0.tgz<br />
Run: cd xdebug-2.1.0<br />
Run: phpize</p>
<p>As part of its output it should show:</p>
<p>Configuring for:<br />
&#8230;<br />
Zend Module Api No:      20060613<br />
Zend Extension Api No:   220060519<br />
If it does not, you are using the wrong phpize. Please follow this FAQ entry and skip the next step.</p>
<p>Run: ./configure<br />
Run: make<br />
Run: cp modules/xdebug.so /usr/local/zend/lib/php_extensions<br />
Open /usr/local/zend/etc/conf.d/debugger.ini and put a ; in front of the line that says zend_extension_manager.dir.debugger= so that it says ;zend_extension_manager.dir.debugger=<br />
Edit /usr/local/zend/etc/php.ini and add at the begining of the file the line<br />
zend_extension = /usr/local/zend/lib/php_extensions/xdebug.so
</p></blockquote>
<p>I did just paste in has requested my php -i output on <a href="http://xdebug.org/find-binary.php">http://xdebug.org/find-binary.php</a> then compiled and everything ran fine.</p>
<p>The problem is that you have to use one or the other not the both at the same time&#8230; still not a real option for me. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sbw.be/2010/11/12/installing-xdebug-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Subversion backup &amp; restore</title>
		<link>http://blog.sbw.be/2010/10/07/subversion-backup-restore/</link>
		<comments>http://blog.sbw.be/2010/10/07/subversion-backup-restore/#comments</comments>
		<pubDate>Thu, 07 Oct 2010 20:39:02 +0000</pubDate>
		<dc:creator>Sébastien Barbieri</dc:creator>
				<category><![CDATA[freelance]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[restore]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://blog.sbw.be/?p=435</guid>
		<description><![CDATA[Get it first of all you need the best script ever made to backup subversion: the one provided with! Get it here: http://svn.apache.org/repos/asf/subversion/trunk/tools/backup/hot-backup.py.in This script needs to be modified replace: # Path to svnlook utility svnlook = r"@SVN_BINDIR@/svnlook" # Path to svnadmin utility svnadmin = r"@SVN_BINDIR@/svnadmin" with: # Path to svnlook utility svnlook = r"/usr/bin/svnlook" [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Get it</strong></p>
<p>first of all you need the best script ever made to backup subversion: the one provided with!</p>
<p>Get it here: <a href="http://svn.apache.org/repos/asf/subversion/trunk/tools/backup/hot-backup.py.in">http://svn.apache.org/repos/asf/subversion/trunk/tools/backup/hot-backup.py.in</a></p>
<p>This script needs to be modified</p>
<p>replace:</p>
<p><code lang="python"><br />
# Path to svnlook utility<br />
svnlook = r"@SVN_BINDIR@/svnlook"<br />
# Path to svnadmin utility<br />
svnadmin = r"@SVN_BINDIR@/svnadmin"<br />
</code></p>
<p>with:</p>
<p><code lang="python"><br />
# Path to svnlook utility<br />
svnlook = r"/usr/bin/svnlook"<br />
# Path to svnadmin utility<br />
svnadmin = r"/usr/bin/svnadmin"<br />
</code></p>
<p>or your appropriate svnlook and svnadmin path</p>
<p>Then you need to check that your user can modify files</p>
<p>once it&#8217;s verified let&#8217;s create a repository to store backup &#8216;/backup&#8217; for instance and create your directory structure there</p>
<p><strong>Test it</strong></p>
<p>test the whole stuff<br />
<code><br />
./hot-backup.py --archive-type=bz2 --num-backups=45 /svn/TEST_REPO/ /backup/subversion/test_repo/<br />
</code></p>
<p>you should get something like TEST_REPO-2.tar.bz2 (here minus 2 means revision n°2)</p>
<p><strong>Schedule it</strong></p>
<p>If you want to run it daily, put it in a cron such as a daily job</p>
<p>As I have multiple repositories here is my script</p>
<p><code lang="bash"><br />
#!/bin/bash<br />
NUMBACKUP=15<br />
for i in `ls /svn/`<br />
do<br />
        mkdir -p /backup/svn/$i<br />
        ./hot-backup.py --archive-type=bz2 --num-backups=$NUMBACKUP /svn/$i /backup/svn/$i<br />
done<br />
</code></p>
<p><strong>Restore it</strong></p>
<p>Ok that&#8217;s nice, you got a backup, but unless you can restore it, it&#8217;s useless!</p>
<p>So here is how to restore it:</p>
<ol>
<li>tar -xjvf /backup/svn/TEST/test-2.tar.bz2</li>
<li>cp -R /backup/svn/TEST/TEST-2/ /svn/TEST/</li>
</ol>
<p>and&#8230; that&#8217;s it</p>
<p>of course at the end of your backup script I recommend to move everything to another computer, because you will probably need it when disk crashes ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sbw.be/2010/10/07/subversion-backup-restore/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

