$payload */ public function ingest(WooStore $store, array $payload): WooProduct { $externalId = (int) ($payload['id'] ?? 0); if ($externalId === 0) { throw new \InvalidArgumentException('WooCommerce product id missing.'); } $regular = $this->priceMinor($payload['regular_price'] ?? null); $sale = $this->priceMinor($payload['sale_price'] ?? null); $images = collect((array) ($payload['images'] ?? [])) ->map(fn (array $image, int $index) => [ 'id' => (int) ($image['id'] ?? 0), 'src' => (string) ($image['src'] ?? ''), 'alt' => (string) ($image['alt'] ?? ''), 'position' => (int) ($image['position'] ?? $index), ]) ->filter(fn (array $image) => $image['src'] !== '' || $image['id'] > 0) ->sortBy('position') ->values() ->all(); $categoryIds = collect((array) ($payload['categories'] ?? [])) ->map(fn (array $category) => (int) ($category['id'] ?? 0)) ->filter(fn (int $id) => $id > 0) ->values() ->all(); return WooProduct::query()->updateOrCreate( [ 'woo_store_id' => $store->id, 'external_id' => $externalId, ], [ 'name' => (string) ($payload['name'] ?? 'Product'), 'slug' => (string) ($payload['slug'] ?? 'product-'.$externalId), 'sku' => $this->nullableString($payload['sku'] ?? null), 'status' => (string) ($payload['status'] ?? WooProduct::STATUS_DRAFT), 'type' => (string) ($payload['type'] ?? 'simple'), 'regular_price_minor' => $regular, 'sale_price_minor' => $sale, 'stock_quantity' => isset($payload['stock_quantity']) ? (int) $payload['stock_quantity'] : null, 'manage_stock' => (bool) ($payload['manage_stock'] ?? false), 'category_external_ids' => $categoryIds, 'images' => $images, 'short_description' => WooHtml::sanitize($payload['short_description'] ?? null), 'description' => WooHtml::sanitize($payload['description'] ?? null), 'wc_updated_at' => $this->updatedAt($payload), 'metadata' => [ 'permalink' => $payload['permalink'] ?? null, 'featured' => (bool) ($payload['featured'] ?? false), ], ], ); } public function delete(WooStore $store, int $externalId): void { WooProduct::query() ->where('woo_store_id', $store->id) ->where('external_id', $externalId) ->delete(); } private function priceMinor(mixed $value): ?int { if ($value === null || $value === '') { return null; } return (int) round(((float) $value) * 100); } /** @param array $payload */ private function updatedAt(array $payload): ?Carbon { $raw = $payload['date_modified_gmt'] ?? $payload['date_modified'] ?? null; return is_string($raw) && $raw !== '' ? Carbon::parse($raw) : null; } private function nullableString(mixed $value): ?string { $text = trim((string) $value); return $text === '' ? null : $text; } }