Merge pull request #5843 from christianbeeznest/scheduled-announcement01

Session: Allow scheduled announcements to session users
pull/5781/head^2
christianbeeznest 11 months ago committed by GitHub
commit 2f5b7970a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      public/main/inc/lib/ScheduledAnnouncement.php
  2. 17
      public/main/inc/lib/extra_field_value.lib.php
  3. 27
      public/main/session/scheduled_announcement.php
  4. 74
      src/CoreBundle/Command/SendScheduledAnnouncementsCommand.php
  5. 3
      src/CoreBundle/Entity/ScheduledAnnouncement.php
  6. 22
      src/CoreBundle/Repository/Node/UserRepository.php
  7. 31
      src/CoreBundle/Repository/ScheduledAnnouncementRepository.php
  8. 327
      src/CoreBundle/Service/ScheduledAnnouncementService.php
  9. 319
      src/CoreBundle/ServiceHelper/MessageHelper.php

@ -355,9 +355,9 @@ class ScheduledAnnouncement extends Model
if (!empty($sessionInfo) && !empty($courseInfo)) {
$progress = Tracking::get_avg_student_progress(
$user['user_id'],
$courseInfo['code'],
api_get_course_entity($courseInfo['real_id']),
[],
$sessionId
api_get_session_entity($sessionId)
);
}

