xref: /plugin/farmer/DokuWikiFarmCore.php (revision 4b1aad076485f741601600f1c59af6b0a281432d)
1da0ae2c0SAndreas Gohr<?php
2da0ae2c0SAndreas Gohr
31da41c8bSAndreas Gohr// phpcs:disable PSR1.Files.SideEffects
4a646d519SAndreas Gohr/**
5a646d519SAndreas Gohr * Core Manager for the Farm functionality
6a646d519SAndreas Gohr *
7a646d519SAndreas Gohr * This class is initialized before any other DokuWiki code runs. Therefore it is
8a646d519SAndreas Gohr * completely selfcontained and does not use any of DokuWiki's utility functions.
9a646d519SAndreas Gohr *
10b96c66ccSAndreas Gohr * It's registered as a global $FARMCORE variable but you should not interact with
11b96c66ccSAndreas Gohr * it directly. Instead use the Farmer plugin's helper component.
120a5d2da2SAndreas Gohr *
130a5d2da2SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
140a5d2da2SAndreas Gohr * @author  Andreas Gohr <gohr@cosmocode.de>
15a646d519SAndreas Gohr */
161da41c8bSAndreas Gohrclass DokuWikiFarmCore
171da41c8bSAndreas Gohr{
18da0ae2c0SAndreas Gohr    /**
19da0ae2c0SAndreas Gohr     * @var array The default config - changed by loadConfig
20da0ae2c0SAndreas Gohr     */
211da41c8bSAndreas Gohr    protected $config = [
221da41c8bSAndreas Gohr        'base' => [
23a646d519SAndreas Gohr            'farmdir' => '',
24c4c8e953SAndreas Gohr            'farmhost' => '',
251da41c8bSAndreas Gohr            'basedomain' => ''
261da41c8bSAndreas Gohr        ],
271da41c8bSAndreas Gohr        'notfound' => [
28da0ae2c0SAndreas Gohr            'show' => 'farmer',
29da0ae2c0SAndreas Gohr            'url' => ''
301da41c8bSAndreas Gohr        ],
311da41c8bSAndreas Gohr        'inherit' => [
32da0ae2c0SAndreas Gohr            'main' => 1,
33da0ae2c0SAndreas Gohr            'acronyms' => 1,
34da0ae2c0SAndreas Gohr            'entities' => 1,
35da0ae2c0SAndreas Gohr            'interwiki' => 1,
36da0ae2c0SAndreas Gohr            'license' => 1,
37da0ae2c0SAndreas Gohr            'mime' => 1,
38da0ae2c0SAndreas Gohr            'scheme' => 1,
39da0ae2c0SAndreas Gohr            'smileys' => 1,
40da0ae2c0SAndreas Gohr            'wordblock' => 1,
411272da0cSAndreas Gohr            'users' => 0,
42af1c6dd8SAndreas Gohr            'plugins' => 0,
43da0ae2c0SAndreas Gohr            'userstyle' => 0,
4405ea7625SAnna Dabrowska            'userscript' => 0,
453cee9885SAnna Dabrowska            'styleini' => 0
461da41c8bSAndreas Gohr        ]
471da41c8bSAndreas Gohr    ];
48da0ae2c0SAndreas Gohr
49a646d519SAndreas Gohr    /** @var string|false The current animal, false for farmer */
50a646d519SAndreas Gohr    protected $animal = false;
51a646d519SAndreas Gohr    /** @var bool true if an animal was requested but was not found */
52a646d519SAndreas Gohr    protected $notfound = false;
53a646d519SAndreas Gohr    /** @var bool true if the current animal was requested by host */
54a646d519SAndreas Gohr    protected $hostbased = false;
55a646d519SAndreas Gohr
56da0ae2c0SAndreas Gohr    /**
57da0ae2c0SAndreas Gohr     * DokuWikiFarmCore constructor.
58da0ae2c0SAndreas Gohr     *
59a646d519SAndreas Gohr     * This initializes the whole farm by loading the configuration and setting
60a646d519SAndreas Gohr     * DOKU_CONF depending on the requested animal
61da0ae2c0SAndreas Gohr     */
621da41c8bSAndreas Gohr    public function __construct()
631da41c8bSAndreas Gohr    {
64da0ae2c0SAndreas Gohr        $this->loadConfig();
65a646d519SAndreas Gohr        if ($this->config['base']['farmdir'] === '') return; // farm setup not complete
668262a4cbSAndreas Gohr        $this->config['base']['farmdir'] = rtrim($this->config['base']['farmdir'], '/') . '/'; // trailing slash always
6749f2871cSAndreas Gohr        define('DOKU_FARMDIR', $this->config['base']['farmdir']);
68a646d519SAndreas Gohr
69a646d519SAndreas Gohr        // animal?
70a646d519SAndreas Gohr        $this->detectAnimal();
71a646d519SAndreas Gohr
72a646d519SAndreas Gohr        // setup defines
73a646d519SAndreas Gohr        define('DOKU_FARM_ANIMAL', $this->animal);
74a646d519SAndreas Gohr        if ($this->animal) {
758262a4cbSAndreas Gohr            define('DOKU_CONF', DOKU_FARMDIR . $this->animal . '/conf/');
76a646d519SAndreas Gohr        } else {
77a646d519SAndreas Gohr            define('DOKU_CONF', DOKU_INC . '/conf/');
78a646d519SAndreas Gohr        }
79a646d519SAndreas Gohr
80a646d519SAndreas Gohr        $this->setupCascade();
81a646d519SAndreas Gohr        $this->adjustCascade();
82da0ae2c0SAndreas Gohr    }
83da0ae2c0SAndreas Gohr
84da0ae2c0SAndreas Gohr    /**
85da0ae2c0SAndreas Gohr     * @return array the current farm configuration
86da0ae2c0SAndreas Gohr     */
871da41c8bSAndreas Gohr    public function getConfig()
881da41c8bSAndreas Gohr    {
89da0ae2c0SAndreas Gohr        return $this->config;
90da0ae2c0SAndreas Gohr    }
91da0ae2c0SAndreas Gohr
92da0ae2c0SAndreas Gohr    /**
93a646d519SAndreas Gohr     * @return false|string
94a646d519SAndreas Gohr     */
951da41c8bSAndreas Gohr    public function getAnimal()
961da41c8bSAndreas Gohr    {
97a646d519SAndreas Gohr        return $this->animal;
98a646d519SAndreas Gohr    }
99a646d519SAndreas Gohr
100a646d519SAndreas Gohr    /**
101a646d519SAndreas Gohr     * @return boolean
102a646d519SAndreas Gohr     */
1031da41c8bSAndreas Gohr    public function isHostbased()
1041da41c8bSAndreas Gohr    {
105a646d519SAndreas Gohr        return $this->hostbased;
106a646d519SAndreas Gohr    }
107a646d519SAndreas Gohr
108a646d519SAndreas Gohr    /**
109a646d519SAndreas Gohr     * @return boolean
110a646d519SAndreas Gohr     */
1111da41c8bSAndreas Gohr    public function wasNotfound()
1121da41c8bSAndreas Gohr    {
113a646d519SAndreas Gohr        return $this->notfound;
114a646d519SAndreas Gohr    }
115a646d519SAndreas Gohr
116a646d519SAndreas Gohr    /**
117b330074aSAndreas Gohr     * @return string
118b330074aSAndreas Gohr     */
1191da41c8bSAndreas Gohr    public function getAnimalDataDir()
1201da41c8bSAndreas Gohr    {
1218262a4cbSAndreas Gohr        return DOKU_FARMDIR . $this->getAnimal() . '/data/';
122b330074aSAndreas Gohr    }
123b330074aSAndreas Gohr
124b330074aSAndreas Gohr    /**
125b330074aSAndreas Gohr     * @return string
126b330074aSAndreas Gohr     */
1271da41c8bSAndreas Gohr    public function getAnimalBaseDir()
1281da41c8bSAndreas Gohr    {
12904dc6bd5SSzymon Olewniczak        if ($this->isHostbased()) return '/';
130b330074aSAndreas Gohr        return getBaseURL() . '!' . $this->getAnimal();
131b330074aSAndreas Gohr    }
132b330074aSAndreas Gohr
133b330074aSAndreas Gohr    /**
134a646d519SAndreas Gohr     * Detect the current animal
135a646d519SAndreas Gohr     *
136a646d519SAndreas Gohr     * Sets internal members $animal, $notfound and $hostbased
137a646d519SAndreas Gohr     *
138a646d519SAndreas Gohr     * This borrows form DokuWiki's inc/farm.php but does not support a default conf dir
139a646d519SAndreas Gohr     */
1401da41c8bSAndreas Gohr    protected function detectAnimal()
1411da41c8bSAndreas Gohr    {
142a646d519SAndreas Gohr        $farmdir = $this->config['base']['farmdir'];
143a646d519SAndreas Gohr        $farmhost = $this->config['base']['farmhost'];
144a646d519SAndreas Gohr
145917a67f0SAndreas Gohr        // check if animal was set via rewrite parameter
146a646d519SAndreas Gohr        $animal = '';
147917a67f0SAndreas Gohr        if (isset($_GET['animal'])) {
148917a67f0SAndreas Gohr            $animal = $_GET['animal'];
149917a67f0SAndreas Gohr            // now unset the parameter to not leak into new queries
150917a67f0SAndreas Gohr            unset($_GET['animal']);
151917a67f0SAndreas Gohr            $params = [];
152917a67f0SAndreas Gohr            parse_str($_SERVER['QUERY_STRING'], $params);
153917a67f0SAndreas Gohr            if (isset($params['animal'])) unset($params['animal']);
154917a67f0SAndreas Gohr            $_SERVER['QUERY_STRING'] = http_build_query($params);
155917a67f0SAndreas Gohr        }
156917a67f0SAndreas Gohr        // get animal from CLI parameter
1571da41c8bSAndreas Gohr        if ('cli' == PHP_SAPI && isset($_SERVER['animal'])) $animal = $_SERVER['animal'];
158a646d519SAndreas Gohr        if ($animal) {
159a646d519SAndreas Gohr            // check that $animal is a string and just a directory name and not a path
160a646d519SAndreas Gohr            if (!is_string($animal) || strpbrk($animal, '\\/') !== false) {
161a646d519SAndreas Gohr                $this->notfound = true;
162a646d519SAndreas Gohr                return;
163a646d519SAndreas Gohr            };
164a646d519SAndreas Gohr            $animal = strtolower($animal);
165a646d519SAndreas Gohr
166a646d519SAndreas Gohr            // check if animal exists
167a646d519SAndreas Gohr            if (is_dir("$farmdir/$animal/conf")) {
168a646d519SAndreas Gohr                $this->animal = $animal;
169a646d519SAndreas Gohr                return;
170a646d519SAndreas Gohr            } else {
171a646d519SAndreas Gohr                $this->notfound = true;
172a646d519SAndreas Gohr                return;
173a646d519SAndreas Gohr            }
174a646d519SAndreas Gohr        }
175a646d519SAndreas Gohr
17636282384SAndreas Gohr        // no host - no host based setup. if we're still here then it's the farmer
17736282384SAndreas Gohr        if (!isset($_SERVER['HTTP_HOST'])) return;
17836282384SAndreas Gohr
179a646d519SAndreas Gohr        // is this the farmer?
180a646d519SAndreas Gohr        if (strtolower($_SERVER['HTTP_HOST']) == $farmhost) {
181a646d519SAndreas Gohr            return;
182a646d519SAndreas Gohr        }
183a646d519SAndreas Gohr
18485becf1bSAndreas Gohr        // still here? check for host based
185a646d519SAndreas Gohr        $this->hostbased = true;
18685becf1bSAndreas Gohr        $possible = $this->getAnimalNamesForHost($_SERVER['HTTP_HOST']);
18785becf1bSAndreas Gohr        foreach ($possible as $animal) {
188a646d519SAndreas Gohr            if (is_dir("$farmdir/$animal/conf/")) {
189a646d519SAndreas Gohr                $this->animal = $animal;
190a646d519SAndreas Gohr                return;
191a646d519SAndreas Gohr            }
192a646d519SAndreas Gohr        }
193a646d519SAndreas Gohr
194a646d519SAndreas Gohr        // no hit
195a646d519SAndreas Gohr        $this->notfound = true;
196a646d519SAndreas Gohr    }
197a646d519SAndreas Gohr
198a646d519SAndreas Gohr    /**
19985becf1bSAndreas Gohr     * Return a list of possible animal names for the given host
20085becf1bSAndreas Gohr     *
20185becf1bSAndreas Gohr     * @param string $host the HTTP_HOST header
20285becf1bSAndreas Gohr     * @return array
20385becf1bSAndreas Gohr     */
2041da41c8bSAndreas Gohr    protected function getAnimalNamesForHost($host)
2051da41c8bSAndreas Gohr    {
2061da41c8bSAndreas Gohr        $animals = [];
20785becf1bSAndreas Gohr        $parts = explode('.', implode('.', explode(':', rtrim($host, '.'))));
20885becf1bSAndreas Gohr        for ($j = count($parts); $j > 0; $j--) {
20985becf1bSAndreas Gohr            // strip from the end
21085becf1bSAndreas Gohr            $animals[] = implode('.', array_slice($parts, 0, $j));
21185becf1bSAndreas Gohr            // strip from the end without host part
21285becf1bSAndreas Gohr            $animals[] = implode('.', array_slice($parts, 1, $j));
21385becf1bSAndreas Gohr        }
21485becf1bSAndreas Gohr        $animals = array_unique($animals);
21585becf1bSAndreas Gohr        $animals = array_filter($animals);
2160a5d2da2SAndreas Gohr        usort(
217bfecda9bSAndreas Gohr            $animals,
218bfecda9bSAndreas Gohr            // compare by length, then alphabet
219bfecda9bSAndreas Gohr            function ($a, $b) {
220bfecda9bSAndreas Gohr                $ret = strlen($b) - strlen($a);
221bfecda9bSAndreas Gohr                if ($ret != 0) return $ret;
222a2a8c90bSAndreas Gohr                return $a <=> $b;
2230a5d2da2SAndreas Gohr            }
2240a5d2da2SAndreas Gohr        );
22585becf1bSAndreas Gohr        return $animals;
22685becf1bSAndreas Gohr    }
22785becf1bSAndreas Gohr
22885becf1bSAndreas Gohr    /**
229a646d519SAndreas Gohr     * This sets up the default farming config cascade
230a646d519SAndreas Gohr     */
2311da41c8bSAndreas Gohr    protected function setupCascade()
2321da41c8bSAndreas Gohr    {
233a646d519SAndreas Gohr        global $config_cascade;
2341da41c8bSAndreas Gohr        $config_cascade = [
2351da41c8bSAndreas Gohr            'main' => [
2361da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/dokuwiki.php'],
2371da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'local.php'],
2381da41c8bSAndreas Gohr                'protected' => [DOKU_CONF . 'local.protected.php']
2391da41c8bSAndreas Gohr            ],
2401da41c8bSAndreas Gohr            'acronyms' => [
2411da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/acronyms.conf'],
2421da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'acronyms.local.conf']
2431da41c8bSAndreas Gohr            ],
2441da41c8bSAndreas Gohr            'entities' => [
2451da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/entities.conf'],
2461da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'entities.local.conf']
2471da41c8bSAndreas Gohr            ],
2481da41c8bSAndreas Gohr            'interwiki' => [
2491da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/interwiki.conf'],
2501da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'interwiki.local.conf']
2511da41c8bSAndreas Gohr            ],
2521da41c8bSAndreas Gohr            'license' => [
2531da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/license.php'],
2541da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'license.local.php']
2551da41c8bSAndreas Gohr            ],
2561da41c8bSAndreas Gohr            'manifest' => [
2571da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/manifest.json'],
2581da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'manifest.local.json']
2591da41c8bSAndreas Gohr            ],
2601da41c8bSAndreas Gohr            'mediameta' => [
2611da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/mediameta.php'],
2621da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'mediameta.local.php']
2631da41c8bSAndreas Gohr            ],
2641da41c8bSAndreas Gohr            'mime' => [
2651da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/mime.conf'],
2661da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'mime.local.conf']
2671da41c8bSAndreas Gohr            ],
2681da41c8bSAndreas Gohr            'scheme' => [
2691da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/scheme.conf'],
2701da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'scheme.local.conf']
2711da41c8bSAndreas Gohr            ],
2721da41c8bSAndreas Gohr            'smileys' => [
2731da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/smileys.conf'],
2741da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'smileys.local.conf']
2751da41c8bSAndreas Gohr            ],
2761da41c8bSAndreas Gohr            'wordblock' => [
2771da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/wordblock.conf'],
2781da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'wordblock.local.conf']
2791da41c8bSAndreas Gohr            ],
2801da41c8bSAndreas Gohr            'acl' => [
2811da41c8bSAndreas Gohr                'default' => DOKU_CONF . 'acl.auth.php'
2821da41c8bSAndreas Gohr            ],
2831da41c8bSAndreas Gohr            'plainauth.users' => [
2841da41c8bSAndreas Gohr                'default' => DOKU_CONF . 'users.auth.php'
2851da41c8bSAndreas Gohr            ],
2861da41c8bSAndreas Gohr            'plugins' => [
2871da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/plugins.php'],
2881da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'plugins.local.php'],
2891da41c8bSAndreas Gohr                'protected' => [
290a646d519SAndreas Gohr                    DOKU_INC . 'conf/plugins.required.php',
2911da41c8bSAndreas Gohr                    DOKU_CONF . 'plugins.protected.php'
2921da41c8bSAndreas Gohr                ]
2931da41c8bSAndreas Gohr            ],
2941da41c8bSAndreas Gohr            'userstyle' => [
2951da41c8bSAndreas Gohr                'screen' => [
2961da41c8bSAndreas Gohr                    DOKU_CONF . 'userstyle.css',
2971da41c8bSAndreas Gohr                    DOKU_CONF . 'userstyle.less'
2981da41c8bSAndreas Gohr                ],
2991da41c8bSAndreas Gohr                'print' => [
3001da41c8bSAndreas Gohr                    DOKU_CONF . 'userprint.css',
3011da41c8bSAndreas Gohr                    DOKU_CONF . 'userprint.less'
3021da41c8bSAndreas Gohr                ],
3031da41c8bSAndreas Gohr                'feed' => [
3041da41c8bSAndreas Gohr                    DOKU_CONF . 'userfeed.css',
3051da41c8bSAndreas Gohr                    DOKU_CONF . 'userfeed.less'
3061da41c8bSAndreas Gohr                ],
3071da41c8bSAndreas Gohr                'all' => [
3081da41c8bSAndreas Gohr                    DOKU_CONF . 'userall.css',
3091da41c8bSAndreas Gohr                    DOKU_CONF . 'userall.less'
3101da41c8bSAndreas Gohr                ]
3111da41c8bSAndreas Gohr            ],
3121da41c8bSAndreas Gohr            'userscript' => [
3131da41c8bSAndreas Gohr                'default' => [DOKU_CONF . 'userscript.js']
3141da41c8bSAndreas Gohr            ],
3151da41c8bSAndreas Gohr            'styleini' => [
3161da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'lib/tpl/%TEMPLATE%/' . 'style.ini'],
3171da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'tpl/%TEMPLATE%/' . 'style.ini']
3181da41c8bSAndreas Gohr            ]
3191da41c8bSAndreas Gohr        ];
320a646d519SAndreas Gohr    }
321a646d519SAndreas Gohr
322a646d519SAndreas Gohr    /**
323a646d519SAndreas Gohr     * This adds additional files to the config cascade based on the inheritence settings
324a646d519SAndreas Gohr     *
325a646d519SAndreas Gohr     * These are only added for animals, not the farmer
326a646d519SAndreas Gohr     */
3271da41c8bSAndreas Gohr    protected function adjustCascade()
3281da41c8bSAndreas Gohr    {
329b330074aSAndreas Gohr        // nothing to do when on the farmer:
330b330074aSAndreas Gohr        if (!$this->animal) return;
331a646d519SAndreas Gohr
332b330074aSAndreas Gohr        global $config_cascade;
333a646d519SAndreas Gohr        foreach ($this->config['inherit'] as $key => $val) {
334a646d519SAndreas Gohr            if (!$val) continue;
335a646d519SAndreas Gohr
336a646d519SAndreas Gohr            // prepare what is to append or prepend
3371da41c8bSAndreas Gohr            $append = [];
3381da41c8bSAndreas Gohr            $prepend = [];
339a646d519SAndreas Gohr            if ($key == 'main') {
340*4b1aad07Satisne                $prepend = [
341*4b1aad07Satisne                     'protected' => [DOKU_INC . 'conf/local.protected.php']
342*4b1aad07Satisne                ];
3431da41c8bSAndreas Gohr                $append = [
3441da41c8bSAndreas Gohr                    'default' => [DOKU_INC . 'conf/local.php'],
3451da41c8bSAndreas Gohr                    'protected' => [DOKU_INC . 'lib/plugins/farmer/includes/config.php']
3461da41c8bSAndreas Gohr                ];
347a646d519SAndreas Gohr            } elseif ($key == 'license') {
3481da41c8bSAndreas Gohr                $append = [
3491da41c8bSAndreas Gohr                    'default' => [DOKU_INC . 'conf/' . $key . '.local.php']
3501da41c8bSAndreas Gohr                ];
351a646d519SAndreas Gohr            } elseif ($key == 'userscript') {
3521da41c8bSAndreas Gohr                $prepend = [
3531da41c8bSAndreas Gohr                    'default' => [DOKU_INC . 'conf/userscript.js']
3541da41c8bSAndreas Gohr                ];
355a646d519SAndreas Gohr            } elseif ($key == 'userstyle') {
3561da41c8bSAndreas Gohr                $prepend = [
3571da41c8bSAndreas Gohr                    'screen' => [
3581da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userstyle.css',
3591da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userstyle.less'
3601da41c8bSAndreas Gohr                    ],
3611da41c8bSAndreas Gohr                    'print' => [
3621da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userprint.css',
3631da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userprint.less'
3641da41c8bSAndreas Gohr                    ],
3651da41c8bSAndreas Gohr                    'feed' => [
3661da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userfeed.css',
3671da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userfeed.less'
3681da41c8bSAndreas Gohr                    ],
3691da41c8bSAndreas Gohr                    'all' => [
3701da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userall.css',
3711da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userall.less'
3721da41c8bSAndreas Gohr                    ]
3731da41c8bSAndreas Gohr                ];
37405ea7625SAnna Dabrowska            } elseif ($key == 'styleini') {
3751da41c8bSAndreas Gohr                $append = [
3761da41c8bSAndreas Gohr                    'local' => [DOKU_INC . 'conf/tpl/%TEMPLATE%/style.ini']
3771da41c8bSAndreas Gohr                ];
3781272da0cSAndreas Gohr            } elseif ($key == 'users') {
3791272da0cSAndreas Gohr                $config_cascade['plainauth.users']['protected'] = DOKU_INC . 'conf/users.auth.php';
380af1c6dd8SAndreas Gohr            } elseif ($key == 'plugins') {
381*4b1aad07Satisne                $prepend = [
382*4b1aad07Satisne                    'protected' => [DOKU_INC . 'conf/local.protected.php']
383*4b1aad07Satisne                ];
3841da41c8bSAndreas Gohr                $append = [
3851da41c8bSAndreas Gohr                    'default' => [DOKU_INC . 'conf/plugins.local.php']
3861da41c8bSAndreas Gohr                ];
387a646d519SAndreas Gohr            } else {
3881da41c8bSAndreas Gohr                $append = [
3891da41c8bSAndreas Gohr                    'default' => [DOKU_INC . 'conf/' . $key . '.local.conf']
3901da41c8bSAndreas Gohr                ];
391a646d519SAndreas Gohr            }
392a646d519SAndreas Gohr
393a646d519SAndreas Gohr            // add to cascade
394a646d519SAndreas Gohr            foreach ($prepend as $section => $data) {
395a646d519SAndreas Gohr                $config_cascade[$key][$section] = array_merge($data, $config_cascade[$key][$section]);
396a646d519SAndreas Gohr            }
397a646d519SAndreas Gohr            foreach ($append as $section => $data) {
398a646d519SAndreas Gohr                $config_cascade[$key][$section] = array_merge($config_cascade[$key][$section], $data);
399a646d519SAndreas Gohr            }
400a646d519SAndreas Gohr        }
401de156015SAndreas Gohr
402de156015SAndreas Gohr        // add plugin overrides
403de156015SAndreas Gohr        $config_cascade['plugins']['protected'][] = DOKU_INC . 'lib/plugins/farmer/includes/plugins.php';
404a646d519SAndreas Gohr    }
405a646d519SAndreas Gohr
406a646d519SAndreas Gohr    /**
407da0ae2c0SAndreas Gohr     * Loads the farm config
408da0ae2c0SAndreas Gohr     */
4091da41c8bSAndreas Gohr    protected function loadConfig()
4101da41c8bSAndreas Gohr    {
411da0ae2c0SAndreas Gohr        $ini = DOKU_INC . 'conf/farm.ini';
412da0ae2c0SAndreas Gohr        if (!file_exists($ini)) return;
413da0ae2c0SAndreas Gohr        $config = parse_ini_file($ini, true);
414da0ae2c0SAndreas Gohr        foreach (array_keys($this->config) as $section) {
415da0ae2c0SAndreas Gohr            if (isset($config[$section])) {
416da0ae2c0SAndreas Gohr                $this->config[$section] = array_merge(
417da0ae2c0SAndreas Gohr                    $this->config[$section],
418da0ae2c0SAndreas Gohr                    $config[$section]
419da0ae2c0SAndreas Gohr                );
420da0ae2c0SAndreas Gohr            }
421da0ae2c0SAndreas Gohr        }
422da0ae2c0SAndreas Gohr
423a646d519SAndreas Gohr        $this->config['base']['farmdir'] = trim($this->config['base']['farmdir']);
424a646d519SAndreas Gohr        $this->config['base']['farmhost'] = strtolower(trim($this->config['base']['farmhost']));
425a646d519SAndreas Gohr    }
426da0ae2c0SAndreas Gohr}
427da0ae2c0SAndreas Gohr
428da0ae2c0SAndreas Gohr// initialize it globally
42985becf1bSAndreas Gohrif (!defined('DOKU_UNITTEST')) {
430da0ae2c0SAndreas Gohr    global $FARMCORE;
431da0ae2c0SAndreas Gohr    $FARMCORE = new DokuWikiFarmCore();
43285becf1bSAndreas Gohr}
433