PageRenderTime 86ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 0ms

/src/TTinstaller.php

https://github.com/oveas/terra-terra
PHP | 705 lines | 454 code | 43 blank | 208 comment | 71 complexity | 29ef726bb6f21fe5157e85b8b28e6566 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0
  1. <?php
  2. /**
  3. * \file
  4. * \ingroup TT_SO_LAYER
  5. * This file defines the class to install applications
  6. * \copyright{2007-2011} Oscar van Eijk, Oveas Functionality Provider
  7. * \license
  8. * This file is part of Terra-Terra.
  9. *
  10. * Terra-Terra is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * any later version.
  14. *
  15. * Terra-Terra is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with Terra-Terra. If not, see http://www.gnu.org/licenses/.
  22. */
  23. /**
  24. * \ingroup TT_SO_LAYER
  25. * Abstract class to install applications
  26. * \brief Application installer
  27. * \author Oscar van Eijk, Oveas Functionality Provider
  28. * \version Apr 19, 2011 -- O van Eijk -- Initial version for OWL-PHP
  29. */
  30. abstract class TTinstaller
  31. {
  32. /**
  33. * Array with registered rights and their bitvalues
  34. */
  35. private static $rights = array();
  36. /**
  37. * Array with registered groups and their IDs
  38. */
  39. private static $groups = array();
  40. /**
  41. * Preload TT data that can be used during the application install. Skip this when we're installing TT itself
  42. * \author Oscar van Eijk, Oveas Functionality Provider
  43. */
  44. public static function construct()
  45. {
  46. if (defined('TT__BASE__INSTALL')) {
  47. return;
  48. }
  49. $dataset = new DataHandler();
  50. if (ConfigHandler::get ('database', 'tttables', true)) {
  51. $dataset->setPrefix(ConfigHandler::get ('database', 'ttprefix'));
  52. }
  53. $dataset->setTablename('group');
  54. $dataset->set('aid', TT_ID);
  55. $dataset->setKey('aid');
  56. $dataset->prepare();
  57. $dataset->db($_data, __LINE__, __FILE__);
  58. foreach ($_data as $_grp) {
  59. self::$groups[$_grp['groupname'] . '__AID__' . TT_ID] = $_grp['gid'];
  60. }
  61. }
  62. /**
  63. * Register an application in the database
  64. * \param[in] $code Application code
  65. * \param[in] $url URL (relative from the document root) where the application will be installed. When empty or null, defaults to the lowercase application name
  66. * \param[in] $name Name of the application
  67. * \param[in] $version Version number of the application
  68. * \param[in] $released Optional release date of the application
  69. * \param[in] $description Optional description
  70. * \param[in] $link Optional link to the applications homepage
  71. * \param[in] $author Optional name of the copyright holder
  72. * \param[in] $license Optional license
  73. * \return The application ID
  74. * \author Oscar van Eijk, Oveas Functionality Provider
  75. * \todo Error checking
  76. */
  77. private static function installApplication ($code, $url, $name, $version, $released = null, $description = '', $link = '', $author = '', $license = '')
  78. {
  79. OutputHandler::output('Create application ' . $name . ' (' . $code . ')', TT_OUTPUT_NOW);
  80. $dataset = new DataHandler();
  81. if (ConfigHandler::get ('database', 'tttables', true)) {
  82. $dataset->setPrefix(ConfigHandler::get ('database', 'ttprefix'));
  83. }
  84. if (!$url) {
  85. $url = strtolower($name);
  86. }
  87. $dataset->setTablename('applications');
  88. $dataset->set('code', $code);
  89. $dataset->set('url', $url);
  90. $dataset->set('name', $name);
  91. $dataset->set('version', $version);
  92. $dataset->set('released', $released);
  93. $dataset->set('description', $description);
  94. $dataset->set('link', $link);
  95. $dataset->set('author',$author);
  96. $dataset->set('license', $license);
  97. $dataset->set('enabled', '0');
  98. $dataset->prepare(DATA_WRITE);
  99. $dataset->db($_dummy, __LINE__, __FILE__);
  100. return ($dataset->insertedId());
  101. }
  102. /**
  103. * Enable an application
  104. * \param[in] $id Application ID
  105. * \author Oscar van Eijk, Oveas Functionality Provider
  106. */
  107. public static function enableApplication ($id)
  108. {
  109. $dataset = new DataHandler();
  110. if (ConfigHandler::get ('database', 'tttables', true)) {
  111. $dataset->setPrefix(ConfigHandler::get ('database', 'ttprefix'));
  112. }
  113. $dataset->setTablename('applications');
  114. $dataset->set('aid', $id);
  115. $dataset->set('enabled', 1);
  116. $dataset->setKey('aid');
  117. $dataset->prepare(DATA_UPDATE);
  118. $dataset->db($_dummy, __LINE__, __FILE__);
  119. }
  120. /**
  121. * Parse a given SQL file
  122. * \param[in] $fname Full path specification of the file containing SQL statements
  123. * \return An array with all SQL statements from the file, or null when an error occured
  124. * \author Oscar van Eijk, Oveas Functionality Provider
  125. */
  126. public static function parseSQLFile ($fname)
  127. {
  128. if (!file_exists($fname)) {
  129. return null;
  130. }
  131. $statement = '';
  132. $queries = array();
  133. if (!($_fh = fopen($fname, 'r'))) {
  134. return null;
  135. }
  136. while (($_line = fgets($_fh, 4096)) !== false) {
  137. $_line = uncommentLine($_line, TT_COMMENT_SQL);
  138. if (preg_match('/;\s*$/', $_line)) {
  139. $statement .= (' ' . $_line);
  140. TTdbg_add(TTDEBUG_TT_S04, $statement, 'SQL statement');
  141. $queries[] = self::setTablePrefix($statement);
  142. $statement = '';
  143. } elseif ($_line == '') {
  144. continue;
  145. } else {
  146. $statement .= (' ' . $_line);
  147. }
  148. }
  149. fclose($_fh);
  150. return ($queries);
  151. }
  152. /**
  153. * This method adds the tableprefix to all tablenames in an SQL statement as read from the SQL file
  154. * \param $statement Complete SQL statements
  155. * \return Same SQL statement with tables prefix added
  156. * \author Oscar van Eijk, Oveas Functionality Provider
  157. */
  158. private static function setTablePrefix ($statement)
  159. {
  160. $_tablePrefix = ConfigHandler::get ('database', 'ttprefix');
  161. $_checkList = array(
  162. '/CREATE\s+(\w+\s+)?(INDEX)\s+(`?\w+`?)\s+([\s\w]+?)?\s*ON\s+(`)?(\w+)(`)?\s+/i' => "CREATE \${1} \${2} \${3} \${4} ON \${5}$_tablePrefix\${6}\${7} "
  163. ,'/DROP\s+TABLE\s+(IF\s+EXISTS\s+)?(`)?(\w+)(`)?/i' => "DROP TABLE \${1} \${2}$_tablePrefix\${3}\${4} "
  164. ,'/CREATE\s+TABLE\s+(IF\s+NOT\s+EXISTS\s+)?(`)?(\w+)(`)?/i' => "CREATE TABLE \${1} \${2}$_tablePrefix\${3}\${4} "
  165. ,'/REFERENCES\s+(`?)(\w+)(`?)\s+/i' => "REFERENCES \${1}$_tablePrefix\${2}\${3} "
  166. ,'/INSERT\s+INTO\s+(`?)(\w+)(`?)\s+/i' => "INSERT INTO \${1}$_tablePrefix\${2}\${3} "
  167. ,'/FROM\s+(`?)(\w+)(`?)\s+/i' => "FROM \${1}$_tablePrefix\${2}\${3} "
  168. );
  169. foreach ($_checkList as $_pattern => $_replacement) {
  170. if (preg_match($_pattern, $statement)) {
  171. $statement = preg_replace($_pattern, $_replacement, $statement);
  172. }
  173. }
  174. return $statement;
  175. }
  176. /**
  177. * Check an SQL statement and look for table names. When a tablename has been found, the
  178. * table prefix will be added.
  179. *
  180. * The following SQL queries are supported by the regular expressions (with and without backticks):
  181. * - CREATE [TEMPORARY] TABLE [IF NOT EXISTS] `tblname`
  182. * - ALTER [IGNORE] TABLE `tblname`
  183. * - DROP [TEMPORARY] TABLE [IF EXISTS] `tblname`
  184. * - INSERT [insert type] [IGNORE] [INTO] `tblname` (...)
  185. * - CREATE [type] INDEX [name] [using type] ON `tblname` (...)
  186. * \param[in] $q SQL query
  187. * \param[in] $prefix Prefix, or null to use the default
  188. * \return SQL statement with the prefixed tablename
  189. * \todo Add support for UPDATE, DELETE, RENAME and other statements that *might* occur in SQL install files
  190. * \todo Add support for other databases (e.g. Oracle, using quotes iso backticks)
  191. * \todo Handle constraints ([...] REFERENCES `tblname` (...))
  192. * \author Oscar van Eijk, Oveas Functionality Provider
  193. * \deprecated setTablePrefix() is used now
  194. */
  195. private static function addTablePrefix ($q, $prefix)
  196. {
  197. // Abuse a datahandler to get the proper db handler
  198. $_d = new DataHandler();
  199. if ($prefix !== null) {
  200. $_d->setPrefix($prefix);
  201. } else {
  202. $_d->setPrefix(ConfigHandler::get('database', 'prefix', null, true));
  203. }
  204. $db = $_d->getDbLink();
  205. $tblRegEx = '((create|drop|alter)\s+((temporary|ignore)\s+)?(table)(\s*if\s*(not\s*)?(exists))?)';
  206. $idxRegEx = '((create)\s+((unique|fulltext|spatial)\s+)?((index\s+)([a-z_`]+\s*)(using\s+[a-z]+\s+)?on))';
  207. $insRegEx = '((insert)(\s*(low_priority|delayed|high_priority))?(\s*ignore\s*)?(\s*into)?)';
  208. $tblName = '\s+`?([a-z_]+)`?\s*';
  209. $_regexp = "/^\s*($tblRegEx|$idxRegEx|$insRegEx)$tblName/i";
  210. preg_match ($_regexp, $q, $matches);
  211. if (count($matches) > 24) {
  212. $_tblName = $db->tablename($matches[24], true);
  213. $q = preg_replace("/$matches[24]/", $_tblName, $q);
  214. }
  215. return $q;
  216. }
  217. /**
  218. * Execute the queries from a given SQL file to install all tables for this application
  219. * \param[in] $sqlFile Full path specification of the file containing SQL statements
  220. * \param[in] $prefix Table prefix to add if it's not in the SQL file. Specify 'false' to disable adding the prefix
  221. * \return Boolean indicating success (true) or any failure (false)
  222. * \author Oscar van Eijk, Oveas Functionality Provider
  223. */
  224. public static function installTables($sqlFile, $prefix = null)
  225. {
  226. if (($q = self::parseSQLFile($sqlFile)) === null) {
  227. trigger_error('Error reading SQL file ' . $sqlFile, E_USER_ERROR);
  228. return false;
  229. }
  230. if (count($q) == 0) {
  231. return true; // Noting to do
  232. }
  233. $db = TT::factory('DbHandler');
  234. foreach ($q as $_qry) {
  235. // Fix for the MySQL Workbench bug #63956 (http://bugs.mysql.com/bug.php?id=63956)
  236. if (preg_match('/^\s*CREATE\s*(.*?)INDEX\s*.?fk\_/i', $_qry)) {
  237. $_qry = preg_replace('/fk_/', 'fk', $_qry);
  238. }
  239. // if ($prefix !== false) {
  240. // $_qry = self::addTablePrefix($_qry, $prefix);
  241. // }
  242. TTdbg_add(TTDEBUG_TT_LOOP, $_qry, 'SQL statement');
  243. $_logPtrn = '/((create|drop|alter)\s+((temporary|ignore)\s+)?(table)(\s*if\s*(not\s*)?(exists))?)\s+(`)?(\w+)(`)/i';
  244. if (preg_match($_logPtrn, $_qry, $_m)) {
  245. OutputHandler::output(ucfirst(strtolower($_m[2])) . ' table ' . $_m[10], TT_OUTPUT_NOW);
  246. }
  247. $db->setQuery ($_qry);
  248. $db->write($_dummy, __LINE__, __FILE__);
  249. }
  250. return true;
  251. }
  252. /**
  253. * Set the rights bitvalue for a given group
  254. * \param[in] $aid Application ID.
  255. * \param[in] $grp Group name. This can be an existing TT group
  256. * \param[in] $rights Array with right identifiers
  257. * \return Boolean indicating success (true) or any failure (false)
  258. * \author Oscar van Eijk, Oveas Functionality Provider
  259. */
  260. private static function addGroupRights($aid, $grp, array $rights)
  261. {
  262. if (array_key_exists($grp . '__AID__' . $aid, self::$groups)) {
  263. $_grpID = self::$groups[$grp . '__AID__' . $aid];
  264. } else {
  265. if (array_key_exists($grp . '__AID__' . TT_ID, self::$groups)) {
  266. $_grpID = self::$groups[$grp . '__AID__' . TT_ID];
  267. } else {
  268. trigger_error('Group ' . $grp . ' has not been registered yet', E_USER_ERROR);
  269. return false;
  270. }
  271. }
  272. $_val = 0;
  273. foreach ($rights as $_r) {
  274. if (!array_key_exists($_r, self::$rights)) {
  275. trigger_error('Rightsbit ' . $_r . ' has not been registered yet', E_USER_ERROR);
  276. return false;
  277. }
  278. OutputHandler::output('Adding right ' . $_r . ' to group ' . $grp, TT_OUTPUT_NOW);
  279. $_val += self::$rights[$_r];
  280. }
  281. $dataset = new DataHandler();
  282. if (ConfigHandler::get ('database', 'tttables', true)) {
  283. $dataset->setPrefix(ConfigHandler::get ('database', 'ttprefix'));
  284. }
  285. $dataset->setTablename('grouprights');
  286. $dataset->set('aid', $aid);
  287. $dataset->set('gid', $_grpID);
  288. $dataset->set('right', $_val);
  289. $dataset->prepare(DATA_WRITE);
  290. $dataset->db($_dummy, __LINE__, __FILE__);
  291. return (true);
  292. }
  293. /**
  294. * Add the application specific groups to the database
  295. * \param[in] $aid Application ID
  296. * \param[in] $grps Array of groups in the format (groupname => groupdescription)
  297. * \return Boolean indicating success (true) or any failure (false)
  298. * \author Oscar van Eijk, Oveas Functionality Provider
  299. */
  300. private static function addGroups($aid, array $grps)
  301. {
  302. $dataset = new DataHandler();
  303. if (ConfigHandler::get ('database', 'tttables', true)) {
  304. $dataset->setPrefix(ConfigHandler::get ('database', 'ttprefix'));
  305. }
  306. $dataset->setTablename('group');
  307. foreach ($grps as $_grp => $_desc) {
  308. OutputHandler::output('Add group ' . $_grp, TT_OUTPUT_NOW);
  309. $dataset->set('groupname', $_grp);
  310. $dataset->set('description', $_desc);
  311. $dataset->set('aid', $aid);
  312. $dataset->prepare(DATA_WRITE);
  313. $dataset->db($_dummy, __LINE__, __FILE__);
  314. $_id = $dataset->insertedId();
  315. self::$groups[$_grp . '__AID__' . $aid] = $_id;
  316. }
  317. return true;
  318. }
  319. /**
  320. * Add the application specific rights to the database
  321. * \param[in] $aid Application ID
  322. * \param[in] $rights Array of rights in the format name => description
  323. * \return Boolean indicating success (true) or any failure (false)
  324. * \author Oscar van Eijk, Oveas Functionality Provider
  325. */
  326. private static function addRights($aid, array $rights)
  327. {
  328. $dataset = new DataHandler();
  329. if (ConfigHandler::get ('database', 'tttables', true)) {
  330. $dataset->setPrefix(ConfigHandler::get ('database', 'ttprefix'));
  331. }
  332. $dataset->setTablename('rights');
  333. $dataset->set('aid', $aid);
  334. $dataset->set('rid', null, null
  335. ,array('function' => array('max')
  336. ,'name' => array('rid'))
  337. ,array('match' => array(DBMATCH_NONE))
  338. );
  339. $dataset->prepare();
  340. $dataset->db($_rid, __LINE__, __FILE__);
  341. if (count($_rid) == 0) {
  342. $rid = 1;
  343. } else {
  344. $rid = $_rid[0]['rid'] + 1;
  345. }
  346. $dataset->reset(DATA_RESET_FULL);
  347. foreach ($rights as $_right => $_descr) {
  348. OutputHandler::output('Create rightsbit ' . $_right, TT_OUTPUT_NOW);
  349. $dataset->set('rid', $rid);
  350. $dataset->set('name', $_right);
  351. $dataset->set('aid', $aid);
  352. $dataset->set('description', $_descr);
  353. $dataset->prepare(DATA_WRITE);
  354. $dataset->db($_dummy, __LINE__, __FILE__);
  355. self::$rights[$_right] = pow(2, $rid-1);
  356. $rid++;
  357. }
  358. return true;
  359. }
  360. /**
  361. * Add an application specific dynamic config item. It is set or overwritten in the current
  362. * configuration immediately.
  363. * \param[in] $aid Application ID
  364. * \param[in] $section Name of the configuration section
  365. * \param[in] $item Name of the configuration item
  366. * \param[in] $value Value of the configuration item
  367. * \param[in] $protect True if this is a protected item
  368. * \param[in] $hide True if this is an hidden item
  369. * \param[in] $group An optional groupname to which this item belongs
  370. * \return Boolean indicating success (true) or any failure (false)
  371. * \author Oscar van Eijk, Oveas Functionality Provider
  372. */
  373. private static function addConfig ($aid, $section, $item, $value, $protect = false, $hide = false, $group = null)
  374. {
  375. if ($group === null) {
  376. $_grpID = 0;
  377. } else {
  378. if (array_key_exists($grp . '__AID__' . $aid, self::$groups)) {
  379. $_grpID = self::$groups[$grp . '__AID__' . $aid];
  380. } else {
  381. trigger_error('Group ' . $grp . ' has not been registered yet', E_USER_ERROR);
  382. return false;
  383. }
  384. }
  385. $dataset = new DataHandler();
  386. if (ConfigHandler::get ('database', 'tttables', true)) {
  387. $dataset->setPrefix(ConfigHandler::get ('database', 'ttprefix'));
  388. }
  389. OutputHandler::output('Set configuration item [' . $section . ']->' . $item . ' with value ' . $value, TT_OUTPUT_NOW);
  390. $_secId = ConfigHandler::configSection($section, true);
  391. $dataset->setTablename('config');
  392. $dataset->set('aid', $aid);
  393. $dataset->set('gid', $_grpID);
  394. $dataset->set('uid', 0);
  395. $dataset->set('sid', $_secId);
  396. $dataset->set('name', $item);
  397. $dataset->set('value', $value);
  398. $dataset->set('protect', ($protect === true)?1:0);
  399. $dataset->set('hide', ($hide === true)?1:0);
  400. $dataset->prepare(DATA_WRITE);
  401. $dataset->db($_dummy, __LINE__, __FILE__);
  402. ConfigHandler::set($section, $item, $value, true);
  403. return (true);
  404. }
  405. /**
  406. *Add a user for this application
  407. * \param[in] $aid Application ID
  408. * \param[in] $username Given username
  409. * \param[in] $password Given password
  410. * \param[in] $email Given username
  411. * \param[in] $group Name of the primary group
  412. * \param[in] $memberships Array with groupnames for additional memberships
  413. * \return True on success
  414. * \note The default group and the additional memberships must be part of the application being installed
  415. * If no primary group is given, the new user will be member of the default group from the TT configuration
  416. * \author Oscar van Eijk, Oveas Functionality Provider
  417. */
  418. private static function addUser($aid, $username, $password, $email, $group, $memberships = null)
  419. {
  420. $grpObj = new Group();
  421. $group = $grpObj->getGroupByName($group, $aid);
  422. if (TTInstallerUser::getReference()->registerUser($aid, $username, $password, $email, $group, $memberships) < 0) {
  423. return false;
  424. }
  425. OutputHandler::output('User ' . $username . ' added in group ' . $group, TT_OUTPUT_NOW);
  426. return true;
  427. }
  428. /**
  429. * Method to install an application using an XML file
  430. * \param[in] unknown $xmlFile
  431. * \return New application ID or false on failures
  432. * \todo Improved error handling, user input, configuration settings, layout, generate .htaccess for the ttadmin directory, logging to browser and a hell of a lot more....
  433. */
  434. public static function installXMLFile($xmlFile)
  435. {
  436. TTloader::getClass('xmlhandler', TT_BO_INC);
  437. $xmlInstaller = new XmlHandler($xmlFile);
  438. $xmlInstaller->parse();
  439. if ($xmlInstaller->childExists('sqlfiles')) {
  440. // Load the SQL installation script(s)
  441. for ($_cnt = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("sqlfiles/script,$_cnt")) !== null; $_cnt++) {
  442. $_xmlData = $xmlInstaller->getNodeData($_xmlObj);
  443. self::installTables(TT_ROOT . $_xmlData['name'], false);
  444. }
  445. }
  446. // Get the application rootnode
  447. if (($_xmlObj = $xmlInstaller->getNodeByPath()) === null) {
  448. trigger_error('Error fetching the \'application\' rootnode', E_USER_ERROR);
  449. return false;
  450. }
  451. // Check for presence of all required attributes
  452. $_xmlData = $xmlInstaller->getNodeData($_xmlObj);
  453. if (!array_key_exists('code', $_xmlData)) {
  454. trigger_error('application code not set', E_USER_ERROR);
  455. return false;
  456. }
  457. if (!array_key_exists('url', $_xmlData)) {
  458. trigger_error('application url not set', E_USER_ERROR);
  459. return false;
  460. }
  461. if (!array_key_exists('name', $_xmlData)) {
  462. trigger_error('application name not set', E_USER_ERROR);
  463. return false;
  464. }
  465. if (!array_key_exists('version', $_xmlData)) {
  466. trigger_error('application version not set', E_USER_ERROR);
  467. return false;
  468. }
  469. // Load the application
  470. $_applicationID = self::installApplication(
  471. $_xmlData['code']
  472. ,$_xmlData['url']
  473. ,$_xmlData['name']
  474. ,$_xmlData['version']
  475. ,array_key_exists('released',$_xmlData) ? $_xmlData['released'] : null
  476. ,array_key_exists('description',$_xmlData) ? $_xmlData['description'] : ''
  477. ,array_key_exists('link',$_xmlData) ? $_xmlData['link'] : ''
  478. ,array_key_exists('author',$_xmlData) ? $_xmlData['author'] : ''
  479. ,array_key_exists('license',$_xmlData) ? $_xmlData['license'] : ''
  480. );
  481. if ($xmlInstaller->childExists('configuration')) {
  482. // Load the configuration
  483. for ($_cntC = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("configuration,$_cntC")) !== null; $_cntC++) {
  484. // configuration itself has no data, continue with the sections
  485. for ($_cntS = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("configuration,$_cntC/items,$_cntS")) !== null; $_cntS++) {
  486. // configuration itself has no data, continue with the sections
  487. $_xmlData = $xmlInstaller->getNodeData($_xmlObj);
  488. if (!array_key_exists('section', $_xmlData)) {
  489. trigger_error("No section name in path 'configuration,$_cntC/items,$_cntS'", E_USER_ERROR);
  490. return false;
  491. }
  492. $_sectionName = $_xmlData['section'];
  493. // Get all items for this section
  494. for ($_cntI = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("configuration,$_cntC/items,$_cntS/item,$_cntI")) !== null; $_cntI++) {
  495. $_xmlData = $xmlInstaller->getNodeData($_xmlObj);
  496. if (!array_key_exists('id', $_xmlData)) {
  497. trigger_error("No item id in path 'configuration,$_cntC/items,$_cntS'/item,$_cntI", E_USER_ERROR);
  498. return false;
  499. }
  500. // Store this configuration item
  501. self::addConfig($_applicationID, $_sectionName, $_xmlData[ 'id'], $_xmlData['_TTnodeText']);
  502. }
  503. }
  504. }
  505. }
  506. if ($xmlInstaller->childExists('rights')) {
  507. // Get all application rights
  508. $_rights = array();
  509. for ($_cntR = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("rights,$_cntR")) !== null; $_cntR++) {
  510. // rights element itself has no data
  511. for ($_cntI = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("rights,$_cntR/right,$_cntI")) !== null; $_cntI++) {
  512. $_xmlData = $xmlInstaller->getNodeData($_xmlObj);
  513. if (!array_key_exists('id', $_xmlData)) {
  514. trigger_error("No rights id in path 'rights,$_cntR/right,$_cntI'", E_USER_ERROR);
  515. return false;
  516. }
  517. $_rights[$_xmlData['id']] = $_xmlData['_TTnodeText'];
  518. }
  519. }
  520. // Store the application rights
  521. self::addRights($_applicationID, $_rights);
  522. }
  523. if ($xmlInstaller->childExists('groups')) {
  524. // Create groups
  525. $_groups = array();
  526. $_groupRights = array();
  527. for ($_cntG = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("groups,$_cntG")) !== null; $_cntG++) {
  528. // group element itself has no data
  529. for ($_cntN = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("groups,$_cntG/group,$_cntN")) !== null; $_cntN++) {
  530. // Fetch group data
  531. $_xmlData = $xmlInstaller->getNodeData($_xmlObj);
  532. if (!array_key_exists('name', $_xmlData)) {
  533. trigger_error("No groupname in path 'groups,$_cntG/group,$_cntN'", E_USER_ERROR);
  534. return false;
  535. }
  536. $_groupName = $_xmlData['name'];
  537. $_groups[$_groupName] = (array_key_exists('description', $_xmlData) ? $_xmlData[ 'description'] : '');
  538. // Continue with the grouprights
  539. $_grpRights = array();
  540. for ($_cntI = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("groups,$_cntG/group,$_cntN/right,$_cntI")) !== null; $_cntI++) {
  541. $_xmlData = $xmlInstaller->getNodeData($_xmlObj);
  542. // TODO check if the right exists, might be from this XML or an already existing right ID
  543. $_grpRights[] = $_xmlData['_TTnodeText'];
  544. }
  545. // Save the grouprights
  546. $_groupRights[$_groupName] = $_grpRights;
  547. }
  548. self::addGroups($_applicationID, $_groups);
  549. }
  550. // Now store the grouprights
  551. foreach ($_groupRights as $_groupName => $_grpRights) {
  552. self::addGroupRights($_applicationID, $_groupName, $_grpRights);
  553. }
  554. }
  555. if ($xmlInstaller->childExists('users')) {
  556. // Store the users
  557. for ($_cntU = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("users,$_cntU")) !== null; $_cntU++) {
  558. // users element itself has no data
  559. for ($_cntN = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("users,$_cntU/user,$_cntN")) !== null; $_cntN++) {
  560. // Fetch user data
  561. $_xmlData = $xmlInstaller->getNodeData($_xmlObj);
  562. if (!array_key_exists('name', $_xmlData)) {
  563. trigger_error("No username in path 'users,$_cntU/user,$_cntN'", E_USER_ERROR);
  564. return false;
  565. }
  566. if (!array_key_exists('group', $_xmlData)) {
  567. trigger_error("No primary group in path 'groups,$_cntU/user,$_cntN'", E_USER_ERROR);
  568. return false;
  569. }
  570. $_userName = $_xmlData['name'];
  571. $_userGroup = $_xmlData['group'];
  572. $_userPassword = (array_key_exists('password', $_xmlData) ? $_xmlData[ 'password'] : '');
  573. $_userEmail = (array_key_exists('email', $_xmlData) ? $_xmlData[ 'email'] : '');
  574. // Continue with the memberships
  575. $_memberShips = array();
  576. for ($_cntM = 0; ($_xmlObj = $xmlInstaller->getNodeByPath("users,$_cntU/user,$_cntN/membership,$_cntM")) !== null; $_cntM++) {
  577. $_xmlData = $xmlInstaller->getNodeData($_xmlObj);
  578. // TODO check if the group exists, might be from this XML or an already existing right ID when this installer is generalised
  579. $_memberShips[] = $_xmlData['_TTnodeText'];
  580. }
  581. // Store the users
  582. self::addUser(
  583. $_applicationID
  584. ,$_userName
  585. ,$_userPassword
  586. ,$_userEmail
  587. ,$_userGroup
  588. ,$_memberShips
  589. );
  590. }
  591. }
  592. }
  593. return $_applicationID;
  594. }
  595. }
  596. // TT_ROOT must be defined by the application
  597. if (!defined('TT_ROOT')) {
  598. trigger_error('TT_ROOT must be defined by the application', E_USER_ERROR);
  599. }
  600. // Make sure the loader does not attempt to load the application
  601. define('TT___INSTALLER', 1);
  602. require (TT_ROOT . '/TTloader.php');
  603. /**
  604. * Helper class to add users during the installation process
  605. * \brief TTInstallerUser User
  606. * \author Oscar van Eijk, Oveas Functionality Provider
  607. * \version Nov 22, 2011 -- O van Eijk -- initial version
  608. */
  609. class TTInstallerUser extends User
  610. {
  611. /**
  612. * Self reference
  613. */
  614. private static $instance;
  615. /**
  616. * Object constructor
  617. */
  618. private function __construct()
  619. {
  620. parent::construct();
  621. TTInstallerUser::$instance = $this;
  622. }
  623. /**
  624. * Instantiate the singleton or return its reference
  625. */
  626. static public function getReference()
  627. {
  628. if (!TTInstallerUser::$instance instanceof TTInstallerUser) {
  629. TTInstallerUser::$instance = new self();
  630. }
  631. return TTInstallerUser::$instance;
  632. }
  633. /**
  634. * Register a new username
  635. * \param[in] $aid Application ID
  636. * \param[in] $username Given username
  637. * \param[in] $password Given password
  638. * \param[in] $email Given username
  639. * \param[in] $group Primary Group
  640. * \param[in] $memberships Array with additional memberships
  641. * \return New user ID or -1 on failure
  642. * \author Oscar van Eijk, Oveas Functionality Provider
  643. */
  644. public function registerUser($aid, $username, $password, $email, $group, $memberships)
  645. {
  646. if (($_uid = parent::register($username, $email, $password, $password, $group, false)) < 0) {
  647. return -1;
  648. }
  649. if ($memberships !== null) {
  650. foreach ($memberships as $_grp) {
  651. if (parent::addMembership($_grp, $aid, $_uid) === false) {
  652. ; // Ignore failures here
  653. }
  654. }
  655. }
  656. return $_uid;
  657. }
  658. }
  659. TTinstaller::construct();
  660. if (TTCache::get(TTCACHE_OBJECTS, 'user') === null) {
  661. TTInstallerUser::getReference(); // Force the user object to exist in cache
  662. }