In order to control data structures, functions, flow and views AbanteCart utilize hooks placed in various parts of the code in core, storefront and admin. Each hook will have unique name.
To call a hook you must use extensions api object. It is stored in registry as an extensions and since all classes can use registry properties as their own you can use $this->extensions To have an extensions api hook an object of class “ClassName” method call, you do:
$this->extensions->hkMethodName($object, $param1, $param2);
Basically, when you tell the extensions api to hook ClassName::methodName(), it creates Extension hooks and calls them and the main method as follows (this is not always true and it is more complicated than this, but it is better to express more precise wiring in visual form):
- Extension::beforeClassNameMethodName() - use it to update/change parameters passed to method
- Extension::aroundClassNameMethodName() - use it to forbid original method call
- ClassName::methodName()
- Extension::onClassNameMethodName() - use it to change return data
- Extension::afterClassNameMethodName() - use it to run some functions after method is executed
Some of the hooks may seem very similar, but they help to serve different purposes.
Extension automatically has access to the current controller object (class instance) loaded during the hooking process. Current controller instance used in the extension class will be available via $this->baseObject and provides access to all public methods and properties in the extended controller. This also includes access to global structures. Refer to developer’s manual for global data structures and controller public methods and properties.
The state of extended controller instance can be different depending on the hook location and stage of execution.
class ExtensionName extends Extension { public function onClassNameMethodName($param1, $param2) { if ($this->baseObject->property === true) { // ... let's do something now ... } } }
all class properties you want to be used in extensions must be declared as public
Extensions also have the current ExtensionsApi loaded into them so that they can make hookable calls on other objects if needed, such as the base object or another object:
class ExtensionName extends Extension { public function beforeClassNameMethodName($param1, $param2) { // ... $object = new AnotherClass(); // ... $this->ExtensionsApi->hkAnotherMethod($object, 'this is input param 1'); } public function afterClassNameMethodName($param1, $param2) { // ... $this->ExtensionsApi->hkAnotherMethod($this->baseObject); } }
Extensions can even have calls to themselves hooked. You could use the Extension’s ExtensionsApi to accomplish this just as with other objects; however, if you are not overriding the Extension __call() method, there is an easier way:
class ExtensionName extends Extension { public function afterClassNameMethodName($param1, $param2) { // hook $this->performSomeAction() $this->hkPerformSomeAction(); } public function performSomeAction() { // ... } }
When it is a Extension that is being hooked, the base object is not changed. This is usually the desired functionality, but may not always be. However, if one Extension wants to access another Extension, it can do so through its Extension Api:
class AnotherExtensionName extends Extension { public function onExtensionNamePerformSomeAction() { $Extension = $this->ExtensionsApi->ExtensionName; // ... do something with the other Extension now } }
Extension can be called on any hook method called. You need to use overload Hooks property for it
class ExtensionDefaultExtensionLogger extends Extension { public $overloadHooks = true; protected $log = ''; protected function log($message) { $this->log .= '[' . date('Y-m-d H:i:s') . "] $message\n"; } public function __call($method, $args) { $this->log("called Extension::$method()"); } public function printLog() { echo '<strong>Extension Call Log</strong><pre>', $this->log, '</ pre>'; } }