diff --git a/CHANGELOG.md b/CHANGELOG.md index 6816c44..0ad1ee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ See [keep a changelog](https://keepachangelog.com/en/1.0.0/) for information abo ### Added - Added acceptConflict field to resource. +- Added tests for acceptConflict. ### Changed diff --git a/src/Service/MicrosoftGraphBookingService.php b/src/Service/MicrosoftGraphBookingService.php index 448c08b..0c4afc4 100644 --- a/src/Service/MicrosoftGraphBookingService.php +++ b/src/Service/MicrosoftGraphBookingService.php @@ -86,7 +86,7 @@ public function createBookingForResource(string $resourceEmail, string $resource $token = $this->graphHelperService->authenticateAsServiceAccount(); if (!$acceptConflict) { - $bookingConflict = $this->isBookingConflict($resourceEmail, $startTime, $endTime, $token); + $bookingConflict = $this->graphHelperService->isBookingConflict($resourceEmail, $startTime, $endTime, $token); if ($bookingConflict) { throw new BookingCreateConflictException('Booking interval conflict.', 409); @@ -137,7 +137,7 @@ public function createBookingForResource(string $resourceEmail, string $resource $iCalUId = $content['iCalUId']; if (!$acceptConflict) { - if ($this->isBookingConflict($resourceEmail, $startTime, $endTime, $token, [$iCalUId])) { + if ($this->graphHelperService->isBookingConflict($resourceEmail, $startTime, $endTime, $token, [$iCalUId])) { $bookingId = $content['id']; // If another booking has been created at the same time, remove this booking. @@ -232,7 +232,7 @@ public function updateBooking(UserBooking $booking): ?string $resourceMail = $booking->resourceMail; - $bookingConflict = $this->isBookingConflict($resourceMail, $booking->start, $booking->end, $token, [$booking->iCalUId]); + $bookingConflict = $this->graphHelperService->isBookingConflict($resourceMail, $booking->start, $booking->end, $token, [$booking->iCalUId]); if ($bookingConflict) { throw new UserBookingException('Booking interval conflict.', 409); @@ -546,46 +546,4 @@ private function getEventFromResourceByICalUid(string $resourceEmail, string $iC return null; } - - /** - * Check that there is no interval conflict. - * - * @param string $resourceEmail resource to check for conflict in - * @param DateTime $startTime start of interval - * @param DateTime $endTime end of interval - * @param string|null $accessToken access token - * @param array|null $ignoreICalUIds Ignore bookings with these ICalUIds in the evaluation. Use to allow editing an existing booking. - * - * @return bool whether there is a booking conflict for the given interval - * - * @throws MicrosoftGraphCommunicationException - */ - private function isBookingConflict(string $resourceEmail, DateTime $startTime, DateTime $endTime, string $accessToken = null, array $ignoreICalUIds = null): bool - { - $token = $accessToken ?: $this->graphHelperService->authenticateAsServiceAccount(); - $startString = $startTime->setTimezone(new \DateTimeZone('UTC'))->format(MicrosoftGraphBookingService::DATE_FORMAT).'Z'; - $endString = $endTime->setTimezone(new \DateTimeZone('UTC'))->format(MicrosoftGraphBookingService::DATE_FORMAT).'Z'; - - $filterString = "\$filter=start/dateTime lt '$endString' and end/dateTime gt '$startString'"; - - $response = $this->graphHelperService->request("/users/$resourceEmail/calendar/events?$filterString", $token); - - $body = $response->getBody(); - - $entries = $body['value']; - - if (count($entries) > 0) { - if (null != $ignoreICalUIds) { - foreach ($entries as $entry) { - if (!in_array($entry['iCalUId'], $ignoreICalUIds)) { - return true; - } - } - } else { - return true; - } - } - - return false; - } } diff --git a/src/Service/MicrosoftGraphHelperService.php b/src/Service/MicrosoftGraphHelperService.php index c81f52c..fd706be 100644 --- a/src/Service/MicrosoftGraphHelperService.php +++ b/src/Service/MicrosoftGraphHelperService.php @@ -4,6 +4,7 @@ use App\Exception\MicrosoftGraphCommunicationException; use App\Factory\ClientFactory; +use DateTime; use GuzzleHttp\Exception\GuzzleException; use JsonException; use Microsoft\Graph\Exception\GraphException; @@ -79,4 +80,46 @@ public function request(string $path, string $accessToken, string $requestType = throw new MicrosoftGraphCommunicationException($e->getMessage(), $e->getCode()); } } + + /** + * Check that there is no interval conflict. + * + * @param string $resourceEmail resource to check for conflict in + * @param DateTime $startTime start of interval + * @param DateTime $endTime end of interval + * @param string|null $accessToken access token + * @param array|null $ignoreICalUIds Ignore bookings with these ICalUIds in the evaluation. Use to allow editing an existing booking. + * + * @return bool whether there is a booking conflict for the given interval + * + * @throws MicrosoftGraphCommunicationException + */ + public function isBookingConflict(string $resourceEmail, DateTime $startTime, DateTime $endTime, string $accessToken = null, array $ignoreICalUIds = null): bool + { + $token = $accessToken ?: $this->authenticateAsServiceAccount(); + $startString = $startTime->setTimezone(new \DateTimeZone('UTC'))->format(MicrosoftGraphBookingService::DATE_FORMAT).'Z'; + $endString = $endTime->setTimezone(new \DateTimeZone('UTC'))->format(MicrosoftGraphBookingService::DATE_FORMAT).'Z'; + + $filterString = "\$filter=start/dateTime lt '$endString' and end/dateTime gt '$startString'"; + + $response = $this->request("/users/$resourceEmail/calendar/events?$filterString", $token); + + $body = $response->getBody(); + + $entries = $body['value']; + + if (count($entries) > 0) { + if (null != $ignoreICalUIds) { + foreach ($entries as $entry) { + if (!in_array($entry['iCalUId'], $ignoreICalUIds)) { + return true; + } + } + } else { + return true; + } + } + + return false; + } } diff --git a/tests/Api/BookingTest.php b/tests/Api/BookingTest.php index 66e0122..51a13a9 100644 --- a/tests/Api/BookingTest.php +++ b/tests/Api/BookingTest.php @@ -231,7 +231,7 @@ public function testCreateBookingHandler(): void $booking->setResourceEmail('test@bookaarhus.local.itkdev.dk'); $booking->setStartTime(new \DateTime()); $booking->setEndTime(new \DateTime()); - $booking->setUserName('auther1'); + $booking->setUserName('author1'); $booking->setUserMail('author1@bookaarhus.local.itkdev.dk'); $booking->setMetaData([ 'meta_data_4' => '1, 2, 3', diff --git a/tests/Service/MicrosoftGraphBookingServiceTest.php b/tests/Service/MicrosoftGraphBookingServiceTest.php index 50de383..4cc8f81 100644 --- a/tests/Service/MicrosoftGraphBookingServiceTest.php +++ b/tests/Service/MicrosoftGraphBookingServiceTest.php @@ -553,4 +553,59 @@ public function testCreateBookingInviteResource(): void $this->assertEquals(400, $e->getCode()); } } + + /** + * @throws MicrosoftGraphCommunicationException + * @throws BookingCreateConflictException + */ + public function testAcceptConflict(): void + { + $microsoftGraphServiceHelperMock = $this->getMockBuilder(MicrosoftGraphHelperService::class) + ->disableOriginalConstructor() + ->onlyMethods(['isBookingConflict', 'request', 'authenticateAsServiceAccount']) + ->getMock(); + $microsoftGraphServiceHelperMock->expects($this->exactly(1))->method('isBookingConflict')->willReturn(true); + $microsoftGraphServiceHelperMock->method('authenticateAsServiceAccount')->willReturn('1234'); + + $microsoftGraphServiceHelperMock->expects($this->exactly(1))->method('request')->willReturn( + new GraphResponse( + new GraphRequest('GET', '/', '123', 'http://localhost', 'v1'), + json_encode([ + 'iCalUId' => '123', + ]), + 201, + ), + ); + + $microsoftGraphService = new MicrosoftGraphBookingService('test', 'test', $microsoftGraphServiceHelperMock); + + // Accept conflict. + $microsoftGraphService->createBookingForResource( + 'test@bookaarhus.local.itkdev.dk', + 'test resource', + 'test', + '', + new \DateTime('2040-08-18T10:00:00.000Z'), + new \DateTime('2040-08-18T12:00:00.000Z'), + true, + ); + + $exceptionCode = null; + + // Do not accept conflict. + try { + $microsoftGraphService->createBookingForResource( + 'test@bookaarhus.local.itkdev.dk', + 'test resource', + 'test', + '', + new \DateTime('2040-08-18T10:00:00.000Z'), + new \DateTime('2040-08-18T12:00:00.000Z'), + ); + } catch (BookingCreateConflictException $e) { + $exceptionCode = $e->getCode(); + } + + $this->assertEquals(409, $exceptionCode); + } }