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

49 lines
1.8 KiB
PHP

<?php
namespace App\Catalog;
use Lunar\Models\Product;
/**
* 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.
*
* Two sources, because the storefront reads products both ways: a hydrated
* Eloquent model (full-text search via ProductSearchService), or a localized
* index array (ProductService::list()/getById()/random()). Model callers must
* eager-load `variants.prices` and `media`.
*/
final class ProductCard
{
/**
* @return array{name: ?string, price: ?string, image: ?string, href: string}
*/
public static function fromModel(Product $product): array
{
return [
'name' => $product->translateAttribute('name'), //@todo check this
'price' => $product->variants->first()?->prices->first()?->price->decimal, //@todo check this
'image' => $product->media->first()?->getUrl(),
'href' => route('product.show', ['id' => $product->id]),
];
}
/**
* @param array<string, mixed> $product one item from ProductService's localized array shape
* @return array{name: ?string, price: ?string, image: ?string, href: string}
*/
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']]),
];
}
}