X-Git-Url: http://git.osdn.net/view?p=nucleus-jp%2Fnucleus-next.git;a=blobdiff_plain;f=nucleus%2Flibs%2FPLUGIN.php;h=4cebb26bcc3f315f5246e3455e1c4d8263383055;hp=23f9a585f68e586084face66302c281a8d0963d5;hb=6575e866f3fd1938601432841d80f82e9d259265;hpb=b7e5335177b8724f95d0f9b7e08550f4d9ec91b4 diff --git a/nucleus/libs/PLUGIN.php b/nucleus/libs/PLUGIN.php index 23f9a58..4cebb26 100644 --- a/nucleus/libs/PLUGIN.php +++ b/nucleus/libs/PLUGIN.php @@ -1,898 +1,984 @@ if the plugin uses the sql_table() method to get table names + * 'HelpPage' -> if the plugin provides a helppage + * 'SqlApi' -> if the plugin uses the complete sql_* or DB::* api (must also require nucleuscms 3.5) + */ + public function supportsFeature($feature) + { + return 0; + } + + /** + * Report a list of plugin that is required to final public function * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * (see nucleus/documentation/index.html#license for more info) + * @returns an array of names of plugin, an empty array indicates no dependency */ + public function getPluginDep() + { + return array(); + } + + // these helper final public functions should not be redefined in your plugin + /** - * This is an (abstract) class of which all Nucleus Plugins must inherit + * Creates a new option for this plugin * - * for more information on plugins and how to write your own, see the - * plugins.html file that is included with the Nucleus documenation + * @param name + * A string uniquely identifying your option. (max. length is 20 characters) + * @param description + * A description that will show up in the nucleus admin area (max. length: 255 characters) + * @param type + * Either 'text', 'yesno' or 'password' + * This info is used when showing 'edit plugin options' screens + * @param value + * Initial value for the option (max. value length is 128 characters) + */ + final public function createOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('global', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createBlogOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('blog', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createMemberOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('member', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createCategoryOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('category', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createItemOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('item', $name, $desc, $type, $defValue, $typeExtras); + } + + /** + * Removes the option from the database * - * @license http://nucleuscms.org/license.txt GNU General Public License - * @copyright Copyright (C) 2002-2009 The Nucleus Group - * @version $Id: PLUGIN.php 1575 2011-08-03 14:58:04Z ftruscot $ + * Note: Options get erased automatically on plugin uninstall */ - class NucleusPlugin { - - // these functions _have_ to be redefined in your plugin - - function getName() - { - return 'Undefined'; - } - - function getAuthor() - { - return 'Undefined'; - } - - function getURL() - { - return 'Undefined'; - } - - function getVersion() - { - return '0.0'; + final public function deleteOption($name) + { + return $this->delete_option('global', $name); + } + + final public function deleteBlogOption($name) + { + return $this->delete_option('blog', $name); + } + + final public function deleteMemberOption($name) + { + return $this->delete_option('member', $name); + } + + final public function deleteCategoryOption($name) + { + return $this->delete_option('category', $name); + } + + final public function deleteItemOption($name) + { + return $this->delete_option('item', $name); + } + + /** + * Sets the value of an option to something new + */ + final public function setOption($name, $value) + { + return $this->set_option('global', 0, $name, $value); + } + + final public function setBlogOption($blogid, $name, $value) + { + return $this->set_option('blog', $blogid, $name, $value); + } + + final public function setMemberOption($memberid, $name, $value) + { + return $this->set_option('member', $memberid, $name, $value); + } + + final public function setCategoryOption($catid, $name, $value) + { + return $this->set_option('category', $catid, $name, $value); + } + + final public function setItemOption($itemid, $name, $value) { + return $this->set_option('item', $itemid, $name, $value); + } + + /** + * Retrieves the current value for an option + */ + final public function getOption($name) + { + // only request the options the very first time. On subsequent requests + // the static collection is used to save SQL queries. + if ( $this->plugin_options == 0 ) + { + $this->plugin_options = array(); + + $query = "SELECT d.oname as name, o.ovalue as value FROM %s o, %s d WHERE d.opid=%d AND d.oid=o.oid;"; + $query = sprintf($query, sql_table('plugin_option'), sql_table('plugin_option_desc'), (integer) $this->plugid); + $result = DB::getResult($query); + foreach ( $result as $row ) + { + $this->plugin_options[strtolower($row['name'])] = $row['value']; + } } - - function getDescription() - { - return 'Undefined'; + if ( isset($this->plugin_options[strtolower($name)]) ) + { + return $this->plugin_options[strtolower($name)]; } - - // these function _may_ be redefined in your plugin - - function getMinNucleusVersion() - { - return 150; + else + { + return $this->get_option('global', 0, $name); } - - function getMinNucleusPatchLevel() - { - return 0; + } + + final public function getBlogOption($blogid, $name) + { + return $this->get_option('blog', $blogid, $name); + } + + final public function getMemberOption($memberid, $name) + { + return $this->get_option('member', $memberid, $name); + } + + final public function getCategoryOption($catid, $name) + { + return $this->get_option('category', $catid, $name); + } + + final public function getItemOption($itemid, $name) + { + return $this->get_option('item', $itemid, $name); + } + + /** + * Retrieves an associative array with the option value for each + * context id + */ + final public function getAllBlogOptions($name) + { + return $this->get_all_options('blog', $name); + } + + final public function getAllMemberOptions($name) + { + return $this->get_all_options('member', $name); + } + + final public function getAllCategoryOptions($name) + { + return $this->get_all_options('category', $name); + } + + final public function getAllItemOptions($name) + { + return $this->get_all_options('item', $name); + } + + /** + * Retrieves an indexed array with the top (or bottom) of an option + * (delegates to getOptionTop()) + */ + final public function getBlogOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('blog', $name, $amount, $sort); + } + + final public function getMemberOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('member', $name, $amount, $sort); + } + + final public function getCategoryOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('category', $name, $amount, $sort); + } + + final public function getItemOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('item', $name, $amount, $sort); + } + + /** + * NucleusPlugin::getID() + * get id for this plugin + * + * @access public + * @param void + * @return integer this plugid id + */ + final public function getID() + { + return (integer) $this->plugid; + } + + /** + * NucleusPlugin::setID() + * set favorite id for this plugin + * + * @access public + * @param integer $plugid favorite id for plugin + * @return void + */ + final public function setID($plugid) + { + $this->plugid = (integer) $plugid; + return; + } + + /** + * Returns the URL of the admin area for this plugin (in case there's + * no such area, the returned information is invalid) + * + * public + */ + final public function getAdminURL() + { + global $CONF; + return $CONF['PluginURL'] . $this->getShortName() . '/'; + } + + /** + * Returns the directory where the admin directory is located and + * where the plugin can maintain his extra files + * + * public + */ + final public function getDirectory() + { + global $DIR_PLUGINS; + return $DIR_PLUGINS . $this->getShortName() . '/'; + } + + /** + * Derives the short name for the plugin from the classname (all + * lowercase) + * + * public + */ + final public function getShortName() + { + return str_replace('np_','',strtolower(get_class($this))); + } + + /** + * Clears the option value cache which saves the option values during + * the plugin execution. This function is usefull if the options has + * changed during the plugin execution (especially in association with + * the PrePluginOptionsUpdate and the PostPluginOptionsUpdate events) + * + * public + **/ + final public function clearOptionValueCache() + { + $this->option_values = array(); + $this->plugin_options = 0; + return; + } + + // internal functions of the class starts here + protected $option_values; // oid_contextid => value + protected $option_info; // context_name => array('oid' => ..., 'default' => ...) + protected $plugin_options; // see getOption() + protected $plugid; // plugin id + + /** + * Class constructor: Initializes some internal data + */ + public function __construct() + { + $this->option_values = array(); // oid_contextid => value + $this->option_info = array(); // context_name => array('oid' => ..., 'default' => ...) + $this->plugin_options = 0; + } + + /** + * Retrieves an array of the top (or bottom) of an option from a plugin. + * @author TeRanEX + * @param string $context the context for the option: item, blog, member,... + * @param string $name the name of the option + * @param int $amount how many rows must be returned + * @param string $sort desc or asc + * @return array array with both values and contextid's + * @access private + */ + final protected function get_option_top($context, $name, $amount = 10, $sort = 'desc') + { + if ( ($sort != 'desc') && ($sort != 'asc') ) + { + $sort= 'desc'; } - function getEventList() - { - return array(); - } + $oid = $this->get_option_id($context, $name); - function getTableList() - { - return array(); - } + // retrieve the data and return + $query = "SELECT otype, oextra FROM %s WHERE oid = %d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), $oid); + $row = DB::getRow($query); - function hasAdminArea() - { - return 0; - } - - function install() + if ( ($this->optionCanBeNumeric($row['otype'])) && ($row['oextra'] == 'number' ) ) { + $orderby = 'CAST(ovalue AS SIGNED)'; } - - function unInstall() + else { + $orderby = 'ovalue'; } + $query = "SELECT ovalue value, ocontextid id FROM %s WHERE oid = %d ORDER BY %s %s LIMIT 0,%d;"; + $query = sprintf($query, sql_table('plugin_option'), $oid, $orderby, $sort, (integer) $amount); + $result = DB::getResult($query); - function init() - { - } - - function doSkinVar($skinType) + // create the array + $i = 0; + $top = array(); + foreach( $result as $row ) { + $top[$i++] = $row; } - function doTemplateVar(&$item) + // return the array (duh!) + return $top; + } + + /** + * Creates an option in the database table plugin_option_desc + * + * private + */ + final protected function create_option($context, $name, $desc, $type, $defValue, $typeExtras = '') + { + // create in plugin_option_desc + $query = 'INSERT INTO ' . sql_table('plugin_option_desc') + .' (opid, oname, ocontext, odesc, otype, odef, oextra)' + .' VALUES ('.intval($this->plugid) + .', '.DB::quoteValue($name) + .', '.DB::quoteValue($context) + .', '.DB::quoteValue($desc) + .', '.DB::quoteValue($type) + .', '.DB::quoteValue($defValue) + .', '.DB::quoteValue($typeExtras).')'; + DB::execute($query); + $oid = DB::getInsertId(); + + $key = $context . '_' . $name; + $this->option_info[$key] = array('oid' => $oid, 'default' => $defValue); + return 1; + } + + /** + * Deletes an option from the database tables + * plugin_option and plugin_option_desc + * + * private + */ + final protected function delete_option($context, $name) + { + $oid = $this->get_option_id($context, $name); + if ( !$oid ) { - $args = func_get_args(); - array_shift($args); - array_unshift($args, 'template'); - call_user_func_array(array(&$this,'doSkinVar'),$args); + return 0; // no such option } - function doTemplateCommentsVar(&$item, &$comment) - { - $args = func_get_args(); - array_shift($args); - array_shift($args); - array_unshift($args, 'template'); - call_user_func_array(array(&$this,'doSkinVar'),$args); - } + // delete all things from plugin_option + $query = "DELETE FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid); + DB::execute($query); - function doAction($type) - { - return _ERROR_PLUGIN_NOSUCHACTION; - } + // delete entry from plugin_option_desc + $query = "DELETE FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), $oid); + DB::execute($query); - function doIf($key,$value) - { - return false; - } + // clear from cache + unset($this->option_info["{$context}_{$name}"]); + $this->option_values = array(); + return 1; + } + + /** + * Update an option in the database table plugin_option + * + * returns: 1 on success, 0 on failure + * private + */ + final protected function set_option($context, $contextid, $name, $value) + { + global $manager; - function doItemVar (&$item) - { - } - - /** - * Checks if a plugin supports a certain feature. - * - * @returns 1 if the feature is reported, 0 if not - * @param $feature - * Name of the feature. See plugin documentation for more info - * 'SqlTablePrefix' -> if the plugin uses the sql_table() method to get table names - * 'HelpPage' -> if the plugin provides a helppage - * 'SqlApi' -> if the plugin uses the complete sql_* api (must also require nucleuscms 3.5) - */ - function supportsFeature($feature) + $oid = $this->get_option_id($context, $name); + if ( !$oid ) { return 0; } - - /** - * Report a list of plugin that is required to function - * - * @returns an array of names of plugin, an empty array indicates no dependency - */ - function getPluginDep() - { - return array(); - } - - // these helper functions should not be redefined in your plugin - - /** - * Creates a new option for this plugin - * - * @param name - * A string uniquely identifying your option. (max. length is 20 characters) - * @param description - * A description that will show up in the nucleus admin area (max. length: 255 characters) - * @param type - * Either 'text', 'yesno' or 'password' - * This info is used when showing 'edit plugin options' screens - * @param value - * Initial value for the option (max. value length is 128 characters) - */ - function createOption($name, $desc, $type, $defValue = '', $typeExtras = '') - { - return $this->_createOption('global', $name, $desc, $type, $defValue, $typeExtras); - } - function createBlogOption($name, $desc, $type, $defValue = '', $typeExtras = '') + // check if context id exists + switch ( $context ) { - return $this->_createOption('blog', $name, $desc, $type, $defValue, $typeExtras); + case 'member': + if ( !Member::existsID($contextid) ) + { + return 0; + } + break; + case 'blog': + if ( !$manager->existsBlogID($contextid) ) + { + return 0; + } + break; + case 'category': + if ( !$manager->existsCategory($contextid) ) + { + return 0; + } + break; + case 'item': + if ( !$manager->existsItem($contextid, true, true) ) + { + return 0; + } + break; + case 'global': + if ( $contextid != 0 ) + { + return 0; + } + break; } - function createMemberOption($name, $desc, $type, $defValue = '', $typeExtras = '') - { - return $this->_createOption('member', $name, $desc, $type, $defValue, $typeExtras); - } + // update plugin_option + $query = "DELETE FROM %s WHERE oid=%d and ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid); + DB::execute($query); - function createCategoryOption($name, $desc, $type, $defValue = '', $typeExtras = '') - { - return $this->_createOption('category', $name, $desc, $type, $defValue, $typeExtras); - } + $query = "INSERT INTO %s (ovalue, oid, ocontextid) VALUES (%s, %d, %d);"; + $query = sprintf($query, sql_table('plugin_option'), DB::quoteValue($value), $oid, $contextid); + DB::execute($query); - function createItemOption($name, $desc, $type, $defValue = '', $typeExtras = '') - { - return $this->_createOption('item', $name, $desc, $type, $defValue, $typeExtras); - } - - /** - * Removes the option from the database - * - * Note: Options get erased automatically on plugin uninstall - */ - function deleteOption($name) + // update cache + $this->option_values["{$oid}_{$contextid}"] = $value; + if ( $context == 'global' ) { - return $this->_deleteOption('global', $name); + $this->plugin_options[strtolower($name)] = $value; } - function deleteBlogOption($name) + return 1; + } + + /** + * Get an option from Cache or database + * - if not in the option Cache read it from the database + * - if not in the database write default values into the database + * + * private + */ + final protected function get_option($context, $contextid, $name) + { + $oid = $this->get_option_id($context, $name); + if ( !$oid ) { - return $this->_deleteOption('blog', $name); + return ''; } - function deleteMemberOption($name) - { - return $this->_deleteOption('member', $name); - } + $key = "{$oid}_{$contextid}"; - function deleteCategoryOption($name) + if ( isset($this->option_values[$key]) ) { - return $this->_deleteOption('category', $name); + return $this->option_values[$key]; } - function deleteItemOption($name) + // get from DB + $query = "SELECT ovalue FROM %s WHERE oid=%d and ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid); + $result = DB::getResult($query); + + if ( !$result || ($result->rowCount() == 0) ) { - return $this->_deleteOption('item', $name); + // fill DB with default value + $this->option_values[$key] = $this->get_default_value($context, $name); + $query = "INSERT INTO %s (oid, ocontextid, ovalue) VALUES (%d, %d, %s);"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid, DB::quoteValue($this->option_values[$key])); + DB::execute($query); } - - /** - * Sets the value of an option to something new - */ - function setOption($name, $value) + else { - return $this->_setOption('global', 0, $name, $value); + $row = $result->fetch(); + $this->option_values[$key] = $row['ovalue']; } - function setBlogOption($blogid, $name, $value) + return $this->option_values[$key]; + } + + /** + * Returns assoc array with all values for a given option + * (one option per possible context id) + * + * private + */ + final protected function get_all_options($context, $name) + { + $oid = $this->get_option_id($context, $name); + if ( !$oid ) { - return $this->_setOption('blog', $blogid, $name, $value); + return array(); } + $default_value = $this->get_default_value($context, $name); - function setMemberOption($memberid, $name, $value) + $options = array(); + $query = "SELECT %s as contextid FROM %s;"; + switch ( $context ) { - return $this->_setOption('member', $memberid, $name, $value); + case 'blog': + $query = sprintf($query, 'bnumber', sql_table('blog')); + break; + case 'category': + $query = sprintf($query, 'catid', sql_table('category')); + break; + case 'member': + $query = sprintf($query, 'mnumber', sql_table('member')); + break; + case 'item': + $query = sprintf($query, 'inumber', sql_table('item')); + break; } - function setCategoryOption($catid, $name, $value) + $result = DB::getResult($query); + if ( $result ) { - return $this->_setOption('category', $catid, $name, $value); - } - - function setItemOption($itemid, $name, $value) { - return $this->_setOption('item', $itemid, $name, $value); - } - - /** - * Retrieves the current value for an option - */ - function getOption($name) - { - // only request the options the very first time. On subsequent requests - // the static collection is used to save SQL queries. - if ( $this->plugin_options == 0 ) - { - $this->plugin_options = array(); - $query = sql_query( - 'SELECT d.oname as name, o.ovalue as value '. - 'FROM '. - sql_table('plugin_option').' o, '. - sql_table('plugin_option_desc').' d '. - 'WHERE d.opid='. intval($this->getID()).' AND d.oid=o.oid' - ); - while ( $row = sql_fetch_object($query) ) - { - $this->plugin_options[strtolower($row->name)] = $row->value; - } - } - if ( isset($this->plugin_options[strtolower($name)]) ) + foreach ( $result as $row ) { - return $this->plugin_options[strtolower($name)]; + $options[$row['contextid']] = $default_value; } - else { - return $this->_getOption('global', 0, $name); - } - } - - function getBlogOption($blogid, $name) - { - return $this->_getOption('blog', $blogid, $name); } - function getMemberOption($memberid, $name) + $query = "SELECT ocontextid, ovalue FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), $oid); + $result = DB::getResult($query); + foreach ( $result as $row ) { - return $this->_getOption('member', $memberid, $name); + $options[$row['ocontextid']] = $row['ovalue']; } + + return $options; + } + + /** + * NucleusPlugin::get_option_id + * + * Gets the 'option identifier' that corresponds to a given option name. + * When this method is called for the first time, all the OIDs for the plugin + * are loaded into memory, to avoid re-doing the same query all over. + * + * @param string $context option context + * @param string $name plugin name + * @return integer option id + */ + final protected function get_option_id($context, $name) + { + $key = "{$context}_{$name}"; - function getCategoryOption($catid, $name) + if ( array_key_exists($key, $this->option_info) + && array_key_exists('oid', $this->option_info[$key]) ) { - return $this->_getOption('category', $catid, $name); + return $this->option_info[$key]['oid']; } - function getItemOption($itemid, $name) - { - return $this->_getOption('item', $itemid, $name); - } - - /** - * Retrieves an associative array with the option value for each - * context id - */ - function getAllBlogOptions($name) + // load all OIDs for this plugin from the database + $this->option_info = array(); + $query = "SELECT oid, oname, ocontext, odef FROM %s WHERE opid=%d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), $this->plugid); + $result = DB::getResult($query); + foreach ( $result as $row ) { - return $this->_getAllOptions('blog', $name); + $k = $row['ocontext'] . '_' . $row['oname']; + $this->option_info[$k] = array('oid' => $row['oid'], 'default' => $row['odef']); } + $result->closeCursor(); - function getAllMemberOptions($name) - { - return $this->_getAllOptions('member', $name); - } + return $this->option_info[$key]['oid']; + } + final protected function get_default_value($context, $name) + { + $key = $context . '_' . $name; - function getAllCategoryOptions($name) + if ( array_key_exists($key, $this->option_info) + && array_key_exists('default', $this->option_info[$key]) ) { - return $this->_getAllOptions('category', $name); + return $this->option_info[$key]['default']; } + return; + } + + /** + * NucleusPlugin::delete_option_values() + * Deletes all option values for a given context and contextid + * (used when e.g. a blog, member or category is deleted) + * + *@static + *@param String $context global/blog/category/item/member + *@param Integer $contextid ID + *@return Void + */ + static public function delete_option_values($context, $contextid) + { + // delete all associated plugin options + $aOIDs = array(); + // find ids + $query = "SELECT oid FROM %s WHERE ocontext=%s;"; + $query = sprintf($query, sql_table('plugin_option_desc'), DB::quoteValue($context)); - function getAllItemOptions($name) + $result = DB::getResult($query); + foreach ( $result as $row ) { - return $this->_getAllOptions('item', $name); + array_push($aOIDs, $row['oid']); } - - /** - * Retrieves an indexed array with the top (or bottom) of an option - * (delegates to _getOptionTop()) - */ - function getBlogOptionTop($name, $amount = 10, $sort = 'desc') + $result->closeCursor(); + // delete those options. go go go + if ( count($aOIDs) > 0 ) { - return $this->_getOptionTop('blog', $name, $amount, $sort); + $query = "DELETE FROM %s WHERE oid in (%s) and ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), implode(',',$aOIDs), (integer) $contextid); + DB::execute($query); } + return; + } + + /** + * NucleusPlugin::getOptionMeta() + * splits the option's typeextra field (at ;'s) to split the meta collection + * + * @static + * @param string $typeExtra the value of the typeExtra field of an option + * @return array array of the meta-key/value-pairs + */ + static public function getOptionMeta($typeExtra) + { + $meta = array(); - function getMemberOptionTop($name, $amount = 10, $sort = 'desc') - { - return $this->_getOptionTop('member', $name, $amount, $sort); - } + /* 1. if $typeExtra includes delimiter ';', split it to tokens */ + $tokens = preg_split('#;#', $typeExtra); - function getCategoryOptionTop($name, $amount = 10, $sort = 'desc') + /* + * 2. if each of tokens includes "=", it consists of key => value + * else it's 'select' option + */ + foreach ( $tokens as $token ) { - return $this->_getOptionTop('category', $name, $amount, $sort); + $matches = array(); + if ( preg_match("#^([^=]+)?=([^=]+)?$#", $token, $matches) ) + { + $meta[$matches[1]] = $matches[2]; + } + else + { + $meta['select'] = $token; + } } + return $meta; + } + + /** + * NucleusPlugin::getOptionSelectValues() + * filters the selectlists out of the meta collection + * + * @static + * @param string $typeExtra the value of the typeExtra field of an option + * @return string the selectlist + */ + static public function getOptionSelectValues($typeExtra) + { + $meta = NucleusPlugin::getOptionMeta($typeExtra); - function getItemOptionTop($name, $amount = 10, $sort = 'desc') - { - return $this->_getOptionTop('item', $name, $amount, $sort); - } - - /** - * Returns the plugin ID - * - * public - */ - function getID() - { - return $this->plugid; - } - - /** - * Returns the URL of the admin area for this plugin (in case there's - * no such area, the returned information is invalid) - * - * public - */ - function getAdminURL() - { - global $CONF; - return $CONF['PluginURL'] . $this->getShortName() . '/'; - } - - /** - * Returns the directory where the admin directory is located and - * where the plugin can maintain his extra files - * - * public - */ - function getDirectory() - { - global $DIR_PLUGINS; - return $DIR_PLUGINS . $this->getShortName() . '/'; - } - - /** - * Derives the short name for the plugin from the classname (all - * lowercase) - * - * public - */ - function getShortName() - { - return str_replace('np_','',strtolower(get_class($this))); - } - - /** - * Clears the option value cache which saves the option values during - * the plugin execution. This function is usefull if the options has - * changed during the plugin execution (especially in association with - * the PrePluginOptionsUpdate and the PostPluginOptionsUpdate events) - * - * public - **/ - function clearOptionValueCache() + if ( array_key_exists('select', $meta) ) { - $this->_aOptionValues = array(); - $this->plugin_options = 0; + return $meta['select']; } - - // internal functions of the class starts here - - var $_aOptionValues; // oid_contextid => value - var $_aOptionToInfo; // context_name => array('oid' => ..., 'default' => ...) - var $plugin_options; // see getOption() - var $plugid; // plugin id - - - /** - * Class constructor: Initializes some internal data - */ - function NucleusPlugin() + return; + } + + /** + * checks if the eventlist in the database is up-to-date + * @return bool if it is up-to-date it return true, else false + * @author TeRanEX + */ + public function subscribtionListIsUptodate() + { + $res = DB::getResult('SELECT event FROM '.sql_table('plugin_event').' WHERE pid = '.$this->plugid); + $ev = array(); + foreach ( $res as $row ) { - $this->_aOptionValues = array(); // oid_contextid => value - $this->_aOptionToInfo = array(); // context_name => array('oid' => ..., 'default' => ...) - $this->plugin_options = 0; + array_push($ev, $row['event']); } - - /** - * Retrieves an array of the top (or bottom) of an option from a plugin. - * @author TeRanEX - * @param string $context the context for the option: item, blog, member,... - * @param string $name the name of the option - * @param int $amount how many rows must be returned - * @param string $sort desc or asc - * @return array array with both values and contextid's - * @access private - */ - function _getOptionTop($context, $name, $amount = 10, $sort = 'desc') + if ( count($ev) != count($this->getEventList()) ) { - if ( ($sort != 'desc') && ($sort != 'asc') ) - { - $sort= 'desc'; - } - - $oid = $this->_getOID($context, $name); - - // retrieve the data and return - $q = 'SELECT otype, oextra FROM '.sql_table('plugin_option_desc').' WHERE oid = '.$oid; - $query = sql_query($q); - - $o = sql_fetch_array($query); - - if ( ($this->optionCanBeNumeric($o['otype'])) && ($o['oextra'] == 'number' ) ) - { - $orderby = 'CAST(ovalue AS SIGNED)'; - } - else - { - $orderby = 'ovalue'; - } - $q = 'SELECT ovalue value, ocontextid id FROM '.sql_table('plugin_option').' WHERE oid = '.$oid.' ORDER BY '.$orderby.' '.$sort.' LIMIT 0,'.intval($amount); - $query = sql_query($q); - - // create the array - $i = 0; - $top = array(); - while( $row = sql_fetch_array($query) ) - { - $top[$i++] = $row; - } - - // return the array (duh!) - return $top; + return false; } - - /** - * Creates an option in the database table plugin_option_desc - * - * private - */ - function _createOption($context, $name, $desc, $type, $defValue, $typeExtras = '') + $d = array_diff($ev, $this->getEventList()); + if ( count($d) > 0 ) { - // create in plugin_option_desc - $query = 'INSERT INTO ' . sql_table('plugin_option_desc') - .' (opid, oname, ocontext, odesc, otype, odef, oextra)' - .' VALUES ('.intval($this->plugid) - .', \''.sql_real_escape_string($name).'\'' - .', \''.sql_real_escape_string($context).'\'' - .', \''.sql_real_escape_string($desc).'\'' - .', \''.sql_real_escape_string($type).'\'' - .', \''.sql_real_escape_string($defValue).'\'' - .', \''.sql_real_escape_string($typeExtras).'\')'; - sql_query($query); - $oid = sql_insert_id(); - - $key = $context . '_' . $name; - $this->_aOptionToInfo[$key] = array('oid' => $oid, 'default' => $defValue); - return 1; + // there are differences so the db is not up-to-date + return false; } - - - /** - * Deletes an option from the database tables - * plugin_option and plugin_option_desc - * - * private - */ - function _deleteOption($context, $name) + return true; + } + + /** + * NucleusPlugin::apply_plugin_options() + * Update its entry in database table + * + * @static + * @param $options: array ( 'oid' => array( 'contextid' => 'value')) + * (taken from request using requestVar()) + * @param $new_contextid: integer (accepts a contextid when it is for a new + * contextid there was no id available at the moment of writing the + * formcontrols into the page (by ex: itemOptions for new item) + * @return void + */ + static public function apply_plugin_options(&$options, $new_contextid = 0) + { + global $manager; + + if ( !is_array($options) ) { - $oid = $this->_getOID($context, $name); - if ( !$oid ) - { - return 0; // no such option - } - - // delete all things from plugin_option - sql_query('DELETE FROM ' . sql_table('plugin_option') . ' WHERE oid=' . $oid); - - // delete entry from plugin_option_desc - sql_query('DELETE FROM ' . sql_table('plugin_option_desc') . ' WHERE oid=' . $oid); - - // clear from cache - unset($this->_aOptionToInfo[$context . '_' . $name]); - $this->_aOptionValues = array(); - return 1; + return; } - - /** - * Update an option in the database table plugin_option - * - * returns: 1 on success, 0 on failure - * private - */ - function _setOption($context, $contextid, $name, $value) + + foreach ( $options as $oid => $values ) { - global $manager; - - $oid = $this->_getOID($context, $name); - if ( !$oid ) + // get option type info + $query = "SELECT opid, oname, ocontext, otype, oextra, odef FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), (integer) $oid); + $result = DB::getRow($query); + if ( $result ) { - return 0; - } - - // check if context id exists - switch ( $context ) - { - case 'member': - if ( !MEMBER::existsID($contextid) ) - { - return 0; - } - break; - case 'blog': - if ( !$manager->existsBlogID($contextid) ) + foreach ( $values as $id => $value ) + { + // decide wether we are using the contextid of newContextid + if ( $new_contextid != 0 ) { - return 0; + $contextid = $new_contextid; } - break; - case 'category': - if ( !$manager->existsCategory($contextid) ) + else { - return 0; + $contextid = $id; } - break; - case 'item': - if ( !$manager->existsItem($contextid, true, true) ) + + // retreive any metadata + $meta = NucleusPlugin::getOptionMeta($result['oextra']); + + // if the option is readonly or hidden it may not be saved + if ( array_key_exists('access', $meta) + && in_array($meta['access'], array('readonly', 'hidden')) ) { - return 0; + return; } - break; - case 'global': - if ( $contextid != 0 ) + + // value comes from request + $value = undoMagic($value); + + /* validation the value according to its type */ + switch ( $result['otype'] ) { - return 0; - } - break; - } - - - // update plugin_option - sql_query('DELETE FROM ' . sql_table('plugin_option') . ' WHERE oid='.intval($oid) . ' and ocontextid='. intval($contextid)); - sql_query('INSERT INTO ' . sql_table('plugin_option') . ' (ovalue, oid, ocontextid) VALUES (\''.sql_real_escape_string($value).'\', '. intval($oid) . ', ' . intval($contextid) . ')'); - - // update cache - $this->_aOptionValues[$oid . '_' . $contextid] = $value; - if ( $context == 'global') - { - $this->plugin_options[strtolower($name)] = $value; - } - - return 1; - } - - /** - * Get an option from Cache or database - * - if not in the option Cache read it from the database - * - if not in the database write default values into the database - * - * private - */ - function _getOption($context, $contextid, $name) - { - $oid = $this->_getOID($context, $name); - if ( !$oid ) - { - return ''; - } - - - $key = $oid . '_' . $contextid; - - if ( isset($this->_aOptionValues[$key]) ) - { - return $this->_aOptionValues[$key]; - } - - // get from DB - $res = sql_query('SELECT ovalue FROM ' . sql_table('plugin_option') . ' WHERE oid='.intval($oid).' and ocontextid=' . intval($contextid)); - - if ( !$res || (sql_num_rows($res) == 0) ) - { - $defVal = $this->_getDefVal($context, $name); - $this->_aOptionValues[$key] = $defVal; - - // fill DB with default value - $query = 'INSERT INTO ' . sql_table('plugin_option') . ' (oid,ocontextid,ovalue)' - .' VALUES ('.intval($oid).', '.intval($contextid).', \''.sql_real_escape_string($defVal).'\')'; - sql_query($query); - } - else - { - $o = sql_fetch_object($res); - $this->_aOptionValues[$key] = $o->ovalue; - } - - return $this->_aOptionValues[$key]; - } - - /** - * Returns assoc array with all values for a given option - * (one option per possible context id) - * - * private - */ - function _getAllOptions($context, $name) - { - $oid = $this->_getOID($context, $name); - if ( !$oid ) - { - return array(); - } - $defVal = $this->_getDefVal($context, $name); - - $aOptions = array(); - switch ( $context ) - { - case 'blog': - $r = sql_query('SELECT bnumber as contextid FROM ' . sql_table('blog')); - break; - case 'category': - $r = sql_query('SELECT catid as contextid FROM ' . sql_table('category')); - break; - case 'member': - $r = sql_query('SELECT mnumber as contextid FROM ' . sql_table('member')); - break; - case 'item': - $r = sql_query('SELECT inumber as contextid FROM ' . sql_table('item')); - break; - } - if ( $r ) - { - while ( $o = sql_fetch_object($r) ) - { - $aOptions[$o->contextid] = $defVal; - } - } - - $res = sql_query('SELECT ocontextid, ovalue FROM ' . sql_table('plugin_option') . ' WHERE oid=' . $oid); - while ( $o = sql_fetch_object($res) ) - { - $aOptions[$o->ocontextid] = $o->ovalue; - } - - return $aOptions; - } - - /** - * Gets the 'option identifier' that corresponds to a given option name. - * When this method is called for the first time, all the OIDs for the plugin - * are loaded into memory, to avoid re-doing the same query all over. - */ - function _getOID($context, $name) - { - $key = $context . '_' . $name; - $info = $this->_aOptionToInfo[$key]; - if ( is_array($info) ) - { - return $info['oid']; - } - - // load all OIDs for this plugin from the database - $this->_aOptionToInfo = array(); - $query = 'SELECT oid, oname, ocontext, odef FROM ' . sql_table('plugin_option_desc') . ' WHERE opid=' . intval($this->plugid); - $res = sql_query($query); - while ( $o = sql_fetch_object($res) ) - { - $k = $o->ocontext . '_' . $o->oname; - $this->_aOptionToInfo[$k] = array('oid' => $o->oid, 'default' => $o->odef); - } - sql_free_result($res); - - return $this->_aOptionToInfo[$key]['oid']; - } - function _getDefVal($context, $name) - { - $key = $context . '_' . $name; - $info = $this->_aOptionToInfo[$key]; - if ( is_array($info) ) - { - return $info['default']; - } - } - - - /** - * Deletes all option values for a given context and contextid - * (used when e.g. a blog, member or category is deleted) - * - * (static method) - */ - function _deleteOptionValues($context, $contextid) - { - // delete all associated plugin options - $aOIDs = array(); - // find ids - $query = 'SELECT oid FROM '.sql_table('plugin_option_desc') . ' WHERE ocontext=\''.sql_real_escape_string($context).'\''; - $res = sql_query($query); - while ( $o = sql_fetch_object($res) ) - { - array_push($aOIDs, $o->oid); - } - sql_free_result($res); - // delete those options. go go go - if ( count($aOIDs) > 0 ) - { - $query = 'DELETE FROM ' . sql_table('plugin_option') . ' WHERE oid in ('.implode(',',$aOIDs).') and ocontextid=' . intval($contextid); - sql_query($query); - } - } - - /** - * splits the option's typeextra field (at ;'s) to split the meta collection - * @param string $typeExtra the value of the typeExtra field of an option - * @return array array of the meta-key/value-pairs - * @author TeRanEX - * @static - */ - function getOptionMeta($typeExtra) - { - $tmpMeta = i18n::explode(';', $typeExtra); - $meta = array(); - for ( $i = 0; $i < count($tmpMeta); $i++ ) - { - if ( ($i == 0) && (!strstr($tmpMeta[0], '=')) ) - { - // we have the select-list - $meta['select'] = $tmpMeta[0]; - } - else - { - $tmp = i18n::explode('=', $tmpMeta[$i]); - $meta[$tmp[0]] = $tmp[1]; - } - } - return $meta; - } - - /** - * filters the selectlists out of the meta collection - * @param string $typeExtra the value of the typeExtra field of an option - * @return string the selectlist - * @author TeRanEX - */ - function getOptionSelectValues($typeExtra) - { - $meta = NucleusPlugin::getOptionMeta($typeExtra); - //the select list must always be the first part - return $meta['select']; - } - - /** - * checks if the eventlist in the database is up-to-date - * @return bool if it is up-to-date it return true, else false - * @author TeRanEX - */ - function subscribtionListIsUptodate() - { - $res = sql_query('SELECT event FROM '.sql_table('plugin_event').' WHERE pid = '.$this->getID()); - $ev = array(); - while( $a = sql_fetch_array($res) ) - { - array_push($ev, $a['event']); - } - if ( count($ev) != count($this->getEventList()) ) - { - return false; - } - $d = array_diff($ev, $this->getEventList()); - if ( count($d) > 0 ) - { - // there are differences so the db is not up-to-date - return false; - } - return true; - } - - /** - * @param $aOptions: array ( 'oid' => array( 'contextid' => 'value')) - * (taken from request using requestVar()) - * @param $newContextid: integer (accepts a contextid when it is for a new - * contextid there was no id available at the moment of writing the - * formcontrols into the page (by ex: itemOptions for new item) - * @static - */ - function _applyPluginOptions(&$aOptions, $newContextid = 0) - { - global $manager; - if ( !is_array($aOptions) ) - { - return; - } - - foreach ( $aOptions as $oid => $values ) - { - - // get option type info - $query = 'SELECT opid, oname, ocontext, otype, oextra, odef FROM ' . sql_table('plugin_option_desc') . ' WHERE oid=' . intval($oid); - $res = sql_query($query); - if ( $o = sql_fetch_object($res) ) - { - foreach ( $values as $key => $value ) - { - // avoid overriding the key used by foreach statement - $contextid=$key; - - // retreive any metadata - $meta = NucleusPlugin::getOptionMeta($o->oextra); - - // if the option is readonly or hidden it may not be saved - if ( ($meta['access'] != 'readonly') && ($meta['access'] != 'hidden') ) - { - - $value = undoMagic($value); // value comes from request - - switch ( $o->otype ) + case 'yesno': + if ( ($value != 'yes') && ($value != 'no') ) { - case 'yesno': - if ( ($value != 'yes') && ($value != 'no') ) - { - $value = 'no'; - } - break; - default: - break; + $value = 'no'; } - - // check the validity of numerical options - if ( ($meta['datatype'] == 'numerical') && (!is_numeric($value)) ) + break; + case 'text': + case 'select': + if ( array_key_exists('datatype', $meta) + && ($meta['datatype'] == 'numerical') && ($value != (integer) $value) ) { - //the option must be numeric, but the it isn't - //use the default for this option - $value = $o->odef; + $value = (integer) $result['odef']; } - - // decide wether we are using the contextid of newContextid - if ( $newContextid != 0 ) - { - $contextid = $newContextid; - } - - //trigger event PrePluginOptionsUpdate to give the plugin the - //possibility to change/validate the new value for the option - $manager->notify('PrePluginOptionsUpdate',array('context' => $o->ocontext, 'plugid' => $o->opid, 'optionname' => $o->oname, 'contextid' => $contextid, 'value' => &$value)); - - // delete the old value for the option - sql_query('DELETE FROM '.sql_table('plugin_option').' WHERE oid='.intval($oid).' AND ocontextid='.intval($contextid)); - sql_query('INSERT INTO '.sql_table('plugin_option')." (oid, ocontextid, ovalue) VALUES (".intval($oid).",".intval($contextid).",'" . sql_real_escape_string($value) . "')"); - } + break; + case 'password': + case 'textarea': + default: + break; } - } - // clear option value cache if the plugin object is already loaded - if ( is_object($o) ) - { - $plugin=& $manager->pidLoaded($o->opid); - if ( $plugin ) + + /* + * trigger event PrePluginOptionsUpdate to give the plugin the + * possibility to change/validate the new value for the option + */ + $data = array( + 'context' => $result['ocontext'], + 'plugid' => $result['opid'], + 'optionname' => $result['oname'], + 'contextid' => $contextid, + 'value' => &$value); + $manager->notify('PrePluginOptionsUpdate', $data); + + // delete and insert its fields of table in database + $query = "DELETE FROM %s WHERE oid=%d AND ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid); + DB::execute($query); + $query = "INSERT INTO %s (oid, ocontextid, ovalue) VALUES (%d, %d, %s);"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid, DB::quoteValue($value)); + DB::execute($query); + + // clear option value cache if the plugin object is already loaded + $plugin=& $manager->pidLoaded($result['opid']); + if ( $plugin ) { $plugin->clearOptionValueCache(); } + + continue; } } + continue; } + return; } -?> +}