source: trunk/include/functions_plugins.inc.php @ 25406

Last change on this file since 25406 was 25406, checked in by mistic100, 10 years ago

feature 2998: Maintenance class for plugin

  • Property svn:eol-style set to LF
File size: 10.1 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2013 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24/*
25Events and event handlers are the core of Piwigo plugin management.
26Plugins are addons that are found in plugins subdirectory. If activated, PWG
27will include the index.php of each plugin.
28Events are triggered by PWG core code. Plugins (or even PWG itself) can
29register their functions to handle these events. An event is identified by a
30string.
31*/
32
33define('PHPWG_PLUGINS_PATH', PHPWG_ROOT_PATH.'plugins/');
34define('EVENT_HANDLER_PRIORITY_NEUTRAL', 50);
35
36
37/**
38 * class PluginMaintain
39 * used to declare maintenance methods of a plugin
40 */
41abstract class PluginMaintain 
42{
43  protected $plugin_id;
44 
45  function __construct($id)
46  {
47    $this->plugin_id = $id;
48  }
49 
50  abstract function install($plugin_version, &$errors=array());
51  abstract function activate($plugin_version, &$errors=array());
52  abstract function deactivate();
53  abstract function uninstall();
54 
55  /*
56   * test if a plugin needs to be updated and call a update function
57   * @param: string $version, version exposed by the plugin
58   * @param: string $on_update, name of a method to call when an update is needed
59   *          it receives the previous version as first parameter
60   */
61  function autoUpdate($version, $on_update=null)
62  {
63    global $pwg_loaded_plugins;
64   
65    $current_version = $pwg_loaded_plugins[$this->plugin_id]['version'];
66   
67    if ( $version == 'auto' or $current_version == 'auto'
68        or version_compare($current_version, $version, '<')
69      )
70    {
71      if (!empty($on_update))
72      {
73        call_user_func(array(&$this, $on_update), $current_version);
74      }
75     
76      if ($version != 'auto')
77      {
78        $query = '
79UPDATE '. PLUGINS_TABLE .'
80  SET version = "'. $version .'"
81  WHERE id = "'. $this->plugin_id .'"
82;';
83        pwg_query($query);
84       
85        $pwg_loaded_plugins[$this->plugin_id]['version'] = $version;
86      }
87    }
88  }
89}
90
91/**
92 * class ThemeMaintain
93 * used to declare maintenance methods of a theme
94 */
95abstract class ThemeMaintain 
96{
97  protected $theme_id;
98 
99  function __construct($id)
100  {
101    $this->theme_id = $id;
102  }
103 
104  abstract function activate($theme_version, &$errors=array());
105  abstract function deactivate();
106  abstract function delete();
107 
108  /*
109   * test if a theme needs to be updated and call a update function
110   * @param: string $version, version exposed by the theme
111   * @param: string $on_update, name of a method to call when an update is needed
112   *          it receives the previous version as first parameter
113   */
114  function autoUpdate($version, $on_update=null)
115  {
116    $query = '
117SELECT version
118  FROM '. THEMES_TABLE .'
119  WHERE id = "'. $this->theme_id .'"
120;';
121    list($current_version) = pwg_db_fetch_row(pwg_query($query));
122   
123    if ( $version == 'auto' or $current_version == 'auto'
124        or version_compare($current_version, $version, '<')
125      )
126    {
127      if (!empty($on_update))
128      {
129        call_user_func(array(&$this, $on_update), $current_version);
130      }
131     
132      if ($version != 'auto')
133      {
134        $query = '
135UPDATE '. THEMES_TABLE .'
136  SET version = "'. $version .'"
137  WHERE id = "'. $this->theme_id .'"
138;';
139        pwg_query($query);
140      }
141    }
142  }
143}
144
145
146/* Register a event handler.
147 * @param string $event the name of the event to listen to
148 * @param mixed $func the function that will handle the event
149 * @param int $priority optional priority (greater priority will
150 * be executed at last)
151*/
152function add_event_handler($event, $func,
153    $priority=EVENT_HANDLER_PRIORITY_NEUTRAL, $accepted_args=1)
154{
155  global $pwg_event_handlers;
156
157  if ( isset($pwg_event_handlers[$event][$priority]) )
158  {
159    foreach($pwg_event_handlers[$event][$priority] as $handler)
160    {
161      if ( $handler['function'] == $func )
162      {
163        return false;
164      }
165    }
166  }
167
168  $pwg_event_handlers[$event][$priority][] =
169    array(
170      'function'=>$func,
171      'accepted_args'=>$accepted_args);
172  ksort( $pwg_event_handlers[$event] );
173  return true;
174}
175
176/* Register a event handler.
177 * @param string $event the name of the event to listen to
178 * @param mixed $func the function that needs removal
179 * @param int $priority optional priority (greater priority will
180 * be executed at last)
181*/
182function remove_event_handler($event, $func,
183   $priority=EVENT_HANDLER_PRIORITY_NEUTRAL)
184{
185  global $pwg_event_handlers;
186
187  if (!isset( $pwg_event_handlers[$event][$priority] ) )
188  {
189    return false;
190  }
191  for ($i=0; $i<count($pwg_event_handlers[$event][$priority]); $i++)
192  {
193    if ($pwg_event_handlers[$event][$priority][$i]['function']==$func)
194    {
195      unset($pwg_event_handlers[$event][$priority][$i]);
196      $pwg_event_handlers[$event][$priority] =
197        array_values($pwg_event_handlers[$event][$priority]);
198
199      if ( empty($pwg_event_handlers[$event][$priority]) )
200      {
201        unset( $pwg_event_handlers[$event][$priority] );
202        if (empty( $pwg_event_handlers[$event] ) )
203        {
204          unset( $pwg_event_handlers[$event] );
205        }
206      }
207      return true;
208    }
209  }
210  return false;
211}
212
213/* Triggers an event and calls all registered event handlers
214 * @param string $event name of the event
215 * @param mixed $data data to pass to handlers
216*/
217function trigger_event($event, $data=null)
218{
219  global $pwg_event_handlers;
220
221  if ( isset($pwg_event_handlers['trigger']) )
222  {// just for debugging
223    trigger_action('trigger',
224        array('type'=>'event', 'event'=>$event, 'data'=>$data) );
225  }
226
227  if ( !isset($pwg_event_handlers[$event]) )
228  {
229    return $data;
230  }
231  $args = func_get_args();
232
233  foreach ($pwg_event_handlers[$event] as $priority => $handlers)
234  {
235    foreach($handlers as $handler)
236    {
237      $function_name = $handler['function'];
238      $accepted_args = $handler['accepted_args'];
239      $args[1] = $data;
240      $data = call_user_func_array($function_name, array_slice($args,1,$accepted_args) );
241    }
242  }
243  trigger_action('trigger',
244       array('type'=>'post_event', 'event'=>$event, 'data'=>$data) );
245  return $data;
246}
247
248function trigger_action($event, $data=null)
249{
250  global $pwg_event_handlers;
251  if ( isset($pwg_event_handlers['trigger']) and $event!='trigger' )
252  {// special case for debugging - avoid recursive calls
253    trigger_action('trigger',
254        array('type'=>'action', 'event'=>$event, 'data'=>$data) );
255  }
256
257  if ( !isset($pwg_event_handlers[$event]) )
258  {
259    return;
260  }
261  $args = func_get_args();
262
263  foreach ($pwg_event_handlers[$event] as $priority => $handlers)
264  {
265    foreach($handlers as $handler)
266    {
267      $function_name = $handler['function'];
268      $accepted_args = $handler['accepted_args'];
269
270      call_user_func_array($function_name, array_slice($args,1,$accepted_args) );
271    }
272  }
273}
274
275/** Saves some data with the associated plugim id. It can be retrieved later (
276 * during this script lifetime) using get_plugin_data
277 * @param string plugin_id
278 * @param mixed data
279 * returns true on success, false otherwise
280 */
281function set_plugin_data($plugin_id, &$data)
282{
283  global $pwg_loaded_plugins;
284  if ( isset($pwg_loaded_plugins[$plugin_id]) )
285  {
286    $pwg_loaded_plugins[$plugin_id]['plugin_data'] = &$data;
287    return true;
288  }
289  return false;
290}
291
292/** Retrieves plugin data saved previously with set_plugin_data
293 * @param string plugin_id
294 */
295function &get_plugin_data($plugin_id)
296{
297  global $pwg_loaded_plugins;
298  if ( isset($pwg_loaded_plugins[$plugin_id]) )
299  {
300    return $pwg_loaded_plugins[$plugin_id]['plugin_data'];
301  }
302  return null;
303}
304
305/* Returns an array of plugins defined in the database
306 * @param string $state optional filter on this state
307 * @param string $id optional returns only data about given plugin
308*/
309function get_db_plugins($state='', $id='')
310{
311  $query = '
312SELECT * FROM '.PLUGINS_TABLE;
313  $clauses = array();
314  if (!empty($state))
315  {
316    $clauses[] = 'state=\''.$state.'\'';
317  }
318  if (!empty($id))
319  {
320    $clauses[] = 'id="'.$id.'"';
321  }
322  if (count($clauses))
323  {
324      $query .= '
325  WHERE '. implode(' AND ', $clauses);
326  }
327
328  $result = pwg_query($query);
329  $plugins = array();
330  while ($row = pwg_db_fetch_assoc($result))
331  {
332    $plugins[] = $row;
333  }
334  return $plugins;
335}
336
337
338function load_plugin($plugin)
339{
340  $file_name = PHPWG_PLUGINS_PATH.$plugin['id'].'/main.inc.php';
341  if ( file_exists($file_name) )
342  {
343    global $pwg_loaded_plugins;
344    $pwg_loaded_plugins[ $plugin['id'] ] = $plugin;
345    include_once( $file_name );
346  }
347}
348
349/*loads all the plugins on startup*/
350function load_plugins()
351{
352  global $conf, $pwg_loaded_plugins;
353  $pwg_loaded_plugins = array();
354  if ($conf['enable_plugins'])
355  {
356    $plugins = get_db_plugins('active');
357    foreach( $plugins as $plugin)
358    {// include main from a function to avoid using same function context
359      load_plugin($plugin);
360    }
361    trigger_action('plugins_loaded');
362  }
363}
364
365?>
Note: See TracBrowser for help on using the repository browser.