user(); $storeFilter = $request->query('store'); $search = trim((string) $request->query('q', '')); $storeIds = WooStore::query()->where('user_id', $user->id)->pluck('id'); $categories = WooCategory::query() ->whereIn('woo_store_id', $storeIds) ->when($storeFilter, fn ($q) => $q->where('woo_store_id', $storeFilter)) ->when($search !== '', fn ($q) => $q->where('name', 'like', '%'.$search.'%')) ->with('store') ->orderBy('name') ->paginate(30) ->withQueryString(); $stores = WooStore::query()->where('user_id', $user->id)->orderBy('site_name')->get(); return view('woo.categories.index', compact('categories', 'stores', 'storeFilter', 'search')); } public function create(Request $request): View { $stores = $this->activeStores($request); $storeId = (int) $request->query('store', $stores->first()?->id ?? 0); $parentCategories = $storeId > 0 ? WooCategory::query()->where('woo_store_id', $storeId)->orderBy('name')->get() : collect(); return view('woo.categories.form', [ 'category' => new WooCategory, 'stores' => $stores, 'parentCategories' => $parentCategories, 'selectedStoreId' => $storeId, ]); } public function store(Request $request): RedirectResponse { $validated = $this->validateCategory($request); $store = $this->authorizedStore($request, (int) $validated['woo_store_id']); $this->write->createCategory($store, $validated); return redirect()->route('woo.categories.index', ['store' => $store->id]) ->with('success', 'Category saved.'); } public function edit(Request $request, WooCategory $category): View { $category->load('store'); abort_if($category->store?->user_id !== $request->user()->id, 403); $stores = $this->activeStores($request); $parentCategories = $category->store ? $category->store->categories() ->where('external_id', '!=', $category->external_id) ->orderBy('name') ->get() : collect(); return view('woo.categories.form', [ 'category' => $category, 'stores' => $stores, 'parentCategories' => $parentCategories, 'selectedStoreId' => $category->woo_store_id, ]); } public function update(Request $request, WooCategory $category): RedirectResponse { $category->load('store'); abort_if($category->store?->user_id !== $request->user()->id, 403); $validated = $this->validateCategory($request); $this->write->updateCategory($category, $validated); return redirect()->route('woo.categories.index', ['store' => $category->woo_store_id]) ->with('success', 'Category updated.'); } public function destroy(Request $request, WooCategory $category): RedirectResponse { $category->load('store'); abort_if($category->store?->user_id !== $request->user()->id, 403); $storeId = $category->woo_store_id; $this->write->deleteCategory($category); return redirect()->route('woo.categories.index', ['store' => $storeId]) ->with('success', 'Category removed.'); } public function sync(Request $request): RedirectResponse { $validated = $request->validate([ 'store' => ['required', 'integer'], ]); $store = $this->authorizedStore($request, (int) $validated['store']); $count = $this->sync->syncCategories($store); return back()->with('success', sprintf( 'Synced %d categories from %s.', $count, $store->site_name ?? $store->site_url, )); } /** @return array */ private function validateCategory(Request $request): array { return $request->validate([ 'woo_store_id' => ['required', 'integer'], 'name' => ['required', 'string', 'max:255'], 'slug' => ['nullable', 'string', 'max:255'], 'description' => ['nullable', 'string', 'max:10000'], 'parent_external_id' => ['nullable', 'integer', 'min:0'], ]); } private function authorizedStore(Request $request, int $storeId): WooStore { return WooStore::query() ->where('user_id', $request->user()->id) ->whereKey($storeId) ->where('status', WooStore::STATUS_ACTIVE) ->firstOrFail(); } /** @return \Illuminate\Support\Collection */ private function activeStores(Request $request) { return WooStore::query() ->where('user_id', $request->user()->id) ->where('status', WooStore::STATUS_ACTIVE) ->orderBy('site_name') ->get(); } }