Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: send requestee and requester correct date and time when timezone… #5924

Merged
merged 7 commits into from
May 27, 2024
4 changes: 4 additions & 0 deletions lib/Db/AppointmentConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ public function setAvailabilityAsArray(array $availability): self {
return $this;
}

public function getAvailabilityAsArray(): array {
return json_decode($this->getAvailability(), true, 512, JSON_THROW_ON_ERROR);
}

#[ReturnTypeWillChange]
public function jsonSerialize() {
return [
Expand Down
26 changes: 18 additions & 8 deletions lib/Service/Appointments/MailService.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public function sendConfirmationEmail(Booking $booking, AppointmentConfig $confi
}

// Create Booking overview
$this->addBulletList($template, $this->l10n, $booking, $config);
$this->addBulletList($template, $this->l10n, $booking, $config, false);

$bodyText = $this->l10n->t('This confirmation link expires in %s hours.', [(BookingService::EXPIRY / 3600)]);
$template->addBodyText($bodyText);
Expand Down Expand Up @@ -200,7 +200,7 @@ public function sendBookingInformationEmail(Booking $booking, AppointmentConfig
}

// Create Booking overview
$this->addBulletList($template, $this->l10n, $booking, $config);
$this->addBulletList($template, $this->l10n, $booking, $config, false);

$bodyText = $this->l10n->t('If you wish to cancel the appointment after all, please contact your organizer by replying to this email or by visiting their profile page.');
$template->addBodyText($bodyText);
Expand Down Expand Up @@ -230,15 +230,21 @@ public function sendBookingInformationEmail(Booking $booking, AppointmentConfig
private function addBulletList(IEMailTemplate $template,
IL10N $l10n,
Booking $booking,
AppointmentConfig $config):void {
AppointmentConfig $config,
bool $recipient):void {
$template->addBodyListItem($booking->getDisplayName(), $l10n->t('Appointment for:'));

// determain timezone depending on who is getting the message (Requestee/Requester)
$tzid = ($recipient) ? $config->getAvailabilityAsArray()['timezoneId'] : $booking->getTimezone();
$dtstart = new \DateTime("now", new \DateTimeZone($booking->getTimezone())); // generate DateTime with booking time zone
$dtstart->setTimestamp($booking->getStart()); // set booking time stamp

$l = $this->lFactory->findGenericLanguage();
$relativeDateTime = $this->dateFormatter->formatDateTimeRelativeDay(
$booking->getStart(),
$dtstart,
'long',
'short',
new \DateTimeZone($booking->getTimezone()),
new \DateTimeZone($tzid),
$this->lFactory->get('calendar', $l)
);

Expand Down Expand Up @@ -309,7 +315,7 @@ public function sendOrganizerBookingInformationEmail(Booking $booking, Appointme
}

// Create Booking overview
$this->addBulletList($template, $this->l10n, $booking, $config);
$this->addBulletList($template, $this->l10n, $booking, $config, true);
$template->addFooter();

$attachment = $this->mailer->createAttachment($calendar, 'appointment.ics', 'text/calendar');
Expand All @@ -333,11 +339,15 @@ public function sendOrganizerBookingInformationEmail(Booking $booking, Appointme
}

public function sendOrganizerBookingInformationNotification(Booking $booking, AppointmentConfig $config) {
$tzid = $config->getAvailabilityAsArray()['timezoneId']; // extract time zone from appointment configuration
$dtstart = new \DateTime("now", new \DateTimeZone($booking->getTimezone())); // generate DateTime with booking time zone
$dtstart->setTimestamp($booking->getStart()); // set booking time stamp

$relativeDateTime = $this->dateFormatter->formatDateTimeRelativeDay(
$booking->getStart(),
$dtstart,
'long',
'short',
new \DateTimeZone($booking->getTimezone()),
new \DateTimeZone($tzid),
$this->lFactory->get('calendar')
);

Expand Down
140 changes: 140 additions & 0 deletions tests/php/unit/Service/Appointments/MailServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,20 @@ public function testSendBookingInformationEmail(): void {
$config = new AppointmentConfig();
$config->setUserId('test');
$config->setLocation('Test');
$config->setAvailabilityAsArray(
[
"timezoneId" => "Europe/Berlin",
"slots" => [
"MO" => [["start" => 1713153660, "end" => 1713239940]],
"TU" => [["start" => 1713153660, "end" => 1713239940]],
"WE" => [["start" => 1713153660, "end" => 1713239940]],
"TH" => [["start" => 1713153660, "end" => 1713239940]],
"FR" => [["start" => 1713153660, "end" => 1713239940]],
"SA" => [["start" => 1713153660, "end" => 1713239940]],
"SU" => [["start" => 1713153660, "end" => 1713239940]]
]
]
);
$this->userManager->expects(self::once())
->method('get')
->willReturn($this->createConfiguredMock(IUser::class, [
Expand Down Expand Up @@ -505,6 +519,103 @@ public function testSendOrganizerBookingInformationEmail(): void {
$config = new AppointmentConfig();
$config->setUserId('test');
$config->setLocation('Test');
$config->setAvailabilityAsArray(
[
"timezoneId" => "Europe/Berlin",
"slots" => [
"MO" => [["start" => 1713153660, "end" => 1713239940]],
"TU" => [["start" => 1713153660, "end" => 1713239940]],
"WE" => [["start" => 1713153660, "end" => 1713239940]],
"TH" => [["start" => 1713153660, "end" => 1713239940]],
"FR" => [["start" => 1713153660, "end" => 1713239940]],
"SA" => [["start" => 1713153660, "end" => 1713239940]],
"SU" => [["start" => 1713153660, "end" => 1713239940]]
]
]
);
$this->userManager->expects(self::once())
->method('get')
->willReturn($this->createConfiguredMock(IUser::class, [
'getEmailAddress' => 'test@test.com',
'getDisplayName' => 'Test Test'
]));
$mailMessage = $this->createMock(IMessage::class);
$this->mailer->expects(self::once())
->method('createMessage')
->willReturn($mailMessage);
$mailMessage->expects(self::once())
->method('setFrom')
->willReturn($mailMessage);
$mailMessage->expects(self::once())
->method('setTo')
->willReturn($mailMessage);
$mailMessage->expects(self::once())
->method('useTemplate')
->willReturn($mailMessage);
$emailTemplate = $this->createMock(IEMailTemplate::class);
$this->mailer->expects(self::once())
->method('createEmailTemplate')
->willReturn($emailTemplate);
$emailTemplate->expects(self::once())
->method('addHeader');
$emailTemplate->expects(self::once())
->method('setSubject');
$emailTemplate->expects(self::once())
->method('addHeading');
$emailTemplate->expects(self::exactly(5))
->method('addBodyListItem');
$emailTemplate->expects(self::once())
->method('addFooter');
$this->mailer->expects(self::once())
->method('createEmailTemplate');
$this->mailer->expects(self::once())
->method('createAttachment');
$this->l10n->expects(self::exactly(6))
->method('t');
$this->lFactory->expects(self::once())
->method('findGenericLanguage')
->willReturn('en');
$this->lFactory->expects(self::once())
->method('get');
$this->dateFormatter->expects(self::once())
->method('formatDateTimeRelativeDay')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by using ->with(args) you can assert the value of the arguments passed to this method. It will allow you to test if the fourth argument matches the expected timezone value. Same for the new testSendOrganizerBookingInformationEmailDifferentTZ case

->willReturn('Test');
$this->mailer->expects(self::once())
->method('send')
->willReturn([]);
$this->logger->expects(self::never())
->method('warning');
$this->logger->expects(self::never())
->method('debug');

$this->mailService->sendOrganizerBookingInformationEmail($booking, $config, 'abc');
}

public function testSendOrganizerBookingInformationEmailDifferentTZ(): void {
$booking = new Booking();
$booking->setEmail('test@test.com');
$booking->setDisplayName('Test');
$booking->setStart(time());
$booking->setTimezone('America/Toronto');
$booking->setDescription('Test');
$config = new AppointmentConfig();
$config->setUserId('test');
$config->setLocation('Test');
$config->setAvailabilityAsArray(
[
"timezoneId" => "Europe/Berlin",
"slots" => [
"MO" => [["start" => 1713153660, "end" => 1713239940]],
"TU" => [["start" => 1713153660, "end" => 1713239940]],
"WE" => [["start" => 1713153660, "end" => 1713239940]],
"TH" => [["start" => 1713153660, "end" => 1713239940]],
"FR" => [["start" => 1713153660, "end" => 1713239940]],
"SA" => [["start" => 1713153660, "end" => 1713239940]],
"SU" => [["start" => 1713153660, "end" => 1713239940]]
]
]
);

$this->userManager->expects(self::once())
->method('get')
->willReturn($this->createConfiguredMock(IUser::class, [
Expand Down Expand Up @@ -551,6 +662,7 @@ public function testSendOrganizerBookingInformationEmail(): void {
->method('get');
$this->dateFormatter->expects(self::once())
->method('formatDateTimeRelativeDay')
->with(self::anything(), self::anything(), self::anything(), new \DateTimeZone('Europe/Berlin'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 nice

->willReturn('Test');
$this->mailer->expects(self::once())
->method('send')
Expand All @@ -573,6 +685,20 @@ public function testSendOrganizerBookingInformationEmailFailed(): void {
$config = new AppointmentConfig();
$config->setUserId('test');
$config->setLocation('Test');
$config->setAvailabilityAsArray(
[
"timezoneId" => "Europe/Berlin",
"slots" => [
"MO" => [["start" => 1713153660, "end" => 1713239940]],
"TU" => [["start" => 1713153660, "end" => 1713239940]],
"WE" => [["start" => 1713153660, "end" => 1713239940]],
"TH" => [["start" => 1713153660, "end" => 1713239940]],
"FR" => [["start" => 1713153660, "end" => 1713239940]],
"SA" => [["start" => 1713153660, "end" => 1713239940]],
"SU" => [["start" => 1713153660, "end" => 1713239940]]
]
]
);
$this->userManager->expects(self::once())
->method('get')
->willReturn($this->createConfiguredMock(IUser::class, [
Expand Down Expand Up @@ -654,6 +780,20 @@ public function testSendOrganizerBookingNotification(): void {
$config = new AppointmentConfig();
$config->setUserId('test');
$config->setLocation('Test');
$config->setAvailabilityAsArray(
[
"timezoneId" => "Europe/Berlin",
"slots" => [
"MO" => [["start" => 1713153660, "end" => 1713239940]],
"TU" => [["start" => 1713153660, "end" => 1713239940]],
"WE" => [["start" => 1713153660, "end" => 1713239940]],
"TH" => [["start" => 1713153660, "end" => 1713239940]],
"FR" => [["start" => 1713153660, "end" => 1713239940]],
"SA" => [["start" => 1713153660, "end" => 1713239940]],
"SU" => [["start" => 1713153660, "end" => 1713239940]]
]
]
);
$notification = $this->createMock(INotification::class);

$this->lFactory->expects(self::once())
Expand Down
Loading