xref: /dokuwiki/inc/pluginutils.php (revision e5e61eb0b5e7f947cb80e305215246ff894cbcd9)
1<?php
2/**
3 * Utilities for handling plugins
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Andreas Gohr <andi@splitbrain.org>
7 */
8
9// plugin related constants
10if(!defined('DOKU_PLUGIN'))  define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
11
12$plugin_types = array('admin','syntax','action','renderer', 'helper');
13
14global $plugin_controller_class, $plugin_controller;
15if (empty($plugin_controller_class)) $plugin_controller_class = 'Doku_Plugin_Controller';
16
17$plugin_controller = new $plugin_controller_class();
18
19/**
20 * Original plugin functions, remain for backwards compatibility
21 */
22function plugin_list($type='',$all=false) { global $plugin_controller; return $plugin_controller->getList($type,$all); }
23function &plugin_load($type,$name,$new=false) { global $plugin_controller; return $plugin_controller->load($type,$name,$new); }
24function plugin_isdisabled($plugin) { global $plugin_controller; return $plugin_controller->isdisabled($plugin); }
25function plugin_enable($plugin) { global $plugin_controller; return $plugin_controller->enable($plugin); }
26function plugin_disable($plugin) { global $plugin_controller; return $plugin_controller->disable($plugin); }
27function plugin_directory($plugin) { global $plugin_controller; return $plugin_controller->get_directory($plugin); }
28
29class Doku_Plugin_Controller {
30
31  var $list_enabled = array();
32  var $list_disabled = array();
33  var $list_bytype = array();
34
35  function Doku_Plugin_Controller() {
36    $this->_populateMasterList();
37  }
38
39  /**
40   * Returns a list of available plugins of given type
41   *
42   * @param $type  string, plugin_type name;
43   *               the type of plugin to return,
44   *               use empty string for all types
45   * @param $all   bool;
46   *               false to only return enabled plugins,
47   *               true to return both enabled and disabled plugins
48   *
49   * @return       array of plugin names
50   *
51   * @author Andreas Gohr <andi@splitbrain.org>
52   */
53  function getList($type='',$all=false){
54
55    // request the complete list
56    if (!$type) {
57      return $all ? array_merge($this->list_enabled,$this->list_disabled) : $this->list_enabled;
58    }
59
60    if (!isset($this->list_bytype[$type]['enabled'])) {
61      $this->list_bytype[$type]['enabled'] = $this->_getListByType($type,true);
62    }
63    if ($all && !isset($this->list_bytype[$type]['disabled'])) {
64      $this->list_bytype[$type]['disabled'] = $this->_getListByType($type,false);
65    }
66
67    return $all ? array_merge($this->list_bytype[$type]['enabled'],$this->list_bytype[$type]['disabled']) : $this->list_bytype[$type]['enabled'];
68  }
69
70  /**
71   * Loads the given plugin and creates an object of it
72   *
73   * @author Andreas Gohr <andi@splitbrain.org>
74   *
75   * @param  $type string     type of plugin to load
76   * @param  $name string     name of the plugin to load
77   * @param  $new  bool       true to return a new instance of the plugin, false to use an already loaded instance
78   * @return objectreference  the plugin object or null on failure
79   */
80  function &load($type,$name,$new=false){
81    //we keep all loaded plugins available in global scope for reuse
82    global $DOKU_PLUGINS;
83
84    //plugin already loaded?
85    if(!empty($DOKU_PLUGINS[$type][$name])){
86      if ($new) {
87        $class = $type.'_plugin_'.$name;
88        return class_exists($class) ? new $class : null;
89      } else {
90        return $DOKU_PLUGINS[$type][$name];
91      }
92    }
93
94    //try to load the wanted plugin file
95    list($plugin,$component) = $this->_splitName($name);
96    $dir = !$this->isdisabled($plugin) ? $plugin : $plugin.'.disabled';
97    $file = $component ? "$type/$component.php" : "$type.php";
98
99    if (!include_once(DOKU_PLUGIN."$dir/$file")) {
100      return null;
101    }
102
103    //construct class and instantiate
104    $class = $type.'_plugin_'.$name;
105    if (!class_exists($class)) return null;
106
107    $DOKU_PLUGINS[$type][$name] = new $class;
108    return $DOKU_PLUGINS[$type][$name];
109  }
110
111  function isdisabled($plugin) {
112    return (array_search($plugin, $this->list_enabled) === false);
113  }
114
115  function enable($plugin) {
116    if (array_search($plugin, $this->list_disabled) !== false) {
117      return @rename(DOKU_PLUGIN.$plugin.'.disabled',DOKU_PLUGIN.$plugin);
118    }
119    return false;
120  }
121
122  function disable($plugin) {
123   if (array_search($plugin, $this->list_enabled) !== false) {
124      return @rename(DOKU_PLUGIN.$plugin,DOKU_PLUGIN.$plugin.'.disabled');
125    }
126    return false;
127  }
128
129  function get_directory($plugin) {
130    return $this->isdisabled($plugin) ? $plugin.'.disabled' : $plugin;
131  }
132
133  function _populateMasterList() {
134    if ($dh = opendir(DOKU_PLUGIN)) {
135      while (false !== ($plugin = readdir($dh))) {
136        if ($plugin == '.' || $plugin == '..' || $plugin == 'tmp') continue;
137        if (is_file(DOKU_PLUGIN.$plugin)) continue;
138
139        if (substr($plugin,-9) == '.disabled') {
140          $this->list_disabled[] = substr($plugin,0,-9);
141        } else {
142          $this->list_enabled[] = $plugin;
143        }
144      }
145    }
146  }
147
148  function _getListByType($type, $enabled) {
149    $master_list = $enabled ? $this->list_enabled : $this->list_disabled;
150
151    $plugins = array();
152    foreach ($master_list as $plugin) {
153      $dir = $enabled ? $plugin : $plugin.'.disabled';
154
155      if (@file_exists(DOKU_PLUGIN."$dir/$type.php")){
156        $plugins[] = $plugin;
157      } else {
158        if ($dp = @opendir(DOKU_PLUGIN."$dir/$type/")) {
159          while (false !== ($component = readdir($dp))) {
160            if (substr($component,0,1) == '.' || strtolower(substr($component, -4)) != ".php") continue;
161            if (is_file(DOKU_PLUGIN."$dir/$type/$component")) {
162                $plugins[] = $plugin.'_'.substr($component, 0, -4);
163            }
164          }
165        closedir($dp);
166        }
167      }
168    }
169
170    return $plugins;
171  }
172
173  function _splitName($name) {
174    if (array_search($name, $this->list_enabled + $this->list_disabled) === false) {
175      return explode('_',$name,2);
176    }
177
178    return array($name,'');
179  }
180
181}
182