Continuous integration, Hudson and PHP Setting up under Ubuntu – PART 2

21 Feb

In the previous article about Hudson : Continuous integration, Hudson and PHP Setting up under Ubuntu – PART 1 we’ve correctly setup the server and got up fully functional and now comes the funny part : Installing the plugins and the PHP Tools to get all the needed reports.

I will use the php-hudson-template which can be found here, this template provides an easy way to get a proper project configuration and it’s much quicker than configuring every thing manually.

Okay let’s start !

Installing plugins

you’ll need to get the hudson-cli to do this, but you can do this using the Web frontend of hudson Server :

curl -c - -O http://[SERVER]:8080/jnlpJars/hudson-cli.jar

java -jar hudson-cli.jar -s http://[SERVER]:8080 install-plugin checkstyle
java -jar hudson-cli.jar -s http://[SERVER]:8080 install-plugin dry
java -jar hudson-cli.jar -s http://[SERVER]:8080 install-plugin htmlpublisher
java -jar hudson-cli.jar -s http://[SERVER]:8080 install-plugin jdepend
java -jar hudson-cli.jar -s http://[SERVER]:8080 install-plugin pmd
java -jar hudson-cli.jar -s http://[SERVER]:8080 install-plugin template-project
java -jar hudson-cli.jar -s http://[SERVER]:8080 install-plugin violations
java -jar hudson-cli.jar -s http://[SERVER]:8080 install-plugin xunit
java -jar hudson-cli.jar -s http://[SERVER]:8080 install-plugin clover

Installing PHP Tools


pear channel-discover pear.pdepend.org
pear channel-discover pear.phpmd.org
pear channel-discover pear.phpunit.de
pear channel-discover components.ez.no
pear channel-discover pear.symfony-project.com
pear install pdepend/PHP_Depend-beta
pear install phpmd/PHP_PMD-alpha
pear install phpunit/phpcpd
pear install PHPDocumentor
pear install PHP_CodeSniffer
pear install --alldeps phpunit/PHP_CodeBrowser-alpha
pear install --alldeps phpunit/PHPUnit

Getting the php-hudson-template

You’ll need to the hudson home, in my case it’s /var/lib/hudson and under jobs directory do :

git clone git://github.com/sebastianbergmann/php-hudson-template.git

after that you’ll have to change the owner and the group of the directory to let Hudson recognize it, this is very important !

chown -R hudson:hudson php-hudson-template

sudo /etc/init.d/hudson stop
sudo /etc/init.d/hudson start

Build.xml

this is an example of a standard build.xml file, but you’ll need to change executions options when needed, for example to change the code standard for Php checkstyle etc.

<project name="php-object-freezer" default="build" basedir=".">
 <target name="clean">
  <!-- Clean up -->
  <delete dir="build"/>

  <!-- Create build directories -->
  <mkdir dir="${basedir}/build/api"/>
  <mkdir dir="${basedir}/build/code-browser"/>
  <mkdir dir="${basedir}/build/coverage"/>
  <mkdir dir="${basedir}/build/logs"/>
  <mkdir dir="${basedir}/build/pdepend"/>
 </target>

 <!-- Run unit tests and generate junit.xml and clover.xml -->
 <target name="phpunit">
  <exec executable="phpunit" failonerror="true"/>
 </target>

 <!-- Run pdepend, phpmd, phpcpd, and phpcs in parallel -->
 <target name="parallelTasks">
  <parallel>
   <antcall target="pdepend"/>
   <antcall target="phpmd"/>
   <antcall target="phpcpd"/>
   <antcall target="phpcs"/>
   <antcall target="phpdoc"/>
  </parallel>
 </target>

 <!-- Generate jdepend.xml and software metrics charts -->
 <target name="pdepend">
  <exec executable="pdepend">
   <arg line="--jdepend-xml=${basedir}/build/logs/jdepend.xml ./«  />
  </exec>
 </target>

 <!-- Generate pmd.xml -->
 <target name="phpmd">
  <exec executable="phpmd">
   <arg line="./ xml codesize,unusedcode
              --reportfile ${basedir}/build/logs/pmd.xml" />
  </exec>
 </target>

 <!-- Generate pmd-cpd.xml -->
 <target name="phpcpd">
  <exec executable="phpcpd">
   <arg line="--log-pmd ${basedir}/build/logs/pmd-cpd.xml ./" />
  </exec>
 </target>

 <!-- Generate checkstyle.xml -->
 <target name="phpcs">
  <exec executable="phpcs" output="/dev/null">
   <arg line="--report=checkstyle
              --report-file=${basedir}/build/logs/checkstyle.xml
              --standard=Zend
              ./" />
  </exec>
 </target>

 <!-- Generate API documentation -->
 <target name="phpdoc">
  <exec executable="phpdoc">
   <arg line="-d ./ -t build/api" />
  </exec>
 </target>

 <target name="phpcb">
  <exec executable="phpcb">
   <arg line="--log    ${basedir}/build/logs
              --source ${basedir}/./
              --output ${basedir}/build/code-browser" />
  </exec>
 </target>

 <target name="build" depends="clean,parallelTasks,phpunit,phpcb"/>
