Viewing file: plugin_api.inc.php (21.26 KB) -rw-rw-rw- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/*************************
Coppermine Photo Gallery
************************
Copyright (c) 2003-2008 Dev Team
v1.1 originally written by Gregory DEMAR
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3
as published by the Free Software Foundation.
********************************************
Coppermine version: 1.4.18
$HeadURL: https://coppermine.svn.sourceforge.net/svnroot/coppermine/trunk/cpg1.4.x/include/plugin_api.inc.php $
$Revision: 4380 $
$Author: gaugau $
$Date: 2008-04-12 12:00:19 +0200 (Sa, 12 Apr 2008) $
**********************************************/
global $thisplugin; // Stores the current plugin being processed
global $CPG_PLUGINS; // Stores all the plugins
$CPG_PLUGINS = array(); // Initialize the plugin array
define('CPG_EXEC_ALL','all'); // Define CPG_EXEC_ALL
define('CPG_EXEC_FIRST', 'first'); // Define CPG_EXEC_FIRST
define('CPG_EXEC_NEW', 'new'); // Define CPG_EXEC_NEW
if (!defined('IN_COPPERMINE')) { die('Not in Coppermine...');}
// Store the table name in CONFIG
$CONFIG['TABLE_PLUGINS'] = $CONFIG['TABLE_PREFIX'].'plugins';
/**
* Local plugin class
* Processes all the plugins (filters,actions,install,uninstall)
*/
class CPGPluginAPI {
/**
* CPGPluginAPI::load()
*
* Load all the plugins into the global CPG_PLUGINS array
*
* @param N/A
* @return N/A
**/
function load() {
global $CONFIG,$thisplugin,$USER_DATA,$CPG_PLUGINS,$lang_plugin_api;
// Get the installed plugins from the database and sort them by execution priority
$sql = 'select * from '.$CONFIG['TABLE_PLUGINS'].' order by priority asc;';
$result = cpg_db_query($sql);
// Exit if no plugins are installed
if (mysql_num_rows($result) == 0) {
return;
}
// Register page_end action for shutdown
register_shutdown_function('cpg_action_page_end');
// Register plugin_sleep action for shutdown
register_shutdown_function(array('CPGPluginAPI','sleep'));
// Used as a failsafe to keep plugins in order
$index = 0;
// Get the plugin properties from the database
while ($plugin = mysql_fetch_assoc($result)) {
// If configuration and codebase files aren't present, skip this plugin.
if (!file_exists('./plugins/'.$plugin['path'].'/codebase.php') &&
!file_exists('./plugins/'.$plugin['path'].'/configuration.php')) {
continue;
}
$plugin['index'] = $index;
$CPG_PLUGINS[$plugin['plugin_id']] = new CPGPlugin($plugin);
$thisplugin =& $CPG_PLUGINS[$plugin['plugin_id']];
include ('./plugins/'.$thisplugin->path.'/codebase.php');
// Check if plugin has a wakeup action
if (!($thisplugin->awake = CPGPluginAPI::action('plugin_wakeup',true,$thisplugin->plugin_id))) {
if ($CONFIG['log_mode']) {
log_write("Couldn't wake plugin '".$thisplugin->name."' at ".date("F j, Y, g:i a"),CPG_GLOBAL_LOG);
}
$thisplugin->filters = array();
$thisplugin->actions = array();
if (!isset($thisplugin->error['desc']) || is_null($thisplugin->error['desc'])) {
$thisplugin->error['desc'] = "Couldn't wake plugin '{$thisplugin->name}'";
}
}
$index++;
}
mysql_free_result($result);
}
/**
* CPGPluginAPI::installed()
*
* Check if a given plugin installed
*
* @param string $path_to_plugin_folder
* @return boolean TRUE/FALSE
**/
function installed( $plugin_folder ) {
global $CONFIG;
// Stores if a given plugin is installed or not
static $installed_array = array();
// If the plugin doesn't exist in the array get its information from the database
if (!isset($installed_array[$plugin_folder])) {
$sql = 'select plugin_id from '.$CONFIG['TABLE_PLUGINS'].' where '.
'path="'.$plugin_folder.'";';
$result = cpg_db_query($sql);
// If the plugin isn't in the database store a false value in the array
if (mysql_num_rows($result) == 0) {
$installed_array[$plugin_folder] = false;
return false;
}
// It's installed! Get the plugin_id
$plugin = mysql_fetch_assoc($result);
mysql_free_result($result);
// Store the plugin_id in the database
$installed_array[$plugin_folder] = $plugin['plugin_id'];
}
// Return the plugin_id or false, if the plugin isn't installed
return $installed_array[$plugin_folder];
}
/**
* CPGPluginAPI::filter()
*
* Checks all the plugin's for a given filter key sends the value
*
* @param string $filter_name
* @param variant $value
* @param boolean [$execute_scope = 'all']
* @return $value
**/
function& filter( $key, $value, $execute_scope = CPG_EXEC_ALL ) {
global $CPG_PLUGINS,$CONFIG,$USER_DATA,$thisplugin;
if(is_numeric($execute_scope)) {
$plugin_id = $execute_scope;
// Reference current plugin to local scope
$thisplugin =& $CPG_PLUGINS[$plugin_id];
// Skip this plugin; the key isn't set
if (!isset($thisplugin->filters[$key]) || (!$thisplugin->awake)) {
return $value;
}
// Get the filter's value from the plugin
$plugin_function = $thisplugin->filters[$key];
if (function_exists($plugin_function)) {
// Pass the value to the filter's function and get a value back
$value = call_user_func($plugin_function,$value);
// Copy back to global scope
//$CPG_PLUGINS[$plugin_id] = $thisplugin;
}
// Copy back to global scope
//$CPG_PLUGINS[$plugin_id] = $thisplugin;
// Loop through all the plugins
} else {
// Get all the plugin ids
$ids = array_keys($CPG_PLUGINS);
foreach($ids as $plugin_id) {
// Reference current plugin to local scope
$thisplugin =& $CPG_PLUGINS[$plugin_id];
// Get the filter's value from the plugin
if (!isset($thisplugin->filters[$key]) || ($key != 'plugin_wakeup' && !$thisplugin->awake)) {
continue;
} else {
$plugin_function = $thisplugin->filters[$key];
}
// Skip this plugin; Only looking for new plugins
if (($execute_scope == CPG_EXEC_NEW) && ($thisplugin->plugin_id != CPG_EXEC_NEW)) {
continue;
}
if (function_exists($plugin_function)) {
// Pass the value to the filter's function and get a value back
$value = call_user_func($plugin_function,$value);
// Copy back to global scope
//$CPG_PLUGINS[$plugin_id] = $thisplugin;
}
// Copy back to global scope
//$CPG_PLUGINS[$plugin_id] = $thisplugin;
if ($execute_scope != CPG_EXEC_ALL) {
return $value;
break;
}
}
}
// Return the value back to Coppermine
return $value;
}
/**
* CPGPluginAPI::action()
*
* Checks all the plugin's for a given action key sends the value
*
* @param string $action_name
* @param variant $value
* @param boolean [$execute_scope = 'all']
* @return $value
**/
function& action( $key, $value, $execute_scope = CPG_EXEC_ALL ) {
global $CPG_PLUGINS,$CONFIG,$USER_DATA,$thisplugin;
if(is_numeric($execute_scope)) {
$plugin_id = $execute_scope;
// Reference current plugin to local scope
$thisplugin =& $CPG_PLUGINS[$plugin_id];
// Skip this plugin; the key isn't set
if (!isset($thisplugin->actions[$key]) || (!$thisplugin->awake && $key!='plugin_wakeup')) {
return $value;
}
// Get the filter's value from the plugin
$plugin_function = $thisplugin->actions[$key];
if (function_exists($plugin_function)) {
// Pass the value to the filter's function and get a value back
$value = call_user_func($plugin_function,$value);
// Copy back to global scope
//$CPG_PLUGINS[$plugin_id] = $thisplugin;
}
// Copy back to global scope
//$CPG_PLUGINS[$plugin_id] = $thisplugin;
// Loop through all the plugins
} else {
// Get all the plugin ids
$ids = array_keys($CPG_PLUGINS);
foreach($ids as $plugin_id) {
// Copy current plugin to local scope
$thisplugin =& $CPG_PLUGINS[$plugin_id]; //changed to reference for PHP4 see note below
// Get the action's value from the plugin
if (!isset($thisplugin->actions[$key]) || ($key != 'plugin_wakeup' && !$thisplugin->awake)) {
continue;
} else {
$plugin_function = $thisplugin->actions[$key];
}
// Skip this plugin; Only looking for new plugins
if (($execute_scope == CPG_EXEC_NEW) && ($thisplugin->plugin_id != CPG_EXEC_NEW)) {
continue;
}
if (function_exists($plugin_function)) {
// Pass the value to the action's function and get a value back
$value = call_user_func($plugin_function,$value);
/**
* Disabled by donnoman
* when plugins cause any other underlying api hooks to be executed while
* they are running, $thisplugin becomes invalid because it is reset
* by the underlying calls to the plugin system. Therefore the results of copying
* $thisplugin to the global scope is undefined. We don't know what plugin/revision is contained in
* $thisplugin.
*
* This shouldn't be a problem with PHP5 since objects are passed by reference by default
* there shouldn't be much cause to write over a refreenced object with a new reference to the same object.
*
* PHP4 on the other hand copies objects, we should probably always pass the object by reference
* which shouldn't cause PHP5 any greif, and will allow PHP4 to have the latest information from the plugin before
* it's reference was changed to a different plugin.
*/
// Copy back to global scope
//$CPG_PLUGINS[$plugin_id] = $thisplugin;
}
if ($execute_scope != CPG_EXEC_ALL) {
return $value;
break;
}
}
}
// Return the value back to Coppermine
return $value;
}
/**
* CPGPluginAPI::wakeup()
*
* Wakes a plugin
*
* @param array $properties
* @return CPGPlugin $object
**/
function wakeup($properties) {
global $CONFIG,$USER_DATA,$CPG_PLUGINS,$thisplugin,$lang_plugin_api;
// Get a new instance of the plugin object
$CPG_PLUGINS[$properties['plugin_id']] = new CPGPlugin($properties);
$thisplugin =& $CPG_PLUGINS[$properties['plugin_id']];
// Include the plugin's code into Coppermine
include ('./plugins/'.$thisplugin->path.'/codebase.php');
return;
}
/**
* CPGPluginAPI::sleep()
*
* Executes 'plugin_sleep' action
*
* @param N/A
* @return N/A
**/
function sleep() {
global $CPG_PLUGINS,$thisplugin,$lang_plugin_api;
// Loop through all the plugins
foreach($CPG_PLUGINS as $thisplugin) {
// If the plugin has a sleep action, execute it
if (!CPGPluginAPI::action('plugin_sleep',true,$thisplugin->plugin_id)) {
if ($CONFIG['log_mode']) {
log_write("Couldn't put plugin '".$thisplugin->name."' to sleep at ".date("F j, Y, g:i a"),CPG_GLOBAL_LOG);
}
// Couldn't put plugin to sleep...Die!
sprintf($lang_plugin_api['error_sleep'],$thisplugin->name);
}
}
}
/**
* CPGPluginAPI::install()
*
* Installs a plugin and executes 'plugin_install' action
*
* @param string $path_to_plugin_folder
* @return N/A
**/
function install($path) {
global $CONFIG,$thisplugin,$CPG_PLUGINS,$lang_plugin_api;
// If this plugin is already installed return true
if (CPGPluginAPI::installed($path)) {
return true;
}
// If the codebase and configuration.php file is missing return false
if (!file_exists('./plugins/'.$path.'/codebase.php') &&
!file_exists('./plugins/'.$path.'/configuration.php')) {
return false;
}
// Get the lowest priority level (highest number) from the database
$sql = 'select priority from '.$CONFIG['TABLE_PLUGINS'].' order by priority desc limit 1;';
$result = cpg_db_query($sql);
$data = mysql_fetch_assoc($result);
mysql_free_result($result);
// Set the execution priority to last
$priority = (is_null($data['priority'])) ? (0) : ($data['priority']+1);
// Grab the plugin's credits
include_once ('./plugins/'.$path.'/configuration.php');
// Create a generic plugin object
$thisplugin = new CPGPlugin(
array(
'plugin_id' => 'new',
'name' => $name,
'priority' => $priority,
'path' => $path
)
);
$thisplugin->awake = true;
// Grab plugin's code
include_once ('./plugins/'.$path.'/codebase.php');
// Copy it to the global scope
$CPG_PLUGINS['new'] = $thisplugin;
// If the plugin has an install action, execute it
$installed = CPGPluginAPI::action('plugin_install',true,CPG_EXEC_NEW);
// If $installed is boolean then plugin was installed; Return true
if (is_bool($installed) && $installed) {
$sql = 'insert into '.$CONFIG['TABLE_PLUGINS'].' '.
'(name, path,priority) '.
' values '.
'("'.addslashes($name).'",'.
'"'.addslashes($path).'",'.
$priority.');';
$result = cpg_db_query($sql);
if ($CONFIG['log_mode']) {
log_write("Plugin '".$name."' installed at ".date("F j, Y, g:i a"),CPG_GLOBAL_LOG);
}
return $installed;
// If $installed is an integer then the plugin needs to be configured; Return the value
} elseif (is_int($installed)) {
return $installed;
// Plugin wasn't installed; Display an error
} else {
// The plugin's install function failed
cpg_die(CRITICAL_ERROR,sprintf($lang_plugin_api['error_install'],$thisplugin->name),__FILE__,__LINE__);
}
}
/**
* CPGPluginAPI::uninstall()
*
* Uninstalls a plugin and executes 'plugin_uninstall' action
*
* @param integer $plugin_id
* @return N/A
**/
function uninstall($plugin_id) {
global $CONFIG,$USER_DATA,$CPG_PLUGINS,$thisplugin,$lang_plugin_api;
if (!isset($CPG_PLUGINS[$plugin_id])) {
return true;
}
// Grab the plugin from the global scope
$thisplugin =& $CPG_PLUGINS[$plugin_id];
// Grab the priority level, so you can shift the ones in the database
$priority = $thisplugin->priority;
// If plugin has an uninstall action, execute it
$uninstalled = CPGPluginAPI::action('plugin_uninstall',true,$plugin_id);
if (is_bool($uninstalled) && $uninstalled) {
$sql = 'delete from '.$CONFIG['TABLE_PLUGINS'].' '.
'where plugin_id='.$plugin_id.';';
$result = cpg_db_query($sql);
// Shift the plugins up
$sql = 'update '.$CONFIG['TABLE_PLUGINS'].' set priority=priority-1 where priority>'.$priority.';';
$result = cpg_db_query($sql);
unset($CPG_PLUGINS[$plugin_id]);
if ($CONFIG['log_mode']) {
log_write("Plugin '".$name."' uninstalled at ".date("F j, Y, g:i a"),CPG_GLOBAL_LOG);
}
return true;
// If $uninstalled is an integer then the plugin needs to be cleaned up; Return the value
} elseif (is_numeric($uninstalled)) {
return $uninstalled;
} else {
// The plugin's uninstall action failed
cpg_die(CRITICAL_ERROR,sprintf($lang_plugin_api['error_uninstall'],$thisplugin->name),__FILE__,__LINE__);
}
}
}
/**
* class CPGPlugin
*
* The plugin object
**/
class CPGPlugin {
var $actions = array();
var $filters = array();
var $awake = false;
var $error = array();
/**
* CPGPlugin()
*
* Initialize the plugin
*
* @param array $properties
* @return N/A
**/
function CPGPlugin($properties) {
// Store the properties in the object
foreach($properties as $key => $value) {
$this->$key = stripslashes($value);
}
$this->fullpath = './plugins/'.$this->path;
}
/**
* cpg_add_filter()
*
* Add a plugin filter
*
* @param string $action
* @param variant $value
* @return N/A
**/
function add_filter($key,$value) {
if (!isset($this->filters[$key])) {
$this->filters[$key] = $value;
}
}
/**
* cpg_delete_filter()
*
* Delete a plugin filter
*
* @param integer $plugin_id
* @return N/A
**/
function delete_filter($key) {
if (isset($this->filters[$key])) {
unset($this->filters[$key]);
}
}
/**
* cpg_add_action()
*
* Add a plugin action
*
* @param string $action
* @param variant $value
* @return N/A
**/
function add_action($key,$value) {
if (!isset($this->actions[$key])) {
$this->actions[$key] = $value;
}
}
/**
* cpg_delete_action()
*
* Delete a plugin action
*
* @param integer $plugin_id
* @return N/A
**/
function delete_action($key) {
if (isset($this->actions[$key])) {
unset($this->actions[$key]);
}
}
}
/**
* cpg_get_scope()
*
* Get the current plugin from the scope
* Sets global variable $thisplugin to return value
*
* @param integer [$plugin_id = null]
* @return CPGPlugin $object
**/
function& cpg_get_scope( $plugin_id = null ) {
global $CPG_PLUGINS,$thisplugin;
if (!is_null($plugin_id)) {
return $CPG_PLUGINS[$plugin_id];
} else {
$plugin_id = (int) $_GET['scope'];
$thisplugin =& $CPG_PLUGINS[$plugin_id];
return $CPG_PLUGINS[$plugin_id];
}
}
/**
* cpg_action_page_end()
*
* Executes page_end action on all plugins
*
* @param null
* @return N/A
**/
function cpg_action_page_end() {
CPGPluginAPI::action('page_end',null);
}
/**
* cpg_filter_page_html()
*
* Executes page_html filter on all plugins
*
* @param string HTML
* @return string HTML
**/
function& cpg_filter_page_html( &$html ) {
return CPGPluginAPI::filter('page_html',$html);
}
/**
* cpg_get_dir_list()
*
* Returns all the subdirecties in a given folder
*
* @param string $path_to_folder
* @return array $subdirectories
**/
function& cpg_get_dir_list($folder) {
global $CONFIG;
$dirs = array();
$dir = opendir($folder);
while (($file = readdir($dir)) !== false) {
if (is_dir($folder . $file) && $file != '.' && $file != '..') {
$dirs[] = $file;
}
}
closedir($dir);
natcasesort($dirs);
return $dirs;
}
?>
|