From af2f4460ce94f48aa4c3bb3176c59325b6612b32 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 14 Nov 2021 16:49:10 +0300 Subject: [PATCH] * deal with some phpstan warnings in base plugin class * arguably better hack for incompatible plugins causing E_COMPILE_ERROR --- classes/plugin.php | 94 ++++++++++++++++++++++++++++++++++++++++++ classes/pluginhost.php | 18 +++++--- classes/pref/prefs.php | 2 +- 3 files changed, 108 insertions(+), 6 deletions(-) diff --git a/classes/plugin.php b/classes/plugin.php index 8c14cd78d..b027a05c3 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -140,10 +140,19 @@ abstract class Plugin { user_error("Dummy method invoked.", E_USER_ERROR); } + /** + * @param FeedParser $parser + * @param int $feed_id + * @return void + */ function hook_feed_parsed($parser, $feed_id) { user_error("Dummy method invoked.", E_USER_ERROR); } + /** + * @param array $cli_options + * @return void + */ function hook_update_task($cli_options) { user_error("Dummy method invoked.", E_USER_ERROR); } @@ -170,44 +179,94 @@ abstract class Plugin { return false; } + /** + * @param array $hotkeys + * @return array + */ function hook_hotkey_map($hotkeys) { user_error("Dummy method invoked.", E_USER_ERROR); } + /** + * @param array $article + * @return array + */ function hook_render_article($article) { user_error("Dummy method invoked.", E_USER_ERROR); + + return []; } + /** + * @param array $article + * @return array + */ function hook_render_article_cdm($article) { user_error("Dummy method invoked.", E_USER_ERROR); + + return []; } + /** + * @param string $feed_data + * @param string $fetch_url + * @param int $owner_uid + * @param int $feed + * @return string + */ function hook_feed_fetched($feed_data, $fetch_url, $owner_uid, $feed) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } function hook_sanitize($doc, $site_url, $allowed_elements, $disallowed_attributes, $article_id) { user_error("Dummy method invoked.", E_USER_ERROR); } + /** + * @param array{'article': array} $params + * @return array + */ function hook_render_article_api($params) { user_error("Dummy method invoked.", E_USER_ERROR); + + return []; } + /** @return string */ function hook_toolbar_button() { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } + /** @return string */ function hook_action_item() { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } + /** + * @param int $feed_id + * @param bool $is_cat + * @return string + */ function hook_headline_toolbar_button($feed_id, $is_cat) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } + /** + * @param array $hotkeys + * @return array + */ function hook_hotkey_info($hotkeys) { user_error("Dummy method invoked.", E_USER_ERROR); + + return []; } function hook_article_left_button($row) { @@ -230,6 +289,7 @@ abstract class Plugin { user_error("Dummy method invoked.", E_USER_ERROR); } + /** @return void */ function hook_house_keeping() { user_error("Dummy method invoked.", E_USER_ERROR); } @@ -262,6 +322,7 @@ abstract class Plugin { user_error("Dummy method invoked.", E_USER_ERROR); } + /** @return void */ function hook_main_toolbar_button() { user_error("Dummy method invoked.", E_USER_ERROR); } @@ -296,24 +357,57 @@ abstract class Plugin { user_error("Dummy method invoked.", E_USER_ERROR); } + /** NOTE: $article_filters should be renamed $filter_actions because that's what this is + * @param int $feed_id + * @param int $owner_uid + * @param array $article + * @param array $matched_filters + * @param array $matched_rules + * @param array $article_filters + * @return void + */ function hook_filter_triggered($feed_id, $owner_uid, $article, $matched_filters, $matched_rules, $article_filters) { user_error("Dummy method invoked.", E_USER_ERROR); } + /** + * @param string $url + * @return string + */ function hook_get_full_text($url) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } + /** + * @param array $enclosures + * @param string $content + * @param string $site_url + * @param array $article + * @return string + */ function hook_article_image($enclosures, $content, $site_url, $article) { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } + /** @return string */ function hook_feed_tree() { user_error("Dummy method invoked.", E_USER_ERROR); + + return ""; } + /** + * @param string $url + * @return bool + */ function hook_iframe_whitelisted($url) { user_error("Dummy method invoked.", E_USER_ERROR); + + return false; } function hook_enclosure_imported($enclosure, $feed) { diff --git a/classes/pluginhost.php b/classes/pluginhost.php index 7688a6d0d..4b0c14a35 100755 --- a/classes/pluginhost.php +++ b/classes/pluginhost.php @@ -434,16 +434,24 @@ class PluginHost { // WIP hack // we can't catch incompatible method signatures via Throwable - // maybe also auto-disable user plugin in this situation? idk -fox - if ($_SESSION["plugin_blacklist.$class"] ?? false) { - user_error("Plugin $class has caused a PHP Fatal Error so it won't be loaded again in this session.", E_USER_NOTICE); + // this also enables global tt-rss safe mode in case there are more plugins like this + if (($_SESSION["plugin_blacklist"][$class] ?? 0)) { + + // only report once per-plugin per-session + if ($_SESSION["plugin_blacklist"][$class] < 2) { + user_error("Plugin $class has caused a PHP fatal error so it won't be loaded again in this session.", E_USER_WARNING); + $_SESSION["plugin_blacklist"][$class] = 2; + } + + $_SESSION["safe_mode"] = 1; + continue; } try { - $_SESSION["plugin_blacklist.$class"] = true; + $_SESSION["plugin_blacklist"][$class] = 1; require_once $file; - $_SESSION["plugin_blacklist.$class"] = false; + unset($_SESSION["plugin_blacklist"][$class]); } catch (Error $err) { user_error($err, E_USER_WARNING); diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index 3a39bf981..025d8fda2 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -17,7 +17,7 @@ class Pref_Prefs extends Handler_Protected { const PI_ERR_PLUGIN_NOT_FOUND = "PI_ERR_PLUGIN_NOT_FOUND"; const PI_ERR_NO_WORKDIR = "PI_ERR_NO_WORKDIR"; - function csrf_ignore(string $method): bool { + function csrf_ignore($method) : bool { $csrf_ignored = array("index", "updateself", "otpqrcode"); return array_search($method, $csrf_ignored) !== false;