</project>

Now the question that you should ask is : where to put this file ??? well it depends on your needs ..
for example when you will get source code from SVN the simpliest way is to add it into the root of your code.

it’s important to have the build.xml reachable by the hudson server ..

Final configuration

Now go back to the web interface of the hudson server, and choose New Job > free-style software project
Choose your Source code management : SVN or Git etc.
Under Build: click Add build Step -> Invoke Ant
Under Post-build Actions : click Use publishers from another project and write : “php-hudson-template
Hit Save.

Then Click Build Now

Enjoy !

Be Sociable, Share!

IPhone, casting a string as hex representation of an integer

11 Feb

Recently i have found a nice routine that convers hex color to UIColor objects to be used on UIComponents : http://cocoamatic.blogspot.com/2010/07/uicolor-macro-with-hex-values.html

but i was confronted to a little problem, the given colors are Strings and the routine only works with hex representation of integers. So this is a little trick to make the conversion :

unsigned int hexSeparatorColor;
NSScanner *scanner = [NSScanner scannerWithString:@"0xFF0000"];
[scanner scanHexInt:&hexSeparatorColor];
[scanner release];

hexSeparatorColor will contain the hex representation of the casted string !

Be Sociable, Share!

IPhone, synchronous and asynchronous JSON Parse

31 Jan

A common need in Iphone or mobile applications is to get remote Data using JSON servers. In this post i will speak about the two possibilies : Synchronous and Asynchronous calls and how to deserialise JSON Data with JSON Framework for Objective-C.

So you will need to import the class files of the JSON Framework into your project first.

Synchronous Call

responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost/json"]];
NSURLResponse *response = nil;
NSError *error = nil;
//getting the data
NSData *newData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//json parse
NSString *responseString = [[NSString alloc] initWithData:newData encoding:NSUTF8StringEncoding];
NSDictionary *jsonObject = [responseString JSONValue];
//Accessing JSON content
NSLog(@"type :  %@", [jsonObject objectForKey:@"Type"] );

Some explanations :

- response is the url response for the json call

- error is error returned by NSURLConnection

- newData is data returned by the server

Notice that you can cast the JSON deserialized data into a NSDictionnary or an NSMutuableArray.

ASynchronous Call

To make an Asynchronous call we’ll need to use NSURLConnection with initWithRequest method, then we need to implement differents other methods to handle the finish of data loading, error handling etc.

//in the viewDidLoad
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost/json"]];//asynchronous call
[[NSURLConnection alloc] initWithRequest:request delegate:self];

Implementing delegate methods :

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    NSLog(@"%@", error);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
    [responseData release];
    NSDictionary *jsonObject = [responseString JSONValue];
    NSLog(@"type :  %@", [jsonObject objectForKey:@"Type"] );
    [connection release];
}
Be Sociable, Share!

Extjs 4

19 Nov

Ed Spencer Software Architect at Sencha has post today the slides about “introduction to Extjs 4″ presentation made for the senchacon.



Many features like :

  • Speed
  • Stability
  • Simpler configuration
  • MVC
  • etc.

The release date is for the 28 february.

Be Sociable, Share!

CouchDB, Validation functions

18 Nov

The last CouchDB post was about Design Documents, and we described how it’s possible to create views directly on it. Now this post is about another part of Design Documents and it’s fundamental on a CouchDB project context.

