PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/setup/includes/request/modinstallclirequest.class.php

http://github.com/modxcms/revolution
PHP | 370 lines | 362 code | 0 blank | 8 comment | 0 complexity | e134e25812da54372452b5b4ae74732c MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0, BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /*
  3. * This file is part of MODX Revolution.
  4. *
  5. * Copyright (c) MODX, LLC. All Rights Reserved.
  6. *
  7. * For complete copyright and license information, see the COPYRIGHT and LICENSE
  8. * files found in the top-level directory of this distribution.
  9. */
  10. require_once strtr(realpath(MODX_SETUP_PATH.'includes/request/modinstallrequest.class.php'),'\\','/');
  11. /**
  12. * modInstallCLIRequest
  13. *
  14. * @package setup
  15. */
  16. /**
  17. * Handles CLI installs.
  18. *
  19. * @package setup
  20. */
  21. class modInstallCLIRequest extends modInstallRequest {
  22. /** @var modInstall $install */
  23. public $install;
  24. /** @var int $timeStart */
  25. public $timeStart = 0;
  26. /** @var string $timeTotal */
  27. public $timeTotal = '';
  28. /**
  29. * Constructor for modInstallConnector object.
  30. *
  31. * @constructor
  32. * @param modInstall &$modInstall A reference to the modInstall object.
  33. */
  34. function __construct(modInstall &$modInstall) {
  35. $this->install =& $modInstall;
  36. $this->install->loadSettings();
  37. }
  38. /**
  39. * Parse the install mode from a string or int
  40. * @param string|int $mode
  41. * @return int
  42. */
  43. public function getInstallMode($mode) {
  44. if (!is_int($mode)) {
  45. switch ($mode) {
  46. case 'new':
  47. $mode = modInstall::MODE_NEW;
  48. break;
  49. case 'upgrade-evo':
  50. $mode = modInstall::MODE_UPGRADE_EVO;
  51. break;
  52. case 'upgrade-revo-advanced':
  53. case 'upgrade-advanced':
  54. $mode = modInstall::MODE_UPGRADE_REVO_ADVANCED;
  55. break;
  56. case 'upgrade-revo':
  57. case 'upgrade':
  58. default:
  59. $mode = modInstall::MODE_UPGRADE_REVO;
  60. break;
  61. }
  62. }
  63. return $mode;
  64. }
  65. /**
  66. * Handles connector requests.
  67. *
  68. * @param string $action
  69. */
  70. public function handle($action = '') {
  71. $this->beginTimer();
  72. /* prepare the settings */
  73. $settings = $_REQUEST;
  74. if (empty($settings['installmode'])) $settings['installmode'] = modInstall::MODE_NEW;
  75. $settings['installmode'] = $this->getInstallMode($settings['installmode']);
  76. $this->install->settings->fromArray($settings); /* load CLI args into settings */
  77. /* load the config.xml file */
  78. $config = $this->getConfig($settings['installmode']);
  79. if (empty($config)) {
  80. $this->end($this->install->lexicon('cli_no_config_file'));
  81. }
  82. $this->install->settings->fromArray($config);
  83. $this->install->settings->fromArray($settings); /* do again to allow CLI-based overrides of config.xml */
  84. /* load the driver */
  85. $this->install->loadDriver();
  86. /* Run tests */
  87. $mode = (int)$this->install->settings->get('installmode');
  88. $results= $this->install->test($mode);
  89. if (!$this->install->test->success) {
  90. $msg = "\n";
  91. foreach ($results['fail'] as $field => $result) {
  92. $msg .= $field.': '.$result['title'].' - '.$result['message'];
  93. }
  94. $msg = $this->install->lexicon('cli_tests_failed',array(
  95. 'errors' => $msg,
  96. ));
  97. $this->end($msg);
  98. }
  99. /** Attempt to create the database */
  100. $this->checkDatabase();
  101. /* Run installer */
  102. $this->install->getService('runner','runner.modInstallRunnerWeb');
  103. $failed = true;
  104. $errors = array();
  105. if ($this->install->runner) {
  106. $success = $this->install->runner->run($mode);
  107. $results = $this->install->runner->getResults();
  108. $failed= false;
  109. foreach ($results as $item) {
  110. if ($item['class'] === 'failed') {
  111. $failed= true;
  112. $this->install->xpdo->log(xPDO::LOG_LEVEL_ERROR,$item['msg']);
  113. $errors[] = $item;
  114. break;
  115. }
  116. }
  117. }
  118. if ($failed) {
  119. $msg = "\n";
  120. foreach ($errors as $field => $result) {
  121. $msg .= $result['msg'];
  122. }
  123. $msg = $this->install->lexicon('cli_install_failed',array(
  124. 'errors' => $msg,
  125. ));
  126. $this->end($msg);
  127. }
  128. /* cleanup */
  129. $errors= $this->install->verify();
  130. foreach ($errors as $error) {
  131. $this->install->xpdo->log(xPDO::LOG_LEVEL_ERROR,$error);
  132. }
  133. $cleanupErrors = $this->install->cleanup();
  134. foreach ($cleanupErrors as $key => $error) {
  135. $this->install->xpdo->log(xPDO::LOG_LEVEL_ERROR,$error);
  136. }
  137. if ($this->install->settings->get('remove_setup_directory')) {
  138. $this->install->removeSetupDirectory();
  139. }
  140. $this->endTimer();
  141. $this->end(''.$this->install->lexicon('installation_finished',array(
  142. 'time' => $this->timeTotal,
  143. )));
  144. }
  145. /**
  146. * {@inheritDoc}
  147. * @param int $mode
  148. * @param array $config
  149. * @return array
  150. */
  151. public function getConfig($mode = 0, array $config = array()) {
  152. /* load the config file */
  153. $config = array_merge($this->loadConfigFile(), $config);
  154. $config = parent::getConfig($mode, $config);
  155. $this->prepareSettings($config);
  156. return $config;
  157. }
  158. /**
  159. * Attempt to load the config.xml (or other config file) to use when installing. One must be present to run
  160. * MODX Setup in CLI mode.
  161. *
  162. * @return array
  163. */
  164. public function loadConfigFile() {
  165. $settings = array();
  166. $configFile = $this->install->settings->get('config');
  167. if (empty($configFile)) $configFile = MODX_INSTALL_PATH.'setup/config.xml';
  168. if (!empty($configFile)) {
  169. if (!file_exists($configFile) && file_exists(MODX_SETUP_PATH.$configFile)) {
  170. $configFile = MODX_SETUP_PATH.$configFile;
  171. }
  172. } elseif (file_exists(MODX_SETUP_PATH.'config.xml')) {
  173. $configFile = MODX_SETUP_PATH.'config.xml';
  174. }
  175. if (!empty($configFile) && file_exists($configFile)) {
  176. $settings = $this->parseConfigFile($configFile);
  177. }
  178. return $settings;
  179. }
  180. /**
  181. * Prepares settings for installation, including setting of defaults
  182. *
  183. * @param array $settings
  184. * @return void
  185. */
  186. public function prepareSettings(array &$settings) {
  187. if (empty($settings['site_sessionname'])) {
  188. $settings['site_sessionname'] = 'SN' . uniqid('');
  189. }
  190. if (empty($settings['config_options'])) {
  191. $settings['config_options'] = array();
  192. }
  193. if (empty($settings['database']) && !empty($settings['dbase'])) {
  194. $settings['database'] = $settings['dbase'];
  195. }
  196. $settings['database_dsn'] = $this->getDatabaseDSN($settings['database_type'],$settings['database_server'],$settings['database'],$settings['database_connection_charset']);
  197. if (!empty($settings['database'])) {
  198. $settings['dbase'] = $settings['database'];
  199. }
  200. $this->install->settings->fromArray($settings);
  201. $this->setDefaultSetting('processors_path',$this->install->settings->get('core_path').'model/modx/processors/');
  202. $this->setDefaultSetting('connectors_path',$this->install->settings->get('context_connectors_path'));
  203. $this->setDefaultSetting('connectors_url',$this->install->settings->get('context_connectors_url'));
  204. $this->setDefaultSetting('mgr_path',$this->install->settings->get('context_mgr_path'));
  205. $this->setDefaultSetting('mgr_url',$this->install->settings->get('context_mgr_url'));
  206. $this->setDefaultSetting('web_path',$this->install->settings->get('context_web_path'));
  207. $this->setDefaultSetting('web_url',$this->install->settings->get('context_web_url'));
  208. $this->setDefaultSetting('assets_path',$this->install->settings->get('context_assets_path',$this->install->settings->get('context_web_path').'assets/'));
  209. $this->setDefaultSetting('assets_url',$this->install->settings->get('context_assets_url',$this->install->settings->get('context_web_url').'assets/'));
  210. }
  211. /**
  212. * Sets a default for a setting if not set
  213. * @param string $key
  214. * @param mixed $default
  215. * @return void
  216. */
  217. public function setDefaultSetting($key,$default) {
  218. $value = $this->install->settings->get($key,null);
  219. if ($value === null) {
  220. $this->install->settings->set($key,$default);
  221. }
  222. }
  223. /**
  224. * Parse the config XML file
  225. *
  226. * @param string $file
  227. * @return array
  228. */
  229. public function parseConfigFile($file) {
  230. $contents = file_get_contents($file);
  231. $xml = new SimpleXMLElement($contents);
  232. $settings = array();
  233. foreach ($xml as $k => $v) {
  234. $settings[(string)$k] = (string)$v;
  235. }
  236. return $settings;
  237. }
  238. /**
  239. * Check database settings
  240. * @return void
  241. */
  242. public function checkDatabase() {
  243. $mode = $this->install->settings->get('installmode');
  244. if ($mode == modInstall::MODE_NEW) {
  245. $results = $this->install->driver->verifyServerVersion();
  246. if ($results['result'] == 'failure') {
  247. $this->end($results['message']);
  248. }
  249. $this->install->xpdo = null;
  250. }
  251. /* get an instance of xPDO using the install settings */
  252. $xpdo = $this->install->getConnection($mode);
  253. if (!is_object($xpdo) || !($xpdo instanceof xPDO)) {
  254. $this->end($this->install->lexicon('xpdo_err_ins'));
  255. }
  256. /* try to get a connection to the actual database */
  257. $dbExists = $xpdo->connect();
  258. if (!$dbExists) {
  259. if ($mode == modInstall::MODE_NEW && $xpdo->getManager()) {
  260. /* otherwise try to create the database */
  261. $dbExists = $xpdo->manager->createSourceContainer(
  262. array(
  263. 'dbname' => $this->install->settings->get('dbase')
  264. ,'host' => $this->install->settings->get('database_server')
  265. )
  266. ,$this->install->settings->get('database_user')
  267. ,$this->install->settings->get('database_password')
  268. ,array(
  269. 'charset' => $this->install->settings->get('database_connection_charset')
  270. ,'collation' => $this->install->settings->get('database_collation')
  271. )
  272. );
  273. if (!$dbExists) {
  274. $this->end($this->install->lexicon('db_err_create_database'));
  275. } else {
  276. $xpdo = $this->install->getConnection($mode);
  277. if (!is_object($xpdo) || !($xpdo instanceof xPDO)) {
  278. $this->end($this->install->lexicon('xpdo_err_ins'));
  279. }
  280. }
  281. } elseif ($mode == modInstall::MODE_NEW) {
  282. $this->end($this->install->lexicon('db_err_connect_server'));
  283. }
  284. }
  285. if (!$xpdo->connect()) {
  286. $this->end($this->install->lexicon('db_err_connect'));
  287. }
  288. /* test table prefix */
  289. if ($mode == modInstall::MODE_NEW || $mode == modInstall::MODE_UPGRADE_REVO_ADVANCED) {
  290. $count = null;
  291. $database = $this->install->settings->get('dbase');
  292. $prefix = $this->install->settings->get('table_prefix');
  293. $stmt = $xpdo->query($this->install->driver->testTablePrefix($database,$prefix));
  294. if ($stmt) {
  295. $row = $stmt->fetch(PDO::FETCH_ASSOC);
  296. if ($row) {
  297. $count = (integer) $row['ct'];
  298. }
  299. $stmt->closeCursor();
  300. }
  301. if ($mode == modInstall::MODE_NEW && $count !== null) {
  302. $this->end($this->install->lexicon('test_table_prefix_inuse'));
  303. } elseif ($mode == modInstall::MODE_UPGRADE_REVO_ADVANCED && $count === null) {
  304. $this->end($this->install->lexicon('test_table_prefix_nf'));
  305. }
  306. }
  307. }
  308. /**
  309. * End the PHP session and output a message
  310. *
  311. * @param string $message
  312. * @return void
  313. */
  314. public function end($message = '') {
  315. @session_write_close();
  316. die($message."\n");
  317. }
  318. /**
  319. * Start the debugging timer
  320. * @return int
  321. */
  322. protected function beginTimer() {
  323. $mtime = microtime();
  324. $mtime = explode(" ", $mtime);
  325. $mtime = $mtime[1] + $mtime[0];
  326. $this->timeStart = $mtime;
  327. return $this->timeStart;
  328. }
  329. /**
  330. * End the debugging timer
  331. * @return string
  332. */
  333. protected function endTimer() {
  334. $mtime = microtime();
  335. $mtime = explode(" ", $mtime);
  336. $mtime = $mtime[1] + $mtime[0];
  337. $tend = $mtime;
  338. $this->timeTotal = ($tend - $this->timeStart);
  339. $this->timeTotal = sprintf("%2.4f s", $this->timeTotal);
  340. return $this->timeTotal;
  341. }
  342. }