1bc461538SMichael Große<?php 2bc461538SMichael Große/** 3bc461538SMichael Große * DokuWiki Plugin farmer (Helper Component) 4bc461538SMichael Große * 5bc461538SMichael Große * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6bc461538SMichael Große * @author Michael Große <grosse@cosmocode.de> 70a5d2da2SAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 8bc461538SMichael Große */ 9bc461538SMichael Große 10bc461538SMichael Große// must be run within Dokuwiki 11bc461538SMichael Großeif(!defined('DOKU_INC')) die(); 12bc461538SMichael Große 13bc461538SMichael Großeclass helper_plugin_farmer extends DokuWiki_Plugin { 14bc461538SMichael Große 15af1c6dd8SAndreas Gohr protected $defaultPluginState = null; 16af1c6dd8SAndreas Gohr protected $animalPluginState = array(); 17fcbe16a4SMichael Große 18bc461538SMichael Große /** 19632c5618SAndreas Gohr * Returns the name of the current animal if any, false otherwise 20632c5618SAndreas Gohr * 21632c5618SAndreas Gohr * @return string|false 22632c5618SAndreas Gohr */ 23632c5618SAndreas Gohr public function getAnimal() { 24b96c66ccSAndreas Gohr if(!isset($GLOBALS['FARMCORE'])) return false; 25b96c66ccSAndreas Gohr return $GLOBALS['FARMCORE']->getAnimal(); 26632c5618SAndreas Gohr } 27632c5618SAndreas Gohr 28632c5618SAndreas Gohr /** 29b96c66ccSAndreas Gohr * Get the farm config 30b96c66ccSAndreas Gohr * 31b96c66ccSAndreas Gohr * @return array 32b96c66ccSAndreas Gohr */ 33b96c66ccSAndreas Gohr public function getConfig() { 34b96c66ccSAndreas Gohr if(!isset($GLOBALS['FARMCORE'])) return array(); 35b96c66ccSAndreas Gohr return $GLOBALS['FARMCORE']->getConfig(); 36b96c66ccSAndreas Gohr } 37b96c66ccSAndreas Gohr 38b96c66ccSAndreas Gohr /** 39b96c66ccSAndreas Gohr * Was the current animal requested by host? 40b96c66ccSAndreas Gohr * 41b96c66ccSAndreas Gohr * @return bool 42b96c66ccSAndreas Gohr */ 43b96c66ccSAndreas Gohr public function isHostbased() { 44b96c66ccSAndreas Gohr if(!isset($GLOBALS['FARMCORE'])) return false; 45b96c66ccSAndreas Gohr return $GLOBALS['FARMCORE']->isHostbased(); 46b96c66ccSAndreas Gohr } 47b96c66ccSAndreas Gohr 48b96c66ccSAndreas Gohr /** 49b96c66ccSAndreas Gohr * Was an animal requested that could not be found? 50b96c66ccSAndreas Gohr * 51b96c66ccSAndreas Gohr * @return bool 52b96c66ccSAndreas Gohr */ 53b96c66ccSAndreas Gohr public function wasNotfound() { 54b96c66ccSAndreas Gohr if(!isset($GLOBALS['FARMCORE'])) return false; 55b96c66ccSAndreas Gohr return $GLOBALS['FARMCORE']->wasNotfound(); 56b96c66ccSAndreas Gohr } 57b96c66ccSAndreas Gohr 58b96c66ccSAndreas Gohr /** 59c4c8e953SAndreas Gohr * Guess the URL for an animal 60c4c8e953SAndreas Gohr * 61c4c8e953SAndreas Gohr * @param $animal 62c4c8e953SAndreas Gohr * @return string 63c4c8e953SAndreas Gohr */ 64c4c8e953SAndreas Gohr public function getAnimalURL($animal) { 65c4c8e953SAndreas Gohr $config = $this->getConfig(); 66c4c8e953SAndreas Gohr 67c4c8e953SAndreas Gohr if(strpos($animal, '.') !== false) { 68c4c8e953SAndreas Gohr return 'http://' . $animal; 69c4c8e953SAndreas Gohr } elseif($config['base']['basedomain']) { 70c4c8e953SAndreas Gohr return 'http://' . $animal . '.' . $config['base']['basedomain']; 71c4c8e953SAndreas Gohr } else { 720336ab2aSAndreas Gohr return DOKU_URL . '!' . $animal . '/'; 73c4c8e953SAndreas Gohr } 74c4c8e953SAndreas Gohr } 75c4c8e953SAndreas Gohr 76c4c8e953SAndreas Gohr /** 77b96c66ccSAndreas Gohr * List of all animals, i.e. directories within DOKU_FARMDIR without the template. 78b96c66ccSAndreas Gohr * 79b96c66ccSAndreas Gohr * @return array 80b96c66ccSAndreas Gohr */ 81b96c66ccSAndreas Gohr public function getAllAnimals() { 82b96c66ccSAndreas Gohr $animals = array(); 838262a4cbSAndreas Gohr $list = glob(DOKU_FARMDIR . '*/conf/', GLOB_ONLYDIR); 84b96c66ccSAndreas Gohr foreach($list as $path) { 85b96c66ccSAndreas Gohr $animal = basename(dirname($path)); 86b96c66ccSAndreas Gohr if($animal == '_animal') continue; // old template 87b96c66ccSAndreas Gohr $animals[] = $animal; 88b96c66ccSAndreas Gohr } 89b96c66ccSAndreas Gohr sort($animals); 90b96c66ccSAndreas Gohr return $animals; 91b96c66ccSAndreas Gohr } 92b96c66ccSAndreas Gohr 93b96c66ccSAndreas Gohr /** 94b96c66ccSAndreas Gohr * checks wether $path is in under $container 95b96c66ccSAndreas Gohr * 96dfdaf33eSAndreas Gohr * Also returns false if $path and $container are the same directory 97dfdaf33eSAndreas Gohr * 98b96c66ccSAndreas Gohr * @param string $path 99b96c66ccSAndreas Gohr * @param string $container 100b96c66ccSAndreas Gohr * @return bool 101b96c66ccSAndreas Gohr */ 102b96c66ccSAndreas Gohr public function isInPath($path, $container) { 103*0f0a264cSAndreas Gohr $path = fullpath($path).'/'; 104*0f0a264cSAndreas Gohr $container = fullpath($container).'/'; 105dfdaf33eSAndreas Gohr if($path == $container) return false; 106dfdaf33eSAndreas Gohr return (strpos($path, $container) === 0); 107b96c66ccSAndreas Gohr } 108b96c66ccSAndreas Gohr 109b96c66ccSAndreas Gohr /** 110b96c66ccSAndreas Gohr * Check if the farm is correctly configured for this farmer plugin 111b96c66ccSAndreas Gohr * 112b96c66ccSAndreas Gohr * @return bool 113b96c66ccSAndreas Gohr */ 114b96c66ccSAndreas Gohr public function checkFarmSetup() { 115b96c66ccSAndreas Gohr return defined('DOKU_FARMDIR') && isset($GLOBALS['FARMCORE']); 116b96c66ccSAndreas Gohr } 117b96c66ccSAndreas Gohr 11849f2871cSAndreas Gohr /** 11949f2871cSAndreas Gohr * @param string $animalname 12049f2871cSAndreas Gohr * 12149f2871cSAndreas Gohr * @return bool 12249f2871cSAndreas Gohr */ 12349f2871cSAndreas Gohr public function validateAnimalName($animalname) { 12478c63d53SAndreas Gohr return preg_match("/^[a-z0-9]+([\\.\\-][a-z0-9]+)*$/i", $animalname) === 1; 12549f2871cSAndreas Gohr } 126b96c66ccSAndreas Gohr 127b96c66ccSAndreas Gohr /** 128bc461538SMichael Große * Copy a file, or recursively copy a folder and its contents. Adapted for DokuWiki. 129bc461538SMichael Große * 130bc461538SMichael Große * @todo: needs tests 131bc461538SMichael Große * 132bc461538SMichael Große * @author Aidan Lister <aidan@php.net> 133bc461538SMichael Große * @author Michael Große <grosse@cosmocode.de> 134801ebaa1SAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 135bc461538SMichael Große * @link http://aidanlister.com/2004/04/recursively-copying-directories-in-php/ 136bc461538SMichael Große * 137bc461538SMichael Große * @param string $source Source path 138bc461538SMichael Große * @param string $destination Destination path 139801ebaa1SAndreas Gohr * @param string $exclude Regular expression to exclude files or directories (complete with delimiters) 140bc461538SMichael Große * @return bool Returns TRUE on success, FALSE on failure 141bc461538SMichael Große */ 142801ebaa1SAndreas Gohr function io_copyDir($source, $destination, $exclude = '') { 143801ebaa1SAndreas Gohr if($exclude && preg_match($exclude, $source)) { 144801ebaa1SAndreas Gohr return true; 145801ebaa1SAndreas Gohr } 146801ebaa1SAndreas Gohr 147bc461538SMichael Große if(is_link($source)) { 148bc461538SMichael Große io_lock($destination); 149bc461538SMichael Große $result = symlink(readlink($source), $destination); 150bc461538SMichael Große io_unlock($destination); 151bc461538SMichael Große return $result; 152bc461538SMichael Große } 153bc461538SMichael Große 154bc461538SMichael Große if(is_file($source)) { 155bc461538SMichael Große io_lock($destination); 156bc461538SMichael Große $result = copy($source, $destination); 157bc461538SMichael Große io_unlock($destination); 158bc461538SMichael Große return $result; 159bc461538SMichael Große } 160bc461538SMichael Große 161bc461538SMichael Große if(!is_dir($destination)) { 162bc461538SMichael Große io_mkdir_p($destination); 163bc461538SMichael Große } 164bc461538SMichael Große 16549f2871cSAndreas Gohr $dir = @dir($source); 16649f2871cSAndreas Gohr if($dir === false) return false; 167bc461538SMichael Große while(false !== ($entry = $dir->read())) { 168bc461538SMichael Große if($entry == '.' || $entry == '..') { 169bc461538SMichael Große continue; 170bc461538SMichael Große } 171bc461538SMichael Große 172bc461538SMichael Große // recurse into directories 173801ebaa1SAndreas Gohr $this->io_copyDir("$source/$entry", "$destination/$entry", $exclude); 174bc461538SMichael Große } 175bc461538SMichael Große 176bc461538SMichael Große $dir->close(); 177bc461538SMichael Große return true; 178bc461538SMichael Große } 179bc461538SMichael Große 18016bbfe4bSMichael Große /** 18116bbfe4bSMichael Große * get a list of all Plugins installed in the farmer wiki, regardless whether they are active or not. 18216bbfe4bSMichael Große * 183af1c6dd8SAndreas Gohr * @param bool $all get all plugins, even disabled ones 18416bbfe4bSMichael Große * @return array 18516bbfe4bSMichael Große */ 186af1c6dd8SAndreas Gohr public function getAllPlugins($all = true) { 187af1c6dd8SAndreas Gohr 1883536d644SAndreas Gohr /** @var Doku_Plugin_Controller $plugin_controller */ 1893536d644SAndreas Gohr global $plugin_controller; 1903536d644SAndreas Gohr 191af1c6dd8SAndreas Gohr $plugins = $plugin_controller->getList('', $all); 1923536d644SAndreas Gohr 1933536d644SAndreas Gohr // filter out a few plugins 194af1c6dd8SAndreas Gohr $plugins = array_filter( 195af1c6dd8SAndreas Gohr $plugins, function ($item) { 1963536d644SAndreas Gohr if($item == 'farmer') return false; 1973536d644SAndreas Gohr if($item == 'extension') return false; 198f1336aa9SAndreas Gohr if($item == 'upgrade') return false; 1993536d644SAndreas Gohr if($item == 'testing') return false; 2003536d644SAndreas Gohr return true; 201af1c6dd8SAndreas Gohr } 202af1c6dd8SAndreas Gohr ); 2033536d644SAndreas Gohr 2046ec1ad8fSMichael Große sort($plugins); 2050b96e6d7SMichael Große return $plugins; 2060b96e6d7SMichael Große } 2070b96e6d7SMichael Große 20816bbfe4bSMichael Große /** 209af1c6dd8SAndreas Gohr * Get the plugin states configured locally in the given animal 21016bbfe4bSMichael Große * 211af1c6dd8SAndreas Gohr * Response is cached 212af1c6dd8SAndreas Gohr * 213af1c6dd8SAndreas Gohr * @param $animal 214af1c6dd8SAndreas Gohr * @return array 21516bbfe4bSMichael Große */ 216af1c6dd8SAndreas Gohr public function getAnimalPluginLocalStates($animal) { 217af1c6dd8SAndreas Gohr if(isset($this->animalPluginState[$animal])) return $this->animalPluginState[$animal]; 218af1c6dd8SAndreas Gohr 219af1c6dd8SAndreas Gohr $localfile = DOKU_FARMDIR . $animal . '/conf/plugins.local.php'; 220af1c6dd8SAndreas Gohr $plugins = array(); 221af1c6dd8SAndreas Gohr if(file_exists($localfile)) { 222af1c6dd8SAndreas Gohr include($localfile); 223fcbe16a4SMichael Große } 224af1c6dd8SAndreas Gohr 225af1c6dd8SAndreas Gohr $this->animalPluginState[$animal] = $plugins; 226af1c6dd8SAndreas Gohr return $plugins; 227fcbe16a4SMichael Große } 228fcbe16a4SMichael Große 229a0fc814bSMichael Große /** 230af1c6dd8SAndreas Gohr * Return the default state plugins would have in animals 231af1c6dd8SAndreas Gohr * 232af1c6dd8SAndreas Gohr * Response is cached 233af1c6dd8SAndreas Gohr * 234af1c6dd8SAndreas Gohr * @return array 235a0fc814bSMichael Große */ 236af1c6dd8SAndreas Gohr public function getDefaultPluginStates() { 237af1c6dd8SAndreas Gohr if(!is_null($this->defaultPluginState)) return $this->defaultPluginState; 238af1c6dd8SAndreas Gohr 239af1c6dd8SAndreas Gohr $farmconf = $this->getConfig(); 240af1c6dd8SAndreas Gohr $all = $this->getAllPlugins(); 241af1c6dd8SAndreas Gohr 242af1c6dd8SAndreas Gohr $plugins = array(); 243af1c6dd8SAndreas Gohr foreach($all as $one) { 244af1c6dd8SAndreas Gohr if($farmconf['inherit']['plugins']) { 245af1c6dd8SAndreas Gohr $plugins[$one] = !plugin_isdisabled($one); 246fcbe16a4SMichael Große } else { 247af1c6dd8SAndreas Gohr $plugins[$one] = true; // default state is enabled 248fcbe16a4SMichael Große } 249114a05a7SAndreas Gohr } 250af1c6dd8SAndreas Gohr 251511d09feSAndreas Gohr ksort($plugins); 252af1c6dd8SAndreas Gohr $this->defaultPluginState = $plugins; 253af1c6dd8SAndreas Gohr return $plugins; 254af1c6dd8SAndreas Gohr } 255af1c6dd8SAndreas Gohr 256af1c6dd8SAndreas Gohr /** 257af1c6dd8SAndreas Gohr * Return a structure giving detailed info about the state of all plugins in an animal 258af1c6dd8SAndreas Gohr * 259af1c6dd8SAndreas Gohr * @param $animal 260af1c6dd8SAndreas Gohr * @return array 261af1c6dd8SAndreas Gohr */ 262af1c6dd8SAndreas Gohr public function getAnimalPluginRealState($animal) { 263af1c6dd8SAndreas Gohr $info = array(); 264af1c6dd8SAndreas Gohr 265af1c6dd8SAndreas Gohr $defaults = $this->getDefaultPluginStates(); 266af1c6dd8SAndreas Gohr $local = $this->getAnimalPluginLocalStates($animal); 267af1c6dd8SAndreas Gohr 268af1c6dd8SAndreas Gohr foreach($defaults as $plugin => $set) { 269af1c6dd8SAndreas Gohr $current = array( 270af1c6dd8SAndreas Gohr 'name' => $plugin, 271af1c6dd8SAndreas Gohr 'default' => $set, 272af1c6dd8SAndreas Gohr 'actual' => $set, 273af1c6dd8SAndreas Gohr 'isdefault' => true 274af1c6dd8SAndreas Gohr ); 275af1c6dd8SAndreas Gohr 276af1c6dd8SAndreas Gohr if(isset($local[$plugin])) { 277af1c6dd8SAndreas Gohr $current['actual'] = (bool) $local[$plugin]; 278af1c6dd8SAndreas Gohr $current['isdefault'] = false; 279af1c6dd8SAndreas Gohr } 280af1c6dd8SAndreas Gohr 281511d09feSAndreas Gohr $info[$plugin] = $current; 282af1c6dd8SAndreas Gohr } 283af1c6dd8SAndreas Gohr 284511d09feSAndreas Gohr ksort($info); 285af1c6dd8SAndreas Gohr return $info; 286af1c6dd8SAndreas Gohr } 287af1c6dd8SAndreas Gohr 288af1c6dd8SAndreas Gohr /** 289af1c6dd8SAndreas Gohr * Set the state of a plugin in an animal 290af1c6dd8SAndreas Gohr * 291af1c6dd8SAndreas Gohr * @param string $plugin 292af1c6dd8SAndreas Gohr * @param string $animal 293af1c6dd8SAndreas Gohr * @param int $state -1 = default, 1 = enabled, 0 = disabled 294af1c6dd8SAndreas Gohr */ 295af1c6dd8SAndreas Gohr public function setPluginState($plugin, $animal, $state) { 296af1c6dd8SAndreas Gohr $state = (int) $state; 297af1c6dd8SAndreas Gohr 298af1c6dd8SAndreas Gohr $plugins = $this->getAnimalPluginLocalStates($animal); 299af1c6dd8SAndreas Gohr if($state < 0) { 300af1c6dd8SAndreas Gohr if(isset($plugins[$plugin])) unset($plugins[$plugin]); 301af1c6dd8SAndreas Gohr } else { 302af1c6dd8SAndreas Gohr $plugins[$plugin] = $state; 303af1c6dd8SAndreas Gohr } 304af1c6dd8SAndreas Gohr 305fcbe16a4SMichael Große $this->writePluginConf($plugins, $animal); 306511d09feSAndreas Gohr 307511d09feSAndreas Gohr // clear state cache 308511d09feSAndreas Gohr if(isset($this->animalPluginState[$animal])) unset($this->animalPluginState[$animal]); 309fcbe16a4SMichael Große } 310fcbe16a4SMichael Große 31116bbfe4bSMichael Große /** 31216bbfe4bSMichael Große * Write the list of (deactivated) plugins as plugin configuration of an animal to file 31316bbfe4bSMichael Große * 314af1c6dd8SAndreas Gohr * updates the plugin state cache 315af1c6dd8SAndreas Gohr * 31616bbfe4bSMichael Große * @param array $plugins associative array with the key being the plugin name and the value 0 or 1 31716bbfe4bSMichael Große * @param string $animal Directory of the animal within DOKU_FARMDIR 31816bbfe4bSMichael Große */ 319fcbe16a4SMichael Große public function writePluginConf($plugins, $animal) { 320af1c6dd8SAndreas Gohr $pluginConf = '<?php' . "\n# plugins enabled and disabled by the farmer plugin\n"; 321fcbe16a4SMichael Große foreach($plugins as $plugin => $status) { 322af1c6dd8SAndreas Gohr $pluginConf .= '$plugins[\'' . $plugin . '\'] = ' . $status . ";\n"; 323fcbe16a4SMichael Große } 324fcbe16a4SMichael Große io_saveFile(DOKU_FARMDIR . $animal . '/conf/plugins.local.php', $pluginConf); 325fcbe16a4SMichael Große touch(DOKU_FARMDIR . $animal . '/conf/local.php'); 326af1c6dd8SAndreas Gohr 327af1c6dd8SAndreas Gohr $this->animalPluginState[$animal] = $plugins; 328fcbe16a4SMichael Große } 329bc461538SMichael Große} 330