$input */ public function createProduct(WooStore $store, array $input): WooProduct { $payload = $this->productPayload($input); $response = $this->client->post($store, 'products', $payload); if (is_array($response) && isset($response['id'])) { return $this->productIngest->ingest($store, $response); } return $this->createLocalProduct($store, $payload); } /** @param array $input */ public function updateProduct(WooProduct $product, array $input): WooProduct { $product->loadMissing('store'); $store = $product->store; abort_if(! $store, 404); $payload = $this->productPayload($input); $response = $this->client->put($store, 'products/'.$product->external_id, $payload); if (is_array($response) && isset($response['id'])) { return $this->productIngest->ingest($store, $response); } $product->update($this->localProductAttributes($payload)); return $product->fresh(); } /** @param array $input */ public function createCategory(WooStore $store, array $input): WooCategory { $payload = $this->categoryPayload($input); $response = $this->client->post($store, 'categories', $payload); if (is_array($response) && isset($response['id'])) { return $this->categoryIngest->ingest($store, $response); } return $this->createLocalCategory($store, $payload); } /** @param array $input */ public function updateCategory(WooCategory $category, array $input): WooCategory { $category->loadMissing('store'); $store = $category->store; abort_if(! $store, 404); $payload = $this->categoryPayload($input); $response = $this->client->put($store, 'categories/'.$category->external_id, $payload); if (is_array($response) && isset($response['id'])) { return $this->categoryIngest->ingest($store, $response); } $category->update($this->localCategoryAttributes($payload)); return $category->fresh(); } public function deleteCategory(WooCategory $category): bool { $category->loadMissing('store'); $store = $category->store; abort_if(! $store, 404); if ($this->client->delete($store, 'categories/'.$category->external_id)) { $category->delete(); return true; } $category->delete(); return true; } /** @param array $input */ private function productPayload(array $input): array { $categories = collect($input['category_external_ids'] ?? []) ->map(fn ($id) => ['id' => (int) $id]) ->filter(fn (array $row) => $row['id'] > 0) ->values() ->all(); return array_filter([ 'name' => (string) ($input['name'] ?? ''), 'sku' => $input['sku'] ?? null, 'status' => (string) ($input['status'] ?? WooProduct::STATUS_DRAFT), 'regular_price' => $this->majorPrice($input['regular_price'] ?? null), 'sale_price' => $this->majorPrice($input['sale_price'] ?? null), 'manage_stock' => (bool) ($input['manage_stock'] ?? false), 'stock_quantity' => isset($input['stock_quantity']) ? (int) $input['stock_quantity'] : null, 'short_description' => WooHtml::sanitize($input['short_description'] ?? null), 'description' => WooHtml::sanitize($input['description'] ?? null), 'categories' => $categories, 'images' => $input['images'] ?? null, ], fn ($value) => $value !== null && $value !== ''); } /** @param array $input */ private function categoryPayload(array $input): array { $parent = (int) ($input['parent_external_id'] ?? 0); return array_filter([ 'name' => (string) ($input['name'] ?? ''), 'slug' => $input['slug'] ?? null, 'description' => WooHtml::sanitize($input['description'] ?? null), 'parent' => $parent > 0 ? $parent : 0, ], fn ($value) => $value !== null && $value !== ''); } /** @param array $payload */ private function createLocalProduct(WooStore $store, array $payload): WooProduct { $externalId = (int) (WooProduct::query()->where('woo_store_id', $store->id)->max('external_id') ?? 0) + 1; return WooProduct::query()->create(array_merge( $this->localProductAttributes($payload), [ 'woo_store_id' => $store->id, 'external_id' => $externalId, 'slug' => \Illuminate\Support\Str::slug((string) ($payload['name'] ?? 'product')).'-'.$externalId, ], )); } /** @param array $payload */ private function createLocalCategory(WooStore $store, array $payload): WooCategory { $externalId = (int) (WooCategory::query()->where('woo_store_id', $store->id)->max('external_id') ?? 0) + 1; $parent = (int) ($payload['parent'] ?? 0); return WooCategory::query()->create(array_merge( $this->localCategoryAttributes($payload), [ 'woo_store_id' => $store->id, 'external_id' => $externalId, 'parent_external_id' => $parent > 0 ? $parent : null, 'slug' => (string) ($payload['slug'] ?? \Illuminate\Support\Str::slug((string) ($payload['name'] ?? 'category')).'-'.$externalId), ], )); } /** @param array $payload */ private function localProductAttributes(array $payload): array { $categoryIds = collect($payload['categories'] ?? []) ->map(fn (array $row) => (int) ($row['id'] ?? 0)) ->filter(fn (int $id) => $id > 0) ->values() ->all(); return [ 'name' => (string) ($payload['name'] ?? 'Product'), 'sku' => $payload['sku'] ?? null, 'status' => (string) ($payload['status'] ?? WooProduct::STATUS_DRAFT), 'regular_price_minor' => $this->minorPrice($payload['regular_price'] ?? null), 'sale_price_minor' => $this->minorPrice($payload['sale_price'] ?? null), 'manage_stock' => (bool) ($payload['manage_stock'] ?? false), 'stock_quantity' => isset($payload['stock_quantity']) ? (int) $payload['stock_quantity'] : null, 'short_description' => $payload['short_description'] ?? null, 'description' => $payload['description'] ?? null, 'category_external_ids' => $categoryIds, 'images' => $payload['images'] ?? null, ]; } /** @param array $payload */ private function localCategoryAttributes(array $payload): array { $parent = (int) ($payload['parent'] ?? 0); return [ 'name' => (string) ($payload['name'] ?? 'Category'), 'slug' => (string) ($payload['slug'] ?? \Illuminate\Support\Str::slug((string) ($payload['name'] ?? 'category'))), 'description' => $payload['description'] ?? null, 'parent_external_id' => $parent > 0 ? $parent : null, ]; } private function majorPrice(mixed $value): ?string { if ($value === null || $value === '') { return null; } return number_format(((float) $value), 2, '.', ''); } private function minorPrice(mixed $value): ?int { if ($value === null || $value === '') { return null; } return (int) round(((float) $value) * 100); } }