vendor/pimcore/pimcore/models/Notification/Service/NotificationService.php line 224

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * Pimcore
  5. *
  6. * This source file is available under two different licenses:
  7. * - GNU General Public License version 3 (GPLv3)
  8. * - Pimcore Commercial License (PCL)
  9. * Full copyright and license information is available in
  10. * LICENSE.md which is distributed with this source code.
  11. *
  12. * @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  13. * @license http://www.pimcore.org/license GPLv3 and PCL
  14. */
  15. namespace Pimcore\Model\Notification\Service;
  16. use Doctrine\DBAL\Exception;
  17. use Pimcore\Model\Element\ElementInterface;
  18. use Pimcore\Model\Notification;
  19. use Pimcore\Model\Notification\Listing;
  20. use Pimcore\Model\User;
  21. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  22. /**
  23. * @internal
  24. */
  25. class NotificationService
  26. {
  27. /** @var UserService */
  28. private $userService;
  29. /**
  30. * NotificationService constructor.
  31. *
  32. * @param UserService $userService
  33. */
  34. public function __construct(UserService $userService)
  35. {
  36. $this->userService = $userService;
  37. }
  38. /**
  39. * @param int $userId
  40. * @param int $fromUser
  41. * @param string $title
  42. * @param string $message
  43. * @param ElementInterface|null $element
  44. *
  45. * @throws \UnexpectedValueException
  46. */
  47. public function sendToUser(
  48. int $userId,
  49. int $fromUser,
  50. string $title,
  51. string $message,
  52. ?ElementInterface $element = null
  53. ) {
  54. $this->beginTransaction();
  55. $sender = User::getById($fromUser);
  56. $recipient = User::getById($userId);
  57. if (!$recipient instanceof User) {
  58. throw new \UnexpectedValueException(sprintf('No user found with the ID %d', $userId));
  59. }
  60. $notification = new Notification();
  61. $notification->setRecipient($recipient);
  62. $notification->setSender($sender);
  63. $notification->setTitle($title);
  64. $notification->setMessage($message);
  65. $notification->setLinkedElement($element);
  66. $notification->save();
  67. $this->commit();
  68. }
  69. /**
  70. * @param int $groupId
  71. * @param int $fromUser
  72. * @param string $title
  73. * @param string $message
  74. * @param ElementInterface|null $element
  75. *
  76. * @throws \UnexpectedValueException
  77. */
  78. public function sendToGroup(
  79. int $groupId,
  80. int $fromUser,
  81. string $title,
  82. string $message,
  83. ?ElementInterface $element = null
  84. ) {
  85. $group = User\Role::getById($groupId);
  86. if (!$group instanceof User\Role) {
  87. throw new \UnexpectedValueException(sprintf('No group found with the ID %d', $groupId));
  88. }
  89. $listing = new User\Listing();
  90. $listing->setCondition(
  91. 'id != ?
  92. AND active = ?
  93. AND (
  94. roles = ?
  95. OR roles LIKE ?
  96. OR roles LIKE ?
  97. OR roles LIKE ?
  98. )',
  99. [
  100. $fromUser,
  101. 1,
  102. $groupId,
  103. '%,' . $groupId,
  104. $groupId . ',%',
  105. '%,' . $groupId . ',%',
  106. ]
  107. );
  108. $listing->setOrderKey('name');
  109. $listing->setOrder('ASC');
  110. $listing->load();
  111. $users = $listing->getUsers() ?? [];
  112. $users = $this->userService->filterUsersWithPermission($users);
  113. foreach ($users as $user) {
  114. $this->sendToUser($user->getId(), $fromUser, $title, $message, $element);
  115. }
  116. }
  117. /**
  118. * @param int $id
  119. *
  120. * @return Notification
  121. *
  122. * @throws \UnexpectedValueException
  123. */
  124. public function find(int $id): Notification
  125. {
  126. $notification = Notification::getById($id);
  127. if (!$notification instanceof Notification) {
  128. throw new \UnexpectedValueException("Notification with the ID {$id} doesn't exists");
  129. }
  130. return $notification;
  131. }
  132. /**
  133. * @param int $id
  134. * @param int|null $recipientId
  135. *
  136. * @return Notification
  137. *
  138. * @throws \UnexpectedValueException
  139. */
  140. public function findAndMarkAsRead(int $id, ?int $recipientId = null): Notification
  141. {
  142. $this->beginTransaction();
  143. $notification = $this->find($id);
  144. if ($notification->getRecipient()->getId() != $recipientId) {
  145. throw new AccessDeniedHttpException();
  146. }
  147. if ($recipientId && $recipientId == $notification->getRecipient()->getId()) {
  148. $notification->setRead(true);
  149. $notification->save();
  150. $this->commit();
  151. }
  152. return $notification;
  153. }
  154. /**
  155. * @param array $filter
  156. * @param array $options
  157. *
  158. * @return array
  159. */
  160. public function findAll(array $filter = [], array $options = []): array
  161. {
  162. $listing = new Listing();
  163. if (!empty($filter)) {
  164. $conditions = [];
  165. foreach ($filter as $key => $value) {
  166. $conditions[] = $key . ' = :' . $key;
  167. }
  168. $condition = implode(' AND ', $conditions);
  169. $listing->setCondition($condition, $filter);
  170. }
  171. $listing->setOrderKey('creationDate');
  172. $listing->setOrder('DESC');
  173. $options += ['offset' => 0, 'limit' => 0];
  174. $offset = (int) $options['offset'];
  175. $limit = (int) $options['limit'];
  176. $this->beginTransaction();
  177. $result = [
  178. 'total' => $listing->count(),
  179. 'data' => $listing->getItems($offset, $limit),
  180. ];
  181. $this->commit();
  182. return $result;
  183. }
  184. /**
  185. * @param int $user
  186. * @param int $lastUpdate
  187. *
  188. * @return array
  189. *
  190. * @throws Exception
  191. */
  192. public function findLastUnread(int $user, int $lastUpdate): array
  193. {
  194. $listing = new Listing();
  195. $listing->setCondition(
  196. 'recipient = ? AND `read` = 0 AND creationDate >= ?',
  197. [
  198. $user,
  199. date('Y-m-d H:i:s', $lastUpdate),
  200. ]
  201. );
  202. $listing->setOrderKey('creationDate');
  203. $listing->setOrder('DESC');
  204. $listing->setLimit(1);
  205. $this->beginTransaction();
  206. $result = [
  207. 'total' => $listing->count(),
  208. 'data' => $listing->getData(),
  209. ];
  210. $this->commit();
  211. return $result;
  212. }
  213. /**
  214. * @param Notification $notification
  215. *
  216. * @return array
  217. */
  218. public function format(Notification $notification): array
  219. {
  220. $data = [
  221. 'id' => $notification->getId(),
  222. 'type' => $notification->getType(),
  223. 'title' => $notification->getTitle(),
  224. 'message' => $notification->getMessage(),
  225. 'sender' => '',
  226. 'read' => (int) $notification->isRead(),
  227. 'date' => $notification->getCreationDate(),
  228. 'linkedElementType' => $notification->getLinkedElementType(),
  229. 'linkedElementId' => null,
  230. ];
  231. if ($notification->getLinkedElement()) {
  232. $data['linkedElementId'] = $notification->getLinkedElement()->getId();
  233. }
  234. $sender = $notification->getSender();
  235. if ($sender instanceof User\AbstractUser) {
  236. $from = trim(sprintf('%s %s', $sender->getFirstname(), $sender->getLastname()));
  237. if (strlen($from) === 0) {
  238. $from = $sender->getName();
  239. }
  240. $data['sender'] = $from;
  241. }
  242. return $data;
  243. }
  244. /**
  245. * @param int $user
  246. *
  247. * @return int
  248. */
  249. public function countAllUnread(int $user): int
  250. {
  251. $listing = new Listing();
  252. $listing->setCondition('recipient = ? AND `read` = 0', [$user]);
  253. return $listing->count();
  254. }
  255. /**
  256. * @param int $id
  257. * @param int|null $recipientId
  258. */
  259. public function delete(int $id, ?int $recipientId = null): void
  260. {
  261. $this->beginTransaction();
  262. $notification = $this->find($id);
  263. if ($recipientId && $recipientId == $notification->getRecipient()->getId()) {
  264. $notification->delete();
  265. }
  266. $this->commit();
  267. }
  268. /**
  269. * @param int $user
  270. */
  271. public function deleteAll(int $user): void
  272. {
  273. $listing = new Listing();
  274. $listing->setCondition('recipient = ?', [$user]);
  275. $this->beginTransaction();
  276. foreach ($listing->getData() as $notification) {
  277. $notification->delete();
  278. }
  279. $this->commit();
  280. }
  281. private function beginTransaction(): void
  282. {
  283. \Pimcore\Db::getConnection()->beginTransaction();
  284. }
  285. private function commit(): void
  286. {
  287. \Pimcore\Db::getConnection()->commit();
  288. }
  289. }