Files
esun3d/app/code/Esun/Review/Model/Order/ReviewEligibilityService.php
2026-09-15 10:35:56 +08:00

58 lines
2.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun\Review\Model\Order;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Exception\LocalizedException;
use Magento\Sales\Api\OrderItemRepositoryInterface;
class ReviewEligibilityService
{
public function __construct(private readonly OrderItemRepositoryInterface $items, private readonly ResourceConnection $resource)
{
}
public function getItem(int $orderItemId, int $customerId): \Magento\Sales\Api\Data\OrderItemInterface
{
return $this->loadEligibleItem($orderItemId, $customerId, true);
}
public function getItemForLink(int $orderItemId, int $customerId): \Magento\Sales\Api\Data\OrderItemInterface
{
return $this->loadEligibleItem($orderItemId, $customerId, false);
}
private function loadEligibleItem(int $orderItemId, int $customerId, bool $checkExisting): \Magento\Sales\Api\Data\OrderItemInterface
{
$item = $this->items->get($orderItemId);
$order = $item->getOrder();
if ((int)$order->getCustomerId() !== $customerId || (int)$item->getParentItemId() > 0) {
throw new LocalizedException(__('This order item cannot be reviewed.'));
}
if ((float)$item->getQtyOrdered() - (float)$item->getQtyCanceled() <= 0 || !$this->isOrderEligible($order)) {
throw new LocalizedException(__('This order is not yet eligible for review.'));
}
if ($checkExisting && $this->hasReviewed($customerId, (int)$item->getProductId())) {
throw new LocalizedException(__('You have already reviewed this product.'));
}
return $item;
}
public function canReview(\Magento\Sales\Model\Order\Item $item, int $customerId): bool
{
try {
$this->getItem((int)$item->getId(), $customerId);
return true;
} catch (\Throwable) {
return false;
}
}
public function hasReviewed(int $customerId, int $productId): bool
{
$connection = $this->resource->getConnection();
return (bool)$connection->fetchOne($connection->select()->from(['r' => $this->resource->getTableName('review')], ['review_id'])->join(['d' => $this->resource->getTableName('review_detail')], 'd.review_id = r.review_id', [])->where('r.entity_pk_value = ?', $productId)->where('d.customer_id = ?', $customerId)->limit(1));
}
private function isOrderEligible(\Magento\Sales\Model\Order $order): bool
{
return (string)$order->getStatus() === 'received';
}
}