OSDN Git Service

applied some bug fixes
[nucleus-jp/nucleus-jp-ancient.git] / euc / nucleus / libs / MANAGER.php
1 <?php\r
2 /**\r
3   * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/) \r
4   * Copyright (C) 2002-2004 The Nucleus Group\r
5   *\r
6   * This program is free software; you can redistribute it and/or\r
7   * modify it under the terms of the GNU General Public License\r
8   * as published by the Free Software Foundation; either version 2\r
9   * of the License, or (at your option) any later version.\r
10   * (see nucleus/documentation/index.html#license for more info)\r
11   *\r
12   *     This class makes sure each item/weblog/comment object gets requested from\r
13   * the database only once, by keeping them in a cache. The class also acts as \r
14   * a dynamic classloader, loading classes _only_ when they are first needed,\r
15   * hoping to diminish execution time\r
16   *\r
17   * The class is a singleton, meaning that there will be only one object of it\r
18   * active at all times. The object can be requested using MANAGER::instance()\r
19   */\r
20 class MANAGER {\r
21 \r
22         /**\r
23          * Cached ITEM, BLOG, PLUGIN and KARMA objects. When these objects are requested \r
24          * through the global $manager object (getItem, getBlog, ...), only the first call \r
25          * will create an object. Subsequent calls will return the same object.\r
26          *\r
27          * The $items, $blogs, ... arrays map an id to an object (for plugins, the name is used\r
28          * rather than an ID)\r
29          */\r
30         var $items;\r
31         var $blogs;\r
32         var $plugins;\r
33         var $karma;\r
34         \r
35         /**\r
36          * cachedInfo to avoid repeated SQL queries (see pidInstalled/pluginInstalled/getPidFromName)\r
37          * e.g. which plugins exists?\r
38          *\r
39          * $cachedInfo['installedPlugins'] = array($pid -> $name)\r
40          */\r
41         var $cachedInfo;\r
42         \r
43         /**\r
44           * The plugin subscriptionlist\r
45           *\r
46           * The subcription array has the following structure\r
47           *             $subscriptions[$EventName] = array containing names of plugin classes to be\r
48           *                                                                      notified when that event happens\r
49           */\r
50         var $subscriptions;     \r
51         \r
52         /**\r
53           * Returns the only instance of this class. Creates the instance if it \r
54           * does not yet exists. Users should use this function as \r
55           * $manager =& MANAGER::instance(); to get a reference to the object\r
56           * instead of a copy\r
57           */\r
58         function &instance() {\r
59                 static $instance = '';\r
60                 if ($instance == '')\r
61                         $instance = new MANAGER();\r
62                 return $instance;\r
63         }\r
64         \r
65         /**\r
66           * The constructor of this class initializes the object caches \r
67           */\r
68         function MANAGER() {\r
69                 $this->items = array();\r
70                 $this->blogs = array();\r
71                 $this->plugins = array();\r
72                 $this->karma = array();\r
73                 $this->parserPrefs = array();\r
74                 $this->cachedInfo = array();\r
75         }\r
76         \r
77         /**\r
78           * Returns the requested item object. If it is not in the cache, it will\r
79           * first be loaded and then placed in the cache.\r
80           * Intended use: $item =& $manager->getItem(1234)\r
81           */\r
82         function &getItem($itemid, $allowdraft, $allowfuture) {\r
83                 $item =& $this->items[$itemid];\r
84                 \r
85                 // check the draft and future rules if the item was already cached \r
86                 if ($item) {\r
87                         if ((!$allowdraft) && ($item['draft']))\r
88                                 return 0;\r
89 \r
90                         $blog =& $this->getBlog(getBlogIDFromItemID($itemid));\r
91                         if ((!$allowfuture) && ($item['timestamp'] > $blog->getCorrectTime()))\r
92                                 return 0;                               \r
93                 }\r
94                 if (!$item) {\r
95                         // load class if needed\r
96                         $this->loadClass('ITEM');\r
97                         // load item object\r
98                         $item = ITEM::getitem($itemid, $allowdraft, $allowfuture);\r
99                         $this->items[$itemid] = $item;\r
100                 }\r
101                 return $item;\r
102         }\r
103         \r
104         /**\r
105           * Loads a class if it has not yet been loaded\r
106           */\r
107         function loadClass($name) {\r
108                 $this->_loadClass($name, $name . '.php');\r
109         }\r
110         \r
111         /**\r
112           * Checks if an item exists\r
113           */\r
114         function existsItem($id,$future,$draft) {\r
115                 $this->_loadClass('ITEM','ITEM.php');   \r
116                 return ITEM::exists($id,$future,$draft);\r
117         }\r
118         \r
119         /**\r
120           * Checks if a category exists\r
121           */\r
122         function existsCategory($id) {\r
123                 return (quickQuery('SELECT COUNT(*) as result FROM '.sql_table('category').' WHERE catid='.intval($id)) > 0);\r
124         }\r
125         \r
126         function &getBlog($blogid) {\r
127                 $blog =& $this->blogs[$blogid];\r
128 \r
129                 if (!$blog) {\r
130                         // load class if needed\r
131                         $this->_loadClass('BLOG','BLOG.php');\r
132                         // load blog object\r
133                         $blog = new BLOG($blogid);\r
134                         $this->blogs[$blogid] = $blog;\r
135                 }\r
136                 return $blog;\r
137         }\r
138         \r
139         function existsBlog($name) {\r
140                 $this->_loadClass('BLOG','BLOG.php');\r
141                 return BLOG::exists($name);\r
142         }\r
143 \r
144         function existsBlogID($id) {\r
145                 $this->_loadClass('BLOG','BLOG.php');\r
146                 return BLOG::existsID($id);\r
147         }       \r
148         \r
149         /**\r
150          * Returns a KARMA object (karma votes)\r
151          */\r
152         function &getKarma($itemid) {\r
153                 $karma =& $this->karma[$itemid];\r
154 \r
155                 if (!$karma) {\r
156                         // load class if needed\r
157                         $this->_loadClass('KARMA','KARMA.php');\r
158                         // create KARMA object\r
159                         $karma = new KARMA($itemid);\r
160                         $this->karma[$itemid] = $karma;\r
161                 }\r
162                 return $karma;\r
163         }       \r
164         \r
165         /**\r
166          * Global parser preferences\r
167          */\r
168         function setParserProperty($name, $value) {\r
169                 $this->parserPrefs[$name] = $value;\r
170         }\r
171         function getParserProperty($name) {\r
172                 return $this->parserPrefs[$name];\r
173         }\r
174 \r
175         /**\r
176           * A private helper class to load classes\r
177           */\r
178         function _loadClass($name, $filename) {\r
179                 if (!class_exists($name)) {\r
180                                 global $DIR_LIBS;\r
181                                 include($DIR_LIBS . $filename);\r
182                 }       \r
183         }\r
184         \r
185         function _loadPlugin($name) {\r
186                 if (!class_exists($name)) {\r
187                                 global $DIR_PLUGINS;\r
188                                 \r
189                                 $fileName = $DIR_PLUGINS . $name . '.php';\r
190                                 \r
191                                 if (!file_exists($fileName))\r
192                                 {\r
193                                         ACTIONLOG::add(WARNING, 'Plugin ' . $name . ' was not loaded (File not found)');\r
194                                         return 0;\r
195                                 }\r
196                                 \r
197                                 // load plugin\r
198                                 include($fileName);\r
199                                 \r
200                                 // check if class exists (avoid errors in eval'd code)\r
201                                 if (!class_exists($name))\r
202                                 {\r
203                                         ACTIONLOG::add(WARNING, 'Plugin ' . $name . ' was not loaded (Class not found in file, possible parse error)');                         \r
204                                         return 0;\r
205                                 }\r
206                                 \r
207                                 // add to plugin array\r
208                                 eval('$this->plugins[$name] = new ' . $name . '();');\r
209                                 \r
210                                 // get plugid\r
211                                 $this->plugins[$name]->plugid = $this->getPidFromName($name);\r
212                                 \r
213                                 // unload plugin if a prefix is used and the plugin cannot handle this^\r
214                                 global $MYSQL_PREFIX;\r
215                                 if (($MYSQL_PREFIX != '') && !$this->plugins[$name]->supportsFeature('SqlTablePrefix')) \r
216                                 {\r
217                                         unset($this->plugins[$name]);\r
218                                         ACTIONLOG::add(WARNING, 'Plugin ' . $name . ' was not loaded (does not support SqlTablePrefix)');\r
219                                         return 0;\r
220                                 }\r
221                                 \r
222                                 // call init method\r
223                                 $this->plugins[$name]->init();\r
224                                 \r
225                 }       \r
226         }\r
227         \r
228         function &getPlugin($name) {\r
229                 $plugin =& $this->plugins[$name];\r
230 \r
231                 if (!$plugin) {\r
232                         // load class if needed\r
233                         $this->_loadPlugin($name);\r
234                         $plugin =& $this->plugins[$name];                       \r
235                 }\r
236                 return $plugin;\r
237         }\r
238 \r
239         /**\r
240           * checks if the given plugin IS installed or not\r
241           */\r
242         function pluginInstalled($name) {\r
243                 $this->_initCacheInfo('installedPlugins');\r
244                 return ($this->getPidFromName($name) != -1);\r
245         }\r
246         function pidInstalled($pid) {\r
247                 $this->_initCacheInfo('installedPlugins');\r
248                 return ($this->cachedInfo['installedPlugins'][$pid] != '');\r
249         }\r
250         function getPidFromName($name) {\r
251                 $this->_initCacheInfo('installedPlugins');\r
252                 foreach ($this->cachedInfo['installedPlugins'] as $pid => $pfile)\r
253                 {\r
254                         if ($pfile == $name)\r
255                                 return $pid;\r
256                 }\r
257                 return -1;\r
258         }\r
259         function clearCachedInfo($what) {\r
260                 unset($this->cachedInfo[$what]);\r
261         }\r
262         \r
263         /**\r
264          * Loads some info on the first call only\r
265          */\r
266         function _initCacheInfo($what)\r
267         {\r
268                 if (is_array($this->cachedInfo[$what]))\r
269                         return;\r
270                 switch ($what)\r
271                 {\r
272                         // 'installedPlugins' = array ($pid => $name)\r
273                         case 'installedPlugins':\r
274                                 $this->cachedInfo['installedPlugins'] = array();\r
275                                 $res = sql_query('SELECT pid, pfile FROM ' . sql_table('plugin'));\r
276                                 while ($o = mysql_fetch_object($res))\r
277                                 {\r
278                                         $this->cachedInfo['installedPlugins'][$o->pid] = $o->pfile;\r
279                                 }\r
280                                 break;\r
281                 }\r
282         }\r
283         \r
284         /**\r
285           * A function to notify plugins that something has happened. Only the plugins\r
286           * that are subscribed to the event will get notified.\r
287           * Upon the first call, the list of subscriptions will be fetched from the \r
288           * database. The plugins itsself will only get loaded when they are first needed\r
289           *\r
290           * @param $eventName\r
291           *             Name of the event (method to be called on plugins)\r
292           * @param $data\r
293           *             Can contain any type of data, depending on the event type. Usually this is\r
294           *             an itemid, blogid, ... but it can also be an array containing multiple values\r
295           */\r
296         function notify($eventName, $data) {\r
297                 // load subscription list if needed\r
298                 if (!is_array($this->subscriptions)) \r
299                         $this->_loadSubscriptions();\r
300                         \r
301 \r
302                 // get listening objects\r
303                 $listeners = $this->subscriptions[$eventName];\r
304                 \r
305                 // notify all of them\r
306                 if (is_array($listeners)) {\r
307                         foreach($listeners as $listener) {\r
308                                 // load class if needed\r
309                                 $this->_loadPlugin($listener);\r
310                                 // do notify (if method exists)\r
311                                 if (method_exists($this->plugins[$listener], 'event_' . $eventName))\r
312                                         call_user_func(array(&$this->plugins[$listener],'event_' . $eventName), $data);\r
313                         }\r
314                 }\r
315                 \r
316         }\r
317         \r
318         /**\r
319           * Loads plugin subscriptions\r
320           */\r
321         function _loadSubscriptions() {\r
322                 // initialize as array\r
323                 $this->subscriptions = array();\r
324 \r
325                 $res = sql_query('SELECT p.pfile as pfile, e.event as event FROM '.sql_table('plugin_event').' as e, '.sql_table('plugin').' as p WHERE e.pid=p.pid ORDER BY p.porder ASC');\r
326                 while ($o = mysql_fetch_object($res)) {\r
327                         $pluginName = $o->pfile;\r
328                         $eventName = $o->event;\r
329                         $this->subscriptions[$eventName][] = $pluginName;\r
330                 }\r
331                 \r
332         }\r
333 \r
334         \r
335         \r
336 }\r
337 \r
338 ?>