Merge branch '2016.11-develop-setup' into 2016.11-develop
[tine20] / tine20 / Setup / Frontend / Cli.php
1 <?php
2 /**
3  * Tine 2.0
4  * @package     Tinebase
5  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
6  * @author      Philipp Schüle <p.schuele@metaways.de>
7  * @copyright   Copyright (c) 2008-2012 Metaways Infosystems GmbH (http://www.metaways.de)
8  * 
9  * @todo        add ext check again
10  */
11
12 /**
13  * cli server
14  *
15  * This class handles all requests from cli scripts
16  *
17  * @package     Tinebase
18  */
19 class Setup_Frontend_Cli
20 {
21     /**
22      * the internal name of the application
23      *
24      * @var string
25      */
26     protected $_appname = 'Setup';
27
28     /**
29      * authentication
30      *
31      * @param string $_username
32      * @param string $_password
33      * 
34      * @return boolean
35      */
36     public function authenticate($_username, $_password)
37     {
38         return false;
39     }
40     
41     /**
42      * handle request (call -ApplicationName-_Cli.-MethodName- or -ApplicationName-_Cli.getHelp)
43      *
44      * @param Zend_Console_Getopt $_opts
45      * @param boolean $exitAfterHandle
46      * @return void
47      */
48     public function handle(Zend_Console_Getopt $_opts, $exitAfterHandle = true)
49     {
50         Setup_Core::set(Setup_Core::USER, 'setupuser');
51
52         $result = 0;
53         if (isset($_opts->install)) {
54             $result = $this->_install($_opts);
55         } elseif(isset($_opts->update)) {
56             $result = $this->_update($_opts);
57         } elseif(isset($_opts->uninstall)) {
58             $this->_uninstall($_opts);
59         } elseif(isset($_opts->install_dump)) {
60             $this->_installDump($_opts);
61         } elseif(isset($_opts->list)) {
62             $result = $this->_listInstalled();
63         } elseif(isset($_opts->sync_accounts_from_ldap)) {
64             $this->_importAccounts($_opts);
65         } elseif(isset($_opts->sync_passwords_from_ldap)) {
66             $this->_syncPasswords($_opts);
67         } elseif(isset($_opts->egw14import)) {
68             $this->_egw14Import($_opts);
69         } elseif(isset($_opts->check_requirements)) {
70             $this->_checkRequirements($_opts);
71         } elseif(isset($_opts->setconfig)) {
72             $this->_setConfig($_opts);
73         } elseif(isset($_opts->create_admin)) {
74             $this->_createAdminUser($_opts);
75         } elseif(isset($_opts->getconfig)) {
76             $this->_getConfig($_opts);
77         } elseif(isset($_opts->reset_demodata)) {
78             $this->_resetDemodata($_opts);
79         } elseif(isset($_opts->updateAllImportExportDefinitions)) {
80             $this->_updateAllImportExportDefinitions($_opts);
81         } elseif(isset($_opts->backup)) {
82             $this->_backup($_opts);
83         } elseif(isset($_opts->restore)) {
84             $this->_restore($_opts);
85         } elseif(isset($_opts->compare)) {
86             $this->_compare($_opts);
87         }
88         
89         if ($exitAfterHandle) {
90             exit($result);
91         }
92     }
93     
94     /**
95      * install new applications
96      *
97      * @param Zend_Console_Getopt $_opts
98      * @return integer
99      */
100     protected function _install(Zend_Console_Getopt $_opts)
101     {
102         $controller = Setup_Controller::getInstance();
103
104         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
105
106         if ($_opts->install === true) {
107             if (Setup_Controller::getInstance()->isInstalled('Tinebase')) {
108                 // nothing to do
109                 return 0;
110             }
111             $applications = $controller->getInstallableApplications();
112             $applications = array_keys($applications);
113         } else {
114             $applications = array();
115             $applicationNames = explode(',', $_opts->install);
116             if (count($applicationNames) === 1 && strtolower($applicationNames[0]) === 'all') {
117                 $applications = $controller->getInstallableApplications();
118                 $applications = array_keys($applications);
119             } else {
120                 foreach ($applicationNames as $applicationName) {
121                     $applicationName = ucfirst(trim($applicationName));
122                     try {
123                         $controller->getSetupXml($applicationName);
124                         $applications[] = $applicationName;
125                     } catch (Setup_Exception_NotFound $e) {
126                         echo "Application $applicationName not found! Skipped...\n";
127                     }
128                 }
129             }
130         }
131
132         $this->_promptRemainingOptions($applications, $options);
133         $controller->installApplications($applications, $options);
134         
135         if ((isset($options['acceptedTermsVersion']) || array_key_exists('acceptedTermsVersion', $options))) {
136             Setup_Controller::getInstance()->saveAcceptedTerms($options['acceptedTermsVersion']);
137         }
138         
139         echo "Successfully installed " . count($applications) . " applications.\n";
140         return 0;
141     }
142
143     /**
144      * prompt remaining options
145      * 
146      * @param array $_applications
147      * @param array $_options
148      * @return void
149      * 
150      * @todo add required version server side
151      */
152     protected function _promptRemainingOptions($_applications, &$_options)
153     {
154         if (in_array('Tinebase', $_applications)) {
155             
156             if (! isset($_options['acceptedTermsVersion'])) {
157                 fwrite(STDOUT, PHP_EOL . file_get_contents(dirname(dirname(dirname(__FILE__))) . '/LICENSE' ));
158                 $licenseAnswer = Tinebase_Server_Cli::promptInput('I have read the license agreement and accept it (type "yes" to accept)');
159                 
160                 
161                 fwrite(STDOUT, PHP_EOL . file_get_contents(dirname(dirname(dirname(__FILE__))) . '/PRIVACY' ));
162                 $privacyAnswer = Tinebase_Server_Cli::promptInput('I have read the privacy agreement and accept it (type "yes" to accept)');
163             
164                 if (! (strtoupper($licenseAnswer) == 'YES' && strtoupper($privacyAnswer) == 'YES')) {
165                     echo "error: you need to accept the terms! exiting \n";
166                     exit (1);
167                 }
168                 
169                 $_options['acceptedTermsVersion'] = 1;
170             }
171             
172             
173             // initial username
174             if (! isset($_options['adminLoginName'])) {
175                 $_options['adminLoginName'] = Tinebase_Server_Cli::promptInput('Inital Admin Users Username');
176                 if (! $_options['adminLoginName']) {
177                     echo "error: username must be given! exiting \n";
178                     exit (1);
179                 }
180             }
181             
182             // initial password / can be empty => will trigger password change dialogue
183             if (! array_key_exists('adminPassword', $_options)) {
184                 $_options['adminPassword'] = $this->_promptPassword();
185             }
186         }
187     }
188     
189     /**
190      * prompt password
191      * 
192      * @return string
193      */
194     protected function _promptPassword()
195     {
196         $password1 = Tinebase_Server_Cli::promptInput('Admin user password', TRUE);
197         if (! $password1) {
198             echo "Error: Password must not be empty! Exiting ... \n";
199             exit (1);
200         }
201         $password2 = Tinebase_Server_Cli::promptInput('Confirm password', TRUE);
202         if ($password1 !== $password2) {
203             echo "Error: Passwords do not match! Exiting ... \n";
204             exit (1);
205         }
206         
207         return $password1;
208     }
209     
210     /**
211      * update existing applications
212      *
213      * @param Zend_Console_Getopt $_opts
214      * @return integer
215      */
216     protected function _update(Zend_Console_Getopt $_opts)
217     {
218         $maxLoops = 50;
219         do {
220             $result = $this->_updateApplications();
221             if ($_opts->v && ! empty($result['messages'])) {
222                 echo "Messages:\n";
223                 foreach ($result['messages'] as $message) {
224                     echo "  " . $message . "\n";
225                 }
226             }
227             $maxLoops--;
228         } while ($result['updated'] > 0 && $maxLoops > 0);
229         
230         return ($maxLoops > 0) ? 0 : 1;
231     }
232     
233     /**
234      * update all applications
235      * 
236      * @return array
237      */
238     protected function _updateApplications()
239     {
240         $controller = Setup_Controller::getInstance();
241         $applications = Tinebase_Application::getInstance()->getApplications(NULL, 'id');
242         
243         foreach ($applications as $key => &$application) {
244             try {
245                 if (! $controller->updateNeeded($application)) {
246                     unset($applications[$key]);
247                 }
248             } catch (Setup_Exception_NotFound $e) {
249                 Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ 
250                     . ' Failed to check if an application needs an update:' . $e->getMessage());
251                 unset($applications[$key]);
252             }
253         }
254
255         $result = array();
256         if (count($applications) > 0) {
257             $result = $controller->updateApplications($applications);
258             echo "Updated " . $result['updated'] . " application(s).\n";
259         } else {
260             $result['updated'] = 0;
261         }
262         
263         return $result;
264     }
265
266     /**
267      * uninstall applications
268      *
269      * @param Zend_Console_Getopt $_opts
270      */
271     protected function _uninstall(Zend_Console_Getopt $_opts)
272     {
273         $controller = Setup_Controller::getInstance();
274         
275         if($_opts->uninstall === true) {
276             $applications = Tinebase_Application::getInstance()->getApplications(NULL, 'id');
277         } else {
278             $applications = new Tinebase_Record_RecordSet('Tinebase_Model_Application');
279             $applicationNames = explode(',', $_opts->uninstall);
280             foreach($applicationNames as $applicationName) {
281                 $applicationName = ucfirst(trim($applicationName));
282                 try {
283                     $application = Tinebase_Application::getInstance()->getApplicationByName($applicationName);
284                     $applications->addRecord($application);
285                 } catch (Tinebase_Exception_NotFound $e) {
286                 }
287             }
288         }
289         
290         $controller->uninstallApplications($applications->name);
291         
292         echo "Successfully uninstalled " . count($applications) . " applications.\n";
293     }
294     
295     /**
296      * reinstall applications
297      * and reset Demodata
298      * php setup.php --reset_demodata USERNAME
299      * 
300      * @param Zend_Console_Getopt $_opts
301      */
302     protected function _resetDemodata(Zend_Console_Getopt $_opts)
303     {
304         $controller = Setup_Controller::getInstance();
305         $userController = Admin_Controller_User::getInstance();
306         $containerController = Tinebase_Container::getInstance();
307         $cli = new Tinebase_Frontend_Cli();
308         
309         //Don't reset this applications
310         $fixedApplications = array('Tinebase', 'Admin', 'Addressbook');
311         
312         //Log in
313         $opts = $_opts->getRemainingArgs();
314         $username = $opts[0];
315         if (empty($username)) {
316             echo "Username is missing!\n";
317             exit;
318         }
319         $user = Tinebase_User::getInstance()->getUserByLoginName($username);
320         Tinebase_Core::set(Tinebase_Core::USER, $user);
321         
322         //get all applications and remove some
323         $applications = Tinebase_Application::getInstance()->getApplications(NULL, 'id');
324         
325         foreach ($applications as $key => &$application) {
326             if (in_array($application, $fixedApplications)) {
327                 unset($applications[$key]);
328             }
329         }
330         
331         //get set rights
332         $users = Tinebase_Acl_Roles::getInstance()->getRoleByName('user role');
333         $rights = Tinebase_Acl_Roles::getInstance()->getRoleRights($users->getId());
334         
335         //Uninstall Applications
336         try {
337             $controller->uninstallApplications($applications->name);
338             echo "Successfully uninstalled " . count($applications) . " applications.\n";
339         } catch (Tinebase_Exception_NotFound $e) {
340         }
341         //Install Applications
342         try {
343             $controller->installApplications($applications->name);
344             echo "Successfully installed " . count($applications) . " applications.\n";
345         } catch (Tinebase_Exception_NotFound $e) {
346         }
347         
348         //set rights
349         foreach ($applications as $app) {
350             $newApplicationId = Tinebase_Application::getInstance()->getApplicationByName($app->name)->getId();
351             
352             foreach ($rights as &$right) {
353                 if ($right['application_id'] == $app->id) {
354                     $right['application_id'] = $newApplicationId;
355                 }
356             }
357         }
358         
359         Tinebase_Acl_Roles::getInstance()->setRoleRights($users->getId(), $rights);
360         echo "Successfully restored user rights.\n";
361         
362         //Clean up addressbooks
363         $internalContacts = $userController->getDefaultInternalAddressbook();
364         $containers = $containerController->getAll();
365         foreach ($containers as $key => &$container) {
366             if ($container->id == $internalContacts) {
367                 // Do nothing
368             } else {
369                 try {
370                     $containerController->deleteContainer($container, true);
371                 } catch (Exception $e) {
372                 }
373             }
374         }
375         unset($containers);
376         echo "Successfully cleand up containers.\n";
377         
378         //remove state
379         $db = Tinebase_Core::getDb();
380         $statement = "TRUNCATE TABLE " . $db->quoteIdentifier(SQL_TABLE_PREFIX . 'state');
381         $db->query($statement);
382         echo "Successfully truncated state table.\n";
383         
384         //Get Demodata
385         $cli->createAllDemoData();
386         
387         //clear Cache
388         Tinebase_Core::getCache()->clean(Zend_Cache::CLEANING_MODE_ALL);
389         echo "Successfully cleared Cache.\n";
390         
391         echo "Every thing done!\n";
392     }
393
394     /**
395      * Update Import Export Definitions for all applications
396      */
397     protected function _updateAllImportExportDefinitions(Zend_Console_Getopt $_opts){
398
399         $setupUser = Setup_Update_Abstract::getSetupFromConfigOrCreateOnTheFly();
400         if (! Tinebase_Core::getUser() instanceof Tinebase_Model_User) {
401             Tinebase_Core::set(Tinebase_Core::USER, $setupUser);
402         }
403
404         //get all applications
405         $applications = Tinebase_Application::getInstance()->getApplications(NULL, 'id');
406         foreach ($applications as $application) {
407             Setup_Controller::getInstance()->createImportExportDefinitions($application);
408             echo "Update definitions for " . $application->name . "...\n";
409         }
410     }
411     
412     /**
413      * list installed apps
414      */
415     protected function _listInstalled()
416     {
417         try {
418             $applications = Tinebase_Application::getInstance()->getApplications(NULL, 'id');
419         } catch (Zend_Db_Statement_Exception $e) {
420             echo "No applications installed\n";
421             return 1;
422         }
423         
424         echo "Currently installed applications:\n";
425         foreach($applications as $application) {
426             echo "* $application\n";
427         }
428         
429         return 0;
430     }
431     
432     /**
433      * import accounts from ldap
434      *
435      * @param Zend_Console_Getopt $_opts
436      */
437     protected function _importAccounts(Zend_Console_Getopt $_opts)
438     {
439         // disable timelimit during import of user accounts
440         Setup_Core::setExecutionLifeTime(0);
441         
442         // import groups
443         if (! $_opts->onlyusers) {
444             Tinebase_Group::syncGroups();
445         }
446         
447         // import users
448         $options = array('syncContactData' => TRUE);
449         if ($_opts->dbmailldap) {
450             $options['ldapplugins'] = array(
451                 new Tinebase_EmailUser_Imap_LdapDbmailSchema(),
452                 new Tinebase_EmailUser_Smtp_LdapDbmailSchema()
453             );
454         }
455
456         if ($_opts->syncdeletedusers) {
457             $options['deleteUsers'] = true;
458         }
459         if ($_opts->syncaccountstatus) {
460             $options['syncAccountStatus'] = true;
461         }
462         if ($_opts->syncontactphoto) {
463             $options['syncContactPhoto'] = true;
464         }
465
466         Tinebase_User::syncUsers($options);
467     }
468     
469     /**
470      * sync ldap passwords
471      * 
472      * @param Zend_Console_Getopt $_opts
473      */
474     protected function _syncPasswords(Zend_Console_Getopt $_opts)
475     {
476         Tinebase_User::syncLdapPasswords();
477     }
478     
479     /**
480      * import from egw14
481      * 
482      * @param Zend_Console_Getopt $_opts
483      */
484     protected function _egw14Import(Zend_Console_Getopt $_opts)
485     {
486         $args = $_opts->getRemainingArgs();
487         
488         if (count($args) < 1 || ! is_readable($args[0])) {
489             echo "can not open config file \n";
490             echo "see tine20.org/wiki/EGW_Migration_Howto for details \n\n";
491             echo "usage: ./setup.php --egw14import /path/to/config.ini (see Tinebase/Setup/Import/Egw14/config.ini)\n\n";
492             exit(1);
493         }
494         
495         try {
496             $config = new Zend_Config(array(), TRUE);
497             $config->merge(new Zend_Config_Ini($args[0]));
498             $config = $config->merge($config->all);
499         } catch (Zend_Config_Exception $e) {
500             fwrite(STDERR, "Error while parsing config file($args[0]) " .  $e->getMessage() . PHP_EOL);
501             exit(1);
502         }
503         
504         $writer = new Zend_Log_Writer_Stream('php://output');
505         $logger = new Zend_Log($writer);
506         
507         $filter = new Zend_Log_Filter_Priority((int) $config->loglevel);
508         $logger->addFilter($filter);
509         
510         $importer = new Tinebase_Setup_Import_Egw14($config, $logger);
511         $importer->import();
512     }
513     
514     /**
515      * do the environment check
516      *
517      * @return array
518      */
519     protected function _checkRequirements(Zend_Console_Getopt $_opts)
520     {
521         $results = Setup_Controller::getInstance()->checkRequirements();
522         if ($results['success']) {
523           echo "OK - All requirements are met\n";
524         } else {
525           echo "ERRORS - The following requirements are not met: \n";
526           foreach ($results['results'] as $result) {
527             if (!empty($result['message'])) {
528               echo "- " . strip_tags($result['message']) . "\n";
529             }
530           }
531         }
532     }
533     
534     /**
535      * set config
536      *
537      * @return array
538      */
539     protected function _setConfig(Zend_Console_Getopt $_opts)
540     {
541         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
542         $errors = array();
543         if (empty($options['configkey'])) {
544             $errors[] = 'Missing argument: configkey';
545         }
546         if (! isset($options['configvalue'])) {
547             $errors[] = 'Missing argument: configvalue';
548         }
549         $configKey = (string)$options['configkey'];
550         $configValue = self::parseConfigValue($options['configvalue']);
551         $applicationName = (isset($options['app'])) ? $options['app'] : 'Tinebase';
552
553         if (! Tinebase_Application::getInstance()->isInstalled('Tinebase') || ! Tinebase_Application::getInstance()->isInstalled($applicationName)) {
554             $errors[] = $applicationName . ' is not installed';
555         }
556         
557         if (empty($errors)) {
558            Setup_Controller::getInstance()->setConfigOption($configKey, $configValue, $applicationName);
559            echo "OK - Updated configuration option $configKey for application $applicationName\n";
560         } else {
561             echo "ERRORS - The following errors occured: \n";
562             foreach ($errors as $error) {
563                 echo "- " . $error . "\n";
564             }
565         }
566     }
567     
568     /**
569      * get config
570      *
571      */
572     protected function _getConfig(Zend_Console_Getopt $_opts)
573     {
574         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
575         $applicationName = (isset($options['app'])) ? $options['app'] : 'Tinebase';
576
577         $errors = array();
578         if (! Tinebase_Application::getInstance()->isInstalled('Tinebase') || ! Tinebase_Application::getInstance()->isInstalled($applicationName)) {
579             $errors[] = $applicationName . ' is not installed';
580             $config = null;
581         } else {
582             $config = Tinebase_Config_Abstract::factory($applicationName);
583         }
584
585         if (empty($options['configkey'])) {
586             $errors[] = 'Missing argument: configkey';
587             if ($config) {
588                 $errors[] = 'Available config settings:';
589                 $errors[] = print_r($config::getProperties(), true);
590             }
591         }
592         $configKey = (string)$options['configkey'];
593         
594         if (empty($errors)) {
595             $value = $config->get($configKey);
596             $value = is_string($value) ? $value : Zend_Json::encode($value);
597             echo $value . " \n";
598         } else {
599             echo "ERRORS - The following errors occured: \n";
600             foreach ($errors as $error) {
601                 echo "- " . $error . "\n";
602             }
603         }
604     }
605     
606     /**
607      * create admin user / activate existing user / allow to reset password
608      * 
609      * @param Zend_Console_Getopt $_opts
610      * 
611      * @todo check role by rights and not by name
612      * @todo replace echos with stdout logger
613      */
614     protected function _createAdminUser(Zend_Console_Getopt $_opts)
615     {
616         if (! Setup_Controller::getInstance()->isInstalled('Tinebase')) {
617             die('Install Tinebase first.');
618         }
619
620         $setupUser = Setup_Update_Abstract::getSetupFromConfigOrCreateOnTheFly();
621         if (! Tinebase_Core::getUser() instanceof Tinebase_Model_User) {
622             Tinebase_Core::set(Tinebase_Core::USER, $setupUser);
623         }
624
625         echo "Please enter a username. An existing user is reactivated and you can reset the password.\n";
626         $username = strtolower(Tinebase_Server_Cli::promptInput('Username'));
627         $tomorrow = Tinebase_DateTime::now()->addDay(1);
628         
629         try {
630             $user = Tinebase_User::getInstance()->getFullUserByLoginName($username);
631             echo "User $username already exists.\n";
632             Tinebase_User::getInstance()->setStatus($user->getId(), Tinebase_Model_User::ACCOUNT_STATUS_ENABLED);
633             echo "Activated admin user '$username'.\n";
634             
635             $expire = Tinebase_Server_Cli::promptInput('Should the admin user expire tomorrow (default: "no", "y" or "yes" for expiry)?');
636             if ($expire === 'y' or $expire === 'yes') {
637                 Tinebase_User::getInstance()->setExpiryDate($user->getId(), $tomorrow);
638                 echo "User expires tomorrow at $tomorrow.\n";
639             }
640             
641             $resetPw = Tinebase_Server_Cli::promptInput('Do you want to reset the password (default: "no", "y" or "yes" for reset)?');
642             if ($resetPw === 'y' or $resetPw === 'yes') {
643                 $password = $this->_promptPassword();
644                 Tinebase_User::getInstance()->setPassword($user, $password);
645                 echo "User password has been reset.\n";
646             }
647
648             try {
649                 Tinebase_User::getInstance()->assertAdminGroupMembership($user);
650                 echo "Added user to default admin group\n";
651             } catch (Exception $e) {
652                 Tinebase_Exception::log($e);
653                 echo "Could not add user to default admin group: " . $e->getMessage();
654             }
655
656             $this->_checkAdminRole($user);
657             
658         } catch (Tinebase_Exception_NotFound $tenf) {
659             // create new admin user that expires tomorrow
660             $password = $this->_promptPassword();
661             Tinebase_User::createInitialAccounts(array(
662                 'adminLoginName' => $username,
663                 'adminPassword'  => $password,
664                 'expires'        => $tomorrow,
665             ));
666             echo "Created new admin user '$username' that expires tomorrow.\n";
667         }
668     }
669
670
671     /**
672      * check admin role membership
673      * 
674      * @param Tinebase_Model_FullUser $user
675      */
676     protected function _checkAdminRole($user)
677     {
678         $roleMemberships = Tinebase_Acl_Roles::getInstance()->getRoleMemberships($user->getId());
679         $adminRoleFound = FALSE;
680         // TODO allow to configure this / pass it as param
681         $adminRoleName = 'admin role';
682
683         foreach ($roleMemberships as $roleId) {
684             $role = Tinebase_Acl_Roles::getInstance()->getRoleById($roleId);
685             if ($role->name === $adminRoleName) {
686                 $adminRoleFound = TRUE;
687                 break;
688             }
689         }
690
691         if (! $adminRoleFound || ! Tinebase_Acl_Roles::getInstance()->hasRight('Admin', $user->getId(), Tinebase_Acl_Rights::ADMIN)) {
692             echo "Admin role not found for user " . $user->accountLoginName . ".\n";
693
694             try {
695                 $adminRole = Tinebase_Acl_Roles::getInstance()->getRoleByName($adminRoleName);
696             } catch (Tinebase_Exception_NotFound $tenf) {
697                 $adminRole = $this->_createNewAdminRoleForAdmin($adminRoleName);
698             }
699
700             Tinebase_Acl_Roles::getInstance()->setRoleMembers($adminRole->getId(), array(
701                 array(
702                     'id'    => $user->getId(),
703                     'type'  => Tinebase_Acl_Rights::ACCOUNT_TYPE_USER, 
704                 )
705             ));
706             
707             echo "Added user " . $user->accountLoginName . " to role '$adminRoleName''.\n";
708             // @todo clear roles/groups cache
709         }
710     }
711
712     protected function _createNewAdminRoleForAdmin($adminRoleName)
713     {
714         $adminRole = new Tinebase_Model_Role(array(
715             'name'                  => $adminRoleName,
716             'description'           => 'admin role for tine. this role has all rights per default.',
717         ));
718
719         $adminRole = Tinebase_Acl_Roles::getInstance()->createRole($adminRole);
720         // add all rights for all apps
721         $enabledApps = Tinebase_Application::getInstance()->getApplicationsByState(Tinebase_Application::ENABLED);
722         $roleRights = array();
723         foreach ($enabledApps as $application) {
724             $allRights = Tinebase_Application::getInstance()->getAllRights($application->getId());
725             foreach ($allRights as $right) {
726                 $roleRights[] = array(
727                     'application_id' => $application->getId(),
728                     'right'          => $right,
729                 );
730             }
731         }
732         Tinebase_Acl_Roles::getInstance()->setRoleRights($adminRole->getId(), $roleRights);
733
734         return $adminRole;
735     }
736
737     /**
738      * @param Zend_Console_Getopt $_opts
739      * @throws Exception
740      */
741     protected function _backup(Zend_Console_Getopt $_opts)
742     {
743         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
744         Setup_Controller::getInstance()->backup($options);
745     }
746
747     /**
748      * @param Zend_Console_Getopt $_opts
749      * @throws Exception
750      */
751     protected function _restore(Zend_Console_Getopt $_opts)
752     {
753         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
754         Setup_Controller::getInstance()->restore($options);
755     }
756
757     /**
758      * @param Zend_Console_Getopt $_opts
759      * @throws Exception
760      */
761     protected function _installDump(Zend_Console_Getopt $_opts)
762     {
763         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
764         Setup_Controller::getInstance()->installFromDump($options);
765     }
766
767     /**
768      * parse options
769      * 
770      * @param string $_value
771      * @return array|string
772      */
773     public static function parseConfigValue($_value)
774     {
775         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_value, TRUE));
776         
777         // check value is json encoded
778         if (Tinebase_Helper::is_json($_value)) {
779             return Zend_Json::decode($_value); 
780         }
781         
782         $result = array(
783             'active' => 1
784         );
785
786         // keep spaces, \: and \,
787         $_value = preg_replace(array('/ /', '/\\\:/', '/\\\,/', '/\s*/'), array('§', '@', ';', ''), $_value);
788         
789         $parts = explode(',', $_value);
790         
791         foreach ($parts as $part) {
792             $part = str_replace(';', ',', $part);
793             $part = str_replace('§', ' ', $part);
794             $part = str_replace('@', ':', $part);
795             if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $part);
796             if (strpos($part, '_') !== FALSE) {
797                 list($key, $sub) = preg_split('/_/', $part, 2);
798                 if (preg_match('/:/', $sub)) {
799                     list($subKey, $value) = explode(':', $sub);
800                     $result[$key][$subKey] = $value;
801                 } else {
802                     // might be a '_' in the value
803                     if (preg_match('/:/', $part)) {
804                         $exploded = explode(':', $part);
805                         $key = array_shift($exploded);
806                         $result[$key] = implode(':', $exploded);
807                     } else {
808                         throw new Timetracker_Exception_UnexpectedValue('You have an error in the config syntax (":" expected): ' . $part);
809                     }
810                 }
811             } else {
812                 if (strpos($part, ':') !== FALSE) {
813                     list($key, $value) = preg_split('/:/', $part, 2);
814                     $result[$key] = $value;
815                 } else {
816                     $result = $part;
817                 }
818             }
819         }
820
821         return $result;
822     }
823     
824     /**
825      * parse remaining args
826      * 
827      * @param string $_args
828      * @return array
829      */
830     protected function _parseRemainingArgs($_args)
831     {
832         $options = array();
833         foreach ($_args as $arg) {
834             if (strpos($arg, '=') !== FALSE) {
835                 if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $arg);
836                 list($key, $value) = preg_split('/=/', $arg, 2);
837                 $options[$key] = $value;
838             }
839         }
840         
841         return $options;
842     }
843
844     protected function _compare(Zend_Console_Getopt $_opts)
845     {
846         $options = $this->_parseRemainingArgs($_opts->getRemainingArgs());
847         print_r(Setup_Controller::getInstance()->compareSchema($options));
848     }
849 }