Vespolina: The Sandbox Story 4 – composer.json To The Rescue!

This post is about how to set up vespolina project using composer. It is intended mainly for people wanting to setup vespolina sandbox in a snap. When loading dependencies for a project, and in particular with vespolina sandbox which loads 15 vespolina bundles we want to have an easy and standard way of loading not just the vespolina bundles but also all the symfony2 dependencies. For that welcome to composer.

Before we proceed let’s install composer on your system. We don’t want to install it the regular trivial way but we want to set it up so that we can do PRs to the composer repo and help back. So we chose the development setup. The following sets development installation of composer on ubuntu 11.10 latest:

mkdir $HOME/composer
cd $HOME/composer
git clone https://github.com/composer/composer.git .
wget http://getcomposer.org/composer.phar
php composer.phar install
ln -s $HOME/composer/bin/composer /usr/bin/composer

With this we basically want to create a composer folder at the user home directory level, clone composer there, bring composer to build composer source code dependencies, then symlink the script under composer/bin to a default system wide /usr/bin/composer executable. This is a flexible setup indeed as it will let us run it simply in this way `composer [options]`.
If you are not of the same mind, you can find instructions for other types of installation setups here.

Now that we have our setup ready. We move into our project directory. And also create some helper scripts which we would want to PR composer with. These scripts basically remove the files/folders created by a composer run. The remove script is needed because sometimes we just mess with the dependencies writing the composer.json file and we need to start afresh. The remove script looks like this:

// remove.sh
rm -rf vendor composer.lock

Now we are ready to write our composer.json file. There are some gotchas and this is why I wrote this blog post.
The way to add requires to composer.json is to go check the availability on packagist.org and copy the vendor/package_name and do the inserts under require like:

