diff options
| author | 2025-09-30 16:59:41 -0400 | |
|---|---|---|
| committer | 2025-09-30 22:59:41 +0200 | |
| commit | 72884813e13596d211471482ffdc6d723ed678c9 (patch) | |
| tree | 043856f23bdcae7f9f88294c47c499657c2d05ff /lib/Minz/ExtensionManager.php | |
| parent | bf6e634e042b726edd97335ac36b2305f8101b3f (diff) | |
Add hook enums (#8036)
- add an enum to handle hook types (enum are available since PHP 8.1)
- change hook calls from string value to enum value
Diffstat (limited to 'lib/Minz/ExtensionManager.php')
| -rw-r--r-- | lib/Minz/ExtensionManager.php | 201 |
1 files changed, 67 insertions, 134 deletions
diff --git a/lib/Minz/ExtensionManager.php b/lib/Minz/ExtensionManager.php index b91a89de7..04e1806c4 100644 --- a/lib/Minz/ExtensionManager.php +++ b/lib/Minz/ExtensionManager.php @@ -19,114 +19,9 @@ final class Minz_ExtensionManager { /** * List of available hooks. Please keep this list sorted. - * @var array<string,array{'list':array<callable>,'signature':'NoneToNone'|'NoneToString'|'OneToOne'|'PassArguments'}> + * @var array<value-of<Minz_HookType>,array{'list':list<callable>,'signature':Minz_HookSignature}> */ - private static array $hook_list = [ - 'api_misc' => [ // function(): void - 'list' => [], - 'signature' => 'NoneToNone', - ], - 'before_login_btn' => [ // function(): string - 'list' => [], - 'signature' => 'NoneToString', - ], - 'check_url_before_add' => [ // function($url) -> Url | null - 'list' => [], - 'signature' => 'OneToOne', - ], - 'custom_favicon_btn_url' => [ // function(FreshRSS_Feed $feed): string | null - 'list' => [], - 'signature' => 'PassArguments', - ], - 'custom_favicon_hash' => [ // function(FreshRSS_Feed $feed): string | null - 'list' => [], - 'signature' => 'PassArguments', - ], - 'entries_favorite' => [ // function(array $ids, bool $is_favorite): void - 'list' => [], - 'signature' => 'PassArguments', - ], - 'entry_auto_read' => [ // function(FreshRSS_Entry $entry, string $why): void - 'list' => [], - 'signature' => 'PassArguments', - ], - 'entry_auto_unread' => [ // function(FreshRSS_Entry $entry, string $why): void - 'list' => [], - 'signature' => 'PassArguments', - ], - 'entry_before_display' => [ // function($entry) -> Entry | null - 'list' => [], - 'signature' => 'OneToOne', - ], - 'entry_before_insert' => [ // function($entry) -> Entry | null - 'list' => [], - 'signature' => 'OneToOne', - ], - 'entry_before_add' => [ // function($entry) -> Entry | null - 'list' => [], - 'signature' => 'OneToOne', - ], - 'entry_before_update' => [ // function($entry) -> Entry | null - 'list' => [], - 'signature' => 'OneToOne', - ], - 'feed_before_actualize' => [ // function($feed) -> Feed | null - 'list' => [], - 'signature' => 'OneToOne', - ], - 'feed_before_insert' => [ // function($feed) -> Feed | null - 'list' => [], - 'signature' => 'OneToOne', - ], - 'freshrss_init' => [ // function() -> none - 'list' => [], - 'signature' => 'NoneToNone', - ], - 'freshrss_user_maintenance' => [ // function() -> none - 'list' => [], - 'signature' => 'NoneToNone', - ], - 'js_vars' => [ // function($vars = array) -> array | null - 'list' => [], - 'signature' => 'OneToOne', - ], - 'menu_admin_entry' => [ // function() -> string - 'list' => [], - 'signature' => 'NoneToString', - ], - 'menu_configuration_entry' => [ // function() -> string - 'list' => [], - 'signature' => 'NoneToString', - ], - 'menu_other_entry' => [ // function() -> string - 'list' => [], - 'signature' => 'NoneToString', - ], - 'nav_menu' => [ // function() -> string - 'list' => [], - 'signature' => 'NoneToString', - ], - 'nav_reading_modes' => [ // function($readingModes = array) -> array | null - 'list' => [], - 'signature' => 'OneToOne', - ], - 'post_update' => [ // function(none) -> none - 'list' => [], - 'signature' => 'NoneToNone', - ], - 'simplepie_after_init' => [ // function(\SimplePie\SimplePie $simplePie, FreshRSS_Feed $feed, bool $result): void - 'list' => [], - 'signature' => 'PassArguments', - ], - 'simplepie_before_init' => [ // function(\SimplePie\SimplePie $simplePie, FreshRSS_Feed $feed): void - 'list' => [], - 'signature' => 'PassArguments', - ], - 'view_modes' => [ // function($viewModes = array) -> array | null - 'list' => [], - 'signature' => 'OneToOne', - ], - ]; + private static array $hook_list = []; /** Remove extensions and hooks from a previous initialisation */ private static function reset(): void { @@ -134,10 +29,12 @@ final class Minz_ExtensionManager { self::$ext_list = []; self::$ext_list_enabled = []; self::$ext_auto_enabled = []; - foreach (self::$hook_list as $hook_type => $hook_data) { - $hadAny |= !empty($hook_data['list']); - $hook_data['list'] = []; - self::$hook_list[$hook_type] = $hook_data; + foreach (Minz_HookType::cases() as $hook_type) { + $hadAny |= !empty(self::$hook_list[$hook_type->value]['list']); + self::$hook_list[$hook_type->value] = [ + 'list' => [], + 'signature' => $hook_type->signature(), + ]; } if ($hadAny) { gc_collect_cycles(); @@ -357,46 +254,62 @@ final class Minz_ExtensionManager { /** * Add a hook function to a given hook. * - * The hook name must be a valid one. For the valid list, see self::$hook_list - * array keys. + * The hook name must be a valid one. For the valid list, see Minz_HookType enum. * - * @param string $hook_name the hook name (must exist). + * @param string|Minz_HookType $hook the hook name (must exist). * @param callable $hook_function the function name to call (must be callable). */ - public static function addHook(string $hook_name, $hook_function): void { - if (isset(self::$hook_list[$hook_name]) && is_callable($hook_function)) { + public static function addHook(string|Minz_HookType $hook, $hook_function): void { + if (null === $hook = self::extractHook($hook)) { + return; + } + $hook_name = $hook->value; + + if (is_callable($hook_function)) { self::$hook_list[$hook_name]['list'][] = $hook_function; } } /** + * @param string|Minz_HookType $hook the hook or its name + * @return Minz_HookType|null + */ + private static function extractHook(string|Minz_HookType $hook) { + if ($hook instanceof Minz_HookType) { + return $hook; + } + + return Minz_HookType::tryFrom($hook); + } + + /** * Call functions related to a given hook. * - * The hook name must be a valid one. For the valid list, see self::$hook_list - * array keys. + * The hook name must be a valid one. For the valid list, see Minz_HookType enum. * - * @param string $hook_name the hook to call. - * @param mixed ...$args additional parameters (for signature, please see self::$hook_list). + * @param string|Minz_HookType $hook the hook to call. + * @param mixed ...$args additional parameters (for signature, please see Minz_HookType enum). * @return mixed|void|null final result of the called hook. */ - public static function callHook(string $hook_name, ...$args) { - if (!isset(self::$hook_list[$hook_name])) { + public static function callHook(string|Minz_HookType $hook, ...$args) { + if (null === $hook = self::extractHook($hook)) { return; } + $hook_name = $hook->value; $signature = self::$hook_list[$hook_name]['signature']; - if ($signature === 'OneToOne') { + if ($signature === Minz_HookSignature::OneToOne) { return self::callOneToOne($hook_name, $args[0] ?? null); - } elseif ($signature === 'PassArguments') { + } elseif ($signature === Minz_HookSignature::PassArguments) { foreach (self::$hook_list[$hook_name]['list'] as $function) { $result = call_user_func($function, ...$args); if ($result !== null) { return $result; } } - } elseif ($signature === 'NoneToString') { + } elseif ($signature === Minz_HookSignature::NoneToString) { return self::callHookString($hook_name); - } elseif ($signature === 'NoneToNone') { + } elseif ($signature === Minz_HookSignature::NoneToNone) { self::callHookVoid($hook_name); } return; @@ -411,12 +324,17 @@ final class Minz_ExtensionManager { * * If a hook return a null value, the method is stopped and return null. * - * @param string $hook_name is the hook to call. + * @param string|Minz_HookType $hook is the hook to call. * @param mixed $arg is the argument to pass to the first extension hook. * @return mixed|null final chained result of the hooks. If nothing is changed, * the initial argument is returned. */ - private static function callOneToOne(string $hook_name, mixed $arg): mixed { + private static function callOneToOne(string|Minz_HookType $hook, mixed $arg): mixed { + if (null === $hook = self::extractHook($hook)) { + return $arg; + } + $hook_name = $hook->value; + $result = $arg; foreach (self::$hook_list[$hook_name]['list'] as $function) { $result = call_user_func($function, $arg); @@ -436,10 +354,15 @@ final class Minz_ExtensionManager { * The result is concatenated between each hook and the final string is * returned. * - * @param string $hook_name is the hook to call. + * @param string|Minz_HookType $hook is the hook to call. * @return string concatenated result of the call to all the hooks. */ - public static function callHookString(string $hook_name): string { + public static function callHookString(string|Minz_HookType $hook): string { + if (null === $hook = self::extractHook($hook)) { + return ''; + } + $hook_name = $hook->value; + $result = ''; foreach (self::$hook_list[$hook_name]['list'] ?? [] as $function) { $return = call_user_func($function); @@ -456,9 +379,14 @@ final class Minz_ExtensionManager { * This case is simpler than callOneToOne because hooks are called one by * one, without any consideration of argument nor result. * - * @param string $hook_name is the hook to call. + * @param string|Minz_HookType $hook is the hook to call. */ - public static function callHookVoid(string $hook_name): void { + public static function callHookVoid(string|Minz_HookType $hook): void { + if (null === $hook = self::extractHook($hook)) { + return; + } + $hook_name = $hook->value; + foreach (self::$hook_list[$hook_name]['list'] ?? [] as $function) { call_user_func($function); } @@ -468,9 +396,14 @@ final class Minz_ExtensionManager { * Call a hook which takes no argument and returns nothing. * Same as callHookVoid but only calls the first extension. * - * @param string $hook_name is the hook to call. + * @param string|Minz_HookType $hook is the hook to call. */ - public static function callHookUnique(string $hook_name): bool { + public static function callHookUnique(string|Minz_HookType $hook): bool { + if (null === $hook = self::extractHook($hook)) { + throw new \RuntimeException("The “{$hook}” does not exist!"); + } + $hook_name = $hook->value; + foreach (self::$hook_list[$hook_name]['list'] ?? [] as $function) { call_user_func($function); return true; |
