test.ical.ly | getting the web by the balls

Apr/10

30

Writing a simple installer script for symfony

installerSome days ago I wrote about a new blog called labor.ical.ly that I want to use to evaluate symfony plugins. Now I wanted to give it a corporate feeling and I wanted to ease the way to create a new projects and install the plugin(s) I want to evaluate. And of course it should look like the blog.

So I went and wrote an installer script just as described on the symfony blog.

This is a really useful feature so I thought I’d better document my way to promote it. ;)

Let’s set the goal first

What do I want to achieve?

  • I want to create an application called “frontend”
  • I want to replace the default layout.php with my own design
  • I want to start a dialog about what plugins to install
  • I want the given plugins to be installed and activated

The skeleton

Next to my installer script I created a skeleton dir with the following contents:

skeleton/
 `- apps/
   `- frontend/
     `- modules/
       `- default/
         `- templates/
           `- disabledSuccess.php
           `- error404Success.php
           `- indexSuccess.php
           `- loginSuccess.php
           `- moduleSuccess.php
           `- secureSuccess.php
     `- templates/
       `- layout.php
 `- web/
   `- robots.txt

The layout.php contains a similar markup as the blog while the default module templates are copies from the original symfony module but with the decorate_with() calls removed so they use the default layout as well. The robots.txt keeps the crawlers out.

The script basics

Here is the script I will start with.

runTask('configure:author', "'caefer '");

The symfony generate:project task will include() this installer script at some point so it will be executed within the object context of sfGenerateProjectTask. Outside this context the installer will not make any sense so it will just die with a meaningful scream.

Creating a frontend application

Running tasks from within the script is easy as you can see at the above example of cinfiguring the author. So we can also use that to create the default application.

/**
 * Create the frontendapplication
 */
$this->runTask('generate:app', 'frontend --csrf-secret='.sha1(time()));

Replacing files from a skeleton dir

According to the documentation you can use the installDir() method to point to your skeleton which will then be mirrored to the current project like this.

/**
 * Copy the correct layout.php to the frontend application
 */
$this->installDir(dirname(__FILE__).'/skeleton');

Unfortunately this does not replace the files that already exist but justs adds new files. There is currently no way to pass the override option to the internally used sfFilesytem::mirror() method.. So we have to copy a bit of code here.

/**
 * Copy the correct layout.php to the frontend application
 */
$this->getFilesystem()->mirror(
  dirname(__FILE__).'/skeleton',
  sfConfig::get('sf_root_dir'),
  sfFinder::type('any')->discard('.sf'),
  array('override' => true)
);

Enter the dialog

If you’ve ever written your own task with a short dialog you already know that this is quite simple.

/**
 * Lets ask for all Plugins to install
 */
$pluginNames = array();
do
{
  $pluginName = $this->ask('What plugin should be installed? (press return to stop adding)');
  $pluginNames[] = $pluginName;
}
while(!empty($pluginName));
array_pop($pluginNames);

Install and activate the plugins

Now iterating over the given plugin names we try to install them.

/**
 * Let's try to install the plugins
 */
foreach($pluginNames as $pluginName)
{
  try
  {
    $this->runTask('plugin:install', $pluginName);
  }
  catch(sfPluginRestException $e)
  {
    $this->logSection('labor.ical.ly', $e->getMessage(), null, 'ERROR');
    $this->logSection('labor.ical.ly', 'Please install this plugin manually', 'COMMAND');
  }
}

The above will install all plugins if available via the symfony PEAR channel. All other plugins will have to be installed manually.
You could of course try different options here but for my requirements that would be overengineered.

The full script

And that’s it really. Simple install script that saves a lot of time.

Here is the full script for your viewing pleasure. :)

runTask('configure:author', "'caefer '");
/**
 * Create the frontendapplication
 */
$this->runTask('generate:app', 'frontend --csrf-secret='.sha1(time()));
/**
 * Copy the correct layout.php to the frontend application
 */
$this->getFilesystem()->mirror(
  dirname(__FILE__).'/skeleton',
  sfConfig::get('sf_root_dir'),
  sfFinder::type('any')->discard('.sf'),
  array('override' => true)
);
/**
 * Lets ask for all Plugins to install
 */
$pluginNames = array();
do
{
  $pluginName = $this->ask('What plugin should be installed? (press return to stop adding)');
  $pluginNames[] = $pluginName;
}
while(!empty($pluginName));
array_pop($pluginNames);
/**
 * Let's try to install the plugins
 */
foreach($pluginNames as $pluginName)
{
  try
  {
    $this->runTask('plugin:install', $pluginName);
  }
  catch(sfPluginRestException $e)
  {
    $this->logSection('labor.ical.ly', $e->getMessage(), null, 'ERROR');
    $this->logSection('labor.ical.ly', 'Please install this plugin manually', 'COMMAND');
  }
}
/**
 * Create a symlink in the document root of the blog under the projects name
 */
$this->getFilesystem()->symlink(getcwd().'/web', getcwd().'/../htdocs/'.$this->arguments['name']);
$this->getFilesystem()->symlink(getcwd().'/../symfony/data/web/sf', getcwd().'/web/sf');

The last two lines make this new project available at http://labor.ical.ly/ProjectName and create a symlink for the symfony resources used in the default module.

And a result can be seen here for example.

· · ·



<<

>>

Theme Design by devolux.nh2.me