xref: /plugin/farmer/DokuWikiFarmCore.php (revision 1da41c8bdb9ce0b590d5b69552c4ddb4d0aef860)
1da0ae2c0SAndreas Gohr<?php
2da0ae2c0SAndreas Gohr
3*1da41c8bSAndreas 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 */
16*1da41c8bSAndreas Gohrclass DokuWikiFarmCore
17*1da41c8bSAndreas Gohr{
18da0ae2c0SAndreas Gohr    /**
19da0ae2c0SAndreas Gohr     * @var array The default config - changed by loadConfig
20da0ae2c0SAndreas Gohr     */
21*1da41c8bSAndreas Gohr    protected $config = [
22*1da41c8bSAndreas Gohr        'base' => [
23a646d519SAndreas Gohr            'farmdir' => '',
24c4c8e953SAndreas Gohr            'farmhost' => '',
25*1da41c8bSAndreas Gohr            'basedomain' => ''
26*1da41c8bSAndreas Gohr        ],
27*1da41c8bSAndreas Gohr        'notfound' => [
28da0ae2c0SAndreas Gohr            'show' => 'farmer',
29da0ae2c0SAndreas Gohr            'url' => ''
30*1da41c8bSAndreas Gohr        ],
31*1da41c8bSAndreas 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
46*1da41c8bSAndreas Gohr        ]
47*1da41c8bSAndreas 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     */
62*1da41c8bSAndreas Gohr    public function __construct()
63*1da41c8bSAndreas 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     */
87*1da41c8bSAndreas Gohr    public function getConfig()
88*1da41c8bSAndreas Gohr    {
89da0ae2c0SAndreas Gohr        return $this->config;
90da0ae2c0SAndreas Gohr    }
91da0ae2c0SAndreas Gohr
92da0ae2c0SAndreas Gohr    /**
93a646d519SAndreas Gohr     * @return false|string
94a646d519SAndreas Gohr     */
95*1da41c8bSAndreas Gohr    public function getAnimal()
96*1da41c8bSAndreas Gohr    {
97a646d519SAndreas Gohr        return $this->animal;
98a646d519SAndreas Gohr    }
99a646d519SAndreas Gohr
100a646d519SAndreas Gohr    /**
101a646d519SAndreas Gohr     * @return boolean
102a646d519SAndreas Gohr     */
103*1da41c8bSAndreas Gohr    public function isHostbased()
104*1da41c8bSAndreas Gohr    {
105a646d519SAndreas Gohr        return $this->hostbased;
106a646d519SAndreas Gohr    }
107a646d519SAndreas Gohr
108a646d519SAndreas Gohr    /**
109a646d519SAndreas Gohr     * @return boolean
110a646d519SAndreas Gohr     */
111*1da41c8bSAndreas Gohr    public function wasNotfound()
112*1da41c8bSAndreas Gohr    {
113a646d519SAndreas Gohr        return $this->notfound;
114a646d519SAndreas Gohr    }
115a646d519SAndreas Gohr
116a646d519SAndreas Gohr    /**
117b330074aSAndreas Gohr     * @return string
118b330074aSAndreas Gohr     */
119*1da41c8bSAndreas Gohr    public function getAnimalDataDir()
120*1da41c8bSAndreas Gohr    {
1218262a4cbSAndreas Gohr        return DOKU_FARMDIR . $this->getAnimal() . '/data/';
122b330074aSAndreas Gohr    }
123b330074aSAndreas Gohr
124b330074aSAndreas Gohr    /**
125b330074aSAndreas Gohr     * @return string
126b330074aSAndreas Gohr     */
127*1da41c8bSAndreas Gohr    public function getAnimalBaseDir()
128*1da41c8bSAndreas 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     */
140*1da41c8bSAndreas Gohr    protected function detectAnimal()
141*1da41c8bSAndreas 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
157*1da41c8bSAndreas 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     */
204*1da41c8bSAndreas Gohr    protected function getAnimalNamesForHost($host)
205*1da41c8bSAndreas Gohr    {
206*1da41c8bSAndreas 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     */
231*1da41c8bSAndreas Gohr    protected function setupCascade()
232*1da41c8bSAndreas Gohr    {
233a646d519SAndreas Gohr        global $config_cascade;
234*1da41c8bSAndreas Gohr        $config_cascade = [
235*1da41c8bSAndreas Gohr            'main' => [
236*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/dokuwiki.php'],
237*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'local.php'],
238*1da41c8bSAndreas Gohr                'protected' => [DOKU_CONF . 'local.protected.php']
239*1da41c8bSAndreas Gohr            ],
240*1da41c8bSAndreas Gohr            'acronyms' => [
241*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/acronyms.conf'],
242*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'acronyms.local.conf']
243*1da41c8bSAndreas Gohr            ],
244*1da41c8bSAndreas Gohr            'entities' => [
245*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/entities.conf'],
246*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'entities.local.conf']
247*1da41c8bSAndreas Gohr            ],
248*1da41c8bSAndreas Gohr            'interwiki' => [
249*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/interwiki.conf'],
250*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'interwiki.local.conf']
251*1da41c8bSAndreas Gohr            ],
252*1da41c8bSAndreas Gohr            'license' => [
253*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/license.php'],
254*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'license.local.php']
255*1da41c8bSAndreas Gohr            ],
256*1da41c8bSAndreas Gohr            'manifest' => [
257*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/manifest.json'],
258*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'manifest.local.json']
259*1da41c8bSAndreas Gohr            ],
260*1da41c8bSAndreas Gohr            'mediameta' => [
261*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/mediameta.php'],
262*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'mediameta.local.php']
263*1da41c8bSAndreas Gohr            ],
264*1da41c8bSAndreas Gohr            'mime' => [
265*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/mime.conf'],
266*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'mime.local.conf']
267*1da41c8bSAndreas Gohr            ],
268*1da41c8bSAndreas Gohr            'scheme' => [
269*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/scheme.conf'],
270*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'scheme.local.conf']
271*1da41c8bSAndreas Gohr            ],
272*1da41c8bSAndreas Gohr            'smileys' => [
273*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/smileys.conf'],
274*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'smileys.local.conf']
275*1da41c8bSAndreas Gohr            ],
276*1da41c8bSAndreas Gohr            'wordblock' => [
277*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/wordblock.conf'],
278*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'wordblock.local.conf']
279*1da41c8bSAndreas Gohr            ],
280*1da41c8bSAndreas Gohr            'acl' => [
281*1da41c8bSAndreas Gohr                'default' => DOKU_CONF . 'acl.auth.php'
282*1da41c8bSAndreas Gohr            ],
283*1da41c8bSAndreas Gohr            'plainauth.users' => [
284*1da41c8bSAndreas Gohr                'default' => DOKU_CONF . 'users.auth.php'
285*1da41c8bSAndreas Gohr            ],
286*1da41c8bSAndreas Gohr            'plugins' => [
287*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'conf/plugins.php'],
288*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'plugins.local.php'],
289*1da41c8bSAndreas Gohr                'protected' => [
290a646d519SAndreas Gohr                    DOKU_INC . 'conf/plugins.required.php',
291*1da41c8bSAndreas Gohr                    DOKU_CONF . 'plugins.protected.php'
292*1da41c8bSAndreas Gohr                ]
293*1da41c8bSAndreas Gohr            ],
294*1da41c8bSAndreas Gohr            'userstyle' => [
295*1da41c8bSAndreas Gohr                'screen' => [
296*1da41c8bSAndreas Gohr                    DOKU_CONF . 'userstyle.css',
297*1da41c8bSAndreas Gohr                    DOKU_CONF . 'userstyle.less'
298*1da41c8bSAndreas Gohr                ],
299*1da41c8bSAndreas Gohr                'print' => [
300*1da41c8bSAndreas Gohr                    DOKU_CONF . 'userprint.css',
301*1da41c8bSAndreas Gohr                    DOKU_CONF . 'userprint.less'
302*1da41c8bSAndreas Gohr                ],
303*1da41c8bSAndreas Gohr                'feed' => [
304*1da41c8bSAndreas Gohr                    DOKU_CONF . 'userfeed.css',
305*1da41c8bSAndreas Gohr                    DOKU_CONF . 'userfeed.less'
306*1da41c8bSAndreas Gohr                ],
307*1da41c8bSAndreas Gohr                'all' => [
308*1da41c8bSAndreas Gohr                    DOKU_CONF . 'userall.css',
309*1da41c8bSAndreas Gohr                    DOKU_CONF . 'userall.less'
310*1da41c8bSAndreas Gohr                ]
311*1da41c8bSAndreas Gohr            ],
312*1da41c8bSAndreas Gohr            'userscript' => [
313*1da41c8bSAndreas Gohr                'default' => [DOKU_CONF . 'userscript.js']
314*1da41c8bSAndreas Gohr            ],
315*1da41c8bSAndreas Gohr            'styleini' => [
316*1da41c8bSAndreas Gohr                'default' => [DOKU_INC . 'lib/tpl/%TEMPLATE%/' . 'style.ini'],
317*1da41c8bSAndreas Gohr                'local' => [DOKU_CONF . 'tpl/%TEMPLATE%/' . 'style.ini']
318*1da41c8bSAndreas Gohr            ]
319*1da41c8bSAndreas 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     */
327*1da41c8bSAndreas Gohr    protected function adjustCascade()
328*1da41c8bSAndreas 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
337*1da41c8bSAndreas Gohr            $append = [];
338*1da41c8bSAndreas Gohr            $prepend = [];
339a646d519SAndreas Gohr            if ($key == 'main') {
340*1da41c8bSAndreas Gohr                $append = [
341*1da41c8bSAndreas Gohr                    'default' => [DOKU_INC . 'conf/local.php'],
342*1da41c8bSAndreas Gohr                    'protected' => [DOKU_INC . 'lib/plugins/farmer/includes/config.php']
343*1da41c8bSAndreas Gohr                ];
344a646d519SAndreas Gohr            } elseif ($key == 'license') {
345*1da41c8bSAndreas Gohr                $append = [
346*1da41c8bSAndreas Gohr                    'default' => [DOKU_INC . 'conf/' . $key . '.local.php']
347*1da41c8bSAndreas Gohr                ];
348a646d519SAndreas Gohr            } elseif ($key == 'userscript') {
349*1da41c8bSAndreas Gohr                $prepend = [
350*1da41c8bSAndreas Gohr                    'default' => [DOKU_INC . 'conf/userscript.js']
351*1da41c8bSAndreas Gohr                ];
352a646d519SAndreas Gohr            } elseif ($key == 'userstyle') {
353*1da41c8bSAndreas Gohr                $prepend = [
354*1da41c8bSAndreas Gohr                    'screen' => [
355*1da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userstyle.css',
356*1da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userstyle.less'
357*1da41c8bSAndreas Gohr                    ],
358*1da41c8bSAndreas Gohr                    'print' => [
359*1da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userprint.css',
360*1da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userprint.less'
361*1da41c8bSAndreas Gohr                    ],
362*1da41c8bSAndreas Gohr                    'feed' => [
363*1da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userfeed.css',
364*1da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userfeed.less'
365*1da41c8bSAndreas Gohr                    ],
366*1da41c8bSAndreas Gohr                    'all' => [
367*1da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userall.css',
368*1da41c8bSAndreas Gohr                        DOKU_INC . 'conf/userall.less'
369*1da41c8bSAndreas Gohr                    ]
370*1da41c8bSAndreas Gohr                ];
37105ea7625SAnna Dabrowska            } elseif ($key == 'styleini') {
372*1da41c8bSAndreas Gohr                $append = [
373*1da41c8bSAndreas Gohr                    'local' => [DOKU_INC . 'conf/tpl/%TEMPLATE%/style.ini']
374*1da41c8bSAndreas Gohr                ];
3751272da0cSAndreas Gohr            } elseif ($key == 'users') {
3761272da0cSAndreas Gohr                $config_cascade['plainauth.users']['protected'] = DOKU_INC . 'conf/users.auth.php';
377af1c6dd8SAndreas Gohr            } elseif ($key == 'plugins') {
378*1da41c8bSAndreas Gohr                $append = [
379*1da41c8bSAndreas Gohr                    'default' => [DOKU_INC . 'conf/plugins.local.php']
380*1da41c8bSAndreas Gohr                ];
381a646d519SAndreas Gohr            } else {
382*1da41c8bSAndreas Gohr                $append = [
383*1da41c8bSAndreas Gohr                    'default' => [DOKU_INC . 'conf/' . $key . '.local.conf']
384*1da41c8bSAndreas Gohr                ];
385a646d519SAndreas Gohr            }
386a646d519SAndreas Gohr
387a646d519SAndreas Gohr            // add to cascade
388a646d519SAndreas Gohr            foreach ($prepend as $section => $data) {
389a646d519SAndreas Gohr                $config_cascade[$key][$section] = array_merge($data, $config_cascade[$key][$section]);
390a646d519SAndreas Gohr            }
391a646d519SAndreas Gohr            foreach ($append as $section => $data) {
392a646d519SAndreas Gohr                $config_cascade[$key][$section] = array_merge($config_cascade[$key][$section], $data);
393a646d519SAndreas Gohr            }
394a646d519SAndreas Gohr        }
395de156015SAndreas Gohr
396de156015SAndreas Gohr        // add plugin overrides
397de156015SAndreas Gohr        $config_cascade['plugins']['protected'][] = DOKU_INC . 'lib/plugins/farmer/includes/plugins.php';
398a646d519SAndreas Gohr    }
399a646d519SAndreas Gohr
400a646d519SAndreas Gohr    /**
401da0ae2c0SAndreas Gohr     * Loads the farm config
402da0ae2c0SAndreas Gohr     */
403*1da41c8bSAndreas Gohr    protected function loadConfig()
404*1da41c8bSAndreas Gohr    {
405da0ae2c0SAndreas Gohr        $ini = DOKU_INC . 'conf/farm.ini';
406da0ae2c0SAndreas Gohr        if (!file_exists($ini)) return;
407da0ae2c0SAndreas Gohr        $config = parse_ini_file($ini, true);
408da0ae2c0SAndreas Gohr        foreach (array_keys($this->config) as $section) {
409da0ae2c0SAndreas Gohr            if (isset($config[$section])) {
410da0ae2c0SAndreas Gohr                $this->config[$section] = array_merge(
411da0ae2c0SAndreas Gohr                    $this->config[$section],
412da0ae2c0SAndreas Gohr                    $config[$section]
413da0ae2c0SAndreas Gohr                );
414da0ae2c0SAndreas Gohr            }
415da0ae2c0SAndreas Gohr        }
416da0ae2c0SAndreas Gohr
417a646d519SAndreas Gohr        $this->config['base']['farmdir'] = trim($this->config['base']['farmdir']);
418a646d519SAndreas Gohr        $this->config['base']['farmhost'] = strtolower(trim($this->config['base']['farmhost']));
419a646d519SAndreas Gohr    }
420da0ae2c0SAndreas Gohr}
421da0ae2c0SAndreas Gohr
422da0ae2c0SAndreas Gohr// initialize it globally
42385becf1bSAndreas Gohrif (!defined('DOKU_UNITTEST')) {
424da0ae2c0SAndreas Gohr    global $FARMCORE;
425da0ae2c0SAndreas Gohr    $FARMCORE = new DokuWikiFarmCore();
42685becf1bSAndreas Gohr}
427