91 lines
2.9 KiB
PHP
91 lines
2.9 KiB
PHP
<?php
|
|
|
|
namespace Modules\Menus\Http\Controllers;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Validation\ValidationException;
|
|
use Illuminate\View\View;
|
|
use JsonException;
|
|
use Modules\Menus\Models\Menu;
|
|
|
|
final class MenuController extends Controller
|
|
{
|
|
public function index(): View
|
|
{
|
|
return view('menus::admin.index', ['records' => Menu::query()->orderBy('location')->paginate(30)]);
|
|
}
|
|
|
|
public function create(): View
|
|
{
|
|
return view('menus::admin.form', ['locations' => $this->locations()]);
|
|
}
|
|
|
|
public function store(Request $request): RedirectResponse
|
|
{
|
|
Menu::create($this->validated($request));
|
|
|
|
return redirect()->route('administration.menus.index')->with('status', 'Menu created. Every header or footer using this location has been updated.');
|
|
}
|
|
|
|
public function edit(Menu $menu): View
|
|
{
|
|
return view('menus::admin.form', ['record' => $menu, 'locations' => $this->locations()]);
|
|
}
|
|
|
|
public function update(Request $request, Menu $menu): RedirectResponse
|
|
{
|
|
$menu->update($this->validated($request));
|
|
|
|
return redirect()->route('administration.menus.index')->with('status', 'Menu updated everywhere it is used.');
|
|
}
|
|
|
|
public function destroy(Menu $menu): RedirectResponse
|
|
{
|
|
$menu->delete();
|
|
|
|
return back()->with('status', 'Menu deleted. Components using its location will use their safe fallback.');
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
private function validated(Request $request): array
|
|
{
|
|
$data = $request->validate([
|
|
'name' => ['required', 'string', 'max:255'],
|
|
'location' => ['required', 'string', 'max:100', 'regex:/^[a-z0-9_-]+$/'],
|
|
'items_json' => ['nullable', 'string'],
|
|
'enabled' => ['nullable', 'boolean'],
|
|
]);
|
|
|
|
try {
|
|
$items = json_decode($data['items_json'] ?: '[]', true, 512, JSON_THROW_ON_ERROR);
|
|
} catch (JsonException) {
|
|
throw ValidationException::withMessages(['items_json' => 'The menu items could not be saved. Please reload the editor and try again.']);
|
|
}
|
|
|
|
if (! is_array($items)) {
|
|
throw ValidationException::withMessages(['items_json' => 'Menu items must be a list.']);
|
|
}
|
|
|
|
return [
|
|
'name' => $data['name'],
|
|
'location' => $data['location'],
|
|
'items' => array_values($items),
|
|
'enabled' => $request->boolean('enabled'),
|
|
];
|
|
}
|
|
|
|
/** @return array<string, string> */
|
|
private function locations(): array
|
|
{
|
|
return [
|
|
'primary' => 'Primary navigation',
|
|
'footer' => 'Footer — Explore',
|
|
'footer_account' => 'Footer — Account',
|
|
'footer_legal' => 'Footer — Legal',
|
|
'mobile' => 'Mobile navigation override',
|
|
];
|
|
}
|
|
}
|