Merge branch '1.9' into php8

This commit is contained in:
xiaomlove
2025-10-29 17:18:00 +07:00
8 changed files with 67 additions and 62 deletions
+1 -8
View File
@@ -70,6 +70,7 @@ class TorrentResource extends BaseResource
'description' => $this->whenHas('description'), 'description' => $this->whenHas('description'),
'images' => $this->whenHas('images'), 'images' => $this->whenHas('images'),
'download_url' => $this->whenHas('download_url'), 'download_url' => $this->whenHas('download_url'),
'active_status' => $this->whenHas('active_status'),
'user' => new UserResource($this->whenLoaded('user')), 'user' => new UserResource($this->whenLoaded('user')),
'extra' => new TorrentExtraResource($this->whenLoaded('extra')), 'extra' => new TorrentExtraResource($this->whenLoaded('extra')),
'tags' => TagResource::collection($this->whenLoaded('tags')), 'tags' => TagResource::collection($this->whenLoaded('tags')),
@@ -97,14 +98,6 @@ class TorrentResource extends BaseResource
return self::NAME; return self::NAME;
} }
private function getTorrentRep(): TorrentRepository
{
if (!isset(self::$torrentRep)) {
self::$torrentRep = new TorrentRepository();
}
return self::$torrentRep;
}
protected function hex_esc($matches) { protected function hex_esc($matches) {
return sprintf("%02x", ord($matches[0])); return sprintf("%02x", ord($matches[0]));
} }
+13 -5
View File
@@ -153,6 +153,8 @@ class ToolRepository extends BaseRepository
$result_code = 0; $result_code = 0;
do_log("No tar command, use zip."); do_log("No tar command, use zip.");
} }
File::delete($backupWeb['filename']);
File::delete($backupDatabase['filename']);
if (!$transfer) { if (!$transfer) {
return compact('result_code', 'filename'); return compact('result_code', 'filename');
} }
@@ -216,7 +218,7 @@ class ToolRepository extends BaseRepository
$transferResult = $this->transfer($backupResult['filename'], $backupResult['result_code'], $setting); $transferResult = $this->transfer($backupResult['filename'], $backupResult['result_code'], $setting);
$backupResult['transfer_result'] = $transferResult; $backupResult['transfer_result'] = $transferResult;
do_log("[BACKUP_ALL_DONE]: " . json_encode($backupResult)); do_log("[BACKUP_ALL_DONE]: " . json_encode($backupResult));
$this->cleanupBackupFiles(); $this->cleanupBackupFiles(basename($backupResult['filename']));
return $backupResult; return $backupResult;
} }
@@ -336,20 +338,26 @@ class ToolRepository extends BaseRepository
} }
} }
private function cleanupBackupFiles(): void private function cleanupBackupFiles($basename): void
{ {
$nameParts = explode('.', $basename);
$firstPart = $nameParts[0];
$lastPart = $nameParts[count($nameParts) - 1];
$retentionCount = Setting::getBackupRetentionCount(); $retentionCount = Setting::getBackupRetentionCount();
if ($retentionCount <= 0) { if ($retentionCount <= 0) {
$retentionCount = self::BACKUP_RETENTION_COUNT_DEFAULT; $retentionCount = self::BACKUP_RETENTION_COUNT_DEFAULT;
} }
$path = self::getBackupExportPath(); $path = self::getBackupExportPath();
$allFiles = collect(File::allFiles($path)); $allFiles = collect(File::allFiles($path))->filter(function (\Symfony\Component\Finder\SplFileInfo $file) use ($firstPart, $lastPart) {
$name = basename($file->getRealPath());
return str_starts_with($name, $firstPart) && str_ends_with($name, $lastPart);
});
// 按创建时间降序排序 // 按创建时间降序排序
$allFiles = $allFiles->sortByDesc(fn (\Symfony\Component\Finder\SplFileInfo $file) => $file->getCTime()); $allFiles = $allFiles->sortByDesc(fn (\Symfony\Component\Finder\SplFileInfo $file) => $file->getCTime());
$filesToDelete = $allFiles->slice($retentionCount); $filesToDelete = $allFiles->slice($retentionCount);
do_log(sprintf( do_log(sprintf(
"retentionCount: %s, path: %s, fileCount: %s, toDeleteCount: %s", "retentionCount: %s, path: %s, fileCount: %s",
$retentionCount, $path, $allFiles->count(), $filesToDelete->count() $retentionCount, $path, $allFiles->count()
)); ));
foreach ($filesToDelete as $file) { foreach ($filesToDelete as $file) {
$realPath = $file->getRealPath(); $realPath = $file->getRealPath();
+39 -37
View File
@@ -62,7 +62,28 @@ class TorrentRepository extends BaseRepository
const BUY_STATUS_NOT_YET = -1; const BUY_STATUS_NOT_YET = -1;
const BUY_STATUS_UNKNOWN = -2; const BUY_STATUS_UNKNOWN = -2;
private static array $defaultLoadRelationships = [
'basic_category', 'basic_category.search_box',
'basic_audiocodec', 'basic_codec', 'basic_medium',
'basic_source', 'basic_processing', 'basic_standard', 'basic_team',
];
private static array $allowIncludes = ['user', 'extra', 'tags'];
private static array $allowIncludeCounts = ['thank_users', 'reward_logs', 'claims'];
private static array $allowIncludeFields = [
'has_bookmarked', 'has_claimed', 'has_thanked', 'has_rewarded',
'description', 'download_url', 'active_status'
];
private static array $allowFilters = [
'title', 'category', 'source', 'medium', 'codec', 'audiocodec', 'standard', 'processing', 'team',
'owner', 'visible', 'added', 'size', 'sp_state', 'leechers', 'seeders', 'times_completed',
'bookmark',
];
private static array $allowSorts = ['id', 'comments', 'size', 'seeders', 'leechers', 'times_completed'];
/** /**
* fetch torrent list * fetch torrent list
@@ -83,31 +104,15 @@ class TorrentRepository extends BaseRepository
} }
$categoryIdList = $searchBox->categories()->pluck('id')->toArray(); $categoryIdList = $searchBox->categories()->pluck('id')->toArray();
//query this info default //query this info default
$query = Torrent::query()->with([ $query = Torrent::query()->with(self::$defaultLoadRelationships)
'basic_category', 'basic_category.search_box',
'basic_audiocodec', 'basic_codec', 'basic_medium',
'basic_source', 'basic_processing', 'basic_standard', 'basic_team',
])
->whereIn('category', $categoryIdList) ->whereIn('category', $categoryIdList)
->orderBy("pos_state", "DESC"); ->orderBy("pos_state", "DESC");
$allowIncludes = ['user', 'extra', 'tags'];
$allowIncludeCounts = ['thank_users', 'reward_logs', 'claims'];
$allowIncludeFields = [
'has_bookmarked', 'has_claimed', 'has_thanked', 'has_rewarded',
'description', 'download_url'
];
$allowFilters = [
'title', 'category', 'source', 'medium', 'codec', 'audiocodec', 'standard', 'processing', 'team',
'owner', 'visible', 'added', 'size', 'sp_state', 'leechers', 'seeders', 'times_completed',
'bookmark',
];
$allowSorts = ['id', 'comments', 'size', 'seeders', 'leechers', 'times_completed'];
$apiQueryBuilder = ApiQueryBuilder::for(TorrentResource::NAME, $query, $request) $apiQueryBuilder = ApiQueryBuilder::for(TorrentResource::NAME, $query, $request)
->allowIncludes($allowIncludes) ->allowIncludes(self::$allowIncludes)
->allowIncludeCounts($allowIncludeCounts) ->allowIncludeCounts(self::$allowIncludeCounts)
->allowIncludeFields($allowIncludeFields) ->allowIncludeFields(self::$allowIncludeFields)
->allowFilters($allowFilters) ->allowFilters(self::$allowFilters)
->allowSorts($allowSorts) ->allowSorts(self::$allowSorts)
->registerCustomFilter('title', function (Builder $query, Request $request) { ->registerCustomFilter('title', function (Builder $query, Request $request) {
$title = $request->input(ApiQueryBuilder::PARAM_NAME_FILTER.".title"); $title = $request->input(ApiQueryBuilder::PARAM_NAME_FILTER.".title");
$title = trim(str_replace('.', '', $title)); $title = trim(str_replace('.', '', $title));
@@ -161,21 +166,11 @@ class TorrentRepository extends BaseRepository
public function getDetail($id, Authenticatable $user) public function getDetail($id, Authenticatable $user)
{ {
//query this info default //query this info default
$query = Torrent::query()->with([ $query = Torrent::query()->with(self::$defaultLoadRelationships);
'basic_category', 'basic_category.search_box',
'basic_audiocodec', 'basic_codec', 'basic_medium',
'basic_source', 'basic_processing', 'basic_standard', 'basic_team',
]);
$allowIncludes = ['user', 'extra', 'tags'];
$allowIncludeCounts = ['thank_users', 'reward_logs', 'claims'];
$allowIncludeFields = [
'has_bookmarked', 'has_claimed', 'has_thanked', 'has_rewarded',
'description', 'download_url'
];
$apiQueryBuilder = ApiQueryBuilder::for(TorrentResource::NAME, $query) $apiQueryBuilder = ApiQueryBuilder::for(TorrentResource::NAME, $query)
->allowIncludes($allowIncludes) ->allowIncludes(self::$allowIncludes)
->allowIncludeCounts($allowIncludeCounts) ->allowIncludeCounts(self::$allowIncludeCounts)
->allowIncludeFields($allowIncludeFields) ->allowIncludeFields(self::$allowIncludeFields)
; ;
do_log("before query torrent detail"); do_log("before query torrent detail");
$torrent = $apiQueryBuilder->build()->findOrFail($id); $torrent = $apiQueryBuilder->build()->findOrFail($id);
@@ -186,7 +181,7 @@ class TorrentRepository extends BaseRepository
private function appendIncludeFields(ApiQueryBuilder $apiQueryBuilder, Authenticatable $user, $torrentList) private function appendIncludeFields(ApiQueryBuilder $apiQueryBuilder, Authenticatable $user, $torrentList)
{ {
$torrentIdArr = $bookmarkData = $claimData = $thankData = $rewardData =[]; $torrentIdArr = $bookmarkData = $claimData = $thankData = $rewardData = $activeData = [];
foreach ($torrentList as $torrent) { foreach ($torrentList as $torrent) {
$torrentIdArr[] = $torrent->id; $torrentIdArr[] = $torrent->id;
} }
@@ -203,6 +198,10 @@ class TorrentRepository extends BaseRepository
if ($hasFieldHasRewarded = $apiQueryBuilder->hasIncludeField('has_rewarded')) { if ($hasFieldHasRewarded = $apiQueryBuilder->hasIncludeField('has_rewarded')) {
$rewardData = $user->reward_torrent_logs()->whereIn('torrentid', $torrentIdArr)->get()->keyBy('torrentid'); $rewardData = $user->reward_torrent_logs()->whereIn('torrentid', $torrentIdArr)->get()->keyBy('torrentid');
} }
if ($hasFieldActiveStatus = $apiQueryBuilder->hasIncludeField('active_status')) {
$torrentModule = new \Nexus\Torrent\Torrent();
$activeData = $torrentModule->listLeechingSeedingStatus($user->id, $torrentIdArr);
}
do_log("after prepare has data"); do_log("after prepare has data");
foreach ($torrentList as $torrent) { foreach ($torrentList as $torrent) {
@@ -219,6 +218,9 @@ class TorrentRepository extends BaseRepository
if ($hasFieldHasRewarded) { if ($hasFieldHasRewarded) {
$torrent->has_rewarded = $rewardData->has($id); $torrent->has_rewarded = $rewardData->has($id);
} }
if ($hasFieldActiveStatus) {
$torrent->active_status = $activeData[$id] ?? null;
}
if ($apiQueryBuilder->hasIncludeField('description') && $apiQueryBuilder->hasInclude('extra')) { if ($apiQueryBuilder->hasIncludeField('description') && $apiQueryBuilder->hasInclude('extra')) {
$descriptionArr = format_description($torrent->extra->descr ?? ''); $descriptionArr = format_description($torrent->extra->descr ?? '');
+1 -1
View File
@@ -1,6 +1,6 @@
<?php <?php
defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.9.10'); defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.9.10');
defined('RELEASE_DATE') || define('RELEASE_DATE', '2025-10-17'); defined('RELEASE_DATE') || define('RELEASE_DATE', '2025-10-29');
defined('IN_TRACKER') || define('IN_TRACKER', false); defined('IN_TRACKER') || define('IN_TRACKER', false);
defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP"); defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP");
defined('NEXUSPHPURL') || define("NEXUSPHPURL","https://nexusphp.org"); defined('NEXUSPHPURL') || define("NEXUSPHPURL","https://nexusphp.org");
+3 -1
View File
@@ -6063,7 +6063,9 @@ function insert_torrent_tags($torrentId, $tagIdArr, $sync = false)
do_log("special tag: $tagId, and user no permission"); do_log("special tag: $tagId, and user no permission");
continue; continue;
} }
$values[] = sprintf("(%s, %s, '%s', '%s')", $torrentId, $tagId, $dateTimeStringNow, $dateTimeStringNow); if (!isset($values[$tagId])) {
$values[$tagId] = sprintf("(%s, %s, '%s', '%s')", $torrentId, $tagId, $dateTimeStringNow, $dateTimeStringNow);
}
} }
$insertTagsSql .= implode(', ', $values); $insertTagsSql .= implode(', ', $values);
do_log("[INSERT_TAGS], torrent: $torrentId with tags: " . nexus_json_encode($tagIdArr)); do_log("[INSERT_TAGS], torrent: $torrentId with tags: " . nexus_json_encode($tagIdArr));
+4 -1
View File
@@ -725,7 +725,10 @@ function get_tracker_schema_and_host($trackerUrlId, $combine = false): array|str
$url = \App\Models\TrackerUrl::getById($trackerUrlId); $url = \App\Models\TrackerUrl::getById($trackerUrlId);
if (empty($url)) { if (empty($url)) {
$ssl_torrent = isHttps() ? 'https://' : 'http://'; $ssl_torrent = isHttps() ? 'https://' : 'http://';
$base_announce_url = sprintf("%s/%s", \App\Models\Setting::getBaseUrl(), DEFAULT_TRACKER_URI); $base_announce_url = sprintf(
"%s/%s",
trim(\App\Models\Setting::getBaseUrl(), '/'), trim(DEFAULT_TRACKER_URI, '/')
);
$log .= ", ById no value"; $log .= ", ById no value";
} else { } else {
$ssl_torrent = parse_url($url, PHP_URL_SCHEME) . "://" ; $ssl_torrent = parse_url($url, PHP_URL_SCHEME) . "://" ;
+5 -5
View File
@@ -25,17 +25,17 @@ class Torrent
} }
$torrentIdStr = implode(',', $torrentIdArr); $torrentIdStr = implode(',', $torrentIdArr);
//seeding or leeching, from peers //seeding or leeching, from peers
$whereStr = sprintf("userid = %s and torrent in (%s)", sqlesc($uid), $torrentIdStr); $whereStr = sprintf("userid = %s and torrent in (%s)", $uid, $torrentIdStr);
$peerList = NexusDB::getAll('peers', $whereStr, 'torrent, to_go'); $peerList = NexusDB::getAll('peers', $whereStr, 'torrent, to_go');
$peerList = array_column($peerList,'to_go', 'torrent'); $peerList = array_column($peerList,'to_go', 'torrent');
//download progress, from snatched //download progress, from snatched
$sql = sprintf( $sql = sprintf(
"select snatched.to_go, snatched.torrentid, torrents.size from snatched inner join torrents on snatched.torrentid = torrents.id where snatched.userid = %s and snatched.torrentid in (%s)", "select snatched.to_go, snatched.torrentid, torrents.size from snatched inner join torrents on snatched.torrentid = torrents.id where snatched.userid = %s and snatched.torrentid in (%s)",
sqlesc($uid), $torrentIdStr $uid, $torrentIdStr
); );
$snatchedList = []; $snatchedList = [];
$res = sql_query($sql); $res = NexusDB::select($sql);
while ($row = mysql_fetch_assoc($res)) { foreach ($res as $row) {
$id = $row['torrentid']; $id = $row['torrentid'];
$activeStatus = 'inactivity'; $activeStatus = 'inactivity';
if (isset($peerList[$id])) { if (isset($peerList[$id])) {
@@ -49,7 +49,7 @@ class Torrent
$progress = sprintf('%.4f', $realDownloaded / $row['size']); $progress = sprintf('%.4f', $realDownloaded / $row['size']);
$snatchedList[$id] = [ $snatchedList[$id] = [
'finished' => $row['to_go'] == 0 ? 'yes' : 'no', 'finished' => $row['to_go'] == 0 ? 'yes' : 'no',
'progress' => $progress, 'progress' => floatval($progress),
'active_status' => $activeStatus, 'active_status' => $activeStatus,
]; ];
} }
+1 -4
View File
@@ -135,10 +135,7 @@ $isDonor = is_donor($az);
$az['__is_donor'] = $isDonor; $az['__is_donor'] = $isDonor;
$log = "user: $userid, isDonor: $isDonor, seeder: $seeder, ip: $ip, ipv4: $ipv4, ipv6: $ipv6"; $log = "user: $userid, isDonor: $isDonor, seeder: $seeder, ip: $ip, ipv4: $ipv4, ipv6: $ipv6";
//check tracker url //check tracker url
$trackerUrl = \App\Models\TrackerUrl::getById($az['tracker_url_id']); $trackerUrl = get_tracker_schema_and_host($az['tracker_url_id'], true);
if ($trackerUrl === false) {
warn("please select tracker url at user control panel");
}
$currentUrl = getSchemeAndHttpHost(); $currentUrl = getSchemeAndHttpHost();
if (!str_contains($trackerUrl, $currentUrl)) { if (!str_contains($trackerUrl, $currentUrl)) {
do_log("announce check tracker url, trackerUrl: $trackerUrl does not contains: $currentUrl"); do_log("announce check tracker url, trackerUrl: $trackerUrl does not contains: $currentUrl");