ResourceWatcher: The Component They Will Not Tell You About – Part I

Problem to solve

The problem that this component solves is when we have a system of files and folders that we want to watch for any
actions and react accordingly upon specific actions. Actions can be creation, edition, moving or removing. Upon each
action there could be a need to perform a specific re-action therefore the need for events and callbacks.


Architecture

The way ResourceWatcher component is implemented to solve the problem is via main object resource watcher, a tracker
object, some resources objects to be tracked, events objects fired depending on what action happens on these resources,
generic event listeners already built-in to listen to the events fired when resources are acted upon, and state checkers
for these resources which will aid in discerning the state of a particular resource. Currently there are three types of
instances when we can react or types of events, namely: (when resource is) Created, Modified, or Deleted.

ResurceWatcher class can receive any custom tracker object that suits the developer, however the component comes with
two implementations of tracker ready to be used as sensitive defaults. In other words, if custom tracker is not provided
then the resource watcher will use an InotifyTracker or RecursiveIteratorTracker implementation. Once a tracker has been
specified and a watcher has been built with it then the next step is to determine what resources we want to track.

Usage

Example using ResourceWatcher with a custom tracker explicitly set, with folder `src` as resource and it will output on
console the name of the file being acted upon checking every microsecond within the 10000 first microseconds:

    use Symfony\Component\ResourceWatcher\ResourceWatcher;
    use Symfony\Component\ResourceWatcher\Tracker\InotifyTracker;
    use Symfony\Component\Config\Resource\DirectoryResource;
 
    $tracker = new InotifyTracker();
    $watcher = new ResourceWatcher($tracker);
    $resource = new DirectoryResource(realpath(__DIR__.'/../src'));
    $callBack = function ($event) {
                    $fileName = (string) $event->getResource();
                    echo $fileName;
                };
    $watcher->track($resource, $callBack);
    $watcher->start(1, 10000);

Example using ResourceWatcher using default sensitive tracker, lame callback and single file as resource, checking every
microsecond for a time limit of 1 microsecond, and finally making sure it stops tracking resource right after.

    use Symfony\Component\ResourceWatcher\ResourceWatcher;
    use Symfony\Component\Config\Resource\FileResource;
 
    $watcher = new ResourceWatcher();
    $cb = function(){};
    $resource = new FileResource('demo.txt');
    $watcher->track($resource, $cb);
    $watcher->start(1, 1);
    $watcher->stop();

Today I have PR’ed the symfony-docs repo with documentation that is based on a experimental branch from @everzet here.

Thanks my forgiving Lord Jesus for this excitement of documenting this very interesting piece of code! I am so excited about working with this piece of code.

Symfony2: Human Readable Configuration

When integrating bundles from other repositories into our project we would like to have an easy way to get a defacto configuration of the bundle at hand. We could either go jump on github and try to guess the configuration from the `Configuration.php` file within the bundle, but why bother since we have the great and new command `php app/console config:dump-reference NameOfBundle` this can be invoked to display the yml version of a sample default configuration for that given bundle.

By looking at the result of the command we can find out about the available settings in a more human readable fashion. Besides the typical default and mandatory configuration flags there is new information set through methods like *setExample* and *setInfo* which will enrich our `Configuration.php` bundle configuration file used like in the example below:

->scalarNode('access_denied_url')->defaultNull()->setExample('/foo/error403')->end()
->scalarNode('session_fixation_strategy')->cannotBeEmpty()->setInfo('strategy can be: none, migrate, invalidate')->defaultValue('migrate')->end()

If you don’t know what argument to pass or are just exploring you can easily call `php app/console container:debug` to get their service names with which to call the `config:dump-reference` command. Providing human readable default configurations for the users of our bundle will boost its quick usage and adoption.

PSSMockeryBundle + PHPSpec: The Automation Of Mocking Services Begins!

Let’s say we want to spec a service we are trying to design and we want to use PHPSpec in order to do that.
Our system runs supported by the Symfony2 Components/Framework and according to the rules of the Dependency Injection game we have a client running the application from where we can get all the services of the project the container holds.
Since our service is meant to live within this “Sitz im Leben” or context and would need some interaction with other services we would like to develop the service classes right without leaving at any time this environment.

Welcome to PSSMockeryBundle world. Thanks to Jakub Zalas creator of PSSMockeryBundle, we have something that was meant to solve the problem indicated above by setting up a base class for the container in which we can easily mock any service on the container. Tie this with PHPSpec and you are about to discover a framework setup in which anyone can easily start creating, stubbing, mocking and perfecting their service design for their bundles and craft carefully their dependencies on other services.

<?php
namespace Acme\DemoBundle\Spec\Model;
 
use Symfony\Bundle\FrameworkBundle\Spec\WebSpec;
use Acme\DemoBundle\Model\MyService;
use Twig_Environment;
 
