banner

Plugin Everywhere

The work on the documentation is in progress. Feel free to email me your comments and suggestions. You can find my contacts in Contacts section.

Main idea

The main idea is to make this plugin mechanism global and source code independent. This is done on autoloader level by PHP class source code modifications on-the-fly. Class source code gets modified by plugin manager to setup "hooks" for all class methods at the autoload stage. This gives a unique ability to use plugins with any new and existent classes without source code modifications. So, hooks are used to produce the events plugins can catch.

How it's made

Let's look how classes get wrapped by PluginManager on autoload:

Classes wrapping

So, as you see, it doesn't require a lot of changes to integrate with your project. You have just to call it in your autoloader and check return code. If it isn't success, you have to perform autoloading in regular way.

Once class is wrapped, you can receive events.

Source code look

Let's take a look at the source and wrapped class sources.

Source class:

class TestClass {

	private $_var = null;

	public function testMethod($var) {
		$this->_var = $var;
	}

	private function _testPrivate() {
		return $this->_var*2;
	}

	protected function _testProtected() {
		return $this->_var+1;
	}

}

Wrapped class:

class TestClass {

	public function getSensorData($sensorName) {

		if (isset($this->$sensorName)) {
			return $this->$sensorName;
		}
		return null;
	}

	public static function getStaticSensorData($sensorName) {

		if (isset(self::$$sensorName)) {
			return self::$$sensorName;
		}
		return null;
	}

	 

	private $_var = null;

	public  function testMethod($var) {
		$args = func_get_args();
		$args = PluginManager::getInstance()->hookCallback(PluginManager::HOOK_ON_BEFORE_CALL, $this, "testMethod", $args);
		$return = call_user_func_array(array($this, "testMethod_Hooked"), $args);
		$return = PluginManager::getInstance()->hookCallback(PluginManager::HOOK_ON_AFTER_CALL, $this, "testMethod", $return);
		return $return;
	}

	public  function testMethod_Hooked ($var) {
		$this->_var = $var;
	}

	private  function _testPrivate() {
		$args = func_get_args();
		$args = PluginManager::getInstance()->hookCallback(PluginManager::HOOK_ON_BEFORE_CALL, $this, "_testPrivate", $args);
		$return = call_user_func_array(array($this, "_testPrivate_Hooked"), $args);
		$return = PluginManager::getInstance()->hookCallback(PluginManager::HOOK_ON_AFTER_CALL, $this, "_testPrivate", $return);
		return $return;
	}

	private  function _testPrivate_Hooked () {
		return $this->_var*2;
	}

	protected  function _testProtected() {
		$args = func_get_args();
		$args = PluginManager::getInstance()->hookCallback(PluginManager::HOOK_ON_BEFORE_CALL, $this, "_testProtected", $args);
		$return = call_user_func_array(array($this, "_testProtected_Hooked"), $args);
		$return = PluginManager::getInstance()->hookCallback(PluginManager::HOOK_ON_AFTER_CALL, $this, "_testProtected", $return);
		return $return;
	}

	protected  function _testProtected_Hooked () {
		return $this->_var+1;
	}

}

Calls

As you see, each method gets replaced by a generated one and two calls to PluginManager are made. Each call is made by the following scheme (using the example above):

This is the example with GenericPlugin class which is an abstract entity only

Method calls

Because PluginManager wraps all methods, you're able to catch events even for protected and private methods as well.

Static classes wrapping

Static classes are successfully wrapped by PluginManager. You will not feel the difference working with dynamic or or static objects in your plugin. PluginTransport does the trick. Your plugin will always receive dynamically created object without any difference was it static or dynamic.

Let's see how static classes get wrapped:

Static class wrapping

So, your plugin will get 'fake' object, which delegates method calls to the static one it is linked with. The next picture shows this process:

Dynamical call to static object

Download

It's time for you to experiment. Just Download it and try!