X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FCore%2FHook.php;h=3167464a790da9f46d5261e2bbf5ffcbabdd3678;hb=34521c228bd69609fa4f475bb2e2e826723fcc16;hp=85ed98e886b2d39ab6724dae72c658dc74d837f4;hpb=ebc97ba8fe80442ca817bfe8f79b32588c2573ef;p=friendica.git diff --git a/src/Core/Hook.php b/src/Core/Hook.php index 85ed98e886..3167464a79 100644 --- a/src/Core/Hook.php +++ b/src/Core/Hook.php @@ -1,17 +1,35 @@ . + * */ + namespace Friendica\Core; use Friendica\App; -use Friendica\BaseObject; use Friendica\Database\DBA; +use Friendica\DI; +use Friendica\Util\Strings; /** * Some functions to handle hooks */ -class Hook extends BaseObject +class Hook { /** * Array of registered hooks @@ -31,6 +49,8 @@ class Hook extends BaseObject /** * Load hooks + * + * @return void */ public static function loadHooks() { @@ -38,35 +58,51 @@ class Hook extends BaseObject $stmt = DBA::select('hook', ['hook', 'file', 'function'], [], ['order' => ['priority' => 'desc', 'file']]); while ($hook = DBA::fetch($stmt)) { - if (!array_key_exists($hook['hook'], self::$hooks)) { - self::$hooks[$hook['hook']] = []; - } - self::$hooks[$hook['hook']][] = [$hook['file'], $hook['function']]; + self::add($hook['hook'], $hook['file'], $hook['function']); } DBA::close($stmt); } + /** + * Adds a new hook to the hooks array. + * + * This function is meant to be called by modules on each page load as it works after loadHooks has been called. + * + * @param string $hook + * @param string $file + * @param string $function + * @return void + */ + public static function add(string $hook, string $file, string $function) + { + if (!array_key_exists($hook, self::$hooks)) { + self::$hooks[$hook] = []; + } + self::$hooks[$hook][] = [$file, $function]; + } + /** * Registers a hook. * + * This function is meant to be called once when an addon is enabled for example as it doesn't add to the current hooks. + * * @param string $hook the name of the hook * @param string $file the name of the file that hooks into * @param string $function the name of the function that the hook will call * @param int $priority A priority (defaults to 0) * @return mixed|bool + * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function register($hook, $file, $function, $priority = 0) + public static function register(string $hook, string $file, string $function, int $priority = 0) { - $file = str_replace(self::getApp()->getBasePath() . DIRECTORY_SEPARATOR, '', $file); + $file = str_replace(DI::app()->getBasePath() . DIRECTORY_SEPARATOR, '', $file); $condition = ['hook' => $hook, 'file' => $file, 'function' => $function]; if (DBA::exists('hook', $condition)) { return true; } - $result = DBA::insert('hook', ['hook' => $hook, 'file' => $file, 'function' => $function, 'priority' => $priority]); - - return $result; + return self::insert(['hook' => $hook, 'file' => $file, 'function' => $function, 'priority' => $priority]); } /** @@ -76,18 +112,19 @@ class Hook extends BaseObject * @param string $file the name of the file that hooks into * @param string $function the name of the function that the hook called * @return boolean + * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function unregister($hook, $file, $function) + public static function unregister(string $hook, string $file, string $function): bool { - $relative_file = str_replace(self::getApp()->getBasePath() . DIRECTORY_SEPARATOR, '', $file); + $relative_file = str_replace(DI::app()->getBasePath() . DIRECTORY_SEPARATOR, '', $file); // This here is only needed for fixing a problem that existed on the develop branch $condition = ['hook' => $hook, 'file' => $file, 'function' => $function]; - DBA::delete('hook', $condition); + self::delete($condition); $condition = ['hook' => $hook, 'file' => $relative_file, 'function' => $function]; - $result = DBA::delete('hook', $condition); - return $result; + + return self::delete($condition); } /** @@ -96,7 +133,7 @@ class Hook extends BaseObject * @param string $name Name of the hook * @return array */ - public static function getByName($name) + public static function getByName(string $name): array { $return = []; @@ -108,64 +145,85 @@ class Hook extends BaseObject } /** - * @brief Forks a hook. + * Forks a hook. * * Use this function when you want to fork a hook via the worker. * * @param integer $priority of the hook * @param string $name of the hook to call * @param mixed $data to transmit to the callback handler + * @return void + * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function fork($priority, $name, $data = null) + public static function fork(int $priority, string $name, $data = null) { if (array_key_exists($name, self::$hooks)) { foreach (self::$hooks[$name] as $hook) { + // Call a hook to check if this hook call needs to be forked + if (array_key_exists('hook_fork', self::$hooks)) { + $hookdata = ['name' => $name, 'data' => $data, 'execute' => true]; + + foreach (self::$hooks['hook_fork'] as $fork_hook) { + if ($hook[0] != $fork_hook[0]) { + continue; + } + self::callSingle('hook_fork', $fork_hook, $hookdata); + } + + if (!$hookdata['execute']) { + continue; + } + } + Worker::add($priority, 'ForkHook', $name, $hook, $data); } } } /** - * @brief Calls a hook. + * Calls a hook. * * Use this function when you want to be able to allow a hook to manipulate * the provided data. * - * @param string $name of the hook to call + * @param string $name of the hook to call * @param string|array &$data to transmit to the callback handler + * @return void + * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function callAll($name, &$data = null) + public static function callAll(string $name, &$data = null) { if (array_key_exists($name, self::$hooks)) { foreach (self::$hooks[$name] as $hook) { - self::callSingle(self::getApp(), $name, $hook, $data); + self::callSingle($name, $hook, $data); } } } /** - * @brief Calls a single hook. + * Calls a single hook. * - * @param App $a - * @param string $name of the hook to call - * @param array $hook Hook data + * @param string $name of the hook to call + * @param array $hook Hook data * @param string|array &$data to transmit to the callback handler + * @return void + * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function callSingle(App $a, $name, $hook, &$data = null) + public static function callSingle(string $name, array $hook, &$data = null) { // Don't run a theme's hook if the user isn't using the theme - if (strpos($hook[0], 'view/theme/') !== false && strpos($hook[0], 'view/theme/' . $a->getCurrentTheme()) === false) { + if (strpos($hook[0], 'view/theme/') !== false && strpos($hook[0], 'view/theme/' . DI::app()->getCurrentTheme()) === false) { return; } @include_once($hook[0]); if (function_exists($hook[1])) { $func = $hook[1]; - $func($a, $data); + $func($data); } else { // remove orphan hooks $condition = ['hook' => $name, 'file' => $hook[0], 'function' => $hook[1]]; - DBA::delete('hook', $condition, ['cascade' => false]); + self::delete($condition); } } @@ -176,8 +234,10 @@ class Hook extends BaseObject * @param string $name Name of the addon * @return boolean */ - public static function isAddonApp($name) + public static function isAddonApp(string $name): bool { + $name = Strings::sanitizeFilePathItem($name); + if (array_key_exists('app_menu', self::$hooks)) { foreach (self::$hooks['app_menu'] as $hook) { if ($hook[0] == 'addon/' . $name . '/' . $name . '.php') { @@ -188,4 +248,44 @@ class Hook extends BaseObject return false; } + + /** + * Deletes one or more hook records + * + * We have to clear the cached routerDispatchData because addons can provide routes + * + * @param array $condition + * @return bool + * @throws \Exception + */ + public static function delete(array $condition): bool + { + $result = DBA::delete('hook', $condition); + + if ($result) { + DI::cache()->delete('routerDispatchData'); + } + + return $result; + } + + /** + * Inserts a hook record + * + * We have to clear the cached routerDispatchData because addons can provide routes + * + * @param array $condition + * @return bool + * @throws \Exception + */ + private static function insert(array $condition): bool + { + $result = DBA::insert('hook', $condition); + + if ($result) { + DI::cache()->delete('routerDispatchData'); + } + + return $result; + } }