1da0ae2c0SAndreas Gohr<?php 2da0ae2c0SAndreas Gohr 3a646d519SAndreas Gohr/** 4a646d519SAndreas Gohr * Core Manager for the Farm functionality 5a646d519SAndreas Gohr * 6a646d519SAndreas Gohr * This class is initialized before any other DokuWiki code runs. Therefore it is 7a646d519SAndreas Gohr * completely selfcontained and does not use any of DokuWiki's utility functions. 8a646d519SAndreas Gohr * 9b96c66ccSAndreas Gohr * It's registered as a global $FARMCORE variable but you should not interact with 10b96c66ccSAndreas Gohr * it directly. Instead use the Farmer plugin's helper component. 110a5d2da2SAndreas Gohr * 120a5d2da2SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 130a5d2da2SAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 14a646d519SAndreas Gohr */ 15da0ae2c0SAndreas Gohrclass DokuWikiFarmCore { 16da0ae2c0SAndreas Gohr /** 17da0ae2c0SAndreas Gohr * @var array The default config - changed by loadConfig 18da0ae2c0SAndreas Gohr */ 19da0ae2c0SAndreas Gohr protected $config = array( 20a646d519SAndreas Gohr 'base' => array( 21a646d519SAndreas Gohr 'farmdir' => '', 22c4c8e953SAndreas Gohr 'farmhost' => '', 23c4c8e953SAndreas Gohr 'basedomain' => '', 24a646d519SAndreas Gohr ), 25da0ae2c0SAndreas Gohr 'notfound' => array( 26da0ae2c0SAndreas Gohr 'show' => 'farmer', 27da0ae2c0SAndreas Gohr 'url' => '' 28da0ae2c0SAndreas Gohr ), 29da0ae2c0SAndreas Gohr 'inherit' => array( 30da0ae2c0SAndreas Gohr 'main' => 1, 31da0ae2c0SAndreas Gohr 'acronyms' => 1, 32da0ae2c0SAndreas Gohr 'entities' => 1, 33da0ae2c0SAndreas Gohr 'interwiki' => 1, 34da0ae2c0SAndreas Gohr 'license' => 1, 35da0ae2c0SAndreas Gohr 'mime' => 1, 36da0ae2c0SAndreas Gohr 'scheme' => 1, 37da0ae2c0SAndreas Gohr 'smileys' => 1, 38da0ae2c0SAndreas Gohr 'wordblock' => 1, 391272da0cSAndreas Gohr 'users' => 0, 40af1c6dd8SAndreas Gohr 'plugins' => 0, 41da0ae2c0SAndreas Gohr 'userstyle' => 0, 4205ea7625SAnna Dabrowska 'userscript' => 0, 433cee9885SAnna Dabrowska 'styleini' => 0 44da0ae2c0SAndreas Gohr ) 45da0ae2c0SAndreas Gohr ); 46da0ae2c0SAndreas Gohr 47a646d519SAndreas Gohr /** @var string|false The current animal, false for farmer */ 48a646d519SAndreas Gohr protected $animal = false; 49a646d519SAndreas Gohr /** @var bool true if an animal was requested but was not found */ 50a646d519SAndreas Gohr protected $notfound = false; 51a646d519SAndreas Gohr /** @var bool true if the current animal was requested by host */ 52a646d519SAndreas Gohr protected $hostbased = false; 53a646d519SAndreas Gohr 54da0ae2c0SAndreas Gohr /** 55da0ae2c0SAndreas Gohr * DokuWikiFarmCore constructor. 56da0ae2c0SAndreas Gohr * 57a646d519SAndreas Gohr * This initializes the whole farm by loading the configuration and setting 58a646d519SAndreas Gohr * DOKU_CONF depending on the requested animal 59da0ae2c0SAndreas Gohr */ 60da0ae2c0SAndreas Gohr public function __construct() { 61da0ae2c0SAndreas Gohr $this->loadConfig(); 62a646d519SAndreas Gohr if($this->config['base']['farmdir'] === '') return; // farm setup not complete 638262a4cbSAndreas Gohr $this->config['base']['farmdir'] = rtrim($this->config['base']['farmdir'], '/').'/'; // trailing slash always 6449f2871cSAndreas Gohr define('DOKU_FARMDIR', $this->config['base']['farmdir']); 65a646d519SAndreas Gohr 66a646d519SAndreas Gohr // animal? 67a646d519SAndreas Gohr $this->detectAnimal(); 68a646d519SAndreas Gohr 69a646d519SAndreas Gohr // setup defines 70a646d519SAndreas Gohr define('DOKU_FARM_ANIMAL', $this->animal); 71a646d519SAndreas Gohr if($this->animal) { 728262a4cbSAndreas Gohr define('DOKU_CONF', DOKU_FARMDIR . $this->animal . '/conf/'); 73a646d519SAndreas Gohr } else { 74a646d519SAndreas Gohr define('DOKU_CONF', DOKU_INC . '/conf/'); 75a646d519SAndreas Gohr } 76a646d519SAndreas Gohr 77a646d519SAndreas Gohr $this->setupCascade(); 78a646d519SAndreas Gohr $this->adjustCascade(); 79da0ae2c0SAndreas Gohr } 80da0ae2c0SAndreas Gohr 81da0ae2c0SAndreas Gohr /** 82da0ae2c0SAndreas Gohr * @return array the current farm configuration 83da0ae2c0SAndreas Gohr */ 84da0ae2c0SAndreas Gohr public function getConfig() { 85da0ae2c0SAndreas Gohr return $this->config; 86da0ae2c0SAndreas Gohr } 87da0ae2c0SAndreas Gohr 88da0ae2c0SAndreas Gohr /** 89a646d519SAndreas Gohr * @return false|string 90a646d519SAndreas Gohr */ 91a646d519SAndreas Gohr public function getAnimal() { 92a646d519SAndreas Gohr return $this->animal; 93a646d519SAndreas Gohr } 94a646d519SAndreas Gohr 95a646d519SAndreas Gohr /** 96a646d519SAndreas Gohr * @return boolean 97a646d519SAndreas Gohr */ 98a646d519SAndreas Gohr public function isHostbased() { 99a646d519SAndreas Gohr return $this->hostbased; 100a646d519SAndreas Gohr } 101a646d519SAndreas Gohr 102a646d519SAndreas Gohr /** 103a646d519SAndreas Gohr * @return boolean 104a646d519SAndreas Gohr */ 105a646d519SAndreas Gohr public function wasNotfound() { 106a646d519SAndreas Gohr return $this->notfound; 107a646d519SAndreas Gohr } 108a646d519SAndreas Gohr 109a646d519SAndreas Gohr /** 110b330074aSAndreas Gohr * @return string 111b330074aSAndreas Gohr */ 112b330074aSAndreas Gohr public function getAnimalDataDir() { 1138262a4cbSAndreas Gohr return DOKU_FARMDIR . $this->getAnimal() . '/data/'; 114b330074aSAndreas Gohr } 115b330074aSAndreas Gohr 116b330074aSAndreas Gohr /** 117b330074aSAndreas Gohr * @return string 118b330074aSAndreas Gohr */ 119b330074aSAndreas Gohr public function getAnimalBaseDir() { 12004dc6bd5SSzymon Olewniczak if($this->isHostbased()) return '/'; 121b330074aSAndreas Gohr return getBaseURL() . '!' . $this->getAnimal(); 122b330074aSAndreas Gohr } 123b330074aSAndreas Gohr 124b330074aSAndreas Gohr /** 125a646d519SAndreas Gohr * Detect the current animal 126a646d519SAndreas Gohr * 127a646d519SAndreas Gohr * Sets internal members $animal, $notfound and $hostbased 128a646d519SAndreas Gohr * 129a646d519SAndreas Gohr * This borrows form DokuWiki's inc/farm.php but does not support a default conf dir 130a646d519SAndreas Gohr */ 131a646d519SAndreas Gohr protected function detectAnimal() { 132a646d519SAndreas Gohr $farmdir = $this->config['base']['farmdir']; 133a646d519SAndreas Gohr $farmhost = $this->config['base']['farmhost']; 134a646d519SAndreas Gohr 135*917a67f0SAndreas Gohr // check if animal was set via rewrite parameter 136a646d519SAndreas Gohr $animal = ''; 137*917a67f0SAndreas Gohr if (isset($_GET['animal'])) { 138*917a67f0SAndreas Gohr $animal = $_GET['animal']; 139*917a67f0SAndreas Gohr // now unset the parameter to not leak into new queries 140*917a67f0SAndreas Gohr unset($_GET['animal']); 141*917a67f0SAndreas Gohr $params = []; 142*917a67f0SAndreas Gohr parse_str($_SERVER['QUERY_STRING'], $params); 143*917a67f0SAndreas Gohr if (isset($params['animal'])) unset($params['animal']); 144*917a67f0SAndreas Gohr $_SERVER['QUERY_STRING'] = http_build_query($params); 145*917a67f0SAndreas Gohr } 146*917a67f0SAndreas Gohr // get animal from CLI parameter 147a646d519SAndreas Gohr if('cli' == php_sapi_name() && isset($_SERVER['animal'])) $animal = $_SERVER['animal']; 148a646d519SAndreas Gohr if($animal) { 149a646d519SAndreas Gohr // check that $animal is a string and just a directory name and not a path 150a646d519SAndreas Gohr if(!is_string($animal) || strpbrk($animal, '\\/') !== false) { 151a646d519SAndreas Gohr $this->notfound = true; 152a646d519SAndreas Gohr return; 153a646d519SAndreas Gohr }; 154a646d519SAndreas Gohr $animal = strtolower($animal); 155a646d519SAndreas Gohr 156a646d519SAndreas Gohr // check if animal exists 157a646d519SAndreas Gohr if(is_dir("$farmdir/$animal/conf")) { 158a646d519SAndreas Gohr $this->animal = $animal; 159a646d519SAndreas Gohr return; 160a646d519SAndreas Gohr } else { 161a646d519SAndreas Gohr $this->notfound = true; 162a646d519SAndreas Gohr return; 163a646d519SAndreas Gohr } 164a646d519SAndreas Gohr } 165a646d519SAndreas Gohr 16636282384SAndreas Gohr // no host - no host based setup. if we're still here then it's the farmer 16736282384SAndreas Gohr if(!isset($_SERVER['HTTP_HOST'])) return; 16836282384SAndreas Gohr 169a646d519SAndreas Gohr // is this the farmer? 170a646d519SAndreas Gohr if(strtolower($_SERVER['HTTP_HOST']) == $farmhost) { 171a646d519SAndreas Gohr return; 172a646d519SAndreas Gohr } 173a646d519SAndreas Gohr 17485becf1bSAndreas Gohr // still here? check for host based 175a646d519SAndreas Gohr $this->hostbased = true; 17685becf1bSAndreas Gohr $possible = $this->getAnimalNamesForHost($_SERVER['HTTP_HOST']); 17785becf1bSAndreas Gohr foreach($possible as $animal) { 178a646d519SAndreas Gohr if(is_dir("$farmdir/$animal/conf/")) { 179a646d519SAndreas Gohr $this->animal = $animal; 180a646d519SAndreas Gohr return; 181a646d519SAndreas Gohr } 182a646d519SAndreas Gohr } 183a646d519SAndreas Gohr 184a646d519SAndreas Gohr // no hit 185a646d519SAndreas Gohr $this->notfound = true; 186a646d519SAndreas Gohr return; 187a646d519SAndreas Gohr } 188a646d519SAndreas Gohr 189a646d519SAndreas Gohr /** 19085becf1bSAndreas Gohr * Return a list of possible animal names for the given host 19185becf1bSAndreas Gohr * 19285becf1bSAndreas Gohr * @param string $host the HTTP_HOST header 19385becf1bSAndreas Gohr * @return array 19485becf1bSAndreas Gohr */ 19585becf1bSAndreas Gohr protected function getAnimalNamesForHost($host) { 19685becf1bSAndreas Gohr $animals = array(); 19785becf1bSAndreas Gohr $parts = explode('.', implode('.', explode(':', rtrim($host, '.')))); 19885becf1bSAndreas Gohr for($j = count($parts); $j > 0; $j--) { 19985becf1bSAndreas Gohr // strip from the end 20085becf1bSAndreas Gohr $animals[] = implode('.', array_slice($parts, 0, $j)); 20185becf1bSAndreas Gohr // strip from the end without host part 20285becf1bSAndreas Gohr $animals[] = implode('.', array_slice($parts, 1, $j)); 20385becf1bSAndreas Gohr } 20485becf1bSAndreas Gohr $animals = array_unique($animals); 20585becf1bSAndreas Gohr $animals = array_filter($animals); 2060a5d2da2SAndreas Gohr usort( 207bfecda9bSAndreas Gohr $animals, 208bfecda9bSAndreas Gohr // compare by length, then alphabet 209bfecda9bSAndreas Gohr function ($a, $b) { 210bfecda9bSAndreas Gohr $ret = strlen($b) - strlen($a); 211bfecda9bSAndreas Gohr if($ret != 0) return $ret; 212bfecda9bSAndreas Gohr return $a > $b; 2130a5d2da2SAndreas Gohr } 2140a5d2da2SAndreas Gohr ); 21585becf1bSAndreas Gohr return $animals; 21685becf1bSAndreas Gohr } 21785becf1bSAndreas Gohr 21885becf1bSAndreas Gohr /** 219a646d519SAndreas Gohr * This sets up the default farming config cascade 220a646d519SAndreas Gohr */ 221a646d519SAndreas Gohr protected function setupCascade() { 222a646d519SAndreas Gohr global $config_cascade; 223a646d519SAndreas Gohr $config_cascade = array( 224a646d519SAndreas Gohr 'main' => array( 225a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/dokuwiki.php',), 226a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'local.php',), 227a646d519SAndreas Gohr 'protected' => array(DOKU_CONF . 'local.protected.php',), 228a646d519SAndreas Gohr ), 229a646d519SAndreas Gohr 'acronyms' => array( 230a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/acronyms.conf',), 231a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'acronyms.local.conf',), 232a646d519SAndreas Gohr ), 233a646d519SAndreas Gohr 'entities' => array( 234a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/entities.conf',), 235a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'entities.local.conf',), 236a646d519SAndreas Gohr ), 237a646d519SAndreas Gohr 'interwiki' => array( 238a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/interwiki.conf',), 239a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'interwiki.local.conf',), 240a646d519SAndreas Gohr ), 241a646d519SAndreas Gohr 'license' => array( 242a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/license.php',), 243a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'license.local.php',), 244a646d519SAndreas Gohr ), 24527d95445SMichael Große 'manifest' => array( 24627d95445SMichael Große 'default' => array(DOKU_INC . 'conf/manifest.json',), 24727d95445SMichael Große 'local' => array(DOKU_CONF . 'manifest.local.json',), 24827d95445SMichael Große ), 249a646d519SAndreas Gohr 'mediameta' => array( 250a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/mediameta.php',), 251a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'mediameta.local.php',), 252a646d519SAndreas Gohr ), 253a646d519SAndreas Gohr 'mime' => array( 254a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/mime.conf',), 255a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'mime.local.conf',), 256a646d519SAndreas Gohr ), 257a646d519SAndreas Gohr 'scheme' => array( 258a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/scheme.conf',), 259a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'scheme.local.conf',), 260a646d519SAndreas Gohr ), 261a646d519SAndreas Gohr 'smileys' => array( 262a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/smileys.conf',), 263a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'smileys.local.conf',), 264a646d519SAndreas Gohr ), 265a646d519SAndreas Gohr 'wordblock' => array( 266a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/wordblock.conf',), 267a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'wordblock.local.conf',), 268a646d519SAndreas Gohr ), 269a646d519SAndreas Gohr 'acl' => array( 270a646d519SAndreas Gohr 'default' => DOKU_CONF . 'acl.auth.php', 271a646d519SAndreas Gohr ), 272a646d519SAndreas Gohr 'plainauth.users' => array( 273a646d519SAndreas Gohr 'default' => DOKU_CONF . 'users.auth.php', 274a646d519SAndreas Gohr ), 275de156015SAndreas Gohr 'plugins' => array( 276a646d519SAndreas Gohr 'default' => array(DOKU_INC . 'conf/plugins.php',), 277a646d519SAndreas Gohr 'local' => array(DOKU_CONF . 'plugins.local.php',), 278a646d519SAndreas Gohr 'protected' => array( 279a646d519SAndreas Gohr DOKU_INC . 'conf/plugins.required.php', 280a646d519SAndreas Gohr DOKU_CONF . 'plugins.protected.php', 281a646d519SAndreas Gohr ), 282a646d519SAndreas Gohr ), 283a646d519SAndreas Gohr 'userstyle' => array( 284a646d519SAndreas Gohr 'screen' => array(DOKU_CONF . 'userstyle.css', DOKU_CONF . 'userstyle.less',), 285a646d519SAndreas Gohr 'print' => array(DOKU_CONF . 'userprint.css', DOKU_CONF . 'userprint.less',), 286a646d519SAndreas Gohr 'feed' => array(DOKU_CONF . 'userfeed.css', DOKU_CONF . 'userfeed.less',), 287a646d519SAndreas Gohr 'all' => array(DOKU_CONF . 'userall.css', DOKU_CONF . 'userall.less',), 288a646d519SAndreas Gohr ), 289a646d519SAndreas Gohr 'userscript' => array( 290a646d519SAndreas Gohr 'default' => array(DOKU_CONF . 'userscript.js',), 291a646d519SAndreas Gohr ), 29205ea7625SAnna Dabrowska 'styleini' => array( 293bdb1e6e9SAnna Dabrowska 'default' => array(DOKU_INC . 'lib/tpl/%TEMPLATE%/' . 'style.ini'), 294bdb1e6e9SAnna Dabrowska 'local' => array(DOKU_CONF . 'tpl/%TEMPLATE%/' . 'style.ini') 29505ea7625SAnna Dabrowska ), 296a646d519SAndreas Gohr ); 297a646d519SAndreas Gohr } 298a646d519SAndreas Gohr 299a646d519SAndreas Gohr /** 300a646d519SAndreas Gohr * This adds additional files to the config cascade based on the inheritence settings 301a646d519SAndreas Gohr * 302a646d519SAndreas Gohr * These are only added for animals, not the farmer 303a646d519SAndreas Gohr */ 304a646d519SAndreas Gohr protected function adjustCascade() { 305b330074aSAndreas Gohr // nothing to do when on the farmer: 306b330074aSAndreas Gohr if(!$this->animal) return; 307a646d519SAndreas Gohr 308b330074aSAndreas Gohr global $config_cascade; 309a646d519SAndreas Gohr foreach($this->config['inherit'] as $key => $val) { 310a646d519SAndreas Gohr if(!$val) continue; 311a646d519SAndreas Gohr 312a646d519SAndreas Gohr // prepare what is to append or prepend 313a646d519SAndreas Gohr $append = array(); 314a646d519SAndreas Gohr $prepend = array(); 315a646d519SAndreas Gohr if($key == 'main') { 316b330074aSAndreas Gohr $append = array( 317b330074aSAndreas Gohr 'default' => array(DOKU_INC . 'conf/local.php'), 318b330074aSAndreas Gohr 'protected' => array(DOKU_INC . 'lib/plugins/farmer/includes/config.php') 319b330074aSAndreas Gohr ); 320a646d519SAndreas Gohr } elseif($key == 'license') { 321a646d519SAndreas Gohr $append = array('default' => array(DOKU_INC . 'conf/' . $key . '.local.php')); 322a646d519SAndreas Gohr } elseif($key == 'userscript') { 323a646d519SAndreas Gohr $prepend = array('default' => array(DOKU_INC . 'conf/userscript.js')); 324a646d519SAndreas Gohr } elseif($key == 'userstyle') { 325a646d519SAndreas Gohr $prepend = array( 326a646d519SAndreas Gohr 'screen' => array(DOKU_INC . 'conf/userstyle.css', DOKU_INC . 'conf/userstyle.less',), 327a646d519SAndreas Gohr 'print' => array(DOKU_INC . 'conf/userprint.css', DOKU_INC . 'conf/userprint.less',), 328a646d519SAndreas Gohr 'feed' => array(DOKU_INC . 'conf/userfeed.css', DOKU_INC . 'conf/userfeed.less',), 329a646d519SAndreas Gohr 'all' => array(DOKU_INC . 'conf/userall.css', DOKU_INC . 'conf/userall.less',), 330a646d519SAndreas Gohr ); 33105ea7625SAnna Dabrowska } elseif ($key == 'styleini') { 33205ea7625SAnna Dabrowska $append = array( 33305ea7625SAnna Dabrowska 'local' => array( 3343cee9885SAnna Dabrowska DOKU_INC . 'conf/tpl/%TEMPLATE%/style.ini' 33505ea7625SAnna Dabrowska ) 33605ea7625SAnna Dabrowska ); 3371272da0cSAndreas Gohr } elseif($key == 'users') { 3381272da0cSAndreas Gohr $config_cascade['plainauth.users']['protected'] = DOKU_INC . 'conf/users.auth.php'; 339af1c6dd8SAndreas Gohr } elseif($key == 'plugins') { 340af1c6dd8SAndreas Gohr $append = array('default' => array(DOKU_INC . 'conf/plugins.local.php')); 341a646d519SAndreas Gohr } else { 342a646d519SAndreas Gohr $append = array('default' => array(DOKU_INC . 'conf/' . $key . '.local.conf')); 343a646d519SAndreas Gohr } 344a646d519SAndreas Gohr 345a646d519SAndreas Gohr // add to cascade 346a646d519SAndreas Gohr foreach($prepend as $section => $data) { 347a646d519SAndreas Gohr $config_cascade[$key][$section] = array_merge($data, $config_cascade[$key][$section]); 348a646d519SAndreas Gohr } 349a646d519SAndreas Gohr foreach($append as $section => $data) { 350a646d519SAndreas Gohr $config_cascade[$key][$section] = array_merge($config_cascade[$key][$section], $data); 351a646d519SAndreas Gohr } 352a646d519SAndreas Gohr } 353de156015SAndreas Gohr 354de156015SAndreas Gohr // add plugin overrides 355de156015SAndreas Gohr $config_cascade['plugins']['protected'][] = DOKU_INC . 'lib/plugins/farmer/includes/plugins.php'; 356a646d519SAndreas Gohr } 357a646d519SAndreas Gohr 358a646d519SAndreas Gohr /** 359da0ae2c0SAndreas Gohr * Loads the farm config 360da0ae2c0SAndreas Gohr */ 361da0ae2c0SAndreas Gohr protected function loadConfig() { 362da0ae2c0SAndreas Gohr $ini = DOKU_INC . 'conf/farm.ini'; 363da0ae2c0SAndreas Gohr if(!file_exists($ini)) return; 364da0ae2c0SAndreas Gohr $config = parse_ini_file($ini, true); 365da0ae2c0SAndreas Gohr foreach(array_keys($this->config) as $section) { 366da0ae2c0SAndreas Gohr if(isset($config[$section])) { 367da0ae2c0SAndreas Gohr $this->config[$section] = array_merge( 368da0ae2c0SAndreas Gohr $this->config[$section], 369da0ae2c0SAndreas Gohr $config[$section] 370da0ae2c0SAndreas Gohr ); 371da0ae2c0SAndreas Gohr } 372da0ae2c0SAndreas Gohr } 373da0ae2c0SAndreas Gohr 374a646d519SAndreas Gohr $this->config['base']['farmdir'] = trim($this->config['base']['farmdir']); 375a646d519SAndreas Gohr $this->config['base']['farmhost'] = strtolower(trim($this->config['base']['farmhost'])); 376a646d519SAndreas Gohr } 377da0ae2c0SAndreas Gohr 378da0ae2c0SAndreas Gohr} 379da0ae2c0SAndreas Gohr 380da0ae2c0SAndreas Gohr// initialize it globally 38185becf1bSAndreas Gohrif(!defined('DOKU_UNITTEST')) { 382da0ae2c0SAndreas Gohr global $FARMCORE; 383da0ae2c0SAndreas Gohr $FARMCORE = new DokuWikiFarmCore(); 38485becf1bSAndreas Gohr} 385