/**
  * @covers \Ilios\CoreBundle\Entity\Manager\OfferingManager::getOfferingsForTeachingReminders
  */
 public function testGetOfferingsForTeachingReminders()
 {
     $offering = new Offering();
     $session = new Session();
     $offering->setSession($session);
     $course = new Course();
     $session->setCourse($course);
     $class = 'Ilios\\CoreBundle\\Entity\\Offering';
     $em = m::mock('Doctrine\\ORM\\EntityManager');
     $repository = m::mock('Doctrine\\ORM\\Repository')->shouldReceive('matching')->andReturn(new ArrayCollection([$offering]))->mock();
     $registry = m::mock('Doctrine\\Bundle\\DoctrineBundle\\Registry')->shouldReceive('getManagerForClass')->andReturn($em)->shouldReceive('getRepository')->andReturn($repository)->mock();
     $manager = new OfferingManager($registry, $class);
     $session->setPublished(true);
     $course->setPublished(true);
     $offerings = $manager->getOfferingsForTeachingReminders(10);
     $this->assertEquals(1, $offerings->count());
     $this->assertEquals($offering, $offerings->first());
     $session->setPublished(false);
     $course->setPublished(true);
     $offerings = $manager->getOfferingsForTeachingReminders(10);
     $this->assertEquals(0, $offerings->count());
     $session->setPublished(true);
     $course->setPublished(false);
     $offerings = $manager->getOfferingsForTeachingReminders(10);
     $this->assertEquals(0, $offerings->count());
     $session->setPublished(false);
     $course->setPublished(false);
     $offerings = $manager->getOfferingsForTeachingReminders(10);
     $this->assertEquals(0, $offerings->count());
 }