@ -291,28 +291,22 @@ class ExtraFieldValue extends Model
}
break;
case ExtraField::FIELD_TYPE_FILE:
$cleanedName = api_replace_dangerous_char($value['name']);
$fileName = ExtraField::FIELD_TYPE_FILE."_{$params['item_id']}_$cleanedName";
if (isset($value['name']) && !empty($value['tmp_name']) && isset($value['error']) && 0 == $value['error']) {
$cleanedName = api_replace_dangerous_char($value['name']);
$fileName = ExtraField::FIELD_TYPE_FILE."_{$params['item_id']}_$cleanedName";
if (!empty($value['tmp_name']) && isset($value['error']) && 0 == $value['error']) {
$mimeType = mime_content_type($value['tmp_name']);
$file = new UploadedFile($value['tmp_name'], $fileName, $mimeType, null, true);
$asset = (new Asset())
->setCategory(Asset::EXTRA_FIELD)
->setTitle($fileName)
->setFile($file)
;
->setFile($file);
$em->persist($asset);
$em->flush();
$assetId = $asset->getId();
if ($assetId) {
/*$new_params = [
'item_id' => $params['item_id'],
'field_id' => $extraFieldInfo['id'],
'value' => $assetId,
'asset_id' => $assetId,
];*/
$field = Container::getExtraFieldRepository()->find($extraFieldInfo['id']);
$extraFieldValues = (new ExtraFieldValues())
->setItemId((int) $params['item_id'])
@ -323,7 +317,6 @@ class ExtraFieldValue extends Model
;
$em->persist($extraFieldValues);
$em->flush();
//$this->save($new_params);
}
}
break;

@ -89,6 +89,7 @@ switch ($action) {
break;
}
$values['sent'] = isset($values['sent']) ? (int) $values['sent'] : 0;
$res = $object->save($values);
if ($res) {
@ -129,7 +130,7 @@ switch ($action) {
if ($form->validate()) {
$values = $form->getSubmitValues();
$values['id'] = $id;
$values['sent'] = isset($values['sent']) ? 1 : '';
$values['sent'] = isset($values['sent']) ? (int)$values['sent'] : 0;
$values['date'] = api_get_utc_datetime($values['date']);
$res = $object->update($values);
@ -141,13 +142,15 @@ switch ($action) {
get_lang('Update successful'),
'confirmation'
));
header("Location: $url");
exit;
$content = $object->getGrid($sessionId);
} else {
$item = $object->get($id);
$item['date'] = api_get_local_time($item['date']);
$form->setDefaults($item);
$content = $form->returnForm();
}
$item = $object->get($id);
$item['date'] = api_get_local_time($item['date']);
$form->setDefaults($item);
$content = $form->returnForm();
break;
case 'delete':
$object->delete($id);
@ -171,27 +174,25 @@ $columnModel = [
[
'name' => 'subject',
'index' => 'subject',
'width' => '250',
'width' => '350',
'align' => 'left',
],
[
'name' => 'date',
'index' => 'date',
//'width' => '90',
//'align' => 'left',
'width' => '190',
'align' => 'left',
'sortable' => 'true',
],
[
'name' => 'sent',
'index' => 'sent',
//'width' => '90',
//'align' => 'left',
'sortable' => 'true',
],
[
'name' => 'actions',
'index' => 'actions',
'width' => '100',
'width' => '200',
'align' => 'left',
'formatter' => 'action_formatter',
'sortable' => 'false',

@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Command;
use Chamilo\CoreBundle\Framework\Container;
use Chamilo\CoreBundle\Repository\Node\AccessUrlRepository;
use Chamilo\CoreBundle\Service\ScheduledAnnouncementService;
use Database;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class SendScheduledAnnouncementsCommand extends Command
{
protected static $defaultName = 'app:send-scheduled-announcements';
public function __construct(
private readonly AccessUrlRepository $accessUrlRepository,
private readonly ScheduledAnnouncementService $scheduledAnnouncementService,
private readonly EntityManager $em
) {
parent::__construct();
}
protected function configure(): void
{
$this
->setDescription('Send scheduled announcements to all users.')
->addOption('debug', null, null, 'If set, debug messages will be shown.');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
Database::setManager($this->em);
$container = $this->getApplication()->getKernel()->getContainer();
Container::setContainer($container);
$io = new SymfonyStyle($input, $output);
$debug = (bool) $input->getOption('debug');
$urlList = $this->accessUrlRepository->findAll();
if (empty($urlList)) {
$io->warning('No access URLs found.');
return Command::SUCCESS;
}
foreach ($urlList as $url) {
$urlId = $url->getId();
$io->writeln("Portal: #".$urlId." - ".$url->getUrl());
try {
$messagesSent = $this->scheduledAnnouncementService->sendPendingMessages($urlId, $debug);
$io->writeln("Messages sent: $messagesSent");
if ($debug) {
$io->writeln("Debug: Processed portal with ID ".$urlId);
}
} catch (\Exception $e) {
$io->error('Error processing portal with ID ' . $urlId . ': ' . $e->getMessage());
return Command::FAILURE;
}
}
$io->success('All scheduled announcements have been sent.');
return Command::SUCCESS;
}
}

@ -6,6 +6,7 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\Entity;
use Chamilo\CoreBundle\Repository\ScheduledAnnouncementRepository;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
@ -13,7 +14,7 @@ use Doctrine\ORM\Mapping as ORM;
* ScheduledAnnouncement.
*/
#[ORM\Table(name: 'scheduled_announcements')]
#[ORM\Entity]
#[ORM\Entity(repositoryClass: ScheduledAnnouncementRepository::class)]
class ScheduledAnnouncement
{
#[ORM\Column(name: 'id', type: 'integer')]

@ -1033,4 +1033,26 @@ class UserRepository extends ResourceRepository implements PasswordUpgraderInter
return $url.$paramsToString;
}
/**
* Retrieves the list of DRH (HR) users related to a specific user and access URL.
*/
public function getDrhListFromUser(int $userId, int $accessUrlId): array
{
$qb = $this->createQueryBuilder('u');
$this->addAccessUrlQueryBuilder($accessUrlId, $qb);
$qb->select('u.id, u.username, u.firstname, u.lastname')
->innerJoin('u.friends', 'uru', Join::WITH, 'uru.friend = u.id')
->where('uru.user = :userId')
->andWhere('uru.relationType = :relationType')
->setParameter('userId', $userId)
->setParameter('relationType', UserRelUser::USER_RELATION_TYPE_RRHH);
$qb->orderBy('u.lastname', 'ASC')
->addOrderBy('u.firstname', 'ASC');
return $qb->getQuery()->getResult();
}
}

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Repository;
use Chamilo\CoreBundle\Entity\ScheduledAnnouncement;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class ScheduledAnnouncementRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, ScheduledAnnouncement::class);
}
/**
* Mark an announcement as sent.
*
* @param ScheduledAnnouncement $announcement
*/
public function markAsSent(ScheduledAnnouncement $announcement): void
{
$announcement->setSent(true);
$this->_em->persist($announcement);
$this->_em->flush();
}
}

