Design pattern decorator

<?php
 
interface IDecorator {
    public function decorate();
}
 
abstract class Decorator implements IDecorator {
    protected $_toDecorate;
 
    public function __construct(IDecorator $toDecorate) {
        $this->_toDecorate = $toDecorate;
    }
}
 
class Html implements IDecorator {
    protected $_str;
 
    public function __construct($str) {
        $this->_str = $str;
    }
 
    public function decorate() {
        return $this->_str;
    }
}
 
class Strong extends Decorator {
    public function decorate() {
        return '<strong>'.$this->_toDecorate->decorate().'</strong>';
    }
}
 
class Em extends Decorator {
    public function decorate() {
        return '<em>'.$this->_toDecorate->decorate().'</em>';
    }
}
 
 
$html = new Html('text to decorate');
 
$decorate = new Strong($html);
$decorated = $decorate->decorate();
echo $decorated.PHP_EOL;
 
$decorate = new Em($html);
$decorated = $decorate->decorate();
echo $decorated.PHP_EOL;
 
$decorate = new Strong(new Em($html));
$decorated = $decorate->decorate();
echo $decorated.PHP_EOL;

Install node.js and npm quickly

node.js

go on nodejs.org
download source

tar -xvzf node-v0.6.15.tar.gz
cd node node-v0.6.15/
./configure
make
make test
make doc
sudo make install

npm

wget http://npmjs.org/install.sh
sudo bash install.sh
 
tar=/bin/tar
version:
tar (GNU tar) 1.25
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
 
Written by John Gilmore and Jay Fenlason.
install npm@1.1
fetching: http://registry.npmjs.org/npm/-/npm-1.1.18.tgz
0.6.15
1.1.18
cleanup prefix=/usr/local
 
All clean!
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
npm@1.1.18 /usr/local/lib/node_modules/npm
It worked
npm install socket.io

Symfony2 preExecute Controller

Listener/PublisherListener.php

<?php
namespace Main\PublisherBundle\Listener;
 
use Symfony\Component\EventDispatcher\Event; 
use Symfony\Component\HttpKernel\HttpKernelInterface; 
use Symfony\Component\HttpKernel\Event\FilterControllerEvent; 
 
class PublisherListener {
 
    public function onCoreController(FilterControllerEvent $event) {
        if(HttpKernelInterface::MASTER_REQUEST == $event->getRequestType()) {
            $_controller = $event->getController();
            if(isset($_controller[0])) {
                $controller = $_controller[0];
                if(method_exists($controller, 'preExecute')) {
                    $controller->preExecute();
                }
            }
        }
    }
}

Resources/config/services.xml

<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
 
    <parameters>
        <parameter key="main_publisher.listener.class">Main\PublisherBundle\Listener\PublisherListener</parameter>
    </parameters>
 
    <services>
        <service id="main_publisher_listener" class="%main_publisher.listener.class%">
            <tag name="kernel.event_listener" event="kernel.controller" method="onCoreController"/>
        </service>
    </services>
</container>

Controller/PublisherController.php

<?php
namespace Main\PublisherBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
 
class GamesController extends Controller {
   public function preExecute() {
        $this->gameManager = $this->container->get('main_publisher.game.manager');
        $this->userManager = $this->container->get('main_user_manager');
    }
}

symfony2 twig i18n date

sudo aptitude install php5-intl

app/config/config.yml

services:
    twig.extension.intl:
       class: Twig_Extensions_Extension_Intl
       tags:
           - { name: twig.extension }

In twig template

{{ game.created_at| localizeddate('full', 'none') }}

twig macro link title translation

{% macro link(route, title, name, attr) %}
{% spaceless %}
<a href="{{ path(route) }}" title="{{ title|trans({}, 'link') }}"{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor %}>{{ name|trans({}, 'link') }}</a>
{% endspaceless %}
{% endmacro %}
 
<!-- Usage 
{{ macro.link('route_name', 'link title', 'link name', {'class':'css_class'}) }}
-->
 
