X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FCore%2FAddon.php;h=a06982820e11530dd8e605789b3150d48bb3f42c;hb=4bf27019125f0426aef952f3bbb166b3bd12ca46;hp=f9a21d429c63aa15a813c0760bd6bf6514c1401c;hpb=213f6ae1a14cb646a0a0fcf0d115a65d3693525f;p=friendica.git diff --git a/src/Core/Addon.php b/src/Core/Addon.php index f9a21d429c..a06982820e 100644 --- a/src/Core/Addon.php +++ b/src/Core/Addon.php @@ -1,300 +1,340 @@ - $plugin]); - - @include_once('addon/' . $plugin . '/' . $plugin . '.php'); - if (function_exists($plugin . '_uninstall')) { - $func = $plugin . '_uninstall'; - $func(); - } - } - - /** - * @brief installs an addon. - * - * @param string $plugin name of the addon - * @return bool - */ - function install_plugin($plugin) { - // silently fail if plugin was removed - - if (!file_exists('addon/' . $plugin . '/' . $plugin . '.php')) { - return false; - } - logger("Addons: installing " . $plugin); - $t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php'); - @include_once('addon/' . $plugin . '/' . $plugin . '.php'); - if (function_exists($plugin . '_install')) { - $func = $plugin . '_install'; - $func(); - - $plugin_admin = (function_exists($plugin."_plugin_admin") ? 1 : 0); - - dba::insert('addon', ['name' => $plugin, 'installed' => true, - 'timestamp' => $t, 'plugin_admin' => $plugin_admin]); - - // we can add the following with the previous SQL - // once most site tables have been updated. - // This way the system won't fall over dead during the update. - - if (file_exists('addon/' . $plugin . '/.hidden')) { - dba::update('addon', ['hidden' => true], ['name' => $plugin]); - } - return true; - } else { - logger("Addons: FAILED installing " . $plugin); - return false; - } - } - - // reload all updated plugins - - function reload_plugins() { - $plugins = Config::get('system', 'addon'); - if (strlen($plugins)) { - - $r = q("SELECT * FROM `addon` WHERE `installed` = 1"); - if (DBM::is_result($r)) { - $installed = $r; - } else { - $installed = []; - } - - $parr = explode(',',$plugins); - - if (count($parr)) { - foreach ($parr as $pl) { - - $pl = trim($pl); - - $fname = 'addon/' . $pl . '/' . $pl . '.php'; - - if (file_exists($fname)) { - $t = @filemtime($fname); - foreach ($installed as $i) { - if (($i['name'] == $pl) && ($i['timestamp'] != $t)) { - logger('Reloading plugin: ' . $i['name']); - @include_once($fname); - - if (function_exists($pl . '_uninstall')) { - $func = $pl . '_uninstall'; - $func(); - } - if (function_exists($pl . '_install')) { - $func = $pl . '_install'; - $func(); - } - dba::update('addon', ['timestamp' => $t], ['id' => $i['id']]); - } - } - } - } - } - } - - } - - /** - * @brief check if addon is enabled - * - * @param string $plugin - * @return boolean - */ - function plugin_enabled($plugin) { - return dba::exists('addon', ['installed' => true, 'name' => $plugin]); - } - - - /** - * @brief registers a hook. - * - * @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 - */ - function register_hook($hook, $file, $function, $priority=0) { - $condition = ['hook' => $hook, 'file' => $file, 'function' => $function]; - $exists = dba::exists('hook', $condition); - if ($exists) { - return true; - } - - $r = dba::insert('hook', ['hook' => $hook, 'file' => $file, 'function' => $function, 'priority' => $priority]); - - return $r; - } - - /** - * @brief unregisters a hook. - * - * @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 called - * @return array - */ - function unregister_hook($hook, $file, $function) { - $condition = ['hook' => $hook, 'file' => $file, 'function' => $function]; - $r = dba::delete('hook', $condition); - return $r; - } - - - function load_hooks() { - $a = get_app(); - $a->hooks = []; - $r = dba::select('hook', ['hook', 'file', 'function'], [], ['order' => ['priority' => 'desc', 'file']]); - - while ($rr = dba::fetch($r)) { - if (! array_key_exists($rr['hook'],$a->hooks)) { - $a->hooks[$rr['hook']] = []; - } - $a->hooks[$rr['hook']][] = [$rr['file'],$rr['function']]; - } - dba::close($r); - } - - /** - * @brief 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|array &$data to transmit to the callback handler - */ - function call_hooks($name, &$data = null) - { - $a = get_app(); - - if (is_array($a->hooks) && array_key_exists($name, $a->hooks)) { - foreach ($a->hooks[$name] as $hook) { - call_single_hook($a, $name, $hook, $data); - } - } - } - - /** - * @brief Calls a single hook. - * - * @param string $name of the hook to call - * @param array $hook Hook data - * @param string|array &$data to transmit to the callback handler - */ - function call_single_hook($a, $name, $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/'.current_theme()) === false) - return; - - @include_once($hook[0]); - if (function_exists($hook[1])) { - $func = $hook[1]; - $func($a, $data); - } else { - // remove orphan hooks - $condition = ['hook' => $name, 'file' => $hook[0], 'function' => $hook[1]]; - dba::delete('hook', $condition); - } - } - - //check if an app_menu hook exist for plugin $name. - //Return true if the plugin is an app - function plugin_is_app($name) { - $a = get_app(); - - if (is_array($a->hooks) && (array_key_exists('app_menu',$a->hooks))) { - foreach ($a->hooks['app_menu'] as $hook) { - if ($hook[0] == 'addon/'.$name.'/'.$name.'.php') - return true; - } - } - - return false; - } - - /** - * @brief Parse plugin comment in search of plugin infos. - * - * like - * \code - *...* Name: Plugin - * * Description: A plugin which plugs in - * . * Version: 1.2.3 - * * Author: John - * * Author: Jane - * * - * *\endcode - * @param string $plugin the name of the plugin - * @return array with the plugin information - */ - - function get_plugin_info($plugin) { - - $a = get_app(); - - $info=[ - 'name' => $plugin, - 'description' => "", - 'author' => [], - 'version' => "", - 'status' => "" - ]; - - if (!is_file("addon/$plugin/$plugin.php")) return $info; - - $stamp1 = microtime(true); - $f = file_get_contents("addon/$plugin/$plugin.php"); - $a->save_timestamp($stamp1, "file"); - - $r = preg_match("|/\*.*\*/|msU", $f, $m); - - if ($r) { - $ll = explode("\n", $m[0]); - foreach ( $ll as $l ) { - $l = trim($l,"\t\n\r */"); - if ($l != "") { - list($k,$v) = array_map("trim", explode(":",$l,2)); - $k= strtolower($k); - if ($k == "author") { - $r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); - if ($r) { - $info['author'][] = ['name'=>$m[1], 'link'=>$m[2]]; - } else { - $info['author'][] = ['name'=>$v]; - } - } else { - if (array_key_exists($k,$info)) { - $info[$k]=$v; - } - } - - } - } - - } - return $info; - } -} + 1]); + if (DBA::isResult($r)) { + $installed_addons = DBA::toArray($r); + } + + $addons = Config::get('system', 'addon'); + $addons_arr = []; + + if ($addons) { + $addons_arr = explode(',', str_replace(' ', '', $addons)); + } + + self::$addons = $addons_arr; + + $installed_arr = []; + + foreach ($installed_addons as $addon) { + if (!self::isEnabled($addon['name'])) { + self::uninstall($addon['name']); + } else { + $installed_arr[] = $addon['name']; + } + } + + foreach (self::$addons as $p) { + if (!in_array($p, $installed_arr)) { + self::install($p); + } + } + } + + /** + * @brief uninstalls an addon. + * + * @param string $addon name of the addon + * @return boolean + */ + public static function uninstall($addon) + { + Logger::log("Addons: uninstalling " . $addon); + DBA::delete('addon', ['name' => $addon]); + + @include_once('addon/' . $addon . '/' . $addon . '.php'); + if (function_exists($addon . '_uninstall')) { + $func = $addon . '_uninstall'; + $func(); + } + + unset(self::$addons[array_search($addon, self::$addons)]); + } + + /** + * @brief installs an addon. + * + * @param string $addon name of the addon + * @return bool + */ + public static function install($addon) + { + // silently fail if addon was removed + + if (!file_exists('addon/' . $addon . '/' . $addon . '.php')) { + return false; + } + Logger::log("Addons: installing " . $addon); + $t = @filemtime('addon/' . $addon . '/' . $addon . '.php'); + @include_once('addon/' . $addon . '/' . $addon . '.php'); + if (function_exists($addon . '_install')) { + $func = $addon . '_install'; + $func(); + + $addon_admin = (function_exists($addon . "_addon_admin") ? 1 : 0); + + DBA::insert('addon', ['name' => $addon, 'installed' => true, + 'timestamp' => $t, 'plugin_admin' => $addon_admin]); + + // we can add the following with the previous SQL + // once most site tables have been updated. + // This way the system won't fall over dead during the update. + + if (file_exists('addon/' . $addon . '/.hidden')) { + DBA::update('addon', ['hidden' => true], ['name' => $addon]); + } + + if (!self::isEnabled($addon)) { + self::$addons[] = $addon; + } + return true; + } else { + Logger::log("Addons: FAILED installing " . $addon); + return false; + } + } + + /** + * reload all updated addons + */ + public static function reload() + { + $addons = Config::get('system', 'addon'); + if (strlen($addons)) { + $r = DBA::select('addon', [], ['installed' => 1]); + if (DBA::isResult($r)) { + $installed = DBA::toArray($r); + } else { + $installed = []; + } + + $addon_list = explode(',', $addons); + + if (count($addon_list)) { + foreach ($addon_list as $addon) { + $addon = trim($addon); + $fname = 'addon/' . $addon . '/' . $addon . '.php'; + + if (file_exists($fname)) { + $t = @filemtime($fname); + foreach ($installed as $i) { + if (($i['name'] == $addon) && ($i['timestamp'] != $t)) { + Logger::log('Reloading addon: ' . $i['name']); + @include_once($fname); + + if (function_exists($addon . '_uninstall')) { + $func = $addon . '_uninstall'; + $func(); + } + if (function_exists($addon . '_install')) { + $func = $addon . '_install'; + $func(); + } + DBA::update('addon', ['timestamp' => $t], ['id' => $i['id']]); + } + } + } + } + } + } + } + + /** + * @brief Parse addon comment in search of addon infos. + * + * like + * \code + * * Name: addon + * * Description: An addon which plugs in + * . * Version: 1.2.3 + * * Author: John + * * Author: Jane + * * Maintainer: Jess + * * + * *\endcode + * @param string $addon the name of the addon + * @return array with the addon information + */ + public static function getInfo($addon) + { + $a = self::getApp(); + + $info = [ + 'name' => $addon, + 'description' => "", + 'author' => [], + 'maintainer' => [], + 'version' => "", + 'status' => "" + ]; + + if (!is_file("addon/$addon/$addon.php")) { + return $info; + } + + $stamp1 = microtime(true); + $f = file_get_contents("addon/$addon/$addon.php"); + $a->saveTimestamp($stamp1, "file"); + + $r = preg_match("|/\*.*\*/|msU", $f, $m); + + if ($r) { + $ll = explode("\n", $m[0]); + foreach ($ll as $l) { + $l = trim($l, "\t\n\r */"); + if ($l != "") { + $addon_info = array_map("trim", explode(":", $l, 2)); + if (count($addon_info) < 2) { + continue; + } + + list($type, $v) = $addon_info; + $type = strtolower($type); + if ($type == "author" || $type == "maintainer") { + $r = preg_match("|([^<]+)<([^>]+)>|", $v, $m); + if ($r) { + $info[$type][] = ['name' => $m[1], 'link' => $m[2]]; + } else { + $info[$type][] = ['name' => $v]; + } + } else { + if (array_key_exists($type, $info)) { + $info[$type] = $v; + } + } + } + } + } + return $info; + } + + /** + * Checks if the provided addon is enabled + * + * @param string $addon + * @return boolean + */ + public static function isEnabled($addon) + { + return in_array($addon, self::$addons); + } + + /** + * Returns a list of the enabled addon names + * + * @return array + */ + public static function getEnabledList() + { + return self::$addons; + } + + /** + * Saves the current enabled addon list in the system.addon config key + * + * @return boolean + */ + public static function saveEnabledList() + { + return Config::set("system", "addon", implode(", ", self::$addons)); + } + + /** + * Returns the list of non-hidden enabled addon names + * + * @return array + */ + public static function getVisibleList() + { + $visible_addons = []; + $stmt = DBA::select('addon', ['name'], ['hidden' => false, 'installed' => true]); + if (DBA::isResult($stmt)) { + foreach (DBA::toArray($stmt) as $addon) { + $visible_addons[] = $addon['name']; + } + } + + return $visible_addons; + } + + /** + * Shim of Hook::register left for backward compatibility purpose. + * + * @see Hook::register + * @deprecated since version 2018.12 + * @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 + */ + public static function registerHook($hook, $file, $function, $priority = 0) + { + return Hook::register($hook, $file, $function, $priority); + } + + /** + * Shim of Hook::unregister left for backward compatibility purpose. + * + * @see Hook::unregister + * @deprecated since version 2018.12 + * @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 called + * @return boolean + */ + public static function unregisterHook($hook, $file, $function) + { + return Hook::unregister($hook, $file, $function); + } + + /** + * Shim of Hook::callAll left for backward-compatibility purpose. + * + * @see Hook::callAll + * @deprecated since version 2018.12 + * @param string $name of the hook to call + * @param string|array &$data to transmit to the callback handler + */ + public static function callHooks($name, &$data = null) + { + Hook::callAll($name, $data); + } +}