2014-07-06 13:21:10 +02:00
|
|
|
<?php
|
|
|
|
// +-----------------------------------------------------------------------+
|
|
|
|
// | Piwigo - a PHP based photo gallery |
|
|
|
|
// +-----------------------------------------------------------------------+
|
2016-08-27 21:53:29 +02:00
|
|
|
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
|
2014-07-06 13:21:10 +02:00
|
|
|
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
|
|
|
|
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
|
|
|
|
// +-----------------------------------------------------------------------+
|
|
|
|
// | 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 |
|
|
|
|
// | |
|
|
|
|
// | This program is distributed in the hope that it will be useful, but |
|
|
|
|
// | WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
|
|
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
|
|
|
// | General Public License for more details. |
|
|
|
|
// | |
|
|
|
|
// | You should have received a copy of the GNU General Public License |
|
|
|
|
// | along with this program; if not, write to the Free Software |
|
|
|
|
// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
|
|
|
|
// | USA. |
|
|
|
|
// +-----------------------------------------------------------------------+
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @package functions\plugins
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** base directory of plugins */
|
|
|
|
define('PHPWG_PLUGINS_PATH', PHPWG_ROOT_PATH.'plugins/');
|
|
|
|
/** default priority for plugins handlers */
|
|
|
|
define('EVENT_HANDLER_PRIORITY_NEUTRAL', 50);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used to declare maintenance methods of a plugin.
|
|
|
|
*/
|
2015-07-05 19:03:18 +02:00
|
|
|
class PluginMaintain
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
|
|
|
/** @var string $plugin_id */
|
|
|
|
protected $plugin_id;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $id
|
|
|
|
*/
|
|
|
|
function __construct($id)
|
|
|
|
{
|
|
|
|
$this->plugin_id = $id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $plugin_version
|
|
|
|
* @param array &$errors - used to return error messages
|
|
|
|
*/
|
2015-07-05 19:03:18 +02:00
|
|
|
function install($plugin_version, &$errors=array()) {}
|
2014-07-06 13:21:10 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $plugin_version
|
|
|
|
* @param array &$errors - used to return error messages
|
|
|
|
*/
|
2015-07-05 19:03:18 +02:00
|
|
|
function activate($plugin_version, &$errors=array()) {}
|
2014-07-06 13:21:10 +02:00
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
function deactivate() {}
|
2014-07-06 13:21:10 +02:00
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
function uninstall() {}
|
2014-07-06 13:21:10 +02:00
|
|
|
|
|
|
|
/**
|
2015-07-05 19:03:18 +02:00
|
|
|
* @param string $old_version
|
|
|
|
* @param string $new_version
|
|
|
|
* @param array &$errors - used to return error messages
|
2014-07-06 13:21:10 +02:00
|
|
|
*/
|
2015-07-05 19:03:18 +02:00
|
|
|
function update($old_version, $new_version, &$errors=array()) {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @removed 2.7
|
|
|
|
*/
|
|
|
|
function autoUpdate()
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
if (is_admin() && !defined('IN_WS'))
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
trigger_error('Function PluginMaintain::autoUpdate deprecated', E_USER_WARNING);
|
2014-07-06 13:21:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used to declare maintenance methods of a theme.
|
|
|
|
*/
|
2015-07-05 19:03:18 +02:00
|
|
|
class ThemeMaintain
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
|
|
|
/** @var string $theme_id */
|
|
|
|
protected $theme_id;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $id
|
|
|
|
*/
|
|
|
|
function __construct($id)
|
|
|
|
{
|
|
|
|
$this->theme_id = $id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $theme_version
|
|
|
|
* @param array &$errors - used to return error messages
|
|
|
|
*/
|
2015-07-05 19:03:18 +02:00
|
|
|
function activate($theme_version, &$errors=array()) {}
|
2014-07-06 13:21:10 +02:00
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
function deactivate() {}
|
2014-07-06 13:21:10 +02:00
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
function delete() {}
|
2014-07-06 13:21:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register an event handler.
|
|
|
|
*
|
|
|
|
* @param string $event the name of the event to listen to
|
|
|
|
* @param Callable $func the callback function
|
|
|
|
* @param int $priority greater priority will be executed at last
|
2015-07-05 19:03:18 +02:00
|
|
|
* @param string $include_path file to include before executing the callback
|
|
|
|
* @return bool false is handler already exists
|
2014-07-06 13:21:10 +02:00
|
|
|
*/
|
|
|
|
function add_event_handler($event, $func,
|
2015-07-05 19:03:18 +02:00
|
|
|
$priority=EVENT_HANDLER_PRIORITY_NEUTRAL, $include_path=null)
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
|
|
|
global $pwg_event_handlers;
|
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
if (isset($pwg_event_handlers[$event][$priority]))
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
foreach ($pwg_event_handlers[$event][$priority] as $handler)
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
if ($handler['function'] == $func)
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
$pwg_event_handlers[$event][$priority][] = array(
|
|
|
|
'function' => $func,
|
|
|
|
'include_path' => is_string($include_path) ? $include_path : null,
|
|
|
|
);
|
|
|
|
|
|
|
|
ksort($pwg_event_handlers[$event]);
|
2014-07-06 13:21:10 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes an event handler.
|
|
|
|
* @see add_event_handler()
|
|
|
|
*
|
|
|
|
* @param string $event
|
|
|
|
* @param Callable $func
|
|
|
|
* @param int $priority
|
|
|
|
*/
|
|
|
|
function remove_event_handler($event, $func,
|
|
|
|
$priority=EVENT_HANDLER_PRIORITY_NEUTRAL)
|
|
|
|
{
|
|
|
|
global $pwg_event_handlers;
|
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
if (!isset($pwg_event_handlers[$event][$priority]))
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for ($i=0; $i<count($pwg_event_handlers[$event][$priority]); $i++)
|
|
|
|
{
|
|
|
|
if ($pwg_event_handlers[$event][$priority][$i]['function']==$func)
|
|
|
|
{
|
|
|
|
unset($pwg_event_handlers[$event][$priority][$i]);
|
|
|
|
$pwg_event_handlers[$event][$priority] =
|
|
|
|
array_values($pwg_event_handlers[$event][$priority]);
|
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
if (empty($pwg_event_handlers[$event][$priority]))
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
unset($pwg_event_handlers[$event][$priority]);
|
|
|
|
if (empty($pwg_event_handlers[$event]))
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
unset($pwg_event_handlers[$event]);
|
2014-07-06 13:21:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Triggers a modifier event and calls all registered event handlers.
|
|
|
|
* trigger_change() is used as a modifier: it allows to transmit _$data_
|
|
|
|
* through all handlers, thus each handler MUST return a value,
|
|
|
|
* optional _$args_ are not transmitted.
|
|
|
|
*
|
|
|
|
* @since 2.6
|
|
|
|
*
|
|
|
|
* @param string $event
|
|
|
|
* @param mixed $data data to transmit to all handlers
|
|
|
|
* @param mixed $args,... optional arguments
|
2015-07-05 19:03:18 +02:00
|
|
|
* @return mixed $data
|
2014-07-06 13:21:10 +02:00
|
|
|
*/
|
|
|
|
function trigger_change($event, $data=null)
|
|
|
|
{
|
|
|
|
global $pwg_event_handlers;
|
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
if (isset($pwg_event_handlers['trigger']))
|
|
|
|
{// debugging
|
|
|
|
trigger_notify('trigger',
|
|
|
|
array('type'=>'event', 'event'=>$event, 'data'=>$data)
|
|
|
|
);
|
2014-07-06 13:21:10 +02:00
|
|
|
}
|
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
if (!isset($pwg_event_handlers[$event]))
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
$args = func_get_args();
|
2015-07-05 19:03:18 +02:00
|
|
|
array_shift($args);
|
2014-07-06 13:21:10 +02:00
|
|
|
|
|
|
|
foreach ($pwg_event_handlers[$event] as $priority => $handlers)
|
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
foreach ($handlers as $handler)
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
$args[0] = $data;
|
|
|
|
|
|
|
|
if (!empty($handler['include_path']))
|
|
|
|
{
|
|
|
|
include_once($handler['include_path']);
|
|
|
|
}
|
|
|
|
|
|
|
|
$data = call_user_func_array($handler['function'], $args);
|
2014-07-06 13:21:10 +02:00
|
|
|
}
|
|
|
|
}
|
2015-07-05 19:03:18 +02:00
|
|
|
|
|
|
|
if (isset($pwg_event_handlers['trigger']))
|
|
|
|
{// debugging
|
|
|
|
trigger_notify('trigger',
|
|
|
|
array('type'=>'post_event', 'event'=>$event, 'data'=>$data)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2014-07-06 13:21:10 +02:00
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Triggers a notifier event and calls all registered event handlers.
|
|
|
|
* trigger_notify() is only used as a notifier, no modification of data is possible
|
|
|
|
*
|
|
|
|
* @since 2.6
|
|
|
|
*
|
|
|
|
* @param string $event
|
|
|
|
* @param mixed $args,... optional arguments
|
|
|
|
*/
|
|
|
|
function trigger_notify($event)
|
|
|
|
{
|
|
|
|
global $pwg_event_handlers;
|
2015-07-05 19:03:18 +02:00
|
|
|
|
|
|
|
if (isset($pwg_event_handlers['trigger']) and $event!='trigger')
|
|
|
|
{// debugging - avoid recursive calls
|
|
|
|
trigger_notify('trigger',
|
|
|
|
array('type'=>'action', 'event'=>$event, 'data'=>null)
|
|
|
|
);
|
2014-07-06 13:21:10 +02:00
|
|
|
}
|
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
if (!isset($pwg_event_handlers[$event]))
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$args = func_get_args();
|
2015-07-05 19:03:18 +02:00
|
|
|
array_shift($args);
|
2014-07-06 13:21:10 +02:00
|
|
|
|
|
|
|
foreach ($pwg_event_handlers[$event] as $priority => $handlers)
|
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
foreach ($handlers as $handler)
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
if (!empty($handler['include_path']))
|
|
|
|
{
|
|
|
|
include_once($handler['include_path']);
|
|
|
|
}
|
2014-07-06 13:21:10 +02:00
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
call_user_func_array($handler['function'], $args);
|
2014-07-06 13:21:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Saves some data with the associated plugin id, data are only available
|
|
|
|
* during script lifetime.
|
|
|
|
* @depracted 2.6
|
|
|
|
*
|
|
|
|
* @param string $plugin_id
|
|
|
|
* @param mixed &$data
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
function set_plugin_data($plugin_id, &$data)
|
|
|
|
{
|
|
|
|
global $pwg_loaded_plugins;
|
|
|
|
if ( isset($pwg_loaded_plugins[$plugin_id]) )
|
|
|
|
{
|
|
|
|
$pwg_loaded_plugins[$plugin_id]['plugin_data'] = &$data;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieves plugin data saved previously with set_plugin_data.
|
|
|
|
* @see set_plugin_data()
|
|
|
|
* @depracted 2.6
|
|
|
|
*
|
|
|
|
* @param string $plugin_id
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
function &get_plugin_data($plugin_id)
|
|
|
|
{
|
|
|
|
global $pwg_loaded_plugins;
|
|
|
|
if ( isset($pwg_loaded_plugins[$plugin_id]['plugin_data']) )
|
|
|
|
{
|
|
|
|
return $pwg_loaded_plugins[$plugin_id]['plugin_data'];
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an array of plugins defined in the database.
|
|
|
|
*
|
|
|
|
* @param string $state optional filter
|
|
|
|
* @param string $id returns only data about given plugin
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function get_db_plugins($state='', $id='')
|
|
|
|
{
|
|
|
|
$query = '
|
|
|
|
SELECT * FROM '.PLUGINS_TABLE;
|
|
|
|
$clauses = array();
|
|
|
|
if (!empty($state))
|
|
|
|
{
|
|
|
|
$clauses[] = 'state=\''.$state.'\'';
|
|
|
|
}
|
|
|
|
if (!empty($id))
|
|
|
|
{
|
|
|
|
$clauses[] = 'id="'.$id.'"';
|
|
|
|
}
|
|
|
|
if (count($clauses))
|
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
$query .= '
|
2014-07-06 13:21:10 +02:00
|
|
|
WHERE '. implode(' AND ', $clauses);
|
|
|
|
}
|
|
|
|
|
2015-07-05 19:03:18 +02:00
|
|
|
return query2array($query);
|
2014-07-06 13:21:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-07-05 19:03:18 +02:00
|
|
|
* Loads a plugin in memory.
|
|
|
|
* It performs autoupdate, includes the main.inc.php file and updates *$pwg_loaded_plugins*.
|
2014-07-06 13:21:10 +02:00
|
|
|
*
|
|
|
|
* @param string $plugin
|
|
|
|
*/
|
|
|
|
function load_plugin($plugin)
|
|
|
|
{
|
|
|
|
$file_name = PHPWG_PLUGINS_PATH.$plugin['id'].'/main.inc.php';
|
2015-07-05 19:03:18 +02:00
|
|
|
if (file_exists($file_name))
|
2014-07-06 13:21:10 +02:00
|
|
|
{
|
2015-07-05 19:03:18 +02:00
|
|
|
autoupdate_plugin($plugin);
|
2014-07-06 13:21:10 +02:00
|
|
|
global $pwg_loaded_plugins;
|
|
|
|
$pwg_loaded_plugins[ $plugin['id'] ] = $plugin;
|
2015-07-05 19:03:18 +02:00
|
|
|
include_once($file_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Performs update task of a plugin.
|
|
|
|
* Autoupdate is only performed if the plugin has a maintain.class.php file.
|
|
|
|
*
|
|
|
|
* @since 2.7
|
|
|
|
*
|
|
|
|
* @param array &$plugin (id, version, state) will be updated if version changes
|
|
|
|
*/
|
|
|
|
function autoupdate_plugin(&$plugin)
|
|
|
|
{
|
|
|
|
// try to find the filesystem version in lines 2 to 10 of main.inc.php
|
|
|
|
$fh = fopen(PHPWG_PLUGINS_PATH.$plugin['id'].'/main.inc.php', 'r');
|
|
|
|
$fs_version = null;
|
|
|
|
$i = -1;
|
|
|
|
|
|
|
|
while (($line = fgets($fh))!==false && $fs_version==null && $i<10)
|
|
|
|
{
|
|
|
|
$i++;
|
|
|
|
if ($i < 2) continue; // first lines are typically "<?php" and "/*"
|
|
|
|
|
|
|
|
if (preg_match('/Version:\\s*([\\w.-]+)/', $line, $matches))
|
|
|
|
{
|
|
|
|
$fs_version = $matches[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose($fh);
|
|
|
|
|
|
|
|
// if version is auto (dev) or superior
|
|
|
|
if ($fs_version != null && (
|
|
|
|
$fs_version == 'auto' || $plugin['version'] == 'auto' ||
|
|
|
|
safe_version_compare($plugin['version'], $fs_version, '<')
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
$plugin['version'] = $fs_version;
|
|
|
|
|
|
|
|
$maintain_file = PHPWG_PLUGINS_PATH.$plugin['id'].'/maintain.class.php';
|
|
|
|
|
|
|
|
// autoupdate is applicable only to plugins with 2.7 architecture
|
|
|
|
if (file_exists($maintain_file))
|
|
|
|
{
|
|
|
|
global $page;
|
|
|
|
|
|
|
|
// call update method
|
|
|
|
include_once($maintain_file);
|
|
|
|
|
|
|
|
$classname = $plugin['id'].'_maintain';
|
|
|
|
$plugin_maintain = new $classname($plugin['id']);
|
|
|
|
$plugin_maintain->update($plugin['version'], $fs_version, $page['errors']);
|
|
|
|
}
|
|
|
|
|
|
|
|
// update database (only on production)
|
|
|
|
if ($plugin['version'] != 'auto')
|
|
|
|
{
|
|
|
|
$query = '
|
|
|
|
UPDATE '. PLUGINS_TABLE .'
|
|
|
|
SET version = "'. $plugin['version'] .'"
|
|
|
|
WHERE id = "'. $plugin['id'] .'"
|
|
|
|
;';
|
|
|
|
pwg_query($query);
|
|
|
|
}
|
2014-07-06 13:21:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads all the registered plugins.
|
|
|
|
*/
|
|
|
|
function load_plugins()
|
|
|
|
{
|
|
|
|
global $conf, $pwg_loaded_plugins;
|
|
|
|
$pwg_loaded_plugins = array();
|
|
|
|
if ($conf['enable_plugins'])
|
|
|
|
{
|
|
|
|
$plugins = get_db_plugins('active');
|
|
|
|
foreach( $plugins as $plugin)
|
|
|
|
{// include main from a function to avoid using same function context
|
|
|
|
load_plugin($plugin);
|
|
|
|
}
|
2015-07-05 19:03:18 +02:00
|
|
|
trigger_notify('plugins_loaded');
|
2014-07-06 13:21:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
?>
|