<!-- HTML
<a href="/dashboard" title="Manage" class="pouet">Manage</a>
-->

jenkins for php project

read http://jenkins-php.org/

aptitude install jenkins
#!/bin/bash
host="http://jenkins.domain.tld:8080"
 
wget $host/jnlpJars/jenkins-cli.jar
java -jar jenkins-cli.jar -s $host install-plugin checkstyle
java -jar jenkins-cli.jar -s $host install-plugin cloverphp
java -jar jenkins-cli.jar -s $host install-plugin dry
java -jar jenkins-cli.jar -s $host install-plugin htmlpublisher
java -jar jenkins-cli.jar -s $host install-plugin jdepend
java -jar jenkins-cli.jar -s $host install-plugin plot
java -jar jenkins-cli.jar -s $host install-plugin pmd
java -jar jenkins-cli.jar -s $host install-plugin violations
java -jar jenkins-cli.jar -s $host install-plugin xunit
java -jar jenkins-cli.jar -s $host install-plugin phing
java -jar jenkins-cli.jar -s $host safe-restart
#!/bin/bash
pear upgrade PEAR
pear config-set auto_discover 1
pear install pear.phpqatools.org/phpqatools pear.netpirates.net/phpDox
cd $JENKINSHOME/jobs
git clone git://github.com/sebastianbergmann/php-jenkins-template.git php-template
chown -R jenkins:nogroup php-template/

in $JENKINSHOME/jobs/$PROJECT/workspace/build.xml for phing

<project name="project" default="build" basedir=".">
    <property name="basedir" value="${project.basedir}" />
    <property name="source" value="${basedir}/src"/>
 
    <target name="clean" description="Clean up and create artifact directories">
        <delete dir="${basedir}/build/api"/>
        <delete dir="${basedir}/build/code-browser"/>
        <delete dir="${basedir}/build/coverage"/>
        <delete dir="${basedir}/build/logs"/>
        <delete dir="${basedir}/build/pdepend"/>
 
        <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>
 
    <target name="phpunit" description="Run unit tests using PHPUnit and generates junit.xml and clover.xml">
        <exec logoutput="true"
            command="phpunit --configuration=${basedir}/app/phpunit.xml.dist --log-junit=${basedir}/build/logs/junit.xml --coverage-clover=${basedir}/build/logs/clover.xml" />
    </target>
 
    <target name="parallelTasks" description="Run the pdepend, phpmd, phpcpd, phpcs, phpdoc and phploc tasks in parallel using a maximum of 2 threads.">
        <phingcall target="pdepend"/>
        <phingcall target="phpmd"/>
        <phingcall target="phpcpd"/>
        <phingcall target="phpcs"/>
        <phingcall target="phpdoc"/>
        <phingcall target="phploc"/>
    </target>
 
    <target name="pdepend" description="Generate jdepend.xml and software metrics charts using PHP_Depend">
        <exec logoutput="true"
            command="pdepend --jdepend-xml=${basedir}/build/logs/jdepend.xml --jdepend-chart=${basedir}/build/pdepend/dependencies.svg --overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg ${source}" />
    </target>
 
    <target name="phpmd" description="Generate pmd.xml using PHPMD">
        <exec logoutput="true" spawn="true"
            command="phpmd ${source} xml codesize,design,naming,unusedcode --reportfile ${basedir}/build/logs/pmd.xml" />
    </target>
 
    <target name="phpcpd" description="Generate pmd-cpd.xml using PHPCPD">
        <exec logoutput="true"
            command="phpcpd --log-pmd ${basedir}/build/logs/pmd-cpd.xml ${source}" />
    </target>
 
    <target name="phploc" description="Generate phploc.csv">
        <exec logoutput="true"
            command="phploc --log-csv ${basedir}/build/logs/phploc.csv ${source}" />
    </target>
 
    <target name="phpcs" description="Generate checkstyle.xml using PHP_CodeSniffer">
        <exec logoutput="true"
            command="phpcs --report=checkstyle --report-file=${basedir}/build/logs/checkstyle.xml --standard=Zend ${source}" />
    </target>
 
    <target name="phpdoc" description="Generate API documentation using PHPDocumentor">
        <exec logoutput="true"
            command="phpdoc -d ${source} -t ${basedir}/build/api" />
    </target>
 
    <target name="phpcb" description="Aggregate tool output with PHP_CodeBrowser">
        <exec logoutput="true"
            command="phpcb --log ${basedir}/build/logs --source ${source} --output ${basedir}/build/code-browser" />
    </target>
 
    <target name="build" depends="clean,parallelTasks,phpunit,phpcb"/>
 
