|
|
@@ -0,0 +1,183 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace Longyi\FrontMenu\Http\Controllers;
|
|
|
+
|
|
|
+use Illuminate\Http\Request;
|
|
|
+use Illuminate\Routing\Controller;
|
|
|
+use Longyi\FrontMenu\Models\FrontMenuItem;
|
|
|
+use Longyi\FrontMenu\Repositories\FrontMenuItemRepository;
|
|
|
+
|
|
|
+class FrontMenuController extends Controller
|
|
|
+{
|
|
|
+ protected $repository;
|
|
|
+
|
|
|
+ public function __construct(FrontMenuItemRepository $repository)
|
|
|
+ {
|
|
|
+ $this->repository = $repository;
|
|
|
+ $this->_config = request('_config');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Display the menu tree list.
|
|
|
+ */
|
|
|
+ public function index()
|
|
|
+ {
|
|
|
+ $menuItems = $this->repository->getMenuTree();
|
|
|
+
|
|
|
+ return view($this->_config['view'], compact('menuItems'));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Show the create form.
|
|
|
+ */
|
|
|
+ public function create()
|
|
|
+ {
|
|
|
+ $menuItems = $this->repository->getMenuTree();
|
|
|
+
|
|
|
+ return view($this->_config['view'], compact('menuItems'));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Store a new menu item.
|
|
|
+ */
|
|
|
+ public function store(Request $request)
|
|
|
+ {
|
|
|
+ $request->validate([
|
|
|
+ 'name' => 'required|string|max:255',
|
|
|
+ 'slug' => 'required|string|max:255|unique:front_menu_items,slug',
|
|
|
+ 'url' => 'nullable|string|max:2048',
|
|
|
+ 'image' => 'nullable|string|max:2048',
|
|
|
+ 'banner' => 'nullable|string|max:2048',
|
|
|
+ 'wap_image' => 'nullable|string|max:2048',
|
|
|
+ 'wap_banner' => 'nullable|string|max:2048',
|
|
|
+ 'parent_id' => 'nullable|exists:front_menu_items,id',
|
|
|
+ 'sort_order' => 'nullable|integer',
|
|
|
+ 'status' => 'nullable|boolean',
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $this->repository->create($this->prepareData($request));
|
|
|
+
|
|
|
+ session()->flash('success', __('frontmenu::app.admin.menu.created'));
|
|
|
+
|
|
|
+ return redirect()->route($this->_config['redirect']);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Show the edit form.
|
|
|
+ */
|
|
|
+ public function edit($id)
|
|
|
+ {
|
|
|
+ $menuItem = $this->repository->findOrFail($id);
|
|
|
+ $menuItems = $this->repository->getMenuTree();
|
|
|
+
|
|
|
+ return view($this->_config['view'], compact('menuItem', 'menuItems'));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Update an existing menu item.
|
|
|
+ */
|
|
|
+ public function update(Request $request, $id)
|
|
|
+ {
|
|
|
+ $request->validate([
|
|
|
+ 'name' => 'required|string|max:255',
|
|
|
+ 'slug' => 'required|string|max:255|unique:front_menu_items,slug,' . $id,
|
|
|
+ 'url' => 'nullable|string|max:2048',
|
|
|
+ 'image' => 'nullable|string|max:2048',
|
|
|
+ 'banner' => 'nullable|string|max:2048',
|
|
|
+ 'wap_image' => 'nullable|string|max:2048',
|
|
|
+ 'wap_banner' => 'nullable|string|max:2048',
|
|
|
+ 'parent_id' => 'nullable|exists:front_menu_items,id',
|
|
|
+ 'sort_order' => 'nullable|integer',
|
|
|
+ 'status' => 'nullable|boolean',
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // Prevent a menu item from becoming its own parent or a descendant's child.
|
|
|
+ if ($request->filled('parent_id') && $request->input('parent_id') == $id) {
|
|
|
+ session()->flash('error', __('frontmenu::app.admin.menu.self-parent'));
|
|
|
+
|
|
|
+ return redirect()->back()->withInput();
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->repository->update($this->prepareData($request), $id);
|
|
|
+
|
|
|
+ session()->flash('success', __('frontmenu::app.admin.menu.updated'));
|
|
|
+
|
|
|
+ return redirect()->route($this->_config['redirect']);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Delete a menu item (and its children via cascade).
|
|
|
+ */
|
|
|
+ public function destroy($id)
|
|
|
+ {
|
|
|
+ $menuItem = $this->repository->findOrFail($id);
|
|
|
+
|
|
|
+ $menuItem->delete();
|
|
|
+
|
|
|
+ session()->flash('success', __('frontmenu::app.admin.menu.deleted'));
|
|
|
+
|
|
|
+ return redirect()->route($this->_config['redirect']);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Reorder menu items via drag & drop.
|
|
|
+ */
|
|
|
+ public function reorder(Request $request)
|
|
|
+ {
|
|
|
+ $request->validate([
|
|
|
+ 'items' => 'required|array',
|
|
|
+ 'items.*.id' => 'required|integer|exists:front_menu_items,id',
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $items = $request->input('items', []);
|
|
|
+
|
|
|
+ // Group by parent so each level gets its own sort order sequence.
|
|
|
+ $grouped = [];
|
|
|
+
|
|
|
+ foreach ($items as $item) {
|
|
|
+ $parentId = $item['parent_id'] ?? null;
|
|
|
+ $grouped[$parentId ?? 'root'][] = $item['id'];
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach ($grouped as $parentKey => $ids) {
|
|
|
+ $parentId = $parentKey === 'root' ? null : $parentKey;
|
|
|
+
|
|
|
+ foreach ($ids as $index => $id) {
|
|
|
+ FrontMenuItem::query()->where('id', $id)->update([
|
|
|
+ 'parent_id' => $parentId,
|
|
|
+ 'sort_order' => $index,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return response()->json([
|
|
|
+ 'success' => true,
|
|
|
+ 'message' => __('frontmenu::app.admin.menu.reordered'),
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Normalize request data before persisting.
|
|
|
+ */
|
|
|
+ protected function prepareData(Request $request): array
|
|
|
+ {
|
|
|
+ $data = $request->only([
|
|
|
+ 'name',
|
|
|
+ 'slug',
|
|
|
+ 'url',
|
|
|
+ 'image',
|
|
|
+ 'banner',
|
|
|
+ 'wap_image',
|
|
|
+ 'wap_banner',
|
|
|
+ 'parent_id',
|
|
|
+ 'sort_order',
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $data['parent_id'] = $request->filled('parent_id') ? (int) $request->input('parent_id') : null;
|
|
|
+ $data['sort_order'] = $request->input('sort_order', 0);
|
|
|
+ $data['status'] = $request->has('status') ? (bool) $request->input('status') : true;
|
|
|
+ $data['created_by'] = auth()->guard('admin')->user()->id ?? null;
|
|
|
+
|
|
|
+ return $data;
|
|
|
+ }
|
|
|
+}
|