1da0ae2c0SAndreas Gohr<?php 2da0ae2c0SAndreas Gohr 31da41c8bSAndreas Gohr// phpcs:disable PSR1.Files.SideEffects 4*c468f8caSAndreas Gohr 5a646d519SAndreas Gohr/** 6a646d519SAndreas Gohr * Core Manager for the Farm functionality 7a646d519SAndreas Gohr * 8a646d519SAndreas Gohr * This class is initialized before any other DokuWiki code runs. Therefore it is 9a646d519SAndreas Gohr * completely selfcontained and does not use any of DokuWiki's utility functions. 10a646d519SAndreas Gohr * 11b96c66ccSAndreas Gohr * It's registered as a global $FARMCORE variable but you should not interact with 12b96c66ccSAndreas Gohr * it directly. Instead use the Farmer plugin's helper component. 130a5d2da2SAndreas Gohr * 140a5d2da2SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 150a5d2da2SAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 16a646d519SAndreas Gohr */ 171da41c8bSAndreas Gohrclass DokuWikiFarmCore 181da41c8bSAndreas Gohr{ 19da0ae2c0SAndreas Gohr /** 20da0ae2c0SAndreas Gohr * @var array The default config - changed by loadConfig 21da0ae2c0SAndreas Gohr */ 221da41c8bSAndreas Gohr protected $config = [ 231da41c8bSAndreas Gohr 'base' => [ 24a646d519SAndreas Gohr 'farmdir' => '', 25c4c8e953SAndreas Gohr 'farmhost' => '', 261da41c8bSAndreas Gohr 'basedomain' => '' 271da41c8bSAndreas Gohr ], 281da41c8bSAndreas Gohr 'notfound' => [ 29da0ae2c0SAndreas Gohr 'show' => 'farmer', 30da0ae2c0SAndreas Gohr 'url' => '' 311da41c8bSAndreas Gohr ], 321da41c8bSAndreas Gohr 'inherit' => [ 33da0ae2c0SAndreas Gohr 'main' => 1, 34da0ae2c0SAndreas Gohr 'acronyms' => 1, 35da0ae2c0SAndreas Gohr 'entities' => 1, 36da0ae2c0SAndreas Gohr 'interwiki' => 1, 37da0ae2c0SAndreas Gohr 'license' => 1, 38da0ae2c0SAndreas Gohr 'mime' => 1, 39da0ae2c0SAndreas Gohr 'scheme' => 1, 40da0ae2c0SAndreas Gohr 'smileys' => 1, 41da0ae2c0SAndreas Gohr 'wordblock' => 1, 421272da0cSAndreas Gohr 'users' => 0, 43af1c6dd8SAndreas Gohr 'plugins' => 0, 44da0ae2c0SAndreas Gohr 'userstyle' => 0, 4505ea7625SAnna Dabrowska 'userscript' => 0, 463cee9885SAnna Dabrowska 'styleini' => 0 471da41c8bSAndreas Gohr ] 481da41c8bSAndreas Gohr ]; 49da0ae2c0SAndreas Gohr 50a646d519SAndreas Gohr /** @var string|false The current animal, false for farmer */ 51a646d519SAndreas Gohr protected $animal = false; 52a646d519SAndreas Gohr /** @var bool true if an animal was requested but was not found */ 53a646d519SAndreas Gohr protected $notfound = false; 54a646d519SAndreas Gohr /** @var bool true if the current animal was requested by host */ 55a646d519SAndreas Gohr protected $hostbased = false; 56a646d519SAndreas Gohr 57da0ae2c0SAndreas Gohr /** 58da0ae2c0SAndreas Gohr * DokuWikiFarmCore constructor. 59da0ae2c0SAndreas Gohr * 60a646d519SAndreas Gohr * This initializes the whole farm by loading the configuration and setting 61a646d519SAndreas Gohr * DOKU_CONF depending on the requested animal 62da0ae2c0SAndreas Gohr */ 631da41c8bSAndreas Gohr public function __construct() 641da41c8bSAndreas Gohr { 65da0ae2c0SAndreas Gohr $this->loadConfig(); 66a646d519SAndreas Gohr if ($this->config['base']['farmdir'] === '') return; // farm setup not complete 678262a4cbSAndreas Gohr $this->config['base']['farmdir'] = rtrim($this->config['base']['farmdir'], '/') . '/'; // trailing slash always 6849f2871cSAndreas Gohr define('DOKU_FARMDIR', $this->config['base']['farmdir']); 69a646d519SAndreas Gohr 70a646d519SAndreas Gohr // animal? 71a646d519SAndreas Gohr $this->detectAnimal(); 72a646d519SAndreas Gohr 73a646d519SAndreas Gohr // setup defines 74a646d519SAndreas Gohr define('DOKU_FARM_ANIMAL', $this->animal); 75a646d519SAndreas Gohr if ($this->animal) { 768262a4cbSAndreas Gohr define('DOKU_CONF', DOKU_FARMDIR . $this->animal . '/conf/'); 77a646d519SAndreas Gohr } else { 78a646d519SAndreas Gohr define('DOKU_CONF', DOKU_INC . '/conf/'); 79a646d519SAndreas Gohr } 80a646d519SAndreas Gohr 81a646d519SAndreas Gohr $this->setupCascade(); 82a646d519SAndreas Gohr $this->adjustCascade(); 83da0ae2c0SAndreas Gohr } 84da0ae2c0SAndreas Gohr 85da0ae2c0SAndreas Gohr /** 86da0ae2c0SAndreas Gohr * @return array the current farm configuration 87da0ae2c0SAndreas Gohr */ 881da41c8bSAndreas Gohr public function getConfig() 891da41c8bSAndreas Gohr { 90da0ae2c0SAndreas Gohr return $this->config; 91da0ae2c0SAndreas Gohr } 92da0ae2c0SAndreas Gohr 93da0ae2c0SAndreas Gohr /** 94a646d519SAndreas Gohr * @return false|string 95a646d519SAndreas Gohr */ 961da41c8bSAndreas Gohr public function getAnimal() 971da41c8bSAndreas Gohr { 98a646d519SAndreas Gohr return $this->animal; 99a646d519SAndreas Gohr } 100a646d519SAndreas Gohr 101a646d519SAndreas Gohr /** 102a646d519SAndreas Gohr * @return boolean 103a646d519SAndreas Gohr */ 1041da41c8bSAndreas Gohr public function isHostbased() 1051da41c8bSAndreas Gohr { 106a646d519SAndreas Gohr return $this->hostbased; 107a646d519SAndreas Gohr } 108a646d519SAndreas Gohr 109a646d519SAndreas Gohr /** 110a646d519SAndreas Gohr * @return boolean 111a646d519SAndreas Gohr */ 1121da41c8bSAndreas Gohr public function wasNotfound() 1131da41c8bSAndreas Gohr { 114a646d519SAndreas Gohr return $this->notfound; 115a646d519SAndreas Gohr } 116a646d519SAndreas Gohr 117a646d519SAndreas Gohr /** 118b330074aSAndreas Gohr * @return string 119b330074aSAndreas Gohr */ 1201da41c8bSAndreas Gohr public function getAnimalDataDir() 1211da41c8bSAndreas Gohr { 1228262a4cbSAndreas Gohr return DOKU_FARMDIR . $this->getAnimal() . '/data/'; 123b330074aSAndreas Gohr } 124b330074aSAndreas Gohr 125b330074aSAndreas Gohr /** 126b330074aSAndreas Gohr * @return string 127b330074aSAndreas Gohr */ 1281da41c8bSAndreas Gohr public function getAnimalBaseDir() 1291da41c8bSAndreas Gohr { 13004dc6bd5SSzymon Olewniczak if ($this->isHostbased()) return '/'; 131b330074aSAndreas Gohr return getBaseURL() . '!' . $this->getAnimal(); 132b330074aSAndreas Gohr } 133b330074aSAndreas Gohr 134b330074aSAndreas Gohr /** 135*c468f8caSAndreas Gohr * Set the animal 136a646d519SAndreas Gohr * 137*c468f8caSAndreas Gohr * Checks if the animal exists and is a valid directory name. 138a646d519SAndreas Gohr * 139*c468f8caSAndreas Gohr * @param mixed $animal the animal name 140*c468f8caSAndreas Gohr * @return bool returns true if the animal was set successfully, false otherwise 141a646d519SAndreas Gohr */ 142*c468f8caSAndreas Gohr protected function setAnimal($animal) 1431da41c8bSAndreas Gohr { 144a646d519SAndreas Gohr $farmdir = $this->config['base']['farmdir']; 145a646d519SAndreas Gohr 146*c468f8caSAndreas Gohr // invalid animal stuff is always a not found 147a646d519SAndreas Gohr if (!is_string($animal) || strpbrk($animal, '\\/') !== false) { 148a646d519SAndreas Gohr $this->notfound = true; 149*c468f8caSAndreas Gohr return false; 150*c468f8caSAndreas Gohr } 151a646d519SAndreas Gohr $animal = strtolower($animal); 152a646d519SAndreas Gohr 153a646d519SAndreas Gohr // check if animal exists 154a646d519SAndreas Gohr if (is_dir("$farmdir/$animal/conf")) { 155a646d519SAndreas Gohr $this->animal = $animal; 156*c468f8caSAndreas Gohr $this->notfound = false; 157*c468f8caSAndreas Gohr return true; 158a646d519SAndreas Gohr } else { 159a646d519SAndreas Gohr $this->notfound = true; 160*c468f8caSAndreas Gohr return false; 161a646d519SAndreas Gohr } 162a646d519SAndreas Gohr } 163a646d519SAndreas Gohr 164*c468f8caSAndreas Gohr /** 165*c468f8caSAndreas Gohr * Detect the animal from the given query string 166*c468f8caSAndreas Gohr * 167*c468f8caSAndreas Gohr * This removes the animal parameter from the given string and sets the animal 168*c468f8caSAndreas Gohr * 169*c468f8caSAndreas Gohr * @param string $queryString The query string to extract the animal from, will be modified 170*c468f8caSAndreas Gohr * @return bool true if the animal was set successfully, false otherwise 171*c468f8caSAndreas Gohr */ 172*c468f8caSAndreas Gohr protected function detectAnimalFromQueryString(string &$queryString): bool 173*c468f8caSAndreas Gohr { 174*c468f8caSAndreas Gohr $params = []; 175*c468f8caSAndreas Gohr parse_str($queryString, $params); 176*c468f8caSAndreas Gohr if (!isset($params['animal'])) return false; 177*c468f8caSAndreas Gohr $animal = $params['animal']; 178*c468f8caSAndreas Gohr unset($params['animal']); 179*c468f8caSAndreas Gohr $queryString = http_build_query($params); 180*c468f8caSAndreas Gohr 181*c468f8caSAndreas Gohr $this->hostbased = false; 182*c468f8caSAndreas Gohr return $this->setAnimal($animal); 183*c468f8caSAndreas Gohr } 184*c468f8caSAndreas Gohr 185*c468f8caSAndreas Gohr /** 186*c468f8caSAndreas Gohr * Detect the animal from the bang path 187*c468f8caSAndreas Gohr * 188*c468f8caSAndreas Gohr * This is used to detect the animal from a bang path like `/!animal/my:page` or '/dokuwiki/!animal/my:page'. 189*c468f8caSAndreas Gohr * 190*c468f8caSAndreas Gohr * @param string $path The bang path to extract the animal from 191*c468f8caSAndreas Gohr * @return bool true if the animal was set successfully, false otherwise 192*c468f8caSAndreas Gohr */ 193*c468f8caSAndreas Gohr protected function detectAnimalFromBangPath(string $path): bool 194*c468f8caSAndreas Gohr { 195*c468f8caSAndreas Gohr $bangregex = '#^(/(?:[^/]*/)*)!([^/]+)/#'; 196*c468f8caSAndreas Gohr if (preg_match($bangregex, $path, $matches)) { 197*c468f8caSAndreas Gohr // found a bang path 198*c468f8caSAndreas Gohr $animal = $matches[2]; 199*c468f8caSAndreas Gohr 200*c468f8caSAndreas Gohr $this->hostbased = false; 201*c468f8caSAndreas Gohr return $this->setAnimal($animal); 202*c468f8caSAndreas Gohr } 203*c468f8caSAndreas Gohr return false; 204*c468f8caSAndreas Gohr } 205*c468f8caSAndreas Gohr 206*c468f8caSAndreas Gohr /** 207*c468f8caSAndreas Gohr * Detect the animal from the host name 208*c468f8caSAndreas Gohr * 209*c468f8caSAndreas Gohr * @param string $host The hostname 210*c468f8caSAndreas Gohr * @return bool true if the animal was set successfully, false otherwise 211*c468f8caSAndreas Gohr */ 212*c468f8caSAndreas Gohr protected function detectAnimalFromHostName(string $host): bool 213*c468f8caSAndreas Gohr { 214*c468f8caSAndreas Gohr $possible = $this->getAnimalNamesForHost($host); 215*c468f8caSAndreas Gohr foreach ($possible as $animal) { 216*c468f8caSAndreas Gohr if ($this->setAnimal($animal)) { 217*c468f8caSAndreas Gohr $this->hostbased = true; 218*c468f8caSAndreas Gohr return true; 219*c468f8caSAndreas Gohr } 220*c468f8caSAndreas Gohr } 221*c468f8caSAndreas Gohr return false; 222*c468f8caSAndreas Gohr } 223*c468f8caSAndreas Gohr 224*c468f8caSAndreas Gohr /** 225*c468f8caSAndreas Gohr * Detect the current animal 226*c468f8caSAndreas Gohr * 227*c468f8caSAndreas Gohr * Sets internal members $animal, $notfound and $hostbased 228*c468f8caSAndreas Gohr * 229*c468f8caSAndreas Gohr * This borrows form DokuWiki's inc/farm.php but does not support a default conf dir 230*c468f8caSAndreas Gohr * 231*c468f8caSAndreas Gohr * @params string|null $sapi the SAPI to use. Only changed during testing 232*c468f8caSAndreas Gohr */ 233*c468f8caSAndreas Gohr protected function detectAnimal($sapi = null) 234*c468f8caSAndreas Gohr { 235*c468f8caSAndreas Gohr $sapi = $sapi ?: PHP_SAPI; 236*c468f8caSAndreas Gohr $farmhost = $this->config['base']['farmhost']; 237*c468f8caSAndreas Gohr 238*c468f8caSAndreas Gohr if ('cli' == $sapi) { 239*c468f8caSAndreas Gohr if (!isset($_SERVER['animal'])) return; // no animal parameter given - we're the farmer 240*c468f8caSAndreas Gohr 241*c468f8caSAndreas Gohr if (preg_match('#^https?://#i', $_SERVER['animal'])) { 242*c468f8caSAndreas Gohr // CLI animal parameter is a URL 243*c468f8caSAndreas Gohr $urlparts = parse_url($_SERVER['animal']); 244*c468f8caSAndreas Gohr $urlparts['query'] ??= ''; 245*c468f8caSAndreas Gohr 246*c468f8caSAndreas Gohr // detect the animal from the URL 247*c468f8caSAndreas Gohr $this->detectAnimalFromQueryString($urlparts['query']) || 248*c468f8caSAndreas Gohr $this->detectAnimalFromBangPath($urlparts['path']) || 249*c468f8caSAndreas Gohr $this->detectAnimalFromHostName($urlparts['host']); 250*c468f8caSAndreas Gohr 251*c468f8caSAndreas Gohr // fake baseurl etc. 252*c468f8caSAndreas Gohr $this->injectServerEnvironment($urlparts); 253*c468f8caSAndreas Gohr } else { 254*c468f8caSAndreas Gohr // CLI animal parameter is just a name 255*c468f8caSAndreas Gohr $this->setAnimal(strtolower($_SERVER['animal'])); 256*c468f8caSAndreas Gohr } 257*c468f8caSAndreas Gohr } else { 258*c468f8caSAndreas Gohr // an animal url parameter has been set 259*c468f8caSAndreas Gohr if (isset($_GET['animal'])) { 260*c468f8caSAndreas Gohr $this->detectAnimalFromQueryString($_SERVER['QUERY_STRING']); 261*c468f8caSAndreas Gohr unset($_GET['animal']); 262*c468f8caSAndreas Gohr return; 263*c468f8caSAndreas Gohr } 264*c468f8caSAndreas Gohr 26536282384SAndreas Gohr // no host - no host based setup. if we're still here then it's the farmer 266*c468f8caSAndreas Gohr if (empty($_SERVER['HTTP_HOST'])) return; 26736282384SAndreas Gohr 268a646d519SAndreas Gohr // is this the farmer? 269a646d519SAndreas Gohr if (strtolower($_SERVER['HTTP_HOST']) == $farmhost) { 270a646d519SAndreas Gohr return; 271a646d519SAndreas Gohr } 272a646d519SAndreas Gohr 273*c468f8caSAndreas Gohr // we're in host based mode now 274a646d519SAndreas Gohr $this->hostbased = true; 275*c468f8caSAndreas Gohr 276*c468f8caSAndreas Gohr // we should get an animal now 277*c468f8caSAndreas Gohr if (!$this->detectAnimalFromHostName($_SERVER['HTTP_HOST'])) { 278*c468f8caSAndreas Gohr $this->notfound = true; 279*c468f8caSAndreas Gohr } 280a646d519SAndreas Gohr } 281a646d519SAndreas Gohr } 282a646d519SAndreas Gohr 283*c468f8caSAndreas Gohr /** 284*c468f8caSAndreas Gohr * Create Server environment variables for the current animal 285*c468f8caSAndreas Gohr * 286*c468f8caSAndreas Gohr * This is called when the animal is initialized on the command line using a full URL. 287*c468f8caSAndreas Gohr * Since the initialization is running before any configuration is loaded, we instead 288*c468f8caSAndreas Gohr * set the $_SERVER variables that will later be used to autodetect the base URL. This 289*c468f8caSAndreas Gohr * way a manually set base URL will still take precedence. 290*c468f8caSAndreas Gohr * 291*c468f8caSAndreas Gohr * @param array $urlparts A parse_url() result array 292*c468f8caSAndreas Gohr * @return void 293*c468f8caSAndreas Gohr * @see is_ssl() 294*c468f8caSAndreas Gohr * @see getBaseURL() 295*c468f8caSAndreas Gohr */ 296*c468f8caSAndreas Gohr protected function injectServerEnvironment(array $urlparts) 297*c468f8caSAndreas Gohr { 298*c468f8caSAndreas Gohr // prepare data for DOKU_REL 299*c468f8caSAndreas Gohr $path = $urlparts['path'] ?? '/'; 300*c468f8caSAndreas Gohr if (($bangpos = strpos($path, '!')) !== false) { 301*c468f8caSAndreas Gohr // strip from the bang path 302*c468f8caSAndreas Gohr $path = substr($path, 0, $bangpos); 303*c468f8caSAndreas Gohr } 304*c468f8caSAndreas Gohr if (!str_ends_with($path, '.php')) { 305*c468f8caSAndreas Gohr // make sure we have a script name 306*c468f8caSAndreas Gohr $path = rtrim($path, '/') . '/doku.php'; 307*c468f8caSAndreas Gohr } 308*c468f8caSAndreas Gohr $_SERVER['SCRIPT_NAME'] = $path; 309*c468f8caSAndreas Gohr 310*c468f8caSAndreas Gohr // prepare data for is_ssl() 311*c468f8caSAndreas Gohr if (($urlparts['scheme'] ?? '') === 'https') { 312*c468f8caSAndreas Gohr $_SERVER['HTTPS'] = 'on'; 313*c468f8caSAndreas Gohr } else { 314*c468f8caSAndreas Gohr $_SERVER['HTTPS'] = 'off'; 315*c468f8caSAndreas Gohr } 316*c468f8caSAndreas Gohr 317*c468f8caSAndreas Gohr // prepare data for DOKU_URL 318*c468f8caSAndreas Gohr $_SERVER['HTTP_HOST'] = $urlparts['host'] ?? ''; 319*c468f8caSAndreas Gohr if (isset($urlparts['port'])) { 320*c468f8caSAndreas Gohr $_SERVER['HTTP_HOST'] .= ':' . $urlparts['port']; 321*c468f8caSAndreas Gohr } 322a646d519SAndreas Gohr } 323a646d519SAndreas Gohr 324a646d519SAndreas Gohr /** 32585becf1bSAndreas Gohr * Return a list of possible animal names for the given host 32685becf1bSAndreas Gohr * 32785becf1bSAndreas Gohr * @param string $host the HTTP_HOST header 32885becf1bSAndreas Gohr * @return array 32985becf1bSAndreas Gohr */ 3301da41c8bSAndreas Gohr protected function getAnimalNamesForHost($host) 3311da41c8bSAndreas Gohr { 3321da41c8bSAndreas Gohr $animals = []; 33385becf1bSAndreas Gohr $parts = explode('.', implode('.', explode(':', rtrim($host, '.')))); 33485becf1bSAndreas Gohr for ($j = count($parts); $j > 0; $j--) { 33585becf1bSAndreas Gohr // strip from the end 33685becf1bSAndreas Gohr $animals[] = implode('.', array_slice($parts, 0, $j)); 33785becf1bSAndreas Gohr // strip from the end without host part 33885becf1bSAndreas Gohr $animals[] = implode('.', array_slice($parts, 1, $j)); 33985becf1bSAndreas Gohr } 34085becf1bSAndreas Gohr $animals = array_unique($animals); 34185becf1bSAndreas Gohr $animals = array_filter($animals); 3420a5d2da2SAndreas Gohr usort( 343bfecda9bSAndreas Gohr $animals, 344bfecda9bSAndreas Gohr // compare by length, then alphabet 345bfecda9bSAndreas Gohr function ($a, $b) { 346bfecda9bSAndreas Gohr $ret = strlen($b) - strlen($a); 347bfecda9bSAndreas Gohr if ($ret != 0) return $ret; 348a2a8c90bSAndreas Gohr return $a <=> $b; 3490a5d2da2SAndreas Gohr } 3500a5d2da2SAndreas Gohr ); 35185becf1bSAndreas Gohr return $animals; 35285becf1bSAndreas Gohr } 35385becf1bSAndreas Gohr 35485becf1bSAndreas Gohr /** 355a646d519SAndreas Gohr * This sets up the default farming config cascade 356a646d519SAndreas Gohr */ 3571da41c8bSAndreas Gohr protected function setupCascade() 3581da41c8bSAndreas Gohr { 359a646d519SAndreas Gohr global $config_cascade; 3601da41c8bSAndreas Gohr $config_cascade = [ 3611da41c8bSAndreas Gohr 'main' => [ 3621da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/dokuwiki.php'], 3631da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'local.php'], 3641da41c8bSAndreas Gohr 'protected' => [DOKU_CONF . 'local.protected.php'] 3651da41c8bSAndreas Gohr ], 3661da41c8bSAndreas Gohr 'acronyms' => [ 3671da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/acronyms.conf'], 3681da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'acronyms.local.conf'] 3691da41c8bSAndreas Gohr ], 3701da41c8bSAndreas Gohr 'entities' => [ 3711da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/entities.conf'], 3721da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'entities.local.conf'] 3731da41c8bSAndreas Gohr ], 3741da41c8bSAndreas Gohr 'interwiki' => [ 3751da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/interwiki.conf'], 3761da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'interwiki.local.conf'] 3771da41c8bSAndreas Gohr ], 3781da41c8bSAndreas Gohr 'license' => [ 3791da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/license.php'], 3801da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'license.local.php'] 3811da41c8bSAndreas Gohr ], 3821da41c8bSAndreas Gohr 'manifest' => [ 3831da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/manifest.json'], 3841da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'manifest.local.json'] 3851da41c8bSAndreas Gohr ], 3861da41c8bSAndreas Gohr 'mediameta' => [ 3871da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/mediameta.php'], 3881da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'mediameta.local.php'] 3891da41c8bSAndreas Gohr ], 3901da41c8bSAndreas Gohr 'mime' => [ 3911da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/mime.conf'], 3921da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'mime.local.conf'] 3931da41c8bSAndreas Gohr ], 3941da41c8bSAndreas Gohr 'scheme' => [ 3951da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/scheme.conf'], 3961da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'scheme.local.conf'] 3971da41c8bSAndreas Gohr ], 3981da41c8bSAndreas Gohr 'smileys' => [ 3991da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/smileys.conf'], 4001da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'smileys.local.conf'] 4011da41c8bSAndreas Gohr ], 4021da41c8bSAndreas Gohr 'wordblock' => [ 4031da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/wordblock.conf'], 4041da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'wordblock.local.conf'] 4051da41c8bSAndreas Gohr ], 4061da41c8bSAndreas Gohr 'acl' => [ 4071da41c8bSAndreas Gohr 'default' => DOKU_CONF . 'acl.auth.php' 4081da41c8bSAndreas Gohr ], 4091da41c8bSAndreas Gohr 'plainauth.users' => [ 4101da41c8bSAndreas Gohr 'default' => DOKU_CONF . 'users.auth.php' 4111da41c8bSAndreas Gohr ], 4121da41c8bSAndreas Gohr 'plugins' => [ 4131da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/plugins.php'], 4141da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'plugins.local.php'], 4151da41c8bSAndreas Gohr 'protected' => [ 416a646d519SAndreas Gohr DOKU_INC . 'conf/plugins.required.php', 4171da41c8bSAndreas Gohr DOKU_CONF . 'plugins.protected.php' 4181da41c8bSAndreas Gohr ] 4191da41c8bSAndreas Gohr ], 4201da41c8bSAndreas Gohr 'userstyle' => [ 4211da41c8bSAndreas Gohr 'screen' => [ 4221da41c8bSAndreas Gohr DOKU_CONF . 'userstyle.css', 4231da41c8bSAndreas Gohr DOKU_CONF . 'userstyle.less' 4241da41c8bSAndreas Gohr ], 4251da41c8bSAndreas Gohr 'print' => [ 4261da41c8bSAndreas Gohr DOKU_CONF . 'userprint.css', 4271da41c8bSAndreas Gohr DOKU_CONF . 'userprint.less' 4281da41c8bSAndreas Gohr ], 4291da41c8bSAndreas Gohr 'feed' => [ 4301da41c8bSAndreas Gohr DOKU_CONF . 'userfeed.css', 4311da41c8bSAndreas Gohr DOKU_CONF . 'userfeed.less' 4321da41c8bSAndreas Gohr ], 4331da41c8bSAndreas Gohr 'all' => [ 4341da41c8bSAndreas Gohr DOKU_CONF . 'userall.css', 4351da41c8bSAndreas Gohr DOKU_CONF . 'userall.less' 4361da41c8bSAndreas Gohr ] 4371da41c8bSAndreas Gohr ], 4381da41c8bSAndreas Gohr 'userscript' => [ 4391da41c8bSAndreas Gohr 'default' => [DOKU_CONF . 'userscript.js'] 4401da41c8bSAndreas Gohr ], 4411da41c8bSAndreas Gohr 'styleini' => [ 4421da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'lib/tpl/%TEMPLATE%/' . 'style.ini'], 4431da41c8bSAndreas Gohr 'local' => [DOKU_CONF . 'tpl/%TEMPLATE%/' . 'style.ini'] 4441da41c8bSAndreas Gohr ] 4451da41c8bSAndreas Gohr ]; 446a646d519SAndreas Gohr } 447a646d519SAndreas Gohr 448a646d519SAndreas Gohr /** 449a646d519SAndreas Gohr * This adds additional files to the config cascade based on the inheritence settings 450a646d519SAndreas Gohr * 451a646d519SAndreas Gohr * These are only added for animals, not the farmer 452a646d519SAndreas Gohr */ 4531da41c8bSAndreas Gohr protected function adjustCascade() 4541da41c8bSAndreas Gohr { 455b330074aSAndreas Gohr // nothing to do when on the farmer: 456b330074aSAndreas Gohr if (!$this->animal) return; 457a646d519SAndreas Gohr 458b330074aSAndreas Gohr global $config_cascade; 459a646d519SAndreas Gohr foreach ($this->config['inherit'] as $key => $val) { 460a646d519SAndreas Gohr if (!$val) continue; 461a646d519SAndreas Gohr 462a646d519SAndreas Gohr // prepare what is to append or prepend 4631da41c8bSAndreas Gohr $append = []; 4641da41c8bSAndreas Gohr $prepend = []; 465a646d519SAndreas Gohr if ($key == 'main') { 4664b1aad07Satisne $prepend = [ 4674b1aad07Satisne 'protected' => [DOKU_INC . 'conf/local.protected.php'] 4684b1aad07Satisne ]; 4691da41c8bSAndreas Gohr $append = [ 4701da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/local.php'], 4711da41c8bSAndreas Gohr 'protected' => [DOKU_INC . 'lib/plugins/farmer/includes/config.php'] 4721da41c8bSAndreas Gohr ]; 473a646d519SAndreas Gohr } elseif ($key == 'license') { 4741da41c8bSAndreas Gohr $append = [ 4751da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/' . $key . '.local.php'] 4761da41c8bSAndreas Gohr ]; 477a646d519SAndreas Gohr } elseif ($key == 'userscript') { 4781da41c8bSAndreas Gohr $prepend = [ 4791da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/userscript.js'] 4801da41c8bSAndreas Gohr ]; 481a646d519SAndreas Gohr } elseif ($key == 'userstyle') { 4821da41c8bSAndreas Gohr $prepend = [ 4831da41c8bSAndreas Gohr 'screen' => [ 4841da41c8bSAndreas Gohr DOKU_INC . 'conf/userstyle.css', 4851da41c8bSAndreas Gohr DOKU_INC . 'conf/userstyle.less' 4861da41c8bSAndreas Gohr ], 4871da41c8bSAndreas Gohr 'print' => [ 4881da41c8bSAndreas Gohr DOKU_INC . 'conf/userprint.css', 4891da41c8bSAndreas Gohr DOKU_INC . 'conf/userprint.less' 4901da41c8bSAndreas Gohr ], 4911da41c8bSAndreas Gohr 'feed' => [ 4921da41c8bSAndreas Gohr DOKU_INC . 'conf/userfeed.css', 4931da41c8bSAndreas Gohr DOKU_INC . 'conf/userfeed.less' 4941da41c8bSAndreas Gohr ], 4951da41c8bSAndreas Gohr 'all' => [ 4961da41c8bSAndreas Gohr DOKU_INC . 'conf/userall.css', 4971da41c8bSAndreas Gohr DOKU_INC . 'conf/userall.less' 4981da41c8bSAndreas Gohr ] 4991da41c8bSAndreas Gohr ]; 50005ea7625SAnna Dabrowska } elseif ($key == 'styleini') { 5011da41c8bSAndreas Gohr $append = [ 5021da41c8bSAndreas Gohr 'local' => [DOKU_INC . 'conf/tpl/%TEMPLATE%/style.ini'] 5031da41c8bSAndreas Gohr ]; 5041272da0cSAndreas Gohr } elseif ($key == 'users') { 5051272da0cSAndreas Gohr $config_cascade['plainauth.users']['protected'] = DOKU_INC . 'conf/users.auth.php'; 506af1c6dd8SAndreas Gohr } elseif ($key == 'plugins') { 5074b1aad07Satisne $prepend = [ 5084b1aad07Satisne 'protected' => [DOKU_INC . 'conf/local.protected.php'] 5094b1aad07Satisne ]; 5101da41c8bSAndreas Gohr $append = [ 5111da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/plugins.local.php'] 5121da41c8bSAndreas Gohr ]; 513a646d519SAndreas Gohr } else { 5141da41c8bSAndreas Gohr $append = [ 5151da41c8bSAndreas Gohr 'default' => [DOKU_INC . 'conf/' . $key . '.local.conf'] 5161da41c8bSAndreas Gohr ]; 517a646d519SAndreas Gohr } 518a646d519SAndreas Gohr 519a646d519SAndreas Gohr // add to cascade 520a646d519SAndreas Gohr foreach ($prepend as $section => $data) { 521a646d519SAndreas Gohr $config_cascade[$key][$section] = array_merge($data, $config_cascade[$key][$section]); 522a646d519SAndreas Gohr } 523a646d519SAndreas Gohr foreach ($append as $section => $data) { 524a646d519SAndreas Gohr $config_cascade[$key][$section] = array_merge($config_cascade[$key][$section], $data); 525a646d519SAndreas Gohr } 526a646d519SAndreas Gohr } 527de156015SAndreas Gohr 528de156015SAndreas Gohr // add plugin overrides 529de156015SAndreas Gohr $config_cascade['plugins']['protected'][] = DOKU_INC . 'lib/plugins/farmer/includes/plugins.php'; 530a646d519SAndreas Gohr } 531a646d519SAndreas Gohr 532a646d519SAndreas Gohr /** 533da0ae2c0SAndreas Gohr * Loads the farm config 534da0ae2c0SAndreas Gohr */ 5351da41c8bSAndreas Gohr protected function loadConfig() 5361da41c8bSAndreas Gohr { 537da0ae2c0SAndreas Gohr $ini = DOKU_INC . 'conf/farm.ini'; 538700b5633SAndreas Gohr if (file_exists($ini)) { 539da0ae2c0SAndreas Gohr $config = parse_ini_file($ini, true); 540da0ae2c0SAndreas Gohr foreach (array_keys($this->config) as $section) { 541da0ae2c0SAndreas Gohr if (isset($config[$section])) { 542da0ae2c0SAndreas Gohr $this->config[$section] = array_merge( 543da0ae2c0SAndreas Gohr $this->config[$section], 544da0ae2c0SAndreas Gohr $config[$section] 545da0ae2c0SAndreas Gohr ); 546da0ae2c0SAndreas Gohr } 547da0ae2c0SAndreas Gohr } 548700b5633SAndreas Gohr } 549700b5633SAndreas Gohr 550700b5633SAndreas Gohr // farmdir setup can be done via environment 551700b5633SAndreas Gohr if ($this->config['base']['farmdir'] === '' && isset($_ENV['DOKU_FARMDIR'])) { 552700b5633SAndreas Gohr $this->config['base']['farmdir'] = $_ENV['DOKU_FARMDIR']; 553700b5633SAndreas Gohr } 554da0ae2c0SAndreas Gohr 555a646d519SAndreas Gohr $this->config['base']['farmdir'] = trim($this->config['base']['farmdir']); 556a646d519SAndreas Gohr $this->config['base']['farmhost'] = strtolower(trim($this->config['base']['farmhost'])); 557a646d519SAndreas Gohr } 558da0ae2c0SAndreas Gohr} 559da0ae2c0SAndreas Gohr 560da0ae2c0SAndreas Gohr// initialize it globally 56185becf1bSAndreas Gohrif (!defined('DOKU_UNITTEST')) { 562da0ae2c0SAndreas Gohr global $FARMCORE; 563da0ae2c0SAndreas Gohr $FARMCORE = new DokuWikiFarmCore(); 56485becf1bSAndreas Gohr} 565