Deploy Ladill Woo Manager / deploy (push) Successful in 55s
Sync catalog via plugin webhooks and REST proxy, with list/create/edit UI and updated logo from monolith assets. Co-authored-by: Cursor <cursoragent@cursor.com>
162 lines
5.4 KiB
PHP
162 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Woo;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\WooCategory;
|
|
use App\Models\WooStore;
|
|
use App\Services\Woo\CatalogSyncService;
|
|
use App\Services\Woo\CatalogWriteService;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\View\View;
|
|
|
|
class CategoryController extends Controller
|
|
{
|
|
public function __construct(
|
|
private CatalogWriteService $write,
|
|
private CatalogSyncService $sync,
|
|
) {}
|
|
|
|
public function index(Request $request): View
|
|
{
|
|
$user = $request->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<string, mixed> */
|
|
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<int, WooStore> */
|
|
private function activeStores(Request $request)
|
|
{
|
|
return WooStore::query()
|
|
->where('user_id', $request->user()->id)
|
|
->where('status', WooStore::STATUS_ACTIVE)
|
|
->orderBy('site_name')
|
|
->get();
|
|
}
|
|
}
|