Files
kupshop/bundles/KupShop/CommentsBundle/Util/CommentsUtil.php
2025-08-02 16:30:27 +02:00

243 lines
7.6 KiB
PHP

<?php
namespace KupShop\CommentsBundle\Util;
use KupShop\CommentsBundle\Comment;
use KupShop\CommentsBundle\Email\AdminNotificationCommentEmail;
use KupShop\CommentsBundle\Email\CommentEmail;
use KupShop\CommentsBundle\Email\UserNotificationCommentEmail;
use KupShop\CommentsBundle\Exception\CommentException;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\KupShopBundle\Util\Entity\EntityUtil;
use KupShop\KupShopBundle\Util\Mail\EmailLocator;
class CommentsUtil
{
private $emailLocator;
private $languageContext;
private $userContext;
private $contextManager;
private $entityUtil;
public function __construct(
EmailLocator $emailLocator,
LanguageContext $languageContext,
UserContext $userContext,
ContextManager $contextManager,
EntityUtil $entityUtil,
) {
$this->emailLocator = $emailLocator;
$this->languageContext = $languageContext;
$this->userContext = $userContext;
$this->contextManager = $contextManager;
$this->entityUtil = $entityUtil;
}
public function addComment(
int $objectId,
string $type,
string $content,
?int $parentId = null,
?int $userId = null,
?string $languageId = null,
?int $adminId = null,
int $status = Comment::STATUS_UNCONFIRMED,
): Comment {
if (!$languageId) {
$languageId = $this->languageContext->getActiveId();
}
$solved = Comment::SOLVED_NO;
if (!$userId && !$adminId) {
if (!($userId = $this->userContext->getActiveId())) {
$admin = getAdminUser();
if (!($adminId = ($admin['id'] ?? false))) {
throw new CommentException('User is not logged in and \'$userId\' or \'$adminId\' is not specified!');
}
}
}
// set co confirmed and solved if comment added by admin
if ($adminId) {
$status = Comment::STATUS_CONFIRMED;
$solved = Comment::SOLVED_YES;
}
if (empty($content)) {
throw new CommentException('Empty \'$content\' given. Content cannot be empty!');
}
$comment = sqlGetConnection()->transactional(
function () use (
$parentId,
$languageId,
$type,
$objectId,
$userId,
$adminId,
$content,
$status,
$solved
) {
sqlQueryBuilder()
->insert('comments')
->directValues(
[
'id_parent' => $parentId,
'id_language' => $languageId,
$this->getObjectField($type) => $objectId,
'id_user' => $userId,
'id_admin' => $adminId,
'content' => $content,
'status' => $status,
'solved' => $solved,
]
)->execute();
$id = sqlInsertId();
if ($userId) {
$userGroup = match ($type) {
'product' => 'Komentáře k produktům',
'article' => 'Komentáře k článkům',
default => 'Komentáře k '.$type,
};
sqlQuery("INSERT INTO users_groups (name) VALUES ('{$userGroup}') ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)");
$groupId = sqlInsertID();
sqlQuery("INSERT IGNORE INTO users_groups_relations (id_group, id_user) VALUES ('{$groupId}', '{$userId}')");
}
return $this->getCommentById((int) $id);
}
);
$this->sendEmail($comment);
return $comment;
}
public function getCommentById(int $id): ?Comment
{
// nactu i parenty a children pridaneho komentare - abych byl schopny si getnout parenta, childa...
$comments = sqlQuery('WITH RECURSIVE ancestors as (
SELECT * FROM comments WHERE id = :id
UNION
SELECT c.* FROM comments c, ancestors a WHERE (a.id_parent = c.id) OR (a.id = c.id_parent)
) SELECT * FROM ancestors;', ['id' => $id])->fetchAll();
if (!$comments) {
return null;
}
// vytvorim strukturu
$comments = $this->buildCommentsTree(
$this->loadComments($comments)
);
$comment = reset($comments);
if (!$comment) {
return null;
}
// najdu ten jeden konkretni komentar
while ($comment->getId() !== $id && $children = $comment->getChildren()) {
$comment = reset($children);
}
return $comment;
}
public function loadComments(array $comments): array
{
$result = [];
foreach ($comments as $item) {
$result[] = $this->entityUtil->createEntity($item, Comment::class);
}
return $result;
}
public function buildCommentsTree(array $comments, ?Comment $parent = null): array
{
$tree = [];
$parentId = null;
if ($parent) {
$parentId = $parent->getId();
}
/** @var Comment $item */
foreach ($comments as $index => $item) {
if ((!$parentId && !$item->getIdParent()) || $item->getIdParent() === $parentId) {
unset($comments[$index]);
$children = $this->buildCommentsTree($comments, $item);
if (count($children) > 0) {
$item->setChildren($children);
}
if ($parent) {
$item->setParent($parent);
}
$tree[] = $item;
}
}
return $tree;
}
public function getObjectField(string $type): string
{
return 'id_'.$type;
}
protected function sendEmail(Comment $comment): void
{
$this->contextManager->activateContexts([LanguageContext::class => $comment->getIdLanguage()], function () use ($comment) {
if (!$comment->getIdAdmin()) {
$dbcfg = \Settings::getDefault();
$shopkeeperEmail = $dbcfg->comments['shopkeeper_email'] ?? false;
if (!empty($shopkeeperEmail)) {
$this->doSendEmail($comment, AdminNotificationCommentEmail::getType(), $shopkeeperEmail);
}
}
if ($comment->getIdParent()) {
$emails = $this->getUsersEmails($comment);
if (!empty($emails)) {
$this->doSendEmail($comment, UserNotificationCommentEmail::getType(), implode(',', $emails));
}
}
});
}
private function doSendEmail(Comment $comment, string $type, string $to): bool
{
/** @var CommentEmail $email */
$email = $this->emailLocator->getEmailService($type);
$email->setComment($comment);
$message = $email->getEmail();
$message['to'] = $to;
return $email->sendEmail($message);
}
private function getUsersEmails(Comment $comment): array
{
$return = [];
do {
if ($user = $comment->getUser()) {
$return[] = $user->email;
}
} while ($comment = $comment->getParent());
return array_unique($return);
}
}