]> git.wh0rd.org Git - tt-rss.git/blob - classes/pluginhost.php
Merge branch 'master' into tunable-fetches
[tt-rss.git] / classes / pluginhost.php
1 <?php
2 class PluginHost {
3         private $link;
4         private $hooks = array();
5         private $plugins = array();
6         private $handlers = array();
7         private $commands = array();
8         private $storage = array();
9         private $feeds = array();
10         private $owner_uid;
11         private $debug;
12
13         const HOOK_ARTICLE_BUTTON = 1;
14         const HOOK_ARTICLE_FILTER = 2;
15         const HOOK_PREFS_TAB = 3;
16         const HOOK_PREFS_TAB_SECTION = 4;
17         const HOOK_PREFS_TABS = 5;
18         const HOOK_FEED_PARSED = 6;
19         const HOOK_UPDATE_TASK = 7;
20         const HOOK_AUTH_USER = 8;
21         const HOOK_HOTKEY_MAP = 9;
22         const HOOK_RENDER_ARTICLE = 10;
23         const HOOK_RENDER_ARTICLE_CDM = 11;
24         const HOOK_FEED_FETCHED = 12;
25         const HOOK_SANITIZE = 13;
26         const HOOK_RENDER_ARTICLE_API = 14;
27         const HOOK_TOOLBAR_BUTTON = 15;
28         const HOOK_ACTION_ITEM = 16;
29         const HOOK_HEADLINE_TOOLBAR_BUTTON = 17;
30
31         const KIND_ALL = 1;
32         const KIND_SYSTEM = 2;
33         const KIND_USER = 3;
34
35         function __construct($link) {
36                 $this->link = $link;
37
38                 $this->storage = $_SESSION["plugin_storage"];
39
40                 if (!$this->storage) $this->storage = array();
41         }
42
43         private function register_plugin($name, $plugin) {
44                 //array_push($this->plugins, $plugin);
45                 $this->plugins[$name] = $plugin;
46         }
47
48         function get_link() {
49                 return $this->link;
50         }
51
52         function get_plugins() {
53                 return $this->plugins;
54         }
55
56         function get_plugin($name) {
57                 return $this->plugins[$name];
58         }
59
60         function run_hooks($type, $method, $args) {
61                 foreach ($this->get_hooks($type) as $hook) {
62                         $hook->$method($args);
63                 }
64         }
65
66         function add_hook($type, $sender) {
67                 if (!is_array($this->hooks[$type])) {
68                         $this->hooks[$type] = array();
69                 }
70
71                 array_push($this->hooks[$type], $sender);
72         }
73
74         function del_hook($type, $sender) {
75                 if (is_array($this->hooks[$type])) {
76                         $key = array_Search($this->hooks[$type], $sender);
77                         if ($key !== FALSE) {
78                                 unset($this->hooks[$type][$key]);
79                         }
80                 }
81         }
82
83         function get_hooks($type) {
84                 if (isset($this->hooks[$type])) {
85                         return $this->hooks[$type];
86                 } else {
87                         return array();
88                 }
89         }
90         function load_all($kind, $owner_uid = false) {
91                 $plugins = array_map("basename", glob("plugins/*"));
92                 $this->load(join(",", $plugins), $kind, $owner_uid);
93         }
94
95         function load($classlist, $kind, $owner_uid = false) {
96                 $plugins = explode(",", $classlist);
97
98                 $this->owner_uid = (int) $owner_uid;
99
100                 foreach ($plugins as $class) {
101                         $class = trim($class);
102                         $class_file = strtolower(basename($class));
103                         $file = dirname(__FILE__)."/../plugins/$class_file/init.php";
104
105                         if (!isset($this->plugins[$class])) {
106                                 if (file_exists($file)) require_once $file;
107
108                                 if (class_exists($class) && is_subclass_of($class, "Plugin")) {
109                                         $plugin = new $class($this);
110
111                                         switch ($kind) {
112                                         case $this::KIND_SYSTEM:
113                                                 if ($this->is_system($plugin)) {
114                                                         $plugin->init($this);
115                                                         $this->register_plugin($class, $plugin);
116                                                 }
117                                                 break;
118                                         case $this::KIND_USER:
119                                                 if (!$this->is_system($plugin)) {
120                                                         $plugin->init($this);
121                                                         $this->register_plugin($class, $plugin);
122                                                 }
123                                                 break;
124                                         case $this::KIND_ALL:
125                                                 $plugin->init($this);
126                                                 $this->register_plugin($class, $plugin);
127                                                 break;
128                                         }
129                                 }
130                         }
131                 }
132         }
133
134         function is_system($plugin) {
135                 $about = $plugin->about();
136
137                 return @$about[3];
138         }
139
140         // only system plugins are allowed to modify routing
141         function add_handler($handler, $method, $sender) {
142                 $handler = str_replace("-", "_", strtolower($handler));
143                 $method = strtolower($method);
144
145                 if ($this->is_system($sender)) {
146                         if (!is_array($this->handlers[$handler])) {
147                                 $this->handlers[$handler] = array();
148                         }
149
150                         $this->handlers[$handler][$method] = $sender;
151                 }
152         }
153
154         function del_handler($handler, $method) {
155                 $handler = str_replace("-", "_", strtolower($handler));
156                 $method = strtolower($method);
157
158                 if ($this->is_system($sender)) {
159                         unset($this->handlers[$handler][$method]);
160                 }
161         }
162
163         function lookup_handler($handler, $method) {
164                 $handler = str_replace("-", "_", strtolower($handler));
165                 $method = strtolower($method);
166
167                 if (is_array($this->handlers[$handler])) {
168                         if (isset($this->handlers[$handler]["*"])) {
169                                 return $this->handlers[$handler]["*"];
170                         } else {
171                                 return $this->handlers[$handler][$method];
172                         }
173                 }
174
175                 return false;
176         }
177
178         function add_command($command, $description, $sender, $suffix = "", $arghelp = "") {
179                 $command = str_replace("-", "_", strtolower($command));
180
181                 $this->commands[$command] = array("description" => $description,
182                         "suffix" => $suffix,
183                         "arghelp" => $arghelp,
184                         "class" => $sender);
185         }
186
187         function del_command($command) {
188                 $command = "-" . strtolower($command);
189
190                 unset($this->commands[$command]);
191         }
192
193         function lookup_command($command) {
194                 $command = "-" . strtolower($command);
195
196                 if (is_array($this->commands[$command])) {
197                         return $this->commands[$command]["class"];
198                 } else {
199                         return false;
200                 }
201
202                 return false;
203         }
204
205         function get_commands() {
206                 return $this->commands;
207         }
208
209         function run_commands($args) {
210                 foreach ($this->get_commands() as $command => $data) {
211                         if (isset($args[$command])) {
212                                 $command = str_replace("-", "", $command);
213                                 $data["class"]->$command($args);
214                         }
215                 }
216         }
217
218         function load_data($force = false) {
219                 if ($this->owner_uid && (!$_SESSION["plugin_storage"] || $force))  {
220                         $plugin = db_escape_string($this->link, $plugin);
221
222                         $result = db_query($this->link, "SELECT name, content FROM ttrss_plugin_storage
223                                 WHERE owner_uid = '".$this->owner_uid."'");
224
225                         while ($line = db_fetch_assoc($result)) {
226                                 $this->storage[$line["name"]] = unserialize($line["content"]);
227                         }
228
229                         $_SESSION["plugin_storage"] = $this->storage;
230                 }
231         }
232
233         private function save_data($plugin) {
234                 if ($this->owner_uid) {
235                         $plugin = db_escape_string($this->link, $plugin);
236
237                         db_query($this->link, "BEGIN");
238
239                         $result = db_query($this->link,"SELECT id FROM ttrss_plugin_storage WHERE
240                                 owner_uid= '".$this->owner_uid."' AND name = '$plugin'");
241
242                         if (!isset($this->storage[$plugin]))
243                                 $this->storage[$plugin] = array();
244
245                         $content = db_escape_string($this->link, serialize($this->storage[$plugin]));
246
247                         if (db_num_rows($result) != 0) {
248                                 db_query($this->link, "UPDATE ttrss_plugin_storage SET content = '$content'
249                                         WHERE owner_uid= '".$this->owner_uid."' AND name = '$plugin'");
250
251                         } else {
252                                 db_query($this->link, "INSERT INTO ttrss_plugin_storage
253                                         (name,owner_uid,content) VALUES
254                                         ('$plugin','".$this->owner_uid."','$content')");
255                         }
256
257                         db_query($this->link, "COMMIT");
258                 }
259         }
260
261         function set($sender, $name, $value, $sync = true) {
262                 $idx = get_class($sender);
263
264                 if (!isset($this->storage[$idx]))
265                         $this->storage[$idx] = array();
266
267                 $this->storage[$idx][$name] = $value;
268
269                 $_SESSION["plugin_storage"] = $this->storage;
270
271                 if ($sync) $this->save_data(get_class($sender));
272         }
273
274         function get($sender, $name, $default_value = false) {
275                 $idx = get_class($sender);
276
277                 if (isset($this->storage[$idx][$name])) {
278                         return $this->storage[$idx][$name];
279                 } else {
280                         return $default_value;
281                 }
282         }
283
284         function get_all($sender) {
285                 $idx = get_class($sender);
286
287                 return $this->storage[$idx];
288         }
289
290         function clear_data($sender) {
291                 if ($this->owner_uid) {
292                         $idx = get_class($sender);
293
294                         unset($this->storage[$idx]);
295
296                         db_query($this->link, "DELETE FROM ttrss_plugin_storage WHERE name = '$idx'
297                                 AND owner_uid = " . $this->owner_uid);
298
299                         $_SESSION["plugin_storage"] = $this->storage;
300                 }
301         }
302
303         function set_debug($debug) {
304                 $this->debug = $debug;
305         }
306
307         function get_debug() {
308                 return $this->debug;
309         }
310
311         // Plugin feed functions are *EXPERIMENTAL*!
312
313         // cat_id: only -1 is supported (Special)
314         function add_feed($cat_id, $title, $icon, $sender) {
315                 if (!$this->feeds[$cat_id]) $this->feeds[$cat_id] = array();
316
317                 $id = count($this->feeds[$cat_id]);
318
319                 array_push($this->feeds[$cat_id],
320                         array('id' => $id, 'title' => $title, 'sender' => $sender, 'icon' => $icon));
321
322                 return $id;
323         }
324
325         function get_feeds($cat_id) {
326                 return $this->feeds[$cat_id];
327         }
328
329         // convert feed_id (e.g. -129) to pfeed_id first
330         function get_feed_handler($pfeed_id) {
331                 foreach ($this->feeds as $cat) {
332                         foreach ($cat as $feed) {
333                                 if ($feed['id'] == $pfeed_id) {
334                                         return $feed['sender'];
335                                 }
336                         }
337                 }
338         }
339
340         static function pfeed_to_feed_id($label) {
341                 return PLUGIN_FEED_BASE_INDEX - 1 - abs($label);
342         }
343
344         static function feed_to_pfeed_id($feed) {
345                 return PLUGIN_FEED_BASE_INDEX - 1 + abs($feed);
346         }
347
348 }
349 ?>