class DescribeMyService extends WebSpec
{
    protected $container;
    protected $client;
    protected $serviceUnderSpec;
 
    public function before()
    {
        $this->client = self::createClient();
        $this->container = $this->client->getContainer();
        $this->serviceUnderSpec = $this->spec(new MyService($this->container));
    }
 
    /**
     * Specking MyService class mocking another service directly related
     */
    public function itShouldGetCreateDirectoryUsingFileSystemServiceFromContainer()
    {
        $filesystemMock = $this->container->mock('filesystem', 'Symfony\Component\Filesystem\Filesystem');
        $filesystemMock->shouldReceive('mkdir')->once()->andReturn(true);
 
        $this->serviceUnderSpec->methodUsingFileSystem()->should->beTrue();
    }
 
    /**
     * Specking MyService method that uses the router service
     * we do not mock the routing but we do mock the Twig_Environment service
     * used by the router
     */
    public function itShouldIndirectlyMockServiceTheRouterDependsOn()
    {
        $twigEnvironmentMock = $this->container->mock('twig','\Twig_Environment');
        $this->serviceUnderSpec->methodUsingRouter()->should->be('/');
    }
}

We first have created a Spec class to speck our new service `MyService` non-existent at this time. The idea is to write one example method at a time. Here we have just gone ahead and written the two we are interested in demoing. Then we proceed to run:

~ phpspec src/Acme/DemoBundle/Spec/

Then we get an error telling us to create the methods on our empty class:

~ phpspec src/Acme/DemoBundle/Spec/
EE
 
Exceptions:
 
  1) Acme\DemoBundle\Spec\Model\MyService should get create directory using file system service from container
     Failure\Exception: $this->runExamples($exampleGroup, $reporter);
     ErrorException: Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'Acme\DemoBundle\Model\MyService' does not have a method 'methodUsingFileSystem' in /home/cordoval/sites-2/spec-symfony/vendor/phpspec/src/PHPSpec/Specification/Interceptor/Object.php line 66
 
  2) Acme\DemoBundle\Spec\Model\MyService should run command on client
     Failure\Exception: $this->runExamples($exampleGroup, $reporter);
     ErrorException: Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'Acme\DemoBundle\Model\MyService' does not have a method 'methodUsingRouter' in /home/cordoval/sites-2/spec-symfony/vendor/phpspec/src/PHPSpec/Specification/Interceptor/Object.php line 66
 
Finished in 0.052649 seconds
2 examples, 2 exceptions

Next is writing just about enough code on our Service class to make the examples pass. For that we take a look at our `MyService` class:

<?php
namespace Acme\DemoBundle\Model;
 
class MyService
{
    protected $container;
 
    public function __construct($container)
    {
        $this->container = $container;
    }
 
    public function methodUsingFileSystem()
    {
        $filesystem = $this->container->get('filesystem');
        return $filesystem->mkdir('folder1');
    }
 
    public function methodUsingRouter()
    {
        $router = $this->container->get('router');
        return $router->generate('_welcome');
    }
 
    public function checkInternalResponse()
    {
        return true;
    }
}

If you fail to meet the requirements with the writing of your methods, don’t worry PHPSpec is here to guide you make that example green:

~ phpspec src/Acme/DemoBundle/Spec/
.F
 
Failures:
 
  1) Acme\DemoBundle\Spec\Model\MyService should run command on client
     Failure\Error: $this->serviceUnderSpec->methodUsingRouter()->should->be('/somepath');
     expected '/somepath', got '/' (using be())
     # ./src/Acme/DemoBundle/Spec/Model/MyServiceSpec.php:39

Finished in 0.060213 seconds
2 examples, 1 failure

If we get everything right after all we should get:

~ phpspec src/Acme/DemoBundle/Spec/ -fd -c -b
Acme\DemoBundle\Spec\Model\MyService
  should get create directory using file system service from container
  should run command on client
 
Finished in 0.074234 seconds
2 examples

Notice that the examples are simple and are meant for you to see how easy is to use PHPSpec with PSSMockeryBundle within Symfony. We are using the spec-symfony sandbox available in our PHPSpec repos. A lot of effort is being put these days in bringing powerful tools for BDD Spec type of BDD methodology into Symfony2. PHPSpecBundle is the leading bundle along these lines that will have commands to generate the skeletons required to practice good BDD Spec type on Symfony2. BDD Spec and BDD Scenario complement each other so that is why it is important to keep the and use them together because they are more powerful together than separate.

I thank the Lord Jesus Christ for all the help in completing this effort through good friends and very good willing people like Jakub who is an expert in symfony2. We brainstormed once and next day he had the bundle ready. This is a very interesting community accomplishment! bravo!

Symfony2 Event Manager: The Stand Alone Way

My first clearer read on event manager on symfony2 was the following.

