Files
2026-09-15 10:35:56 +08:00

175 lines
5.3 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun\Homepage\Block;
use Esun\Catalog\Model\Product\CardPriceResolver;
use Magento\Catalog\Block\Product\AbstractProduct;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\Product\Visibility;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Customer\Model\Context as CustomerContext;
use Magento\Framework\App\Http\Context as HttpContext;
use Magento\Framework\DataObject\IdentityInterface;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Framework\UrlInterface;
use Magento\Store\Model\ScopeInterface;
class Accessories extends AbstractProduct implements IdentityInterface
{
private const XML_PATH = 'esun_homepage/accessories/';
private const BACKGROUND_MEDIA_PATH = 'esun/homepage/accessories/';
/**
* @var Product[]|null
*/
private ?array $products = null;
public function __construct(
Context $context,
private readonly CollectionFactory $productCollectionFactory,
private readonly Visibility $productVisibility,
private readonly PriceCurrencyInterface $priceCurrency,
private readonly HttpContext $httpContext,
private readonly CardPriceResolver $cardPriceResolver,
array $data = []
) {
parent::__construct($context, $data);
}
/**
* @return Product[]
*/
public function getProducts(): array
{
if ($this->products !== null) {
return $this->products;
}
$skus = $this->getConfiguredSkus();
if (!$skus) {
return $this->products = [];
}
$collection = $this->productCollectionFactory->create();
$collection->setStoreId((int) $this->_storeManager->getStore()->getId());
$this->_addProductAttributesAndPrices($collection);
$collection->addStoreFilter();
$collection->addAttributeToFilter('sku', ['in' => $skus]);
$collection->addAttributeToFilter(
'visibility',
['in' => $this->productVisibility->getVisibleInSiteIds()]
);
$collection->addAttributeToFilter(
'status',
Product\Attribute\Source\Status::STATUS_ENABLED
);
$productsBySku = [];
foreach ($collection as $product) {
$productsBySku[strtolower((string) $product->getSku())] = $product;
}
$this->products = [];
foreach ($skus as $sku) {
$key = strtolower($sku);
if (isset($productsBySku[$key])) {
$this->products[] = $productsBySku[$key];
}
}
return $this->products;
}
public function getBackgroundImageUrl(): string
{
$image = ltrim(trim((string) $this->getConfig('background_image')), '/');
if ($image === '') {
return '';
}
return $this->_storeManager->getStore()->getBaseUrl(UrlInterface::URL_TYPE_MEDIA)
. self::BACKGROUND_MEDIA_PATH
. $image;
}
public function getExploreAllUrl(): string
{
return trim((string) $this->getConfig('explore_all_url'));
}
public function getFormattedFinalPrice(Product $product): string
{
return $this->formatPrice($this->getFinalPriceValue($product));
}
public function getFormattedRegularPrice(Product $product): string
{
return $this->formatPrice($this->getRegularPriceValue($product));
}
public function hasRegularPrice(Product $product): bool
{
return $this->getRegularPriceValue($product) > $this->getFinalPriceValue($product);
}
public function getCacheKeyInfo(): array
{
return [
'ESUN_HOMEPAGE_ACCESSORIES',
(int) $this->_storeManager->getStore()->getId(),
(int) $this->httpContext->getValue(CustomerContext::CONTEXT_GROUP),
sha1(implode('|', $this->getConfiguredSkus())),
sha1($this->getBackgroundImageUrl()),
sha1($this->getExploreAllUrl()),
];
}
public function getIdentities(): array
{
$identities = [];
foreach ($this->getProducts() as $product) {
$identities = array_merge($identities, $product->getIdentities());
}
return array_values(array_unique($identities));
}
private function getConfiguredSkus(): array
{
$value = (string) $this->getConfig('skus');
$skus = preg_split('/[\s,;]+/', $value, -1, PREG_SPLIT_NO_EMPTY) ?: [];
return array_values(array_unique(array_map('trim', $skus)));
}
private function getConfig(string $field): mixed
{
return $this->_scopeConfig->getValue(
self::XML_PATH . $field,
ScopeInterface::SCOPE_STORE
);
}
private function getFinalPriceValue(Product $product): float
{
return $this->cardPriceResolver->getFinalPrice($product);
}
private function getRegularPriceValue(Product $product): float
{
return $this->cardPriceResolver->getRegularPrice($product);
}
private function formatPrice(float $price): string
{
return $this->priceCurrency->format(
$price,
false,
PriceCurrencyInterface::DEFAULT_PRECISION,
$this->_storeManager->getStore()
);
}
}