Skip to content

Commit

Permalink
fixup! fix: override iTip Broker to fix several issues
Browse files Browse the repository at this point in the history
Signed-off-by: SebastianKrupinski <[email protected]>
  • Loading branch information
SebastianKrupinski committed Oct 21, 2024
1 parent b932df3 commit 21dd4fe
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 1 deletion.
2 changes: 1 addition & 1 deletion apps/dav/lib/CalDAV/TipBroker.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo,

$message->significantChange =
$attendee['forceSend'] === 'REQUEST' ||
count($oldAttendeeInstances) != count($newAttendeeInstances) ||
count($oldAttendeeInstances) !== count($newAttendeeInstances) ||
count(array_diff($oldAttendeeInstances, $newAttendeeInstances)) > 0 ||
$oldEventInfo['significantChangeHash'] !== $eventInfo['significantChangeHash'];

Expand Down
185 changes: 185 additions & 0 deletions apps/dav/tests/unit/CalDAV/TipBrokerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
<?php
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\Tests\unit\CalDAV;

use OCA\DAV\CalDAV\TipBroker;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\ITip\ITipException;
use Sabre\VObject\ITip\SameOrganizerForAllComponentsException;
use Test\TestCase;

class TipBrokerTest extends TestCase {

private TipBroker $broker;
private VCalendar $vCalendar1a;

protected function setUp(): void {
parent::setUp();

$this->broker = new TipBroker();
// construct calendar with a 1 hour event and same start/end time zones
$this->vCalendar1a = new VCalendar();
/** @var VEvent $vEvent */
$vEvent = $this->vCalendar1a->add('VEVENT', []);
$vEvent->add('UID', '96a0e6b1-d886-4a55-a60d-152b31401dcc');
$vEvent->add('DTSTAMP', '20240701T000000Z');
$vEvent->add('CREATED', '20240701T000000Z');
$vEvent->add('LAST-MODIFIED', '20240701T000000Z');
$vEvent->add('SEQUENCE', '1');
$vEvent->add('STATUS', 'CONFIRMED');
$vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
$vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
$vEvent->add('SUMMARY', 'Test Event');
$vEvent->add('ORGANIZER', 'mailto:[email protected]', ['CN' => 'Organizer']);
$vEvent->add('ATTENDEE', 'mailto:[email protected]', [
'CN' => 'Attendee One',
'CUTYPE' => 'INDIVIDUAL',
'PARTSTAT' => 'NEEDS-ACTION',
'ROLE' => 'REQ-PARTICIPANT',
'RSVP' => 'TRUE'
]);
}

public function testParseEventForOrganizerOnCreate(): void {

// construct calendar and generate event info for newly created event with one attendee
$calendar = clone $this->vCalendar1a;
$previousEventInfo = [
'organizer' => null,
'significantChangeHash' => '',
'attendees' => [],
];
$currentEventInfo = $this->callMethod($this->broker, 'parseEventInfo', [$calendar]);
// test iTip generation
$messages = $this->callMethod($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
$this->assertCount(1, $messages);
$this->assertEquals('REQUEST', $messages[0]->method);
$this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
$this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);

}

public function testParseEventForOrganizerOnModify(): void {

// construct calendar and generate event info for modified event with one attendee
$calendar = clone $this->vCalendar1a;
$previousEventInfo = $this->callMethod($this->broker, 'parseEventInfo', [$calendar]);
$calendar->VEVENT->{'LAST-MODIFIED'}->setValue('20240701T020000Z');
$calendar->VEVENT->SEQUENCE->setValue(2);
$calendar->VEVENT->SUMMARY->setValue('Test Event Modified');
$currentEventInfo = $this->callMethod($this->broker, 'parseEventInfo', [$calendar]);
// test iTip generation
$messages = $this->callMethod($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
$this->assertCount(1, $messages);
$this->assertEquals('REQUEST', $messages[0]->method);
$this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
$this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);

}

public function testParseEventForOrganizerOnDelete(): void {

// construct calendar and generate event info for modified event with one attendee
$calendar = clone $this->vCalendar1a;
$previousEventInfo = $this->callMethod($this->broker, 'parseEventInfo', [$calendar]);
$currentEventInfo = $previousEventInfo;
$currentEventInfo['attendees'] = [];
++$currentEventInfo['sequence'];
// test iTip generation
$messages = $this->callMethod($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
$this->assertCount(1, $messages);
$this->assertEquals('CANCEL', $messages[0]->method);
$this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
$this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);

}

public function testParseEventForOrganizerOnStatusCancelled(): void {

// construct calendar and generate event info for modified event with one attendee
$calendar = clone $this->vCalendar1a;
$previousEventInfo = $this->callMethod($this->broker, 'parseEventInfo', [$calendar]);
$calendar->VEVENT->{'LAST-MODIFIED'}->setValue('20240701T020000Z');
$calendar->VEVENT->SEQUENCE->setValue(2);
$calendar->VEVENT->STATUS->setValue('CANCELLED');
$currentEventInfo = $this->callMethod($this->broker, 'parseEventInfo', [$calendar]);
// test iTip generation
$messages = $this->callMethod($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
$this->assertCount(1, $messages);
$this->assertEquals('CANCEL', $messages[0]->method);
$this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
$this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);

}

public function testParseEventForOrganizerOnAddAttendee(): void {

// construct calendar and generate event info for modified event with two attendees
$calendar = clone $this->vCalendar1a;
$previousEventInfo = $this->callMethod($this->broker, 'parseEventInfo', [$calendar]);
$calendar->VEVENT->{'LAST-MODIFIED'}->setValue('20240701T020000Z');
$calendar->VEVENT->SEQUENCE->setValue(2);
$calendar->VEVENT->add('ATTENDEE', 'mailto:[email protected]', [
'CN' => 'Attendee Two',
'CUTYPE' => 'INDIVIDUAL',
'PARTSTAT' => 'NEEDS-ACTION',
'ROLE' => 'REQ-PARTICIPANT',
'RSVP' => 'TRUE'
]);
$currentEventInfo = $this->callMethod($this->broker, 'parseEventInfo', [$calendar]);
// test iTip generation
$messages = $this->callMethod($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
$this->assertCount(2, $messages);
$this->assertEquals('REQUEST', $messages[0]->method);
$this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
$this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);
$this->assertEquals('REQUEST', $messages[1]->method);
$this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[1]->sender);
$this->assertEquals($calendar->VEVENT->ATTENDEE[1]->getValue(), $messages[1]->recipient);

}

