summaryrefslogtreecommitdiff
path: root/platform/www/lib/plugins/farmer/helper.php
blob: 53e71537fefb17235009054765042b721d704f8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
<?php
/**
 * DokuWiki Plugin farmer (Helper Component)
 *
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
 * @author  Michael Große <grosse@cosmocode.de>
 * @author  Andreas Gohr <gohr@cosmocode.de>
 */

// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();

class helper_plugin_farmer extends DokuWiki_Plugin {

    protected $defaultPluginState = null;
    protected $animalPluginState  = array();

    /**
     * Returns the name of the current animal if any, false otherwise
     *
     * @return string|false
     */
    public function getAnimal() {
        if(!isset($GLOBALS['FARMCORE'])) return false;
        return $GLOBALS['FARMCORE']->getAnimal();
    }

    /**
     * Get the farm config
     *
     * @return array
     */
    public function getConfig() {
        if(!isset($GLOBALS['FARMCORE'])) return array();
        return $GLOBALS['FARMCORE']->getConfig();
    }

    /**
     * Was the current animal requested by host?
     *
     * @return bool
     */
    public function isHostbased() {
        if(!isset($GLOBALS['FARMCORE'])) return false;
        return $GLOBALS['FARMCORE']->isHostbased();
    }

    /**
     * Was an animal requested that could not be found?
     *
     * @return bool
     */
    public function wasNotfound() {
        if(!isset($GLOBALS['FARMCORE'])) return false;
        return $GLOBALS['FARMCORE']->wasNotfound();
    }

    /**
     * Guess the URL for an animal
     *
     * @param $animal
     * @return string
     */
    public function getAnimalURL($animal) {
        $config = $this->getConfig();

        if(strpos($animal, '.') !== false) {
            return 'http://' . $animal;
        } elseif($config['base']['basedomain']) {
            return 'http://' . $animal . '.' . $config['base']['basedomain'];
        } else {
            return DOKU_URL . '!' . $animal . '/';
        }
    }

    /**
     * List of all animals, i.e. directories within DOKU_FARMDIR without the template.
     *
     * @return array
     */
    public function getAllAnimals() {
        $animals = array();
        $list = glob(DOKU_FARMDIR . '*/conf/', GLOB_ONLYDIR);
        foreach($list as $path) {
            $animal = basename(dirname($path));
            if($animal == '_animal') continue; // old template
            $animals[] = $animal;
        }
        sort($animals);
        return $animals;
    }

    /**
     * checks wether $path is in under $container
     *
     * Also returns false if $path and $container are the same directory
     *
     * @param string $path
     * @param string $container
     * @return bool
     */
    public function isInPath($path, $container) {
        $path = fullpath($path).'/';
        $container = fullpath($container).'/';
        if($path == $container) return false;
        return (strpos($path, $container) === 0);
    }

    /**
     * Check if the farm is correctly configured for this farmer plugin
     *
     * @return bool
     */
    public function checkFarmSetup() {
        return defined('DOKU_FARMDIR') && isset($GLOBALS['FARMCORE']);
    }

    /**
     * @param string $animalname
     *
     * @return bool
     */
    public function validateAnimalName($animalname) {
        return preg_match("/^[a-z0-9]+([\\.\\-][a-z0-9]+)*$/i", $animalname) === 1;
    }

    /**
     * Copy a file, or recursively copy a folder and its contents. Adapted for DokuWiki.
     *
     * @todo: needs tests
     *
     * @author      Aidan Lister <aidan@php.net>
     * @author      Michael Große <grosse@cosmocode.de>
     * @author      Andreas Gohr <gohr@cosmocode.de>
     * @link        http://aidanlister.com/2004/04/recursively-copying-directories-in-php/
     *
     * @param string $source Source path
     * @param string $destination Destination path
     * @param string $exclude Regular expression to exclude files or directories (complete with delimiters)
     * @return bool Returns TRUE on success, FALSE on failure
     */
    function io_copyDir($source, $destination, $exclude = '') {
        if($exclude && preg_match($exclude, $source)) {
            return true;
        }

        if(is_link($source)) {
            io_lock($destination);
            $result = symlink(readlink($source), $destination);
            io_unlock($destination);
            return $result;
        }

        if(is_file($source)) {
            io_lock($destination);
            $result = copy($source, $destination);
            io_unlock($destination);
            return $result;
        }

        if(!is_dir($destination)) {
            io_mkdir_p($destination);
        }

        $dir = @dir($source);
        if($dir === false) return false;
        while(false !== ($entry = $dir->read())) {
            if($entry == '.' || $entry == '..') {
                continue;
            }

            // recurse into directories
            $this->io_copyDir("$source/$entry", "$destination/$entry", $exclude);
        }

        $dir->close();
        return true;
    }

