mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-18 15:50:50 +08:00
install
This commit is contained in:
@@ -16,6 +16,10 @@
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2|^8",
|
||||
"ext-gd": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-mysqli": "*",
|
||||
"ext-json": "*",
|
||||
"swiftmailer/swiftmailer": "^6.2",
|
||||
"guzzlehttp/guzzle": "~6.0",
|
||||
"imdbphp/imdbphp": "^6.4"
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
if(!defined('IN_TRACKER')) {
|
||||
die('Hacking attempt!');
|
||||
}
|
||||
if (!file_exists($rootpath . '.env')) {
|
||||
header('Location: ' . getBaseUrl() . '/install/install.php');
|
||||
exit(0);
|
||||
}
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_errors', 0);
|
||||
if (!empty($_SERVER['HTTP_X_REQUEST_ID'])) {
|
||||
define('REQUEST_ID', $_SERVER['HTTP_X_REQUEST_ID']);
|
||||
} else {
|
||||
@@ -12,13 +16,8 @@ if (!empty($_SERVER['HTTP_X_REQUEST_ID'])) {
|
||||
define('ROOT_PATH', $rootpath);
|
||||
define('VERSION_NUMBER', '1.6.0');
|
||||
define('IS_ANNOUNCE', (basename($_SERVER['SCRIPT_FILENAME']) == 'announce.php'));
|
||||
|
||||
require $rootpath . 'include/database/interface_db.php';
|
||||
require $rootpath . 'include/database/class_db_mysqli.php';
|
||||
require $rootpath . 'include/database/class_db.php';
|
||||
require $rootpath . 'include/database/helpers.php';
|
||||
require $rootpath . 'include/database/class_exception.php';
|
||||
|
||||
require $rootpath . 'vendor/autoload.php';
|
||||
require $rootpath . 'nexus/Database/helpers.php';
|
||||
require $rootpath . 'classes/class_advertisement.php';
|
||||
require $rootpath . 'classes/class_cache_redis.php';
|
||||
require $rootpath . 'include/config.php';
|
||||
@@ -52,5 +51,3 @@ define ("UC_SYSOP",15);
|
||||
define ("UC_STAFFLEADER",16);
|
||||
ignore_user_abort(1);
|
||||
@set_time_limit(60);
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
@@ -1752,17 +1752,7 @@ function getExportedValue($input,$t = null) {
|
||||
|
||||
function dbconn($autoclean = false, $doLogin = true)
|
||||
{
|
||||
if (DB::getInstance()->isConnected()) {
|
||||
return;
|
||||
}
|
||||
$config = config('database.mysql');
|
||||
if (!mysql_connect($config['host'], $config['username'], $config['password'], $config['database'], $config['port']))
|
||||
{
|
||||
die("[" . mysql_errno() . "] dbconn: mysql_connect: " . mysql_error());
|
||||
}
|
||||
mysql_query("SET NAMES UTF8");
|
||||
mysql_query("SET collation_connection = 'utf8_general_ci'");
|
||||
mysql_query("SET sql_mode=''");
|
||||
\Nexus\Database\DB::getInstance()->autoConnect();
|
||||
|
||||
if ($doLogin) {
|
||||
userlogin();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Nexus\Database;
|
||||
|
||||
class DB
|
||||
{
|
||||
private $driver;
|
||||
@@ -41,20 +43,36 @@ class DB
|
||||
|
||||
public function connect($host, $username, $password, $database, $port)
|
||||
{
|
||||
if (!$this->isConnected) {
|
||||
if (!$this->isConnected()) {
|
||||
$this->driver->connect($host, $username, $password, $database, $port);
|
||||
$this->isConnected = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function autoConnect()
|
||||
{
|
||||
if ($this->isConnected()) {
|
||||
return;
|
||||
}
|
||||
$config = config('database.mysql');
|
||||
if (!mysql_connect($config['host'], $config['username'], $config['password'], $config['database'], $config['port'])) {
|
||||
throw new DatabaseException(sprintf("mysql connect error: [%s] %s", mysql_errno(), mysql_error()));
|
||||
}
|
||||
mysql_query("SET NAMES UTF8");
|
||||
mysql_query("SET collation_connection = 'utf8_general_ci'");
|
||||
mysql_query("SET sql_mode=''");
|
||||
$this->isConnected = true;
|
||||
}
|
||||
|
||||
public function query(string $sql)
|
||||
{
|
||||
try {
|
||||
$this->autoConnect();
|
||||
return $this->driver->query($sql);
|
||||
} catch (\Exception $e) {
|
||||
do_log(sprintf("%s [%s] %s", $e->getMessage(), $sql, $e->getTraceAsString()));
|
||||
throw new \DatabaseException($sql, $e->getMessage());
|
||||
throw new DatabaseException($e->getMessage(), $sql);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -101,6 +119,7 @@ class DB
|
||||
|
||||
public function escapeString(string $string)
|
||||
{
|
||||
$this->autoConnect();
|
||||
return $this->driver->escapeString($string);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
namespace Nexus\Database;
|
||||
|
||||
interface DBInterface
|
||||
{
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
namespace Nexus\Database;
|
||||
|
||||
class DBMysqli implements DBInterface
|
||||
{
|
||||
@@ -6,13 +7,13 @@ class DBMysqli implements DBInterface
|
||||
|
||||
public function connect($host, $username, $password, $database, $port)
|
||||
{
|
||||
$mysqli = new mysqli($host, $username, $password, $database, $port);
|
||||
$mysqli = new \mysqli($host, $username, $password, $database, $port);
|
||||
/* check connection */
|
||||
if (mysqli_connect_errno()) {
|
||||
throw new \DatabaseException('', mysqli_connect_error());
|
||||
throw new DatabaseException(mysqli_connect_error());
|
||||
}
|
||||
/* activate reporting */
|
||||
$driver = new mysqli_driver();
|
||||
$driver = new \mysqli_driver();
|
||||
$driver->report_mode = MYSQLI_REPORT_ALL & ~MYSQLI_REPORT_INDEX;
|
||||
|
||||
return $this->mysqli = $mysqli;
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
namespace Nexus\Database;
|
||||
|
||||
class DatabaseException extends \Exception
|
||||
{
|
||||
|
||||
public function __construct($query, $message)
|
||||
public function __construct($message, $query = '')
|
||||
{
|
||||
parent::__construct("$message [$query]");
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
use Nexus\Database\DB;
|
||||
|
||||
function mysql_connect($host, $username, $password, $database, $port)
|
||||
{
|
||||
359
nexus/Install/Install.php
Normal file
359
nexus/Install/Install.php
Normal file
@@ -0,0 +1,359 @@
|
||||
<?php
|
||||
|
||||
namespace Nexus\Install;
|
||||
|
||||
use Nexus\Database\DB;
|
||||
|
||||
class Install
|
||||
{
|
||||
private $currentStep;
|
||||
|
||||
private $minimumPhpVersion = '7.2.0';
|
||||
|
||||
protected $steps = ['环境检测', '添加 .env 文件', '新建数据表', '导入数据', '创建管理员账号'];
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->currentStep = min(intval($_REQUEST['step'] ?? 1) ?: 1, count($this->steps) + 1);
|
||||
}
|
||||
|
||||
public function currentStep()
|
||||
{
|
||||
return $this->currentStep;
|
||||
}
|
||||
|
||||
public function getLogFile()
|
||||
{
|
||||
return sprintf('%s/nexus_install_%s.log', sys_get_temp_dir(), date('Ymd'));
|
||||
}
|
||||
|
||||
public function getInsallDirectory()
|
||||
{
|
||||
return ROOT_PATH . 'public/install';
|
||||
}
|
||||
|
||||
public function doLog($log)
|
||||
{
|
||||
$log = sprintf('[%s] [%s] %s%s', date('Y-m-d H:i:s'), $this->currentStep, $log, PHP_EOL);
|
||||
file_put_contents($this->getLogFile(), $log, FILE_APPEND);
|
||||
}
|
||||
|
||||
public function listAllTableCreate($sqlFile = '')
|
||||
{
|
||||
if (empty($sqlFile)) {
|
||||
$sqlFile = ROOT_PATH . '_db/dbstructure_v1.6.sql';
|
||||
}
|
||||
$pattern = '/CREATE TABLE `(.*)`.*;/isU';
|
||||
$string = file_get_contents($sqlFile);
|
||||
if ($string === false) {
|
||||
throw new \RuntimeException("sql file: $sqlFile can not read, make sure it exits and can be read.");
|
||||
}
|
||||
$count = preg_match_all($pattern, $string, $matches, PREG_SET_ORDER);
|
||||
if ($count == 0) {
|
||||
return [];
|
||||
}
|
||||
return array_column($matches, 0, 1);
|
||||
}
|
||||
|
||||
public function listExistsTable()
|
||||
{
|
||||
dbconn(false, false);
|
||||
$sql = 'show tables';
|
||||
$res = sql_query($sql);
|
||||
$data = [];
|
||||
while ($row = mysql_fetch_row($res)) {
|
||||
$data[] = $row[0];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function listShouldAlterTableTableRows()
|
||||
{
|
||||
$tables = $this->listExistsTable();
|
||||
$data = [];
|
||||
foreach ($tables as $table) {
|
||||
$sql = "desc $table";
|
||||
$res = sql_query($sql);
|
||||
while ($row = mysql_fetch_assoc($res)) {
|
||||
if ($row['Type'] == 'datetime' && $row['Default'] == '0000-00-00 00:00:00') {
|
||||
$data[$table][] = $row['Field'];
|
||||
$data[] = [
|
||||
'label' => "$table." . $row['Field'],
|
||||
'required' => 'default null',
|
||||
'current' => '0000-00-00 00:00:00',
|
||||
'result' => 'NO',
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function listRequirementTableRows()
|
||||
{
|
||||
$gdInfo = gd_info();
|
||||
$tableRows = [
|
||||
[
|
||||
'label' => 'PHP version',
|
||||
'required' => '>= ' . $this->minimumPhpVersion,
|
||||
'current' => PHP_VERSION,
|
||||
'result' => $this->yesOrNo(version_compare(PHP_VERSION, $this->minimumPhpVersion, '>=')),
|
||||
],
|
||||
[
|
||||
'label' => 'PHP extension redis',
|
||||
'required' => 'optional',
|
||||
'current' => extension_loaded('redis'),
|
||||
'result' => $this->yesOrNo(extension_loaded('redis')),
|
||||
],
|
||||
[
|
||||
'label' => 'PHP extension mysqli',
|
||||
'required' => 'enabled',
|
||||
'current' => extension_loaded('mysqli'),
|
||||
'result' => $this->yesOrNo(extension_loaded('mysqli')),
|
||||
],
|
||||
[
|
||||
'label' => 'PHP extension mbstring',
|
||||
'required' => 'enabled',
|
||||
'current' => extension_loaded('mbstring'),
|
||||
'result' => $this->yesOrNo(extension_loaded('mbstring')),
|
||||
],
|
||||
[
|
||||
'label' => 'PHP extension gd',
|
||||
'required' => 'enabled',
|
||||
'current' => extension_loaded('gd'),
|
||||
'result' => $this->yesOrNo(extension_loaded('gd')),
|
||||
],
|
||||
[
|
||||
'label' => 'PHP extension gd JPEG Support',
|
||||
'required' => 'true',
|
||||
'current' => $gdInfo['JPEG Support'],
|
||||
'result' => $this->yesOrNo($gdInfo['JPEG Support']),
|
||||
],
|
||||
[
|
||||
'label' => 'PHP extension gd PNG Support',
|
||||
'required' => 'true',
|
||||
'current' => $gdInfo['PNG Support'],
|
||||
'result' => $this->yesOrNo($gdInfo['PNG Support']),
|
||||
],
|
||||
[
|
||||
'label' => 'PHP extension gd GIF Read Support',
|
||||
'required' => 'true',
|
||||
'current' => $gdInfo['GIF Read Support'],
|
||||
'result' => $this->yesOrNo($gdInfo['GIF Read Support']),
|
||||
],
|
||||
];
|
||||
$fails = array_filter($tableRows, function ($value) {return $value['required'] == 'true' && $value['result'] == 'NO';});
|
||||
$pass = empty($fails);
|
||||
|
||||
return [
|
||||
'table_rows' => $tableRows,
|
||||
'pass' => $pass,
|
||||
];
|
||||
}
|
||||
|
||||
public function listSettingTableRows()
|
||||
{
|
||||
$defaultSettingsFile = ROOT_PATH . '_doc/install/settings.default.php';
|
||||
$originalConfigFile = ROOT_PATH . 'config/allconfig.php';
|
||||
if (!file_exists($defaultSettingsFile)) {
|
||||
throw new \RuntimeException("default setting file: $defaultSettingsFile not exists.");
|
||||
}
|
||||
if (!file_exists($originalConfigFile)) {
|
||||
throw new \RuntimeException("original setting file: $originalConfigFile not exists.");
|
||||
}
|
||||
$tableRows = [
|
||||
[
|
||||
'label' => basename($defaultSettingsFile),
|
||||
'required' => 'exists && readable',
|
||||
'current' => $defaultSettingsFile,
|
||||
'result' => $this->yesOrNo(file_exists($defaultSettingsFile) && is_readable($defaultSettingsFile)),
|
||||
],
|
||||
[
|
||||
'label' => basename($originalConfigFile),
|
||||
'required' => 'exists && readable',
|
||||
'current' => $originalConfigFile,
|
||||
'result' => $this->yesOrNo(file_exists($originalConfigFile) && is_readable($originalConfigFile)),
|
||||
],
|
||||
];
|
||||
$requireDirs = [
|
||||
'main' => ['bitbucket', 'torrent_dir'],
|
||||
'attachment' => ['savedirectory', ],
|
||||
];
|
||||
$symbolicLinks = [];
|
||||
require $originalConfigFile;
|
||||
$settings = require $defaultSettingsFile;
|
||||
foreach ($settings as $prefix => &$group) {
|
||||
$prefixUpperCase = strtoupper($prefix);
|
||||
$oldGroupValues = $$prefixUpperCase ?? null;
|
||||
foreach ($group as $key => &$value) {
|
||||
//merge original config to default setting
|
||||
if (isset($oldGroupValues) && isset($oldGroupValues[$key])) {
|
||||
$value = $oldGroupValues[$key];;
|
||||
}
|
||||
if (isset($requireDirs[$prefix]) && in_array($key, $requireDirs[$prefix])) {
|
||||
$dir = getFullDirectory($value);
|
||||
$tableRows[] = [
|
||||
'label' => "{$prefix}.{$key}",
|
||||
'required' => 'exists && readable',
|
||||
'current' => $dir,
|
||||
'result' => $this->yesOrNo(is_dir($dir) && is_readable($dir)),
|
||||
];
|
||||
$symbolicLinks[] = $dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
$fails = array_filter($tableRows, function ($value) {return $value['required'] == 'true' && $value['result'] == 'NO';});
|
||||
$pass = empty($fails);
|
||||
return [
|
||||
'table_rows' => $tableRows,
|
||||
'symbolic_links' => $symbolicLinks,
|
||||
'settings' => $settings,
|
||||
'pass' => $pass,
|
||||
];
|
||||
}
|
||||
|
||||
public function nextStep()
|
||||
{
|
||||
$this->gotoStep($this->currentStep + 1);
|
||||
}
|
||||
|
||||
public function gotoStep($step)
|
||||
{
|
||||
header('Location: ' . getBaseUrl() . "?step=$step");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
public function maxStep()
|
||||
{
|
||||
return count($this->steps);
|
||||
}
|
||||
|
||||
public function yesOrNo($condition) {
|
||||
if ($condition) {
|
||||
return 'YES';
|
||||
}
|
||||
return 'NO';
|
||||
}
|
||||
|
||||
public function renderTable($header, $data)
|
||||
{
|
||||
$table = '<div class="table w-full text-left">';
|
||||
$table .= '<div class="table-row-group">';
|
||||
$table .= '<div class="table-row">';
|
||||
foreach ($header as $value) {
|
||||
$table .= '<div class="table-cell bg-gray-400 text-gray-700 px-4 py-2">' . $value . '</div>';
|
||||
}
|
||||
$table .= '</div>';
|
||||
foreach ($data as $value) {
|
||||
$table .= '<div class="table-row">';
|
||||
$table .= '<div class="table-cell bg-gray-200 text-gray-700 px-4 py-2 text-sm">' . $value['label'] . '</div>';
|
||||
$table .= '<div class="table-cell bg-gray-200 text-gray-700 px-4 py-2 text-sm">' . $value['required'] . '</div>';
|
||||
$table .= '<div class="table-cell bg-gray-200 text-gray-700 px-4 py-2 text-sm">' . $value['current'] . '</div>';
|
||||
$table .= '<div class="table-cell bg-' . ($value['result'] == 'YES' ? 'green' : 'gray') . '-200 text-gray-700 px-4 py-2 text-sm">' . $value['result'] . '</div>';
|
||||
$table .= '</div>';
|
||||
}
|
||||
$table .= '</div>';
|
||||
$table .= '</div>';
|
||||
|
||||
return $table;
|
||||
|
||||
}
|
||||
|
||||
public function renderForm($formControls, $formWidth = '1/2', $labelWidth = '1/3', $valueWidth = '2/3')
|
||||
{
|
||||
$form = '<div class="inline-block w-' . $formWidth . '">';
|
||||
foreach ($formControls as $value) {
|
||||
$form .= '<div class="flex mt-2">';
|
||||
$form .= sprintf('<div class="w-%s flex justify-end items-center pr-10"><span>%s</span></div>', $labelWidth, $value['label']);
|
||||
$form .= sprintf(
|
||||
'<div class="w-%s flex justify-start items-center pr-10"><input class="border py-2 px-3 text-grey-darkest w-full" type="text" name="%s" value="%s" /></div>',
|
||||
$valueWidth, $value['name'], $value['value'] ?? ''
|
||||
);
|
||||
$form .= '</div>';
|
||||
}
|
||||
$form .= '</div>';
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function renderSteps()
|
||||
{
|
||||
$steps = '<div class="flex mt-10 step text-center">';
|
||||
$currentStep = $this->currentStep();
|
||||
foreach ($this->steps as $key => $value) {
|
||||
$steps .= sprintf('<div class="flex-1 %s">', $currentStep > $key + 1 ? 'done' : ($currentStep < $key + 1 ? 'none' : ''));
|
||||
$steps .= sprintf('<div>第%s步</div>', $key + 1);
|
||||
$steps .= sprintf('<div>%s</div>', $value);
|
||||
$steps .= '</div>';
|
||||
}
|
||||
$steps .= '</div>';
|
||||
return $steps;
|
||||
}
|
||||
|
||||
public function listEnvFormControls()
|
||||
{
|
||||
$envExampleFile = ROOT_PATH . ".env.example";
|
||||
$envExampleData = readEnvFile($envExampleFile);
|
||||
$envFile = ROOT_PATH . '.env';
|
||||
$envData = [];
|
||||
if (file_exists($envFile) && is_readable($envFile)) {
|
||||
//already exists, read it ,and merge
|
||||
$envData = readEnvFile($envFile);
|
||||
}
|
||||
$mergeData = array_merge($envExampleData, $envData);
|
||||
$formControls = [];
|
||||
foreach ($mergeData as $key => $value) {
|
||||
if (isset($_POST[$key])) {
|
||||
$value = $_POST[$key];
|
||||
}
|
||||
$formControls[] = [
|
||||
'label' => $key,
|
||||
'name' => $key,
|
||||
'value' => $value,
|
||||
];
|
||||
}
|
||||
|
||||
return $formControls;
|
||||
}
|
||||
|
||||
public function createAdministrator($username, $email, $password, $confirmPassword)
|
||||
{
|
||||
if (!validusername($username)) {
|
||||
throw new \InvalidArgumentException("Innvalid username: $username");
|
||||
}
|
||||
$email = htmlspecialchars(trim($email));
|
||||
$email = safe_email($email);
|
||||
if (!check_email($email)) {
|
||||
throw new \InvalidArgumentException("Innvalid email: $email");
|
||||
}
|
||||
$res = sql_query("SELECT id FROM users WHERE email=" . sqlesc($email));
|
||||
$arr = mysql_fetch_row($res);
|
||||
if ($arr) {
|
||||
throw new \InvalidArgumentException("The email address: $email is already in use");
|
||||
}
|
||||
if (mb_strlen($password) < 6 || mb_strlen($password) > 40) {
|
||||
throw new \InvalidArgumentException("Innvalid password: $password, it should be more than 6 character and less than 40 character");
|
||||
}
|
||||
if ($password != $confirmPassword) {
|
||||
throw new \InvalidArgumentException("confirmPassword: $confirmPassword != password");
|
||||
}
|
||||
$setting = get_setting('main');
|
||||
$secret = mksecret();
|
||||
$passhash = md5($secret . $password . $secret);
|
||||
$insert = [
|
||||
'username' => $username,
|
||||
'passhash' => $passhash,
|
||||
'secret' => $secret,
|
||||
'email' => $email,
|
||||
'stylesheet' => $setting['defstylesheet'],
|
||||
'class' => 16,
|
||||
'status' => 'confirmed',
|
||||
'added' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
$this->doLog("insert user: " . json_encode($insert));
|
||||
return DB::insert('users', $insert);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
311
public/install/install.php
Normal file
311
public/install/install.php
Normal file
@@ -0,0 +1,311 @@
|
||||
<?php
|
||||
if (!session_id()) {
|
||||
session_start();
|
||||
}
|
||||
$rootpath = dirname(dirname(__DIR__)) . '/';
|
||||
define('ROOT_PATH', $rootpath);
|
||||
$isPost = $_SERVER['REQUEST_METHOD'] == 'POST';
|
||||
require $rootpath . 'vendor/autoload.php';
|
||||
require $rootpath . 'include/globalfunctions.php';
|
||||
require $rootpath . 'include/functions.php';
|
||||
require $rootpath . 'nexus/Database/helpers.php';
|
||||
|
||||
$install = new \Nexus\Install\Install();
|
||||
$currentStep = $install->currentStep();
|
||||
$maxStep = $install->maxStep();
|
||||
|
||||
//step 1
|
||||
if ($currentStep == 1) {
|
||||
$requirements = $install->listRequirementTableRows();
|
||||
$pass = $requirements['pass'];
|
||||
if ($isPost) {
|
||||
$install->nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
if ($currentStep == 2) {
|
||||
$envExampleFile = "$rootpath.env.example";
|
||||
$envExampleData = readEnvFile($envExampleFile);
|
||||
$envFormControls = $install->listEnvFormControls();
|
||||
$newData = array_column($envFormControls, 'value', 'name');
|
||||
while ($isPost) {
|
||||
// $envFile = "$rootpath.env." . time();
|
||||
// $newData = $formData = [];
|
||||
// if (file_exists($envFile) && is_readable($envFile)) {
|
||||
// //already exists, read it ,and merge post data
|
||||
// $newData = readEnvFile($envFile);
|
||||
// }
|
||||
// foreach ($envExampleData as $key => $value) {
|
||||
// $postValue = trim($_POST[$key] ?? '');
|
||||
// if ($postValue) {
|
||||
// $value = $postValue;
|
||||
// }
|
||||
// $newData[$key] = $value;
|
||||
// $envExampleData[] = [
|
||||
// 'label' => $key,
|
||||
// 'name' => $key,
|
||||
// 'value' => $value,
|
||||
// ];
|
||||
// }
|
||||
// unset($key);
|
||||
//check
|
||||
try {
|
||||
$connectMysql = mysql_connect($newData['MYSQL_HOST'], $newData['MYSQL_USERNAME'], $newData['MYSQL_PASSWORD'], $newData['MYSQL_DATABASE'], $newData['MYSQL_PORT']);
|
||||
} catch (\Exception $e) {
|
||||
$_SESSION['error'] = "Mysql: " . $e->getMessage();
|
||||
break;
|
||||
}
|
||||
if (extension_loaded('redis') && !empty($newData['REDIS_HOST'])) {
|
||||
try {
|
||||
$redis = new Redis();
|
||||
$redis->connect($newData['REDIS_HOST'], $newData['REDIS_PORT'] ?: 6379);
|
||||
} catch (\Exception $e) {
|
||||
$_SESSION['error'] = "Redis: " . $e->getMessage();
|
||||
break;
|
||||
}
|
||||
if (!ctype_digit($newData['REDIS_DATABASE']) || $newData['REDIS_DATABASE'] < 0 || $newData['REDIS_DATABASE'] > 15) {
|
||||
$_SESSION['error'] = "invalid REDIS_DATABASE";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// $content = "";
|
||||
// foreach ($newData as $key => $value) {
|
||||
// $content .= "{$key}={$value}\n";
|
||||
// }
|
||||
// $fp = @fopen($envFile, 'w');
|
||||
// if ($fp === false) {
|
||||
// $msg = "文件无法打开, 确保 PHP 有权限在根目录创建文件";
|
||||
// $msg .= "\n也可以复制以下内容保存到 $envFile 中";
|
||||
// $_SESSION['error'] = $msg;
|
||||
// $_SESSION['copy'] = $content;
|
||||
// }
|
||||
// fwrite($fp, $content);
|
||||
// fclose($fp);
|
||||
$install->nextStep();
|
||||
break;
|
||||
}
|
||||
|
||||
$tableRows = [
|
||||
[
|
||||
'label' => '.env.example',
|
||||
'required' => 'exists && readable',
|
||||
'current' => $envExampleFile,
|
||||
'result' => $install->yesOrNo(file_exists($envExampleFile) && is_readable($envExampleFile)),
|
||||
],
|
||||
];
|
||||
$fails = array_filter($tableRows, function ($value) {return $value['result'] == 'NO';});
|
||||
$pass = empty($fails);
|
||||
}
|
||||
|
||||
if ($currentStep == 3) {
|
||||
$pass = true;
|
||||
$existsTable = $install->listExistsTable();
|
||||
$tableCreate = $install->listAllTableCreate();
|
||||
$shouldCreateTable = [];
|
||||
foreach ($tableCreate as $table => $sql) {
|
||||
if (in_array($table, $existsTable)) {
|
||||
continue;
|
||||
}
|
||||
$shouldCreateTable[$table] = $sql;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// $sqlFile = $rootpath . '_db/dbstructure_v1.6.sql';
|
||||
// try {
|
||||
// $tableCreate = listAllTableCreate($sqlFile);
|
||||
// } catch (\Exception $e) {
|
||||
// $_SESSION['error'] = $e->getMessage();
|
||||
// break;
|
||||
// }
|
||||
// if (empty($tableCreate)) {
|
||||
// $_SESSION['error'] = "no table create, make sure sql file is correct";
|
||||
// break;
|
||||
// }
|
||||
|
||||
if ($isPost) {
|
||||
try {
|
||||
foreach ($shouldCreateTable as $table => $sql) {
|
||||
sql_query($sql);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$_SESSION['error'] = $e->getMessage();
|
||||
break;
|
||||
}
|
||||
$install->nextStep();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if ($currentStep == 4) {
|
||||
// $pass = true;
|
||||
// while (true) {
|
||||
// $shouldAlterTable = listShouldAlterTable();
|
||||
// if ($isPost) {
|
||||
// if (!empty($shouldAlterTable)) {
|
||||
// try {
|
||||
// sql_query('SET sql_mode=(SELECT REPLACE(@@sql_mode,"NO_ZERO_DATE", ""));');
|
||||
// foreach ($shouldAlterTable as $table => $fields) {
|
||||
// $sqlAlter = "alter table $table";
|
||||
// $sqlUpdate = "update $table";
|
||||
// $updateWhere = [];
|
||||
// foreach ($fields as $field) {
|
||||
// $sqlAlter .= " modify $field datetime default null,";
|
||||
// $sqlUpdate .= " set $field = null,";
|
||||
// $updateWhere[] = "$field = '0000-00-00 00:00:00'";
|
||||
// }
|
||||
// $sqlAlter = rtrim($sqlAlter, ',');
|
||||
// $sqlUpdate = rtrim($sqlUpdate, ',') . " where " . implode(' or ', $updateWhere);
|
||||
// sql_query($sqlUpdate);
|
||||
// sql_query($sqlAlter);
|
||||
// }
|
||||
// } catch (\Exception $e) {
|
||||
// $_SESSION['error'] = $e->getMessage();
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// goStep($currentStep + 1);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
if ($currentStep == 4) {
|
||||
$settingTableRows = $install->listSettingTableRows();
|
||||
$settings = $settingTableRows['settings'];
|
||||
$symbolicLinks = $settingTableRows['symbolic_links'];
|
||||
$tableRows = $settingTableRows['table_rows'];
|
||||
$pass = $settingTableRows['pass'];
|
||||
while (true) {
|
||||
try {
|
||||
foreach ($settings as $prefix => &$group) {
|
||||
if ($isPost) {
|
||||
$install->doLog("[SAVE] prefix: $prefix, nameAndValues: " . json_encode($group));
|
||||
foreach ($symbolicLinks as $path) {
|
||||
$linkName = ROOT_PATH . 'public/' . basename($path);
|
||||
if (is_dir($linkName)) {
|
||||
$install->doLog("path: $linkName already exits, skip create symbolic link $linkName -> $path");
|
||||
continue;
|
||||
}
|
||||
//@todo
|
||||
// $linkResult = symlink($path, $linkName);
|
||||
// if ($linkResult === false) {
|
||||
// throw new \Exception("can't not make symbolic link: $linkName -> $path");
|
||||
// }
|
||||
}
|
||||
//@todo
|
||||
// saveSetting($prefix, $group);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$_SESSION['error'] = $e->getMessage();
|
||||
break;
|
||||
}
|
||||
$isPost && $install->nextStep();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($currentStep == 5) {
|
||||
if ($isPost) {
|
||||
try {
|
||||
$install->createAdministrator($_POST['username'], $_POST['email'], $_POST['password'], $_POST['confirm_password']);
|
||||
$install->nextStep();
|
||||
} catch (\Exception $exception) {
|
||||
$_SESSION['error'] = $exception->getMessage();
|
||||
}
|
||||
}
|
||||
$pass = true;
|
||||
$userFormControls = [
|
||||
['label' => '用户名', 'name' => 'username', 'value' => $_POST['username'] ?? ''],
|
||||
['label' => '邮箱', 'name' => 'email', 'value' => $_POST['email'] ?? ''],
|
||||
['label' => '密码', 'name' => 'password', 'value' => $_POST['password'] ?? ''],
|
||||
['label' => '重复密码', 'name' => 'confirm_password', 'value' => $_POST['confirm_password'] ?? ''],
|
||||
];
|
||||
}
|
||||
?>
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||
<title>Update NexusPHP | step <?php echo $currentStep?></title>
|
||||
<style type="text/css">
|
||||
.step .none {
|
||||
color: #aaa;
|
||||
}
|
||||
.step .done {
|
||||
color: #67c23a;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mx-auto">
|
||||
<?php echo $install->renderSteps()?>
|
||||
<div class="mt-10">
|
||||
<form method="post" action="<?php echo getBaseUrl() . '?step=' . $currentStep?>">
|
||||
<input type="hidden" name="step" value="<?php echo $currentStep?>">
|
||||
<?php
|
||||
echo'<div class="step-' . $currentStep . ' text-center">';
|
||||
$header = ['项目', '要求', '当前', '结果'];
|
||||
if ($currentStep == 1) {
|
||||
echo $install->renderTable($header, $requirements['table_rows']);
|
||||
} elseif ($currentStep == 2) {
|
||||
echo $install->renderTable($header, $tableRows);
|
||||
echo '<div class="text-gray-700 p-4 text-red-400">若 Redis 不启用,相关项目留空</div>';
|
||||
echo $install->renderForm($envFormControls);
|
||||
|
||||
} elseif ($currentStep == 3) {
|
||||
echo '<h1 class="mb-4 text-lg font-bold">需要新建以下数据表</h1>';
|
||||
if (empty($shouldCreateTable)) {
|
||||
echo '<div class="text-green-600 text-center">恭喜,需要的表均已创建!</div>';
|
||||
} else {
|
||||
echo sprintf('<div class="h-64 text-left inline-block w-2/3"><code class="bolck w-px-100">%s</code></div>', implode(', ', array_keys($shouldCreateTable)));
|
||||
}
|
||||
} elseif ($currentStep == 4) {
|
||||
echo $install->renderTable($header, $tableRows);
|
||||
echo '<div class="text-blue-500 pt-10">';
|
||||
echo sprintf('这一步会把 <code>%s</code> 的数据合并到 <code>%s</code>, 然后插入数据库中。', $tableRows[1]['label'], $tableRows[0]['label']);
|
||||
echo '</div>';
|
||||
} elseif ($currentStep == 5) {
|
||||
echo $install->renderForm($userFormControls, '1/3', '1/4', '3/4');
|
||||
} elseif ($currentStep > $maxStep) {
|
||||
echo '<div class="text-green-900 text-6xl p-10">恭喜,一切就绪!</div>';
|
||||
echo '<div class="mb-6">有问题可查阅安装日志:<code>' . $install->getLogFile() . '</code></div>';
|
||||
echo '<div class="text-red-500">为安全起见,请删除以下目录</div>';
|
||||
echo '<div class="text-red-500"><code>' . $install->getInsallDirectory() . '</code></div>';
|
||||
}
|
||||
echo'</div>';
|
||||
|
||||
if (!empty($_SESSION['error'])) {
|
||||
echo sprintf('<div class="text-center text-red-500 p-4">Error: %s</div>', nl2br($_SESSION['error']));
|
||||
unset($_SESSION['error']);
|
||||
}
|
||||
if (!empty($_SESSION['copy'])) {
|
||||
echo sprintf('<div class="text-center"><textarea class="w-1/2 h-40 border">%s</textarea></div>', $_SESSION['copy']);
|
||||
unset($_SESSION['copy']);
|
||||
}
|
||||
?>
|
||||
<div class="mt-10 text-center">
|
||||
<button class="bg-blue-500 p-2 m-4 text-white rounded" type="button" onclick="goBack()">上一步</button>
|
||||
<?php if ($currentStep <= $maxStep) {?>
|
||||
<button class="bg-blue-<?php echo $pass ? 500 : 200;?> p-2 m-4 text-white rounded" type="submit" <?php echo $pass ? '' : 'disabled';?>>下一步</button>
|
||||
<?php } else {?>
|
||||
<a class="bg-blue-500 p-2 m-4 text-white rounded" href="<?php echo getSchemaAndHttpHost()?>">回首页</a>
|
||||
<?php }?>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
function goBack() {
|
||||
window.location.search="step=<?php echo $currentStep == 1 ? 1 : $currentStep - 1?>"
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
Reference in New Issue
Block a user