From 434d4532ebd3831404f949268493593c1b49b51e Mon Sep 17 00:00:00 2001 From: Roman Kelesidis Date: Wed, 7 Aug 2024 17:32:41 +0700 Subject: [PATCH] [CLI] TorrentPier installer (#1576) * Added CLI preparing installation script * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Revert "Update install.php" This reverts commit 554319e003f3b647d893049e64fab4f40e6fa446. * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update .env.example * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php * Update CHANGELOG.md * Update install.php * Update install.php * Update install.php * Update install.php * Update install.php --- .env.example | 2 +- CHANGELOG.md | 1 + install.php | 259 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 install.php diff --git a/.env.example b/.env.example index f47c87658..10776f570 100644 --- a/.env.example +++ b/.env.example @@ -9,4 +9,4 @@ DB_HOST=localhost DB_PORT=3306 DB_DATABASE=torrentpier DB_USERNAME=root -DB_PASSWORD=secret +DB_PASSWORD= diff --git a/CHANGELOG.md b/CHANGELOG.md index b293875a5..28dc78b29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ **Merged pull requests:** - Release 2.4.5 🦕 ([belomaxorka](https://github.com/belomaxorka)) +- [CLI] TorrentPier installer ☕️ [\#1576](https://github.com/torrentpier/torrentpier/pull/1576) ([belomaxorka](https://github.com/belomaxorka)) - Added some new HTML meta-tags [\#1562](https://github.com/torrentpier/torrentpier/pull/1562) ([belomaxorka](https://github.com/belomaxorka)) - Added showing releaser stats in profile [\#1568](https://github.com/torrentpier/torrentpier/pull/1568) ([belomaxorka](https://github.com/belomaxorka)) - Fixed `md5()` deprecated in PHP 8.4 [\#1561](https://github.com/torrentpier/torrentpier/pull/1561) ([belomaxorka](https://github.com/belomaxorka)) diff --git a/install.php b/install.php new file mode 100644 index 000000000..3c212bda7 --- /dev/null +++ b/install.php @@ -0,0 +1,259 @@ +php ' . basename(__FILE__) . ' in CLI mode'); +} + +// Check if already installed +if (is_file(ROOT . '.env')) { + exit; +} + +// Check readline extension +if (!extension_loaded('readline')) { + out('- ext-readline not found. Check out PHP instance', 'error'); + exit; +} + +/** + * Colored console output + * + * @param string $str + * @param string $type + * @return void + */ +function out(string $str, string $type = ''): void +{ + echo match ($type) { + 'error' => "\033[31m$str \033[0m\n", + 'success' => "\033[32m$str \033[0m\n", + 'warning' => "\033[33m$str \033[0m\n", + 'info' => "\033[36m$str \033[0m\n", + 'debug' => "\033[90m$str \033[0m\n", + default => $str, + }; +} + +/** + * Run process with realtime output + * + * @param string $cmd + * @param string|null $input + * @return void + */ +function runProcess(string $cmd, string $input = null): void +{ + $descriptorSpec = [ + 0 => ['pipe', 'r'], + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + + $process = proc_open($cmd, $descriptorSpec, $pipes); + + if (!is_resource($process)) { + out('- Could not start subprocess', 'error'); + return; + } + + // Write input if provided + if ($input !== null) { + fwrite($pipes[0], $input); + fclose($pipes[0]); + } + + // Read and print output in real-time + while (!feof($pipes[1])) { + echo stream_get_contents($pipes[1], 1); + flush(); // Flush output buffer for immediate display + } + + // Read and print error output + while (!feof($pipes[2])) { + echo stream_get_contents($pipes[2], 1); + flush(); + } + + fclose($pipes[1]); + fclose($pipes[2]); + + proc_close($process); +} + +// Welcoming message +out("- TorrentPier Installer\n", 'info'); + +// Check composer installation +if (!is_file(ROOT . 'vendor/autoload.php')) { + out('- Hmm, it seems there are no Composer dependencies', 'info'); + + // Downloading composer + if (!is_file(ROOT . 'composer.phar')) { + out('- Downloading Composer...', 'info'); + if (copy('https://getcomposer.org/installer', ROOT . 'composer-setup.php')) { + out("- Composer successfully downloaded!\n", 'success'); + runProcess('php ' . ROOT . 'composer-setup.php'); + } else { + out('- Cannot download Composer', 'error'); + exit; + } + if (is_file(ROOT . 'composer-setup.php')) { + if (unlink(ROOT . 'composer-setup.php')) { + out("- Composer installation file successfully removed!\n", 'success'); + } else { + out('- Cannot remove Composer installation file. Delete it manually', 'warning'); + } + } + } + + // Installing dependencies + if (is_file(ROOT . 'composer.phar')) { + out('- Installing dependencies...', 'info'); + runProcess('php ' . ROOT . 'composer.phar install --no-interaction --no-ansi'); + out("- Completed!\n", 'success'); + } else { + out('- composer.phar not found', 'error'); + exit; + } +} + +// Preparing ENV +if (is_file(ROOT . '.env.example') && !is_file(ROOT . '.env')) { + if (copy(ROOT . '.env.example', ROOT . '.env')) { + out("- Environment file created!\n", 'success'); + } else { + out('- Cannot create environment file', 'error'); + exit; + } +} + +// Editing ENV file +$DB_HOST = ''; +$DB_PORT = 3306; +$DB_DATABASE = ''; +$DB_USERNAME = ''; +$DB_PASSWORD = ''; + +if (is_file(ROOT . '.env')) { + out("--- Configuring TorrentPier ---\n", 'info'); + + $envContent = file_get_contents(ROOT . '.env'); + if ($envContent === false) { + out('- Cannot open environment file', 'error'); + exit; + } + $envLines = explode("\n", $envContent); + + $editedLines = []; + foreach ($envLines as $line) { + if (trim($line) !== '' && !str_starts_with($line, '#')) { + $parts = explode('=', $line, 2); + $key = trim($parts[0]); + $value = isset($parts[1]) ? trim($parts[1]) : ''; + + // Database default values + if (in_array($key, ['DB_HOST', 'DB_PORT', 'DB_DATABASE', 'DB_USERNAME', 'DB_PASSWORD'])) { + $$key = $value; + } + + out("Current value of $key: $value", 'debug'); + out("Enter a new value for $key (or leave empty to not change): "); + $newValue = readline(); + + if (!empty($newValue)) { + $line = "$key=$newValue"; + // Configuring database connection + if (in_array($key, ['DB_HOST', 'DB_PORT', 'DB_DATABASE', 'DB_USERNAME', 'DB_PASSWORD'])) { + $$key = $newValue; + } + } + + $editedLines[] = $line; + } + } + + $newEnvContent = implode("\n", $editedLines); + if (file_put_contents(ROOT . '.env', $newEnvContent)) { + out("- TorrentPier successfully configured!\n", 'success'); + } else { + out('- Cannot save environment file', 'error'); + exit; + } +} else { + out('- Environment file not found', 'error'); + exit; +} + +if (!empty($DB_HOST) && !empty($DB_DATABASE) && !empty($DB_USERNAME)) { + out("--- Checking environment settings ---\n", 'info'); + // Connecting to database + out("- Trying connect to MySQL...", 'info'); + + // Checking mysqli extension installed + if (!extension_loaded('mysqli')) { + out('- ext-mysqli not found. Check out php.ini file', 'error'); + exit; + } + + // Connect to MySQL server + try { + $conn = new mysqli($DB_HOST, $DB_USERNAME, $DB_PASSWORD, port: $DB_PORT); + } catch (mysqli_sql_exception $exception) { + out("- Connection failed: {$exception->getMessage()}", 'error'); + exit; + } + if (!$conn->connect_error) { + out('- Connected successfully!', 'success'); + } + + // Creating database if not exist + if ($conn->query("CREATE DATABASE IF NOT EXISTS $DB_DATABASE")) { + out('- Database created successfully!', 'success'); + } else { + out("- Cannot create database: $DB_DATABASE", 'error'); + exit; + } + $conn->select_db($DB_DATABASE); + + // Checking SQL dump + $dumpPath = ROOT . 'install/sql/mysql.sql'; + if (is_file($dumpPath) && is_readable($dumpPath)) { + out('- SQL dump file found and readable!', 'success'); + } else { + out('- SQL dump file not found / not readable', 'error'); + exit; + } + + // Inserting SQL dump + out('- Start importing SQL dump...', 'info'); + $tempLine = ''; + foreach (file($dumpPath) as $line) { + if (str_starts_with($line, '--') || $line == '') { + continue; + } + + $tempLine .= $line; + if (str_ends_with(trim($line), ';')) { + if (!$conn->query($tempLine)) { + out("- Error performing query: $tempLine", 'error'); + exit; + } + $tempLine = ''; + } + } + + $conn->close(); + out("- Importing SQL dump completed!\n", 'success'); + out("- Voila! Good luck & have fun!", 'success'); + rename(__FILE__, hash('md5', time())); +}