xref: /plugin/farmer/admin/new.php (revision 6348ab5b7af6099ea4b8519e34ad47a027f1bfe4)
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;
41*6348ab5bSMichael Grosse        if($this->createNewAnimal($data['name'], $data['admin'], $data['pass'], $data['template'], $data['aclpolicy'], $data['allowreg'])) {
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() {
55*6348ab5bSMichael Grosse        global $lang;
561272da0cSAndreas Gohr        $farmconfig = $this->helper->getConfig();
5749f2871cSAndreas Gohr
5849f2871cSAndreas Gohr        $form = new \dokuwiki\Form\Form();
5949f2871cSAndreas Gohr        $form->addClass('plugin_farmer')->id('farmer__create_animal_form');
6049f2871cSAndreas Gohr
6149f2871cSAndreas Gohr        $form->addFieldsetOpen($this->getLang('animal configuration'));
6223164e01SAndreas Gohr        $form->addTextInput('animalname', $this->getLang('animal'));
6349f2871cSAndreas Gohr        $form->addFieldsetClose();
6449f2871cSAndreas Gohr
65801ebaa1SAndreas Gohr        $animals = $this->helper->getAllAnimals();
66801ebaa1SAndreas Gohr        array_unshift($animals, '');
67801ebaa1SAndreas Gohr        $form->addFieldsetOpen($this->getLang('animal template'));
68801ebaa1SAndreas Gohr        $form->addDropdown('animaltemplate', $animals)->addClass('farmer_choosen_animals');
69801ebaa1SAndreas Gohr        $form->addFieldsetClose();
70801ebaa1SAndreas Gohr
71*6348ab5bSMichael Grosse        $form->addFieldsetOpen($lang['i_policy'])->attr('id', 'aclPolicyFieldset');
72*6348ab5bSMichael Grosse        $policyOptions = array('open' => $lang['i_pol0'],'public' => $lang['i_pol1'], 'closed' => $lang['i_pol2']);
73*6348ab5bSMichael Grosse        $form->addDropdown('aclpolicy', $policyOptions)->addClass('acl_chosen');
74*6348ab5bSMichael Grosse        if ($farmconfig['inherit']['main']) {
75*6348ab5bSMichael Grosse            $form->addRadioButton('allowreg',$this->getLang('inherit user registration'))->val('inherit')->attr('checked', 'checked');
76*6348ab5bSMichael Grosse            $form->addRadioButton('allowreg',$this->getLang('enable user registration'))->val('allow');
77*6348ab5bSMichael Grosse            $form->addRadioButton('allowreg',$this->getLang('disable user registration'))->val('disable');
78*6348ab5bSMichael Grosse        } else {
79*6348ab5bSMichael Grosse            $form->addCheckbox('allowreg', $lang['i_allowreg'])->attr('checked', 'checked');
80*6348ab5bSMichael Grosse        }
81*6348ab5bSMichael Grosse
82*6348ab5bSMichael Grosse        $form->addFieldsetClose();
83*6348ab5bSMichael Grosse
8449f2871cSAndreas Gohr        $form->addFieldsetOpen($this->getLang('animal administrator'));
851272da0cSAndreas Gohr        $btn = $form->addRadioButton('adminsetup', $this->getLang('noUsers'))->val('noUsers');
861272da0cSAndreas Gohr        if($farmconfig['inherit']['users']) {
871272da0cSAndreas Gohr            $btn->attr('checked', 'checked');  // default when inherit available
881a130845SAndreas Gohr        } else {
891a130845SAndreas Gohr            // no user copying when inheriting
9049f2871cSAndreas Gohr            $form->addRadioButton('adminsetup', $this->getLang('importUsers'))->val('importUsers');
9149f2871cSAndreas Gohr            $form->addRadioButton('adminsetup', $this->getLang('currentAdmin'))->val('currentAdmin');
921a130845SAndreas Gohr        }
931272da0cSAndreas Gohr        $btn = $form->addRadioButton('adminsetup', $this->getLang('newAdmin'))->val('newAdmin');
941272da0cSAndreas Gohr        if(!$farmconfig['inherit']['users']) {
951272da0cSAndreas Gohr            $btn->attr('checked', 'checked'); // default when inherit not available
961272da0cSAndreas Gohr        }
9749f2871cSAndreas Gohr        $form->addPasswordInput('adminPassword', $this->getLang('admin password'));
9849f2871cSAndreas Gohr        $form->addFieldsetClose();
9949f2871cSAndreas Gohr
10049f2871cSAndreas Gohr        $form->addButton('farmer__submit', $this->getLang('submit'))->attr('type', 'submit')->val('newAnimal');
10149f2871cSAndreas Gohr        echo $form->toHTML();
10249f2871cSAndreas Gohr    }
10349f2871cSAndreas Gohr
10449f2871cSAndreas Gohr    /**
10549f2871cSAndreas Gohr     * Validate the data for a new animal
10649f2871cSAndreas Gohr     *
10749f2871cSAndreas Gohr     * @return array|bool false on errors, clean data otherwise
10849f2871cSAndreas Gohr     */
10949f2871cSAndreas Gohr    protected function validateAnimalData() {
11049f2871cSAndreas Gohr        global $INPUT;
11149f2871cSAndreas Gohr
11249f2871cSAndreas Gohr        $animalname = $INPUT->filter('trim')->str('animalname');
11349f2871cSAndreas Gohr        $adminsetup = $INPUT->str('adminsetup');
11449f2871cSAndreas Gohr        $adminpass = $INPUT->filter('trim')->str('adminPassword');
115801ebaa1SAndreas Gohr        $template = $INPUT->filter('trim')->str('animaltemplate');
116*6348ab5bSMichael Grosse        $aclpolicy = $INPUT->filter('trim')->str('aclpolicy');
117*6348ab5bSMichael Grosse        $allowreg = $INPUT->str('allowreg');
11849f2871cSAndreas Gohr
11949f2871cSAndreas Gohr        $errors = array();
12049f2871cSAndreas Gohr
12149f2871cSAndreas Gohr        if($animalname === '') {
12249f2871cSAndreas Gohr            $errors[] = $this->getLang('animalname_missing');
12349f2871cSAndreas Gohr        } elseif(!$this->helper->validateAnimalName($animalname)) {
12449f2871cSAndreas Gohr            $errors[] = $this->getLang('animalname_invalid');
12549f2871cSAndreas Gohr        }
12649f2871cSAndreas Gohr
12749f2871cSAndreas Gohr        if($adminsetup === 'newAdmin' && $adminpass === '') {
12849f2871cSAndreas Gohr            $errors[] = $this->getLang('adminPassword_empty');
12949f2871cSAndreas Gohr        }
13049f2871cSAndreas Gohr
13149f2871cSAndreas Gohr        if($animalname !== '' && file_exists(DOKU_FARMDIR . '/' . $animalname)) {
13249f2871cSAndreas Gohr            $errors[] = $this->getLang('animalname_preexisting');
13349f2871cSAndreas Gohr        }
13449f2871cSAndreas Gohr
135*6348ab5bSMichael Grosse        if (!is_dir(DOKU_FARMDIR . $template) && !in_array($aclpolicy,array('open', 'public', 'closed'))) {
136*6348ab5bSMichael Grosse            $errors[] = $this->getLang('aclpolicy missing/bad');
137*6348ab5bSMichael Grosse        }
138*6348ab5bSMichael Grosse
13949f2871cSAndreas Gohr        if($errors) {
14049f2871cSAndreas Gohr            foreach($errors as $error) {
14149f2871cSAndreas Gohr                msg($error, -1);
14249f2871cSAndreas Gohr            }
14349f2871cSAndreas Gohr            return false;
14449f2871cSAndreas Gohr        }
14549f2871cSAndreas Gohr
1468262a4cbSAndreas Gohr        if(!is_dir(DOKU_FARMDIR . $template)) {
147801ebaa1SAndreas Gohr            $template = '';
148801ebaa1SAndreas Gohr        }
149*6348ab5bSMichael Grosse        if ($template != '') {
150*6348ab5bSMichael Grosse            $aclpolicy = '';
151*6348ab5bSMichael Grosse        }
152801ebaa1SAndreas Gohr
15349f2871cSAndreas Gohr        return array(
15449f2871cSAndreas Gohr            'name' => $animalname,
15549f2871cSAndreas Gohr            'admin' => $adminsetup,
156801ebaa1SAndreas Gohr            'pass' => $adminpass,
157*6348ab5bSMichael Grosse            'template' => $template,
158*6348ab5bSMichael Grosse            'aclpolicy' => $aclpolicy,
159*6348ab5bSMichael Grosse            'allowreg' => $allowreg
16049f2871cSAndreas Gohr        );
16149f2871cSAndreas Gohr    }
16249f2871cSAndreas Gohr
16349f2871cSAndreas Gohr    /**
16449f2871cSAndreas Gohr     * Create a new animal
16549f2871cSAndreas Gohr     *
16649f2871cSAndreas Gohr     * @param string $name name/title of the animal, will be the directory name for htaccess setup
16749f2871cSAndreas Gohr     * @param string $adminSetup newAdmin, currentAdmin or importUsers
16849f2871cSAndreas Gohr     * @param string $adminPassword required if $adminSetup is newAdmin
169801ebaa1SAndreas Gohr     * @param string $template name of animal to copy
170*6348ab5bSMichael Grosse     * @param $aclpolicy
171*6348ab5bSMichael Grosse     * @param $userreg
17249f2871cSAndreas Gohr     * @return bool true if successful
173*6348ab5bSMichael Grosse     * @throws Exception
17449f2871cSAndreas Gohr     */
175*6348ab5bSMichael Grosse    protected function createNewAnimal($name, $adminSetup, $adminPassword, $template, $aclpolicy, $userreg) {
1768262a4cbSAndreas Gohr        $animaldir = DOKU_FARMDIR . $name;
17749f2871cSAndreas Gohr
17849f2871cSAndreas Gohr        // copy basic template
17949f2871cSAndreas Gohr        $ok = $this->helper->io_copyDir(__DIR__ . '/../_animal', $animaldir);
18049f2871cSAndreas Gohr        if(!$ok) {
18149f2871cSAndreas Gohr            msg($this->getLang('animal creation error'), -1);
18249f2871cSAndreas Gohr            return false;
18349f2871cSAndreas Gohr        }
18449f2871cSAndreas Gohr
185801ebaa1SAndreas Gohr        // copy animal template
186801ebaa1SAndreas Gohr        if($template != '') {
187801ebaa1SAndreas Gohr            foreach(array('conf', 'data/pages', 'data/media', 'data/meta', 'data/media_meta', 'index') as $dir) {
1888262a4cbSAndreas Gohr                $templatedir = DOKU_FARMDIR . $template . '/' . $dir;
189801ebaa1SAndreas Gohr                if(!is_dir($templatedir)) continue;
190801ebaa1SAndreas Gohr                // do not copy changelogs in meta
191801ebaa1SAndreas Gohr                if(substr($dir, -4) == 'meta') {
192801ebaa1SAndreas Gohr                    $exclude = '/\.changes$/';
193801ebaa1SAndreas Gohr                } else {
194801ebaa1SAndreas Gohr                    $exclude = '';
195801ebaa1SAndreas Gohr                }
196801ebaa1SAndreas Gohr                if(!$this->helper->io_copyDir($templatedir, $animaldir . '/' . $dir, $exclude)) {
197801ebaa1SAndreas Gohr                    msg(sprintf($this->getLang('animal template copy error'), $dir), -1);
198801ebaa1SAndreas Gohr                    // we go on anyway
199801ebaa1SAndreas Gohr                }
200801ebaa1SAndreas Gohr            }
201801ebaa1SAndreas Gohr        }
202801ebaa1SAndreas Gohr
20349f2871cSAndreas Gohr        // append title to local config
20449f2871cSAndreas Gohr        $ok &= io_saveFile($animaldir . '/conf/local.php', "\n" . '$conf[\'title\'] = \'' . $name . '\';' . "\n", true);
20549f2871cSAndreas Gohr
2064eba53bcSAndreas Gohr        // create a random logo and favicon
2074eba53bcSAndreas Gohr        if(!class_exists('\splitbrain\RingIcon\RingIcon', false)) {
2084eba53bcSAndreas Gohr            require(__DIR__ . '/../3rdparty/RingIcon.php');
2094eba53bcSAndreas Gohr        }
2104eba53bcSAndreas Gohr        if(!class_exists('\chrisbliss18\phpico\PHPIco', false)) {
2114eba53bcSAndreas Gohr            require(__DIR__ . '/../3rdparty/PHPIco.php');
2124eba53bcSAndreas Gohr        }
2134eba53bcSAndreas Gohr        try {
214b263debeSAndreas Gohr            if(function_exists('imagecreatetruecolor')) {
2154eba53bcSAndreas Gohr                $ringicon = new \splitbrain\RingIcon\RingIcon(64);
2164eba53bcSAndreas Gohr                $ringicon->createImage($animaldir, $animaldir . '/data/media/wiki/logo.png');
2174eba53bcSAndreas Gohr                $icongen = new \chrisbliss18\phpico\PHPIco($animaldir . '/data/media/wiki/logo.png');
2184eba53bcSAndreas Gohr                $icongen->save_ico($animaldir . '/data/media/wiki/favicon.ico');
219b263debeSAndreas Gohr            }
2204eba53bcSAndreas Gohr        } catch(\Exception $ignore) {
2214eba53bcSAndreas Gohr            // something went wrong, but we don't care. this is a nice to have feature only
2224eba53bcSAndreas Gohr        }
22349f2871cSAndreas Gohr
22449f2871cSAndreas Gohr        // create admin user
22549f2871cSAndreas Gohr        if($adminSetup === 'newAdmin') {
22649f2871cSAndreas Gohr            $users = "# <?php exit()?>\n" . $this->makeAdminLine($adminPassword) . "\n";
22749f2871cSAndreas Gohr        } elseif($adminSetup === 'currentAdmin') {
22849f2871cSAndreas Gohr            $users = "# <?php exit()?>\n" . $this->getAdminLine() . "\n";
2291272da0cSAndreas Gohr        } elseif($adminSetup === 'noUsers') {
230801ebaa1SAndreas Gohr            if(file_exists($animaldir . '/conf/users.auth.php')) {
231801ebaa1SAndreas Gohr                // a user file exists already, probably from animal template - don't overwrite
232801ebaa1SAndreas Gohr                $users = '';
233801ebaa1SAndreas Gohr            } else {
234801ebaa1SAndreas Gohr                // create empty user file
2351272da0cSAndreas Gohr                $users = "# <?php exit()?>\n";
236801ebaa1SAndreas Gohr            }
23749f2871cSAndreas Gohr        } else {
23849f2871cSAndreas Gohr            $users = io_readFile(DOKU_CONF . 'users.auth.php');
23949f2871cSAndreas Gohr        }
240801ebaa1SAndreas Gohr        if($users) {
24149f2871cSAndreas Gohr            $ok &= io_saveFile($animaldir . '/conf/users.auth.php', $users);
242801ebaa1SAndreas Gohr        }
24349f2871cSAndreas Gohr
244*6348ab5bSMichael Grosse        if ($aclpolicy != '') {
245*6348ab5bSMichael Grosse            $aclfile = file($animaldir . '/conf/acl.auth.php');
246*6348ab5bSMichael Grosse            array_pop($aclfile);
247*6348ab5bSMichael Grosse            switch ($aclpolicy) {
248*6348ab5bSMichael Grosse                case 'open':
249*6348ab5bSMichael Grosse                    $aclfile[] = "* @ALL 8";
250*6348ab5bSMichael Grosse                    break;
251*6348ab5bSMichael Grosse                case 'public':
252*6348ab5bSMichael Grosse                    $aclfile[] = "* @ALL 1";
253*6348ab5bSMichael Grosse                    $aclfile[] = "* @user 8";
254*6348ab5bSMichael Grosse                    break;
255*6348ab5bSMichael Grosse                case 'closed':
256*6348ab5bSMichael Grosse                    $aclfile[] = "* @ALL 0";
257*6348ab5bSMichael Grosse                    $aclfile[] = "* @user 8";
258*6348ab5bSMichael Grosse                    break;
259*6348ab5bSMichael Grosse                default:
260*6348ab5bSMichael Grosse                    throw new Exception('Undefined aclpolicy given');
261*6348ab5bSMichael Grosse            }
262*6348ab5bSMichael Grosse            $ok &= io_saveFile($animaldir . '/conf/acl.auth.php', join("\n", $aclfile));
263*6348ab5bSMichael Grosse
264*6348ab5bSMichael Grosse            global $conf;
265*6348ab5bSMichael Grosse            switch ($userreg) {
266*6348ab5bSMichael Grosse                case 'allow':
267*6348ab5bSMichael Grosse                    $disableactions = join(',', array_diff(explode(',', $conf['disableactions']), array('register')));
268*6348ab5bSMichael Grosse                    $ok &= io_saveFile($animaldir . '/conf/local.php', "\n" . '$conf[\'disableactions\'] = \''.$disableactions.'\';' . "\n", true);
269*6348ab5bSMichael Grosse                    break;
270*6348ab5bSMichael Grosse                case 'disable':
271*6348ab5bSMichael Grosse                    $disableactions = join(',', array_merge(explode(',', $conf['disableactions']), array('register')));
272*6348ab5bSMichael Grosse                    $ok &= io_saveFile($animaldir . '/conf/local.php', "\n" . '$conf[\'disableactions\'] = \''.$disableactions.'\';' . "\n", true);
273*6348ab5bSMichael Grosse                    break;
274*6348ab5bSMichael Grosse                case 'inherit':
275*6348ab5bSMichael Grosse                case true:
276*6348ab5bSMichael Grosse                    // nothing needs to be done
277*6348ab5bSMichael Grosse                    break;
278*6348ab5bSMichael Grosse                default:
279*6348ab5bSMichael Grosse                    $ok &= io_saveFile($animaldir . '/conf/local.php', "\n" . '$conf[\'disableactions\'] = \'register\';' . "\n", true);
280*6348ab5bSMichael Grosse            }
281*6348ab5bSMichael Grosse        }
282*6348ab5bSMichael Grosse
2834664a1d2SAndreas Gohr        // deactivate plugins by default FIXME this should be nicer
28449f2871cSAndreas Gohr        $deactivatedPluginsList = explode(',', $this->getConf('deactivated plugins'));
2854664a1d2SAndreas Gohr        $deactivatedPluginsList = array_map('trim', $deactivatedPluginsList);
2864664a1d2SAndreas Gohr        $deactivatedPluginsList = array_unique($deactivatedPluginsList);
2874664a1d2SAndreas Gohr        $deactivatedPluginsList = array_filter($deactivatedPluginsList);
28849f2871cSAndreas Gohr        foreach($deactivatedPluginsList as $plugin) {
289af1c6dd8SAndreas Gohr            $this->helper->setPluginState(trim($plugin), $name, 0);
29049f2871cSAndreas Gohr        }
29149f2871cSAndreas Gohr
29249f2871cSAndreas Gohr        return $ok;
29349f2871cSAndreas Gohr    }
29449f2871cSAndreas Gohr
29549f2871cSAndreas Gohr    /**
29649f2871cSAndreas Gohr     * Creates a new user line
29749f2871cSAndreas Gohr     *
29849f2871cSAndreas Gohr     * @param $password
29949f2871cSAndreas Gohr     * @return string
30049f2871cSAndreas Gohr     */
30149f2871cSAndreas Gohr    protected function makeAdminLine($password) {
30249f2871cSAndreas Gohr        $pass = auth_cryptPassword($password);
3031272da0cSAndreas Gohr        $line = join(
30465e7bfd1SAndreas Gohr            ':', array(
30549f2871cSAndreas Gohr                   'admin',
30649f2871cSAndreas Gohr                   $pass,
30749f2871cSAndreas Gohr                   'Administrator',
30849f2871cSAndreas Gohr                   'admin@example.org',
30949f2871cSAndreas Gohr                   'admin,user'
3101272da0cSAndreas Gohr               )
3111272da0cSAndreas Gohr        );
31249f2871cSAndreas Gohr        return $line;
31349f2871cSAndreas Gohr    }
31449f2871cSAndreas Gohr
31549f2871cSAndreas Gohr    /**
31649f2871cSAndreas Gohr     * Copies the current user as new admin line
31749f2871cSAndreas Gohr     *
31849f2871cSAndreas Gohr     * @return string
31949f2871cSAndreas Gohr     */
32049f2871cSAndreas Gohr    protected function getAdminLine() {
32149f2871cSAndreas Gohr        $currentAdmin = $_SERVER['REMOTE_USER'];
32249f2871cSAndreas Gohr        $masterUsers = file_get_contents(DOKU_CONF . 'users.auth.php');
32349f2871cSAndreas Gohr        $masterUsers = ltrim(strstr($masterUsers, "\n" . $currentAdmin . ":"));
32449f2871cSAndreas Gohr        $newAdmin = substr($masterUsers, 0, strpos($masterUsers, "\n") + 1);
32549f2871cSAndreas Gohr        return $newAdmin;
32649f2871cSAndreas Gohr    }
32749f2871cSAndreas Gohr
32849f2871cSAndreas Gohr}
32949f2871cSAndreas Gohr
33049f2871cSAndreas Gohr// vim:ts=4:sw=4:et:
331