I’ve updated my libraries for WordPress to stick with my better understanding of PHP and an urgent need to update and review them.
Below the updated information (can be found in the repository README
).
The library contains a set of classes meant to make test-driven and object-oriented WordPress plugin and themes development easier.
The classes are aimed at developers wishing to test their code and stick to some standards and best practices.
Adapters
Functions adapter
The libraries contain an adapter class meant to act as middle man between a plugin or theme and the globally defined functions and objects; WordPress core and many plugins make heavy use of globally defined functions and that would force someone wishing to use one of those functions to run a WordPress local server to do some testing develop strongly coupled code. The adapter will abstract that dependency allowing classes to be tested in isolation.
Given the below class
<?php
class SomeClass
{
protected $functions;
public function __construct(\tad\interfaces\FunctionsAdapter $functions = null)
{
if(is_null($functions)) {
$functions</span></span> = new \tad\adapters\Functions.php
}
$this->functions = $functions;
}
public function someMethod()
{
// some logic
$this->functions->add_action('init', array($this, 'anotherMethod'));
// some more logic
}
public function anotherMethod()
{
// do something here
}
}
The PHPUnit test case might be
<?php
// SomeClass has been included or is autoloaded
class SomeClassTest extends \PHPUnit_Framework_TestCase
{
testSomeMethodWillHookIntoInit()
{
$mockFunctions = $this->getMock('\tad\interfaces\FunctionsAdapter', array('__call', 'add_action'));
$sut = new SomeClass($mockFunctions);
$mockFunctions->expects($this->once())
->method('add_action')
->with('init', array($sut, 'anotherMethod'));
$sut->someMethod();
}
}
Superglobals adapter
While mocking global variables is not difficult I appreciate the possibility to check and test the access to those variables via mocks and expectations, that’s not possible if the superglobals are accessed directly in the methods to test.
<?php
class SomeClass
{
// 'sg' stands for 'superglobals'
protected $sg;
public function __construct(\tad\interfaces\GlobalsAdapter $sg = null)
{
if(is_null($<span class="hiddenGrammarError" pre=""><span class="hiddenGrammarError" pre="">sg)) {
$sg</span></span> = new \tad\adapters\Globals.php
}
$this->sg = $sg;
}
public function testableMethod()
{
// get the 'foo' variable in the $GLOBALS array
$foo = $this->sg->globals('foo');
// get the $_SERVER array
$server = $this->sg->server();
}
public function notThatTestableMethod()
{
$foo = $GLOBALS['foo'];
$server = $SERVER;
}
}
And I can test testableMethod
access to the globals easily
<?php
// SomeClass has been included or is autoloaded
class SomeClassTest extends \PHPUnit_Framework_TestCase
{
testTestableMethodWillRequireFooVariable()
{
$mockGlobals = $this->getMock('\tad\interfaces\FunctionsAdapter', array('__call', 'globals'));
$sut = new SomeClass($mockGlobals);
$mockFunctions->expects($this->once())
->method('globals')
->with('foo');
$sut->testableMethod();
}
}
Superglobals can be accessed using a function named like their lowercase name, hence $GLOBALS
with Globals::globals()
, $_SERVER
with Globals::server()
and so on.
Specialized wrappers
While the Functions
and the Globals
adadpter will allow access to all what’s global in a WordPress session I’m implementing, as I see fit and feel the need, more classes with less god-like attitude and single responsibilities.
Theme supports
This class will take care of adding and removing theme support for theme features; the usage is quite simple
$themeSupport = new \tad\wrappers\ThemeSupport();
$themeSupport->add('some-feature');
$themeSupport->remove('some-feature');
The class instance will take care to hook into the after_setup_theme
action hook and handling the support options.