Wire::runHooks PHP Method

runHooks() public method

Unlike __call, this method won't trigger an Exception if the hook and method don't exist. Instead it returns a result array containing information about the call.
public runHooks ( string $method, array $arguments, string $type = 'method' ) : array
$method string Method or property to run hooks for.
$arguments array Arguments passed to the method and hook.
$type string May be either 'method' or 'property', depending on the type of call. Default is 'method'.
return array Returns an array with the following information: [return] => The value returned from the hook or NULL if no value returned or hook didn't exist. [numHooksRun] => The number of hooks that were actually run. [methodExists] => Did the hook method exist as a real method in the class? (i.e. with 3 underscores ___method). [replace] => Set by the hook at runtime if it wants to prevent execution of the original hooked method.
    public function runHooks($method, $arguments, $type = 'method')
    {
        $result = array('return' => null, 'numHooksRun' => 0, 'methodExists' => false, 'replace' => false);
        $realMethod = "___{$method}";
        if ($type == 'method') {
            $result['methodExists'] = method_exists($this, $realMethod);
        }
        if (!$result['methodExists'] && !self::isHooked($method . ($type == 'method' ? '()' : ''))) {
            return $result;
            // exit quickly when we can
        }
        $hooks = $this->getHooks($method);
        foreach (array('before', 'after') as $when) {
            if ($type === 'method' && $when === 'after' && $result['replace'] !== true) {
                if ($result['methodExists']) {
                    $result['return'] = call_user_func_array(array($this, $realMethod), $arguments);
                } else {
                    $result['return'] = null;
                }
            }
            foreach ($hooks as $priority => $hook) {
                if (!$hook['options'][$when]) {
                    continue;
                }
                if (!empty($hook['options']['objMatch'])) {
                    $objMatch = $hook['options']['objMatch'];
                    // object match comparison to determine at runtime whether to execute the hook
                    if (is_object($objMatch)) {
                        if (!$objMatch->matches($this)) {
                            continue;
                        }
                    } else {
                        if ((string) $this != $objMatch) {
                            continue;
                        }
                    }
                }
                if ($type == 'method' && !empty($hook['options']['argMatch'])) {
                    // argument comparison to determine at runtime whether to execute the hook
                    $argMatches = $hook['options']['argMatch'];
                    $matches = true;
                    foreach ($argMatches as $argKey => $argMatch) {
                        $argVal = isset($arguments[$argKey]) ? $arguments[$argKey] : null;
                        if (is_object($argMatch)) {
                            // Selectors object
                            if (is_object($argVal)) {
                                $matches = $argMatch->matches($argVal);
                            } else {
                                // we don't work with non-object here
                                $matches = false;
                            }
                        } else {
                            if (is_array($argVal)) {
                                // match any array element
                                $matches = in_array($argMatch, $argVal);
                            } else {
                                // exact string match
                                $matches = $argMatch == $argVal;
                            }
                        }
                        if (!$matches) {
                            break;
                        }
                    }
                    if (!$matches) {
                        continue;
                    }
                    // don't run hook
                }
                $event = new HookEvent();
                $event->object = $this;
                $event->method = $method;
                $event->arguments = $arguments;
                $event->when = $when;
                $event->return = $result['return'];
                $event->id = $hook['id'];
                $event->options = $hook['options'];
                $toObject = $hook['toObject'];
                $toMethod = $hook['toMethod'];
                if (is_null($toObject)) {
                    $toMethod($event);
                } else {
                    $toObject->{$toMethod}($event);
                }
                $result['numHooksRun']++;
                if ($when == 'before') {
                    $arguments = $event->arguments;
                    $result['replace'] = $event->replace === true || $result['replace'] === true;
                    if ($result['replace']) {
                        $result['return'] = $event->return;
                    }
                }
                if ($when == 'after') {
                    $result['return'] = $event->return;
                }
            }
        }
        return $result;
    }