Files
3dealer/app/Catalog/ProductCard.php
T

48 lines
2.3 KiB
PHP

<?php
namespace App\Catalog;
/**
* Presentation shaping — how a storefront product listing/grid card is built:
* name, price, image, href. Deliberately not in boboko-core: `href` depends on
* this storefront's own routes, and another app on the same core package could
* want an entirely different card shape. One place, so HomeController /
* CategoryController / ProductController / SearchController don't each
* hand-write the same name/price/image/href mapping.
*
* One source: a localized index array — ProductService::list()/getById()/
* random(), and now ProductSearchService::search() too, all return the exact
* same document shape (see ProductListingResult), so this is the only mapping
* every storefront listing page needs.
*/
final class ProductCard
{
/**
* @param array<string, mixed> $product one item from ProductService's localized array shape
* @return array{name: ?string, price: ?string, image: ?string, href: string, variantId: ?int, hasCustomFields: bool, soldOut: bool}
*/
public static function fromIndexed(array $product): array
{
return [
'name' => $product['name'],
'price' => $product['price'],
'image' => $product['media'][0]['url'] ?? null,
'href' => route('product.show', ['id' => $product['id']]),
// The card's quick "Add to cart" always adds this variant, same
// default Modules\Core\Catalog\Services\ProductService::
// variantSummaries() and product/show.blade.php both use — no
// picker at listing-grid scope, unlike the product page's own
// color swatches.
'variantId' => $product['variants'][0]['id'] ?? null,
// A product with custom fields (photo upload, engraving text…)
// can't be quick-added from a card — the card links to the
// product page instead, even when every field is optional.
'hasCustomFields' => ! empty($product['custom_fields']),
// Index-time stock (see boboko-core's ProductIndexer `in_stock`),
// so only as fresh as the last reindex. A document missing the
// field is treated as in stock rather than hiding its cart button.
'soldOut' => ! ($product['in_stock'] ?? true),
];
}
}