Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 5c7c306d authored by Christoph Wurst's avatar Christoph Wurst Committed by GitHub
Browse files

Merge pull request #3635 from nextcloud/fix/appointments-daily-limit-calendar-and-property

Fix appointments daily max filter
parents 120ede5f 0340ac6d
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -64,9 +64,12 @@ class DailyLimitFilter {
		// 2. Check what days are bookable
		/** @var CalendarQuery $query */
		$query = $this->calendarManger->newQuery($config->getPrincipalUri());
		$query->addSearchCalendar($config->getTargetCalendarUri());
		$query->addSearchProperty('X-NC-APPOINTMENT');
		$query->setSearchPattern($config->getToken());
		// Note: the query is not limited to the target calendar so that the user can
		//         1. Move the event to another calendar
		//         2. Update the config to write to another calendar
		//       Also, the CalDAV back-end currently only indexes some event properties
		//       and our X-* property isn't one of them. Therefore we have to do the
		//       filtering in PHP rather than on the DB.
		$available = [];
		foreach ($days as $ts => $day) {
			$nextDay = $day->modify('+1 day');
@@ -75,8 +78,14 @@ class DailyLimitFilter {

			$events = $this->calendarManger->searchForPrincipal($query);

			$eventsOfSameAppointment = array_filter($events, function(array $event) use ($config) {
				$appointmentToken = $event['objects'][0]['X-NC-APPOINTMENT'][0][0] ?? null;

				return $config->getToken() === $appointmentToken;
			});

			// Only days with less than the max number are still available
			$available[$ts] = count($events) < $config->getDailyMax();
			$available[$ts] = count($eventsOfSameAppointment) < $config->getDailyMax();
		}

		// 3. Filter out the slots that are on an unavailable day
+62 −3
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ class DailyLimitFilterTest extends TestCase {

	public function testNoFilteringRequired(): void {
		$config = new AppointmentConfig();
		$config->setDailyMax(0);
		$config->setDailyMax(null);
		$slots = [
			new Interval(0, 100),
		];
@@ -63,6 +63,43 @@ class DailyLimitFilterTest extends TestCase {
		self::assertSame($slots, $filtered);
	}

	public function testOneOtherEventButUnrelated(): void {
		$config = new AppointmentConfig();
		$config->setDailyMax(1);
		$config->setUserId('user1');
		$config->setTargetCalendarUri('personal');
		$config->setToken('abc123');
		$slots = [
			new Interval(0, 100),
		];
		$query = $this->createMock(ICalendarQuery::class);
		$this->manager->expects(self::once())
			->method('newQuery')
			->with('principals/users/user1')
			->willReturn($query);
		$this->manager->expects(self::once())
			->method('searchForPrincipal')
			->with($query)
			->willReturn([
				[
					'UID' => 'abc',
					'objects' => [
						0 => [
							'X-NC-APPOINTMENT' => [
								0 => [
									0 => 'somethingelse',
								],
							],
						],
					],
				]
			]);

		$filtered = $this->filter->filter($config, $slots);

		self::assertSame($slots, $filtered);
	}

	public function testOneNotAvailable(): void {
		$config = new AppointmentConfig();
		$config->setDailyMax(1);
@@ -81,7 +118,18 @@ class DailyLimitFilterTest extends TestCase {
			->method('searchForPrincipal')
			->with($query)
			->willReturn([
				['UID' => 'abc']
				[
					'UID' => 'abc',
					'objects' => [
						0 => [
							'X-NC-APPOINTMENT' => [
								0 => [
									0 => 'abc123',
								],
							],
						],
					],
				]
			]);

		$filtered = $this->filter->filter($config, $slots);
@@ -111,7 +159,18 @@ class DailyLimitFilterTest extends TestCase {
			->with($query)
			->willReturnOnConsecutiveCalls(
				[
					['UID' => 'abc']
					[
						'UID' => 'abc',
						'objects' => [
							0 => [
								'X-NC-APPOINTMENT' => [
									0 => [
										0 => 'abc123',
									],
								],
							],
						],
					],
				],
				[],
			);