This article explains how to use the symfony2 even dispatcher to create custom listener and event using the symfony2 event manager component. The blog is very clear and teaches one how to get started on the code for when working inside a symfony2 project.

The second read was this article was a bit old. Actually a year old and taught me a lot about how to work with the stand-alone component however it was kind of unreliable but ultimately very useful. I really liked the examples that they have provided, that helped me to understand how to plug the events, how to work with priorities, how to filter values when working with events, and how use notifyUntil for instance, among other things.

Thirdly, we reviewed the symfony2 documentation chapter titled internal components here.

Basically the model has these components:

The Event is an object subclassed that is passed to all listeners with mechanisms to access information objects regarding the event. “The moral of the story is this: when creating a listener to an event, the Event object that’s passed to the listener may be a special subclass that has additional methods for retrieving information from and responding to the event.”
The Dispatcher class, which is the master class that notifies with the event all the listener classes.
The Listerner class, which is the class who is instructed to listen to the dispatcher events and that can be sub-classed so to extend with some methods to port some objects or data meant to be looked upon or processed/changed. Optionally we can gather all Events into an Events class for documentation purposes and have that class to hold statically the names or strings constants for the event names.

Note: It is important to realize that Dispatcher class is not singleton therefore it has to be injected into my master class from where O use it.
Note: On a last note, there are two approaches for using the event manager: (1) default listener approach, (2) using subscribers.
To stand on the shoulders of dustin10, I asked him what is the difference between these and he answered:

“cordoval they are basically the same thing except a subscriber implemements a method that lets doctrine know which events to subscribe to if using a listener you would create a tag for each event.”

Although I am using it standalone I can get that the idea.

Master Class

This class is in charge of creating all the objects, receive dispatcher injected through DI, assign the listeners on the constructor or elsewhere at initialization. Master class is also in charge of creating the specializing events that give access to some of the objects to compute from/on, and dispatching on a particular event string the corresponding event object just created.

So let’s get to the hands-on part. Let’s try to design this for the tictactoe problem I am facing.

/**
 * Central Class from where dispatcher is used
 */
namespace Tictactoe\Game;
use Symfony\Component\EventDispatcher\EventDispatcher;
class GameMaster
{
    protected $dispatcher = null;
    protected $player = null;
 
    public function __construct(EventDispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
 
        $listener = new GameListener();
        $dispatcher->addListener(GameEvents::onFinishPlay, array($listener, 'onFinishPlay'));
 
        $this->player = new Player();
    }
 
    public function play () {       
        $event = new FilterGameEvent($this->player);
        $dispatcher->dispatch(GameEvents::onFinishPlay, $event);
    }
}

Events Class

This class is not mandatory and its only purpose is to hold all the documentation for the strings corresponding to the event channels used in solving the problem. The Events class is mostly used when there are multiple events that need clear documentation. The Events class will allow a developer to easily find the specific event channels the core can dispatch through. This file then becomes very handy for when we need to hack the core, that is extending it, without touching it. We can see this as our list of hooks that we can use to clamp our added functionality to the application.

/**
 * Events Class
 */
namespace Tictactoe\Game;
 
final class GameEvents
{
    /**
     * The event listener receives an Tictactoe\Game\FilterGameEvent
     * instance.
     *
     * @var string
     */
    const onFinishPlay = 'turnswitcher.action';
}

Listener Class

This class should be the keystone in comprising all the logic that should be decoupled from the main core or all the logic that will extend the functionality of the core. Other classes could be easily copy pasted but this one. This class is very customized. The other classes are just copied and adapted to specific problem, they are support classes, whereas the Listener class is the main class that will extend the functionality.

/**
 * Listener TurnSwitcher Class
 */
namespace Tictactoe\Game;
 
use Symfony\Component\EventDispatcher\Event;
 
class TurnSwitcherListener
{
    // ...
    public function onFinishPlay(GameEvent $event)
    {
        // do something like
        $player = $event->getPlayer();
        // extend here the functionality of the core
        // ...
    }
}

Event Class

This class’ main purpose is to provide access to specific objects or parameters that will be useful to our logic extending the core. This class just customizes the method to get certain objects and thereby can be adapted anytime to provide first hand access to the objects that are being read from the master class or that are being written onto the master class set of properties.

/**
 * FilterGameEvent class
 * allows access to the player object
 */
namespace Tictactoe\Game\Event;
 
use Symfony\Component\EventDispatcher\Event;
use Tictactoe\Game\Player;
 
class FilterGameEvent extends Event
{
    protected $player;
 
    public function __construct(Player $player)
    {
        $this->player = $player;
    }
 
    public function getPlayer()
    {
        return $this->player;
    }
}

I hope this makes clearer the Event Manager Pattern as used in symfony2. I will be updating this to correct some mistakes I have made and also I will apply the pattern to the tictactoe game and provide more details on how to install the symfony2 component to be used standalone. So far we have worked on making things understandable.

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.