Move hook-related methods from Core\Addon to Core\Hook

This commit is contained in:
Hypolite Petovan 2018-10-21 01:15:02 -04:00
parent 0aa7671119
commit ca9cad3491
9 changed files with 153 additions and 242 deletions

View File

@ -214,11 +214,12 @@ function admin_content(App $a)
$r = q("SELECT `name` FROM `addon` WHERE `plugin_admin` = 1 ORDER BY `name`"); $r = q("SELECT `name` FROM `addon` WHERE `plugin_admin` = 1 ORDER BY `name`");
$aside_tools['addons_admin'] = []; $aside_tools['addons_admin'] = [];
$addons_admin = [];
foreach ($r as $h) { foreach ($r as $h) {
$addon = $h['name']; $addon = $h['name'];
$aside_tools['addons_admin'][] = ["admin/addons/" . $addon, $addon, "addon"]; $aside_tools['addons_admin'][] = ["admin/addons/" . $addon, $addon, "addon"];
// temp addons with admin // temp addons with admin
$a->addons_admin[] = $addon; $addons_admin[] = $addon;
} }
$t = get_markup_template('admin/aside.tpl'); $t = get_markup_template('admin/aside.tpl');
@ -243,7 +244,7 @@ function admin_content(App $a)
$o = admin_page_users($a); $o = admin_page_users($a);
break; break;
case 'addons': case 'addons':
$o = admin_page_addons($a); $o = admin_page_addons($a, $addons_admin);
break; break;
case 'themes': case 'themes':
$o = admin_page_themes($a); $o = admin_page_themes($a);
@ -932,7 +933,7 @@ function admin_page_summary(App $a)
'$platform' => FRIENDICA_PLATFORM, '$platform' => FRIENDICA_PLATFORM,
'$codename' => FRIENDICA_CODENAME, '$codename' => FRIENDICA_CODENAME,
'$build' => Config::get('system', 'build'), '$build' => Config::get('system', 'build'),
'$addons' => [L10n::t('Active addons'), $a->addons], '$addons' => [L10n::t('Active addons'), Addon::getEnabledList()],
'$serversettings' => $server_settings, '$serversettings' => $server_settings,
'$showwarning' => $showwarning, '$showwarning' => $showwarning,
'$warningtext' => $warningtext '$warningtext' => $warningtext
@ -1957,9 +1958,10 @@ function admin_page_users(App $a)
* The returned string returned hulds the HTML code of the page. * The returned string returned hulds the HTML code of the page.
* *
* @param App $a * @param App $a
* @param array $addons_admin A list of admin addon names
* @return string * @return string
*/ */
function admin_page_addons(App $a) function admin_page_addons(App $a, array $addons_admin)
{ {
/* /*
* Single addon * Single addon
@ -1971,27 +1973,25 @@ function admin_page_addons(App $a)
return ''; return '';
} }
if (x($_GET, "a") && $_GET['a'] == "t") { if (defaults($_GET, 'a', '') == "t") {
BaseModule::checkFormSecurityTokenRedirectOnError('/admin/addons', 'admin_themes', 't'); BaseModule::checkFormSecurityTokenRedirectOnError('/admin/addons', 'admin_themes', 't');
// Toggle addon status // Toggle addon status
$idx = array_search($addon, $a->addons); if (Addon::isEnabled($addon)) {
if ($idx !== false) {
unset($a->addons[$idx]);
Addon::uninstall($addon); Addon::uninstall($addon);
info(L10n::t("Addon %s disabled.", $addon)); info(L10n::t("Addon %s disabled.", $addon));
} else { } else {
$a->addons[] = $addon;
Addon::install($addon); Addon::install($addon);
info(L10n::t("Addon %s enabled.", $addon)); info(L10n::t("Addon %s enabled.", $addon));
} }
Config::set("system", "addon", implode(", ", $a->addons));
Addon::saveEnabledList();
$a->internalRedirect('admin/addons'); $a->internalRedirect('admin/addons');
return ''; // NOTREACHED return ''; // NOTREACHED
} }
// display addon details // display addon details
if (in_array($addon, $a->addons)) { if (Addon::isEnabled($addon)) {
$status = "on"; $status = "on";
$action = L10n::t("Disable"); $action = L10n::t("Disable");
} else { } else {
@ -2007,7 +2007,7 @@ function admin_page_addons(App $a)
} }
$admin_form = ""; $admin_form = "";
if (in_array($addon, $a->addons_admin)) { if (in_array($addon, $addons_admin)) {
require_once "addon/$addon/$addon.php"; require_once "addon/$addon/$addon.php";
$func = $addon . '_addon_admin'; $func = $addon . '_addon_admin';
$func($a, $admin_form); $func($a, $admin_form);
@ -2058,7 +2058,7 @@ function admin_page_addons(App $a)
$show_addon = true; $show_addon = true;
// If the addon is unsupported, then only show it, when it is enabled // If the addon is unsupported, then only show it, when it is enabled
if ((strtolower($info["status"]) == "unsupported") && !in_array($id, $a->addons)) { if ((strtolower($info["status"]) == "unsupported") && !Addon::isEnabled($id)) {
$show_addon = false; $show_addon = false;
} }
@ -2068,7 +2068,7 @@ function admin_page_addons(App $a)
} }
if ($show_addon) { if ($show_addon) {
$addons[] = [$id, (in_array($id, $a->addons) ? "on" : "off"), $info]; $addons[] = [$id, (Addon::isEnabled($id) ? "on" : "off"), $info];
} }
} }
} }

View File

@ -31,15 +31,7 @@ function friendica_init(App $a)
$admin = false; $admin = false;
} }
$visible_addons = []; $visible_addons = Addon::getVisibleList();
if (is_array($a->addons) && count($a->addons)) {
$r = q("SELECT * FROM `addon` WHERE `hidden` = 0");
if (DBA::isResult($r)) {
foreach ($r as $rr) {
$visible_addons[] = $rr['name'];
}
}
}
Config::load('feature_lock'); Config::load('feature_lock');
$locked_features = []; $locked_features = [];
@ -91,16 +83,7 @@ function friendica_content(App $a)
$o .= L10n::t('Suggestions, praise, etc. - please email "info" at "friendi - dot - ca'); $o .= L10n::t('Suggestions, praise, etc. - please email "info" at "friendi - dot - ca');
$o .= '</p>' . PHP_EOL; $o .= '</p>' . PHP_EOL;
$visible_addons = []; $visible_addons = Addon::getVisibleList();
if (is_array($a->addons) && count($a->addons)) {
$r = q("SELECT * FROM `addon` WHERE `hidden` = 0");
if (DBA::isResult($r)) {
foreach ($r as $rr) {
$visible_addons[] = $rr['name'];
}
}
}
if (count($visible_addons)) { if (count($visible_addons)) {
$o .= '<p>' . L10n::t('Installed addons/apps:') . '</p>' . PHP_EOL; $o .= '<p>' . L10n::t('Installed addons/apps:') . '</p>' . PHP_EOL;
$sorted = $visible_addons; $sorted = $visible_addons;

View File

@ -50,11 +50,8 @@ class App
public $argv; public $argv;
public $argc; public $argc;
public $module; public $module;
public $hooks = [];
public $timezone; public $timezone;
public $interactive = true; public $interactive = true;
public $addons;
public $addons_admin = [];
public $identities; public $identities;
public $is_mobile = false; public $is_mobile = false;
public $is_tablet = false; public $is_tablet = false;
@ -360,7 +357,7 @@ class App
Core\Config::load(); Core\Config::load();
if ($this->getMode()->has(App\Mode::DBAVAILABLE)) { if ($this->getMode()->has(App\Mode::DBAVAILABLE)) {
Core\Addon::loadHooks(); Core\Hook::loadHooks();
$this->loadAddonConfig(); $this->loadAddonConfig();
} }

View File

@ -16,7 +16,14 @@ require_once 'include/dba.php';
class Addon extends BaseObject class Addon extends BaseObject
{ {
/** /**
* @brief Synchronise addons: * List of the names of enabled addons
*
* @var array
*/
private static $addons = [];
/**
* @brief Synchronize addons:
* *
* system.addon contains a comma-separated list of names * system.addon contains a comma-separated list of names
* of addons which are used on this system. * of addons which are used on this system.
@ -27,15 +34,13 @@ class Addon extends BaseObject
* call the install procedure and add it to the database. * call the install procedure and add it to the database.
* *
*/ */
public static function check() public static function loadAddons()
{ {
$a = self::getApp(); $installed_addons = [];
$r = DBA::select('addon', [], ['installed' => 1]); $r = DBA::select('addon', [], ['installed' => 1]);
if (DBA::isResult($r)) { if (DBA::isResult($r)) {
$installed = DBA::toArray($r); $installed_addons = DBA::toArray($r);
} else {
$installed = [];
} }
$addons = Config::get('system', 'addon'); $addons = Config::get('system', 'addon');
@ -45,33 +50,25 @@ class Addon extends BaseObject
$addons_arr = explode(',', str_replace(' ', '', $addons)); $addons_arr = explode(',', str_replace(' ', '', $addons));
} }
$a->addons = $addons_arr; self::$addons = $addons_arr;
$installed_arr = []; $installed_arr = [];
if (count($installed)) { foreach ($installed_addons as $addon) {
foreach ($installed as $i) { if (!self::isEnabled($addon['name'])) {
if (!in_array($i['name'], $addons_arr)) { self::uninstall($addon['name']);
self::uninstall($i['name']);
} else { } else {
$installed_arr[] = $i['name']; $installed_arr[] = $addon['name'];
}
} }
} }
if (count($addons_arr)) { foreach (self::$addons as $p) {
foreach ($addons_arr as $p) {
if (!in_array($p, $installed_arr)) { if (!in_array($p, $installed_arr)) {
self::install($p); self::install($p);
} }
} }
} }
self::loadHooks();
return;
}
/** /**
* @brief uninstalls an addon. * @brief uninstalls an addon.
* *
@ -88,6 +85,8 @@ class Addon extends BaseObject
$func = $addon . '_uninstall'; $func = $addon . '_uninstall';
$func(); $func();
} }
unset(self::$addons[$idx]);
} }
/** /**
@ -122,6 +121,10 @@ class Addon extends BaseObject
if (file_exists('addon/' . $addon . '/.hidden')) { if (file_exists('addon/' . $addon . '/.hidden')) {
DBA::update('addon', ['hidden' => true], ['name' => $addon]); DBA::update('addon', ['hidden' => true], ['name' => $addon]);
} }
if (!self::isEnabled($addon)) {
self::$addons[] = $addon;
}
return true; return true;
} else { } else {
logger("Addons: FAILED installing " . $addon); logger("Addons: FAILED installing " . $addon);
@ -174,165 +177,6 @@ class Addon extends BaseObject
} }
} }
/**
* @brief check if addon is enabled
*
* @param string $addon
* @return boolean
*/
public static function isEnabled($addon)
{
return DBA::exists('addon', ['installed' => true, 'name' => $addon]);
}
/**
* @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
*/
public static function registerHook($hook, $file, $function, $priority = 0)
{
$file = str_replace(self::getApp()->getBasePath() . DIRECTORY_SEPARATOR, '', $file);
$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
*/
public static function unregisterHook($hook, $file, $function)
{
$relative_file = str_replace(self::getApp()->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);
$condition = ['hook' => $hook, 'file' => $relative_file, 'function' => $function];
$r = DBA::delete('hook', $condition);
return $r;
}
/**
* Load hooks
*/
public static function loadHooks()
{
$a = self::getApp();
$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 Forks a hook.
*
* Use this function when you want to fork a hook via the worker.
*
* @param string $name of the hook to call
* @param string|array $data to transmit to the callback handler
*/
public static function forkHooks($priority, $name, $data = null)
{
$a = self::getApp();
if (is_array($a->hooks) && array_key_exists($name, $a->hooks)) {
foreach ($a->hooks[$name] as $hook) {
Worker::add($priority, 'ForkHook', $name, $hook, $data);
}
}
}
/**
* @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
*/
public static function callHooks($name, &$data = null)
{
$a = self::getApp();
if (is_array($a->hooks) && array_key_exists($name, $a->hooks)) {
foreach ($a->hooks[$name] as $hook) {
self::callSingleHook($a, $name, $hook, $data);
}
}
}
/**
* @brief Calls a single hook.
*
* @param App $a
* @param string $name of the hook to call
* @param array $hook Hook data
* @param string|array &$data to transmit to the callback handler
*/
public static function callSingleHook(App $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/' . $a->getCurrentTheme()) === 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, ['cascade' => false]);
}
}
/**
* check if an app_menu hook exist for addon $name.
* Return true if the addon is an app
*/
public static function isApp($name)
{
$a = self::getApp();
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 addon comment in search of addon infos. * @brief Parse addon comment in search of addon infos.
* *
@ -401,4 +245,92 @@ class Addon extends BaseObject
} }
return $info; 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);
}
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);
}
} }

