xref: /plugin/farmer/admin/new.php (revision 65e7bfd16afbefa80e1df5ba4341a6fd74f734c6)
149f2871cSAndreas Gohr<?php
249f2871cSAndreas Gohr/**
349f2871cSAndreas Gohr * DokuWiki Plugin farmer (Admin Component)
449f2871cSAndreas Gohr *
549f2871cSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
649f2871cSAndreas Gohr * @author  Michael Große <grosse@cosmocode.de>
749f2871cSAndreas Gohr */
849f2871cSAndreas Gohr
949f2871cSAndreas Gohr// must be run within Dokuwiki
1049f2871cSAndreas Gohrif(!defined('DOKU_INC')) die();
1149f2871cSAndreas Gohr
1249f2871cSAndreas Gohrclass admin_plugin_farmer_new extends DokuWiki_Admin_Plugin {
1349f2871cSAndreas Gohr
1449f2871cSAndreas Gohr    /** @var helper_plugin_farmer $helper */
1549f2871cSAndreas Gohr    protected $helper;
1649f2871cSAndreas Gohr
1749f2871cSAndreas Gohr    /**
1849f2871cSAndreas Gohr     * @return bool true if only access for superuser, false is for superusers and moderators
1949f2871cSAndreas Gohr     */
2049f2871cSAndreas Gohr    public function forAdminOnly() {
2149f2871cSAndreas Gohr        return true;
2249f2871cSAndreas Gohr    }
2349f2871cSAndreas Gohr
2449f2871cSAndreas Gohr    /**
2549f2871cSAndreas Gohr     * admin_plugin_farmer_new constructor.
2649f2871cSAndreas Gohr     */
2749f2871cSAndreas Gohr    public function __construct() {
2849f2871cSAndreas Gohr        $this->helper = plugin_load('helper', 'farmer');
2949f2871cSAndreas Gohr    }
3049f2871cSAndreas Gohr
3149f2871cSAndreas Gohr    /**
3249f2871cSAndreas Gohr     * Should carry out any processing required by the plugin.
3349f2871cSAndreas Gohr     */
3449f2871cSAndreas Gohr    public function handle() {
3549f2871cSAndreas Gohr        global $INPUT;
3649f2871cSAndreas Gohr        global $ID;
3749f2871cSAndreas Gohr        if(!$INPUT->has('farmer__submit')) return;
3849f2871cSAndreas Gohr
3949f2871cSAndreas Gohr        $data = $this->validateAnimalData();
4049f2871cSAndreas Gohr        if(!$data) return;
41801ebaa1SAndreas Gohr        if($this->createNewAnimal($data['name'], $data['admin'], $data['pass'], $data['template'])) {
420336ab2aSAndreas Gohr            $url = $this->helper->getAnimalURL($data['name']);
430336ab2aSAndreas Gohr            $link = '<a href="' . $url . '">' . hsc($data['name']) . '</a>';
440336ab2aSAndreas Gohr
450336ab2aSAndreas Gohr            msg(sprintf($this->getLang('animal creation success'), $link), 1);
4649f2871cSAndreas Gohr            $link = wl($ID, array('do' => 'admin', 'page' => 'farmer', 'sub' => 'new'), true, '&');
4749f2871cSAndreas Gohr            send_redirect($link);
4849f2871cSAndreas Gohr        }
4949f2871cSAndreas Gohr    }
5049f2871cSAndreas Gohr
5149f2871cSAndreas Gohr    /**
5249f2871cSAndreas Gohr     * Render HTML output, e.g. helpful text and a form
5349f2871cSAndreas Gohr     */
5449f2871cSAndreas Gohr    public function html() {
551272da0cSAndreas Gohr        $farmconfig = $this->helper->getConfig();
5649f2871cSAndreas Gohr
5749f2871cSAndreas Gohr        $form = new \dokuwiki\Form\Form();
5849f2871cSAndreas Gohr        $form->addClass('plugin_farmer')->id('farmer__create_animal_form');
5949f2871cSAndreas Gohr
6049f2871cSAndreas Gohr        $form->addFieldsetOpen($this->getLang('animal configuration'));
6123164e01SAndreas Gohr        $form->addTextInput('animalname', $this->getLang('animal'));
6249f2871cSAndreas Gohr        $form->addFieldsetClose();
6349f2871cSAndreas Gohr
64801ebaa1SAndreas Gohr        $animals = $this->helper->getAllAnimals();
65801ebaa1SAndreas Gohr        array_unshift($animals, '');
66801ebaa1SAndreas Gohr        $form->addFieldsetOpen($this->getLang('animal template'));
67801ebaa1SAndreas Gohr        $form->addDropdown('animaltemplate', $animals)->addClass('farmer_choosen_animals');
68801ebaa1SAndreas Gohr        $form->addFieldsetClose();
69801ebaa1SAndreas Gohr
7049f2871cSAndreas Gohr        $form->addFieldsetOpen($this->getLang('animal administrator'));
711272da0cSAndreas Gohr        $btn = $form->addRadioButton('adminsetup', $this->getLang('noUsers'))->val('noUsers');
721272da0cSAndreas Gohr        if($farmconfig['inherit']['users']) {
731272da0cSAndreas Gohr            $btn->attr('checked', 'checked');  // default when inherit available
741272da0cSAndreas Gohr        }
7549f2871cSAndreas Gohr        $form->addRadioButton('adminsetup', $this->getLang('importUsers'))->val('importUsers');
7649f2871cSAndreas Gohr        $form->addRadioButton('adminsetup', $this->getLang('currentAdmin'))->val('currentAdmin');
771272da0cSAndreas Gohr        $btn = $form->addRadioButton('adminsetup', $this->getLang('newAdmin'))->val('newAdmin');
781272da0cSAndreas Gohr        if(!$farmconfig['inherit']['users']) {
791272da0cSAndreas Gohr            $btn->attr('checked', 'checked'); // default when inherit not available
801272da0cSAndreas Gohr        }
8149f2871cSAndreas Gohr        $form->addPasswordInput('adminPassword', $this->getLang('admin password'));
8249f2871cSAndreas Gohr        $form->addFieldsetClose();
8349f2871cSAndreas Gohr
8449f2871cSAndreas Gohr        $form->addButton('farmer__submit', $this->getLang('submit'))->attr('type', 'submit')->val('newAnimal');
8549f2871cSAndreas Gohr        echo $form->toHTML();
8649f2871cSAndreas Gohr    }
8749f2871cSAndreas Gohr
8849f2871cSAndreas Gohr    /**
8949f2871cSAndreas Gohr     * Validate the data for a new animal
9049f2871cSAndreas Gohr     *
9149f2871cSAndreas Gohr     * @return array|bool false on errors, clean data otherwise
9249f2871cSAndreas Gohr     */
9349f2871cSAndreas Gohr    protected function validateAnimalData() {
9449f2871cSAndreas Gohr        global $INPUT;
9549f2871cSAndreas Gohr
9649f2871cSAndreas Gohr        $animalname = $INPUT->filter('trim')->str('animalname');
9749f2871cSAndreas Gohr        $adminsetup = $INPUT->str('adminsetup');
9849f2871cSAndreas Gohr        $adminpass = $INPUT->filter('trim')->str('adminPassword');
99801ebaa1SAndreas Gohr        $template = $INPUT->filter('trim')->str('animaltemplate');
10049f2871cSAndreas Gohr
10149f2871cSAndreas Gohr        $errors = array();
10249f2871cSAndreas Gohr
10349f2871cSAndreas Gohr        if($animalname === '') {
10449f2871cSAndreas Gohr            $errors[] = $this->getLang('animalname_missing');
10549f2871cSAndreas Gohr        } elseif(!$this->helper->validateAnimalName($animalname)) {
10649f2871cSAndreas Gohr            $errors[] = $this->getLang('animalname_invalid');
10749f2871cSAndreas Gohr        }
10849f2871cSAndreas Gohr
10949f2871cSAndreas Gohr        if($adminsetup === 'newAdmin' && $adminpass === '') {
11049f2871cSAndreas Gohr            $errors[] = $this->getLang('adminPassword_empty');
11149f2871cSAndreas Gohr        }
11249f2871cSAndreas Gohr
11349f2871cSAndreas Gohr        if($animalname !== '' && file_exists(DOKU_FARMDIR . '/' . $animalname)) {
11449f2871cSAndreas Gohr            $errors[] = $this->getLang('animalname_preexisting');
11549f2871cSAndreas Gohr        }
11649f2871cSAndreas Gohr
11749f2871cSAndreas Gohr        if($errors) {
11849f2871cSAndreas Gohr            foreach($errors as $error) {
11949f2871cSAndreas Gohr                msg($error, -1);
12049f2871cSAndreas Gohr            }
12149f2871cSAndreas Gohr            return false;
12249f2871cSAndreas Gohr        }
12349f2871cSAndreas Gohr
124801ebaa1SAndreas Gohr        if(!is_dir(DOKU_FARMDIR . '/' . $template)) {
125801ebaa1SAndreas Gohr            $template = '';
126801ebaa1SAndreas Gohr        }
127801ebaa1SAndreas Gohr
12849f2871cSAndreas Gohr        return array(
12949f2871cSAndreas Gohr            'name' => $animalname,
13049f2871cSAndreas Gohr            'admin' => $adminsetup,
131801ebaa1SAndreas Gohr            'pass' => $adminpass,
132801ebaa1SAndreas Gohr            'template' => $template
13349f2871cSAndreas Gohr        );
13449f2871cSAndreas Gohr    }
13549f2871cSAndreas Gohr
13649f2871cSAndreas Gohr    /**
13749f2871cSAndreas Gohr     * Create a new animal
13849f2871cSAndreas Gohr     *
13949f2871cSAndreas Gohr     * @param string $name name/title of the animal, will be the directory name for htaccess setup
14049f2871cSAndreas Gohr     * @param string $adminSetup newAdmin, currentAdmin or importUsers
14149f2871cSAndreas Gohr     * @param string $adminPassword required if $adminSetup is newAdmin
142801ebaa1SAndreas Gohr     * @param string $template name of animal to copy
14349f2871cSAndreas Gohr     * @return bool true if successful
14449f2871cSAndreas Gohr     */
145801ebaa1SAndreas Gohr    protected function createNewAnimal($name, $adminSetup, $adminPassword, $template) {
14649f2871cSAndreas Gohr        $animaldir = DOKU_FARMDIR . '/' . $name;
14749f2871cSAndreas Gohr
14849f2871cSAndreas Gohr        // copy basic template
14949f2871cSAndreas Gohr        $ok = $this->helper->io_copyDir(__DIR__ . '/../_animal', $animaldir);
15049f2871cSAndreas Gohr        if(!$ok) {
15149f2871cSAndreas Gohr            msg($this->getLang('animal creation error'), -1);
15249f2871cSAndreas Gohr            return false;
15349f2871cSAndreas Gohr        }
15449f2871cSAndreas Gohr
155801ebaa1SAndreas Gohr        // copy animal template
156801ebaa1SAndreas Gohr        if($template != '') {
157801ebaa1SAndreas Gohr            foreach(array('conf', 'data/pages', 'data/media', 'data/meta', 'data/media_meta', 'index') as $dir) {
158801ebaa1SAndreas Gohr                $templatedir = DOKU_FARMDIR . '/' . $template . '/' . $dir;
159801ebaa1SAndreas Gohr                if(!is_dir($templatedir)) continue;
160801ebaa1SAndreas Gohr                // do not copy changelogs in meta
161801ebaa1SAndreas Gohr                if(substr($dir, -4) == 'meta') {
162801ebaa1SAndreas Gohr                    $exclude = '/\.changes$/';
163801ebaa1SAndreas Gohr                } else {
164801ebaa1SAndreas Gohr                    $exclude = '';
165801ebaa1SAndreas Gohr                }
166801ebaa1SAndreas Gohr                if(!$this->helper->io_copyDir($templatedir, $animaldir . '/' . $dir, $exclude)) {
167801ebaa1SAndreas Gohr                    msg(sprintf($this->getLang('animal template copy error'), $dir), -1);
168801ebaa1SAndreas Gohr                    // we go on anyway
169801ebaa1SAndreas Gohr                }
170801ebaa1SAndreas Gohr            }
171801ebaa1SAndreas Gohr        }
172801ebaa1SAndreas Gohr
17349f2871cSAndreas Gohr        // append title to local config
17449f2871cSAndreas Gohr        $ok &= io_saveFile($animaldir . '/conf/local.php', "\n" . '$conf[\'title\'] = \'' . $name . '\';' . "\n", true);
17549f2871cSAndreas Gohr
1764eba53bcSAndreas Gohr        // create a random logo and favicon
1774eba53bcSAndreas Gohr        if(!class_exists('\splitbrain\RingIcon\RingIcon', false)) {
1784eba53bcSAndreas Gohr            require(__DIR__ . '/../3rdparty/RingIcon.php');
1794eba53bcSAndreas Gohr        }
1804eba53bcSAndreas Gohr        if(!class_exists('\chrisbliss18\phpico\PHPIco', false)) {
1814eba53bcSAndreas Gohr            require(__DIR__ . '/../3rdparty/PHPIco.php');
1824eba53bcSAndreas Gohr        }
1834eba53bcSAndreas Gohr        try {
1844eba53bcSAndreas Gohr            $ringicon = new \splitbrain\RingIcon\RingIcon(64);
1854eba53bcSAndreas Gohr            $ringicon->createImage($animaldir, $animaldir . '/data/media/wiki/logo.png');
1864eba53bcSAndreas Gohr            $icongen = new \chrisbliss18\phpico\PHPIco($animaldir . '/data/media/wiki/logo.png');
1874eba53bcSAndreas Gohr            $icongen->save_ico($animaldir . '/data/media/wiki/favicon.ico');
1884eba53bcSAndreas Gohr        } catch(\Exception $ignore) {
1894eba53bcSAndreas Gohr            // something went wrong, but we don't care. this is a nice to have feature only
1904eba53bcSAndreas Gohr        }
19149f2871cSAndreas Gohr
19249f2871cSAndreas Gohr        // create admin user
19349f2871cSAndreas Gohr        if($adminSetup === 'newAdmin') {
19449f2871cSAndreas Gohr            $users = "# <?php exit()?>\n" . $this->makeAdminLine($adminPassword) . "\n";
19549f2871cSAndreas Gohr        } elseif($adminSetup === 'currentAdmin') {
19649f2871cSAndreas Gohr            $users = "# <?php exit()?>\n" . $this->getAdminLine() . "\n";
1971272da0cSAndreas Gohr        } elseif($adminSetup === 'noUsers') {
198801ebaa1SAndreas Gohr            if(file_exists($animaldir . '/conf/users.auth.php')) {
199801ebaa1SAndreas Gohr                // a user file exists already, probably from animal template - don't overwrite
200801ebaa1SAndreas Gohr                $users = '';
201801ebaa1SAndreas Gohr            } else {
202801ebaa1SAndreas Gohr                // create empty user file
2031272da0cSAndreas Gohr                $users = "# <?php exit()?>\n";
204801ebaa1SAndreas Gohr            }
20549f2871cSAndreas Gohr        } else {
20649f2871cSAndreas Gohr            $users = io_readFile(DOKU_CONF . 'users.auth.php');
20749f2871cSAndreas Gohr        }
208801ebaa1SAndreas Gohr        if($users) {
20949f2871cSAndreas Gohr            $ok &= io_saveFile($animaldir . '/conf/users.auth.php', $users);
210801ebaa1SAndreas Gohr        }
21149f2871cSAndreas Gohr
2124664a1d2SAndreas Gohr        // deactivate plugins by default FIXME this should be nicer
21349f2871cSAndreas Gohr        $deactivatedPluginsList = explode(',', $this->getConf('deactivated plugins'));
2144664a1d2SAndreas Gohr        $deactivatedPluginsList = array_map('trim', $deactivatedPluginsList);
2154664a1d2SAndreas Gohr        $deactivatedPluginsList = array_unique($deactivatedPluginsList);
2164664a1d2SAndreas Gohr        $deactivatedPluginsList = array_filter($deactivatedPluginsList);
21749f2871cSAndreas Gohr        foreach($deactivatedPluginsList as $plugin) {
2184664a1d2SAndreas Gohr            $this->helper->deactivatePlugin(trim($plugin), $name);
21949f2871cSAndreas Gohr        }
22049f2871cSAndreas Gohr
22149f2871cSAndreas Gohr        return $ok;
22249f2871cSAndreas Gohr    }
22349f2871cSAndreas Gohr
22449f2871cSAndreas Gohr    /**
22549f2871cSAndreas Gohr     * Creates a new user line
22649f2871cSAndreas Gohr     *
22749f2871cSAndreas Gohr     * @param $password
22849f2871cSAndreas Gohr     * @return string
22949f2871cSAndreas Gohr     */
23049f2871cSAndreas Gohr    protected function makeAdminLine($password) {
23149f2871cSAndreas Gohr        $pass = auth_cryptPassword($password);
2321272da0cSAndreas Gohr        $line = join(
233*65e7bfd1SAndreas Gohr            ':', array(
23449f2871cSAndreas Gohr                    'admin',
23549f2871cSAndreas Gohr                    $pass,
23649f2871cSAndreas Gohr                    'Administrator',
23749f2871cSAndreas Gohr                    'admin@example.org',
23849f2871cSAndreas Gohr                    'admin,user'
2391272da0cSAndreas Gohr                )
2401272da0cSAndreas Gohr        );
24149f2871cSAndreas Gohr        return $line;
24249f2871cSAndreas Gohr    }
24349f2871cSAndreas Gohr
24449f2871cSAndreas Gohr    /**
24549f2871cSAndreas Gohr     * Copies the current user as new admin line
24649f2871cSAndreas Gohr     *
24749f2871cSAndreas Gohr     * @return string
24849f2871cSAndreas Gohr     */
24949f2871cSAndreas Gohr    protected function getAdminLine() {
25049f2871cSAndreas Gohr        $currentAdmin = $_SERVER['REMOTE_USER'];
25149f2871cSAndreas Gohr        $masterUsers = file_get_contents(DOKU_CONF . 'users.auth.php');
25249f2871cSAndreas Gohr        $masterUsers = ltrim(strstr($masterUsers, "\n" . $currentAdmin . ":"));
25349f2871cSAndreas Gohr        $newAdmin = substr($masterUsers, 0, strpos($masterUsers, "\n") + 1);
25449f2871cSAndreas Gohr        return $newAdmin;
25549f2871cSAndreas Gohr    }
25649f2871cSAndreas Gohr
25749f2871cSAndreas Gohr}
25849f2871cSAndreas Gohr
25949f2871cSAndreas Gohr// vim:ts=4:sw=4:et:
260