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