xref: /plugin/farmer/helper.php (revision 632c5618770a957e69c8313b2a509bb6c25da282)
1bc461538SMichael Große<?php
2bc461538SMichael Große/**
3bc461538SMichael Große * DokuWiki Plugin farmer (Helper Component)
4bc461538SMichael Große *
5bc461538SMichael Große * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6bc461538SMichael Große * @author  Michael Große <grosse@cosmocode.de>
7bc461538SMichael Große */
8bc461538SMichael Große
9bc461538SMichael Große// must be run within Dokuwiki
10bc461538SMichael Großeif(!defined('DOKU_INC')) die();
11bc461538SMichael Große
12bc461538SMichael Großeclass helper_plugin_farmer extends DokuWiki_Plugin {
13bc461538SMichael Große
14fcbe16a4SMichael Große    private $allPlugins = array();
15fcbe16a4SMichael Große
16bc461538SMichael Große    /**
17*632c5618SAndreas Gohr     * Returns the name of the current animal if any, false otherwise
18*632c5618SAndreas Gohr     *
19*632c5618SAndreas Gohr     * @return string|false
20*632c5618SAndreas Gohr     */
21*632c5618SAndreas Gohr    public function getAnimal() {
22*632c5618SAndreas Gohr        if(defined('DOKU_FARM_ANIMAL')) return DOKU_FARM_ANIMAL;
23*632c5618SAndreas Gohr        return false;
24*632c5618SAndreas Gohr    }
25*632c5618SAndreas Gohr
26*632c5618SAndreas Gohr    /**
27bc461538SMichael Große     * Copy a file, or recursively copy a folder and its contents. Adapted for DokuWiki.
28bc461538SMichael Große     *
29bc461538SMichael Große     * @todo: needs tests
30bc461538SMichael Große     *
31bc461538SMichael Große     * @author      Aidan Lister <aidan@php.net>
32bc461538SMichael Große     * @author      Michael Große <grosse@cosmocode.de>
33bc461538SMichael Große     * @version     1.0.1
34bc461538SMichael Große     * @link        http://aidanlister.com/2004/04/recursively-copying-directories-in-php/
35bc461538SMichael Große     *
36bc461538SMichael Große     * @param       string $source       Source path
37bc461538SMichael Große     * @param       string $destination  Destination path
38bc461538SMichael Große     *
39bc461538SMichael Große     * @return      bool     Returns TRUE on success, FALSE on failure
40bc461538SMichael Große     */
41bc461538SMichael Große    function io_copyDir($source, $destination) {
42bc461538SMichael Große        if (is_link($source)) {
43bc461538SMichael Große            io_lock($destination);
44bc461538SMichael Große            $result=symlink(readlink($source), $destination);
45bc461538SMichael Große            io_unlock($destination);
46bc461538SMichael Große            return $result;
47bc461538SMichael Große        }
48bc461538SMichael Große
49bc461538SMichael Große        if (is_file($source)) {
50bc461538SMichael Große            io_lock($destination);
51bc461538SMichael Große            $result=copy($source, $destination);
52bc461538SMichael Große            io_unlock($destination);
53bc461538SMichael Große            return $result;
54bc461538SMichael Große        }
55bc461538SMichael Große
56bc461538SMichael Große        if (!is_dir($destination)) {
57bc461538SMichael Große            io_mkdir_p($destination);
58bc461538SMichael Große        }
59bc461538SMichael Große
60bc461538SMichael Große        $dir = dir($source);
61bc461538SMichael Große        while (false !== ($entry = $dir->read())) {
62bc461538SMichael Große            if ($entry == '.' || $entry == '..') {
63bc461538SMichael Große                continue;
64bc461538SMichael Große            }
65bc461538SMichael Große
66bc461538SMichael Große            // recurse into directories
67bc461538SMichael Große            $this->io_copyDir("$source/$entry", "$destination/$entry");
68bc461538SMichael Große        }
69bc461538SMichael Große
70bc461538SMichael Große        $dir->close();
71bc461538SMichael Große        return true;
72bc461538SMichael Große    }
73bc461538SMichael Große
7416bbfe4bSMichael Große    /**
7516bbfe4bSMichael Große     * get a list of all Plugins installed in the farmer wiki, regardless whether they are active or not.
7616bbfe4bSMichael Große     *
7716bbfe4bSMichael Große     * @return array
7816bbfe4bSMichael Große     */
790b96e6d7SMichael Große    public function getAllPlugins() {
800b96e6d7SMichael Große        $dir = dir(DOKU_PLUGIN);
810b96e6d7SMichael Große        $plugins = array();
820b96e6d7SMichael Große        while (false !== ($entry = $dir->read())) {
833949d8a1SMichael Große            if($entry == '.' || $entry == '..' || $entry == 'testing' || $entry == 'farmer') {
840b96e6d7SMichael Große                continue;
850b96e6d7SMichael Große            }
860b96e6d7SMichael Große            if (!is_dir(DOKU_PLUGIN ."/$entry")) {
870b96e6d7SMichael Große                continue;
880b96e6d7SMichael Große            }
890b96e6d7SMichael Große            $plugins[] = $entry;
900b96e6d7SMichael Große        }
916ec1ad8fSMichael Große        sort($plugins);
920b96e6d7SMichael Große        return $plugins;
930b96e6d7SMichael Große    }
940b96e6d7SMichael Große
9516bbfe4bSMichael Große    /**
9616bbfe4bSMichael Große     * List of all animals, i.e. directories within DOKU_FARMDIR without the template.
9716bbfe4bSMichael Große     *
9816bbfe4bSMichael Große     * @return array
9916bbfe4bSMichael Große     */
1000b96e6d7SMichael Große    public function getAllAnimals() {
1010b96e6d7SMichael Große        $animals = array();
1020b96e6d7SMichael Große
1030b96e6d7SMichael Große        $dir = dir(DOKU_FARMDIR);
1040b96e6d7SMichael Große        while (false !== ($entry = $dir->read())) {
105a0fc814bSMichael Große            if ($entry == '.' || $entry == '..' || $entry == '_animal' || $entry == '.htaccess') {
106a0fc814bSMichael Große                continue;
107a0fc814bSMichael Große            }
108a0fc814bSMichael Große            if (!is_dir(DOKU_FARMDIR . $entry)) {
1090b96e6d7SMichael Große                continue;
1100b96e6d7SMichael Große            }
1110b96e6d7SMichael Große            $animals[] = $entry;
1120b96e6d7SMichael Große        }
1130b96e6d7SMichael Große        $dir->close();
1140b96e6d7SMichael Große        return $animals;
1150b96e6d7SMichael Große    }
1160b96e6d7SMichael Große
11716bbfe4bSMichael Große    /**
11816bbfe4bSMichael Große     * Actiate a specific plugin in a specific animal
11916bbfe4bSMichael Große     *
12016bbfe4bSMichael Große     * @param string $plugin Name of the plugin to be activated
12116bbfe4bSMichael Große     * @param string $animal Directory of the animal within DOKU_FARMDIR
12216bbfe4bSMichael Große     */
123fcbe16a4SMichael Große    public function activatePlugin($plugin, $animal) {
124fcbe16a4SMichael Große        if (isset($this->allPlugins[$animal])) {
125fcbe16a4SMichael Große            $plugins = $this->allPlugins[$animal];
126fcbe16a4SMichael Große        } else {
127fcbe16a4SMichael Große            include(DOKU_FARMDIR . $animal . '/conf/plugins.local.php');
128fcbe16a4SMichael Große        }
129fcbe16a4SMichael Große        if (isset($plugins[$plugin]) && $plugins[$plugin] === 0) {
130fcbe16a4SMichael Große            unset($plugins[$plugin]);
131fcbe16a4SMichael Große            $this->writePluginConf($plugins, $animal);
132fcbe16a4SMichael Große        }
133fcbe16a4SMichael Große        $this->allPlugins[$animal] = $plugins;
134fcbe16a4SMichael Große    }
135fcbe16a4SMichael Große
136a0fc814bSMichael Große    /**
13716bbfe4bSMichael Große     * @param string $plugin Name of the plugin to be deactivated
13816bbfe4bSMichael Große     * @param string $animal Directory of the animal within DOKU_FARMDIR
139a0fc814bSMichael Große     */
140fcbe16a4SMichael Große    public function deactivatePlugin($plugin, $animal) {
141fcbe16a4SMichael Große        if (isset($this->allPlugins[$animal])) {
142fcbe16a4SMichael Große            $plugins = $this->allPlugins[$animal];
143fcbe16a4SMichael Große        } else {
144fcbe16a4SMichael Große            include(DOKU_FARMDIR . $animal . '/conf/plugins.local.php');
145fcbe16a4SMichael Große        }
146fcbe16a4SMichael Große        if (!isset($plugins[$plugin]) || $plugins[$plugin] !== 0) {
147fcbe16a4SMichael Große            $plugins[$plugin] = 0;
148fcbe16a4SMichael Große            $this->writePluginConf($plugins, $animal);
149fcbe16a4SMichael Große        }
150fcbe16a4SMichael Große        $this->allPlugins[$animal] = $plugins;
151fcbe16a4SMichael Große    }
152fcbe16a4SMichael Große
15316bbfe4bSMichael Große    /**
15416bbfe4bSMichael Große     * Write the list of (deactivated) plugins as plugin configuration of an animal to file
15516bbfe4bSMichael Große     *
15616bbfe4bSMichael Große     * @param array  $plugins associative array with the key being the plugin name and the value 0 or 1
15716bbfe4bSMichael Große     * @param string $animal  Directory of the animal within DOKU_FARMDIR
15816bbfe4bSMichael Große     */
159fcbe16a4SMichael Große    public function writePluginConf($plugins, $animal) {
160fcbe16a4SMichael Große        $pluginConf = '<?php' . "\n";
161fcbe16a4SMichael Große        foreach ($plugins as $plugin => $status) {
162fcbe16a4SMichael Große            $pluginConf .= '$plugins["' . $plugin  . '"] = ' . $status . ";\n";
163fcbe16a4SMichael Große        }
164fcbe16a4SMichael Große        io_saveFile(DOKU_FARMDIR . $animal . '/conf/plugins.local.php', $pluginConf);
165fcbe16a4SMichael Große        touch(DOKU_FARMDIR . $animal . '/conf/local.php');
166fcbe16a4SMichael Große    }
167fcbe16a4SMichael Große
16816bbfe4bSMichael Große    /**
16916bbfe4bSMichael Große     * Show a message for all errors which occured during form validation
17016bbfe4bSMichael Große     *
17116bbfe4bSMichael Große     * @param \dokuwiki\Form\Form $form        The form to which the errors should be added.
17216bbfe4bSMichael Große     * @param array               $errorArray  An associative array with the key being the name of the element at fault
17316bbfe4bSMichael Große     *                                         and the value being the associated error message.
17416bbfe4bSMichael Große     */
175a12b96c0SMichael Große    public function addErrorsToForm(\dokuwiki\Form\Form &$form, $errorArray) {
176628ea26fSMichael Große        foreach ($errorArray as $elementName => $errorMessage) {
177628ea26fSMichael Große            $offset = 0;
178628ea26fSMichael Große            msg($errorMessage, -1);
179628ea26fSMichael Große            while ($form->findPositionByAttribute('name',$elementName, $offset)) {
180628ea26fSMichael Große                $offset = $form->findPositionByAttribute('name',$elementName, $offset);
181628ea26fSMichael Große                $form->getElementAt($offset)->addClass('error');
182628ea26fSMichael Große                ++$offset;
183a12b96c0SMichael Große            }
184a12b96c0SMichael Große        }
185a12b96c0SMichael Große    }
186a12b96c0SMichael Große
18716bbfe4bSMichael Große    /**
18816bbfe4bSMichael Große     * @param string|null $page load adminpage $page, reload the current page if $page is ommited or null
18916bbfe4bSMichael Große     */
1904d120480SMichael Große    public function reloadAdminPage($page = null) {
1914d120480SMichael Große        global $ID;
1924d120480SMichael Große        $get = $_GET;
1934d120480SMichael Große        if(isset($get['id'])) unset($get['id']);
1944d120480SMichael Große        if ($page !== null ) {
1954d120480SMichael Große            $get['page'] = $page;
1964d120480SMichael Große        }
1974d120480SMichael Große        $self = wl($ID, $get, false, '&');
1984d120480SMichael Große        send_redirect($self);
1994d120480SMichael Große    }
2004d120480SMichael Große
20116bbfe4bSMichael Große    /**
20216bbfe4bSMichael Große     * Download and extract the animal template
20316bbfe4bSMichael Große     *
20416bbfe4bSMichael Große     * @param string $animalpath
20516bbfe4bSMichael Große     *
20616bbfe4bSMichael Große     * @throws \splitbrain\PHPArchive\ArchiveIOException
20716bbfe4bSMichael Große     */
20879435a6fSMichael Große    public function downloadTemplate($animalpath) {
20979435a6fSMichael Große        file_put_contents($animalpath . '/_animal.zip',fopen('https://www.dokuwiki.org/_media/dokuwiki_farm_animal.zip','r'));
210c9fd7b89SMichael Große        $zip = new splitbrain\PHPArchive\Zip();
21179435a6fSMichael Große        $zip->open($animalpath.'/_animal.zip');
212c9fd7b89SMichael Große        $zip->extract($animalpath);
21379435a6fSMichael Große        $zip->close();
21479435a6fSMichael Große        unlink($animalpath.'/_animal.zip');
21579435a6fSMichael Große    }
21679435a6fSMichael Große
217efa7af45SMichael Große    /**
218*632c5618SAndreas Gohr     * checks wether $path is in under $container
219efa7af45SMichael Große     *
220*632c5618SAndreas Gohr     * @param string $path
221*632c5618SAndreas Gohr     * @param string $container
222efa7af45SMichael Große     * @return bool
223efa7af45SMichael Große     */
224efa7af45SMichael Große    public function isInPath ($path, $container) {
225*632c5618SAndreas Gohr        return (strpos(fullpath($path), fullpath($container)) === 0);
226efa7af45SMichael Große    }
227efa7af45SMichael Große
228d9ec4524SMichael Große    /**
22916bbfe4bSMichael Große     * Check if the farm is correctly configured for this farmer plugin
23016bbfe4bSMichael Große     *
231d9ec4524SMichael Große     * @return bool
232d9ec4524SMichael Große     */
233d9ec4524SMichael Große    public function checkFarmSetup () {
234*632c5618SAndreas Gohr        return defined('DOKU_FARMDIR');
235d9ec4524SMichael Große    }
236d9ec4524SMichael Große
23780ef674eSMichael Große    /**
23880ef674eSMichael Große     * The subdomain must contain at least two dots
23980ef674eSMichael Große     *
24080ef674eSMichael Große     * @link http://stackoverflow.com/questions/17986371/regular-expression-to-validate-fqdn-in-c-sharp-and-javascript
24180ef674eSMichael Große     *
24280ef674eSMichael Große     * @param string $subdomain
24380ef674eSMichael Große     *
24480ef674eSMichael Große     * @return bool
24580ef674eSMichael Große     */
24680ef674eSMichael Große    public function validateSubdomain ($subdomain) {
24780ef674eSMichael Große        return preg_match("/^(?=.{1,254}$)((?=[a-z0-9-]{1,63}\.)(xn--+)?[a-z0-9]+(-[a-z0-9]+)*\.){2,}[a-z]{2,63}$/i",$subdomain) === 1;
24880ef674eSMichael Große    }
24980ef674eSMichael Große
250909f2ff6SMichael Große    /**
251909f2ff6SMichael Große     * @param string $animalname
252909f2ff6SMichael Große     *
253909f2ff6SMichael Große     * @return bool
254909f2ff6SMichael Große     */
255909f2ff6SMichael Große    public function validateAnimalName ($animalname) {
256909f2ff6SMichael Große        return preg_match("/^[a-z0-9]+(-[a-z0-9]+)*$/i",$animalname) === 1;
257909f2ff6SMichael Große    }
258909f2ff6SMichael Große
259c66a21e9SMichael Große    /**
260c66a21e9SMichael Große     * @return string
261c66a21e9SMichael Große     */
262c66a21e9SMichael Große    public function getUserLine($currentAdmin) {
263c66a21e9SMichael Große        $masterUsers = file_get_contents(DOKU_CONF . 'users.auth.php');
264c66a21e9SMichael Große        $masterUsers = ltrim(strstr($masterUsers, "\n" . $currentAdmin . ":"));
265c66a21e9SMichael Große        $newAdmin = substr($masterUsers, 0, strpos($masterUsers, "\n") + 1);
266c66a21e9SMichael Große        return $newAdmin;
267c66a21e9SMichael Große    }
268c66a21e9SMichael Große
269bc461538SMichael Große}
270