diff options
author | Yaco <franco@reevo.org> | 2022-03-08 13:08:34 +0000 |
---|---|---|
committer | Yaco <franco@reevo.org> | 2022-03-08 13:08:34 +0000 |
commit | c985c40d3f3fc6a2be3be3186df3bf2f32189475 (patch) | |
tree | cee11f5e5a7e351ee0fec36d58d72cbee4f7e49b /platform/www/lib/plugins/farmer/DokuWikiFarmCore.php |
first commit after acervus codebase
Diffstat (limited to 'platform/www/lib/plugins/farmer/DokuWikiFarmCore.php')
-rw-r--r-- | platform/www/lib/plugins/farmer/DokuWikiFarmCore.php | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/platform/www/lib/plugins/farmer/DokuWikiFarmCore.php b/platform/www/lib/plugins/farmer/DokuWikiFarmCore.php new file mode 100644 index 0000000..6c8547a --- /dev/null +++ b/platform/www/lib/plugins/farmer/DokuWikiFarmCore.php @@ -0,0 +1,375 @@ +<?php + +/** + * Core Manager for the Farm functionality + * + * This class is initialized before any other DokuWiki code runs. Therefore it is + * completely selfcontained and does not use any of DokuWiki's utility functions. + * + * It's registered as a global $FARMCORE variable but you should not interact with + * it directly. Instead use the Farmer plugin's helper component. + * + * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html + * @author Andreas Gohr <gohr@cosmocode.de> + */ +class DokuWikiFarmCore { + /** + * @var array The default config - changed by loadConfig + */ + protected $config = array( + 'base' => array( + 'farmdir' => '', + 'farmhost' => '', + 'basedomain' => '', + ), + 'notfound' => array( + 'show' => 'farmer', + 'url' => '' + ), + 'inherit' => array( + 'main' => 1, + 'acronyms' => 1, + 'entities' => 1, + 'interwiki' => 1, + 'license' => 1, + 'mime' => 1, + 'scheme' => 1, + 'smileys' => 1, + 'wordblock' => 1, + 'users' => 0, + 'plugins' => 0, + 'userstyle' => 0, + 'userscript' => 0, + 'styleini' => 0 + ) + ); + + /** @var string|false The current animal, false for farmer */ + protected $animal = false; + /** @var bool true if an animal was requested but was not found */ + protected $notfound = false; + /** @var bool true if the current animal was requested by host */ + protected $hostbased = false; + + /** + * DokuWikiFarmCore constructor. + * + * This initializes the whole farm by loading the configuration and setting + * DOKU_CONF depending on the requested animal + */ + public function __construct() { + $this->loadConfig(); + if($this->config['base']['farmdir'] === '') return; // farm setup not complete + $this->config['base']['farmdir'] = rtrim($this->config['base']['farmdir'], '/').'/'; // trailing slash always + define('DOKU_FARMDIR', $this->config['base']['farmdir']); + + // animal? + $this->detectAnimal(); + + // setup defines + define('DOKU_FARM_ANIMAL', $this->animal); + if($this->animal) { + define('DOKU_CONF', DOKU_FARMDIR . $this->animal . '/conf/'); + } else { + define('DOKU_CONF', DOKU_INC . '/conf/'); + } + + $this->setupCascade(); + $this->adjustCascade(); + } + + /** + * @return array the current farm configuration + */ + public function getConfig() { + return $this->config; + } + + /** + * @return false|string + */ + public function getAnimal() { + return $this->animal; + } + + /** + * @return boolean + */ + public function isHostbased() { + return $this->hostbased; + } + + /** + * @return boolean + */ + public function wasNotfound() { + return $this->notfound; + } + + /** + * @return string + */ + public function getAnimalDataDir() { + return DOKU_FARMDIR . $this->getAnimal() . '/data/'; + } + + /** + * @return string + */ + public function getAnimalBaseDir() { + if($this->isHostbased()) return '/'; + return getBaseURL() . '!' . $this->getAnimal(); + } + + /** + * Detect the current animal + * + * Sets internal members $animal, $notfound and $hostbased + * + * This borrows form DokuWiki's inc/farm.php but does not support a default conf dir + */ + protected function detectAnimal() { + $farmdir = $this->config['base']['farmdir']; + $farmhost = $this->config['base']['farmhost']; + + // check if animal was set via parameter (rewrite or CLI) + $animal = ''; + if(isset($_REQUEST['animal'])) $animal = $_REQUEST['animal']; + if('cli' == php_sapi_name() && isset($_SERVER['animal'])) $animal = $_SERVER['animal']; + if($animal) { + // check that $animal is a string and just a directory name and not a path + if(!is_string($animal) || strpbrk($animal, '\\/') !== false) { + $this->notfound = true; + return; + }; + $animal = strtolower($animal); + + // check if animal exists + if(is_dir("$farmdir/$animal/conf")) { + $this->animal = $animal; + return; + } else { + $this->notfound = true; + return; + } + } + + // no host - no host based setup. if we're still here then it's the farmer + if(!isset($_SERVER['HTTP_HOST'])) return; + + // is this the farmer? + if(strtolower($_SERVER['HTTP_HOST']) == $farmhost) { + return; + } + + // still here? check for host based + $this->hostbased = true; + $possible = $this->getAnimalNamesForHost($_SERVER['HTTP_HOST']); + foreach($possible as $animal) { + if(is_dir("$farmdir/$animal/conf/")) { + $this->animal = $animal; + return; + } + } + + // no hit + $this->notfound = true; + return; + } + + /** + * Return a list of possible animal names for the given host + * + * @param string $host the HTTP_HOST header + * @return array + */ + protected function getAnimalNamesForHost($host) { + $animals = array(); + $parts = explode('.', implode('.', explode(':', rtrim($host, '.')))); + for($j = count($parts); $j > 0; $j--) { + // strip from the end + $animals[] = implode('.', array_slice($parts, 0, $j)); + // strip from the end without host part + $animals[] = implode('.', array_slice($parts, 1, $j)); + } + $animals = array_unique($animals); + $animals = array_filter($animals); + usort( + $animals, + // compare by length, then alphabet + function ($a, $b) { + $ret = strlen($b) - strlen($a); + if($ret != 0) return $ret; + return $a > $b; + } + ); + return $animals; + } + + /** + * This sets up the default farming config cascade + */ + protected function setupCascade() { + global $config_cascade; + $config_cascade = array( + 'main' => array( + 'default' => array(DOKU_INC . 'conf/dokuwiki.php',), + 'local' => array(DOKU_CONF . 'local.php',), + 'protected' => array(DOKU_CONF . 'local.protected.php',), + ), + 'acronyms' => array( + 'default' => array(DOKU_INC . 'conf/acronyms.conf',), + 'local' => array(DOKU_CONF . 'acronyms.local.conf',), + ), + 'entities' => array( + 'default' => array(DOKU_INC . 'conf/entities.conf',), + 'local' => array(DOKU_CONF . 'entities.local.conf',), + ), + 'interwiki' => array( + 'default' => array(DOKU_INC . 'conf/interwiki.conf',), + 'local' => array(DOKU_CONF . 'interwiki.local.conf',), + ), + 'license' => array( + 'default' => array(DOKU_INC . 'conf/license.php',), + 'local' => array(DOKU_CONF . 'license.local.php',), + ), + 'manifest' => array( + 'default' => array(DOKU_INC . 'conf/manifest.json',), + 'local' => array(DOKU_CONF . 'manifest.local.json',), + ), + 'mediameta' => array( + 'default' => array(DOKU_INC . 'conf/mediameta.php',), + 'local' => array(DOKU_CONF . 'mediameta.local.php',), + ), + 'mime' => array( + 'default' => array(DOKU_INC . 'conf/mime.conf',), + 'local' => array(DOKU_CONF . 'mime.local.conf',), + ), + 'scheme' => array( + 'default' => array(DOKU_INC . 'conf/scheme.conf',), + 'local' => array(DOKU_CONF . 'scheme.local.conf',), + ), + 'smileys' => array( + 'default' => array(DOKU_INC . 'conf/smileys.conf',), + 'local' => array(DOKU_CONF . 'smileys.local.conf',), + ), + 'wordblock' => array( + 'default' => array(DOKU_INC . 'conf/wordblock.conf',), + 'local' => array(DOKU_CONF . 'wordblock.local.conf',), + ), + 'acl' => array( + 'default' => DOKU_CONF . 'acl.auth.php', + ), + 'plainauth.users' => array( + 'default' => DOKU_CONF . 'users.auth.php', + ), + 'plugins' => array( + 'default' => array(DOKU_INC . 'conf/plugins.php',), + 'local' => array(DOKU_CONF . 'plugins.local.php',), + 'protected' => array( + DOKU_INC . 'conf/plugins.required.php', + DOKU_CONF . 'plugins.protected.php', + ), + ), + 'userstyle' => array( + 'screen' => array(DOKU_CONF . 'userstyle.css', DOKU_CONF . 'userstyle.less',), + 'print' => array(DOKU_CONF . 'userprint.css', DOKU_CONF . 'userprint.less',), + 'feed' => array(DOKU_CONF . 'userfeed.css', DOKU_CONF . 'userfeed.less',), + 'all' => array(DOKU_CONF . 'userall.css', DOKU_CONF . 'userall.less',), + ), + 'userscript' => array( + 'default' => array(DOKU_CONF . 'userscript.js',), + ), + 'styleini' => array( + 'default' => array(DOKU_INC . 'lib/tpl/%TEMPLATE%/' . 'style.ini'), + 'local' => array(DOKU_CONF . 'tpl/%TEMPLATE%/' . 'style.ini') + ), + ); + } + + /** + * This adds additional files to the config cascade based on the inheritence settings + * + * These are only added for animals, not the farmer + */ + protected function adjustCascade() { + // nothing to do when on the farmer: + if(!$this->animal) return; + + global $config_cascade; + foreach($this->config['inherit'] as $key => $val) { + if(!$val) continue; + + // prepare what is to append or prepend + $append = array(); + $prepend = array(); + if($key == 'main') { + $append = array( + 'default' => array(DOKU_INC . 'conf/local.php'), + 'protected' => array(DOKU_INC . 'lib/plugins/farmer/includes/config.php') + ); + } elseif($key == 'license') { + $append = array('default' => array(DOKU_INC . 'conf/' . $key . '.local.php')); + } elseif($key == 'userscript') { + $prepend = array('default' => array(DOKU_INC . 'conf/userscript.js')); + } elseif($key == 'userstyle') { + $prepend = array( + 'screen' => array(DOKU_INC . 'conf/userstyle.css', DOKU_INC . 'conf/userstyle.less',), + 'print' => array(DOKU_INC . 'conf/userprint.css', DOKU_INC . 'conf/userprint.less',), + 'feed' => array(DOKU_INC . 'conf/userfeed.css', DOKU_INC . 'conf/userfeed.less',), + 'all' => array(DOKU_INC . 'conf/userall.css', DOKU_INC . 'conf/userall.less',), + ); + } elseif ($key == 'styleini') { + $append = array( + 'local' => array( + DOKU_INC . 'conf/tpl/%TEMPLATE%/style.ini' + ) + ); + } elseif($key == 'users') { + $config_cascade['plainauth.users']['protected'] = DOKU_INC . 'conf/users.auth.php'; + } elseif($key == 'plugins') { + $append = array('default' => array(DOKU_INC . 'conf/plugins.local.php')); + } else { + $append = array('default' => array(DOKU_INC . 'conf/' . $key . '.local.conf')); + } + + // add to cascade + foreach($prepend as $section => $data) { + $config_cascade[$key][$section] = array_merge($data, $config_cascade[$key][$section]); + } + foreach($append as $section => $data) { + $config_cascade[$key][$section] = array_merge($config_cascade[$key][$section], $data); + } + } + + // add plugin overrides + $config_cascade['plugins']['protected'][] = DOKU_INC . 'lib/plugins/farmer/includes/plugins.php'; + } + + /** + * Loads the farm config + */ + protected function loadConfig() { + $ini = DOKU_INC . 'conf/farm.ini'; + if(!file_exists($ini)) return; + $config = parse_ini_file($ini, true); + foreach(array_keys($this->config) as $section) { + if(isset($config[$section])) { + $this->config[$section] = array_merge( + $this->config[$section], + $config[$section] + ); + } + } + + $this->config['base']['farmdir'] = trim($this->config['base']['farmdir']); + $this->config['base']['farmhost'] = strtolower(trim($this->config['base']['farmhost'])); + } + +} + +// initialize it globally +if(!defined('DOKU_UNITTEST')) { + global $FARMCORE; + $FARMCORE = new DokuWikiFarmCore(); +} |