We already know that CouchDB is a schema free document oriented database, this means that there are no constraints when we create / update documents ! now let’s imagine that every user of the CouchDB application can create any kind of document with what he wants .. we need to deal with data consistency and for that we’ll need Validation Functions !

The Validation Function definition :

It’s important to know that Validation functions are optional, if you don’t define them there will be no check. Also validation functions are stored on the Design Document under the “validate_doc_update” field.

  function(newDoc, oldDoc, userCtx) {}
  • newDoc is for the incoming document.
  • oldDoc is the current saved document.
  • userCtx the user object doing the request.

Now let’s try to add a validation function to a design document, what you need is to open Futon then :

choose a database > view “Design documents” > Choose a design

Now edit the document and add this at the end of document defintion :

"validate_doc_update": "function(newDoc, oldDoc, userCtx) {
  throw({forbidden : 'you are not allowed !'
});}"

You will get something like this (you’ll need to save the document) :

couchDb validation function

Okey now let’s try to create an new document using Curl :

curl -X PUT http://127.0.0.1:5984/contacts/contactValidation -d '{"name" : "contact validation"}'
//return
{"error":"forbidden","reason":"you are not allowed !"}

Et voilà ! the validation function has thrown an exception and no more document creation / update is possible ! now lets tune it a little bit. We are using a contact database so we’ll not permit creation of document without name, and phone fields :

function(newDoc, oldDoc, userCtx) {
   function require(field){
      var message = field + ' is required';
      if(!newDoc[field]){
         throw({'forbidden':message})
      }
   }
   require('name');
   require('phone')}

Okey let’s try again with curl :

curl -X PUT http://127.0.0.1:5984/contacts/contactValidation -d '{"name" : "contact validation"}'
{"error":"forbidden","reason":"phone is required"}

And now we add required fields :

curl -X PUT http://127.0.0.1:5984/contacts/contactValidation -d '{"name" : "contact validation", "phone":"123-1111"}'
{"ok":true,"id":"contactValidation","rev":"1-8330cb19d688702b4c24e3ae468f31f2"}

And it’s working ! as you can see it’s simple to check document consistency with simple javascript tests ! Hope you like this post.

Be Sociable, Share!

CouchDB, Design Documents

11 Nov

In this post i will try to talk about another concept of CouchDb “Design Documents” ( you can read the last post that i wrote about CouchDB views it will be a reference for the rest of this content)

So what are Design Documents ?? in the last tutorial we created temporary views then we stored them into permanent views. These views are stored on a special document called Design Document ! Let’s see what we have on futon :

You have to go to : contact database  > then choose View “Design Documents” :

Then choose “_design/contacts” :

You will notice that also a design Document is a Document ! Let’s explain what we have here :

language : is the language used for the views, usually it’s Javascript but in the latest Versions of CouchDB you can use Erlang.

views : contains all the views included with the contact document, and for every view you can find the map and reduce functions :

{
   "_id": "_design/contacts",
   "_rev": "1-a8487fd2a8b3698a19a5ae6dd59b178d",
   "language": "javascript",
   "views": {
       "phones": {
           "map": "function(doc) {
              if(doc.phone){
                  temit(doc._id, doc.phone);
              }
           }"
       }
   }
}

Creating permanent Views using Curl

We already know how to execute a view using curl :

curl -X GET http://127.0.0.1:5984/contacts/_design/contacts/_view/phones

Now we will try to create a new view to get “contact names”, so first of all we need to create our new Design Document :

{
  "language" : "javascript",
  "views" : {
    "contact_names" : {
      "map" : "function(doc){
         emit(doc._id, {Name : doc.firstName});
      }"
    }
  }
}

As you can see the json document have the same structure of the first Design Document.
Now let’s tell Couch to add our new json definition :

curl -X PUT http://127.0.0.1:5984/contacts/_design/new_design -d @new_design.json

will return :

{"ok":true,"id":"_design/new_design",
    "rev":"1-485e1a6b2ab85442744a994da51eb9c0"}

Now to call the new view :

curl -X GET http://127.0.0.1:5984/contacts/_design/new_design/_view/contact_names

getting :

{"total_rows":2,"offset":0,"rows":[
  {"id":"joelennon","key":"joelennon","value":{"Name":"Joe"}},
  {"id":"johnsmith","key":"johnsmith","value":{"Name":"John"}}
]}

