Files

247 lines
8.1 KiB
PHP
Raw Permalink Normal View History

2025-09-13 17:39:17 +03:00
<?php
namespace App\Http\Controllers;
use App\Models\Book;
use App\Models\Category;
2025-09-20 16:47:41 +03:00
use App\Models\Author;
2025-09-13 17:39:17 +03:00
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class BookController extends Controller
{
/**
* Display a listing of the resource.
*/
2025-09-20 16:47:41 +03:00
public function index(Request $request)
2025-09-13 17:39:17 +03:00
{
2025-09-20 16:47:41 +03:00
$query = Book::query()->with(['category', 'authors', 'summary'])->orderByDesc('created_at');
// Text search
if ($search = trim((string) $request->get('q'))) {
$query->where(function ($q) use ($search) {
$q->where('title', 'like', "%{$search}%")
->orWhere('description', 'like', "%{$search}%");
});
}
// Category filter (by id or slug)
if ($cat = $request->get('category')) {
if (is_numeric($cat)) {
$query->where('category_id', (int) $cat);
} else {
$query->whereHas('category', function ($q) use ($cat) {
$q->where('slug', $cat)->orWhere('name', 'like', "%{$cat}%");
});
}
}
// Author filter (by id, slug, or name)
if ($author = $request->get('author')) {
$query->whereHas('authors', function ($q) use ($author) {
if (is_numeric($author)) {
$q->where('authors.id', (int) $author);
} else {
$q->where('authors.slug', $author)
->orWhere('authors.name', 'like', "%{$author}%");
}
});
}
// Publication date range
if ($from = $request->get('date_from')) {
$query->whereDate('publication_date', '>=', $from);
}
if ($to = $request->get('date_to')) {
$query->whereDate('publication_date', '<=', $to);
}
$books = $query->paginate(12)->withQueryString();
// For filter dropdowns
$categories = Category::orderBy('name')->get();
$authors = Author::orderBy('name')->get();
return view('books.index', [
'books' => $books,
'categories' => $categories,
'authors' => $authors,
'filters' => [
'q' => $request->get('q'),
'category' => $request->get('category'),
'author' => $request->get('author'),
'date_from' => $request->get('date_from'),
'date_to' => $request->get('date_to'),
],
]);
2025-09-13 17:39:17 +03:00
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$categories = Category::all();
return view('books.create', compact('categories'));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$request->validate([
'title' => 'required|string|max:255',
'author' => 'required|string|max:255',
'description' => 'nullable|string',
'publication_date' => 'nullable|date',
'cover_image' => 'nullable|string|max:255',
'category_id' => 'required|exists:categories,id',
]);
2025-09-20 16:47:41 +03:00
// Generate a unique slug for the title
$baseSlug = Str::slug($request->title);
$slug = $baseSlug;
$i = 2;
while (Book::where('slug', $slug)->exists()) {
$slug = $baseSlug . '-' . $i;
$i++;
}
$book = Book::create([
2025-09-13 17:39:17 +03:00
'title' => $request->title,
2025-09-20 16:47:41 +03:00
'slug' => $slug,
2025-09-13 17:39:17 +03:00
'author' => $request->author,
'description' => $request->description,
'publication_date' => $request->publication_date,
'cover_image' => $request->cover_image,
'category_id' => $request->category_id,
]);
2025-09-20 16:47:41 +03:00
// Normalize author: link to authors table via pivot
if (!empty($request->author)) {
$name = trim($request->author);
$slug = Str::slug($name);
$author = Author::where('slug', $slug)->first();
if (!$author) {
$author = Author::where('name', $name)->first();
}
if ($author) {
$author->fill(['name' => $name, 'slug' => $author->slug ?: $slug])->save();
} else {
$author = Author::create(['name' => $name, 'slug' => $slug]);
}
$book->authors()->sync([$author->id]);
}
2025-09-13 17:39:17 +03:00
return redirect()->route('books.index')
->with('success', 'Book created successfully.');
}
/**
* Display the specified resource.
*/
public function show(Book $book)
{
2025-09-20 16:47:41 +03:00
$book->load(['summary', 'category', 'authors', 'reviews.user']);
$avgRating = (float) round($book->reviews()->avg('rating') ?? 0, 1);
$reviewsCount = (int) $book->reviews()->count();
$userReview = auth()->check() ? $book->reviews()->where('user_id', auth()->id())->first() : null;
return view('books.show', [
'book' => $book,
'avgRating' => $avgRating,
'reviewsCount' => $reviewsCount,
'userReview' => $userReview,
]);
2025-09-13 17:39:17 +03:00
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Book $book)
{
$categories = Category::all();
return view('books.edit', compact('book', 'categories'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, Book $book)
{
$request->validate([
'title' => 'required|string|max:255',
'author' => 'required|string|max:255',
'description' => 'nullable|string',
'publication_date' => 'nullable|date',
'cover_image' => 'nullable|string|max:255',
'category_id' => 'required|exists:categories,id',
]);
2025-09-20 16:47:41 +03:00
// If title changed, compute a unique slug (preserving current slug if still matching)
$baseSlug = Str::slug($request->title);
$slug = $baseSlug;
if ($book->slug !== $baseSlug) {
$i = 2;
while (Book::where('slug', $slug)->where('id', '!=', $book->id)->exists()) {
$slug = $baseSlug . '-' . $i;
$i++;
}
} else {
// Ensure no collision with other records even if same base
if (Book::where('slug', $baseSlug)->where('id', '!=', $book->id)->exists()) {
$i = 2;
$slug = $baseSlug . '-' . $i;
while (Book::where('slug', $slug)->where('id', '!=', $book->id)->exists()) {
$i++;
$slug = $baseSlug . '-' . $i;
}
}
}
2025-09-13 17:39:17 +03:00
$book->update([
'title' => $request->title,
2025-09-20 16:47:41 +03:00
'slug' => $slug,
2025-09-13 17:39:17 +03:00
'author' => $request->author,
'description' => $request->description,
'publication_date' => $request->publication_date,
'cover_image' => $request->cover_image,
'category_id' => $request->category_id,
]);
2025-09-20 16:47:41 +03:00
// Normalize author: sync pivot to the single provided author
if (!empty($request->author)) {
$name = trim($request->author);
$slug = Str::slug($name);
$author = Author::where('slug', $slug)->first();
if (!$author) {
$author = Author::where('name', $name)->first();
}
if ($author) {
$author->fill(['name' => $name, 'slug' => $author->slug ?: $slug])->save();
} else {
$author = Author::create(['name' => $name, 'slug' => $slug]);
}
$book->authors()->sync([$author->id]);
} else {
// If author field is cleared, detach all author links
$book->authors()->detach();
}
2025-09-13 17:39:17 +03:00
return redirect()->route('books.index')
->with('success', 'Book updated successfully.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Book $book)
{
$book->delete();
return redirect()->route('books.index')
->with('success', 'Book deleted successfully.');
}
}