PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/system/console/OctoberInstall.php

https://gitlab.com/gideonmarked/atls-express
PHP | 362 lines | 248 code | 61 blank | 53 comment | 10 complexity | ea0beb431349854d1d67375fd1ce65fe MD5 | raw file
  1. <?php namespace System\Console;
  2. use Db;
  3. use App;
  4. use Str;
  5. use Url;
  6. use PDO;
  7. use File;
  8. use Config;
  9. use Artisan;
  10. use Cms\Classes\Theme;
  11. use Cms\Classes\ThemeManager;
  12. use Backend\Database\Seeds\SeedSetupAdmin;
  13. use System\Classes\UpdateManager;
  14. use October\Rain\Config\ConfigWriter;
  15. use Illuminate\Console\Command;
  16. use Illuminate\Encryption\Encrypter;
  17. use Symfony\Component\Console\Input\InputOption;
  18. use Exception;
  19. class OctoberInstall extends Command
  20. {
  21. use \Illuminate\Console\ConfirmableTrait;
  22. /**
  23. * The console command name.
  24. */
  25. protected $name = 'october:install';
  26. /**
  27. * The console command description.
  28. */
  29. protected $description = 'Set up October for the first time.';
  30. /**
  31. * @var October\Rain\Config\ConfigWriter
  32. */
  33. protected $configWriter;
  34. /**
  35. * Create a new command instance.
  36. */
  37. public function __construct()
  38. {
  39. parent::__construct();
  40. $this->configWriter = new ConfigWriter;
  41. }
  42. /**
  43. * Execute the console command.
  44. */
  45. public function fire()
  46. {
  47. $this->displayIntro();
  48. if (
  49. App::hasDatabase() &&
  50. !$this->confirm('Application appears to be installed already. Continue anyway?', false)
  51. ) {
  52. return;
  53. }
  54. $this->setupDatabaseConfig();
  55. $this->setupAdminUser();
  56. $this->setupCommonValues();
  57. if ($this->confirm('Configure advanced options?', false)) {
  58. $this->setupEncryptionKey();
  59. $this->setupAdvancedValues();
  60. }
  61. else {
  62. $this->setupEncryptionKey(true);
  63. }
  64. $this->setupMigrateDatabase();
  65. $this->displayOutro();
  66. }
  67. /**
  68. * Get the console command arguments.
  69. */
  70. protected function getArguments()
  71. {
  72. return [];
  73. }
  74. /**
  75. * Get the console command options.
  76. */
  77. protected function getOptions()
  78. {
  79. return [
  80. ['force', null, InputOption::VALUE_NONE, 'Force the operation to run.'],
  81. ];
  82. }
  83. //
  84. // Misc
  85. //
  86. protected function setupCommonValues()
  87. {
  88. $url = $this->ask('Application URL', Config::get('app.url'));
  89. $this->writeToConfig('app', ['url' => $url]);
  90. }
  91. protected function setupAdvancedValues()
  92. {
  93. $backendUri = $this->ask('Backend URL', Config::get('cms.backendUri'));
  94. $this->writeToConfig('cms', ['backendUri' => $backendUri]);
  95. $defaultMask = $this->ask('File Permission Mask', Config::get('cms.defaultMask.file') ?: '777');
  96. $this->writeToConfig('cms', ['defaultMask.file' => $defaultMask]);
  97. $defaultMask = $this->ask('Folder Permission Mask', Config::get('cms.defaultMask.folder') ?: '777');
  98. $this->writeToConfig('cms', ['defaultMask.folder' => $defaultMask]);
  99. $debug = (bool) $this->confirm('Enable Debug Mode?', true);
  100. $this->writeToConfig('app', ['debug' => $debug]);
  101. }
  102. //
  103. // Encryption key
  104. //
  105. protected function setupEncryptionKey($force = false)
  106. {
  107. $validKey = false;
  108. $cipher = Config::get('app.cipher');
  109. $keyLength = $this->getKeyLength($cipher);
  110. $randomKey = $this->getRandomKey($cipher);
  111. if ($force) {
  112. $key = $randomKey;
  113. }
  114. else {
  115. $this->line(sprintf('Enter a new value of %s characters, or press ENTER to use the generated key', $keyLength));
  116. while (!$validKey) {
  117. $key = $this->ask('Application key', $randomKey);
  118. $validKey = Encrypter::supported($key, $cipher);
  119. if (!$validKey) {
  120. $this->error(sprintf('[ERROR] Invalid key length for "%s" cipher. Supplied key must be %s characters in length.', $cipher, $keyLength));
  121. }
  122. }
  123. }
  124. $this->writeToConfig('app', ['key' => $key]);
  125. $this->info(sprintf('Application key [%s] set successfully.', $key));
  126. }
  127. /**
  128. * Generate a random key for the application.
  129. *
  130. * @param string $cipher
  131. * @return string
  132. */
  133. protected function getRandomKey($cipher)
  134. {
  135. return Str::random($this->getKeyLength($cipher));
  136. }
  137. /**
  138. * Returns the supported length of a key for a cipher.
  139. *
  140. * @param string $cipher
  141. * @return int
  142. */
  143. protected function getKeyLength($cipher)
  144. {
  145. return $cipher === 'AES-128-CBC' ? 16 : 32;
  146. }
  147. //
  148. // Database config
  149. //
  150. protected function setupDatabaseConfig()
  151. {
  152. $type = $this->choice('Database type', ['MySQL', 'Postgres', 'SQLite', 'SQL Server']);
  153. $typeMap = [
  154. 'SQLite' => 'sqlite',
  155. 'MySQL' => 'mysql',
  156. 'Postgres' => 'pgsql',
  157. 'SQL Server' => 'sqlsrv',
  158. ];
  159. $driver = array_get($typeMap, $type, 'sqlite');
  160. $method = 'setupDatabase'.Str::studly($driver);
  161. $newConfig = $this->$method();
  162. $this->writeToConfig('database', ['default' => $driver]);
  163. foreach ($newConfig as $config => $value) {
  164. $this->writeToConfig('database', ['connections.'.$driver.'.'.$config => $value]);
  165. }
  166. }
  167. protected function setupDatabaseMysql()
  168. {
  169. $result = [];
  170. $result['host'] = $this->ask('MySQL Host', Config::get('database.connections.mysql.host'));
  171. $result['port'] = $this->output->ask('MySQL Port', Config::get('database.connections.mysql.port') ?: false) ?: '';
  172. $result['database'] = $this->ask('Database Name', Config::get('database.connections.mysql.database'));
  173. $result['username'] = $this->ask('MySQL Login', Config::get('database.connections.mysql.username'));
  174. $result['password'] = $this->ask('MySQL Password', Config::get('database.connections.mysql.password') ?: false) ?: '';
  175. return $result;
  176. }
  177. protected function setupDatabasePgsql()
  178. {
  179. $result = [];
  180. $result['host'] = $this->ask('Postgres Host', Config::get('database.connections.pgsql.host'));
  181. $result['port'] = $this->ask('Postgres Port', Config::get('database.connections.pgsql.port') ?: false) ?: '';
  182. $result['database'] = $this->ask('Database Name', Config::get('database.connections.pgsql.database'));
  183. $result['username'] = $this->ask('Postgres Login', Config::get('database.connections.pgsql.username'));
  184. $result['password'] = $this->ask('Postgres Password', Config::get('database.connections.pgsql.password') ?: false) ?: '';
  185. return $result;
  186. }
  187. protected function setupDatabaseSqlite()
  188. {
  189. $filename = $this->ask('Database path', Config::get('database.connections.sqlite.database'));
  190. try {
  191. if (!file_exists($filename)) {
  192. $directory = dirname($filename);
  193. if (!is_dir($directory)) {
  194. mkdir($directory, 0777, true);
  195. }
  196. new PDO('sqlite:'.$filename);
  197. }
  198. }
  199. catch (Exception $ex) {
  200. $this->error($ex->getMessage());
  201. $this->setupDatabaseSqlite();
  202. }
  203. return ['database' => $filename];
  204. }
  205. protected function setupDatabaseSqlsrv()
  206. {
  207. $result = [];
  208. $result['host'] = $this->ask('SQL Host', Config::get('database.connections.sqlsrv.host'));
  209. $result['port'] = $this->ask('SQL Port', Config::get('database.connections.sqlsrv.port') ?: false) ?: '';
  210. $result['database'] = $this->ask('Database Name', Config::get('database.connections.sqlsrv.database'));
  211. $result['username'] = $this->ask('SQL Login', Config::get('database.connections.sqlsrv.username'));
  212. $result['password'] = $this->ask('SQL Password', Config::get('database.connections.sqlsrv.password') ?: false) ?: '';
  213. return $result;
  214. }
  215. //
  216. // Migration
  217. //
  218. protected function setupAdminUser()
  219. {
  220. $this->line('Enter a new value, or press ENTER for the default');
  221. SeedSetupAdmin::$firstName = $this->ask('First Name', SeedSetupAdmin::$firstName);
  222. SeedSetupAdmin::$lastName = $this->ask('Last Name', SeedSetupAdmin::$lastName);
  223. SeedSetupAdmin::$email = $this->ask('Email Address', SeedSetupAdmin::$email);
  224. SeedSetupAdmin::$login = $this->ask('Admin Login', SeedSetupAdmin::$login);
  225. SeedSetupAdmin::$password = $this->ask('Admin Password', SeedSetupAdmin::$password);
  226. if (!$this->confirm('Is the information correct?', true)) {
  227. $this->setupAdminUser();
  228. }
  229. }
  230. protected function setupMigrateDatabase()
  231. {
  232. $this->line('Migrating application and plugins...');
  233. try {
  234. Db::purge();
  235. UpdateManager::instance()->resetNotes()->update();
  236. }
  237. catch (Exception $ex) {
  238. $this->error($ex->getMessage());
  239. $this->setupDatabaseConfig();
  240. $this->setupMigrateDatabase();
  241. }
  242. }
  243. //
  244. // Helpers
  245. //
  246. protected function displayIntro()
  247. {
  248. $message = [
  249. ".====================================================================.",
  250. " ",
  251. " .d8888b. .o8888b. db .d8888b. d8888b. d88888b d8888b. .d888b. ",
  252. ".8P Y8. d8P Y8 88 .8P Y8. 88 `8D 88' 88 `8D .8P , Y8.",
  253. "88 88 8P oooo88 88 88 88oooY' 88oooo 88oobY' 88 | 88",
  254. "88 88 8b ~~~~88 88 88 88~~~b. 88~~~~ 88`8b 88 |/ 88",
  255. "`8b d8' Y8b d8 88 `8b d8' 88 8D 88. 88 `88. `8b | d8'",
  256. " `Y8888P' `Y8888P' YP `Y8888P' Y8888P' Y88888P 88 YD `Y888P' ",
  257. " ",
  258. "`=========================== INSTALLATION ==========================='",
  259. "",
  260. ];
  261. $this->line($message);
  262. }
  263. protected function displayOutro()
  264. {
  265. $message = [
  266. ".=========================================.",
  267. " ,@@@@@@@, ",
  268. " ,,,. ,@@@@@@/@@, .oo8888o. ",
  269. " ,&%%&%&&%,@@@@@/@@@@@@,8888\88/8o ",
  270. " ,%&\%&&%&&%,@@@\@@@/@@@88\88888/88' ",
  271. " %&&%&%&/%&&%@@\@@/ /@@@88888\88888' ",
  272. " %&&%/ %&%%&&@@\ V /@@' `88\8 `/88' ",
  273. " `&%\ ` /%&' |.| \ '|8' ",
  274. " |o| | | | | ",
  275. " |.| | | | | ",
  276. "`========= INSTALLATION COMPLETE ========='",
  277. "",
  278. ];
  279. $this->line($message);
  280. }
  281. protected function writeToConfig($file, $values)
  282. {
  283. $configFile = $this->getConfigFile($file);
  284. foreach ($values as $key => $value) {
  285. Config::set($file.'.'.$key, $value);
  286. }
  287. $this->configWriter->toFile($configFile, $values);
  288. }
  289. /**
  290. * Get a config file and contents.
  291. *
  292. * @return array
  293. */
  294. protected function getConfigFile($name = 'app')
  295. {
  296. $env = $this->option('env') ? $this->option('env').'/' : '';
  297. $name .= '.php';
  298. $contents = File::get($path = $this->laravel['path.config']."/{$env}{$name}");
  299. return $path;
  300. }
  301. }