Beispiel #2
0
 /**
  * @covers Ilios\CoreBundle\Entity\Manager\OfferingManager::findOfferingsBy
  */
 public function testFindOfferingsDoNotIncludeDeleted()
 {
     $class = 'Ilios\\CoreBundle\\Entity\\Offering';
     $em = m::mock('Doctrine\\ORM\\EntityManager');
     $repository = m::mock('Doctrine\\ORM\\Repository')->shouldReceive('findBy')->with(array('foo' => 'bar', 'deleted' => false), null, null, null)->mock();
     $registry = m::mock('Doctrine\\Bundle\\DoctrineBundle\\Registry')->shouldReceive('getManagerForClass')->andReturn($em)->shouldReceive('getRepository')->andReturn($repository)->mock();
     $manager = new OfferingManager($registry, $class);
     $manager->findOfferingsBy(array('foo' => 'bar'));
 }
 /**
  * @covers \Ilios\CliBundle\Command\SendTeachingRemindersCommand::execute
  */
 public function testExecuteDryRun()
 {
     $sender = '*****@*****.**';
     $baseUrl = 'https://ilios.bar.edu';
     $this->commandTester->execute(['sender' => $sender, 'base_url' => $baseUrl, '--dry-run' => true]);
     /** @var OfferingInterface $offering */
     $offering = $this->fakeOfferingManager->getOfferingsForTeachingReminders(7)->toArray()[0];
     $output = $this->commandTester->getDisplay();
     /** @var UserInterface $instructor */
     foreach ($offering->getAllInstructors()->toArray() as $instructor) {
         $this->assertContains("To: {$instructor->getEmail()}", $output);
         $this->assertContains("Dear {$instructor->getFirstName()} {$instructor->getLastName()}", $output);
     }
     $timezone = new \DateTimeZone($this->timezone);
     $startDate = $offering->getStartDate()->setTimezone($timezone);
     $endDate = $offering->getEndDate()->setTimezone($timezone);
     $this->assertContains("From: {$sender}", $output);
     $subject = SendTeachingRemindersCommand::DEFAULT_MESSAGE_SUBJECT;
     $this->assertContains("Subject: {$subject}", $output);
     $this->assertContains("upcoming {$offering->getSession()->getSessionType()->getTitle()}", $output);
     $this->assertContains("School of {$offering->getSession()->getCourse()->getSchool()->getTitle()}", $output);
     $courseTitle = trim(strip_tags($offering->getSession()->getCourse()->getTitle()));
     $this->assertContains("Course:   {$courseTitle}", $output);
     $sessionTitle = trim(strip_tags($offering->getSession()->getTitle()));
     $this->assertContains("Session:  {$sessionTitle}", $output);
     $this->assertContains("Date:     {$startDate->format('D M d, Y')}", $output);
     $this->assertContains("Time:     {$startDate->format('h:i a')} - {$endDate->format('h:i a')}", $output);
     $this->assertContains("Location: {$offering->getRoom()}", $output);
     $this->assertContains("Coordinator at {$offering->getSession()->getCourse()->getSchool()->getIliosAdministratorEmail()}.", $output);
     /** @var LearnerGroupInterface $learnerGroup */
     foreach ($offering->getLearnerGroups()->toArray() as $learnerGroup) {
         $this->assertContains("- {$learnerGroup->getTitle()}", $output);
     }
     /** @var UserInterface $learner */
     foreach ($offering->getLearners()->toArray() as $learner) {
         $this->assertContains("- {$learner->getFirstName()} {$learner->getLastName()}", $output);
     }
     /** @var ObjectiveInterface $objective */
     foreach ($offering->getSession()->getObjectives() as $objective) {
         $title = trim(strip_tags($objective->getTitle()));
         $this->assertContains("- {$title}", $output);
     }
     /** @var ObjectiveInterface $objective */
     foreach ($offering->getSession()->getCourse()->getObjectives() as $objective) {
         $title = trim(strip_tags($objective->getTitle()));
         $this->assertContains("- {$title}", $output);
     }
     $this->assertContains("{$baseUrl}/courses/{$offering->getSession()->getCourse()->getId()}", $output);
     $totalMailsSent = count($offering->getAllInstructors()->toArray());
     $this->assertContains("Sent {$totalMailsSent} teaching reminders.", $output);
 }
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // input validation
     $errors = $this->validateInput($input);
     if (!empty($errors)) {
         foreach ($errors as $error) {
             $output->writeln("<error>{$error}</error>");
         }
         return;
     }
     $daysInAdvance = $input->getOption('days');
     $sender = $input->getArgument('sender');
     $baseUrl = rtrim($input->getArgument('base_url'), '/');
     $subject = $input->getOption('subject');
     $isDryRun = $input->getOption('dry-run');
     $senderName = $input->getOption('sender_name');
     $from = $sender;
     if ($senderName) {
         $from = [$sender => $senderName];
     }
     // get all applicable offerings.
     $offerings = $this->offeringManager->getOfferingsForTeachingReminders($daysInAdvance);
     if ($offerings->isEmpty()) {
         $output->writeln('<info>No offerings with pending teaching reminders found.</info>');
         return;
     }
     // mail out a reminder per instructor per offering.
     $templateCache = [];
     $iterator = $offerings->getIterator();
     $i = 0;
     /** @var OfferingInterface $offering */
     foreach ($iterator as $offering) {
         $deleted = !$offering->getSession() || !$offering->getSession()->getCourse() || !$offering->getSchool();
         if ($deleted) {
             continue;
         }
         $school = $offering->getSchool();
         if (!array_key_exists($school->getId(), $templateCache)) {
             $template = $this->getTemplatePath($school);
             $templateCache[$school->getId()] = $template;
         }
         $template = $templateCache[$school->getId()];
         $instructors = $offering->getAllInstructors()->toArray();
         /** @var UserInterface $instructor */
         foreach ($instructors as $instructor) {
             $i++;
             $messageBody = $this->templatingEngine->render($template, ['base_url' => $baseUrl, 'instructor' => $instructor, 'offering' => $offering, 'timezone' => $this->timezone]);
             $message = \Swift_Message::newInstance()->setSubject($subject)->setFrom($from)->setTo($instructor->getEmail())->setCharset('UTF-8')->setContentType('text/plain')->setBody($messageBody)->setMaxLineLength(998);
             if ($isDryRun) {
                 $output->writeln($message->getHeaders()->toString());
                 $output->writeln($message->getBody());
             } else {
                 $this->mailer->send($message);
             }
         }
     }
     $output->writeln("<info>Sent {$i} teaching reminders.</info>");
 }
