Smarter and smaller Adapter Classes

I’ve updated the Adapter Classes for WordPress plugin again to keep it current with my development needs.
I very much like the philosophy behind products that allow users to do more by allowing them to do less and, even if not a typical consumer product, I’ve tried doing so with Adapter Classes.

The first goal of Adapter Classes

Adapter Classes were born out of my need to be able to write testable WordPress code, themes and plugins, out of the box and with no need for frameworks like WordPress unit tests.
Now, wiser than I was two weeks ago, I understand completely isolating code from WordPress global functions and variables is not possible if not using adapter classes and what I built is really that: an environment (“framework” is a good synonym) to isolate plugins.
The main difference between my solution and the wordpress-unit-tests one is that I’ve created the Adapter Classes with the clear intent to mock them in test: Adapter Classes are not something to use in test but rather something to use for the normal plugin functions and that can hence be mocked in tests. The idea is the same behind Toppa Plugins Libraries for WordPress I guess.

The actual implementation

There is still some testing to do but after a first contraption the adapter classes got even smaller. So small I can paste the code for the adclasses_Functions global functions wrapper class below:

<?php
/**
 * Global WordPress functions adapter classes
 *
 * Classes to wrap and isolate miscellaneous WordPress global functions
 *
 * @package   adclasses
 * @author    theAverageDev (Luca Tumedei) <luca@theaveragedev.com>
 * @license   GPL-2.0+
 * @link      http://theaveragedev.local
 * @copyright 2013 theAverageDev (Luca Tumedei)
 */
if (!class_exists('adclasses_Functions')) {
    class adclasses_Functions
    {
        /**
         * The instance of this class
         * @var object
         */
        protected static $instance = null;
        /**
         * Return an instance of this class.
         *
         * @since     1.0.0
         *
         * @return    object    A single instance of this class.
         */
        public static function get_instance()
        {
            // If the single instance hasn't been set, set it now.
            if (null == self::$instance) {
                self::$instance = new self;
            }

            return self::$instance;
        }
        /**
         * Magic method to wrap WordPress function calls at run time
         * @param  string $name      The original WordPress function name
         * @param  array  $arguments The arguments to pass to the original WordPress function
         * @return mixed            The original WordPress function return value.
         */
        public function __call($name, array $arguments)
        {
            // if name is not a string return
            if (!is_string($name)) {

                return;
            }
            // if the function called is defined then return it
            if (function_exists($name)) {

                return call_user_func_array($name, $arguments);
            }

            return;
        }
    }
}

I will have to modify the class further, the global variable wrapper class is similar, but the core of it is that the functions will be wrapped and returned at runtime. The “magic” happens using the __call magic method in the functions class and the __get magic method in the globals.
The actual problem is the class comes with no methods at all and when mocked like this

...
$mock_functions_adapter = $this->getMock('adclasses_Functions')
...

what gets out of the mock is nothing. No method stubbing at all. Methods have then to be added explicitly, in spite of having them stubbed to null returning method, one by one like

...
$mock_functions_adapter = $this->getMock('adclasses_Functions')
$mock_functions_adapter->expects($this->once())->method('wp_login_form')->will($this->returnValue('foo'));
$mock_functions_adapter->expects($this->once())->method('add_filter')->will($this->returnValue('true'));
$mock_functions_adapter->expects($this->once())->method('add_action')->will($this->returnValue('true'));
... 

not the handiest mocks.

Speed is a problem perhaps

All the runtime, lazy as much as possible, wrapping of the functions and the globals sure has a cost; maybe not one I can register now but sure it has a cost.

Next steps

Next step is to introduce some form of caching and make the class really comfortably mockable.