This commit is contained in:
167
app/Http/Controllers/Admin/HomeSlideController.php
Normal file
167
app/Http/Controllers/Admin/HomeSlideController.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\HomeSlide;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class HomeSlideController extends Controller
|
||||
{
|
||||
private const ZONES = ['left', 'right'];
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
$slides = HomeSlide::query()
|
||||
->orderByRaw("CASE WHEN zone = 'left' THEN 0 ELSE 1 END")
|
||||
->ordered()
|
||||
->get()
|
||||
->groupBy('zone');
|
||||
|
||||
return view('admin.home-slides.index', [
|
||||
'slides' => $slides,
|
||||
'zoneLabels' => $this->zoneLabels(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(Request $request): View
|
||||
{
|
||||
$zone = in_array($request->query('zone'), self::ZONES, true) ? $request->query('zone') : 'left';
|
||||
|
||||
return view('admin.home-slides.create', [
|
||||
'slide' => new HomeSlide([
|
||||
'zone' => $zone,
|
||||
'show_title' => true,
|
||||
'show_subtitle' => true,
|
||||
'show_button' => true,
|
||||
'sort_order' => 100,
|
||||
'is_active' => true,
|
||||
]),
|
||||
'zoneLabels' => $this->zoneLabels(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$data = $this->validateSlide($request, true);
|
||||
$data['image_path'] = $this->storeImage($request);
|
||||
|
||||
HomeSlide::create($data);
|
||||
|
||||
return redirect()->route('admin.home-slides.index')->with('status', 'Слайд добавлен.');
|
||||
}
|
||||
|
||||
public function edit(HomeSlide $homeSlide): View
|
||||
{
|
||||
return view('admin.home-slides.edit', [
|
||||
'slide' => $homeSlide,
|
||||
'zoneLabels' => $this->zoneLabels(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, HomeSlide $homeSlide): RedirectResponse
|
||||
{
|
||||
$data = $this->validateSlide($request);
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
$newPath = $this->storeImage($request);
|
||||
$oldPath = $homeSlide->image_path;
|
||||
|
||||
$data['image_path'] = $newPath;
|
||||
$homeSlide->update($data);
|
||||
|
||||
if ($oldPath && $oldPath !== $newPath) {
|
||||
$this->deleteImage($oldPath);
|
||||
}
|
||||
|
||||
return redirect()->route('admin.home-slides.index')->with('status', 'Слайд обновлен.');
|
||||
}
|
||||
|
||||
$homeSlide->update($data);
|
||||
|
||||
return redirect()->route('admin.home-slides.index')->with('status', 'Слайд обновлен.');
|
||||
}
|
||||
|
||||
public function destroy(HomeSlide $homeSlide): RedirectResponse
|
||||
{
|
||||
$this->deleteImage($homeSlide->image_path);
|
||||
$homeSlide->delete();
|
||||
|
||||
return redirect()->route('admin.home-slides.index')->with('status', 'Слайд удален.');
|
||||
}
|
||||
|
||||
private function validateSlide(Request $request, bool $requireImage = false): array
|
||||
{
|
||||
return $request->validate([
|
||||
'zone' => ['required', Rule::in(self::ZONES)],
|
||||
'title' => ['nullable', 'string', 'max:160'],
|
||||
'show_title' => ['nullable', 'boolean'],
|
||||
'subtitle' => ['nullable', 'string', 'max:1500'],
|
||||
'show_subtitle' => ['nullable', 'boolean'],
|
||||
'button_text' => ['nullable', 'string', 'max:60'],
|
||||
'button_url' => ['nullable', 'string', 'max:255', 'regex:/^(\\/|https?:\\/\\/).+/i'],
|
||||
'show_button' => ['nullable', 'boolean'],
|
||||
'sort_order' => ['required', 'integer', 'min:0', 'max:9999'],
|
||||
'is_active' => ['nullable', 'boolean'],
|
||||
'image' => [
|
||||
$requireImage ? 'required' : 'nullable',
|
||||
'image',
|
||||
'mimes:jpg,jpeg,png,webp',
|
||||
'max:5120',
|
||||
],
|
||||
]) + [
|
||||
'show_title' => $request->boolean('show_title'),
|
||||
'show_subtitle' => $request->boolean('show_subtitle'),
|
||||
'show_button' => $request->boolean('show_button'),
|
||||
'is_active' => $request->boolean('is_active'),
|
||||
];
|
||||
}
|
||||
|
||||
private function storeImage(Request $request): string
|
||||
{
|
||||
$file = $request->file('image');
|
||||
if (!$file) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$extension = strtolower((string) $file->getClientOriginalExtension());
|
||||
if ($extension === '') {
|
||||
$extension = 'jpg';
|
||||
}
|
||||
|
||||
$name = now()->format('YmdHis') . '-' . Str::uuid() . '.' . $extension;
|
||||
return (string) $file->storeAs('home-slides', $name, 'public');
|
||||
}
|
||||
|
||||
private function deleteImage(?string $path): void
|
||||
{
|
||||
if (!$path) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (str_starts_with($path, 'uploads/')) {
|
||||
$filePath = public_path(ltrim($path, '/'));
|
||||
if (File::exists($filePath)) {
|
||||
File::delete($filePath);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Storage::disk('public')->delete($path);
|
||||
}
|
||||
|
||||
private function zoneLabels(): array
|
||||
{
|
||||
return [
|
||||
'left' => 'Большой слайдер (2/3)',
|
||||
'right' => 'Малый слайдер (1/3)',
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user