diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..00380e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +!.gitignore +.idea diff --git a/README.md b/README.md index 17aacd2..01843ec 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,30 @@ Hook::listen('template.hookName', function ($callback, $output, $variables) { }); ``` +# Wildcards + +You can use wildcards to attach the same listener to multiple hooks. +With wildcards, you can get another parameter `$wildcards` containing an array : +```php +Hook::listen('template.*', function($callback, $output, $variables, $wildcards = []) { + // For the hook "template.foobar", $wildcards will contain : ["foobar"] +}): +``` + +:exclamation: Warning : the wildcard hook will be executed **only if there is no exact match** for the given hook name. +
For example : +```php +Hook::listen('*', function () { + return 'wildcard'; +}); +Hook::listen('foo', function () { + return 'foo'; +}); + +Hook::get('foobar'); // => Will return 'wildcard' +Hook::get('bar'); // => Will return 'wildcard' +Hook::get('foo'); // => Will return 'foo' +``` # Stop ```php diff --git a/src/Facades/Hook.php b/src/Facades/Hook.php index 710d300..5d4e3b8 100644 --- a/src/Facades/Hook.php +++ b/src/Facades/Hook.php @@ -4,6 +4,15 @@ use Illuminate\Support\Facades\Facade; +/** + * @method static void listen($hook, $function, $priority = null) + * @method static mixed get($hook, $params = [], callable $callback = null, $htmlContent = '') + * @method static void stop($hook) + * @method static void mock($name, $return) + * @method static array getListeners() + * @method static array getEvents($hook) + * @method static array getHooks() + */ class Hook extends Facade { protected static function getFacadeAccessor() diff --git a/src/Hook.php b/src/Hook.php index adc711e..eaaa126 100644 --- a/src/Hook.php +++ b/src/Hook.php @@ -3,6 +3,7 @@ namespace Esemve\Hook; use Illuminate\Support\Arr; +use Illuminate\Support\Str; class Hook { @@ -86,6 +87,32 @@ public function listen($hook, $function, $priority = null) ksort($this->watch[$hook]); } + /** + * Extract and return the words corresponding to wildcard(s) in the hook name pattern. + * + * @param string $hook Hook name + * @param string $pattern Pattern to match against hook name + * + * @return array + */ + protected function getWildcards($hook, $pattern) + { + $matches = []; + + // Prepare $hook as a regex pattern + $hook = '/^'.$hook.'$/'; + $hook = str_replace('.', '\.', $hook); + $hook = str_replace('*', '(.*)', $hook); + + // Try to match wildcards + preg_match($hook, $pattern, $matches); + + // Remove first element, containing the full pattern match + array_shift($matches); + + return $matches; + } + /** * Return all registered hooks. * @@ -177,16 +204,41 @@ protected function run($hook, $params, Callback $callback, $output = null) array_unshift($params, $callback); if (array_key_exists($hook, $this->watch)) { - if (is_array($this->watch[$hook])) { - foreach ($this->watch[$hook] as $function) { - if (!empty($this->stop[$hook])) { - unset($this->stop[$hook]); - break; - } - - $output = call_user_func_array($function['function'], $params); - $params[1] = $output; + array_push($params, []); + $output = $this->getOutputForHook($hook, $params, $output); + } else { + foreach (array_keys($this->watch) as $key) { + if (Str::is($key, $hook)) { + array_push($params, $this->getWildcards($key, $hook)); + $output = $this->getOutputForHook($key, $params, $output); + break; + } + } + } + + return $output; + } + + /** + * Calculate and return the output for the given hook name. + * + * @param string $hook Hook name + * @param array $params Parameters + * @param string|null $output html wrapped by hook + * + * @return mixed + */ + protected function getOutputForHook($hook, $params, $output) + { + if (is_array($this->watch[$hook])) { + foreach ($this->watch[$hook] as $function) { + if (!empty($this->stop[$hook])) { + unset($this->stop[$hook]); + break; } + + $output = call_user_func_array($function['function'], $params); + $params[1] = $output; } }