xref: /plugin/farmer/admin/new.php (revision 1a130845736a25864877b71fc992ae63fb654df1)
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
74*1a130845SAndreas Gohr        } else {
75*1a130845SAndreas Gohr            // no user copying when inheriting
7649f2871cSAndreas Gohr            $form->addRadioButton('adminsetup', $this->getLang('importUsers'))->val('importUsers');
7749f2871cSAndreas Gohr            $form->addRadioButton('adminsetup', $this->getLang('currentAdmin'))->val('currentAdmin');
78*1a130845SAndreas Gohr        }
791272da0cSAndreas Gohr        $btn = $form->addRadioButton('adminsetup', $this->getLang('newAdmin'))->val('newAdmin');
801272da0cSAndreas Gohr        if(!$farmconfig['inherit']['users']) {
811272da0cSAndreas Gohr            $btn->attr('checked', 'checked'); // default when inherit not available
821272da0cSAndreas Gohr        }
8349f2871cSAndreas Gohr        $form->addPasswordInput('adminPassword', $this->getLang('admin password'));
8449f2871cSAndreas Gohr        $form->addFieldsetClose();
8549f2871cSAndreas Gohr
8649f2871cSAndreas Gohr        $form->addButton('farmer__submit', $this->getLang('submit'))->attr('type', 'submit')->val('newAnimal');
8749f2871cSAndreas Gohr        echo $form->toHTML();
8849f2871cSAndreas Gohr    }
8949f2871cSAndreas Gohr
9049f2871cSAndreas Gohr    /**
9149f2871cSAndreas Gohr     * Validate the data for a new animal
9249f2871cSAndreas Gohr     *
9349f2871cSAndreas Gohr     * @return array|bool false on errors, clean data otherwise
9449f2871cSAndreas Gohr     */
9549f2871cSAndreas Gohr    protected function validateAnimalData() {
9649f2871cSAndreas Gohr        global $INPUT;
9749f2871cSAndreas Gohr
9849f2871cSAndreas Gohr        $animalname = $INPUT->filter('trim')->str('animalname');
9949f2871cSAndreas Gohr        $adminsetup = $INPUT->str('adminsetup');
10049f2871cSAndreas Gohr        $adminpass = $INPUT->filter('trim')->str('adminPassword');
101801ebaa1SAndreas Gohr        $template = $INPUT->filter('trim')->str('animaltemplate');
10249f2871cSAndreas Gohr
10349f2871cSAndreas Gohr        $errors = array();
10449f2871cSAndreas Gohr
10549f2871cSAndreas Gohr        if($animalname === '') {
10649f2871cSAndreas Gohr            $errors[] = $this->getLang('animalname_missing');
10749f2871cSAndreas Gohr        } elseif(!$this->helper->validateAnimalName($animalname)) {
10849f2871cSAndreas Gohr            $errors[] = $this->getLang('animalname_invalid');
10949f2871cSAndreas Gohr        }
11049f2871cSAndreas Gohr
11149f2871cSAndreas Gohr        if($adminsetup === 'newAdmin' && $adminpass === '') {
11249f2871cSAndreas Gohr            $errors[] = $this->getLang('adminPassword_empty');
11349f2871cSAndreas Gohr        }
11449f2871cSAndreas Gohr
11549f2871cSAndreas Gohr        if($animalname !== '' && file_exists(DOKU_FARMDIR . '/' . $animalname)) {
11649f2871cSAndreas Gohr            $errors[] = $this->getLang('animalname_preexisting');
11749f2871cSAndreas Gohr        }
11849f2871cSAndreas Gohr
11949f2871cSAndreas Gohr        if($errors) {
12049f2871cSAndreas Gohr            foreach($errors as $error) {
12149f2871cSAndreas Gohr                msg($error, -1);
12249f2871cSAndreas Gohr            }
12349f2871cSAndreas Gohr            return false;
12449f2871cSAndreas Gohr        }
12549f2871cSAndreas Gohr
126801ebaa1SAndreas Gohr        if(!is_dir(DOKU_FARMDIR . '/' . $template)) {
127801ebaa1SAndreas Gohr            $template = '';
128801ebaa1SAndreas Gohr        }
129801ebaa1SAndreas Gohr
13049f2871cSAndreas Gohr        return array(
13149f2871cSAndreas Gohr            'name' => $animalname,
13249f2871cSAndreas Gohr            'admin' => $adminsetup,
133801ebaa1SAndreas Gohr            'pass' => $adminpass,
134801ebaa1SAndreas Gohr            'template' => $template
13549f2871cSAndreas Gohr        );
13649f2871cSAndreas Gohr    }
13749f2871cSAndreas Gohr
13849f2871cSAndreas Gohr    /**
13949f2871cSAndreas Gohr     * Create a new animal
14049f2871cSAndreas Gohr     *
14149f2871cSAndreas Gohr     * @param string $name name/title of the animal, will be the directory name for htaccess setup
14249f2871cSAndreas Gohr     * @param string $adminSetup newAdmin, currentAdmin or importUsers
14349f2871cSAndreas Gohr     * @param string $adminPassword required if $adminSetup is newAdmin
144801ebaa1SAndreas Gohr     * @param string $template name of animal to copy
14549f2871cSAndreas Gohr     * @return bool true if successful
14649f2871cSAndreas Gohr     */
147801ebaa1SAndreas Gohr    protected function createNewAnimal($name, $adminSetup, $adminPassword, $template) {
14849f2871cSAndreas Gohr        $animaldir = DOKU_FARMDIR . '/' . $name;
14949f2871cSAndreas Gohr
15049f2871cSAndreas Gohr        // copy basic template
15149f2871cSAndreas Gohr        $ok = $this->helper->io_copyDir(__DIR__ . '/../_animal', $animaldir);
15249f2871cSAndreas Gohr        if(!$ok) {
15349f2871cSAndreas Gohr            msg($this->getLang('animal creation error'), -1);
15449f2871cSAndreas Gohr            return false;
15549f2871cSAndreas Gohr        }
15649f2871cSAndreas Gohr
157801ebaa1SAndreas Gohr        // copy animal template
158801ebaa1SAndreas Gohr        if($template != '') {
159801ebaa1SAndreas Gohr            foreach(array('conf', 'data/pages', 'data/media', 'data/meta', 'data/media_meta', 'index') as $dir) {
160801ebaa1SAndreas Gohr                $templatedir = DOKU_FARMDIR . '/' . $template . '/' . $dir;
161801ebaa1SAndreas Gohr                if(!is_dir($templatedir)) continue;
162801ebaa1SAndreas Gohr                // do not copy changelogs in meta
163801ebaa1SAndreas Gohr                if(substr($dir, -4) == 'meta') {
164801ebaa1SAndreas Gohr                    $exclude = '/\.changes$/';
165801ebaa1SAndreas Gohr                } else {
166801ebaa1SAndreas Gohr                    $exclude = '';
167801ebaa1SAndreas Gohr                }
168801ebaa1SAndreas Gohr                if(!$this->helper->io_copyDir($templatedir, $animaldir . '/' . $dir, $exclude)) {
169801ebaa1SAndreas Gohr                    msg(sprintf($this->getLang('animal template copy error'), $dir), -1);
170801ebaa1SAndreas Gohr                    // we go on anyway
171801ebaa1SAndreas Gohr                }
172801ebaa1SAndreas Gohr            }
173801ebaa1SAndreas Gohr        }
174801ebaa1SAndreas Gohr
17549f2871cSAndreas Gohr        // append title to local config
17649f2871cSAndreas Gohr        $ok &= io_saveFile($animaldir . '/conf/local.php', "\n" . '$conf[\'title\'] = \'' . $name . '\';' . "\n", true);
17749f2871cSAndreas Gohr
1784eba53bcSAndreas Gohr        // create a random logo and favicon
1794eba53bcSAndreas Gohr        if(!class_exists('\splitbrain\RingIcon\RingIcon', false)) {
1804eba53bcSAndreas Gohr            require(__DIR__ . '/../3rdparty/RingIcon.php');
1814eba53bcSAndreas Gohr        }
1824eba53bcSAndreas Gohr        if(!class_exists('\chrisbliss18\phpico\PHPIco', false)) {
1834eba53bcSAndreas Gohr            require(__DIR__ . '/../3rdparty/PHPIco.php');
1844eba53bcSAndreas Gohr        }
1854eba53bcSAndreas Gohr        try {
1864eba53bcSAndreas Gohr            $ringicon = new \splitbrain\RingIcon\RingIcon(64);
1874eba53bcSAndreas Gohr            $ringicon->createImage($animaldir, $animaldir . '/data/media/wiki/logo.png');
1884eba53bcSAndreas Gohr            $icongen = new \chrisbliss18\phpico\PHPIco($animaldir . '/data/media/wiki/logo.png');
1894eba53bcSAndreas Gohr            $icongen->save_ico($animaldir . '/data/media/wiki/favicon.ico');
1904eba53bcSAndreas Gohr        } catch(\Exception $ignore) {
1914eba53bcSAndreas Gohr            // something went wrong, but we don't care. this is a nice to have feature only
1924eba53bcSAndreas Gohr        }
19349f2871cSAndreas Gohr
19449f2871cSAndreas Gohr        // create admin user
19549f2871cSAndreas Gohr        if($adminSetup === 'newAdmin') {
19649f2871cSAndreas Gohr            $users = "# <?php exit()?>\n" . $this->makeAdminLine($adminPassword) . "\n";
19749f2871cSAndreas Gohr        } elseif($adminSetup === 'currentAdmin') {
19849f2871cSAndreas Gohr            $users = "# <?php exit()?>\n" . $this->getAdminLine() . "\n";
1991272da0cSAndreas Gohr        } elseif($adminSetup === 'noUsers') {
200801ebaa1SAndreas Gohr            if(file_exists($animaldir . '/conf/users.auth.php')) {
201801ebaa1SAndreas Gohr                // a user file exists already, probably from animal template - don't overwrite
202801ebaa1SAndreas Gohr                $users = '';
203801ebaa1SAndreas Gohr            } else {
204801ebaa1SAndreas Gohr                // create empty user file
2051272da0cSAndreas Gohr                $users = "# <?php exit()?>\n";
206801ebaa1SAndreas Gohr            }
20749f2871cSAndreas Gohr        } else {
20849f2871cSAndreas Gohr            $users = io_readFile(DOKU_CONF . 'users.auth.php');
20949f2871cSAndreas Gohr        }
210801ebaa1SAndreas Gohr        if($users) {
21149f2871cSAndreas Gohr            $ok &= io_saveFile($animaldir . '/conf/users.auth.php', $users);
212801ebaa1SAndreas Gohr        }
21349f2871cSAndreas Gohr
2144664a1d2SAndreas Gohr        // deactivate plugins by default FIXME this should be nicer
21549f2871cSAndreas Gohr        $deactivatedPluginsList = explode(',', $this->getConf('deactivated plugins'));
2164664a1d2SAndreas Gohr        $deactivatedPluginsList = array_map('trim', $deactivatedPluginsList);
2174664a1d2SAndreas Gohr        $deactivatedPluginsList = array_unique($deactivatedPluginsList);
2184664a1d2SAndreas Gohr        $deactivatedPluginsList = array_filter($deactivatedPluginsList);
21949f2871cSAndreas Gohr        foreach($deactivatedPluginsList as $plugin) {
2204664a1d2SAndreas Gohr            $this->helper->deactivatePlugin(trim($plugin), $name);
22149f2871cSAndreas Gohr        }
22249f2871cSAndreas Gohr
22349f2871cSAndreas Gohr        return $ok;
22449f2871cSAndreas Gohr    }
22549f2871cSAndreas Gohr
22649f2871cSAndreas Gohr    /**
22749f2871cSAndreas Gohr     * Creates a new user line
22849f2871cSAndreas Gohr     *
22949f2871cSAndreas Gohr     * @param $password
23049f2871cSAndreas Gohr     * @return string
23149f2871cSAndreas Gohr     */
23249f2871cSAndreas Gohr    protected function makeAdminLine($password) {
23349f2871cSAndreas Gohr        $pass = auth_cryptPassword($password);
2341272da0cSAndreas Gohr        $line = join(
23565e7bfd1SAndreas Gohr            ':', array(
23649f2871cSAndreas Gohr                    'admin',
23749f2871cSAndreas Gohr                    $pass,
23849f2871cSAndreas Gohr                    'Administrator',
23949f2871cSAndreas Gohr                    'admin@example.org',
24049f2871cSAndreas Gohr                    'admin,user'
2411272da0cSAndreas Gohr                )
2421272da0cSAndreas Gohr        );
24349f2871cSAndreas Gohr        return $line;
24449f2871cSAndreas Gohr    }
24549f2871cSAndreas Gohr
24649f2871cSAndreas Gohr    /**
24749f2871cSAndreas Gohr     * Copies the current user as new admin line
24849f2871cSAndreas Gohr     *
24949f2871cSAndreas Gohr     * @return string
25049f2871cSAndreas Gohr     */
25149f2871cSAndreas Gohr    protected function getAdminLine() {
25249f2871cSAndreas Gohr        $currentAdmin = $_SERVER['REMOTE_USER'];
25349f2871cSAndreas Gohr        $masterUsers = file_get_contents(DOKU_CONF . 'users.auth.php');
25449f2871cSAndreas Gohr        $masterUsers = ltrim(strstr($masterUsers, "\n" . $currentAdmin . ":"));
25549f2871cSAndreas Gohr        $newAdmin = substr($masterUsers, 0, strpos($masterUsers, "\n") + 1);
25649f2871cSAndreas Gohr        return $newAdmin;
25749f2871cSAndreas Gohr    }
25849f2871cSAndreas Gohr
25949f2871cSAndreas Gohr}
26049f2871cSAndreas Gohr
26149f2871cSAndreas Gohr// vim:ts=4:sw=4:et:
262