public function testParseEventForOrganizerOnRemoveAttendee(): void {

// construct calendar and generate event info for modified event with two attendees
$calendar = clone $this->vCalendar1a;
$calendar->VEVENT->add('ATTENDEE', 'mailto:[email protected]', [
'CN' => 'Attendee Two',
'CUTYPE' => 'INDIVIDUAL',
'PARTSTAT' => 'NEEDS-ACTION',
'ROLE' => 'REQ-PARTICIPANT',
'RSVP' => 'TRUE'
]);
$previousEventInfo = $this->callMethod($this->broker, 'parseEventInfo', [$calendar]);
$calendar->VEVENT->{'LAST-MODIFIED'}->setValue('20240701T020000Z');
$calendar->VEVENT->SEQUENCE->setValue(2);
$calendar->VEVENT->remove('ATTENDEE');
$calendar->VEVENT->add('ATTENDEE', 'mailto:[email protected]', [
'CN' => 'Attendee One',
'CUTYPE' => 'INDIVIDUAL',
'PARTSTAT' => 'NEEDS-ACTION',
'ROLE' => 'REQ-PARTICIPANT',
'RSVP' => 'TRUE'
]);
$currentEventInfo = $this->callMethod($this->broker, 'parseEventInfo', [$calendar]);
// test iTip generation
$messages = $this->callMethod($this->broker, 'parseEventForOrganizer', [$calendar, $currentEventInfo, $previousEventInfo]);
$this->assertCount(2, $messages);
$this->assertEquals('REQUEST', $messages[0]->method);
$this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[0]->sender);
$this->assertEquals($calendar->VEVENT->ATTENDEE[0]->getValue(), $messages[0]->recipient);
$this->assertEquals('CANCEL', $messages[1]->method);
$this->assertEquals($calendar->VEVENT->ORGANIZER->getValue(), $messages[1]->sender);
$this->assertEquals('mailto:[email protected]', $messages[1]->recipient);

}

public static function callMethod($obj, $name, array $args) {
$class = new \ReflectionClass($obj);
$method = $class->getMethod($name);
return $method->invokeArgs($obj, $args);
}
}

0 comments on commit 21dd4fe

Please sign in to comment.