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.