with('quickReplies') ->when($search !== '', function ($query) use ($numericSearch, $search): void { $like = "%{$search}%"; $query->where(function ($query) use ($numericSearch, $like): void { $query ->where('title', 'ilike', $like) ->orWhere('content', 'ilike', $like) ->orWhere('source_url', 'ilike', $like) ->orWhere('source_article_id', 'ilike', $like); if (ctype_digit($numericSearch)) { $query->orWhere('id', (int) $numericSearch); } }); }) ->latest() ->paginate($perPage); } public function create(string $title, string $content, ?string $note = null, array $allowedActions = []): Article { return Article::query()->create([ 'title' => trim($title), 'content' => trim($content), 'note' => $note !== null && trim($note) !== '' ? trim($note) : null, 'allowed_actions' => $this->sanitizeAllowedActions($allowedActions), 'status' => 'published', 'is_ai_draft' => false, ]); } public function deleteById(int $articleId): bool { return (bool) Article::query()->whereKey($articleId)->delete(); } public function findById(int $articleId): ?Article { return Article::query()->find($articleId); } public function updateContent(int $articleId, string $title, string $content): bool { $article = Article::query()->find($articleId); if ($article === null) { return false; } $article->title = trim($title); $article->content = trim($content); $article->save(); return true; } public function updateMetadata(int $articleId, ?string $note, array $allowedActions, array $quickReplyIds = []): bool { $article = Article::query()->find($articleId); if ($article === null) { return false; } DB::transaction(function () use ($article, $note, $allowedActions, $quickReplyIds): void { $article->note = $note !== null && trim($note) !== '' ? trim($note) : null; $article->allowed_actions = $this->sanitizeAllowedActions($allowedActions); $article->save(); $article->quickReplies()->sync($this->existingQuickReplyIds($quickReplyIds)); }); return true; } public function approveDraft(int $articleId): bool { $article = Article::query()->find($articleId); if ($article === null) { return false; } $article->status = 'published'; $article->is_ai_draft = false; $article->save(); return true; } private function sanitizeAllowedActions(array $allowedActions): array { return array_values(array_intersect(array_unique($allowedActions), ['domain_inf'])); } private function existingQuickReplyIds(array $quickReplyIds): array { $ids = array_values(array_unique(array_filter( array_map(static fn ($id) => (int) $id, $quickReplyIds), static fn ($id) => $id > 0 ))); if ($ids === []) { return []; } return QuickReply::query() ->whereIn('id', $ids) ->pluck('id') ->map(static fn ($id) => (int) $id) ->all(); } }