Files
nexusphp/nexus/Install/Update.php

423 lines
15 KiB
PHP
Raw Normal View History

2021-02-01 02:33:45 +08:00
<?php
namespace Nexus\Install;
2021-06-13 22:21:42 +08:00
use App\Models\Attendance;
2021-06-21 02:01:26 +08:00
use App\Models\BonusLogs;
2021-05-29 21:48:50 +08:00
use App\Models\Category;
use App\Models\Exam;
use App\Models\ExamUser;
2021-06-22 01:04:50 +08:00
use App\Models\HitAndRun;
2021-05-29 21:48:50 +08:00
use App\Models\Icon;
2021-06-06 13:41:05 +08:00
use App\Models\Setting;
2022-03-08 15:08:56 +08:00
use App\Models\Tag;
use App\Models\Torrent;
use App\Models\TorrentTag;
2021-06-21 02:01:26 +08:00
use App\Models\User;
2022-03-10 21:45:23 +08:00
use App\Repositories\AttendanceRepository;
2022-02-10 22:30:26 +08:00
use App\Repositories\BonusRepository;
use App\Repositories\ExamRepository;
2022-03-08 15:08:56 +08:00
use App\Repositories\TagRepository;
2021-06-21 02:01:26 +08:00
use Carbon\Carbon;
2021-06-17 20:07:22 +08:00
use GuzzleHttp\Client;
2022-02-10 22:30:26 +08:00
use Illuminate\Database\Eloquent\Model;
2021-06-06 13:41:05 +08:00
use Illuminate\Support\Str;
2021-06-08 10:42:39 +08:00
use Nexus\Database\NexusDB;
2021-02-01 02:33:45 +08:00
class Update extends Install
{
2022-03-08 15:08:56 +08:00
protected $steps = ['Env check', 'Get files', 'Update .env', 'Perform updates'];
2021-02-01 02:33:45 +08:00
2022-04-25 02:30:15 +08:00
protected string $lockFile = 'update.lock';
2021-02-01 02:33:45 +08:00
public function getLogFile()
{
2021-06-05 17:04:53 +08:00
return sprintf('%s/nexus-update-%s.log', sys_get_temp_dir(), date('Ymd'));
2021-02-01 02:33:45 +08:00
}
public function getUpdateDirectory()
{
return ROOT_PATH . 'public/update';
}
2021-02-01 20:19:39 +08:00
public function listTableFieldsFromCreateTable($createTableSql)
{
$arr = preg_split("/[\r\n]+/", $createTableSql);
$result = [];
foreach ($arr as $value) {
$value = trim($value);
if (substr($value, 0, 1) != '`') {
continue;
}
$pos = strpos($value, '`', 1);
$field = substr($value, 1, $pos - 1);
$result[$field] = rtrim($value, ',');
}
return $result;
}
2021-02-01 02:33:45 +08:00
2021-02-01 20:19:39 +08:00
public function listTableFieldsFromDb($table)
2021-02-01 02:33:45 +08:00
{
2021-02-01 20:19:39 +08:00
$sql = "desc $table";
$res = sql_query($sql);
2021-02-01 02:33:45 +08:00
$data = [];
2021-02-01 20:19:39 +08:00
while ($row = mysql_fetch_assoc($res)) {
$data[$row['Field']] = $row;
2021-02-01 02:33:45 +08:00
}
return $data;
}
2021-06-21 02:01:26 +08:00
private function addSetting($name, $value)
{
$attributes = [
'name' => $name,
];
$now = Carbon::now()->toDateTimeString();
$values = [
'value' => $value,
'created_at' => $now,
'updated_at' => $now,
];
return Setting::query()->firstOrCreate($attributes, $values);
}
public function runExtraQueries()
{
2022-05-30 02:08:30 +08:00
/**
* @since 1.7.13
*/
foreach (['adminpanel', 'modpanel', 'sysoppanel'] as $table) {
$columnInfo = NexusDB::getMysqlColumnInfo($table, 'id');
if ($columnInfo['DATA_TYPE'] == 'tinyint') {
sql_query("alter table $table modify id int(11) unsigned not null AUTO_INCREMENT");
}
}
//custom field menu
$url = 'fields.php';
$table = 'adminpanel';
$count = get_row_count($table, "where url = " . sqlesc($url));
if ($count == 0) {
$insert = [
'name' => 'Custom Field Manage',
'url' => $url,
'info' => 'Manage custom fields',
];
2021-06-08 10:42:39 +08:00
$id = NexusDB::insert($table, $insert);
$this->doLog("[ADD CUSTOM FIELD MENU] insert: " . json_encode($insert) . " to table: $table, id: $id");
}
2021-06-06 13:41:05 +08:00
//since beta8
2022-05-13 14:40:59 +08:00
if (WITH_LARAVEL && !NexusDB::hasColumn('categories', 'icon_id')) {
$this->doLog('[INIT CATEGORY ICON_ID]');
2022-03-08 15:08:56 +08:00
$this->runMigrate('database/migrations/2022_03_08_040415_add_icon_id_to_categories_table.php');
2021-05-29 21:48:50 +08:00
$icon = Icon::query()->orderBy('id', 'asc')->first();
if ($icon) {
Category::query()->where('icon_id', 0)->update(['icon_id' => $icon->id]);
}
}
2021-06-06 13:41:05 +08:00
//fix base url, since beta8
2022-05-13 14:40:59 +08:00
if (WITH_LARAVEL && NexusDB::hasTable('settings')) {
2021-06-06 13:41:05 +08:00
$settingBasic = get_setting('basic');
if (isset($settingBasic['BASEURL']) && Str::startsWith($settingBasic['BASEURL'], 'localhost')) {
$this->doLog('[RESET CONFIG basic.BASEURL]');
Setting::query()->where('name', 'basic.BASEURL')->update(['value' => '']);
}
if (isset($settingBasic['announce_url']) && Str::startsWith($settingBasic['announce_url'], 'localhost')) {
$this->doLog('[RESET CONFIG basic.announce_url]');
Setting::query()->where('name', 'basic.announce_url')->update(['value' => '']);
}
}
//torrent support sticky second level
if (WITH_LARAVEL) {
2021-06-08 10:42:39 +08:00
$columnInfo = NexusDB::getMysqlColumnInfo('torrents', 'pos_state');
2021-06-06 13:41:05 +08:00
$this->doLog("[TORRENT POS_STATE], column info: " . json_encode($columnInfo));
if ($columnInfo['DATA_TYPE'] == 'enum') {
$sql = "alter table torrents modify `pos_state` varchar(32) NOT NULL DEFAULT 'normal'";
$this->doLog("[ALTER TORRENT POS_STATE TYPE TO VARCHAR], $sql");
sql_query($sql);
}
}
2021-06-13 22:21:42 +08:00
/**
* @since 1.6.0-beta9
*
* attendance change, do migrate
*/
if (WITH_LARAVEL) {
2022-05-13 14:40:59 +08:00
if (!NexusDB::hasTable('attendance')) {
//no table yet, no need to migrate
$this->runMigrate('database/migrations/2021_06_08_113437_create_attendance_table.php');
}
2022-05-13 14:40:59 +08:00
if (!NexusDB::hasColumn('attendance', 'total_days')) {
$this->runMigrate('database/migrations/2021_06_13_215440_add_total_days_to_attendance_table.php');
2022-03-10 21:45:23 +08:00
$attendanceRep = new AttendanceRepository();
$count = $attendanceRep->migrateAttendance();
$this->doLog("[MIGRATE_ATTENDANCE] $count");
}
2021-06-13 22:21:42 +08:00
}
2021-06-21 02:01:26 +08:00
2022-02-10 22:30:26 +08:00
/**
* @since 1.6.0-beta13
*
* add seed points to user
*/
2022-05-13 14:40:59 +08:00
if (WITH_LARAVEL && !NexusDB::hasColumn('users', 'seed_points')) {
$this->runMigrate('database/migrations/2021_06_24_013107_add_seed_points_to_users_table.php');
2022-02-19 23:37:27 +08:00
//Don't do this, initial seed points = 0;
// $result = $this->initSeedPoints();
$this->doLog("[INIT SEED POINTS]");
2021-06-21 02:01:26 +08:00
}
2022-02-10 22:30:26 +08:00
2022-02-25 23:13:34 +08:00
/**
* @since 1.6.0-beta14
*
* add id to agent_allowed_exception
*/
2022-05-13 14:40:59 +08:00
if (WITH_LARAVEL && !NexusDB::hasColumn('agent_allowed_exception', 'id')) {
2022-02-25 23:13:34 +08:00
$this->runMigrate('database/migrations/2022_02_25_021356_add_id_to_agent_allowed_exception_table.php');
$this->doLog("[ADD_ID_TO_AGENT_ALLOWED_EXCEPTION]");
}
2022-03-08 15:25:15 +08:00
/**
* @since 1.6.0
*
* init tag
*/
2022-05-13 14:40:59 +08:00
if (WITH_LARAVEL && !NexusDB::hasTable('tags')) {
2022-03-08 15:25:15 +08:00
$this->runMigrate('database/migrations/2022_03_07_012545_create_tags_table.php');
$this->initTag();
$this->doLog("[INIT_TAG]");
}
2022-03-21 19:09:32 +08:00
/**
* @since 1.6.3
*
* add usersearch.php and unco.php
*/
$menus = [
['name' => 'Search user', 'url' => 'usersearch.php', 'info' => 'Search user'],
['name' => 'Confirm user', 'url' => 'unco.php', 'info' => 'Confirm user to complete registration'],
];
$table = 'modpanel';
foreach ($menus as $menu) {
$count = get_row_count($table, "where url = " . sqlesc($menu['url']));
if ($count == 0) {
$id = NexusDB::insert($table, $menu);
$this->doLog("[ADD MENU] insert: " . json_encode($menu) . " to table: $table, id: $id");
}
}
2022-02-10 22:30:26 +08:00
2022-04-03 16:03:47 +08:00
/**
* @since 1.7.0
*
* add attendance_card to users
*/
2022-05-13 14:40:59 +08:00
if (WITH_LARAVEL && !NexusDB::hasColumn('users', 'attendance_card')) {
2022-04-03 16:03:47 +08:00
$this->runMigrate('database/migrations/2022_04_02_163930_create_attendance_logs_table.php');
$this->runMigrate('database/migrations/2022_04_03_041642_add_attendance_card_to_users_table.php');
$rep = new AttendanceRepository();
$count = $rep->migrateAttendanceLogs();
$this->doLog("[ADD_ATTENDANCE_CARD_TO_USERS], migrateAttendanceLogs: $count");
}
2022-04-04 17:26:26 +08:00
/**
* @since 1.7.12
2022-04-04 17:26:26 +08:00
*/
$menus = [
['name' => 'Add Bonus/Attend card/Invite/upload', 'url' => 'increment-bulk.php', 'info' => 'Add Bonus/Attend card/Invite/upload to certain classes'],
2022-04-04 17:26:26 +08:00
];
$table = 'sysoppanel';
$this->addMenu($table, $menus);
2022-06-03 03:42:53 +08:00
$menuToDel = ['amountupload.php', 'amountattendancecard.php', 'amountbonus.php', 'deletedisabled.php'];
$this->removeMenu('sysoppanel', $menuToDel);
$this->removeMenu('adminpanel', $menuToDel);
$this->removeMenu('modpanel', $menuToDel);
2022-05-30 02:08:30 +08:00
2022-03-08 15:08:56 +08:00
}
public function runExtraMigrate()
{
if (!WITH_LARAVEL) {
$this->doLog(__METHOD__ . ", laravel is not available");
return;
}
2022-05-13 14:40:59 +08:00
if (NexusDB::hasColumn('torrents', 'tags')) {
2022-03-13 22:47:53 +08:00
if (Torrent::query()->where('tags', '>', 0)->count() > 0 && TorrentTag::query()->count() == 0) {
$this->doLog("[MIGRATE_TORRENT_TAG]...");
$tagRep = new TagRepository();
$tagRep->migrateTorrentTag();
$this->doLog("[MIGRATE_TORRENT_TAG] done!");
}
$sql = 'alter table torrents drop column tags';
sql_query($sql);
$this->doLog($sql);
2022-03-08 15:08:56 +08:00
} else {
2022-03-13 22:47:53 +08:00
$this->doLog("torrents table does not has column: tags");
2022-03-08 15:08:56 +08:00
}
2022-03-08 21:01:12 +08:00
2021-06-13 22:21:42 +08:00
}
2022-04-04 17:26:26 +08:00
private function addMenu($table, array $menus)
{
foreach ($menus as $menu) {
$count = get_row_count($table, "where url = " . sqlesc($menu['url']));
if ($count == 0) {
$id = NexusDB::insert($table, $menu);
$this->doLog("[ADD MENU] insert: " . json_encode($menu) . " to table: $table, id: $id");
}
}
}
private function removeMenu($table, array $menus)
{
foreach ($menus as $menu) {
NexusDB::delete($table, "url = " . sqlesc($menu));
}
}
2021-06-17 20:07:22 +08:00
public function listVersions()
{
$url = "https://api.github.com/repos/xiaomlove/nexusphp/releases";
2022-02-12 19:46:04 +08:00
$versions = $this->requestGithub($url);
return array_reverse($versions);
}
public function getLatestCommit()
{
$url = "https://api.github.com/repos/xiaomlove/nexusphp/commits/php8";
return $this->requestGithub($url);
}
public function requestGithub($url)
{
$client = new Client();
$logPrefix = "Request github: $url";
2021-06-17 20:07:22 +08:00
$response = $client->get($url, ['timeout' => 10,]);
if (($statusCode = $response->getStatusCode()) != 200) {
throw new \RuntimeException("$logPrefix fail, status code$statusCode");
2021-06-17 20:07:22 +08:00
}
if ($response->getBody()->getSize() <= 0) {
throw new \RuntimeException("$logPrefix fail, response empty");
2021-06-17 20:07:22 +08:00
}
$bodyString = $response->getBody()->getContents();
2022-02-12 19:46:04 +08:00
$this->doLog("[REQUEST_GITHUB_RESPONSE]: $bodyString");
$results = json_decode($bodyString, true);
if (empty($results) || !is_array($results)) {
throw new \RuntimeException("$logPrefix response invalid");
2021-06-17 20:07:22 +08:00
}
2022-02-12 19:46:04 +08:00
return $results;
2021-06-17 20:07:22 +08:00
}
2022-07-03 14:00:07 +08:00
public function downAndExtractCode($url, array $includes = []): string
2021-06-17 20:07:22 +08:00
{
$arr = explode('/', $url);
$basename = last($arr);
2022-02-12 19:46:04 +08:00
$isZip = false;
if (Str::contains($basename,'.zip')) {
$isZip = true;
$basename = strstr($basename, '.zip', true);
$suffix = ".zip";
} else {
$suffix = '.tar.gz';
}
2021-06-17 20:07:22 +08:00
$filename = sprintf('%s/nexusphp-%s-%s%s', sys_get_temp_dir(), $basename, date('YmdHis'), $suffix);
$this->doLog("download from: $url, save to filename: $filename");
2021-06-17 20:07:22 +08:00
$client = new Client();
$response = $client->request('GET', $url, ['sink' => $filename]);
if (($statusCode = $response->getStatusCode()) != 200) {
throw new \RuntimeException("Download fail, status code$statusCode");
2021-06-17 20:07:22 +08:00
}
if (($bodySize = $response->getBody()->getSize()) <= 0) {
throw new \RuntimeException("Download fail, file size$bodySize");
2021-06-17 20:07:22 +08:00
}
if (!file_exists($filename)) {
throw new \RuntimeException("Download fail, file not exists$filename");
2021-06-17 20:07:22 +08:00
}
if (filesize($filename) <= 0) {
throw new \RuntimeException("Download fail, file: $filename size = 0");
2021-06-17 20:07:22 +08:00
}
$this->doLog('SUCCESS_DOWNLOAD');
$extractDir = str_replace($suffix, "", $filename);
$command = "mkdir -p $extractDir";
2022-02-12 19:46:04 +08:00
$this->executeCommand($command);
2021-06-17 20:07:22 +08:00
2022-02-12 19:46:04 +08:00
if ($isZip) {
$command = "unzip -q $filename -d $extractDir";
2022-02-12 19:46:04 +08:00
} else {
$command = "tar -xf $filename -C $extractDir";
2021-06-17 20:07:22 +08:00
}
2022-02-12 19:46:04 +08:00
$this->executeCommand($command);
2021-06-17 20:07:22 +08:00
foreach (glob("$extractDir/*") as $path) {
if (is_dir($path)) {
2022-07-03 14:00:07 +08:00
$excludes = ['.git', 'public/favicon.ico', '.env'];
if (!in_array('composer', $includes)) {
$excludes[] = 'composer.lock';
$excludes[] = 'composer.json';
}
// $command = sprintf('cp -raf %s/. %s', $path, ROOT_PATH);
$command = "rsync -rvq $path/ " . ROOT_PATH;
foreach ($excludes as $exclude) {
$command .= " --exclude=$exclude";
}
2022-02-12 19:46:04 +08:00
$this->executeCommand($command);
2021-06-17 20:07:22 +08:00
break;
}
}
$this->doLog('SUCCESS_EXTRACT');
return $extractDir;
2021-06-17 20:07:22 +08:00
}
2022-02-10 22:30:26 +08:00
public function initSeedPoints(): int
{
$size = 10000;
$tableName = (new User())->getTable();
$result = 0;
do {
$affectedRows = NexusDB::table($tableName)
->whereNull('seed_points')
->limit($size)
->update([
'seed_points' => NexusDB::raw('seedbonus')
2022-02-10 22:30:26 +08:00
]);
$result += $affectedRows;
$this->doLog("affectedRows: $affectedRows, query: " . last_query());
} while ($affectedRows > 0);
return $result;
}
2022-02-12 15:48:26 +08:00
public function updateDependencies()
{
2022-02-12 20:57:34 +08:00
$command = "composer install -d " . ROOT_PATH;
2022-02-12 15:48:26 +08:00
$this->executeCommand($command);
$this->doLog("[COMPOSER INSTALL] SUCCESS");
}
2022-03-08 15:25:15 +08:00
public function initTag()
{
$priority = count(Tag::DEFAULTS);
$dateTimeStringNow = date('Y-m-d H:i:s');
foreach (Tag::DEFAULTS as $value) {
$attributes = [
'name' => $value['name'],
];
$values = [
'priority' => $priority,
'color' => $value['color'],
'created_at' => $dateTimeStringNow,
'updated_at' => $dateTimeStringNow,
];
Tag::query()->firstOrCreate($attributes, $values);
$priority--;
}
}
2022-03-08 15:08:56 +08:00
2021-05-01 02:02:01 +08:00
}