1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-21 14:02:59 +02:00

Some minor optimizations in WireHooks class, plus enable before/after option for $type argument in runHooks method that was mentioned in the phpdoc but wasn't fully supported yet

This commit is contained in:
Ryan Cramer
2018-03-13 09:37:05 -04:00
parent d82d011eca
commit 3a76db94f9
2 changed files with 54 additions and 20 deletions

View File

@@ -529,7 +529,7 @@ abstract class Wire implements WireTranslatable, WireFuelable, WireTrackable {
*
* @param string $method Method or property to run hooks for.
* @param array $arguments Arguments passed to the method and hook.
* @param string $type May be either 'method' or 'property', depending on the type of call. Default is 'method'.
* @param string|array $type May be either 'method', 'property' or array of hooks (from getHooks) to run. 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.
@@ -597,8 +597,8 @@ abstract class Wire implements WireTranslatable, WireFuelable, WireTrackable {
* - Also considers the class parents for hooks.
*
* ~~~~~
* if($pages->hasHook('find')) {
* // the Pages::find method is hooked
* if($pages->hasHook('find()')) {
* // the Pages::find() method is hooked
* }
* ~~~~~
*

View File

@@ -673,11 +673,12 @@ class WireHooks {
* @param Wire $object
* @param string $method Method or property to run hooks for.
* @param array $arguments Arguments passed to the method and hook.
* @param string $type May be any one of the following:
* @param string|array $type May be any one of the following:
* - method: for hooked methods (default)
* - property: for hooked properties
* - before: only run before hooks and do nothing else
* - after: only run after hooks and do nothing else
* - Or array[] of hooks (from getHooks method) to run (does not call hooked 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.
@@ -688,33 +689,46 @@ class WireHooks {
public function runHooks(Wire $object, $method, $arguments, $type = 'method') {
$hookTimer = self::___debug ? $this->hookTimer($object, $method, $arguments) : null;
$realMethod = "___$method";
$cancelHooks = false;
$profiler = $this->wire->wire('profiler');
$hooks = null;
if(is_array($type)) {
// array of hooks to run provided in $type argument
$hooks = $type;
$type = 'custom';
}
$result = array(
'return' => null,
'numHooksRun' => 0,
'methodExists' => false,
'methodExists' => ($type === 'method' ? method_exists($object, $realMethod) : false),
'replace' => false,
);
$realMethod = "___$method";
if($type == 'method') $result['methodExists'] = method_exists($object, $realMethod);
// if(!$result['methodExists'] && !$this->hasHook($object, $method . ($type == 'method' ? '()' : ''))) {
if(!$result['methodExists'] && !$this->isHookedOrParents($object, $method, $type)) {
return $result; // exit quickly when we can
if($type === 'method' || $type === 'property') {
if(!$result['methodExists'] && !$this->isHookedOrParents($object, $method, $type)) {
return $result; // exit quickly when we can
}
}
$hooks = $this->getHooks($object, $method);
$cancelHooks = false;
$profiler = $this->wire->wire('profiler');
if($hooks === null) $hooks = $this->getHooks($object, $method);
foreach(array('before', 'after') as $when) {
if($type === 'method' && $when === 'after' && $result['replace'] !== true) {
if($result['methodExists']) {
$result['return'] = $object->_callMethod($realMethod, $arguments);
} else {
$result['return'] = null;
if($type === 'method') {
if($when === 'after' && $result['replace'] !== true) {
if($result['methodExists']) {
$result['return'] = $object->_callMethod($realMethod, $arguments);
} else {
$result['return'] = null;
}
}
} else if($type === 'after') {
if($when === 'before') continue;
} else if($type === 'before') {
if($when === 'after') break;
}
foreach($hooks as $priority => $hook) {
@@ -843,6 +857,26 @@ class WireHooks {
return $result;
}
/**
* Filter and return hooks matching given property and value
*
* @param array $hooks Hooks from getHooks() method
* @param string $property Property name from hook (or hook options)
* @param string|bool|int $value Value to match
* @return array
*
*/
public function filterHooks(array $hooks, $property, $value) {
foreach($hooks as $key => $hook) {
if(array_key_exists($property, $hook)) {
if($hook[$property] !== $value) unset($hooks[$key]);
} else if(array_key_exists($property, $hook['options'])) {
if($hook['options'][$property] !== $value) unset($hooks[$key]);
}
}
return $hooks;
}
/**
* Start timing a hook and return the timer name
*