OSDN Git Service

Merge branch 'skinnable-master'
[nucleus-jp/nucleus-next.git] / nucleus / libs / PLUGIN.php
1 <<<<<<< HEAD
2 <?php\r
3 /*\r
4  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)\r
5  * Copyright (C) 2002-2012 The Nucleus Group\r
6  *\r
7  * This program is free software; you can redistribute it and/or\r
8  * modify it under the terms of the GNU General Public License\r
9  * as published by the Free Software Foundation; either version 2\r
10  * of the License, or (at your option) any later version.\r
11  * (see nucleus/documentation/index.html#license for more info)\r
12  */\r
13 /**\r
14  * This is an (abstract) class of which all Nucleus Plugins must inherit\r
15  *\r
16  * for more information on plugins and how to write your own, see the\r
17  * plugins.html file that is included with the Nucleus documenation\r
18  *\r
19  * @license http://nucleuscms.org/license.txt GNU General Public License\r
20  * @copyright Copyright (C) 2002-2012 The Nucleus Group\r
21  * @version $Id: PLUGIN.php 1630 2012-01-28 12:16:14Z sakamocchi $\r
22  */\r
23 abstract class NucleusPlugin\r
24 {\r
25         // these public functions should to be redefined in your plugin\r
26         public function getName()\r
27         {\r
28                 return __CLASS__;\r
29         }\r
30         \r
31         public function getAuthor()\r
32         {\r
33                 return 'Undefined';\r
34         }\r
35         \r
36         public function getURL()\r
37         {\r
38                 return 'Undefined';\r
39         }\r
40         \r
41         public function getVersion()\r
42         {\r
43                 return '0.0';\r
44         }\r
45         \r
46         public function getDescription()\r
47         {\r
48                 return 'Undefined';\r
49         }\r
50         \r
51         // these final public function _may_ be redefined in your plugin\r
52         \r
53         public function getMinNucleusVersion()\r
54         {\r
55                 return 150;\r
56         }\r
57         \r
58         public function getMinNucleusPatchLevel()\r
59         {\r
60                 return 0;\r
61         }\r
62         \r
63         public function getEventList()\r
64         {\r
65                 return array();\r
66         }\r
67         \r
68         public function getTableList()\r
69         {\r
70                 return array();\r
71         }\r
72         \r
73         public function hasAdminArea()\r
74         {\r
75                 return 0;\r
76         }\r
77         \r
78         public function install()\r
79         {\r
80                 return;\r
81         }\r
82         \r
83         public function unInstall()\r
84         {\r
85                 return;\r
86         }\r
87         \r
88         public function init()\r
89         {\r
90                 return;\r
91         }\r
92         \r
93         public function doSkinVar($skinType)\r
94         {\r
95                 return;\r
96         }\r
97         \r
98         public function doTemplateVar(&$item)\r
99         {\r
100                 $args = func_get_args();\r
101                 array_shift($args);\r
102                 array_unshift($args, 'template');\r
103                 call_user_func_array(array(&$this,'doSkinVar'),$args);\r
104                 return;\r
105         }\r
106         \r
107         public function doTemplateCommentsVar(&$item, &$comment)\r
108         {\r
109                 $args = func_get_args();\r
110                 array_shift($args);\r
111                 array_shift($args);\r
112                 array_unshift($args, 'template');\r
113                 call_user_func_array(array(&$this,'doSkinVar'),$args);\r
114                 return;\r
115         }\r
116         \r
117         public function doAction($type)\r
118         {\r
119                 return _ERROR_PLUGIN_NOSUCHACTION;\r
120         }\r
121         \r
122         public function doIf($key,$value)\r
123         {\r
124                 return false;\r
125         }\r
126         \r
127         public function doItemVar (&$item)\r
128         {\r
129                 return;\r
130         }\r
131         \r
132         /**\r
133          * Checks if a plugin supports a certain feature.\r
134          *\r
135          * @returns 1 if the feature is reported, 0 if not\r
136          * @param $feature\r
137          *  Name of the feature. See plugin documentation for more info\r
138          *   'SqlTablePrefix' -> if the plugin uses the sql_table() method to get table names\r
139          *   'HelpPage' -> if the plugin provides a helppage\r
140          *   'SqlApi' -> if the plugin uses the complete sql_* or DB::* api (must also require nucleuscms 3.5)\r
141          */\r
142         public function supportsFeature($feature)\r
143         {\r
144                 return 0;\r
145         }\r
146         \r
147         /**\r
148          * Report a list of plugin that is required to final public function\r
149          *\r
150          * @returns an array of names of plugin, an empty array indicates no dependency\r
151          */\r
152         public function getPluginDep()\r
153         {\r
154                 return array();\r
155         }\r
156         \r
157         // these helper final public functions should not be redefined in your plugin\r
158         \r
159         /**\r
160          * Creates a new option for this plugin\r
161          *\r
162          * @param name\r
163          *              A string uniquely identifying your option. (max. length is 20 characters)\r
164          * @param description\r
165          *              A description that will show up in the nucleus admin area (max. length: 255 characters)\r
166          * @param type\r
167          *              Either 'text', 'yesno' or 'password'\r
168          *              This info is used when showing 'edit plugin options' screens\r
169          * @param value\r
170          *              Initial value for the option (max. value length is 128 characters)\r
171          */\r
172         final public function createOption($name, $desc, $type, $defValue = '', $typeExtras = '')\r
173         {\r
174                 return $this->create_option('global', $name, $desc, $type, $defValue, $typeExtras);\r
175         }\r
176         \r
177         final public function createBlogOption($name, $desc, $type, $defValue = '', $typeExtras = '')\r
178         {\r
179                 return $this->create_option('blog', $name, $desc, $type, $defValue, $typeExtras);\r
180         }\r
181         \r
182         final public function createMemberOption($name, $desc, $type, $defValue = '', $typeExtras = '')\r
183         {\r
184                 return $this->create_option('member', $name, $desc, $type, $defValue, $typeExtras);\r
185         }\r
186         \r
187         final public function createCategoryOption($name, $desc, $type, $defValue = '', $typeExtras = '')\r
188         {\r
189                 return $this->create_option('category', $name, $desc, $type, $defValue, $typeExtras);\r
190         }\r
191         \r
192         final public function createItemOption($name, $desc, $type, $defValue = '', $typeExtras = '')\r
193         {\r
194                 return $this->create_option('item', $name, $desc, $type, $defValue, $typeExtras);\r
195         }\r
196         \r
197         /**\r
198          * Removes the option from the database\r
199          *\r
200          * Note: Options get erased automatically on plugin uninstall\r
201          */\r
202         final public function deleteOption($name)\r
203         {\r
204                 return $this->delete_option('global', $name);\r
205         }\r
206         \r
207         final public function deleteBlogOption($name)\r
208         {\r
209                 return $this->delete_option('blog', $name);\r
210         }\r
211         \r
212         final public function deleteMemberOption($name)\r
213         {\r
214                 return $this->delete_option('member', $name);\r
215         }\r
216         \r
217         final public function deleteCategoryOption($name)\r
218         {\r
219                 return $this->delete_option('category', $name);\r
220         }\r
221         \r
222         final public function deleteItemOption($name)\r
223         {\r
224                 return $this->delete_option('item', $name);\r
225         }\r
226         \r
227         /**\r
228          * Sets the value of an option to something new\r
229          */\r
230         final public function setOption($name, $value)\r
231         {\r
232                 return $this->set_option('global', 0, $name, $value);\r
233         }\r
234         \r
235         final public function setBlogOption($blogid, $name, $value)\r
236         {\r
237                 return $this->set_option('blog', $blogid, $name, $value);\r
238         }\r
239         \r
240         final public function setMemberOption($memberid, $name, $value)\r
241         {\r
242                 return $this->set_option('member', $memberid, $name, $value);\r
243         }\r
244         \r
245         final public function setCategoryOption($catid, $name, $value)\r
246         {\r
247                 return $this->set_option('category', $catid, $name, $value);\r
248         }\r
249         \r
250         final public function setItemOption($itemid, $name, $value) {\r
251                 return $this->set_option('item', $itemid, $name, $value);\r
252         }\r
253         \r
254         /**\r
255          * Retrieves the current value for an option\r
256          */\r
257         final public function getOption($name)\r
258         {\r
259                 // only request the options the very first time. On subsequent requests\r
260                 // the static collection is used to save SQL queries.\r
261                 if ( $this->plugin_options == 0 )\r
262                 {\r
263                         $this->plugin_options = array();\r
264                         \r
265                         $query =  "SELECT d.oname as name, o.ovalue as value FROM %s o, %s d WHERE d.opid=%d AND d.oid=o.oid;";\r
266                         $query = sprintf($query, sql_table('plugin_option'), sql_table('plugin_option_desc'), (integer) $this->plugid);\r
267                         $result = DB::getResult($query);\r
268                         foreach ( $result as $row )\r
269                         {\r
270                                 $this->plugin_options[strtolower($row['name'])] = $row['value'];\r
271                         }\r
272                 }\r
273                 if ( isset($this->plugin_options[strtolower($name)]) )\r
274                 {\r
275                         return $this->plugin_options[strtolower($name)];\r
276                 }\r
277                 else\r
278                 {\r
279                         return $this->get_option('global', 0, $name);\r
280                 }\r
281         }\r
282         \r
283         final public function getBlogOption($blogid, $name)\r
284         {\r
285                 return $this->get_option('blog', $blogid, $name);\r
286         }\r
287         \r
288         final public function getMemberOption($memberid, $name)\r
289         {\r
290                 return $this->get_option('member', $memberid, $name);\r
291         }\r
292         \r
293         final public function getCategoryOption($catid, $name)\r
294         {\r
295                 return $this->get_option('category', $catid, $name);\r
296         }\r
297         \r
298         final public function getItemOption($itemid, $name)\r
299         {\r
300                 return $this->get_option('item', $itemid, $name);\r
301         }\r
302         \r
303         /**\r
304          * Retrieves an associative array with the option value for each\r
305          * context id\r
306          */\r
307         final public function getAllBlogOptions($name)\r
308         {\r
309                 return $this->get_all_options('blog', $name);\r
310         }\r
311         \r
312         final public function getAllMemberOptions($name)\r
313         {\r
314                 return $this->get_all_options('member', $name);\r
315         }\r
316         \r
317         final public function getAllCategoryOptions($name)\r
318         {\r
319                 return $this->get_all_options('category', $name);\r
320         }\r
321         \r
322         final public function getAllItemOptions($name)\r
323         {\r
324                 return $this->get_all_options('item', $name);\r
325         }\r
326         \r
327         /**\r
328          * Retrieves an indexed array with the top (or bottom) of an option\r
329          * (delegates to getOptionTop())\r
330          */\r
331         final public function getBlogOptionTop($name, $amount = 10, $sort = 'desc')\r
332         {\r
333                 return $this->get_option_top('blog', $name, $amount, $sort);\r
334         }\r
335         \r
336         final public function getMemberOptionTop($name, $amount = 10, $sort = 'desc')\r
337         {\r
338                 return $this->get_option_top('member', $name, $amount, $sort);\r
339         }\r
340         \r
341         final public function getCategoryOptionTop($name, $amount = 10, $sort = 'desc')\r
342         {\r
343                 return $this->get_option_top('category', $name, $amount, $sort);\r
344         }\r
345         \r
346         final public function getItemOptionTop($name, $amount = 10, $sort = 'desc')\r
347         {\r
348                 return $this->get_option_top('item', $name, $amount, $sort);\r
349         }\r
350         \r
351         /**\r
352          * NucleusPlugin::getID()\r
353          * get id for this plugin\r
354          * \r
355          * @access      public\r
356          * @param       void\r
357          * @return      integer this plugid id\r
358          */\r
359         final public function getID()\r
360         {\r
361                 return (integer) $this->plugid;\r
362         }\r
363         \r
364         /**\r
365          * NucleusPlugin::setID()\r
366          * set favorite id for this plugin\r
367          * \r
368          * @access      public\r
369          * @param       integer $plugid favorite id for plugin\r
370          * @return      void\r
371          */\r
372         final public function setID($plugid)\r
373         {\r
374                 $this->plugid = (integer) $plugid;\r
375                 return;\r
376         }\r
377         \r
378         /**\r
379          * Returns the URL of the admin area for this plugin (in case there's\r
380          * no such area, the returned information is invalid)\r
381          *\r
382          * public\r
383          */\r
384         final public function getAdminURL()\r
385         {\r
386                 global $CONF;\r
387                 return $CONF['PluginURL'] . $this->getShortName() . '/';\r
388         }\r
389         \r
390         /**\r
391          * Returns the directory where the admin directory is located and\r
392          * where the plugin can maintain his extra files\r
393          *\r
394          * public\r
395          */\r
396         final public function getDirectory()\r
397         {\r
398                 global $DIR_PLUGINS;\r
399                 return $DIR_PLUGINS . $this->getShortName() . '/';\r
400         }\r
401         \r
402         /**\r
403          * Derives the short name for the plugin from the classname (all\r
404          * lowercase)\r
405          *\r
406          * public\r
407          */\r
408         final public function getShortName()\r
409         {\r
410                 return str_replace('np_','',strtolower(get_class($this)));\r
411         }\r
412         \r
413         /**\r
414          *      Clears the option value cache which saves the option values during\r
415          *      the plugin execution. This function is usefull if the options has\r
416          *      changed during the plugin execution (especially in association with\r
417          *      the PrePluginOptionsUpdate and the PostPluginOptionsUpdate events)\r
418          *      \r
419          *  public\r
420          **/\r
421         final public function clearOptionValueCache()\r
422         {\r
423                 $this->option_values = array();\r
424                 $this->plugin_options = 0;\r
425                 return;\r
426         }\r
427         \r
428         // internal functions of the class starts here\r
429         protected $option_values;       // oid_contextid => value\r
430         protected $option_info;         // context_name => array('oid' => ..., 'default' => ...)\r
431         protected $plugin_options;      // see getOption()\r
432         protected $plugid;                      // plugin id\r
433         \r
434         /**\r
435          * Class constructor: Initializes some internal data\r
436          */\r
437         public function __construct()\r
438         {\r
439                 $this->option_values = array(); // oid_contextid => value\r
440                 $this->option_info = array();   // context_name => array('oid' => ..., 'default' => ...)\r
441                 $this->plugin_options = 0;\r
442         }\r
443         \r
444         /**\r
445          * Retrieves an array of the top (or bottom) of an option from a plugin.\r
446          * @author TeRanEX\r
447          * @param  string $context the context for the option: item, blog, member,...\r
448          * @param  string $name    the name of the option\r
449          * @param  int    $amount  how many rows must be returned\r
450          * @param  string $sort    desc or asc\r
451          * @return array           array with both values and contextid's\r
452          * @access private\r
453          */\r
454         final protected function get_option_top($context, $name, $amount = 10, $sort = 'desc')\r
455         {\r
456                 if ( ($sort != 'desc') && ($sort != 'asc') )\r
457                 {\r
458                         $sort= 'desc';\r
459                 }\r
460                 \r
461                 $oid = $this->get_option_id($context, $name);\r
462                 \r
463                 // retrieve the data and return\r
464                 $query = "SELECT otype, oextra FROM %s WHERE oid = %d;";\r
465                 $query = sprintf($query, sql_table('plugin_option_desc'), $oid);\r
466                 $row = DB::getRow($query);\r
467                 \r
468                 if ( ($this->optionCanBeNumeric($row['otype'])) && ($row['oextra'] == 'number' ) )\r
469                 {\r
470                         $orderby = 'CAST(ovalue AS SIGNED)';\r
471                 }\r
472                 else\r
473                 {\r
474                         $orderby = 'ovalue';\r
475                 }\r
476                 $query = "SELECT ovalue value, ocontextid id FROM %s WHERE oid = %d ORDER BY %s %s LIMIT 0,%d;";\r
477                 $query = sprintf($query, sql_table('plugin_option'), $oid, $orderby, $sort, (integer) $amount);\r
478                 $result = DB::getResult($query);\r
479                 \r
480                 // create the array\r
481                 $i = 0;\r
482                 $top = array();\r
483                 foreach( $result as $row )\r
484                 {\r
485                         $top[$i++] = $row;\r
486                 }\r
487                 \r
488                 // return the array (duh!)\r
489                 return $top;\r
490         }\r
491         \r
492         /**\r
493          * Creates an option in the database table plugin_option_desc\r
494          *      \r
495          * private\r
496          */\r
497         final protected function create_option($context, $name, $desc, $type, $defValue, $typeExtras = '')\r
498         {\r
499                 // create in plugin_option_desc\r
500                 $query = 'INSERT INTO ' . sql_table('plugin_option_desc')\r
501                                 .' (opid, oname, ocontext, odesc, otype, odef, oextra)'\r
502                                 .' VALUES ('.intval($this->plugid)\r
503                                         .', '.DB::quoteValue($name)\r
504                                         .', '.DB::quoteValue($context)\r
505                                         .', '.DB::quoteValue($desc)\r
506                                         .', '.DB::quoteValue($type)\r
507                                         .', '.DB::quoteValue($defValue)\r
508                                         .', '.DB::quoteValue($typeExtras).')';\r
509                 DB::execute($query);\r
510                 $oid = DB::getInsertId();\r
511                 \r
512                 $key = $context . '_' . $name;\r
513                 $this->option_info[$key] = array('oid' => $oid, 'default' => $defValue);\r
514                 return 1;\r
515         }\r
516         \r
517         /**\r
518          * Deletes an option from the database tables\r
519          * plugin_option and plugin_option_desc\r
520          *\r
521          * private\r
522          */\r
523         final protected function delete_option($context, $name)\r
524         {\r
525                 $oid = $this->get_option_id($context, $name);\r
526                 if ( !$oid )\r
527                 {\r
528                         return 0; // no such option\r
529                 }\r
530                 \r
531                 // delete all things from plugin_option\r
532                 $query = "DELETE FROM %s WHERE oid=%d;";\r
533                 $query = sprintf($query, sql_table('plugin_option'), (integer) $oid);\r
534                 DB::execute($query);\r
535                 \r
536                 // delete entry from plugin_option_desc\r
537                 $query = "DELETE FROM %s WHERE oid=%d;";\r
538                 $query = sprintf($query, sql_table('plugin_option_desc'), $oid);\r
539                 DB::execute($query);\r
540                 \r
541                 // clear from cache\r
542                 unset($this->option_info["{$context}_{$name}"]);\r
543                 $this->option_values = array();\r
544                 return 1;\r
545         }\r
546         \r
547         /**\r
548          * Update an option in the database table plugin_option\r
549          *              \r
550          * returns: 1 on success, 0 on failure\r
551          * private\r
552          */\r
553         final protected function set_option($context, $contextid, $name, $value)\r
554         {\r
555                 global $manager;\r
556                 \r
557                 $oid = $this->get_option_id($context, $name);\r
558                 if ( !$oid )\r
559                 {\r
560                         return 0;\r
561                 }\r
562                 \r
563                 // check if context id exists\r
564                 switch ( $context )\r
565                 {\r
566                         case 'member':\r
567                                 if ( !Member::existsID($contextid) )\r
568                                 {\r
569                                         return 0;\r
570                                 }\r
571                                 break;\r
572                         case 'blog':\r
573                                 if ( !$manager->existsBlogID($contextid) )\r
574                                 {\r
575                                         return 0;\r
576                                 }\r
577                                 break;\r
578                         case 'category':\r
579                                 if ( !$manager->existsCategory($contextid) )\r
580                                 {\r
581                                         return 0;\r
582                                 }\r
583                                 break;\r
584                         case 'item':\r
585                                 if ( !$manager->existsItem($contextid, true, true) )\r
586                                 {\r
587                                         return 0;\r
588                                 }\r
589                                 break;\r
590                         case 'global':\r
591                                 if ( $contextid != 0 )\r
592                                 {\r
593                                         return 0;\r
594                                 }\r
595                                 break;\r
596                 }\r
597                 \r
598                 // update plugin_option\r
599                 $query = "DELETE FROM %s WHERE oid=%d and ocontextid=%d;";\r
600                 $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid);\r
601                 DB::execute($query);\r
602                 \r
603                 $query = "INSERT INTO %s (ovalue, oid, ocontextid) VALUES (%s, %d, %d);";\r
604                 $query = sprintf($query, sql_table('plugin_option'), DB::quoteValue($value), $oid, $contextid);\r
605                 DB::execute($query);\r
606                 \r
607                 // update cache\r
608                 $this->option_values["{$oid}_{$contextid}"] = $value;\r
609                 if ( $context == 'global' )\r
610                 {\r
611                         $this->plugin_options[strtolower($name)] = $value;\r
612                 }\r
613                 \r
614                 return 1;\r
615         }\r
616         \r
617         /**\r
618          * Get an option from Cache or database\r
619          *       - if not in the option Cache read it from the database\r
620          *   - if not in the database write default values into the database\r
621          *              \r
622          * private              \r
623          */                                             \r
624         final protected function get_option($context, $contextid, $name)\r
625         {\r
626                 $oid = $this->get_option_id($context, $name);\r
627                 if ( !$oid )\r
628                 {\r
629                         return '';\r
630                 }\r
631                 \r
632                 $key = "{$oid}_{$contextid}";\r
633                 \r
634                 if ( isset($this->option_values[$key]) )\r
635                 {\r
636                         return $this->option_values[$key];\r
637                 }\r
638                 \r
639                 // get from DB\r
640                 $query = "SELECT ovalue FROM %s WHERE oid=%d and ocontextid=%d;";\r
641                 $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid);\r
642                 $result = DB::getResult($query);\r
643                 \r
644                 if ( !$result || ($result->rowCount() == 0) )\r
645                 {\r
646                         // fill DB with default value\r
647                         $this->option_values[$key] = $this->get_default_value($context, $name);\r
648                         $query = "INSERT INTO %s (oid, ocontextid, ovalue) VALUES (%d, %d, %s);";\r
649                         $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid, DB::quoteValue($this->option_values[$key]));\r
650                         DB::execute($query);\r
651                 }\r
652                 else\r
653                 {\r
654                         $row = $result->fetch();\r
655                         $this->option_values[$key] = $row['ovalue'];\r
656                 }\r
657                 \r
658                 return $this->option_values[$key];\r
659         }\r
660         \r
661         /**\r
662          * Returns assoc array with all values for a given option\r
663          * (one option per possible context id)\r
664          *\r
665          * private                              \r
666          */\r
667         final protected function get_all_options($context, $name)\r
668         {\r
669                 $oid = $this->get_option_id($context, $name);\r
670                 if ( !$oid )\r
671                 {\r
672                         return array();\r
673                 }\r
674                 $default_value = $this->get_default_value($context, $name);\r
675                 \r
676                 $options = array();\r
677                 $query = "SELECT %s as contextid FROM %s;";\r
678                 switch ( $context )\r
679                 {\r
680                         case 'blog':\r
681                                 $query = sprintf($query, 'bnumber', sql_table('blog'));\r
682                                 break;\r
683                         case 'category':\r
684                                 $query = sprintf($query, 'catid', sql_table('category'));\r
685                                 break;\r
686                         case 'member':\r
687                                 $query = sprintf($query, 'mnumber', sql_table('member'));\r
688                                 break;\r
689                         case 'item':\r
690                                 $query = sprintf($query, 'inumber', sql_table('item'));\r
691                                 break;\r
692                 }\r
693                 \r
694                 $result = DB::getResult($query);\r
695                 if ( $result )\r
696                 {\r
697                         foreach ( $result as $row )\r
698                         {\r
699                                 $options[$row['contextid']] = $default_value;\r
700                         }\r
701                 }\r
702                 \r
703                 $query = "SELECT ocontextid, ovalue FROM %s WHERE oid=%d;";\r
704                 $query = sprintf($query, sql_table('plugin_option'), $oid);\r
705                 $result = DB::getResult($query);\r
706                 foreach ( $result as $row )\r
707                 {\r
708                         $options[$row['ocontextid']] = $row['ovalue'];\r
709                 }\r
710 \r
711                 return $options;\r
712         }\r
713         \r
714         /**\r
715          * NucleusPlugin::get_option_id\r
716          * \r
717          * Gets the 'option identifier' that corresponds to a given option name.\r
718          * When this method is called for the first time, all the OIDs for the plugin\r
719          * are loaded into memory, to avoid re-doing the same query all over.\r
720          * \r
721          * @param       string  $context        option context\r
722          * @param       string  $name           plugin name\r
723          * @return              integer option id\r
724          */\r
725         final protected function get_option_id($context, $name)\r
726         {\r
727                 $key = "{$context}_{$name}";\r
728                 \r
729                 if ( array_key_exists($key, $this->option_info)\r
730                  && array_key_exists('oid', $this->option_info[$key]) )\r
731                 {\r
732                         return $this->option_info[$key]['oid'];\r
733                 }\r
734                 \r
735                 // load all OIDs for this plugin from the database\r
736                 $this->option_info = array();\r
737                 $query = "SELECT oid, oname, ocontext, odef FROM %s WHERE opid=%d;";\r
738                 $query = sprintf($query, sql_table('plugin_option_desc'), $this->plugid);\r
739                 $result = DB::getResult($query);\r
740                 foreach ( $result as $row )\r
741                 {\r
742                         $k = $row['ocontext'] . '_' . $row['oname'];\r
743                         $this->option_info[$k] = array('oid' => $row['oid'], 'default' => $row['odef']);\r
744                 }\r
745                 $result->closeCursor();\r
746                 \r
747                 return $this->option_info[$key]['oid'];\r
748         }\r
749         final protected function get_default_value($context, $name)\r
750         {\r
751                 $key = $context . '_' . $name;\r
752                 \r
753                 if ( array_key_exists($key, $this->option_info)\r
754                  && array_key_exists('default', $this->option_info[$key]) )\r
755                 {\r
756                         return $this->option_info[$key]['default'];\r
757                 }\r
758                 return;\r
759         }\r
760         \r
761         /**\r
762          * NucleusPlugin::delete_option_values()\r
763          * Deletes all option values for a given context and contextid\r
764          * (used when e.g. a blog, member or category is deleted)\r
765          *\r
766          *@static\r
767          *@param        String  $context        global/blog/category/item/member\r
768          *@param        Integer $contextid              ID\r
769          *@return       Void\r
770          */\r
771         static public function delete_option_values($context, $contextid)\r
772         {\r
773                 // delete all associated plugin options\r
774                 $aOIDs = array();\r
775                 // find ids\r
776                 $query = "SELECT oid FROM %s WHERE ocontext=%s;";\r
777                 $query = sprintf($query, sql_table('plugin_option_desc'), DB::quoteValue($context));\r
778                 \r
779                 $result = DB::getResult($query);\r
780                 foreach ( $result as $row )\r
781                 {\r
782                         array_push($aOIDs, $row['oid']);\r
783                 }\r
784                 $result->closeCursor();\r
785                 // delete those options. go go go\r
786                 if ( count($aOIDs) > 0 )\r
787                 {\r
788                         $query = "DELETE FROM %s WHERE oid in (%s) and ocontextid=%d;";\r
789                         $query = sprintf($query, sql_table('plugin_option'), implode(',',$aOIDs), (integer) $contextid);\r
790                         DB::execute($query);\r
791                 }\r
792                 return;\r
793         }\r
794         \r
795         /**\r
796          * NucleusPlugin::getOptionMeta()\r
797          * splits the option's typeextra field (at ;'s) to split the meta collection\r
798          * \r
799          * @static\r
800          * @param string $typeExtra the value of the typeExtra field of an option\r
801          * @return array array of the meta-key/value-pairs\r
802          */\r
803         static public function getOptionMeta($typeExtra)\r
804         {\r
805                 $meta = array();\r
806                 \r
807                 /* 1. if $typeExtra includes delimiter ';', split it to tokens */\r
808                 $tokens = preg_split('#;#', $typeExtra);\r
809                 \r
810                 /*\r
811                  * 2. if each of tokens includes "=", it consists of key => value\r
812                  *    else it's 'select' option\r
813                  */\r
814                 foreach ( $tokens as $token )\r
815                 {\r
816                         $matches = array();\r
817                         if ( preg_match("#^([^=]+)?=([^=]+)?$#", $token, $matches) )\r
818                         {\r
819                                 $meta[$matches[1]] = $matches[2];\r
820                         }\r
821                         else\r
822                         {\r
823                                 $meta['select'] = $token;\r
824                         }\r
825                 }\r
826                 return $meta;\r
827         }\r
828         \r
829         /**\r
830          * NucleusPlugin::getOptionSelectValues()\r
831          * filters the selectlists out of the meta collection\r
832          * \r
833          * @static\r
834          * @param string $typeExtra the value of the typeExtra field of an option\r
835          * @return string the selectlist\r
836          */\r
837         static public function getOptionSelectValues($typeExtra)\r
838         {\r
839                 $meta = NucleusPlugin::getOptionMeta($typeExtra);\r
840                 \r
841                 if ( array_key_exists('select', $meta) )\r
842                 {\r
843                         return $meta['select'];\r
844                 }\r
845                 return;\r
846         }\r
847         \r
848         /**\r
849          * checks if the eventlist in the database is up-to-date\r
850          * @return bool if it is up-to-date it return true, else false\r
851          * @author TeRanEX\r
852          */\r
853         public function subscribtionListIsUptodate()\r
854         {\r
855                 $res = DB::getResult('SELECT event FROM '.sql_table('plugin_event').' WHERE pid = '.$this->plugid);\r
856                 $ev = array();\r
857                 foreach ( $res as $row )\r
858                 {\r
859                         array_push($ev, $row['event']);\r
860                 }\r
861                 if ( count($ev) != count($this->getEventList()) )\r
862                 {\r
863                         return false;\r
864                 }\r
865                 $d = array_diff($ev, $this->getEventList());\r
866                 if ( count($d) > 0 )\r
867                 {\r
868                         // there are differences so the db is not up-to-date\r
869                         return false;\r
870                 }\r
871                 return true;\r
872         }\r
873         \r
874         /**\r
875          * NucleusPlugin::apply_plugin_options()\r
876          * Update its entry in database table\r
877          * \r
878          * @static\r
879          * @param       $options: array ( 'oid' => array( 'contextid' => 'value'))\r
880          *                       (taken from request using requestVar())\r
881          * @param       $new_contextid: integer (accepts a contextid when it is for a new\r
882          *                       contextid there was no id available at the moment of writing the\r
883          *                        formcontrols into the page (by ex: itemOptions for new item)\r
884          * @return void\r
885          */\r
886         static public function apply_plugin_options(&$options, $new_contextid = 0)\r
887         {\r
888                 global $manager;\r
889                 \r
890                 if ( !is_array($options) )\r
891                 {\r
892                         return;\r
893                 }\r
894                 \r
895                 foreach ( $options as $oid => $values )\r
896                 {\r
897                         // get option type info\r
898                         $query = "SELECT opid, oname, ocontext, otype, oextra, odef FROM %s WHERE oid=%d;";\r
899                         $query = sprintf($query, sql_table('plugin_option_desc'), (integer) $oid);\r
900                         $result = DB::getRow($query);\r
901                         if ( $result )\r
902                         {\r
903                                 foreach ( $values as $id => $value )\r
904                                 {\r
905                                         // decide wether we are using the contextid of newContextid\r
906                                         if ( $new_contextid != 0 )\r
907                                         {\r
908                                                 $contextid = $new_contextid;\r
909                                         }\r
910                                         else\r
911                                         {\r
912                                                 $contextid = $id;\r
913                                         }\r
914                                         \r
915                                         // retreive any metadata\r
916                                         $meta = NucleusPlugin::getOptionMeta($result['oextra']);\r
917                                         \r
918                                         // if the option is readonly or hidden it may not be saved\r
919                                         if ( array_key_exists('access', $meta)\r
920                                          && in_array($meta['access'], array('readonly', 'hidden')) )\r
921                                         {\r
922                                                 return;\r
923                                         }\r
924                                         \r
925                                         // value comes from request\r
926                                         $value = undoMagic($value);\r
927                                         \r
928                                         /* validation the value according to its type */\r
929                                         switch ( $result['otype'] )\r
930                                         {\r
931                                                 case 'yesno':\r
932                                                         if ( ($value != 'yes') && ($value != 'no') )\r
933                                                         {\r
934                                                                 $value = 'no';\r
935                                                         }\r
936                                                         break;\r
937                                                 case 'text':\r
938                                                 case 'select':\r
939                                                         if ( array_key_exists('datatype', $meta)\r
940                                                          && ($meta['datatype'] == 'numerical') && ($value != (integer) $value) )\r
941                                                         {\r
942                                                                 $value = (integer) $result['odef'];\r
943                                                         }\r
944                                                         break;\r
945                                                 case 'password':\r
946                                                 case 'textarea':\r
947                                                 default:\r
948                                                         break;\r
949                                         }\r
950                                         \r
951                                         /*\r
952                                          * trigger event PrePluginOptionsUpdate to give the plugin the\r
953                                          * possibility to change/validate the new value for the option\r
954                                          */\r
955                                         $data = array(\r
956                                                 'context'               => $result['ocontext'],\r
957                                                 'plugid'                => $result['opid'],\r
958                                                 'optionname'    => $result['oname'],\r
959                                                 'contextid'             => $contextid,\r
960                                                 'value'                 => &$value);\r
961                                         $manager->notify('PrePluginOptionsUpdate', $data);\r
962                                         \r
963                                         // delete and insert its fields of table in database\r
964                                         $query = "DELETE FROM %s WHERE oid=%d AND ocontextid=%d;";\r
965                                         $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid);\r
966                                         DB::execute($query);\r
967                                         $query = "INSERT INTO %s (oid, ocontextid, ovalue) VALUES (%d, %d, %s);";\r
968                                         $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid, DB::quoteValue($value));\r
969                                         DB::execute($query);\r
970                                         \r
971                                         // clear option value cache if the plugin object is already loaded\r
972                                         $plugin=& $manager->pidLoaded($result['opid']);\r
973                                         if ( $plugin )\r
974                                         {\r
975                                                 $plugin->clearOptionValueCache();\r
976                                         }\r
977                                         \r
978                                         continue;\r
979                                 }\r
980                         }\r
981                         continue;\r
982                 }\r
983                 return;\r
984         }\r
985 }\r
986 =======
987 <?php
988 /*
989  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
990  * Copyright (C) 2002-2009 The Nucleus Group
991  *
992  * This program is free software; you can redistribute it and/or
993  * modify it under the terms of the GNU General Public License
994  * as published by the Free Software Foundation; either version 2
995  * of the License, or (at your option) any later version.
996  * (see nucleus/documentation/index.html#license for more info)
997  */
998 /**
999  * This is an (abstract) class of which all Nucleus Plugins must inherit
1000  *
1001  * for more information on plugins and how to write your own, see the
1002  * plugins.html file that is included with the Nucleus documenation
1003  *
1004  * @license http://nucleuscms.org/license.txt GNU General Public License
1005  * @copyright Copyright (C) 2002-2009 The Nucleus Group
1006  * @version $Id: PLUGIN.php 1866 2012-05-20 13:21:55Z sakamocchi $
1007  */
1008 abstract class NucleusPlugin
1009 {
1010         // these public functions should to be redefined in your plugin
1011         public function getName()
1012         {
1013                 return __CLASS__;
1014         }
1015         
1016         public function getAuthor()
1017         {
1018                 return 'Undefined';
1019         }
1020         
1021         public function getURL()
1022         {
1023                 return 'Undefined';
1024         }
1025         
1026         public function getVersion()
1027         {
1028                 return '0.0';
1029         }
1030         
1031         public function getDescription()
1032         {
1033                 return 'Undefined';
1034         }
1035         
1036         // these final public function _may_ be redefined in your plugin
1037         
1038         public function getMinNucleusVersion()
1039         {
1040                 return 150;
1041         }
1042         
1043         public function getMinNucleusPatchLevel()
1044         {
1045                 return 0;
1046         }
1047         
1048         public function getEventList()
1049         {
1050                 return array();
1051         }
1052         
1053         public function getTableList()
1054         {
1055                 return array();
1056         }
1057         
1058         public function hasAdminArea()
1059         {
1060                 return 0;
1061         }
1062         
1063         public function install()
1064         {
1065                 return;
1066         }
1067         
1068         public function unInstall()
1069         {
1070                 return;
1071         }
1072         
1073         public function init()
1074         {
1075                 return;
1076         }
1077         
1078         public function doSkinVar($skinType)
1079         {
1080                 return;
1081         }
1082         
1083         public function doTemplateVar(&$item)
1084         {
1085                 $args = func_get_args();
1086                 array_shift($args);
1087                 array_unshift($args, 'template');
1088                 call_user_func_array(array($this, 'doSkinVar'), $args);
1089                 return;
1090         }
1091         
1092         public function doTemplateCommentsVar(&$item, &$comment)
1093         {
1094                 $args = func_get_args();
1095                 array_shift($args);
1096                 array_shift($args);
1097                 array_unshift($args, 'template');
1098                 call_user_func_array(array($this, 'doSkinVar'), $args);
1099                 return;
1100         }
1101         
1102         public function doAction($type)
1103         {
1104                 return _ERROR_PLUGIN_NOSUCHACTION;
1105         }
1106         
1107         public function doIf($key,$value)
1108         {
1109                 return false;
1110         }
1111         
1112         public function doItemVar (&$item)
1113         {
1114                 return;
1115         }
1116         
1117         /**
1118          * Checks if a plugin supports a certain feature.
1119          *
1120          * @returns 1 if the feature is reported, 0 if not
1121          * @param $feature
1122          *  Name of the feature. See plugin documentation for more info
1123          *   'SqlTablePrefix' -> if the plugin uses the sql_table() method to get table names
1124          *   'HelpPage' -> if the plugin provides a helppage
1125          *   'SqlApi' -> if the plugin uses the complete sql_* or DB::* api (must also require nucleuscms 3.5)
1126          */
1127         public function supportsFeature($feature)
1128         {
1129                 return 0;
1130         }
1131         
1132         /**
1133          * Report a list of plugin that is required to final public function
1134          *
1135          * @returns an array of names of plugin, an empty array indicates no dependency
1136          */
1137         public function getPluginDep()
1138         {
1139                 return array();
1140         }
1141         
1142         // these helper final public functions should not be redefined in your plugin
1143         
1144         /**
1145          * Creates a new option for this plugin
1146          *
1147          * @param name
1148          *              A string uniquely identifying your option. (max. length is 20 characters)
1149          * @param description
1150          *              A description that will show up in the nucleus admin area (max. length: 255 characters)
1151          * @param type
1152          *              Either 'text', 'yesno' or 'password'
1153          *              This info is used when showing 'edit plugin options' screens
1154          * @param value
1155          *              Initial value for the option (max. value length is 128 characters)
1156          */
1157         final public function createOption($name, $desc, $type, $defValue = '', $typeExtras = '')
1158         {
1159                 return $this->create_option('global', $name, $desc, $type, $defValue, $typeExtras);
1160         }
1161         
1162         final public function createBlogOption($name, $desc, $type, $defValue = '', $typeExtras = '')
1163         {
1164                 return $this->create_option('blog', $name, $desc, $type, $defValue, $typeExtras);
1165         }
1166         
1167         final public function createMemberOption($name, $desc, $type, $defValue = '', $typeExtras = '')
1168         {
1169                 return $this->create_option('member', $name, $desc, $type, $defValue, $typeExtras);
1170         }
1171         
1172         final public function createCategoryOption($name, $desc, $type, $defValue = '', $typeExtras = '')
1173         {
1174                 return $this->create_option('category', $name, $desc, $type, $defValue, $typeExtras);
1175         }
1176         
1177         final public function createItemOption($name, $desc, $type, $defValue = '', $typeExtras = '')
1178         {
1179                 return $this->create_option('item', $name, $desc, $type, $defValue, $typeExtras);
1180         }
1181         
1182         /**
1183          * Removes the option from the database
1184          *
1185          * Note: Options get erased automatically on plugin uninstall
1186          */
1187         final public function deleteOption($name)
1188         {
1189                 return $this->delete_option('global', $name);
1190         }
1191         
1192         final public function deleteBlogOption($name)
1193         {
1194                 return $this->delete_option('blog', $name);
1195         }
1196         
1197         final public function deleteMemberOption($name)
1198         {
1199                 return $this->delete_option('member', $name);
1200         }
1201         
1202         final public function deleteCategoryOption($name)
1203         {
1204                 return $this->delete_option('category', $name);
1205         }
1206         
1207         final public function deleteItemOption($name)
1208         {
1209                 return $this->delete_option('item', $name);
1210         }
1211         
1212         /**
1213          * Sets the value of an option to something new
1214          */
1215         final public function setOption($name, $value)
1216         {
1217                 return $this->set_option('global', 0, $name, $value);
1218         }
1219         
1220         final public function setBlogOption($blogid, $name, $value)
1221         {
1222                 return $this->set_option('blog', $blogid, $name, $value);
1223         }
1224         
1225         final public function setMemberOption($memberid, $name, $value)
1226         {
1227                 return $this->set_option('member', $memberid, $name, $value);
1228         }
1229         
1230         final public function setCategoryOption($catid, $name, $value)
1231         {
1232                 return $this->set_option('category', $catid, $name, $value);
1233         }
1234         
1235         final public function setItemOption($itemid, $name, $value) {
1236                 return $this->set_option('item', $itemid, $name, $value);
1237         }
1238         
1239         /**
1240          * Retrieves the current value for an option
1241          */
1242         final public function getOption($name)
1243         {
1244                 // only request the options the very first time. On subsequent requests
1245                 // the static collection is used to save SQL queries.
1246                 if ( $this->plugin_options == 0 )
1247                 {
1248                         $this->plugin_options = array();
1249                         
1250                         $query =  "SELECT d.oname as name, o.ovalue as value FROM %s o, %s d WHERE d.opid=%d AND d.oid=o.oid;";
1251                         $query = sprintf($query, sql_table('plugin_option'), sql_table('plugin_option_desc'), (integer) $this->plugid);
1252                         $result = DB::getResult($query);
1253                         foreach ( $result as $row )
1254                         {
1255                                 $this->plugin_options[strtolower($row['name'])] = $row['value'];
1256                         }
1257                 }
1258                 if ( isset($this->plugin_options[strtolower($name)]) )
1259                 {
1260                         return $this->plugin_options[strtolower($name)];
1261                 }
1262                 else
1263                 {
1264                         return $this->get_option('global', 0, $name);
1265                 }
1266         }
1267         
1268         final public function getBlogOption($blogid, $name)
1269         {
1270                 return $this->get_option('blog', $blogid, $name);
1271         }
1272         
1273         final public function getMemberOption($memberid, $name)
1274         {
1275                 return $this->get_option('member', $memberid, $name);
1276         }
1277         
1278         final public function getCategoryOption($catid, $name)
1279         {
1280                 return $this->get_option('category', $catid, $name);
1281         }
1282         
1283         final public function getItemOption($itemid, $name)
1284         {
1285                 return $this->get_option('item', $itemid, $name);
1286         }
1287         
1288         /**
1289          * Retrieves an associative array with the option value for each
1290          * context id
1291          */
1292         final public function getAllBlogOptions($name)
1293         {
1294                 return $this->get_all_options('blog', $name);
1295         }
1296         
1297         final public function getAllMemberOptions($name)
1298         {
1299                 return $this->get_all_options('member', $name);
1300         }
1301         
1302         final public function getAllCategoryOptions($name)
1303         {
1304                 return $this->get_all_options('category', $name);
1305         }
1306         
1307         final public function getAllItemOptions($name)
1308         {
1309                 return $this->get_all_options('item', $name);
1310         }
1311         
1312         /**
1313          * Retrieves an indexed array with the top (or bottom) of an option
1314          * (delegates to getOptionTop())
1315          */
1316         final public function getBlogOptionTop($name, $amount = 10, $sort = 'desc')
1317         {
1318                 return $this->get_option_top('blog', $name, $amount, $sort);
1319         }
1320         
1321         final public function getMemberOptionTop($name, $amount = 10, $sort = 'desc')
1322         {
1323                 return $this->get_option_top('member', $name, $amount, $sort);
1324         }
1325         
1326         final public function getCategoryOptionTop($name, $amount = 10, $sort = 'desc')
1327         {
1328                 return $this->get_option_top('category', $name, $amount, $sort);
1329         }
1330         
1331         final public function getItemOptionTop($name, $amount = 10, $sort = 'desc')
1332         {
1333                 return $this->get_option_top('item', $name, $amount, $sort);
1334         }
1335         
1336         /**
1337          * NucleusPlugin::getID()
1338          * get id for this plugin
1339          * 
1340          * @access      public
1341          * @param       void
1342          * @return      integer this plugid id
1343          */
1344         final public function getID()
1345         {
1346                 return (integer) $this->plugid;
1347         }
1348         
1349         /**
1350          * NucleusPlugin::setID()
1351          * set favorite id for this plugin
1352          * 
1353          * @access      public
1354          * @param       integer $plugid favorite id for plugin
1355          * @return      void
1356          */
1357         final public function setID($plugid)
1358         {
1359                 $this->plugid = (integer) $plugid;
1360                 return;
1361         }
1362         
1363         /**
1364          * Returns the URL of the admin area for this plugin (in case there's
1365          * no such area, the returned information is invalid)
1366          *
1367          * public
1368          */
1369         final public function getAdminURL()
1370         {
1371                 global $CONF;
1372                 return $CONF['PluginURL'] . $this->getShortName() . '/';
1373         }
1374         
1375         /**
1376          * Returns the directory where the admin directory is located and
1377          * where the plugin can maintain his extra files
1378          *
1379          * public
1380          */
1381         final public function getDirectory()
1382         {
1383                 global $DIR_PLUGINS;
1384                 return $DIR_PLUGINS . $this->getShortName() . '/';
1385         }
1386         
1387         /**
1388          * Derives the short name for the plugin from the classname (all
1389          * lowercase)
1390          *
1391          * public
1392          */
1393         final public function getShortName()
1394         {
1395                 return str_replace('np_','',strtolower(get_class($this)));
1396         }
1397         
1398         /**
1399          *      Clears the option value cache which saves the option values during
1400          *      the plugin execution. This function is usefull if the options has
1401          *      changed during the plugin execution (especially in association with
1402          *      the PrePluginOptionsUpdate and the PostPluginOptionsUpdate events)
1403          *      
1404          *  public
1405          **/
1406         final public function clearOptionValueCache()
1407         {
1408                 $this->option_values = array();
1409                 $this->plugin_options = 0;
1410                 return;
1411         }
1412         
1413         // internal functions of the class starts here
1414         protected $option_values;       // oid_contextid => value
1415         protected $option_info;         // context_name => array('oid' => ..., 'default' => ...)
1416         protected $plugin_options;      // see getOption()
1417         protected $plugid;                      // plugin id
1418         
1419         /**
1420          * Class constructor: Initializes some internal data
1421          */
1422         public function __construct()
1423         {
1424                 $this->option_values = array(); // oid_contextid => value
1425                 $this->option_info = array();   // context_name => array('oid' => ..., 'default' => ...)
1426                 $this->plugin_options = 0;
1427         }
1428         
1429         /**
1430          * Retrieves an array of the top (or bottom) of an option from a plugin.
1431          * @author TeRanEX
1432          * @param  string $context the context for the option: item, blog, member,...
1433          * @param  string $name    the name of the option
1434          * @param  int    $amount  how many rows must be returned
1435          * @param  string $sort    desc or asc
1436          * @return array           array with both values and contextid's
1437          * @access private
1438          */
1439         final protected function get_option_top($context, $name, $amount = 10, $sort = 'desc')
1440         {
1441                 if ( ($sort != 'desc') && ($sort != 'asc') )
1442                 {
1443                         $sort= 'desc';
1444                 }
1445                 
1446                 $oid = $this->get_option_id($context, $name);
1447                 
1448                 // retrieve the data and return
1449                 $query = "SELECT otype, oextra FROM %s WHERE oid = %d;";
1450                 $query = sprintf($query, sql_table('plugin_option_desc'), $oid);
1451                 $row = DB::getRow($query);
1452                 
1453                 if ( ($this->optionCanBeNumeric($row['otype'])) && ($row['oextra'] == 'number' ) )
1454                 {
1455                         $orderby = 'CAST(ovalue AS SIGNED)';
1456                 }
1457                 else
1458                 {
1459                         $orderby = 'ovalue';
1460                 }
1461                 $query = "SELECT ovalue value, ocontextid id FROM %s WHERE oid = %d ORDER BY %s %s LIMIT 0,%d;";
1462                 $query = sprintf($query, sql_table('plugin_option'), $oid, $orderby, $sort, (integer) $amount);
1463                 $result = DB::getResult($query);
1464                 
1465                 // create the array
1466                 $i = 0;
1467                 $top = array();
1468                 foreach( $result as $row )
1469                 {
1470                         $top[$i++] = $row;
1471                 }
1472                 
1473                 // return the array (duh!)
1474                 return $top;
1475         }
1476         
1477         /**
1478          * Creates an option in the database table plugin_option_desc
1479          *      
1480          * private
1481          */
1482         final protected function create_option($context, $name, $desc, $type, $defValue, $typeExtras = '')
1483         {
1484                 // create in plugin_option_desc
1485                 $query = 'INSERT INTO ' . sql_table('plugin_option_desc')
1486                                 .' (opid, oname, ocontext, odesc, otype, odef, oextra)'
1487                                 .' VALUES ('.intval($this->plugid)
1488                                         .', '.DB::quoteValue($name)
1489                                         .', '.DB::quoteValue($context)
1490                                         .', '.DB::quoteValue($desc)
1491                                         .', '.DB::quoteValue($type)
1492                                         .', '.DB::quoteValue($defValue)
1493                                         .', '.DB::quoteValue($typeExtras).')';
1494                 DB::execute($query);
1495                 $oid = DB::getInsertId();
1496                 
1497                 $key = $context . '_' . $name;
1498                 $this->option_info[$key] = array('oid' => $oid, 'default' => $defValue);
1499                 return 1;
1500         }
1501         
1502         /**
1503          * Deletes an option from the database tables
1504          * plugin_option and plugin_option_desc
1505          *
1506          * private
1507          */
1508         final protected function delete_option($context, $name)
1509         {
1510                 $oid = $this->get_option_id($context, $name);
1511                 if ( !$oid )
1512                 {
1513                         return 0; // no such option
1514                 }
1515                 
1516                 // delete all things from plugin_option
1517                 $query = "DELETE FROM %s WHERE oid=%d;";
1518                 $query = sprintf($query, sql_table('plugin_option'), (integer) $oid);
1519                 DB::execute($query);
1520                 
1521                 // delete entry from plugin_option_desc
1522                 $query = "DELETE FROM %s WHERE oid=%d;";
1523                 $query = sprintf($query, sql_table('plugin_option_desc'), $oid);
1524                 DB::execute($query);
1525                 
1526                 // clear from cache
1527                 unset($this->option_info["{$context}_{$name}"]);
1528                 $this->option_values = array();
1529                 return 1;
1530         }
1531         
1532         /**
1533          * Update an option in the database table plugin_option
1534          *              
1535          * returns: 1 on success, 0 on failure
1536          * private
1537          */
1538         final protected function set_option($context, $contextid, $name, $value)
1539         {
1540                 global $manager;
1541                 
1542                 $oid = $this->get_option_id($context, $name);
1543                 if ( !$oid )
1544                 {
1545                         return 0;
1546                 }
1547                 
1548                 // check if context id exists
1549                 switch ( $context )
1550                 {
1551                         case 'member':
1552                                 if ( !Member::existsID($contextid) )
1553                                 {
1554                                         return 0;
1555                                 }
1556                                 break;
1557                         case 'blog':
1558                                 if ( !$manager->existsBlogID($contextid) )
1559                                 {
1560                                         return 0;
1561                                 }
1562                                 break;
1563                         case 'category':
1564                                 if ( !$manager->existsCategory($contextid) )
1565                                 {
1566                                         return 0;
1567                                 }
1568                                 break;
1569                         case 'item':
1570                                 if ( !$manager->existsItem($contextid, true, true) )
1571                                 {
1572                                         return 0;
1573                                 }
1574                                 break;
1575                         case 'global':
1576                                 if ( $contextid != 0 )
1577                                 {
1578                                         return 0;
1579                                 }
1580                                 break;
1581                 }
1582                 
1583                 // update plugin_option
1584                 $query = "DELETE FROM %s WHERE oid=%d and ocontextid=%d;";
1585                 $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid);
1586                 DB::execute($query);
1587                 
1588                 $query = "INSERT INTO %s (ovalue, oid, ocontextid) VALUES (%s, %d, %d);";
1589                 $query = sprintf($query, sql_table('plugin_option'), DB::quoteValue($value), $oid, $contextid);
1590                 DB::execute($query);
1591                 
1592                 // update cache
1593                 $this->option_values["{$oid}_{$contextid}"] = $value;
1594                 if ( $context == 'global' )
1595                 {
1596                         $this->plugin_options[strtolower($name)] = $value;
1597                 }
1598                 
1599                 return 1;
1600         }
1601         
1602         /**
1603          * Get an option from Cache or database
1604          *       - if not in the option Cache read it from the database
1605          *   - if not in the database write default values into the database
1606          *              
1607          * private              
1608          */                                             
1609         final protected function get_option($context, $contextid, $name)
1610         {
1611                 $oid = $this->get_option_id($context, $name);
1612                 if ( !$oid )
1613                 {
1614                         return '';
1615                 }
1616                 
1617                 $key = "{$oid}_{$contextid}";
1618                 
1619                 if ( isset($this->option_values[$key]) )
1620                 {
1621                         return $this->option_values[$key];
1622                 }
1623                 
1624                 // get from DB
1625                 $query = "SELECT ovalue FROM %s WHERE oid=%d and ocontextid=%d;";
1626                 $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid);
1627                 $result = DB::getResult($query);
1628                 
1629                 if ( !$result || ($result->rowCount() == 0) )
1630                 {
1631                         // fill DB with default value
1632                         $this->option_values[$key] = $this->get_default_value($context, $name);
1633                         $query = "INSERT INTO %s (oid, ocontextid, ovalue) VALUES (%d, %d, %s);";
1634                         $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid, DB::quoteValue($this->option_values[$key]));
1635                         DB::execute($query);
1636                 }
1637                 else
1638                 {
1639                         $row = $result->fetch();
1640                         $this->option_values[$key] = $row['ovalue'];
1641                 }
1642                 
1643                 return $this->option_values[$key];
1644         }
1645         
1646         /**
1647          * Returns assoc array with all values for a given option
1648          * (one option per possible context id)
1649          *
1650          * private                              
1651          */
1652         final protected function get_all_options($context, $name)
1653         {
1654                 $oid = $this->get_option_id($context, $name);
1655                 if ( !$oid )
1656                 {
1657                         return array();
1658                 }
1659                 $default_value = $this->get_default_value($context, $name);
1660                 
1661                 $options = array();
1662                 $query = "SELECT %s as contextid FROM %s;";
1663                 switch ( $context )
1664                 {
1665                         case 'blog':
1666                                 $query = sprintf($query, 'bnumber', sql_table('blog'));
1667                                 break;
1668                         case 'category':
1669                                 $query = sprintf($query, 'catid', sql_table('category'));
1670                                 break;
1671                         case 'member':
1672                                 $query = sprintf($query, 'mnumber', sql_table('member'));
1673                                 break;
1674                         case 'item':
1675                                 $query = sprintf($query, 'inumber', sql_table('item'));
1676                                 break;
1677                 }
1678                 
1679                 $result = DB::getResult($query);
1680                 if ( $result )
1681                 {
1682                         foreach ( $result as $row )
1683                         {
1684                                 $options[$row['contextid']] = $default_value;
1685                         }
1686                 }
1687                 
1688                 $query = "SELECT ocontextid, ovalue FROM %s WHERE oid=%d;";
1689                 $query = sprintf($query, sql_table('plugin_option'), $oid);
1690                 $result = DB::getResult($query);
1691                 foreach ( $result as $row )
1692                 {
1693                         $options[$row['ocontextid']] = $row['ovalue'];
1694                 }
1695
1696                 return $options;
1697         }
1698         
1699         /**
1700          * NucleusPlugin::get_option_id
1701          * 
1702          * Gets the 'option identifier' that corresponds to a given option name.
1703          * When this method is called for the first time, all the OIDs for the plugin
1704          * are loaded into memory, to avoid re-doing the same query all over.
1705          * 
1706          * @param       string  $context        option context
1707          * @param       string  $name           plugin name
1708          * @return              integer option id
1709          */
1710         final protected function get_option_id($context, $name)
1711         {
1712                 $key = "{$context}_{$name}";
1713                 
1714                 if ( array_key_exists($key, $this->option_info)
1715                  && array_key_exists('oid', $this->option_info[$key]) )
1716                 {
1717                         return $this->option_info[$key]['oid'];
1718                 }
1719                 
1720                 // load all OIDs for this plugin from the database
1721                 $this->option_info = array();
1722                 $query = "SELECT oid, oname, ocontext, odef FROM %s WHERE opid=%d;";
1723                 $query = sprintf($query, sql_table('plugin_option_desc'), $this->plugid);
1724                 $result = DB::getResult($query);
1725                 foreach ( $result as $row )
1726                 {
1727                         $k = $row['ocontext'] . '_' . $row['oname'];
1728                         $this->option_info[$k] = array('oid' => $row['oid'], 'default' => $row['odef']);
1729                 }
1730                 $result->closeCursor();
1731                 
1732                 return $this->option_info[$key]['oid'];
1733         }
1734         final protected function get_default_value($context, $name)
1735         {
1736                 $key = $context . '_' . $name;
1737                 
1738                 if ( array_key_exists($key, $this->option_info)
1739                  && array_key_exists('default', $this->option_info[$key]) )
1740                 {
1741                         return $this->option_info[$key]['default'];
1742                 }
1743                 return;
1744         }
1745         
1746         /**
1747          * NucleusPlugin::delete_option_values()
1748          * Deletes all option values for a given context and contextid
1749          * (used when e.g. a blog, member or category is deleted)
1750          *
1751          *@static
1752          *@param        String  $context        global/blog/category/item/member
1753          *@param        Integer $contextid              ID
1754          *@return       Void
1755          */
1756         static public function delete_option_values($context, $contextid)
1757         {
1758                 // delete all associated plugin options
1759                 $aOIDs = array();
1760                 // find ids
1761                 $query = "SELECT oid FROM %s WHERE ocontext=%s;";
1762                 $query = sprintf($query, sql_table('plugin_option_desc'), DB::quoteValue($context));
1763                 
1764                 $result = DB::getResult($query);
1765                 foreach ( $result as $row )
1766                 {
1767                         array_push($aOIDs, $row['oid']);
1768                 }
1769                 $result->closeCursor();
1770                 // delete those options. go go go
1771                 if ( count($aOIDs) > 0 )
1772                 {
1773                         $query = "DELETE FROM %s WHERE oid in (%s) and ocontextid=%d;";
1774                         $query = sprintf($query, sql_table('plugin_option'), implode(',',$aOIDs), (integer) $contextid);
1775                         DB::execute($query);
1776                 }
1777                 return;
1778         }
1779         
1780         /**
1781          * NucleusPlugin::getOptionMeta()
1782          * splits the option's typeextra field (at ;'s) to split the meta collection
1783          * 
1784          * @static
1785          * @param string $typeExtra the value of the typeExtra field of an option
1786          * @return array array of the meta-key/value-pairs
1787          */
1788         static public function getOptionMeta($typeExtra)
1789         {
1790                 $meta = array();
1791                 
1792                 /* 1. if $typeExtra includes delimiter ';', split it to tokens */
1793                 $tokens = preg_split('#;#', $typeExtra);
1794                 
1795                 /*
1796                  * 2. if each of tokens includes "=", it consists of key => value
1797                  *    else it's 'select' option
1798                  */
1799                 foreach ( $tokens as $token )
1800                 {
1801                         $matches = array();
1802                         if ( preg_match("#^([^=]+)?=([^=]+)?$#", $token, $matches) )
1803                         {
1804                                 $meta[$matches[1]] = $matches[2];
1805                         }
1806                         else
1807                         {
1808                                 $meta['select'] = $token;
1809                         }
1810                 }
1811                 return $meta;
1812         }
1813         
1814         /**
1815          * NucleusPlugin::getOptionSelectValues()
1816          * filters the selectlists out of the meta collection
1817          * 
1818          * @static
1819          * @param string $typeExtra the value of the typeExtra field of an option
1820          * @return string the selectlist
1821          */
1822         static public function getOptionSelectValues($typeExtra)
1823         {
1824                 $meta = NucleusPlugin::getOptionMeta($typeExtra);
1825                 
1826                 if ( array_key_exists('select', $meta) )
1827                 {
1828                         return $meta['select'];
1829                 }
1830                 return;
1831         }
1832         
1833         /**
1834          * checks if the eventlist in the database is up-to-date
1835          * @return bool if it is up-to-date it return true, else false
1836          * @author TeRanEX
1837          */
1838         public function subscribtionListIsUptodate()
1839         {
1840                 $res = DB::getResult('SELECT event FROM '.sql_table('plugin_event').' WHERE pid = '.$this->plugid);
1841                 $ev = array();
1842                 foreach ( $res as $row )
1843                 {
1844                         array_push($ev, $row['event']);
1845                 }
1846                 if ( count($ev) != count($this->getEventList()) )
1847                 {
1848                         return false;
1849                 }
1850                 $d = array_diff($ev, $this->getEventList());
1851                 if ( count($d) > 0 )
1852                 {
1853                         // there are differences so the db is not up-to-date
1854                         return false;
1855                 }
1856                 return true;
1857         }
1858         
1859         /**
1860          * NucleusPlugin::apply_plugin_options()
1861          * Update its entry in database table
1862          * 
1863          * @static
1864          * @param       $options: array ( 'oid' => array( 'contextid' => 'value'))
1865          *                       (taken from request using requestVar())
1866          * @param       $new_contextid: integer (accepts a contextid when it is for a new
1867          *                       contextid there was no id available at the moment of writing the
1868          *                        formcontrols into the page (by ex: itemOptions for new item)
1869          * @return void
1870          */
1871         static public function apply_plugin_options(&$options, $new_contextid = 0)
1872         {
1873                 global $manager;
1874                 
1875                 if ( !is_array($options) )
1876                 {
1877                         return;
1878                 }
1879                 
1880                 foreach ( $options as $oid => $values )
1881                 {
1882                         // get option type info
1883                         $query = "SELECT opid, oname, ocontext, otype, oextra, odef FROM %s WHERE oid=%d;";
1884                         $query = sprintf($query, sql_table('plugin_option_desc'), (integer) $oid);
1885                         $result = DB::getRow($query);
1886                         if ( $result )
1887                         {
1888                                 foreach ( $values as $id => $value )
1889                                 {
1890                                         // decide wether we are using the contextid of newContextid
1891                                         if ( $new_contextid != 0 )
1892                                         {
1893                                                 $contextid = $new_contextid;
1894                                         }
1895                                         else
1896                                         {
1897                                                 $contextid = $id;
1898                                         }
1899                                         
1900                                         // retreive any metadata
1901                                         $meta = NucleusPlugin::getOptionMeta($result['oextra']);
1902                                         
1903                                         // if the option is readonly or hidden it may not be saved
1904                                         if ( array_key_exists('access', $meta)
1905                                          && in_array($meta['access'], array('readonly', 'hidden')) )
1906                                         {
1907                                                 return;
1908                                         }
1909                                         
1910                                         // value comes from request
1911                                         $value = undoMagic($value);
1912                                         
1913                                         /* validation the value according to its type */
1914                                         switch ( $result['otype'] )
1915                                         {
1916                                                 case 'yesno':
1917                                                         if ( ($value != 'yes') && ($value != 'no') )
1918                                                         {
1919                                                                 $value = 'no';
1920                                                         }
1921                                                         break;
1922                                                 case 'text':
1923                                                 case 'select':
1924                                                         if ( array_key_exists('datatype', $meta)
1925                                                          && ($meta['datatype'] == 'numerical') && ($value != (integer) $value) )
1926                                                         {
1927                                                                 $value = (integer) $result['odef'];
1928                                                         }
1929                                                         break;
1930                                                 case 'password':
1931                                                 case 'textarea':
1932                                                 default:
1933                                                         break;
1934                                         }
1935                                         
1936                                         /*
1937                                          * trigger event PrePluginOptionsUpdate to give the plugin the
1938                                          * possibility to change/validate the new value for the option
1939                                          */
1940                                         $data = array(
1941                                                 'context'               => $result['ocontext'],
1942                                                 'plugid'                => $result['opid'],
1943                                                 'optionname'    => $result['oname'],
1944                                                 'contextid'     => $contextid,
1945                                                 'value'         => &$value);
1946                                         $manager->notify('PrePluginOptionsUpdate', $data);
1947                                         
1948                                         // delete and insert its fields of table in database
1949                                         $query = "DELETE FROM %s WHERE oid=%d AND ocontextid=%d;";
1950                                         $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid);
1951                                         DB::execute($query);
1952                                         $query = "INSERT INTO %s (oid, ocontextid, ovalue) VALUES (%d, %d, %s);";
1953                                         $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid, DB::quoteValue($value));
1954                                         DB::execute($query);
1955                                         
1956                                         // clear option value cache if the plugin object is already loaded
1957                                         $plugin=& $manager->pidLoaded($result['opid']);
1958                                         if ( $plugin )
1959                                         {
1960                                                 $plugin->clearOptionValueCache();
1961                                         }
1962                                         
1963                                         continue;
1964                                 }
1965                         }
1966                         continue;
1967                 }
1968                 return;
1969         }
1970 }
1971 >>>>>>> skinnable-master