@ -0,0 +1,327 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Service;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Repository\Node\AccessUrlRepository;
use Chamilo\CoreBundle\Repository\ScheduledAnnouncementRepository;
use Chamilo\CoreBundle\Repository\SessionRepository;
use Chamilo\CoreBundle\ServiceHelper\MessageHelper;
use Chamilo\CoreBundle\Settings\SettingsManager;
use Chamilo\CoreBundle\Entity\Course;
use Doctrine\ORM\EntityManager;
use ExtraField;
use ExtraFieldValue;
use Symfony\Contracts\Translation\TranslatorInterface;
use Tracking;
class ScheduledAnnouncementService
{
public function __construct(
private readonly ScheduledAnnouncementRepository $announcementRepository,
private readonly AccessUrlRepository $accessUrlRepository,
private readonly EntityManager $em,
private readonly SettingsManager $settingsManager,
private readonly SessionRepository $sessionRepository,
private readonly MessageHelper $messageHelper,
private readonly TranslatorInterface $translator
) {}
/**
* Sends pending announcements to users and coaches.
*/
public function sendPendingMessages(int $urlId, bool $debug = false): int
{
if (!$this->allowed()) {
if ($debug) {
error_log("Announcements not allowed.");
}
return 0;
}
$messagesSent = 0;
$now = new \DateTime();
if ($debug) {
error_log("Current time: " . $now->format('Y-m-d H:i:s'));
}
$announcements = $this->announcementRepository->findBy(['sent' => false]);
if ($debug) {
error_log(count($announcements) . " pending announcements found.");
}
$extraField = new ExtraField('user');
$extraFields = $extraField->get_all(['filter = ? AND visible_to_self = ?' => [1, 1]]);
foreach ($announcements as $announcement) {
if (!$announcement->isSent() && $announcement->getDate() < $now) {
if ($debug) {
error_log("Processing announcement ID: " . $announcement->getId());
}
$sessionId = $announcement->getSessionId();
$session = $this->sessionRepository->find($sessionId);
if (!$session) {
if ($debug) {
error_log("Session not found for session ID: $sessionId");
}
continue;
}
$accessUrl = $this->accessUrlRepository->find($urlId);
$sessionRelUsers = $this->sessionRepository->getUsersByAccessUrl($session, $accessUrl);
$generalCoaches = $session->getGeneralCoaches();
if (empty($sessionRelUsers) || $generalCoaches->count() === 0) {
if ($debug) {
error_log("No users or general coaches found for session ID: $sessionId");
}
continue;
}
$coachId = $generalCoaches->first()->getId();
if ($debug) {
error_log("Coach ID: $coachId");
}
$coachList = [];
$sendToCoaches = $this->shouldSendToCoaches($announcement->getId());
$courseList = $session->getCourses();
if ($debug) {
error_log("Number of courses in session: " . count($courseList));
foreach ($courseList as $sessionRelCourse) {
$course = $sessionRelCourse->getCourse();
error_log("Course ID: " . $course->getId() . ", Course Title: " . $course->getTitle());
}
}
if ($sendToCoaches) {
foreach ($courseList as $course) {
$coaches = $session->getGeneralCoaches();
$coachList = array_merge($coachList, $coaches->toArray());
}
$coachList = array_unique($coachList);
}
$announcement->setSent(true);
$this->em->persist($announcement);
$this->em->flush();
$attachments = '';
$subject = $announcement->getSubject();
foreach ($sessionRelUsers as $sessionRelUser) {
$user = $sessionRelUser->getUser();
if ($debug) {
error_log('User ::: ' . $user->getId());
}
if ($user->getId() !== $coachId) {
$courseInfo = $this->getCourseInfo($courseList);
$progress = $this->getUserProgress($user->getId(), $courseInfo, $session);
$message = $this->buildMessage(
$announcement,
$session,
$user,
$courseInfo,
$attachments,
$progress
);
if (!empty($extraFields)) {
$extraFieldValue = new ExtraFieldValue('user');
foreach ($extraFields as $extraField) {
$valueExtra = $extraFieldValue->get_values_by_handler_and_field_variable($user->getId(), $extraField['variable'], true);
$tags['(('.strtolower($extraField['variable']).'))'] = $valueExtra['value'] ?? '';
}
$message = str_replace(array_keys($tags), $tags, $message);
}
if ($debug) {
error_log("Sending email to user ID: " . $user->getId());
}
$this->sendEmail($user->getId(), $subject, $message, $coachId);
}
}
$coachMessage = $this->buildCoachMessage($announcement, $generalCoaches, $message);
foreach ($coachList as $courseCoach) {
if ($debug) {
error_log("Sending email to coach ID: " . $courseCoach->getId());
}
$this->sendEmail($courseCoach->getId(), $subject, $coachMessage, $coachId);
}
$messagesSent++;
if ($debug) {
error_log("Messages sent for announcement ID: " . $announcement->getId());
}
}
}
if ($debug) {
error_log("Total messages sent: $messagesSent");
}
return $messagesSent;
}
/**
* Checks if the announcement should be sent to coaches.
*/
private function shouldSendToCoaches(int $announcementId): bool
{
$extraFieldValue = new ExtraFieldValue('scheduled_announcement');
$sendToCoaches = $extraFieldValue->get_values_by_handler_and_field_variable($announcementId, 'send_to_coaches');
return !empty($sendToCoaches) && !empty($sendToCoaches['value']) && (int)$sendToCoaches['value'] === 1;
}
/**
* Verifies if sending scheduled announcements is allowed.
*/
private function allowed(): bool
{
return 'true' === $this->settingsManager->getSetting('announcement.allow_scheduled_announcements');
}
/**
* Builds the announcement message for the user.
*/
private function buildMessage($announcement, Session $session, User $user, $courseInfo, $attachments, $progress): string
{
$generalCoaches = $session->getGeneralCoaches();
$generalCoachName = [];
$generalCoachEmail = [];
foreach ($generalCoaches as $coach) {
$generalCoachName[] = $coach->getFullname();
$generalCoachEmail[] = $coach->getEmail();
}
$startTime = $this->getLocalTime($session->getAccessStartDate());
$endTime = $this->getLocalTime($session->getAccessEndDate());
$tags = [
'((session_name))' => $session->getTitle(),
'((session_start_date))' => $startTime,
'((general_coach))' => implode(' - ', $generalCoachName),
'((general_coach_email))' => implode(' - ', $generalCoachEmail),
'((session_end_date))' => $endTime,
'((user_complete_name))' => $user->getFirstname() . ' ' . $user->getLastname(),
'((user_firstname))' => $user->getFirstname(),
'((user_lastname))' => $user->getLastname(),
'((lp_progress))' => $progress,
];
$message = str_replace(array_keys($tags), $tags, $announcement->getMessage());
return $message . $attachments;
}
/**
* Builds the announcement message for the coach.
*/
private function buildCoachMessage($announcement, $generalCoaches, $message): string
{
$coachNames = [];
foreach ($generalCoaches as $coach) {
$coachNames[] = $coach->getFullname();
}
$coachMessageIntro = count($generalCoaches) > 1
? $this->translator->trans('You are receiving a copy because you are one of the course coaches')
: $this->translator->trans('You are receiving a copy because you are the course coach');
$coachMessage = $coachMessageIntro . ': ' . implode(', ', $coachNames);
return $coachMessage . '<br /><br />' . $message;
}
/**
* Sends an email with the announcement to a user or coach.
*/
private function sendEmail(int $userId, string $subject, string $message, int $coachId): void
{
$user = $this->em->getRepository(User::class)->find($userId);
$coach = $this->em->getRepository(User::class)->find($coachId);
if (!$user || !$coach) {
throw new \Exception("User or coach not found.");
}
$this->messageHelper->sendMessageSimple(
$userId,
$subject,
$message,
$coachId
);
}
/**
* Retrieves course information from a list of courses.
*/
private function getCourseInfo($courseList)
{
if (!empty($courseList) && current($courseList) instanceof Course) {
$courseId = current($courseList)->getId();
return $this->getCourseInfoById($courseId);
} else {
return [];
}
}
/**
* Retrieves course information by course ID.
*/
private function getCourseInfoById(int $courseId)
{
$course = $this->em->getRepository(Course::class)->find($courseId);
if ($course) {
return [
'real_id' => $course->getId(),
'title' => $course->getTitle(),
'code' => $course->getCode(),
'description' => $course->getDescription(),
'tutor_name' => $course->getTutorName(),
];
}
return [];
}
/**
* Gets the user's progress for a specific course and session.
*/
private function getUserProgress(int $userId, $courseInfo, Session $session): string
{
if (!empty($courseInfo) && $session) {
$progress = Tracking::get_avg_student_progress($userId, $courseInfo['real_id'], [], $session->getId());
return is_numeric($progress) ? $progress . '%' : '0%';
}
return '0%';
}
/**
* Formats a DateTime object to a string.
*/
private function getLocalTime(?\DateTime $datetime): string
{
return $datetime ? $datetime->format('Y-m-d H:i:s') : '';
}
}

