mirror of
https://git.tt-rss.org/fox/tt-rss.git
synced 2025-10-12 03:20:59 +02:00
Runs HTML and enclosures array through a plugin hook when rendering an article's enclosures in format_article_enclosures(). Allows plugins to override handling of how enclosures are presented by either filtering the array of enclosures, or generating the HTML to add to the article content.
402 lines
9.2 KiB
PHP
402 lines
9.2 KiB
PHP
<?php
|
|
class PluginHost {
|
|
private $dbh;
|
|
private $hooks = array();
|
|
private $plugins = array();
|
|
private $handlers = array();
|
|
private $commands = array();
|
|
private $storage = array();
|
|
private $feeds = array();
|
|
private $api_methods = array();
|
|
private $owner_uid;
|
|
private $debug;
|
|
private $last_registered;
|
|
private static $instance;
|
|
|
|
const API_VERSION = 2;
|
|
|
|
const HOOK_ARTICLE_BUTTON = 1;
|
|
const HOOK_ARTICLE_FILTER = 2;
|
|
const HOOK_PREFS_TAB = 3;
|
|
const HOOK_PREFS_TAB_SECTION = 4;
|
|
const HOOK_PREFS_TABS = 5;
|
|
const HOOK_FEED_PARSED = 6;
|
|
const HOOK_UPDATE_TASK = 7;
|
|
const HOOK_AUTH_USER = 8;
|
|
const HOOK_HOTKEY_MAP = 9;
|
|
const HOOK_RENDER_ARTICLE = 10;
|
|
const HOOK_RENDER_ARTICLE_CDM = 11;
|
|
const HOOK_FEED_FETCHED = 12;
|
|
const HOOK_SANITIZE = 13;
|
|
const HOOK_RENDER_ARTICLE_API = 14;
|
|
const HOOK_TOOLBAR_BUTTON = 15;
|
|
const HOOK_ACTION_ITEM = 16;
|
|
const HOOK_HEADLINE_TOOLBAR_BUTTON = 17;
|
|
const HOOK_HOTKEY_INFO = 18;
|
|
const HOOK_ARTICLE_LEFT_BUTTON = 19;
|
|
const HOOK_PREFS_EDIT_FEED = 20;
|
|
const HOOK_PREFS_SAVE_FEED = 21;
|
|
const HOOK_FETCH_FEED = 22;
|
|
const HOOK_QUERY_HEADLINES = 23;
|
|
const HOOK_HOUSE_KEEPING = 24;
|
|
const HOOK_SEARCH = 25;
|
|
const HOOK_FORMAT_ENCLOSURES = 26;
|
|
|
|
const KIND_ALL = 1;
|
|
const KIND_SYSTEM = 2;
|
|
const KIND_USER = 3;
|
|
|
|
function __construct() {
|
|
$this->dbh = Db::get();
|
|
|
|
$this->storage = array();
|
|
}
|
|
|
|
private function __clone() {
|
|
//
|
|
}
|
|
|
|
public static function getInstance() {
|
|
if (self::$instance == null)
|
|
self::$instance = new self();
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
private function register_plugin($name, $plugin) {
|
|
//array_push($this->plugins, $plugin);
|
|
$this->plugins[$name] = $plugin;
|
|
}
|
|
|
|
// needed for compatibility with API 1
|
|
function get_link() {
|
|
return false;
|
|
}
|
|
|
|
function get_dbh() {
|
|
return $this->dbh;
|
|
}
|
|
|
|
function get_plugin_names() {
|
|
$names = array();
|
|
|
|
foreach ($this->plugins as $p) {
|
|
array_push($names, get_class($p));
|
|
}
|
|
|
|
return $names;
|
|
}
|
|
|
|
function get_plugins() {
|
|
return $this->plugins;
|
|
}
|
|
|
|
function get_plugin($name) {
|
|
return $this->plugins[$name];
|
|
}
|
|
|
|
function run_hooks($type, $method, $args) {
|
|
foreach ($this->get_hooks($type) as $hook) {
|
|
$hook->$method($args);
|
|
}
|
|
}
|
|
|
|
function add_hook($type, $sender) {
|
|
if (!is_array($this->hooks[$type])) {
|
|
$this->hooks[$type] = array();
|
|
}
|
|
|
|
array_push($this->hooks[$type], $sender);
|
|
}
|
|
|
|
function del_hook($type, $sender) {
|
|
if (is_array($this->hooks[$type])) {
|
|
$key = array_Search($sender, $this->hooks[$type]);
|
|
if ($key !== FALSE) {
|
|
unset($this->hooks[$type][$key]);
|
|
}
|
|
}
|
|
}
|
|
|
|
function get_hooks($type) {
|
|
if (isset($this->hooks[$type])) {
|
|
return $this->hooks[$type];
|
|
} else {
|
|
return array();
|
|
}
|
|
}
|
|
function load_all($kind, $owner_uid = false) {
|
|
$plugins = array_map("basename", glob("plugins/*"));
|
|
$this->load(join(",", $plugins), $kind, $owner_uid);
|
|
}
|
|
|
|
function load($classlist, $kind, $owner_uid = false) {
|
|
$plugins = explode(",", $classlist);
|
|
|
|
$this->owner_uid = (int) $owner_uid;
|
|
|
|
foreach ($plugins as $class) {
|
|
$class = trim($class);
|
|
$class_file = strtolower(basename($class));
|
|
|
|
if (!is_dir(dirname(__FILE__)."/../plugins/$class_file")) continue;
|
|
|
|
$file = dirname(__FILE__)."/../plugins/$class_file/init.php";
|
|
|
|
if (!isset($this->plugins[$class])) {
|
|
if (file_exists($file)) require_once $file;
|
|
|
|
if (class_exists($class) && is_subclass_of($class, "Plugin")) {
|
|
$plugin = new $class($this);
|
|
|
|
$plugin_api = $plugin->api_version();
|
|
|
|
if ($plugin_api < PluginHost::API_VERSION) {
|
|
user_error("Plugin $class is not compatible with current API version (need: " . PluginHost::API_VERSION . ", got: $plugin_api)", E_USER_WARNING);
|
|
continue;
|
|
}
|
|
|
|
$this->last_registered = $class;
|
|
|
|
switch ($kind) {
|
|
case $this::KIND_SYSTEM:
|
|
if ($this->is_system($plugin)) {
|
|
$plugin->init($this);
|
|
$this->register_plugin($class, $plugin);
|
|
}
|
|
break;
|
|
case $this::KIND_USER:
|
|
if (!$this->is_system($plugin)) {
|
|
$plugin->init($this);
|
|
$this->register_plugin($class, $plugin);
|
|
}
|
|
break;
|
|
case $this::KIND_ALL:
|
|
$plugin->init($this);
|
|
$this->register_plugin($class, $plugin);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function is_system($plugin) {
|
|
$about = $plugin->about();
|
|
|
|
return @$about[3];
|
|
}
|
|
|
|
// only system plugins are allowed to modify routing
|
|
function add_handler($handler, $method, $sender) {
|
|
$handler = str_replace("-", "_", strtolower($handler));
|
|
$method = strtolower($method);
|
|
|
|
if ($this->is_system($sender)) {
|
|
if (!is_array($this->handlers[$handler])) {
|
|
$this->handlers[$handler] = array();
|
|
}
|
|
|
|
$this->handlers[$handler][$method] = $sender;
|
|
}
|
|
}
|
|
|
|
function del_handler($handler, $method, $sender) {
|
|
$handler = str_replace("-", "_", strtolower($handler));
|
|
$method = strtolower($method);
|
|
|
|
if ($this->is_system($sender)) {
|
|
unset($this->handlers[$handler][$method]);
|
|
}
|
|
}
|
|
|
|
function lookup_handler($handler, $method) {
|
|
$handler = str_replace("-", "_", strtolower($handler));
|
|
$method = strtolower($method);
|
|
|
|
if (is_array($this->handlers[$handler])) {
|
|
if (isset($this->handlers[$handler]["*"])) {
|
|
return $this->handlers[$handler]["*"];
|
|
} else {
|
|
return $this->handlers[$handler][$method];
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function add_command($command, $description, $sender, $suffix = "", $arghelp = "") {
|
|
$command = str_replace("-", "_", strtolower($command));
|
|
|
|
$this->commands[$command] = array("description" => $description,
|
|
"suffix" => $suffix,
|
|
"arghelp" => $arghelp,
|
|
"class" => $sender);
|
|
}
|
|
|
|
function del_command($command) {
|
|
$command = "-" . strtolower($command);
|
|
|
|
unset($this->commands[$command]);
|
|
}
|
|
|
|
function lookup_command($command) {
|
|
$command = "-" . strtolower($command);
|
|
|
|
if (is_array($this->commands[$command])) {
|
|
return $this->commands[$command]["class"];
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function get_commands() {
|
|
return $this->commands;
|
|
}
|
|
|
|
function run_commands($args) {
|
|
foreach ($this->get_commands() as $command => $data) {
|
|
if (isset($args[$command])) {
|
|
$command = str_replace("-", "", $command);
|
|
$data["class"]->$command($args);
|
|
}
|
|
}
|
|
}
|
|
|
|
function load_data($force = false) {
|
|
if ($this->owner_uid) {
|
|
$result = $this->dbh->query("SELECT name, content FROM ttrss_plugin_storage
|
|
WHERE owner_uid = '".$this->owner_uid."'");
|
|
|
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
|
$this->storage[$line["name"]] = unserialize($line["content"]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function save_data($plugin) {
|
|
if ($this->owner_uid) {
|
|
$plugin = $this->dbh->escape_string($plugin);
|
|
|
|
$this->dbh->query("BEGIN");
|
|
|
|
$result = $this->dbh->query("SELECT id FROM ttrss_plugin_storage WHERE
|
|
owner_uid= '".$this->owner_uid."' AND name = '$plugin'");
|
|
|
|
if (!isset($this->storage[$plugin]))
|
|
$this->storage[$plugin] = array();
|
|
|
|
$content = $this->dbh->escape_string(serialize($this->storage[$plugin]),
|
|
false);
|
|
|
|
if ($this->dbh->num_rows($result) != 0) {
|
|
$this->dbh->query("UPDATE ttrss_plugin_storage SET content = '$content'
|
|
WHERE owner_uid= '".$this->owner_uid."' AND name = '$plugin'");
|
|
|
|
} else {
|
|
$this->dbh->query("INSERT INTO ttrss_plugin_storage
|
|
(name,owner_uid,content) VALUES
|
|
('$plugin','".$this->owner_uid."','$content')");
|
|
}
|
|
|
|
$this->dbh->query("COMMIT");
|
|
}
|
|
}
|
|
|
|
function set($sender, $name, $value, $sync = true) {
|
|
$idx = get_class($sender);
|
|
|
|
if (!isset($this->storage[$idx]))
|
|
$this->storage[$idx] = array();
|
|
|
|
$this->storage[$idx][$name] = $value;
|
|
|
|
if ($sync) $this->save_data(get_class($sender));
|
|
}
|
|
|
|
function get($sender, $name, $default_value = false) {
|
|
$idx = get_class($sender);
|
|
|
|
if (isset($this->storage[$idx][$name])) {
|
|
return $this->storage[$idx][$name];
|
|
} else {
|
|
return $default_value;
|
|
}
|
|
}
|
|
|
|
function get_all($sender) {
|
|
$idx = get_class($sender);
|
|
|
|
return $this->storage[$idx];
|
|
}
|
|
|
|
function clear_data($sender) {
|
|
if ($this->owner_uid) {
|
|
$idx = get_class($sender);
|
|
|
|
unset($this->storage[$idx]);
|
|
|
|
$this->dbh->query("DELETE FROM ttrss_plugin_storage WHERE name = '$idx'
|
|
AND owner_uid = " . $this->owner_uid);
|
|
}
|
|
}
|
|
|
|
function set_debug($debug) {
|
|
$this->debug = $debug;
|
|
}
|
|
|
|
function get_debug() {
|
|
return $this->debug;
|
|
}
|
|
|
|
// Plugin feed functions are *EXPERIMENTAL*!
|
|
|
|
// cat_id: only -1 is supported (Special)
|
|
function add_feed($cat_id, $title, $icon, $sender) {
|
|
if (!$this->feeds[$cat_id]) $this->feeds[$cat_id] = array();
|
|
|
|
$id = count($this->feeds[$cat_id]);
|
|
|
|
array_push($this->feeds[$cat_id],
|
|
array('id' => $id, 'title' => $title, 'sender' => $sender, 'icon' => $icon));
|
|
|
|
return $id;
|
|
}
|
|
|
|
function get_feeds($cat_id) {
|
|
return $this->feeds[$cat_id];
|
|
}
|
|
|
|
// convert feed_id (e.g. -129) to pfeed_id first
|
|
function get_feed_handler($pfeed_id) {
|
|
foreach ($this->feeds as $cat) {
|
|
foreach ($cat as $feed) {
|
|
if ($feed['id'] == $pfeed_id) {
|
|
return $feed['sender'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static function pfeed_to_feed_id($label) {
|
|
return PLUGIN_FEED_BASE_INDEX - 1 - abs($label);
|
|
}
|
|
|
|
static function feed_to_pfeed_id($feed) {
|
|
return PLUGIN_FEED_BASE_INDEX - 1 + abs($feed);
|
|
}
|
|
|
|
function add_api_method($name, $sender) {
|
|
if ($this->is_system($sender)) {
|
|
$this->api_methods[strtolower($name)] = $sender;
|
|
}
|
|
}
|
|
|
|
function get_api_method($name) {
|
|
return $this->api_methods[$name];
|
|
}
|
|
}
|
|
?>
|