Ken Guest’s online diary

July 31, 2017

And another phing…

Filed under: phing,php — kenguest @ 20:57

Additional things learnt from developing the Mercurial tasks for phing, the php build system based on Java’s Ant tool.

Versions and compatibility.

As much as we might want to ignore versions of PHP that have been EOL-ed (ones
that are no longer supported officially by the good people at, phing
requires that code defining [new] tasks parse ok when linted by php 5.2.
In other words – namespaces are out, “use” is not to be used, short array
syntax is forbidden, the elvis operator has to leave the building etc etc.

Best thing to do, that doesn’t involve installing an age-old version of PHP?
Use Wim Godden’s excellent PHPCompatibility sniffs for PHP_CodeSniffer, and set
it to lint for 5.2. This doesn’t mean that new tasks developed for Phing 2.x have to work in PHP5.2, it just means that loading the main task code has to lint ok.
This is going to change in phing 3.0 where the minimum version of PHP is going to be 5.6, for those slackers that haven’t upgraded to PHP 7 yet.

Don’t reinvent.

In phing xml syntax, you can specify ‘truthy’ values as “yes”, “on”, “true”, “t”, “no”, “off”, “false” and “f”. The best way to handle all this is with:

$bValue = StringHelper::booleanValue($xmlValue);

Much neater than rolling your own, which I was guilty of earlier on! It’s interesting to note though that there is also a Project::toBoolean($value) static function which does something quite similar, but doesn’t consider ‘t’ or ‘f’ as truthy values.

There’s also a StringHelper::isBoolean function that could also be of use,
depending on what you need.

If you refactor things out to a base or abstract class, make sure that you
pull in that class

e.g. require_once ‘phing/tasks/ext/directory/Filename.php’

Internal Properties

There are a number of “internal properties” available, listed at – to get the values
of these inside a Task subclass:

$project = $this->getProject();
$dir = $project->getProperty(‘application.startdir’);

Setting Properties

If you’re at the stage of coding a phing extension/task, you’ll most certainly
know how to define a property in phing XML:

But, defining a phing property in PHP?
You can do it with either:
$project->setNewProperty(“prop”, “value”);
$project->setProperty(“existingProp”, “newValue”);
depending on what you want to do.

Update your grammar

The etc/phing-grammar.rng file is used in PHPStorm and other such IDEs to
provide syntax highlighting and validation for phing build.xml files – so you
can tell at a glance whether you might have typed in xmlint instead of xmllint,
for example.

So it makes sense especially so if you’re adding a new attribute to an existing
phing task or type to update this file.

If you’re adding properties that take default values, this can be indicated in the phing-grammar.rng file as can be seen in the definition for the truncate task:

 <define name="truncate">
     <element name="truncate">
         <attribute name="file"/>
             <attribute name="adjust"/>
             <attribute name="length"/>
     <attribute name="create" a:defaultValue="true">
         <data type="boolean"/>
         <attribute name="mkdirs" a:defaultValue="false">
             <data type="boolean"/>


That’s all for now – just a quick blog entry this time!


December 25, 2015

USB Lamp tweaks.

Filed under: phing,python — kenguest @ 22:04

My wife got me a cheeky webmail notifier (an USB lamp that changes colour) as a part of my over-generous Christmas present.

After a little diversion to Christian’s write-up, I downloaded the  usblamp project from GitHub and made a few little pythonic tweaks I decided to share:

  1. is more configurable (the mailbox and lamp colour had been hard-coded).
  2. The lamp is turned off once new emails have been opened.
  3. closes cleanly, turning off the lamp too –
  4. usblamp recognises ‘pink’ as a colour, which my wife kinda insisted on 🙂 [ e.g. $ usblamp pink works 🙂 ]

So now my lamp turns pink when I receive a new email from Aisling, and turns off once I read it.

There is one issue that I haven’t addressed: what if the lamp is already on, and set to some other colour when it is supposed to switch on in If, for example, I have phing switching it to red because a build has failed, I might want it to flash between the two colours.

I guess that’s something I’ll have to leave for another day.

November 5, 2015

Getting phing custom tasks up to PR standard. What I did.

Filed under: phing,php — kenguest @ 13:44
Tags: ,


Phing is a build system that I’ve written about before which is open source, and developed in PHP.

Two custom tasks that I wrote have been merged into the main phing repository on github and I thought I might write up my notes on what I did to get them up to “PR Standard”.

The first task is for creating and modifying .ini files and is now documented at

The second one is simply a ‘task-wrapper’ (trademark pending) for running notify-send so that pop-up or toaster messages (whatever you want to call them) get displayed at certain stages of a build. This is more efficient for me that alt-tabbing to the window that I’ve phing running in to see what’s going on.

I’m not going to describe how to use them here; hopefully the documentation that I wrote for them in phing is sufficient.

I’m also not going to outline how to write custom tasks – there’s already good documentation for that at

Instead I want to document what I learnt in the process of taking the earlier version of NotifySendTask ( ) and the IniFileTask, and getting them to Pull Request standard for inclusion in phing.

Who knows, this might help some of you decide to add a phing Pull Request of your own.

Documentation Driven Development.

Documentation is always a factor on how well an OSS project will be used, so this is one of the first things that I wanted to address.

The inifile task is an optional one – it is not a core phing task – so I added a new section to the optionaltasks docbook file at

Because the IniFileTask is pretty much a direct port of the ant-contrib equivalent, I took the documentation from and made just a few changes as I wanted to add support for a ‘haltonerror’
Converting it over to docbook from HTML was relatively trivial.

If I wanted, I could have used a docbook specific editor for doing this, but I was comfortable using vim, so I did.

I did something similar for the NotifySend task, except that there is an intentional non-documented attribute.


I added some examples to the documentation and only after the PR for inifiletask did I look at the PDF version of the manual.

I noticed only then that example listings look best when kept to a maximum length of 80 characters per line – after 90 characters or so the lines get truncated.

On with the code.


Obviously in a build system it is expected to see messages being logged, and possibly at differing levels of importance.

To log a message at the default level:
    $this->log("Log this message");

Or, explicitly:
    $this->log("Log this message", Project::MSG_INFO);

These are the levels/priorities that messages can be inserted into the log at:

  • Project::MSG_DEBUG
  • Project::MSG_ERR
  • Project::MSG_INFO
  • Project::MSG_VERBOSE
  • Project::MSG_WARN

You will see below that you can assert against entries being present, or not, in the log.

Knowing all this makes it easier to assert in unit tests that various edge cases are being tested properly, and without adding any visual clutter when the task is being run casually.

Enabling a new task by default.

To make the tasks visible by default, for testing and also so they can be used with the minimum of hassle, I referenced them in the file classes/phing/tasks/ by adding these lines:



The location of the unit test file for the task has to mirror the location of the actual task files; so because the ‘working’ code for the task is in phing/classes/phing/tasks/ext/inifile I put the unit tests into the test/classes/phing/tasks/ext/inifile/ directory.

The NotifySendTask that I developed is less complex in that it requires just one class rather than the four for the IniFileTask so the files for that are ini the tasks/ext directory instead of requiring a separate subdirectory for them. Though if I split out the unit tests for that into separate files then I would’ve created a subdirectory for them rather than clutter up tasks/ext.

Test specific build files for unit tests can be used, they are executed via the executeTarget and should be placed inside the etc/tasks/ext directory structure.

For example: etc/tasks/ext/NotifySendTaskTest.xml

Or a separate subdirectory structure such as ./etc/tasks/ext/inifile/inifile.xml

The unit test class should be a subclass of BuildFileTest.

BuildFileTest provides a number of helper methods, for example assertInLogsassertNotInLogs, configureProject and executeTarget, expectBuildException and others.

Use configureProject in the setUp method to initialise the project that the unit tests are for.

assertInLogs("Assert this text exists in the logs");
assertInLogs("Assert this text exists in the logs", Project::MSG_DEBUG);

 * Configure the project to point to the correct .xml file for these tests
public function setUp() {
    $this->configureProject(PHING_TEST_BASE . "/etc/tasks/ext/inifile/inifile.xml");
    $this->object = new ThisIsTheNewTask();

public function testSetterOutsideXml() {
    $this->object->setTitleProperty("test title");
    $this->assertEquals("test title", $this->object->getTitleProperty());

public function testInTarget()
    $this->assertInLogs("expected as debug log entry", Project::MSG_DEBUG);

public function testTargetUsingHelper()
    $this->expectDebuglog("targetToTest", "expected as debug log entry");

The PHING_TEST_BASE constant is used to refer to the base directory for all phing test files. As well as that, the test functions testInTarget and testTargetUsingHelper are functionally identical. There are many other useful methods in the BuildFileTest class and I looked through phing/test/classes/phing/BuildFileTest.php to get familiar with
what else it can do.
There is also a PhingTestListener class in that BuildFileTest.php file, but there currently are no tasks with unit tests which utilise it.

As mentioned earlier, build files can be used in unit tests. This is very useful so that you can test that the setters in tasks load and work properly when phing parses the XML files. Explicitly calling setters and getters for your unit tests will only go so far, while testing against actual build files will highlight whether or not setters that are expected to be called will be.
The build file to use for unit tests is specified in the configureProject call.
There are a number of helper functions that go along with the executeTarget method, such as expectPropertySet, expectLog, expectLogContaining, expectDebuglog, expectOutput, expectOutputAndError, and two more related to
catching expected exceptions.

Working on the Task code.

One of the main things that I added to the Pull-Request version of the NotifySendTask was additional logging and getters that could be utilised for unit testing.

I also added extra validation on the values being set – checking generic icon values are valid, and if a specified icon is a filename then the task logs whether the file actually exists and so on.

After considering how to handle unit tests being run on systems where notify-send itself wasn’t installed – I added a control parameter, in the vein of an Operator Presence Control, so the system can essentially fake running successfully.

This is the one attribute that I didn’t add to the documentation.

The IniFileTask code is perhaps a level of complexity above that for NotifySendTask – in that there are extra XML elements required, and so extra classes are required as well; all of which have their respective setter methods by necesitty. Also I opted to add corresponding getter methods to these to allow unit tests that don’t require specific build files for each test.

This is also why inifile got a subdirectory for itself and the simpler notifysend task did not.


That’s all folks!

If there’s anything you think I should have covered, let me know and I’ll either edit this with an update or write a follow-up, depending on how substantial it is 🙂

June 24, 2015

Links for my PHPDublin phing talk.

Filed under: phing,php — kenguest @ 21:27

I gave a talk yesterday about the phing php build tool at PHPDublin‘s June meeting in Kittman Labs and thought I should write up a list of the various things that I touched on in the talk.

  • First and foremost – phing (without which I’d have lost all sanity years ago).
  • Secondly, the slides themselves.

Some tasks phing can do:

There’s a whole lot more listed in the documentation!

Some projects that use phing:

Editors supporting phing:

Command line:

Getting it working with Continuous Integration servers:

Various levels of integrating PHP into your phing build.xml:

Refactoring your phing file:

I’ve plagiarised nothing, I’ve stood on the shoulders of giants (acknowledgements to):

May 14, 2015

Phing: Lint PHP code with a different interpreter.

Filed under: phing,php — kenguest @ 08:15

There’s an old server somewhere that creaks along and runs php 5.3 for legacy purposes. Recently one of the services running on that stack started throwing “internal server errors”, due to my use of array short form notation (“[…]”) which came along in php5.4, rather than using “array(…)”.

This wasn’t caught before the deploy because php 5.4 and 5.5 are used everywhere else.

So, what to do to ensure this doesn’t happen again? (Asides from investing effort in upgrading the 5.3 “locked” services to a much more recent version of PHP.)

We use phing for managing our “build process”, so using Christian’s phpfarm tool for installing multiple versions of php, I installed  a cli instance of php5.3 and changed the phplint task in my phing build.xml file to look something like this:

<phplint haltonfailure="true" interpreter="${lintInterpreter}" deprecatedAsError="true">
  <fileset refid="application"/>
  <fileset refid="vendors"/>

This also meant adding a lintInterpreter line to my buildproperties.ini file as I prefer to have any configurable properties refactored out from my build.xml to a seperate file.

These are what the relevant parts of those files look like:

$ cat buildproperties.ini 
$ head -n5 build.xml 
<?xml version="1.0"?>
<!-- phing build xml -->
<project name="ProjectName" default="main">
 <property file="buildproperties.ini"/>

And that should take care of that.

Create a free website or blog at