@ -0,0 +1,319 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\ServiceHelper;
use Chamilo\CoreBundle\Entity\Message;
use Chamilo\CoreBundle\Entity\MessageAttachment;
use Chamilo\CoreBundle\Entity\MessageRelUser;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Entity\Usergroup;
use Chamilo\CoreBundle\Repository\MessageRepository;
use Chamilo\CoreBundle\Repository\Node\UserRepository;
use Chamilo\CoreBundle\Settings\SettingsManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
class MessageHelper
{
private $session;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly MessageRepository $messageRepository,
private readonly UserRepository $userRepository,
private readonly RequestStack $requestStack,
private readonly AccessUrlHelper $accessUrlHelper,
private readonly SettingsManager $settingsManager,
private readonly MailerInterface $mailer
) {
if (php_sapi_name() !== 'cli') {
$this->session = $this->requestStack->getSession();
}
}
/**
* Sends a simple message with optional attachments and notifications to HR users.
*/
public function sendMessageSimple(
int $receiverUserId,
string $subject,
string $message,
int $senderId = 0,
bool $sendCopyToDrhUsers = false,
bool $uploadFiles = true,
array $attachmentList = []
): ?int {
$files = $_FILES ? $_FILES : [];
if (false === $uploadFiles) {
$files = [];
}
if (!empty($attachmentList)) {
$files = $attachmentList;
}
$result = $this->sendMessage(
$receiverUserId,
$subject,
$message,
$files,
[],
0,
0,
0,
$senderId
);
if ($sendCopyToDrhUsers) {
$accessUrl = $this->accessUrlHelper->getCurrent();
if ($accessUrl !== null) {
$drhList = $this->userRepository->getDrhListFromUser($receiverUserId, $accessUrl->getId());
if (!empty($drhList)) {
$receiverInfo = $this->userRepository->find($receiverUserId);
foreach ($drhList as $drhUser) {
$drhMessage = sprintf(
'Copy of message sent to %s',
$receiverInfo->getFirstname() . ' ' . $receiverInfo->getLastname()
) . ' <br />' . $message;
$this->sendMessageSimple(
$drhUser->getId(),
$subject,
$drhMessage,
$senderId
);
}
}
}
}
return $result;
}
/**
* Sends a message with attachments, forwards, and additional settings.
*/
public function sendMessage(
int $receiverUserId,
string $subject,
string $content,
array $attachments = [],
array $fileCommentList = [],
int $groupId = 0,
int $parentId = 0,
int $editMessageId = 0,
int $senderId = 0,
int $forwardId = 0,
bool $checkCurrentAudioId = false,
bool $forceTitleWhenSendingEmail = false,
?int $msgType = null
): ?int {
$sender = $this->userRepository->find($senderId);
$receiver = $this->userRepository->find($receiverUserId);
if (!$sender || !$receiver || !$receiver->isActive()) {
return null;
}
$totalFileSize = 0;
$attachmentList = $this->processAttachments($attachments, $fileCommentList, $totalFileSize);
if ($totalFileSize > (int) $this->settingsManager->getSetting('message.message_max_upload_filesize')) {
throw new \Exception('Files size exceeds allowed limit.');
}
$parent = $this->messageRepository->find($parentId);
if ($editMessageId) {
$message = $this->messageRepository->find($editMessageId);
if ($message) {
$message->setTitle($subject);
$message->setContent($content);
}
} else {
$message = new Message();
$message->setSender($sender)
->addReceiverTo($receiver)
->setTitle($subject)
->setContent($content)
->setGroup($groupId ? $this->getGroupById($groupId) : null)
->setParent($parent);
if ($msgType !== null) {
$message->setMsgType($msgType);
}
}
$this->entityManager->persist($message);
$this->entityManager->flush();
if ($forwardId) {
$this->forwardAttachments($forwardId, $message);
}
if ($checkCurrentAudioId) {
$this->attachAudioMessage($message);
}
$this->saveAttachments($attachmentList, $message);
$this->addSenderAsReceiver($message, $sender);
if ($forceTitleWhenSendingEmail) {
$this->sendEmailNotification($receiver, $sender, $subject, $content, $attachmentList);
}
return $message->getId();
}
/**
* Processes attachments, calculates total file size, and returns the attachment list.
*/
private function processAttachments(array $attachments, array $fileCommentList, &$totalFileSize): array
{
$attachmentList = [];
foreach ($attachments as $index => $attachment) {
$comment = $fileCommentList[$index] ?? '';
$size = $attachment['size'] ?? 0;
if (is_array($size)) {
foreach ($size as $s) {
$totalFileSize += $s;
}
} else {
$totalFileSize += $size;
}
$attachmentList[] = [
'file' => $attachment,
'comment' => $comment,
];
}
return $attachmentList;
}
/**
* Forwards attachments from one message to another.
*/
private function forwardAttachments(int $forwardId, Message $message): void
{
$forwardMessage = $this->messageRepository->find($forwardId);
if ($forwardMessage) {
foreach ($forwardMessage->getAttachments() as $attachment) {
$message->addAttachment($attachment);
}
$this->entityManager->persist($message);
$this->entityManager->flush();
}
}
/**
* Attaches an audio message from the current session to the message.
*/
private function attachAudioMessage(Message $message): void
{
if ($this->session && $this->session->has('current_audio')) {
$audio = $this->session->get('current_audio');
if (!empty($audio['name'])) {
$attachment = new MessageAttachment();
$attachment->setFilename($audio['name'])
->setComment('audio_message')
->setMessage($message);
$message->addAttachment($attachment);
$this->entityManager->persist($attachment);
$this->entityManager->flush();
}
}
}
/**
* Saves the provided attachments and links them to the message.
*/
private function saveAttachments(array $attachments, Message $message): void
{
foreach ($attachments as $attachment) {
$file = $attachment['file'];
$comment = $attachment['comment'] ?? '';
if ($file instanceof UploadedFile && $file->getError() === UPLOAD_ERR_OK) {
$attachmentEntity = new MessageAttachment();
$attachmentEntity->setFilename($file->getClientOriginalName())
->setSize($file->getSize())
->setPath($file->getRealPath())
->setMessage($message)
->setComment($comment);
$message->addAttachment($attachmentEntity);
$this->entityManager->persist($attachmentEntity);
}
}
$this->entityManager->flush();
}
/**
* Adds the sender as a receiver in the message to keep track of the sent message.
*/
private function addSenderAsReceiver(Message $message, User $sender): void
{
$messageRelUserRepository = $this->entityManager->getRepository(MessageRelUser::class);
$existingRelation = $messageRelUserRepository->findOneBy([
'message' => $message,
'receiver' => $sender,
'receiverType' => MessageRelUser::TYPE_SENDER
]);
if (!$existingRelation) {
$messageRelUserSender = new MessageRelUser();
$messageRelUserSender->setMessage($message)
->setReceiver($sender)
->setReceiverType(MessageRelUser::TYPE_SENDER);
$this->entityManager->persist($messageRelUserSender);
$this->entityManager->flush();
}
}
private function sendEmailNotification(User $receiver, User $sender, string $subject, string $content, array $attachmentList): void
{
if (empty($receiver->getEmail())) {
throw new \Exception('The receiver does not have a valid email address.');
}
$email = (new Email())
->from($sender->getEmail())
->to($receiver->getEmail())
->subject($subject)
->text($content)
->html($content);
foreach ($attachmentList as $attachment) {
if ($attachment instanceof UploadedFile) {
$email->attachFromPath($attachment->getRealPath(), $attachment->getClientOriginalName());
}
}
try {
$this->mailer->send($email);
} catch (\Exception $e) {
error_log('Failed to send email: ' . $e->getMessage());
}
}
/**
* Retrieves a user group by its ID.
*/
private function getGroupById(int $groupId)
{
return $this->entityManager->getRepository(Usergroup::class)->find($groupId);
}
}
Loading…
Cancel
Save