暂存
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace app\service\AdminConsole;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use support\Db;
|
||||
|
||||
class ArchiveAdminService
|
||||
{
|
||||
public function list(string $query = '', int $page = 1, int $pageSize = 20): array
|
||||
{
|
||||
$page = max(1, $page);
|
||||
$pageSize = min(100, max(1, $pageSize));
|
||||
|
||||
$builder = Db::table('archives');
|
||||
$query = trim($query);
|
||||
if ($query !== '') {
|
||||
$like = '%' . $query . '%';
|
||||
$builder->where(function ($subQuery) use ($like): void {
|
||||
$subQuery
|
||||
->orWhere('archive_uid', 'like', $like)
|
||||
->orWhere('title', 'like', $like)
|
||||
->orWhere('summary', 'like', $like)
|
||||
->orWhere('author', 'like', $like)
|
||||
->orWhere('source', 'like', $like)
|
||||
->orWhere('series', 'like', $like);
|
||||
});
|
||||
}
|
||||
|
||||
$total = (clone $builder)->count();
|
||||
$rows = $builder
|
||||
->orderByDesc('updated_time')
|
||||
->offset(($page - 1) * $pageSize)
|
||||
->limit($pageSize)
|
||||
->get([
|
||||
'archive_uid',
|
||||
'title',
|
||||
'summary',
|
||||
'year',
|
||||
'author',
|
||||
'source',
|
||||
'series',
|
||||
'tags',
|
||||
'created_time',
|
||||
'updated_time',
|
||||
Db::raw('jsonb_array_length(chunks) as chunk_count'),
|
||||
])
|
||||
->all();
|
||||
|
||||
return [
|
||||
'items' => array_map(fn (object $row): array => $this->listItem($row), $rows),
|
||||
'total' => (int) $total,
|
||||
'page' => $page,
|
||||
'page_size' => $pageSize,
|
||||
];
|
||||
}
|
||||
|
||||
public function detail(string $archiveUid): ?array
|
||||
{
|
||||
$row = Db::table('archives')->where('archive_uid', $archiveUid)->first();
|
||||
if (!$row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->detailItem($row);
|
||||
}
|
||||
|
||||
public function update(string $archiveUid, array $payload): ?array
|
||||
{
|
||||
if (!$this->detail($archiveUid)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$updates = [];
|
||||
foreach (['title', 'summary', 'author', 'source', 'series', 'content', 'raw'] as $field) {
|
||||
if (array_key_exists($field, $payload)) {
|
||||
$updates[$field] = $this->nullableText($payload[$field]);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('year', $payload)) {
|
||||
$year = trim((string) ($payload['year'] ?? ''));
|
||||
if ($year === '') {
|
||||
$updates['year'] = null;
|
||||
} elseif (!preg_match('/^\d{1,4}$/', $year)) {
|
||||
throw new InvalidArgumentException('year must be empty or a 1-4 digit number.');
|
||||
} else {
|
||||
$updates['year'] = (int) $year;
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('tags', $payload)) {
|
||||
$updates['tags'] = json_encode($this->normalizeTags($payload['tags']), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
if (array_key_exists('metadata', $payload)) {
|
||||
$updates['metadata'] = json_encode($this->normalizeMetadata($payload['metadata']), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
if ($updates !== []) {
|
||||
Db::table('archives')->where('archive_uid', $archiveUid)->update($updates);
|
||||
}
|
||||
|
||||
return $this->detail($archiveUid);
|
||||
}
|
||||
|
||||
public function delete(string $archiveUid): bool
|
||||
{
|
||||
return (int) Db::table('archives')->where('archive_uid', $archiveUid)->delete() > 0;
|
||||
}
|
||||
|
||||
private function listItem(object $row): array
|
||||
{
|
||||
$chunks = $this->decodeJson($row->chunks ?? null, []);
|
||||
|
||||
return [
|
||||
'archive_uid' => (string) $row->archive_uid,
|
||||
'title' => $row->title,
|
||||
'summary' => $row->summary,
|
||||
'year' => $row->year === null ? null : (int) $row->year,
|
||||
'author' => $row->author,
|
||||
'source' => $row->source,
|
||||
'series' => $row->series,
|
||||
'tags' => $this->decodeJson($row->tags ?? null, []),
|
||||
'chunk_count' => property_exists($row, 'chunk_count')
|
||||
? ($row->chunk_count === null ? 0 : (int) $row->chunk_count)
|
||||
: count(is_array($chunks) ? $chunks : []),
|
||||
'created_time' => $row->created_time,
|
||||
'updated_time' => $row->updated_time,
|
||||
];
|
||||
}
|
||||
|
||||
private function detailItem(object $row): array
|
||||
{
|
||||
$data = $this->listItem($row);
|
||||
$data['metadata'] = $this->decodeJson($row->metadata ?? null, []);
|
||||
$data['content'] = $row->content;
|
||||
$data['raw'] = $row->raw;
|
||||
$data['chunks'] = $this->decodeJson($row->chunks ?? null, []);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function normalizeTags(mixed $value): array
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$items = $value;
|
||||
} else {
|
||||
$text = trim((string) $value);
|
||||
if ($text === '') {
|
||||
return [];
|
||||
}
|
||||
$items = preg_split('/[\r\n,]+/', $text) ?: [];
|
||||
}
|
||||
|
||||
$tags = [];
|
||||
foreach ($items as $item) {
|
||||
$tag = trim((string) $item);
|
||||
if ($tag !== '') {
|
||||
$tags[] = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values(array_unique($tags));
|
||||
}
|
||||
|
||||
private function normalizeMetadata(mixed $value): array
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$text = trim((string) $value);
|
||||
if ($text === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$decoded = json_decode($text, true);
|
||||
if (!is_array($decoded)) {
|
||||
throw new InvalidArgumentException('metadata must be a JSON object or array.');
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
private function nullableText(mixed $value): ?string
|
||||
{
|
||||
$text = trim((string) $value);
|
||||
return $text === '' ? null : $text;
|
||||
}
|
||||
|
||||
private function decodeJson(mixed $value, mixed $fallback): mixed
|
||||
{
|
||||
if ($value === null) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$decoded = json_decode((string) $value, true);
|
||||
return $decoded === null && json_last_error() !== JSON_ERROR_NONE ? $fallback : $decoded;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user