View File

@ -771,7 +771,7 @@ class Post extends BaseObject
* Hmmm, code depending on the presence of a particular addon? * Hmmm, code depending on the presence of a particular addon?
* This should be better if done by a hook * This should be better if done by a hook
*/ */
if (in_array('qcomment', $a->addons)) { if (Addon::isEnabled('qcomment')) {
$qc = ((local_user()) ? PConfig::get(local_user(), 'qcomment', 'words') : null); $qc = ((local_user()) ? PConfig::get(local_user(), 'qcomment', 'words') : null);
$qcomment = (($qc) ? explode("\n", $qc) : null); $qcomment = (($qc) ? explode("\n", $qc) : null);
} }

View File

@ -7,6 +7,7 @@ namespace Friendica\Worker;
use Friendica\BaseObject; use Friendica\BaseObject;
use Friendica\Core\Addon; use Friendica\Core\Addon;
use Friendica\Core\Config; use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\Core\Worker; use Friendica\Core\Worker;
use Friendica\Database\DBA; use Friendica\Database\DBA;
@ -45,7 +46,7 @@ class Cron
logger('cron: start'); logger('cron: start');
// Fork the cron jobs in separate parts to avoid problems when one of them is crashing // Fork the cron jobs in separate parts to avoid problems when one of them is crashing
Addon::forkHooks($a->queue['priority'], "cron"); Hook::fork($a->queue['priority'], "cron");
// run queue delivery process in the background // run queue delivery process in the background
Worker::add(PRIORITY_NEGLIGIBLE, "Queue"); Worker::add(PRIORITY_NEGLIGIBLE, "Queue");

