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