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; 416348ab5bSMichael 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() { 556348ab5bSMichael 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')); 6843551cfcSMichael Grosse $form->addDropdown('animaltemplate', $animals)->addClass('farmer_chosen_animals'); 69801ebaa1SAndreas Gohr $form->addFieldsetClose(); 70801ebaa1SAndreas Gohr 716348ab5bSMichael Grosse $form->addFieldsetOpen($lang['i_policy'])->attr('id', 'aclPolicyFieldset'); 726348ab5bSMichael Grosse $policyOptions = array('open' => $lang['i_pol0'],'public' => $lang['i_pol1'], 'closed' => $lang['i_pol2']); 736348ab5bSMichael Grosse $form->addDropdown('aclpolicy', $policyOptions)->addClass('acl_chosen'); 746348ab5bSMichael Grosse if ($farmconfig['inherit']['main']) { 756348ab5bSMichael Grosse $form->addRadioButton('allowreg',$this->getLang('inherit user registration'))->val('inherit')->attr('checked', 'checked'); 766348ab5bSMichael Grosse $form->addRadioButton('allowreg',$this->getLang('enable user registration'))->val('allow'); 776348ab5bSMichael Grosse $form->addRadioButton('allowreg',$this->getLang('disable user registration'))->val('disable'); 786348ab5bSMichael Grosse } else { 796348ab5bSMichael Grosse $form->addCheckbox('allowreg', $lang['i_allowreg'])->attr('checked', 'checked'); 806348ab5bSMichael Grosse } 816348ab5bSMichael Grosse 826348ab5bSMichael Grosse $form->addFieldsetClose(); 836348ab5bSMichael 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'); 1166348ab5bSMichael Grosse $aclpolicy = $INPUT->filter('trim')->str('aclpolicy'); 1176348ab5bSMichael 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 1356348ab5bSMichael Grosse if (!is_dir(DOKU_FARMDIR . $template) && !in_array($aclpolicy,array('open', 'public', 'closed'))) { 1366348ab5bSMichael Grosse $errors[] = $this->getLang('aclpolicy missing/bad'); 1376348ab5bSMichael Grosse } 1386348ab5bSMichael 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 } 1496348ab5bSMichael Grosse if ($template != '') { 1506348ab5bSMichael Grosse $aclpolicy = ''; 1516348ab5bSMichael Grosse } 152801ebaa1SAndreas Gohr 15349f2871cSAndreas Gohr return array( 15449f2871cSAndreas Gohr 'name' => $animalname, 15549f2871cSAndreas Gohr 'admin' => $adminsetup, 156801ebaa1SAndreas Gohr 'pass' => $adminpass, 1576348ab5bSMichael Grosse 'template' => $template, 1586348ab5bSMichael Grosse 'aclpolicy' => $aclpolicy, 1596348ab5bSMichael 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 1706348ab5bSMichael Grosse * @param $aclpolicy 1716348ab5bSMichael Grosse * @param $userreg 17249f2871cSAndreas Gohr * @return bool true if successful 1736348ab5bSMichael Grosse * @throws Exception 17449f2871cSAndreas Gohr */ 1756348ab5bSMichael 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')) { 215*c3bd7eb3SAndreas Gohr $logo = $animaldir . '/data/media/wiki/logo.png'; 216*c3bd7eb3SAndreas Gohr if(!file_exists($logo)) { 2174eba53bcSAndreas Gohr $ringicon = new \splitbrain\RingIcon\RingIcon(64); 218*c3bd7eb3SAndreas Gohr $ringicon->createImage($animaldir, $logo); 219*c3bd7eb3SAndreas Gohr } 220*c3bd7eb3SAndreas Gohr 221*c3bd7eb3SAndreas Gohr $icon = $animaldir . '/data/media/wiki/favicon.ico'; 222*c3bd7eb3SAndreas Gohr if(!file_exists($icon)) { 223*c3bd7eb3SAndreas Gohr $icongen = new \chrisbliss18\phpico\PHPIco($logo); 224*c3bd7eb3SAndreas Gohr $icongen->save_ico($icon); 225*c3bd7eb3SAndreas Gohr } 226b263debeSAndreas Gohr } 2274eba53bcSAndreas Gohr } catch(\Exception $ignore) { 2284eba53bcSAndreas Gohr // something went wrong, but we don't care. this is a nice to have feature only 2294eba53bcSAndreas Gohr } 23049f2871cSAndreas Gohr 23149f2871cSAndreas Gohr // create admin user 23249f2871cSAndreas Gohr if($adminSetup === 'newAdmin') { 23349f2871cSAndreas Gohr $users = "# <?php exit()?>\n" . $this->makeAdminLine($adminPassword) . "\n"; 23449f2871cSAndreas Gohr } elseif($adminSetup === 'currentAdmin') { 23549f2871cSAndreas Gohr $users = "# <?php exit()?>\n" . $this->getAdminLine() . "\n"; 2361272da0cSAndreas Gohr } elseif($adminSetup === 'noUsers') { 237801ebaa1SAndreas Gohr if(file_exists($animaldir . '/conf/users.auth.php')) { 238801ebaa1SAndreas Gohr // a user file exists already, probably from animal template - don't overwrite 239801ebaa1SAndreas Gohr $users = ''; 240801ebaa1SAndreas Gohr } else { 241801ebaa1SAndreas Gohr // create empty user file 2421272da0cSAndreas Gohr $users = "# <?php exit()?>\n"; 243801ebaa1SAndreas Gohr } 24449f2871cSAndreas Gohr } else { 24549f2871cSAndreas Gohr $users = io_readFile(DOKU_CONF . 'users.auth.php'); 24649f2871cSAndreas Gohr } 247801ebaa1SAndreas Gohr if($users) { 24849f2871cSAndreas Gohr $ok &= io_saveFile($animaldir . '/conf/users.auth.php', $users); 249801ebaa1SAndreas Gohr } 25049f2871cSAndreas Gohr 2516348ab5bSMichael Grosse if ($aclpolicy != '') { 2526348ab5bSMichael Grosse $aclfile = file($animaldir . '/conf/acl.auth.php'); 2532b85f30dSAndreas Gohr $aclfile = array_map('trim', $aclfile); 2546348ab5bSMichael Grosse array_pop($aclfile); 2556348ab5bSMichael Grosse switch ($aclpolicy) { 2566348ab5bSMichael Grosse case 'open': 2576348ab5bSMichael Grosse $aclfile[] = "* @ALL 8"; 2586348ab5bSMichael Grosse break; 2596348ab5bSMichael Grosse case 'public': 2606348ab5bSMichael Grosse $aclfile[] = "* @ALL 1"; 2616348ab5bSMichael Grosse $aclfile[] = "* @user 8"; 2626348ab5bSMichael Grosse break; 2636348ab5bSMichael Grosse case 'closed': 2646348ab5bSMichael Grosse $aclfile[] = "* @ALL 0"; 2656348ab5bSMichael Grosse $aclfile[] = "* @user 8"; 2666348ab5bSMichael Grosse break; 2676348ab5bSMichael Grosse default: 2686348ab5bSMichael Grosse throw new Exception('Undefined aclpolicy given'); 2696348ab5bSMichael Grosse } 2702b85f30dSAndreas Gohr $ok &= io_saveFile($animaldir . '/conf/acl.auth.php', join("\n", $aclfile)."\n"); 2716348ab5bSMichael Grosse 2726348ab5bSMichael Grosse global $conf; 2736348ab5bSMichael Grosse switch ($userreg) { 2746348ab5bSMichael Grosse case 'allow': 2756348ab5bSMichael Grosse $disableactions = join(',', array_diff(explode(',', $conf['disableactions']), array('register'))); 2766348ab5bSMichael Grosse $ok &= io_saveFile($animaldir . '/conf/local.php', "\n" . '$conf[\'disableactions\'] = \''.$disableactions.'\';' . "\n", true); 2776348ab5bSMichael Grosse break; 2786348ab5bSMichael Grosse case 'disable': 2796348ab5bSMichael Grosse $disableactions = join(',', array_merge(explode(',', $conf['disableactions']), array('register'))); 2806348ab5bSMichael Grosse $ok &= io_saveFile($animaldir . '/conf/local.php', "\n" . '$conf[\'disableactions\'] = \''.$disableactions.'\';' . "\n", true); 2816348ab5bSMichael Grosse break; 2826348ab5bSMichael Grosse case 'inherit': 2836348ab5bSMichael Grosse case true: 2846348ab5bSMichael Grosse // nothing needs to be done 2856348ab5bSMichael Grosse break; 2866348ab5bSMichael Grosse default: 2876348ab5bSMichael Grosse $ok &= io_saveFile($animaldir . '/conf/local.php', "\n" . '$conf[\'disableactions\'] = \'register\';' . "\n", true); 2886348ab5bSMichael Grosse } 2896348ab5bSMichael Grosse } 2906348ab5bSMichael Grosse 2914664a1d2SAndreas Gohr // deactivate plugins by default FIXME this should be nicer 29249f2871cSAndreas Gohr $deactivatedPluginsList = explode(',', $this->getConf('deactivated plugins')); 2934664a1d2SAndreas Gohr $deactivatedPluginsList = array_map('trim', $deactivatedPluginsList); 2944664a1d2SAndreas Gohr $deactivatedPluginsList = array_unique($deactivatedPluginsList); 2954664a1d2SAndreas Gohr $deactivatedPluginsList = array_filter($deactivatedPluginsList); 29649f2871cSAndreas Gohr foreach($deactivatedPluginsList as $plugin) { 297af1c6dd8SAndreas Gohr $this->helper->setPluginState(trim($plugin), $name, 0); 29849f2871cSAndreas Gohr } 29949f2871cSAndreas Gohr 30049f2871cSAndreas Gohr return $ok; 30149f2871cSAndreas Gohr } 30249f2871cSAndreas Gohr 30349f2871cSAndreas Gohr /** 30449f2871cSAndreas Gohr * Creates a new user line 30549f2871cSAndreas Gohr * 30649f2871cSAndreas Gohr * @param $password 30749f2871cSAndreas Gohr * @return string 30849f2871cSAndreas Gohr */ 30949f2871cSAndreas Gohr protected function makeAdminLine($password) { 31049f2871cSAndreas Gohr $pass = auth_cryptPassword($password); 3111272da0cSAndreas Gohr $line = join( 31265e7bfd1SAndreas Gohr ':', array( 31349f2871cSAndreas Gohr 'admin', 31449f2871cSAndreas Gohr $pass, 31549f2871cSAndreas Gohr 'Administrator', 31649f2871cSAndreas Gohr 'admin@example.org', 31749f2871cSAndreas Gohr 'admin,user' 3181272da0cSAndreas Gohr ) 3191272da0cSAndreas Gohr ); 32049f2871cSAndreas Gohr return $line; 32149f2871cSAndreas Gohr } 32249f2871cSAndreas Gohr 32349f2871cSAndreas Gohr /** 32449f2871cSAndreas Gohr * Copies the current user as new admin line 32549f2871cSAndreas Gohr * 32649f2871cSAndreas Gohr * @return string 32749f2871cSAndreas Gohr */ 32849f2871cSAndreas Gohr protected function getAdminLine() { 32949f2871cSAndreas Gohr $currentAdmin = $_SERVER['REMOTE_USER']; 33049f2871cSAndreas Gohr $masterUsers = file_get_contents(DOKU_CONF . 'users.auth.php'); 33149f2871cSAndreas Gohr $masterUsers = ltrim(strstr($masterUsers, "\n" . $currentAdmin . ":")); 33249f2871cSAndreas Gohr $newAdmin = substr($masterUsers, 0, strpos($masterUsers, "\n") + 1); 33349f2871cSAndreas Gohr return $newAdmin; 33449f2871cSAndreas Gohr } 33549f2871cSAndreas Gohr 33649f2871cSAndreas Gohr} 33749f2871cSAndreas Gohr 33849f2871cSAndreas Gohr// vim:ts=4:sw=4:et: 339