That’s all ! hope you enjoy using CouchDB :)

Be Sociable, Share!

JQuery, Duplicate form items with .clone()

2 Nov

Assuming that we have a dynamic form creation, where we need to add as many form items as we need, the problem is that when we duplicate items we’ll get the same input names ..

So this is my own solution to this problem but if you have other methods don’t hesitate to share ^^

This is out form element to duplicate :

<ul >
    <div class="toClone">
        <li id="li_1" >
            <label for="element_1">Name </label>
            <div>
                <input name="name" type="text" maxlength="255" value=""/>
            </div>
        </li>
        <li id="li_2" >
            <label for="element_2">Surname </label>
            <div>
                <input  name="surname" type="text" maxlength="255" value=""/>
            </div>
        </li>
    </div>
...

And this is the js, assuming that we have already set a button to add the cloned content :

counter = 0;
$('#addButton').live('click', function(){
  counter ++;
  cloned = $('.toClone').first().clone();
  cloned.find('input[type=text]').each(function(){
     name = $(this).attr('name').split('_');
     (this).attr('name', name[0] + '_' + counter);

   });
   // path to parent element.
   cloned.prependTo($(this).parent().parent() ... );
});
Be Sociable, Share!

Sencha, My First iphone application

27 Oct

Here we are, Iphone application development  is being more and more easier for web developers, all you have to know is Javascript, html and Css .. 

Sencha is a HTML5 Mobile web application framework .. in other words it simplify creation of mobile application using HTML5 features.

In this article i will try to list all the tweets where the keyword  “hbensalem” exists, i’m using Twitter Api and search.twitter.com.

Setting the project

First of all you’ll need to download sencha-touch from Sencha website.

Then create a html file with this content :

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Sencha</title>
        <!-- Sencha Touch CSS -->
        <link rel="stylesheet" href="./sencha-touch/resources/css/sencha-touch.css" type="text/css">
        <!-- Sencha Touch JS -->
        <script type="text/javascript" src="./sencha-touch/ext-touch-debug.js"></script>
        <!-- Application JS -->
        <script type="text/javascript" src="index.js"></script>
        <style>
            .tweet {
                border-bottom: 1px solid #EEEEEE;
                margin: 0;
                overflow: hidden;
                padding: 15px 5px;
                background-color: grey
            }

            .avatar {
                float: left;
                height: 50px;
                overflow: hidden;
                width: 50px;
            }
            .tweet-content {
                font-size: 16px;
                line-height: 17px;
                margin-bottom: 2px;
                margin-left: 58px;
            }
        </style>
    </head>
    <body></body>
</html>

We need to pay attention to :

  • sencha-touch.css
  • ext-touch-debug.js

Building the application “script.js”

Ext.setup({
    tabletStartupScreen: 'tablet_startup.png',
    phoneStartupScreen: 'phone_startup.png',
    icon: 'icon.png',
    glossOnIcon : false,
    onReady: function() {

        var timeline = new Ext.Component({
            title: 'Timeline for hbensalem',
            cls: 'timeline',
            scroll: 'vertical',
            tpl: [
                '<tpl for=".">',
                    '<div class="tweet">',
                            '<div class="avatar"><img src="{profile_image_url}" /></div>',
                            '<div class="tweet-content">',
                                '<h2>{from_user}</h2>',
                                '<p>{text}</p>',
                            '</div>',
                    '</div>',
                '</tpl>'
            ]
        });

        var panel = new Ext.TabPanel({
            fullscreen: true,
            items: [timeline]
        });

        var reader =  Ext.util.JSONP.request({
                url: 'http://search.twitter.com/search.json',
                callbackKey: 'callback',
                params: {
                    q: 'hbensalem'
                },
                callback: function(data) {
                    data = data.results;
                    timeline.update(data);
                }
            });
    }
});

Some explanations :

Timeline is the component who deals with data from JSON request, the tpl section is for Template, data content is parsed and every token is replaced by the good value.

Panel : is the main container.

Reader : is the JSON reader, we told him where to search and we passed the query. Callback function is called when the loading of request is finished.

And this is the result :

Source and further reading :
http://dev.sencha.com/deploy/touch/getting-started.html

Be Sociable, Share!

Raphael js, Drawing a funny monster

25 Oct

