public static function subscribe(string $hook, callable $callback, int $precedence = 0)
    {
        $parts = explode(".", $hook);
        if (count($parts) < 2)
            throw new InvalidArgumentException("Hook name must consist of at least two parts");

        if ($hook === Hook::SHUTDOWN_HOOK)
            self::registerShutdownHook();

        // Make sure the callback is appropriate
        if (is_object($callback))
            $callback = [$callback, '__invoke'];

        $refl = is_array($callback) ? new \ReflectionMethod($callback[0], $callback[1]) : new \ReflectionFunction($callback);
        $params = $refl->getParameters();
        if (count($params) !== 1)
            throw new InvalidArgumentException("Hook must accept exactly one argument of type Dictionary");
        
        if ($params[0]->getType() === null || $params[0]->getType()->__toString() !== Dictionary::class)
            throw new InvalidArgumentException("Hook must accept exactly one argument of type Dictionary");

        $ref = ++self::$sequence;
        self::$hooks[$hook][] = ['precedence' => $precedence, 'callback' => $callback, 'ref' => $ref];
        usort(
            self::$hooks[$hook], 
            function (array $l, array $r) { 
                if ($l['precedence'] !== $r['precedence'])
                    return $l['precedence'] - $r['precedence']; 
                return $l['ref'] - $r['ref'];
            }
        );

        return $ref;
    }
public static function subscribe(string $hook, callable $callback, int $precedence = 0)
    {
        $parts = explode(".", $hook);
        if (count($parts) < 2)
            throw new InvalidArgumentException("Hook name must consist of at least two parts");

        if ($hook === Hook::SHUTDOWN_HOOK)
            self::registerShutdownHook();

        // Make sure the callback is appropriate
        if (is_object($callback))
            $callback = [$callback, '__invoke'];

        $refl = is_array($callback) ? new \ReflectionMethod($callback[0], $callback[1]) : new \ReflectionFunction($callback);
        $params = $refl->getParameters();
        if (count($params) !== 1)
            throw new InvalidArgumentException("Hook must accept exactly one argument of type Dictionary");
        
        if ($params[0]->getType() === null || $params[0]->getType()->__toString() !== Dictionary::class)
            throw new InvalidArgumentException("Hook must accept exactly one argument of type Dictionary");

        $ref = ++self::$sequence;
        self::$hooks[$hook][] = ['precedence' => $precedence, 'callback' => $callback, 'ref' => $ref];
        usort(
            self::$hooks[$hook], 
            function (array $l, array $r) { 
                if ($l['precedence'] !== $r['precedence'])
                    return $l['precedence'] - $r['precedence']; 
                return $l['ref'] - $r['ref'];
            }
        );

        return $ref;
    }
public static function subscribe ( string $ hook , callable $ callback , int $ precedence = 0 ) { $ parts = explode ( "." , $ hook ) ; if ( count ( $ parts ) < 2 ) throw new InvalidArgumentException ( "Hook name must consist of at least two parts" ) ; if ( $ hook === Hook :: SHUTDOWN_HOOK ) self :: registerShutdownHook ( ) ; // Make sure the callback is appropriate if ( is_object ( $ callback ) ) $ callback = [ $ callback , '__invoke' ] ; $ refl = is_array ( $ callback ) ? new \ ReflectionMethod ( $ callback [ 0 ] , $ callback [ 1 ] ) : new \ ReflectionFunction ( $ callback ) ; $ params = $ refl -> getParameters ( ) ; if ( count ( $ params ) !== 1 ) throw new InvalidArgumentException ( "Hook must accept exactly one argument of type Dictionary" ) ; if ( $ params [ 0 ] -> getType ( ) === null || $ params [ 0 ] -> getType ( ) -> __toString ( ) !== Dictionary :: class ) throw new InvalidArgumentException ( "Hook must accept exactly one argument of type Dictionary" ) ; $ ref = ++ self :: $ sequence ; self :: $ hooks [ $ hook ] [ ] = [ 'precedence' => $ precedence , 'callback' => $ callback , 'ref' => $ ref ] ; usort ( self :: $ hooks [ $ hook ] , function ( array $ l , array $ r ) { if ( $ l [ 'precedence' ] !== $ r [ 'precedence' ] ) return $ l [ 'precedence' ] - $ r [ 'precedence' ] ; return $ l [ 'ref' ] - $ r [ 'ref' ] ; } ) ; return $ ref ; }
Subscribe to a hook.

@param string $hook The hook to hook into. Must contain of at least 2
parts separated by dots: vendor.hookname
@param callable $callback The callback that will be called when the hook
is executed.  The function should have the
following signature: function (Dictionary $params);
@param int $precedence The lower this number, the sooner it will be
called, the higher the later. Default is 0.
Subscribers with equal precedence will be called
in the order they were registered.
@return int The hook reference number. Can be used to unsubscribe
Subscribe to a hook .