first commit
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Book;
|
||||
use App\Models\Category;
|
||||
use App\Models\Summary;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class IngestController extends Controller
|
||||
{
|
||||
/**
|
||||
* Upsert books with summaries and categories.
|
||||
* Accepts either a single book object or an array of books under `books`.
|
||||
*/
|
||||
public function upsertBooks(Request $request)
|
||||
{
|
||||
$payload = $request->all();
|
||||
|
||||
// Normalize to array of items
|
||||
$items = [];
|
||||
if (isset($payload['books']) && is_array($payload['books'])) {
|
||||
$items = $payload['books'];
|
||||
} elseif ($this->isAssocArray($payload)) {
|
||||
$items = [$payload];
|
||||
} elseif (is_array($payload)) {
|
||||
$items = $payload;
|
||||
}
|
||||
|
||||
if (empty($items)) {
|
||||
return response()->json([
|
||||
'message' => 'No books provided.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($items as $index => $item) {
|
||||
// Basic validation (minimal to satisfy requirement)
|
||||
$title = $item['title'] ?? null;
|
||||
$author = $item['author'] ?? null;
|
||||
if (!$title || !$author) {
|
||||
$results[] = [
|
||||
'index' => $index,
|
||||
'status' => 'error',
|
||||
'message' => 'title and author are required.',
|
||||
];
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = DB::transaction(function () use ($item) {
|
||||
// Handle category upsert
|
||||
$categoryData = $item['category'] ?? null;
|
||||
$category = null;
|
||||
if ($categoryData) {
|
||||
$catSlug = $categoryData['slug'] ?? null;
|
||||
$catName = $categoryData['name'] ?? null;
|
||||
if (!$catSlug && $catName) {
|
||||
$catSlug = Str::slug($catName);
|
||||
}
|
||||
|
||||
if ($catSlug) {
|
||||
$category = Category::where('slug', $catSlug)->first();
|
||||
}
|
||||
if (!$category && $catName) {
|
||||
// Try by name
|
||||
$category = Category::where('name', $catName)->first();
|
||||
}
|
||||
|
||||
if ($category) {
|
||||
// Update existing
|
||||
$category->fill([
|
||||
'name' => $catName ?? $category->name,
|
||||
'slug' => $catSlug ?? ($catName ? Str::slug($catName) : $category->slug),
|
||||
'description' => $categoryData['description'] ?? $category->description,
|
||||
])->save();
|
||||
$categoryStatus = 'updated';
|
||||
} else {
|
||||
// Create new if enough data
|
||||
$category = Category::create([
|
||||
'name' => $catName ?? 'Uncategorized',
|
||||
'slug' => $catSlug ?? ($catName ? Str::slug($catName) : Str::slug('Uncategorized')),
|
||||
'description' => $categoryData['description'] ?? null,
|
||||
]);
|
||||
$categoryStatus = 'created';
|
||||
}
|
||||
}
|
||||
|
||||
// Handle book upsert
|
||||
$bookSlug = $item['slug'] ?? null;
|
||||
if (!$bookSlug && !empty($item['title'])) {
|
||||
$bookSlug = Str::slug($item['title']);
|
||||
}
|
||||
|
||||
$bookQuery = Book::query();
|
||||
if ($bookSlug) {
|
||||
$bookQuery->where('slug', $bookSlug);
|
||||
} else {
|
||||
// Fallback: match by title+author
|
||||
$bookQuery->where('title', $item['title'])->where('author', $item['author']);
|
||||
}
|
||||
|
||||
$book = $bookQuery->first();
|
||||
$bookData = [
|
||||
'title' => $item['title'] ?? ($book->title ?? null),
|
||||
'slug' => $bookSlug ?? ($book->slug ?? null),
|
||||
'author' => $item['author'] ?? ($book->author ?? null),
|
||||
'description' => $item['description'] ?? ($book->description ?? null),
|
||||
'publication_date' => $item['publication_date'] ?? ($book->publication_date ?? null),
|
||||
'cover_image' => $item['cover_image'] ?? ($book->cover_image ?? null),
|
||||
];
|
||||
if ($category) {
|
||||
$bookData['category_id'] = $category->id;
|
||||
} elseif (!empty($item['category_id'])) {
|
||||
$bookData['category_id'] = $item['category_id'];
|
||||
}
|
||||
|
||||
if ($book) {
|
||||
$book->fill($bookData)->save();
|
||||
$bookStatus = 'updated';
|
||||
} else {
|
||||
$book = Book::create($bookData);
|
||||
$bookStatus = 'created';
|
||||
}
|
||||
|
||||
// Handle summary upsert
|
||||
$summaryData = $item['summary'] ?? null;
|
||||
$summaryResult = null;
|
||||
if ($summaryData && is_array($summaryData)) {
|
||||
$summary = Summary::where('book_id', $book->id)->first();
|
||||
$sumData = [
|
||||
'content' => $summaryData['content'] ?? ($summary->content ?? null),
|
||||
'key_insights' => $summaryData['key_insights'] ?? ($summary->key_insights ?? null),
|
||||
'book_id' => $book->id,
|
||||
];
|
||||
if ($summary) {
|
||||
$summary->fill($sumData)->save();
|
||||
$summaryResult = ['status' => 'updated', 'id' => $summary->id];
|
||||
} else {
|
||||
$summary = Summary::create($sumData);
|
||||
$summaryResult = ['status' => 'created', 'id' => $summary->id];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'book' => [
|
||||
'status' => $bookStatus,
|
||||
'id' => $book->id,
|
||||
'slug' => $book->slug,
|
||||
],
|
||||
'category' => $category ? [
|
||||
'status' => $categoryStatus,
|
||||
'id' => $category->id,
|
||||
'slug' => $category->slug,
|
||||
] : null,
|
||||
'summary' => $summaryResult,
|
||||
];
|
||||
});
|
||||
|
||||
$results[] = $result;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'results' => $results,
|
||||
]);
|
||||
}
|
||||
|
||||
private function isAssocArray($arr): bool
|
||||
{
|
||||
if (!is_array($arr)) return false;
|
||||
return array_keys($arr) !== range(0, count($arr) - 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user