public function call($hookName, $arg = '') : bool
    {
        $hookName = $this->sanitizeKeyName($hookName);
        if (! $hookName) {
            return false;
        }

        if (! isset($this->actions[$hookName])) {
            $this->actions[$hookName] = 1;
        } else {
            $this->actions[$hookName]++;
        }

        if (! isset($this->filters[$hookName])) {
            return false;
        }

        $this->current[] = $hookName;

        $args = [];
        if (is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0])) {
            $args[] =& $arg[0];
        } else {
            $args[] = $arg;
        }

        for ($a = 2, $num = func_num_args(); $a < $num; $a++) {
            $args[] = func_get_arg($a);
        }

        // Sort
        if (! isset($this->merged[$hookName])) {
            ksort($this->filters[$hookName]);
            $this->merged[$hookName] = true;
        }
        reset($this->filters[$hookName]);
        do {
            foreach (current($this->filters[$hookName]) as $collection) {
                if (!is_null($collection[self::KEY_FUNCTION])) {
                    call_user_func_array(
                        $collection[self::KEY_FUNCTION],
                        array_slice(
                            $args,
                            0,
                            (int) $collection[self::KEY_ACCEPTED_ARGS]
                        )
                    );
                }
            }
        } while (next($this->filters[$hookName]) !== false);

        array_pop($this->current);
        return true;
    }