View File

@ -7,8 +7,8 @@
namespace Friendica\Worker; namespace Friendica\Worker;
use Friendica\BaseObject; use Friendica\BaseObject;
use Friendica\Core\Addon;
use Friendica\Core\Config; use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\Worker; use Friendica\Core\Worker;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\Model\Item; use Friendica\Model\Item;
@ -17,13 +17,13 @@ require_once 'include/dba.php';
class Expire class Expire
{ {
public static function execute($param = '', $hook_name = '') public static function execute($param = '', $hook_function = '')
{ {
$a = BaseObject::getApp(); $a = BaseObject::getApp();
require_once 'include/items.php'; require_once 'include/items.php';
Addon::loadHooks(); Hook::loadHooks();
if ($param == 'delete') { if ($param == 'delete') {
logger('Delete expired items', LOGGER_DEBUG); logger('Delete expired items', LOGGER_DEBUG);
@ -62,11 +62,11 @@ class Expire
logger('Expire items for user '.$user['uid'].' ('.$user['username'].') - done ', LOGGER_DEBUG); logger('Expire items for user '.$user['uid'].' ('.$user['username'].') - done ', LOGGER_DEBUG);
} }
return; return;
} elseif (!empty($hook_name) && ($param == 'hook') && is_array($a->hooks) && array_key_exists("expire", $a->hooks)) { } elseif ($param == 'hook' && !empty($hook_function)) {
foreach ($a->hooks["expire"] as $hook) { foreach (Hook::getByName('expire') as $hook) {
if ($hook[1] == $hook_name) { if ($hook[1] == $hook_function) {
logger("Calling expire hook '" . $hook[1] . "'", LOGGER_DEBUG); logger("Calling expire hook '" . $hook[1] . "'", LOGGER_DEBUG);
Addon::callSingleHook($a, $hook_name, $hook, $data); Hook::callSingle($a, 'expire', $hook, $data);
} }
} }
return; return;
@ -86,14 +86,11 @@ class Expire
DBA::close($r); DBA::close($r);
logger('expire: calling hooks'); logger('expire: calling hooks');
foreach (Hook::getByName('expire') as $hook) {
if (is_array($a->hooks) && array_key_exists('expire', $a->hooks)) {
foreach ($a->hooks['expire'] as $hook) {
logger("Calling expire hook for '" . $hook[1] . "'", LOGGER_DEBUG); logger("Calling expire hook for '" . $hook[1] . "'", LOGGER_DEBUG);
Worker::add(['priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true], Worker::add(['priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true],
'Expire', 'hook', $hook[1]); 'Expire', 'hook', $hook[1]);
} }
}
logger('expire: end'); logger('expire: end');

View File

@ -5,7 +5,7 @@
namespace Friendica\Worker; namespace Friendica\Worker;
use Friendica\Core\Addon; use Friendica\Core\Hook;
Class ForkHook Class ForkHook
{ {
@ -13,6 +13,6 @@ Class ForkHook
{ {
$a = \Friendica\BaseObject::getApp(); $a = \Friendica\BaseObject::getApp();
Addon::callSingleHook($a, $name, $hook, $data); Hook::callSingle($a, $name, $hook, $data);
} }
} }

View File

@ -7,10 +7,12 @@ namespace Friendica\Worker;
use Friendica\BaseObject; use Friendica\BaseObject;
use Friendica\Core\Addon; use Friendica\Core\Addon;
use Friendica\Core\Config; use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\Core\Worker; use Friendica\Core\Worker;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\Conversation;
use Friendica\Model\Group; use Friendica\Model\Group;
use Friendica\Model\Item; use Friendica\Model\Item;
use Friendica\Model\PushSubscriber; use Friendica\Model\PushSubscriber;
@ -20,7 +22,6 @@ use Friendica\Protocol\ActivityPub;
use Friendica\Protocol\Diaspora; use Friendica\Protocol\Diaspora;
use Friendica\Protocol\OStatus; use Friendica\Protocol\OStatus;
use Friendica\Protocol\Salmon; use Friendica\Protocol\Salmon;
use Friendica\Model\Conversation;
require_once 'include/dba.php'; require_once 'include/dba.php';
require_once 'include/items.php'; require_once 'include/items.php';
@ -501,7 +502,7 @@ class Notifier
logger('notifier: calling hooks for ' . $cmd . ' ' . $item_id, LOGGER_DEBUG); logger('notifier: calling hooks for ' . $cmd . ' ' . $item_id, LOGGER_DEBUG);
if ($normal_mode) { if ($normal_mode) {
Addon::forkHooks($a->queue['priority'], 'notifier_normal', $target_item); Hook::fork($a->queue['priority'], 'notifier_normal', $target_item);
} }
Addon::callHooks('notifier_end',$target_item); Addon::callHooks('notifier_end',$target_item);