</project>

now run phing in $JENKINSHOME/jobs/$PROJECT/workspace/

Symfony2 service + manager

Resources/config/services.xml

<?xml version="1.0" ?>
 
<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
 
    <parameters>
        <parameter key="main_publisher.game.manager.class">Main\PublisherBundle\Manager\GameManager</parameter>
    </parameters>
 
    <services>
        <service id="main_publisher.game.manager" class="%main_publisher.game.manager.class%">
            <argument type="service" id="doctrine.orm.entity_manager" />
        </service>
    </services>
</container>

Manager/BaseManager.php

<?php
namespace Main\PublisherBundle\Manager;
 
class BaseManager {
 
    protected function persistAndFlush($entity) {
        $this->_em->persist($entity);
        $this->_em->flush();
    }
 
}

Manager/GameManager.php

<?php
namespace Main\PublisherBundle\Manager;
 
use Doctrine\ORM\EntityManager;
use Main\PublisherBundle\Manager\BaseManager;
use Main\PublisherBundle\Entity\Game;
 
class GameManager extends BaseManager {
    protected $_em;
 
    public function __construct(EntityManager $em) {
        $this->_em = $em;
    } 
 
    public function save(Game $game) {
        return $this->persistAndFlush($game);
    }
 
    public function getRepository() {
        return $this->_em->getRepository('MainPublisherBundle:Game');
    }
}

Controller/GamesController.php

<?php
 
namespace Main\PublisherBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
 
use Main\PublisherBundle\Entity\Game;
use Main\PublisherBundle\Form\GameType;
 
class GamesController extends Controller
{
    public function newAction(Request $request) {
        $form = $this->createForm(new GameType(), new Game());
        if($request->getMethod() == 'POST') {
            $form->bindRequest($request);
            if($form->isValid()) {
                $game = $form->getData();
                $manager = $this->container->get('main_publisher.game.manager');
                $manager->save($game);
                return $this->redirect($this->get('router')->generate('homepage'));
            }
 
        }
        return $this->render('MainPublisherBundle:Games:new.html.twig',
            array('form' => $form->createView()));
    }
}

Mysql subquery

Database

CREATE TABLE IF NOT EXISTS `author` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
 
INSERT INTO `author` (`id`, `name`) VALUES
(1, 'HiO'),
(2, 'Blu'),
(3, 'Pouet');
 
CREATE TABLE IF NOT EXISTS `post` (
  `a_id` INT(10) UNSIGNED DEFAULT NULL,
  `title` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
INSERT INTO `post` (`a_id`, `title`) VALUES
(1, 'My name is HiO :)'),
(NULL, 'I am an anonymous :)'),
(2, 'My name is Blu :D'),
(3, 'My name is Pouet ><''');

Subquery

SELECT *, (SELECT COUNT(post.a_id) FROM post WHERE post.a_id = author.id) AS post_count FROM `author`

Result

$author = array(
  array('id'=>'1','name'=>'HiO','post_count'=>'1'),
  array('id'=>'2','name'=>'Blu','post_count'=>'1'),
  array('id'=>'3','name'=>'Pouet','post_count'=>'1')
);

Subquery in where clause

SELECT * FROM `post` WHERE a_id IN (SELECT id FROM author)

Result

$post = array(
  array('a_id'=>'1','title'=>'My name is HiO :)'),
  array('a_id'=>'2','title'=>'My name is Blu :D'),
  array('a_id'=>'3','title'=>'My name is Pouet ><\'')
);