{
    "autoload": {
        "psr-0": { "": "src/" }
    },
    "require": {
        "php": ">=5.3.2",
        "symfony/symfony": "2.1.0-dev",
        "vendor/package_name": "master-dev",

One can use the command `composer show package_vendor\package_name` in the same way. Be mindful that each package has requirement constraints assigned to packages that the package at hand depends on. If by chance it happens that the package that is depended upon does not match the constraint criteria then the package will not be installed and composer could choose to tell your or not to tell you depending on how bad is the conflict. You may have a successful build of the explicit dependencies but that means little. You will have cryptic errors until:

1. you manually impose the requires as above for the packages depended upon, or
2. you choose the version of package at hand that relaxes the requirements so that its dependency can get installed as well.

There can be a case where #2 above is impossible to meet for a current version or range, and that is more the developer community’s fault rather than yours :D. Worst case scenario is that you do things manually like I have indicated above.

Two things to keep in mind when writing your composer.json are: First, only bundles need a target-dir key to reproduce the path for their namespace. Second, libraries need PSR-0 key set indicating its top namespace and the root directory (lib, src, or whatever is the case) to ensure they can get loaded but libraries do not use a target-dir keyword.

After you have completed your composer.json it is time to make sure composer not only parses correctly but imports what it says it will import. The command that allows this test is:

composer install --dry-run --dev
composer install   // <--- this only when done!

The first command is a dry run to test what will happen. The second command is going to run it all the way.
Determining which dependencies did not load from the errors is simple, however it could also be challenging to the newbie just inferring the missing component. In order to troubleshoot further one should take a look at `installed.json` and `autoload_namespaces.php` under vendors directory (notice vendors directory can be configured by the top composer.json and you can read further on packagist.org). Looking at these two files can help you see what is wrong and back port it to your composer.json to make things work.

Once you have at least one composer.json working, even if you have to explicitly tell all dependencies into your composer.json file, you can take advantage of another more powerful tool. The tool is under the command `depends` and it will tell you what packages are affected by the package at hand and which is the required version of this package at hand:

~ composer depends symfony/symfony
friendsofsymfony/rest-bundle master-dev requires >=2.1.0-dev
doctrine/doctrine-fixtures-bundle master-dev requires >=2.0
snc/redis-bundle 1.0.1 requires >=2.0.4
secotrust/route-statistics-bundle master-dev requires >=2.0.4
doctrine/couchdb-odm-bundle master-dev requires 2.1-dev
loso/di-annotations-bundle 0.0.5-dev requires >=2.0.4
cedriclombardot/admingenerator-generator-bundle 1.0.0-BETA-dev requires >=2.0.0

This command is used to simplify our composer entries. If we go one by one, line by line on our requires and run the depends command on every package in each line and make sure to remove the line if we find that there is a package that is listed already on our composer.json that will import the package in the current line. If we do this operation we will simplify our composer.json to a few lines.

And as you can see it will give you which packages depends upon this package named. Of course that is somewhat helpeful (like the show command) so you don’t have to go online to packagist.org and check every package.
There is also a tool to check locally what packages and its versions are installed:

~ composer debug:packages --local
local: sonata/admin-bundle master-dev (9999999-dev)
local: vespolina/monetary-bundle master-dev (9999999-dev)
local: vespolina/ecommerce-flows-bundle master-dev (9999999-dev)
local: vespolina/workflow-bundle master-dev (9999999-dev)

Also this can help you further understand the dependencies and ensure we have installed all packages and its dependencies. If some package is missing from this list we know it was not imported by composer due to some internal error.

To avoid unnecessary repetitive downloads, we use the command `composer install –dry-run –dev`.
The process to debug an entry in a composer.json file is the following:

1. add one entry
2. run `composer install --dry-run --dev` and check the list of imported packages is correct
3. if yes then go to 1, else check dependencies, move down (remove to debug), or call it for the day.

In order to aid for huge composer files. We have come with the idea of clusters. Clusters of dependencies that can be grouped and pulled altogether with just one require line. In order to accomplish this we create a composer.json inside an empty project folder, push it to a github repository and then submit it to packagist and registered under vendor_name/cluster-other_name. The next step is just add the require line into our top and project level composer.json. An example of this approach follows:

{
    "name": "vespolina/vespolina-sandbox-composer",
    "type": "group-of-deps",
    "description": "Vespolina Bundles",
    "keywords": ["vespolina"],
    "homepage": "http://vespolina-project.org",
    "license": "MIT",
    "authors": [
        {
            "name": "Vespolina Team",
            "email": "cordoval@gmail.com"
        }
    ],
    "require": {
        "vespolina/store-bundle": "*",
        "vespolina/checkout-bundle": "*",
        "vespolina/product-bundle": "*",
        "vespolina/cart-bundle": "*",
        "vespolina/inventory-bundle": "*",
        "vespolina/taxonomy-bundle": "*",
        "vespolina/order-bundle": "*",
        "vespolina/customer-bundle": "*",
        "vespolina/pricing-bundle": "*",
        "vespolina/fulfillment-bundle": "*",
        "vespolina/merchandise-bundle": "*",
        "vespolina/taxation-bundle": "*",
        "vespolina/workflow-bundle": "*",
        "vespolina/ecommerce-flows-bundle": "*",
        "vespolina/monetary-bundle": "*"
    }
}

And inside our project’s composer.json we have the following require entry:

"vespolina/vespolina-sandbox-composer": "*",

There is a word of caution when creating packagist.org repositories for some old projects or projects that are not yet available on packagist.org. That word is to notify and PR the package maintainer to make its package available at packagsit.org. Then you will be able not just include it as a custom repository at the top composer.json level of your project, but you would just include a short require line which will import the package for you and will make your composer.json look much simpler. Right now–and probably always–composer does not resolve repositories recursively, it only does for dependencies available in packagist.org. So it is impossible for composer to resole ALL repositories in ALL packages before starting, and this is the intention of its creators. Therefore the best practice is to inform your package maintainers and to be patient. Do not create temporary repository or namespaces, not even in your namespace, this is not encouraged and will not be tolerated as it will break things for someone who may start depending on your package. Things can go bad for whoever depends on your package and you happen to delete it. So packagist.org is therefore for permanent evolving stuff.

This ends the first part of our series on vespolina and composer. Come back for more.

I thank the Lord Jesus Christ. And the opportunity to have received much help through helpful top guys like Stof, Seldaek, igorw, and asm89 and the developers of composer.

Symfony2 on PHP5.3, Python2.7, Node.js, Java, and what not on Shared Hosting

Sometimes one has too many privileges 😀
Yes so I needed to use less right on my sharedhosting. For that to work I had to install several things. My former hosting had just recently upgraded to php5.3 and only had available python2.4 because of this. I discovered one can install python2.7 latest easily on user space with some commands here. The need for python2.7 is that there is a node.js script for installation that was written on python2.7 or later and that it requires some json components, etc. That being said python2.7 was out of our way. We then moved to install node.js on user space too. We found some helpful commands here and completed our setup setting things on .bashrc on server.
Then in order to configure less we said:

// parameters.yml
parameters:
  node_path:         "/home/cordoval/bin/node"
  node_paths:        "/home/cordoval/bin/node_modules"
 
// config.yml
assetic:
    filters:
        less:
            node: %node_path%
            node_paths: [%node_paths%]

This setup was for local but the server side was similar. If you want like me a shared hosting that looks like VPS where you can do all sort of things with symfony2 (including deploying with capifony.org), well you can find more information here where I am an affiliate. Hope this is useful to you! I hunted for months for a hosting like this.

SPL Iterators Mixing

I found myself again standing in the shoulder of giants. I got some hints on how I would be able to mixin some of the features that several iterators interfaces and implementations were offering me. So here is the code:

These two examples below are usages for implementing similar things. I went for the first since it was what I wanted.

class PlayerCollection implements IteratorAggregate
{
    protected $players;
 
    public function __construct() {
        $this->players = new ArrayIterator();
    }
 
    public function add(Player $player) {
        $this->players[] = $player;
    }
 
    public function first() {
        return $this->players[0];
    }
 
    public function getIterator() {
        return new InfiniteIterator($this->players);
    }
}
 
$p1 = new Player("foo");
$p2 = new Player("bar");
$p3 = new Player("baz");
 
$pc = new PlayerCollection();
$pc->add($p1);
$pc->add($p2);
 
/*
foreach ($pc as $p) {
    echo $p->symbol;
}
*/
 
$pc->add($p3);
 
/*
foreach ($pc as $p) {
    echo $p->symbol;
}
*/
 
highlight_file(__FILE__);
<?php
 
$array = array(1, 2, 3);
$arr_it = new ArrayIterator($array);
 
$inf = new InfiniteIterator ($arr_it);
for ($i = 0; $i < 10; $i++) {
	echo $inf->current(); $inf->next(); 
}
 
echo "<br/><br/>";
 
// Add 4 to it
$arr_it[] = 4;
 
for ($i = 0; $i < 10; $i++) {
	echo $inf->current(); $inf->next(); 
}

Closured Iterator: The Secret While Twig Tag

Lately I was wanting to do a while loop on twig and did not know what to do. The need arose when developing a site with twig and wordpress. In order to overcome the difficulty I had to stand on the shoulders of @Seldaek and @igorw from the symfony dev community.

Explanation: Iterators are an extension of php which is packaged with SPL and is ready to use for php newbies (me). With this you can extend Iterator interface and you will gain iteration powers. The idea was that with these powers we could just pass the object to let it iterate as if it were a for loop. Our template would look like this already transformed:

{% for post in whilePosts %}
    // display post contents, title, etc.
{% endfor %}

Our approach will allow us to set every variable upon calling the_post and stuff. WordPress needs this else it goes crazy. If you happen to install say a plugin and try to just use objects and their properties without the magic of their wordpress hooks and stuff you are left on your own. This is the justification why implementing an iterator as follows.

The code that does the marvel follows. We basically inject two closures for valid and current into Iterator constructor and call their callable values upon return of each of the implemented methods.

    /* create iterator for loops */
    $whilePosts = new whileIterator(
                                    function() { return have_posts(); },
                                    function() { the_post(); return true; }
                                   );
 
class WhileIterator implements Iterator {
    public function __construct($valid, $current) {
        $this->validClosure = $valid;
        $this->currentClosure = $current;
    }
    public function valid() {
        return call_user_func($this->validClosure);
    }
    public function current() {
        return call_user_func($this->currentClosure);
    }
    public function next() {}
    public function rewind() {}
    public function key() {}
}

Edifying version of quote from Philippians 1:7-11 MSG follows:

7-8It’s not at all fanciful for me to think this way about you. My prayers and hopes have deep roots in reality. You have, after all, stuck with me all the way from the time I was thrown in jail, put on trial, and came out of it in one piece. All along you have experienced with me the most generous help from God. He knows how much I love and miss you these days. Sometimes I think I feel as strongly about you as Christ does!

9-11So this is my prayer: that your love will flourish and that you will not only love much but well. Learn to love appropriately. You need to use your head and test your feelings so that your love is sincere and intelligent, not sentimental gush. Live a lover’s life, circumspect and exemplary, a life Jesus will be proud of: bountiful in fruits from the soul, making Jesus Christ attractive to all, getting everyone involved in the glory and praise of God.

Symfony2 Integrated TDD: TestBundle

Introducing TestBundle[1], a Symfony2 bundle that integrates TDD methodology for the main frameworks Behat, PHPSpec, and PHPUnit into one development tool. It is created to foster the BDD methodology into Symfony2 app development.

Instructions to install:

// AppKernel.php
php new Cordova\Bundle\TestBundle\CordovaTestBundle(),
 
// autoload.php
    'Cordova'          => __DIR__.'/../vendor/bundles',
 
// deps
[PHPAutotest]
    git=https://github.com/Programania/PHPAutotest.git
    target=/PHPAutotest
[TestBundle]
    git=https://github.com/cordoval/TestBundle.git
    target=/bundles/Cordova/Bundle/TestBundle
 
// update
bin/vendors update
 
// creates autotest.phar
cd vendor/PHPAutotest
./compile

And here is its usage:

php app/console test:auto vendor/PHPAutotest/demo/Behat/features/minesweeper.feature

What can you do with it?
Well it depends how well one knows the integration of all the frameworks. Basically this bundle currently exploits PHPAutotest[2] and brings it into Symfony2 framework developers to foster new ways of automation and aid in the TDD task. There is a sweepminer’s example you can try and I am working on bringing more information into testing it with a complete integrated flow from start to end.

Contribute
If you have further ideas of how much more this bundle can include you are welcome to post below on the comments. And if you would like to boost development of this bundle then please donations are a strong motivation (see link above).

Praise the Lord Jesus Christ!

References:
[1] TestBundle Repository.
[2] PHPAutotest Tool Repository intro.