commit
423482fcfc
@ -1,32 +1,37 @@ |
|||||||
import gql from 'graphql-tag'; |
import gql from 'graphql-tag'; |
||||||
|
|
||||||
export const GET_COURSE_REL_USER = gql` |
export const GET_COURSE_REL_USER = gql` |
||||||
query getCourses($user: String!) { |
query getCourses($user: String!, $first: Int!, $after: String) { |
||||||
courseRelUsers(user: $user) { |
courseRelUsers(user: $user, first: $first, after: $after) { |
||||||
edges { |
edges { |
||||||
|
cursor |
||||||
|
node { |
||||||
|
course { |
||||||
|
_id, |
||||||
|
title, |
||||||
|
illustrationUrl, |
||||||
|
duration, |
||||||
|
users(status: 1, first: 4) { |
||||||
|
edges { |
||||||
node { |
node { |
||||||
course { |
id |
||||||
_id, |
status |
||||||
title, |
user { |
||||||
illustrationUrl, |
illustrationUrl, |
||||||
duration, |
username, |
||||||
users(status: 1, first: 4) { |
fullName |
||||||
edges { |
} |
||||||
node { |
|
||||||
id |
|
||||||
status |
|
||||||
user { |
|
||||||
illustrationUrl, |
|
||||||
username, |
|
||||||
fullName |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
} |
} |
||||||
|
} |
||||||
} |
} |
||||||
|
} |
||||||
|
pageInfo { |
||||||
|
endCursor |
||||||
|
hasNextPage |
||||||
|
} |
||||||
} |
} |
||||||
|
} |
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -0,0 +1,300 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
|
||||||
|
namespace Chamilo\CoreBundle\Command; |
||||||
|
|
||||||
|
use Chamilo\CoreBundle\Repository\CourseRelUserRepository; |
||||||
|
use Chamilo\CoreBundle\Repository\ExtraFieldValuesRepository; |
||||||
|
use Chamilo\CoreBundle\Repository\Node\CourseRepository; |
||||||
|
use Chamilo\CoreBundle\Repository\Node\UserRepository; |
||||||
|
use Chamilo\CoreBundle\Repository\SessionRelCourseRelUserRepository; |
||||||
|
use Chamilo\CoreBundle\Repository\TrackEDefaultRepository; |
||||||
|
use Chamilo\CoreBundle\ServiceHelper\MessageHelper; |
||||||
|
use DateTime; |
||||||
|
use DateTimeZone; |
||||||
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface; |
||||||
|
use Twig\Environment; |
||||||
|
use Symfony\Component\Console\Command\Command; |
||||||
|
use Symfony\Component\Console\Input\InputInterface; |
||||||
|
use Symfony\Component\Console\Input\InputOption; |
||||||
|
use Symfony\Component\Console\Output\OutputInterface; |
||||||
|
|
||||||
|
class LpProgressReminderCommand extends Command |
||||||
|
{ |
||||||
|
protected static $defaultName = 'app:lp-progress-reminder'; |
||||||
|
|
||||||
|
private const NUMBER_OF_DAYS_TO_RESEND_NOTIFICATION = 3; |
||||||
|
|
||||||
|
public function __construct( |
||||||
|
private readonly CourseRepository $courseRepository, |
||||||
|
private readonly CourseRelUserRepository $courseRelUserRepository, |
||||||
|
private readonly SessionRelCourseRelUserRepository $sessionRelCourseRelUserRepository, |
||||||
|
private readonly ExtraFieldValuesRepository $extraFieldValuesRepository, |
||||||
|
private readonly TrackEDefaultRepository $trackEDefaultRepository, |
||||||
|
private readonly UserRepository $userRepository, |
||||||
|
private readonly Environment $twig, |
||||||
|
private readonly TranslatorInterface $translator, |
||||||
|
private readonly MessageHelper $messageHelper, |
||||||
|
private readonly UrlGeneratorInterface $urlGenerator |
||||||
|
) { |
||||||
|
parent::__construct(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
protected function configure() |
||||||
|
{ |
||||||
|
$this |
||||||
|
->setDescription('Send LP progress reminders to users based on "number_of_days_for_completion".') |
||||||
|
->addOption( |
||||||
|
'debug', |
||||||
|
null, |
||||||
|
InputOption::VALUE_NONE, |
||||||
|
'If set, will output detailed debug information' |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int |
||||||
|
{ |
||||||
|
$debugMode = $input->getOption('debug'); |
||||||
|
$output->writeln('Starting the LP progress reminder process...'); |
||||||
|
|
||||||
|
// Retrieve LPs with completion days |
||||||
|
$lpItems = $this->extraFieldValuesRepository->getLpIdWithDaysForCompletion(); |
||||||
|
if ($debugMode && !empty($lpItems)) { |
||||||
|
$output->writeln('LP Items retrieved: ' . print_r($lpItems, true)); |
||||||
|
} |
||||||
|
|
||||||
|
if (empty($lpItems)) { |
||||||
|
$output->writeln('No learning paths with days for completion found.'); |
||||||
|
return Command::SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
$lpMap = []; |
||||||
|
foreach ($lpItems as $lpItem) { |
||||||
|
$lpMap[$lpItem['lp_id']] = $lpItem['ndays']; |
||||||
|
} |
||||||
|
$lpIds = array_keys($lpMap); |
||||||
|
|
||||||
|
// Retrieve all courses from the CourseRepository |
||||||
|
$courses = $this->courseRepository->findAll(); |
||||||
|
if ($debugMode && !empty($courses)) { |
||||||
|
$output->writeln('Courses retrieved: ' . count($courses)); |
||||||
|
} |
||||||
|
|
||||||
|
foreach ($courses as $course) { |
||||||
|
$courseId = $course->getId(); |
||||||
|
|
||||||
|
// Retrieve users for the course (without session) |
||||||
|
$courseUsers = $this->courseRelUserRepository->getCourseUsers($courseId, $lpIds); |
||||||
|
// Retrieve users for the course session |
||||||
|
$sessionCourseUsers = $this->sessionRelCourseRelUserRepository->getSessionCourseUsers($courseId, $lpIds); |
||||||
|
|
||||||
|
if ($debugMode && (!empty($courseUsers) || !empty($sessionCourseUsers))) { |
||||||
|
$output->writeln('Processing course ID: ' . $courseId); |
||||||
|
if (!empty($courseUsers)) { |
||||||
|
$output->writeln('Course users retrieved: ' . count($courseUsers)); |
||||||
|
//$output->writeln('Course retrieved: ' . print_r($courseUsers, true)); |
||||||
|
} |
||||||
|
if (!empty($sessionCourseUsers)) { |
||||||
|
$output->writeln('Session users retrieved: ' . count($sessionCourseUsers)); |
||||||
|
//$output->writeln('Session retrieved: ' . print_r($sessionCourseUsers, true)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Process users from the main course (sessionId = 0 or null) |
||||||
|
$this->processCourseUsers($courseUsers, $lpMap, $courseId, $debugMode); |
||||||
|
|
||||||
|
// Process users from the course session (sessionId > 0) |
||||||
|
$this->processCourseUsers($sessionCourseUsers, $lpMap, $courseId, $debugMode, true); |
||||||
|
} |
||||||
|
|
||||||
|
$output->writeln('LP progress reminder process finished.'); |
||||||
|
return Command::SUCCESS; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Processes users from a course or session to check if a reminder needs to be sent. |
||||||
|
*/ |
||||||
|
private function processCourseUsers(array $users, array $lpItems, int $courseId, bool $debugMode = false, bool $checkSession = false): void |
||||||
|
{ |
||||||
|
foreach ($users as $user) { |
||||||
|
$userId = $user['userId']; |
||||||
|
$courseTitle = $user['courseTitle']; |
||||||
|
$lpId = $user['lpId']; |
||||||
|
$progress = (int) $user['progress']; |
||||||
|
|
||||||
|
$sessionId = $checkSession ? ($user['sessionId'] ?? 0) : 0; |
||||||
|
|
||||||
|
if ($lpId === null) { |
||||||
|
foreach ($lpItems as $lpId => $nbDaysForLpCompletion) { |
||||||
|
$this->sendReminderIfNeeded( |
||||||
|
$userId, |
||||||
|
$courseTitle, |
||||||
|
$courseId, |
||||||
|
$sessionId, |
||||||
|
(int) $nbDaysForLpCompletion, |
||||||
|
$debugMode, |
||||||
|
$lpId, |
||||||
|
$progress |
||||||
|
); |
||||||
|
} |
||||||
|
} else { |
||||||
|
$nbDaysForLpCompletion = (int) ($lpItems[$lpId] ?? self::NUMBER_OF_DAYS_TO_RESEND_NOTIFICATION); |
||||||
|
$this->sendReminderIfNeeded( |
||||||
|
$userId, |
||||||
|
$courseTitle, |
||||||
|
$courseId, |
||||||
|
$sessionId, |
||||||
|
$nbDaysForLpCompletion, |
||||||
|
$debugMode, |
||||||
|
$lpId, |
||||||
|
$progress |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sends a progress reminder to a user if the conditions for reminder timing are met, |
||||||
|
* based on their registration date and learning path completion criteria. |
||||||
|
*/ |
||||||
|
private function sendReminderIfNeeded( |
||||||
|
int $userId, |
||||||
|
string $courseTitle, |
||||||
|
int $courseId, |
||||||
|
int $sessionId, |
||||||
|
int $nbDaysForLpCompletion, |
||||||
|
bool $debugMode, |
||||||
|
?int $lpId, |
||||||
|
int $progress |
||||||
|
): void { |
||||||
|
$registrationDate = $this->trackEDefaultRepository->getUserCourseRegistrationAt($courseId, $userId, $sessionId); |
||||||
|
if (!$registrationDate) { |
||||||
|
if ($debugMode) { |
||||||
|
echo "No registration date found for user $userId in course $courseId (session ID: $sessionId).\n"; |
||||||
|
} |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if ($debugMode) { |
||||||
|
$sessionInfo = $sessionId > 0 ? "in session ID $sessionId" : "without a session"; |
||||||
|
echo "Registration date: {$registrationDate->format('Y-m-d H:i:s')}, Days for completion: $nbDaysForLpCompletion, LP ID: {$lpId}, $sessionInfo\n"; |
||||||
|
} |
||||||
|
|
||||||
|
if ($this->isTimeToRemindUser($registrationDate, $nbDaysForLpCompletion)) { |
||||||
|
$nbRemind = $this->getNbReminder($registrationDate, $nbDaysForLpCompletion); |
||||||
|
|
||||||
|
if ($debugMode) { |
||||||
|
echo "Sending reminder to user $userId for course $courseTitle (LP ID: {$lpId})\n"; |
||||||
|
} |
||||||
|
$this->logReminderSent($userId, $courseTitle, $nbRemind, $debugMode, $lpId, $sessionId); |
||||||
|
$this->sendLpReminder($userId, $courseTitle, $progress, $registrationDate, $nbRemind); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Logs the reminder details if debug mode is enabled. |
||||||
|
*/ |
||||||
|
private function logReminderSent(int $userId, string $courseTitle, int $nbRemind, bool $debugMode, int $lpId, int $sessionId = 0): void |
||||||
|
{ |
||||||
|
if ($debugMode) { |
||||||
|
$sessionInfo = $sessionId > 0 ? sprintf("in session ID %d", $sessionId) : "without a session"; |
||||||
|
echo sprintf( |
||||||
|
"Reminder number %d sent to user ID %d for the course %s (LP ID: %d) %s.\n", |
||||||
|
$nbRemind, |
||||||
|
$userId, |
||||||
|
$courseTitle, |
||||||
|
$lpId, |
||||||
|
$sessionInfo |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Calculates the number of reminders to be sent based on registration date and days for completion. |
||||||
|
*/ |
||||||
|
private function getNbReminder(DateTime $registrationDate, int $nbDaysForLpCompletion): int |
||||||
|
{ |
||||||
|
$reminderStartDate = (clone $registrationDate)->modify("+$nbDaysForLpCompletion days"); |
||||||
|
$currentDate = new DateTime('now', new DateTimeZone('UTC')); |
||||||
|
$reminderStartDate->setTime(0, 0, 0); |
||||||
|
$currentDate->setTime(0, 0, 0); |
||||||
|
|
||||||
|
$interval = $reminderStartDate->diff($currentDate); |
||||||
|
$diffDays = (int) $interval->format('%a'); |
||||||
|
|
||||||
|
return (int) floor($diffDays / self::NUMBER_OF_DAYS_TO_RESEND_NOTIFICATION) + 1; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Checks if it is time to remind the user based on their registration date and LP completion days. |
||||||
|
*/ |
||||||
|
private function isTimeToRemindUser(DateTime $registrationDate, int $nbDaysForLpCompletion): bool |
||||||
|
{ |
||||||
|
$reminderStartDate = (clone $registrationDate)->modify("+$nbDaysForLpCompletion days"); |
||||||
|
$reminderStartDate->setTime(0, 0, 0); |
||||||
|
|
||||||
|
$currentDate = new DateTime('now', new DateTimeZone('UTC')); |
||||||
|
$currentDate->setTime(0, 0, 0); |
||||||
|
|
||||||
|
$interval = $reminderStartDate->diff($currentDate); |
||||||
|
$diffDays = (int) $interval->format('%a'); |
||||||
|
|
||||||
|
return ($diffDays >= self::NUMBER_OF_DAYS_TO_RESEND_NOTIFICATION && |
||||||
|
$diffDays % self::NUMBER_OF_DAYS_TO_RESEND_NOTIFICATION === 0) || $diffDays === 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Sends a reminder email to the user regarding their LP progress. |
||||||
|
*/ |
||||||
|
private function sendLpReminder(int $toUserId, string $courseName, int $lpProgress, DateTime $registrationDate, int $nbRemind): bool |
||||||
|
{ |
||||||
|
$user = $this->userRepository->find($toUserId); |
||||||
|
if (!$user) { |
||||||
|
throw new \Exception("User not found"); |
||||||
|
} |
||||||
|
|
||||||
|
$platformUrl = $this->urlGenerator->generate('index', [], UrlGeneratorInterface::ABSOLUTE_URL); |
||||||
|
$recoverPasswordUrl = $platformUrl.'/main/auth/lostPassword.php'; |
||||||
|
|
||||||
|
$trainingCenterName = 'Your Training Center'; |
||||||
|
$trainers = 'Trainer Name'; |
||||||
|
|
||||||
|
$hello = $this->translator->trans("Hello %s"); |
||||||
|
$youAreRegCourse = $this->translator->trans("You are registered in the training %s since the %s"); |
||||||
|
$thisMessageIsAbout = $this->translator->trans("You are receiving this message because you have completed a learning path with a %s progress of your training.<br/>Your progress must be 100 to consider that your training was carried out.<br/>If you have the slightest problem, you should contact with your trainer."); |
||||||
|
$stepsToRemind = $this->translator->trans("As a reminder, to access the training platform:<br/>1. Connect to the platform at the address: %s <br/>2. Then enter: <br/>Your username: %s <br/>Your password: This was emailed to you.<br/>if you forgot it and can't find it, you can retrieve it by going to %s <br/><br/>Thank you for doing what is necessary."); |
||||||
|
$lpRemindFooter = $this->translator->trans("The training center<p>%s</p>Trainers:<br/>%s"); |
||||||
|
|
||||||
|
$hello = sprintf($hello, $user->getFullName()); |
||||||
|
$youAreRegCourse = sprintf($youAreRegCourse, $courseName, $registrationDate->format('Y-m-d')); |
||||||
|
$thisMessageIsAbout = sprintf($thisMessageIsAbout, $lpProgress); |
||||||
|
$stepsToRemind = sprintf($stepsToRemind, $platformUrl, $user->getUsername(), $recoverPasswordUrl); |
||||||
|
$lpRemindFooter = sprintf($lpRemindFooter, $trainingCenterName, $trainers); |
||||||
|
|
||||||
|
$messageContent = $this->twig->render('@ChamiloCore/Mailer/Legacy/lp_progress_reminder_body.html.twig', [ |
||||||
|
'HelloX' => $hello, |
||||||
|
'YouAreRegCourseXFromDateX' => $youAreRegCourse, |
||||||
|
'ThisMessageIsAboutX' => $thisMessageIsAbout, |
||||||
|
'StepsToRemindX' => $stepsToRemind, |
||||||
|
'LpRemindFooterX' => $lpRemindFooter, |
||||||
|
]); |
||||||
|
|
||||||
|
try { |
||||||
|
$this->messageHelper->sendMessageSimple( |
||||||
|
$toUserId, |
||||||
|
sprintf("Reminder number %d for the course %s", $nbRemind, $courseName), |
||||||
|
$messageContent |
||||||
|
); |
||||||
|
|
||||||
|
return true; |
||||||
|
} catch (\Exception $e) { |
||||||
|
throw new \Exception('Error sending reminder: ' . $e->getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
|
||||||
|
namespace Chamilo\CoreBundle\Repository; |
||||||
|
|
||||||
|
use Chamilo\CoreBundle\Entity\CourseRelUser; |
||||||
|
use Chamilo\CourseBundle\Entity\CLp; |
||||||
|
use Chamilo\CourseBundle\Entity\CLpView; |
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; |
||||||
|
use Doctrine\Persistence\ManagerRegistry; |
||||||
|
|
||||||
|
class CourseRelUserRepository extends ServiceEntityRepository |
||||||
|
{ |
||||||
|
public function __construct(ManagerRegistry $registry) |
||||||
|
{ |
||||||
|
parent::__construct($registry, CourseRelUser::class); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Retrieves users from a course and their LP progress (without session). |
||||||
|
*/ |
||||||
|
public function getCourseUsers(int $courseId, array $lpIds): array |
||||||
|
{ |
||||||
|
$qb = $this->createQueryBuilder('cu') |
||||||
|
->select('u.id AS userId, c.title AS courseTitle, lp.iid AS lpId, COALESCE(lpv.progress, 0) AS progress') |
||||||
|
->innerJoin('cu.user', 'u') |
||||||
|
->innerJoin('cu.course', 'c') |
||||||
|
->leftJoin(CLpView::class, 'lpv', 'WITH', 'lpv.user = u.id AND lpv.course = cu.course AND lpv.lp IN (:lpIds)') |
||||||
|
->leftJoin(CLp::class, 'lp', 'WITH', 'lp.iid IN (:lpIds)') |
||||||
|
->innerJoin('lp.resourceNode', 'rn') |
||||||
|
->where('cu.course = :courseId') |
||||||
|
->andWhere('rn.parent = c.resourceNode') |
||||||
|
->andWhere('(lpv.progress < 100 OR lpv.progress IS NULL)') |
||||||
|
->setParameter('courseId', $courseId) |
||||||
|
->setParameter('lpIds', $lpIds); |
||||||
|
|
||||||
|
return $qb->getQuery()->getResult(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
|
||||||
|
namespace Chamilo\CoreBundle\Repository; |
||||||
|
|
||||||
|
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser; |
||||||
|
use Chamilo\CourseBundle\Entity\CLp; |
||||||
|
use Chamilo\CourseBundle\Entity\CLpView; |
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; |
||||||
|
use Doctrine\Persistence\ManagerRegistry; |
||||||
|
|
||||||
|
class SessionRelCourseRelUserRepository extends ServiceEntityRepository |
||||||
|
{ |
||||||
|
public function __construct(ManagerRegistry $registry) |
||||||
|
{ |
||||||
|
parent::__construct($registry, SessionRelCourseRelUser::class); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Retrieves users from a course session and their LP progress. |
||||||
|
*/ |
||||||
|
public function getSessionCourseUsers(int $courseId, array $lpIds): array |
||||||
|
{ |
||||||
|
$qb = $this->createQueryBuilder('scu') |
||||||
|
->select('u.id AS userId, c.title AS courseTitle, lp.iid AS lpId, COALESCE(lpv.progress, 0) AS progress, IDENTITY(scu.session) AS sessionId') |
||||||
|
->innerJoin('scu.user', 'u') |
||||||
|
->innerJoin('scu.course', 'c') |
||||||
|
->leftJoin(CLpView::class, 'lpv', 'WITH', 'lpv.user = u.id AND lpv.course = scu.course AND lpv.lp IN (:lpIds)') |
||||||
|
->leftJoin(CLp::class, 'lp', 'WITH', 'lp.iid IN (:lpIds)') |
||||||
|
->innerJoin('lp.resourceNode', 'rn') |
||||||
|
->where('scu.course = :courseId') |
||||||
|
->andWhere('rn.parent = c.resourceNode') |
||||||
|
->andWhere('(lpv.progress < 100 OR lpv.progress IS NULL)') |
||||||
|
->setParameter('courseId', $courseId) |
||||||
|
->setParameter('lpIds', $lpIds); |
||||||
|
|
||||||
|
return $qb->getQuery()->getResult(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
|
||||||
|
namespace Chamilo\CoreBundle\Repository; |
||||||
|
|
||||||
|
use Chamilo\CoreBundle\Entity\TrackEDefault; |
||||||
|
use DateTime; |
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; |
||||||
|
use Doctrine\Persistence\ManagerRegistry; |
||||||
|
|
||||||
|
class TrackEDefaultRepository extends ServiceEntityRepository |
||||||
|
{ |
||||||
|
public function __construct(ManagerRegistry $registry) |
||||||
|
{ |
||||||
|
parent::__construct($registry, TrackEDefault::class); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Retrieves the registration date of a user in a specific course or session. |
||||||
|
*/ |
||||||
|
public function getUserCourseRegistrationAt(int $courseId, int $userId, ?int $sessionId = 0): ?\DateTime |
||||||
|
{ |
||||||
|
$serializedPattern = sprintf('s:2:"id";i:%d;', $userId); |
||||||
|
|
||||||
|
$qb = $this->createQueryBuilder('te') |
||||||
|
->select('te.defaultDate') |
||||||
|
->where('te.cId = :courseId') |
||||||
|
->andWhere('te.defaultValueType = :valueType') |
||||||
|
->andWhere('te.defaultEventType = :eventType') |
||||||
|
->andWhere('te.defaultValue LIKE :serializedPattern') |
||||||
|
->setParameter('courseId', $courseId) |
||||||
|
->setParameter('valueType', 'user_object') |
||||||
|
->setParameter('eventType', 'user_subscribed') |
||||||
|
->setParameter('serializedPattern', '%' . $serializedPattern . '%'); |
||||||
|
|
||||||
|
if ($sessionId > 0) { |
||||||
|
$qb->andWhere('te.sessionId = :sessionId') |
||||||
|
->setParameter('sessionId', $sessionId); |
||||||
|
} elseif ($sessionId === 0) { |
||||||
|
$qb->andWhere('te.sessionId = 0'); |
||||||
|
} else { |
||||||
|
$qb->andWhere('te.sessionId IS NULL'); |
||||||
|
} |
||||||
|
|
||||||
|
$qb->setMaxResults(1); |
||||||
|
$query = $qb->getQuery(); |
||||||
|
|
||||||
|
try { |
||||||
|
$result = $query->getOneOrNullResult(); |
||||||
|
if ($result && isset($result['defaultDate'])) { |
||||||
|
return $result['defaultDate'] instanceof \DateTime |
||||||
|
? $result['defaultDate'] |
||||||
|
: new \DateTime($result['defaultDate']); |
||||||
|
} |
||||||
|
} catch (\Exception $e) { |
||||||
|
throw new \RuntimeException('Error fetching registration date: ' . $e->getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
<p> |
||||||
|
{{HelloX}} |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
{{YouAreRegCourseXFromDateX}}<br /> |
||||||
|
{{ThisMessageIsAboutX}} |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
{{StepsToRemindX}} |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
{{LpRemindFooterX}} |
||||||
|
</p> |
@ -0,0 +1 @@ |
|||||||
|
{{RemindXLpCourseX}} |
Loading…
Reference in new issue