Beispiel #5
0
 /**
  * @param Registry $em
  * @param string $class
  * @param FormFactoryInterface $formFactory
  */
 public function __construct(Registry $em, $class, FormFactoryInterface $formFactory)
 {
     $this->formFactory = $formFactory;
     parent::__construct($em, $class);
 }
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $isDryRun = $input->getOption('dry-run');
     $alerts = $this->alertManager->findBy(['dispatched' => false, 'tableName' => 'offering']);
     if (!count($alerts)) {
         $output->writeln("<info>No undispatched offering alerts found.</info>");
         return;
     }
     $templateCache = [];
     $sent = 0;
     // email out change alerts
     /* @var AlertInterface $alert */
     foreach ($alerts as $alert) {
         $output->writeln("<info>Processing offering change alert {$alert->getId()}.</info>");
         $offering = $this->offeringManager->findOneBy(['id' => $alert->getTableRowId()]);
         if (!$offering) {
             $output->writeln("<warning>No offering with id {$alert->getTableRowId()}," . " unable to send change alert with id {$alert->getId()}.</warning>");
             continue;
         }
         // do not send alerts for deleted stuff.
         $deleted = !$offering->getSession() || !$offering->getSession()->getCourse() || !$offering->getSession()->getCourse()->getSchool();
         if ($deleted) {
             // @todo print another warning here? [ST 2015/09/30]
             continue;
         }
         $schools = $alert->getRecipients();
         if ($schools->isEmpty()) {
             $output->writeln("<error>No alert recipient for offering change alert {$alert->getId()}.</error>");
             continue;
         }
         // Technically, there could be multiple school as recipients to a given alert.
         // The db schema allows for it.
         // In practice, there is really only ever one school recipient.
         // So take the first one and run with it for determining recipients/rendering the email template.
         // [ST 2015/10/05]
         /* @var SchoolInterface $school */
         $school = $schools->first();
         $recipients = trim($school->getChangeAlertRecipients());
         if ('' === $recipients) {
             $output->writeln("<error>Recipient without email for offering change alert {$alert->getId()}.</error>");
             continue;
         }
         $recipients = array_map('trim', explode(',', $recipients));
         // get change alert history from audit logs
         $history = $this->auditLogManager->findBy(['objectId' => $alert->getId(), 'objectClass' => 'alert'], ['createdAt' => 'asc']);
         $history = array_filter($history, function (AuditLogInterface $auditLog) {
             $user = $auditLog->getUser();
             return isset($user);
         });
         $subject = $offering->getSession()->getCourse()->getExternalId() . ' - ' . $offering->getStartDate()->format('m/d/Y');
         if (!array_key_exists($school->getId(), $templateCache)) {
             $template = $this->getTemplatePath($school);
             $templateCache[$school->getId()] = $template;
         }
         $template = $templateCache[$school->getId()];
         $messageBody = $this->templatingEngine->render($template, ['alert' => $alert, 'history' => $history, 'offering' => $offering, 'timezone' => $this->timezone]);
         $message = \Swift_Message::newInstance()->setSubject($subject)->setTo($recipients)->setFrom($school->getIliosAdministratorEmail())->setContentType('text/plain')->setBody($messageBody)->setMaxLineLength(998);
         if ($isDryRun) {
             $output->writeln($message->getHeaders()->toString());
             $output->writeln($message->getBody());
         } else {
             $this->mailer->send($message);
         }
         $sent++;
     }
     if (!$isDryRun) {
         // Mark all alerts as dispatched, regardless as to whether an actual email
         // was sent or not.
         // This is consistent with the Ilios v2 implementation of this process.
         // @todo Reassess the validity of this step. [ST 2015/10/01]
         foreach ($alerts as $alert) {
             $alert->setDispatched(true);
             $this->alertManager->update($alert);
         }
         $dispatched = count($alerts);
         $output->writeln("<info>Sent {$sent} offering change alert notifications.</info>");
         $output->writeln("<info>Marked {$dispatched} offering change alerts as dispatched.</info>");
     }
 }