    /**
     * get a list of all Plugins installed in the farmer wiki, regardless whether they are active or not.
     *
     * @param bool $all get all plugins, even disabled ones
     * @return array
     */
    public function getAllPlugins($all = true) {

        /** @var Doku_Plugin_Controller $plugin_controller */
        global $plugin_controller;

        $plugins = $plugin_controller->getList('', $all);

        // filter out a few plugins
        $plugins = array_filter(
            $plugins, function ($item) {
            if($item == 'farmer') return false;
            if($item == 'extension') return false;
            if($item == 'upgrade') return false;
            if($item == 'testing') return false;
            return true;
        }
        );

        sort($plugins);
        return $plugins;
    }

    /**
     * Get the plugin states configured locally in the given animal
     *
     * Response is cached
     *
     * @param $animal
     * @return array
     */
    public function getAnimalPluginLocalStates($animal) {
        if(isset($this->animalPluginState[$animal])) return $this->animalPluginState[$animal];

        $localfile = DOKU_FARMDIR . $animal . '/conf/plugins.local.php';
        $plugins = array();
        if(file_exists($localfile)) {
            include($localfile);
        }

        $this->animalPluginState[$animal] = $plugins;
        return $plugins;
    }

    /**
     * Return the default state plugins would have in animals
     *
     * Response is cached
     *
     * @return array
     */
    public function getDefaultPluginStates() {
        if(!is_null($this->defaultPluginState)) return $this->defaultPluginState;

        $farmconf = $this->getConfig();
        $all = $this->getAllPlugins();

        $plugins = array();
        foreach($all as $one) {
            if($farmconf['inherit']['plugins']) {
                $plugins[$one] = !plugin_isdisabled($one);
            } else {
                $plugins[$one] = true; // default state is enabled
            }
        }

        ksort($plugins);
        $this->defaultPluginState = $plugins;
        return $plugins;
    }

    /**
     * Return a structure giving detailed info about the state of all plugins in an animal
     *
     * @param $animal
     * @return array
     */
    public function getAnimalPluginRealState($animal) {
        $info = array();

        $defaults = $this->getDefaultPluginStates();
        $local = $this->getAnimalPluginLocalStates($animal);

        foreach($defaults as $plugin => $set) {
            $current = array(
                'name' => $plugin,
                'default' => $set,
                'actual' => $set,
                'isdefault' => true
            );

            if(isset($local[$plugin])) {
                $current['actual'] = (bool) $local[$plugin];
                $current['isdefault'] = false;
            }

            $info[$plugin] = $current;
        }

        ksort($info);
        return $info;
    }

    /**
     * Set the state of a plugin in an animal
     *
     * @param string $plugin
     * @param string $animal
     * @param int $state -1 = default, 1 = enabled, 0 = disabled
     */
    public function setPluginState($plugin, $animal, $state) {
        $state = (int) $state;

        $plugins = $this->getAnimalPluginLocalStates($animal);
        if($state < 0) {
            if(isset($plugins[$plugin])) unset($plugins[$plugin]);
        } else {
            $plugins[$plugin] = $state;
        }

        $this->writePluginConf($plugins, $animal);

        // clear state cache
        if(isset($this->animalPluginState[$animal])) unset($this->animalPluginState[$animal]);
    }

    /**
     * Write the list of (deactivated) plugins as plugin configuration of an animal to file
     *
     * updates the plugin state cache
     *
     * @param array $plugins associative array with the key being the plugin name and the value 0 or 1
     * @param string $animal Directory of the animal within DOKU_FARMDIR
     */
    public function writePluginConf($plugins, $animal) {
        $pluginConf = '<?php' . "\n# plugins enabled and disabled by the farmer plugin\n";
        foreach($plugins as $plugin => $status) {
            $pluginConf .= '$plugins[\'' . $plugin . '\'] = ' . $status . ";\n";
        }
        io_saveFile(DOKU_FARMDIR . $animal . '/conf/plugins.local.php', $pluginConf);
        touch(DOKU_FARMDIR . $animal . '/conf/local.php');

        if(function_exists('opcache_invalidate')) {
            opcache_invalidate(DOKU_FARMDIR . $animal . '/conf/plugins.local.php');
            opcache_invalidate(DOKU_FARMDIR . $animal . '/conf/local.php');
        }

        $this->animalPluginState[$animal] = $plugins;
    }
}