PageRenderTime 58ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/cognifty/modules/install/main.php

https://github.com/markkimsal/cognifty
PHP | 502 lines | 387 code | 83 blank | 32 comment | 58 complexity | d5e8c8464983232f9d66b8fe2d6cf55c MD5 | raw file
  1. <?php
  2. Cgn::loadLibrary('Form::lib_cgn_form');
  3. class Cgn_Service_Install_Main extends Cgn_Service {
  4. public function Cgn_Service_Install_Main () {
  5. $this->templateStyle = 'install';
  6. }
  7. /**
  8. * Attempt to load up a published article and show it
  9. */
  10. function mainEvent(&$req, &$t) {
  11. if (!file_exists(BASE_DIR.'var/search_cache')) {
  12. @mkdir (BASE_DIR.'var/search_cache');
  13. }
  14. //check for config writability
  15. $t['core'] = is_writable(CGN_BOOT_DIR.'local');
  16. $t['var'] = is_writable(BASE_DIR.'var');
  17. $t['search'] = is_writable(BASE_DIR.'var/search_cache');
  18. $t['complete'] = file_exists(CGN_BOOT_DIR.'local/core.ini');
  19. }
  20. function askDsnEvent(&$req, &$t) {
  21. $u = $req->getUser();
  22. if ($this->_installComplete() ) {
  23. header('HTTP/1.1 403 Forbidden');
  24. $this->templateName = 'main_denied';
  25. $u->addMessage('You cannot run the installer on an installed system.', 'msg_warn');
  26. return FALSE;
  27. }
  28. }
  29. public function checkDbEvent($req, &$t) {
  30. $host = $req->cleanString('db_host');
  31. $user = $req->cleanString('db_user');
  32. $pass = $req->cleanString('db_pass');
  33. $schema = $req->cleanString('db_schema');
  34. $driver = $req->cleanString('db_driver');
  35. $host2 = $req->cleanString('db2_host');
  36. $user2 = $req->cleanString('db2_user');
  37. $pass2 = $req->cleanString('db2_pass');
  38. $schema2 = $req->cleanString('db2_schema');
  39. $driver2 = $req->cleanString('db2_driver');
  40. $uri2 = $req->cleanString('db2_uri');
  41. $dsn = $driver."://".$user.":".$pass."@".$host."/".$schema;
  42. Cgn_ObjectStore::storeConfig("dsn://default.uri", $dsn);
  43. $db = Cgn_Db_Connector::getHandle();
  44. $db->disconnect();
  45. $db = null;
  46. //reset the already created DB handle
  47. $dsnPool =& Cgn_ObjectStore::getObject('object://defaultDatabaseLayer');
  48. if (!$dsnPool->createHandle('default') ) {
  49. die('dsf');
  50. $dsn = 'default';
  51. }
  52. $db = Cgn_Db_Connector::getHandle();
  53. $schemaCreated = true;
  54. if ($db->driverId && !$db->isSelected) {
  55. //try to create the DB
  56. $schemaCreated = $db->exec('CREATE DATABASE `'.$db->database.'`');
  57. if ($schemaCreated && mysql_select_db($db->database, $db->driverId) ) {
  58. // __TODO__ perhaps we should throw an error and eat it up somewhere else?
  59. $db->isSelected = true;
  60. }
  61. }
  62. //succeeded
  63. if ($db->isSelected && $schemaCreated) {
  64. $this->presenter = 'redirect';
  65. $t['url'] = cgn_appurl('install', 'main', 'writeConf', $_POST);
  66. return true;
  67. }
  68. $u = $req->getUser();
  69. $u->addSessionMessage("Cannot use the chosen database. Please make sure the database is created and username and password are correct.", 'msg_warn');
  70. $this->presenter = 'redirect';
  71. $t['url'] = cgn_appurl('install', 'main', 'askDsn');
  72. return true;
  73. //failed
  74. die('failed');
  75. }
  76. public function writeConfEvent(&$req, &$t) {
  77. if ($this->_installComplete() ) {
  78. header('HTTP/1.1 403 Forbidden');
  79. $this->templateName = 'main_denied';
  80. $u->addMessage('You cannot run the installer on an installed system.', 'msg_warn');
  81. return FALSE;
  82. }
  83. $host = $req->cleanString('db_host');
  84. $user = $req->cleanString('db_user');
  85. $pass = $req->cleanString('db_pass');
  86. $schema = $req->cleanString('db_schema');
  87. $driver = $req->cleanString('db_driver');
  88. $host2 = $req->cleanString('db2_host');
  89. $user2 = $req->cleanString('db2_user');
  90. $pass2 = $req->cleanString('db2_pass');
  91. $schema2 = $req->cleanString('db2_schema');
  92. $driver2 = $req->cleanString('db2_driver');
  93. $uri2 = $req->cleanString('db2_uri');
  94. if ($user == '') {
  95. die('lost the user variable, can\'t write conf file.');
  96. }
  97. if ($driver == '') {
  98. $driver = 'mysql';
  99. }
  100. $dsn = $driver."://".$user.":".$pass."@".$host."/".$schema;
  101. //handle extra driver
  102. if (!empty($uri2)) {
  103. $uri2line = $uri2.'='.$driver2."://".$user2.":".$pass2."@".$host2."/".$schema2;
  104. }
  105. //just open the file and pass through everything except the line that starts with "default.uri"
  106. $ini = file_get_contents(CGN_BOOT_DIR.'core.ini');
  107. $lines = explode("\n",$ini);
  108. unset($ini);
  109. $size = strlen('default.uri');
  110. $newIni = '';
  111. foreach ($lines as $line) {
  112. if (substr($line,0,$size) == 'default.uri') {
  113. $newIni .= 'default.uri='.$dsn."\n";
  114. if (isset($uri2line)) {
  115. $newIni .= $uri2line."\n";
  116. }
  117. } else {
  118. $newIni .= $line."\n";
  119. }
  120. }
  121. $newIni = trim($newIni);
  122. $f = fopen(CGN_BOOT_DIR.'local/core.ini','w');
  123. fputs($f,$newIni,strlen($newIni));
  124. fclose($f);
  125. unset($newIni);
  126. //open defaults and switch out this installer as the main module.
  127. $ini = file_get_contents(CGN_BOOT_DIR.'default.ini');
  128. $lines = explode("\n",$ini);
  129. unset($ini);
  130. $size = strlen('module');
  131. $newIni = '';
  132. foreach ($lines as $line) {
  133. if (substr($line,0,$size) == 'module') {
  134. $newIni .= 'module=main'."\n";
  135. } else {
  136. $newIni .= $line."\n";
  137. }
  138. }
  139. $newIni = trim($newIni);
  140. $f = fopen(CGN_BOOT_DIR.'local/default.ini','w');
  141. fputs($f,$newIni,strlen($newIni));
  142. fclose($f);
  143. unset($newIni);
  144. $this->writeLocal('signal.ini');
  145. //clear the cache
  146. if (file_exists(CGN_BOOT_DIR.'bootstrap.cache')) {
  147. unlink(CGN_BOOT_DIR.'bootstrap.cache');
  148. }
  149. }
  150. public function writeLocal($iniFile) {
  151. $ini = file_get_contents(CGN_BOOT_DIR.$iniFile);
  152. $newIni = trim($ini);
  153. $f = fopen(CGN_BOOT_DIR.'local/'.$iniFile,'w');
  154. fputs($f,$newIni,strlen($newIni));
  155. fclose($f);
  156. }
  157. public function insertDataEvent($req, &$t) {
  158. if ($this->_installComplete() ) {
  159. header('HTTP/1.1 403 Forbidden');
  160. $this->templateName = 'main_denied';
  161. $u->addMessage('You cannot run the installer on an installed system.', 'msg_warn');
  162. return FALSE;
  163. }
  164. $db = Cgn_Db_Connector::getHandle();
  165. if ($db->driverId === false) {
  166. trigger_error("Cannot connect to database with given parameters. <a href=\"".cgn_appurl('install', 'main', 'askDsn')."\">Go back</a> and re-enter database connection information.");
  167. return true;
  168. }
  169. if (!$db->isSelected) {
  170. //try to create the DB
  171. $x = $db->exec('CREATE DATABASE `'.$db->database.'`');
  172. //var_dump('CREATE DATABASE `'.$db->database.'`');
  173. if (mysql_select_db($db->database, $db->driverId) ) {
  174. // __TODO__ perhaps we should throw an error and eat it up somewhere else?
  175. $db->isSelected = true;
  176. }
  177. }
  178. $thisdir = dirname(__FILE__);
  179. $d = dir($thisdir.'/sql/mysql');
  180. $totalFiles = 0;
  181. $listFiles = array();
  182. while (false !== ($entry = $d->read())) {
  183. //avoid old files
  184. if (substr($entry, -1) === '~') { continue; }
  185. if (strstr($entry, '.mysql.sql') !== FALSE) {
  186. $totalFiles++;
  187. $listFiles[] = $entry;
  188. }
  189. }
  190. $d->close();
  191. // for ($x=1; $x <= $totalFiles; $x++) {
  192. foreach ($listFiles as $file) {
  193. $schema = file_get_contents($thisdir.'/sql/mysql/'.$file);
  194. $queries = $this->splitMlQuery($schema);
  195. foreach ($queries as $q) {
  196. if (!$db->query($q)) {
  197. if (strstr($db->errorMessage, 'IF EXISTS')) {
  198. $e = Cgn_ErrorStack::pullError('php');
  199. continue;
  200. }
  201. if (strstr($db->errorMessage, 'already exists')) {
  202. $e = Cgn_ErrorStack::pullError('php');
  203. continue;
  204. }
  205. if (strstr($db->errorMessage, 'Duplicate')) {
  206. $e = Cgn_ErrorStack::pullError('php');
  207. continue;
  208. }
  209. if (!$db->isSelected) {
  210. $u = $req->getUser();
  211. $u->addSessionMessage("Cannot use the chosen database. Please make sure the database is created and username and password are correct.", 'msg_warn');
  212. $this->presenter = 'redirect';
  213. $t['url'] = cgn_appurl('install', 'main', 'askDsn');
  214. return true;
  215. }
  216. echo "query failed. ($x)\n";
  217. echo $db->errorMessage."\n";
  218. print_r($q);
  219. exit();
  220. return false;
  221. }
  222. }
  223. }
  224. //redirect here to avoid refreshes
  225. $this->presenter = 'redirect';
  226. $t['url'] = cgn_appurl('install', 'main', 'askTemplate');
  227. }
  228. /**
  229. * Load the template with necessary info to display the
  230. * template config screen.
  231. */
  232. function askTemplateEvent($req, &$t) {
  233. $t['site_name'] = Cgn_Template::siteName();
  234. $t['site_tag'] = Cgn_Template::siteTagLine();
  235. $t['form'] = $this->_loadFormTemplate();
  236. $emailForm = $this->_loadFormEmail();
  237. $t['form']->addSubForm($emailForm);
  238. }
  239. function writeTemplateEvent(&$req, &$t) {
  240. if ($this->_installComplete() ) {
  241. header('HTTP/1.1 403 Forbidden');
  242. $this->templateName = 'main_denied';
  243. $u->addMessage('You cannot run the installer on an installed system.', 'msg_warn');
  244. return FALSE;
  245. }
  246. $name = $req->cleanString('site_name');
  247. $tag = $req->cleanString('site_tag');
  248. $ssl = $req->cleanString('ssl_port');
  249. $tpl = $req->cleanString('template_name');
  250. $em1 = $req->cleanString('email_contact_us');
  251. $em2 = $req->cleanString('email_default_from');
  252. $em3 = $req->cleanString('email_error_notify');
  253. if ($name == '') {
  254. die('lost the site name variable, can\'t write conf file.');
  255. }
  256. $replaces = array(
  257. 'site.name' => $name,
  258. 'site.tagline'=>$tag,
  259. 'default.name'=>$tpl,
  260. 'ssl.port' => $ssl);
  261. //just open the file and pass through everything except the line that starts with "default.uri"
  262. $this->_rewriteIni('template.ini', $replaces);
  263. $replaces = array(
  264. 'email.contactus' => $em1,
  265. 'email.errornotify' => $em3,
  266. 'email.defaultfrom' => $em2);
  267. //just open the file and pass through everything except the line that starts with "default.uri"
  268. $this->_rewriteIni('default.ini', $replaces, true);
  269. //redirect here to avoid refreshes
  270. $this->presenter = 'redirect';
  271. $t['url'] = cgn_appurl('install', 'data');
  272. }
  273. function askAdminEvent($req, &$t) {
  274. //suggest a random password
  275. $t['pass'] = base_convert( rand(9000000,10000000), 10, 24);
  276. }
  277. function setupAdminEvent(&$req, &$t) {
  278. $u = $req->getUser();
  279. if ($this->_installComplete() ) {
  280. header('HTTP/1.1 403 Forbidden');
  281. $this->templateName = 'main_denied';
  282. $u->addMessage('You cannot run the installer on an installed system.', 'msg_warn');
  283. return FALSE;
  284. }
  285. $db = Cgn_Db_Connector::getHandle();
  286. $user = "INSERT INTO cgn_user
  287. (username, password, active_on)
  288. VALUES ('".$req->cleanString('adm_user')."',
  289. '".Cgn_User::_hashPassword($req->cleanString('adm_pass'))."',
  290. '".time()."'
  291. )";
  292. $group = "INSERT INTO cgn_group
  293. (code, display_name, active_on)
  294. VALUES ('admin',
  295. 'Site Admins',
  296. '".time()."'
  297. )";
  298. $link = "INSERT INTO cgn_user_group_link
  299. (cgn_group_id, cgn_user_id, active_on)
  300. VALUES (1,
  301. 1,
  302. '".time()."'
  303. )";
  304. if (!$db->query($user)) {
  305. Cgn_ErrorStack::throwError("Could not make admin user, installation *not* complete.", "480");
  306. return false;
  307. }
  308. if (!$db->query($group)) {
  309. Cgn_ErrorStack::throwError("Could not make admin user, installation *not* complete.", "480");
  310. return false;
  311. }
  312. if (!$db->query($link)) {
  313. Cgn_ErrorStack::throwError("Could not make admin user, installation *not* complete.", "480");
  314. return false;
  315. }
  316. }
  317. /**
  318. * Split a multi-line query into multiple single queries.
  319. *
  320. * @return Array
  321. */
  322. public function splitMlQuery($mlQuery) {
  323. $queries = array();
  324. $cleanSchemas = array();
  325. $mlQuery = str_replace("; \n", ";\n", $mlQuery);
  326. $queries[] = explode(";\n", $mlQuery);
  327. foreach ($queries as $_idx => $manyDefs) {
  328. foreach ($manyDefs as $fullDef) {
  329. $lines = explode("\n",$fullDef);
  330. $cleaner = '';
  331. foreach ($lines as $line) {
  332. if (trim($line) == '') {continue;}
  333. if (trim($line) == '--') {continue;}
  334. if (trim($line) == '#') {continue;}
  335. if (trim($line) == '# ') {continue;}
  336. if (preg_match("/^#/",trim($line))) {continue;}
  337. if (preg_match("/^--/",trim($line))) {continue;}
  338. $cleaner .= $line."\n";
  339. }
  340. if (trim($cleaner) == '') { continue; }
  341. $cleanSchemas[] = trim($cleaner)."\n";
  342. }
  343. }
  344. return $cleanSchemas;
  345. }
  346. private function _installComplete() {
  347. $group = new Cgn_DataItem('cgn_group');
  348. $group->hasOne('cgn_user_group_link', 'cgn_group_id', 'Tgrp');
  349. $group->andWhere('Tgrp.cgn_user_id', NULL, 'IS NOT');
  350. $group->andWhere('cgn_group.code', 'admin' );
  351. $group->load();
  352. $e = Cgn_ErrorStack::pullError('php');
  353. return ($group->cgn_group_id > 0);
  354. }
  355. public function _rewriteIni($iniName, $replaces, $useLocal = FALSE) {
  356. if ($useLocal)
  357. $ini = file_get_contents(CGN_BOOT_DIR.'local/'.$iniName);
  358. else
  359. $ini = file_get_contents(CGN_BOOT_DIR.$iniName);
  360. $lines = explode("\n",$ini);
  361. unset($ini);
  362. $newIni = '';
  363. foreach ($lines as $line) {
  364. $found = FALSE;
  365. foreach ($replaces as $_replace => $_rwith) {
  366. $size = strlen($_replace);
  367. if (substr($line,0,$size) == $_replace) {
  368. $newIni .= $_replace.'='.$_rwith."\n";
  369. $found = true;
  370. }
  371. }
  372. if (!$found) {
  373. $newIni .= $line."\n";
  374. }
  375. }
  376. $newIni = trim($newIni);
  377. $f = fopen(CGN_BOOT_DIR.'local/'.$iniName,'w');
  378. fputs($f,$newIni,strlen($newIni));
  379. fclose($f);
  380. unset($newIni);
  381. }
  382. public function _loadFormTemplate() {
  383. Cgn::loadLibrary('Form::lib_cgn_form');
  384. Cgn::loadLibrary('Html_Widgets::lib_cgn_widget');
  385. $f = new Cgn_Form('install_askTemplate');
  386. $f->layout = new Cgn_Form_Layout_Dl();
  387. $f->width = '70%';
  388. $f->action = cgn_appurl('install', 'main', 'writeTemplate');
  389. $f->label = 'Customize your site\'s appearance';
  390. $f->showCancel = false;
  391. $input1 = new Cgn_Form_ElementInput('site_name', 'Site Name');
  392. $f->appendElement($input1, $values['cgn_user_id']);
  393. $input2 = new Cgn_Form_ElementInput('site_tag', 'Site Tag Line');
  394. $f->appendElement($input2, $values['cgn_user_id'], '', 'A short phrase which appears below your site\'s name');
  395. $input3 = new Cgn_Form_ElementInput('ssl_port', 'Port for SSL/HTTP');
  396. $f->appendElement($input3, $values['cgn_user_id'], '443', 'Leave field blank to disable SSL');
  397. $input4 = new Cgn_Form_ElementSelect('template_name', 'Select a Template', 1);
  398. $input4->addChoice('Web App Template with Twitter Bootstrap', 'webapp01');
  399. $input4->addChoice('Open Blog Template with 960gs', 'blueblog01');
  400. $f->appendElement($input4);
  401. return $f;
  402. }
  403. public function _loadFormEmail() {
  404. Cgn::loadLibrary('Form::lib_cgn_form');
  405. Cgn::loadLibrary('Html_Widgets::lib_cgn_widget');
  406. $f = new Cgn_Form('install_askEmail');
  407. $f->layout = new Cgn_Form_Layout_Dl();
  408. $f->width = '100%';
  409. $f->label = 'Set default e-mail addresses';
  410. $f->showCancel = false;
  411. $input1 = new Cgn_Form_ElementInput('email_contact_us', 'Contact-Us');
  412. $f->appendElement($input1, $values['email_contact_us']);
  413. $input2 = new Cgn_Form_ElementInput('email_default_from', 'Default From');
  414. $f->appendElement($input2, $values['email_default_from'], '', 'noreply@example.com');
  415. $input3 = new Cgn_Form_ElementInput('email_error_notify', 'Error Notify Address');
  416. $f->appendElement($input3, $values['email_error_notify'], '', 'This is usually a developer account or mailing list.');
  417. return $f;
  418. }
  419. }