When i was young i discovered that it’s possible to draw using Qbasic language .. So i passed all my time exploring circles, lines sprites and etc. Now the web is populated by great tools for simple and complex graphics, Rapahel is one of them.

Raphael is a javascript library for vectorial graphics, but it can also be used to make nice animations and it is using SVG.

In this tutorial i will try to explain how to draw a funny monster face (which looks like Domo) view Demo , or Download source files.

So first of all you’ll need to download raphael js library and create a simple html file :

Setting up

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title>Domo like</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script src="raphael.js"></script>
        <script>
            window.onload = function(){
                var paper = Raphael("canvas", 640, 480);
            }

        </script>
    </head>
    <body>
        <div id="canvas"></div>
    </body>
</html>

The important thing is “paper” value which is the raphale object :

 var paper = Raphael("canvas", 640, 480);

1 . drawing the head and the mouth :

var head = paper.rect(180, 50, 320, 340, 15);
head.attr({
    'stroke-width' : 6,
    'fill' : '15-#AA0000-#511'
});
mouth = paper.rect(200, 150, 240, 200, 5);

mouth.attr({
    'stroke-width' : 10,
    'fill' : '#000'
})

This code will give us :

2. Adding eyes and tongue

var eyes = paper.set();

eyes.push(
    paper.rect(200, 100, 15, 10, 5),
    paper.rect(410, 100, 35, 20, 5)
);

eyes.attr({
    'stroke-width' : 10,
    'fill' : '#000'
});
tongue = paper.ellipse(350, 310, 60, 20);
tongue.attr({
    'stroke-width' : 3,
    'fill' : '#FF0000'
});

Result :

3. Adding teeth

Okey our little monster needs some teeth we’ll use loops to draw em.

teeth = paper.set();

for(i=200; i<= 420; i+=20){
    teeth.push(paper.rect(i, 150, 20, 70 , 5));
    teeth.push(paper.rect(i, 310, 20, 40, 5));
}

teeth.attr({
    'fill' : '#FFFFFF'
})

Final Result :

Et voilà ! Hope you like the result ! ^^

View Demo Download
 
   
Be Sociable, Share!

CouchDb, Creating views

21 Oct

The first couchDb tutorial that i’ve wrote was about simple operations like creating, updating or deleting documents, in this post i will explain how to create views, and how to call them ;

Creating views

The simplest way to create views is to use “Futon” (the phpmyadmin like for couchDb) accessible via :

http://localhost:5984/_utils/

And if everything is ok we should have something like this :

Then choose database where to create View, then on the select box in front of ‘View‘ select ‘Temporary view‘ :

When you click run button :

the last time we have created database called ‘contacts‘ with documents having this structure :

{
   "_id": "johnsmith",
   "_rev": "3-94052866ba060f57508fde265a243b47",
   "firstName": "John",
   "lastName": "Smith",
   "email": [
       "johnsmith@example.com"
   ],
   "phone": "(555) 555-5555"
}

The default function to show database content is :

function(doc) {
  emit(null, doc);
}

And when you hit run it will display all entries from the database “contact“, know let’s try to get contacts with a specific criteria, for example : “all contacts having a phone number” :

function(doc) {
  if(doc.phone){
	emit(doc._id, doc.phone);
  }
}

As result :

Saving the temporary view

Okey now that we are satisfied of the result let’s save the temporary view a permanent one :

  1. Click “Save As” button
  2. Set a design Name
  3. Set a view Name

That’s all ! our view will be accessible from the “View” Select Box :

Getting view result with curl

To query the server will use curl :

curl -X GET http://127.0.0.1:5984/contacts/_design/contacts/_view/phones

Result :

{"total_rows":1,"offset":0,"rows":[
  {"id":"johnsmith","key":"johnsmith","value":"(555) 555-5555"}
]}

Some explanations about params passed to curl :
- First argument “contact” is database name
- Second argument “_design” with value “contacts” is the design name that we have set when we saved the view
- Third argument “_view” with value “phone” is simply the view name

We can also pass other params at the end to tell the server how many entries to return, or to order them :

curl -X GET http://127.0.0.1:5984/contacts/_design/contacts/_view/phones?limit=11&descending=true

Hope this was helpful to understand how to create simple views with couchDb.

Be Sociable, Share!