<?php
declare(strict_types=1);
namespace Slivki\Services\Comment;
use Slivki\Dao\Order\OfferOrderPurchaseCountDaoInterface;
use Slivki\Dto\Comment\CommentDto;
use Slivki\Factory\Comment\CommentDtoFactory;
use Slivki\Message\Query\Comment\GetOffersCommentsQuery;
use Slivki\Paginator\Comment\CommentPaginatorInterface;
use Slivki\Response\Comment\GetCommentsResponse;
use function array_map;
use function array_values;
final class CommentService
{
private CommentPaginatorInterface $commentPaginator;
private CommentDtoFactory $commentDtoFactory;
private OfferOrderPurchaseCountDaoInterface $offerOrderPurchaseCountDao;
private ?array $childCommentsRuntimeCache = null;
public function __construct(
CommentPaginatorInterface $commentPaginator,
CommentDtoFactory $commentDtoFactory,
OfferOrderPurchaseCountDaoInterface $offerOrderPurchaseCountDao
) {
$this->commentPaginator = $commentPaginator;
$this->commentDtoFactory = $commentDtoFactory;
$this->offerOrderPurchaseCountDao = $offerOrderPurchaseCountDao;
}
public function getOffersCommentsTree(GetOffersCommentsQuery $query): GetCommentsResponse
{
$paginator = $this->commentPaginator->getOffersComments($query);
$parentComments = array_map(
[$this->commentDtoFactory, 'create'],
(array) $paginator->getItems(),
);
$childCommentsQuery = new GetOffersCommentsQuery(
1,
PHP_INT_MAX,
false,
$query->getOfferId(),
$query->getUserId()
);
$this->childCommentsRuntimeCache = (array) $this->commentPaginator->getOffersComments($childCommentsQuery)->getItems();
return new GetCommentsResponse(
$this->buildTree($parentComments),
$paginator->getTotalItemCount(),
);
}
/**
* @param array<CommentDto> $comments
* @return array<CommentDto>
*/
private function buildTree(array $comments): array
{
$branch = [];
foreach ($comments as $comment) {
$children = array_map(
[$this->commentDtoFactory, 'create'],
array_filter(
$this->childCommentsRuntimeCache,
static fn (array $childComment) => $childComment['parent_id'] === $comment->getId(),
),
);
$comment->setChildren($this->buildTree(array_values($children)));
$branch[] = $comment;
}
return $branch;
}
public function isUserAllowToRateInOffer(int $userId, int $offerId): bool
{
return $this->offerOrderPurchaseCountDao->findPurchaseCountByUserAndOffer($userId, $offerId) > 0;
}
public function calcFakeCommentRating(float $rating): float
{
if ($rating == 0) {
return 0.0;
}
return min(5, round(2.5 + ($rating - 1) * 0.625, 2));
}
}