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

Last change on this file since 27335 was 27335, checked in by rvelices, 10 years ago

small optim on events trigger when several handlers are registered (no more array_slice inside the loop)

  • Property svn:eol-style set to LF
File size: 11.3 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2014 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/**
25 * @package functions\plugins
26 */
27
28
29/** base directory of plugins */
30define('PHPWG_PLUGINS_PATH', PHPWG_ROOT_PATH.'plugins/');
31/** default priority for plugins handlers */
32define('EVENT_HANDLER_PRIORITY_NEUTRAL', 50);
33
34
35/**
36 * Used to declare maintenance methods of a plugin.
37 */
38class PluginMaintain 
39{
40  /** @var string $plugin_id */
41  protected $plugin_id;
42
43  /**
44   * @param string $id
45   */
46  function __construct($id)
47  {
48    $this->plugin_id = $id;
49  }
50
51  /**
52   * @param string $plugin_version
53   * @param array &$errors - used to return error messages
54   */
55  function install($plugin_version, &$errors=array()) {}
56
57  /**
58   * @param string $plugin_version
59   * @param array &$errors - used to return error messages
60   */
61  function activate($plugin_version, &$errors=array()) {}
62
63  function deactivate() {}
64
65  function uninstall() {}
66
67  /**
68   * Tests if the plugin needs to be updated and call an update function
69   *
70   * @param string $version version exposed by the plugin (potentially new)
71   * @param string $on_update name of a method to call when an update is needed
72   *          it receives the previous version as first parameter
73   */
74  function autoUpdate($version, $on_update=null)
75  {
76    global $pwg_loaded_plugins;
77   
78    $current_version = $pwg_loaded_plugins[$this->plugin_id]['version'];
79   
80    if ( $version == 'auto' or $current_version == 'auto'
81        or safe_version_compare($current_version, $version, '<')
82      )
83    {
84      if (!empty($on_update))
85      {
86        call_user_func(array(&$this, $on_update), $current_version);
87      }
88     
89      if ($version != 'auto')
90      {
91        $query = '
92UPDATE '. PLUGINS_TABLE .'
93  SET version = "'. $version .'"
94  WHERE id = "'. $this->plugin_id .'"
95;';
96        pwg_query($query);
97       
98        $pwg_loaded_plugins[$this->plugin_id]['version'] = $version;
99      }
100    }
101  }
102}
103
104/**
105 * Used to declare maintenance methods of a theme.
106 */
107class ThemeMaintain 
108{
109  /** @var string $theme_id */
110  protected $theme_id;
111
112  /**
113   * @param string $id
114   */
115  function __construct($id)
116  {
117    $this->theme_id = $id;
118  }
119
120  /**
121   * @param string $theme_version
122   * @param array &$errors - used to return error messages
123   */
124  function activate($theme_version, &$errors=array()) {}
125
126  function deactivate() {}
127
128  function delete() {}
129 
130  /**
131   * Tests if the theme needs to be updated and call an update function
132   *
133   * @param string $version version exposed by the theme (potentially new)
134   * @param string $on_update name of a method to call when an update is needed
135   *          it receives the previous version as first parameter
136   */
137  function autoUpdate($version, $on_update=null)
138  {
139    $query = '
140SELECT version
141  FROM '. THEMES_TABLE .'
142  WHERE id = "'. $this->theme_id .'"
143;';
144    list($current_version) = pwg_db_fetch_row(pwg_query($query));
145   
146    if ( $version == 'auto' or $current_version == 'auto'
147        or safe_version_compare($current_version, $version, '<')
148      )
149    {
150      if (!empty($on_update))
151      {
152        call_user_func(array(&$this, $on_update), $current_version);
153      }
154     
155      if ($version != 'auto')
156      {
157        $query = '
158UPDATE '. THEMES_TABLE .'
159  SET version = "'. $version .'"
160  WHERE id = "'. $this->theme_id .'"
161;';
162        pwg_query($query);
163      }
164    }
165  }
166}
167
168
169/**
170 * Register an event handler.
171 *
172 * @param string $event the name of the event to listen to
173 * @param Callable $func the callback function
174 * @param int $priority greater priority will be executed at last
175 * @param string $include_path file to include before executing the callback
176 * @return bool false is handler already exists
177 */
178function add_event_handler($event, $func,
179    $priority=EVENT_HANDLER_PRIORITY_NEUTRAL, $include_path=null)
180{
181  global $pwg_event_handlers;
182
183  if (isset($pwg_event_handlers[$event][$priority]))
184  {
185    foreach ($pwg_event_handlers[$event][$priority] as $handler)
186    {
187      if ($handler['function'] == $func)
188      {
189        return false;
190      }
191    }
192  }
193
194  $pwg_event_handlers[$event][$priority][] = array(
195    'function' => $func,
196    'include_path' => is_string($include_path) ? $include_path : null,
197    );
198
199  ksort($pwg_event_handlers[$event]);
200  return true;
201}
202
203/**
204 * Removes an event handler.
205 * @see add_event_handler()
206 *
207 * @param string $event
208 * @param Callable $func
209 * @param int $priority
210 */
211function remove_event_handler($event, $func,
212   $priority=EVENT_HANDLER_PRIORITY_NEUTRAL)
213{
214  global $pwg_event_handlers;
215
216  if (!isset($pwg_event_handlers[$event][$priority]))
217  {
218    return false;
219  }
220  for ($i=0; $i<count($pwg_event_handlers[$event][$priority]); $i++)
221  {
222    if ($pwg_event_handlers[$event][$priority][$i]['function']==$func)
223    {
224      unset($pwg_event_handlers[$event][$priority][$i]);
225      $pwg_event_handlers[$event][$priority] =
226        array_values($pwg_event_handlers[$event][$priority]);
227
228      if (empty($pwg_event_handlers[$event][$priority]))
229      {
230        unset($pwg_event_handlers[$event][$priority]);
231        if (empty($pwg_event_handlers[$event]))
232        {
233          unset($pwg_event_handlers[$event]);
234        }
235      }
236      return true;
237    }
238  }
239  return false;
240}
241
242/**
243 * Triggers a modifier event and calls all registered event handlers.
244 * trigger_change() is used as a modifier: it allows to transmit _$data_
245 * through all handlers, thus each handler MUST return a value,
246 * optional _$args_ are not transmitted.
247 *
248 * @since 2.6
249 * @todo remove trigger_event()
250 *
251 * @param string $event
252 * @param mixed $data data to transmit to all handlers
253 * @param mixed $args,... optional arguments
254 * @return mixed $data
255 */
256function trigger_change($event, $data=null)
257{
258  $args = func_get_args();
259  return call_user_func_array('trigger_event', $args);
260}
261
262/**
263 * @deprecated 2.6
264 * @see trigger_change
265 */
266function trigger_event($event, $data=null)
267{
268  global $pwg_event_handlers;
269
270  if (isset($pwg_event_handlers['trigger']))
271  {// debugging
272    trigger_action('trigger',
273      array('type'=>'event', 'event'=>$event, 'data'=>$data)
274      );
275  }
276
277  if (!isset($pwg_event_handlers[$event]))
278  {
279    return $data;
280  }
281  $args = func_get_args();
282  array_shift($args);
283
284  foreach ($pwg_event_handlers[$event] as $priority => $handlers)
285  {
286    foreach ($handlers as $handler)
287    {
288      $args[0] = $data;
289
290      if (!empty($handler['include_path']))
291      {
292        include_once($handler['include_path']);
293      }
294
295      $data = call_user_func_array($handler['function'], $args);
296    }
297  }
298
299  if (isset($pwg_event_handlers['trigger']))
300  {// debugging
301    trigger_action('trigger',
302      array('type'=>'post_event', 'event'=>$event, 'data'=>$data)
303      );
304  }
305
306  return $data;
307}
308
309/**
310 * Triggers a notifier event and calls all registered event handlers.
311 * trigger_notify() is only used as a notifier, no modification of data is possible
312 *
313 * @since 2.6
314 * @todo remove trigger_action()
315 *
316 * @param string $event
317 * @param mixed $args,... optional arguments
318 */
319function trigger_notify($event)
320{
321  $args = func_get_args();
322  return call_user_func_array('trigger_action', $args);
323}
324
325/**
326 * @deprecated 2.6
327 * @see trigger_notify
328 */
329function trigger_action($event)
330{
331  global $pwg_event_handlers;
332
333  if (isset($pwg_event_handlers['trigger']) and $event!='trigger')
334  {// debugging - avoid recursive calls
335    trigger_action('trigger',
336      array('type'=>'action', 'event'=>$event, 'data'=>null)
337      );
338  }
339
340  if (!isset($pwg_event_handlers[$event]))
341  {
342    return;
343  }
344  $args = func_get_args();
345  array_shift($args);
346
347  foreach ($pwg_event_handlers[$event] as $priority => $handlers)
348  {
349    foreach ($handlers as $handler)
350    {
351      if (!empty($handler['include_path']))
352      {
353        include_once($handler['include_path']);
354      }
355
356      call_user_func_array($handler['function'], $args);
357    }
358  }
359}
360
361/**
362 * Saves some data with the associated plugin id, data are only available
363 * during script lifetime.
364 * @depracted 2.6
365 *
366 * @param string $plugin_id
367 * @param mixed &$data
368 * @return bool
369 */
370function set_plugin_data($plugin_id, &$data)
371{
372  global $pwg_loaded_plugins;
373  if ( isset($pwg_loaded_plugins[$plugin_id]) )
374  {
375    $pwg_loaded_plugins[$plugin_id]['plugin_data'] = &$data;
376    return true;
377  }
378  return false;
379}
380
381/**
382 * Retrieves plugin data saved previously with set_plugin_data.
383 * @see set_plugin_data()
384 * @depracted 2.6
385 *
386 * @param string $plugin_id
387 * @return mixed
388 */
389function &get_plugin_data($plugin_id)
390{
391  global $pwg_loaded_plugins;
392  if ( isset($pwg_loaded_plugins[$plugin_id]['plugin_data']) )
393  {
394    return $pwg_loaded_plugins[$plugin_id]['plugin_data'];
395  }
396  return null;
397}
398
399/**
400 * Returns an array of plugins defined in the database.
401 *
402 * @param string $state optional filter
403 * @param string $id returns only data about given plugin
404 * @return array
405 */
406function get_db_plugins($state='', $id='')
407{
408  $query = '
409SELECT * FROM '.PLUGINS_TABLE;
410  $clauses = array();
411  if (!empty($state))
412  {
413    $clauses[] = 'state=\''.$state.'\'';
414  }
415  if (!empty($id))
416  {
417    $clauses[] = 'id="'.$id.'"';
418  }
419  if (count($clauses))
420  {
421    $query .= '
422  WHERE '. implode(' AND ', $clauses);
423  }
424 
425  return query2array($query);
426}
427
428/**
429 * Loads a plugin, it includes the main.inc.php file and updates _$pwg_loaded_plugins_.
430 *
431 * @param string $plugin
432 */
433function load_plugin($plugin)
434{
435  $file_name = PHPWG_PLUGINS_PATH.$plugin['id'].'/main.inc.php';
436  if ( file_exists($file_name) )
437  {
438    global $pwg_loaded_plugins;
439    $pwg_loaded_plugins[ $plugin['id'] ] = $plugin;
440    include_once( $file_name );
441  }
442}
443
444/**
445 * Loads all the registered plugins.
446 */
447function load_plugins()
448{
449  global $conf, $pwg_loaded_plugins;
450  $pwg_loaded_plugins = array();
451  if ($conf['enable_plugins'])
452  {
453    $plugins = get_db_plugins('active');
454    foreach( $plugins as $plugin)
455    {// include main from a function to avoid using same function context
456      load_plugin($plugin);
457    }
458    trigger_action('plugins_loaded');
459  }
460}
461
462?>
Note: See TracBrowser for help on using the repository browser.