aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Citharel <tcit@tcit.fr>2025-05-23 10:53:02 +0200
committerSebastianKrupinski <krupinskis05@gmail.com>2025-07-04 10:30:56 -0400
commite401fe5bc9ce22d94273f729c516b70f2322d83d (patch)
treebcb0f3562c0a8e67064b41f0d582aa179caa35f2
parent927beefae2a79882dbe89ed643689bb6ee033edb (diff)
downloadnextcloud-server-introduce-publish-classification-levels.tar.gz
nextcloud-server-introduce-publish-classification-levels.zip
feat(dav): add custom classification levels for events in public calendarsintroduce-publish-classification-levels
The CLASS:PRIVATE and CLASS:CONFIDENTIAL apply to events shared as well as published ones. This adds two new custom CLASS values: X-NEXTCLOUD-CLASS-PUBLISHED-PRIVATE and X-NEXTCLOUD-CLASS-PUBLISHED-CONFIDENTIAL, which work the same as the standard values, but only when they are published into a public calendar. Therefore, you can set an event to be public (fully visible) for people who you shared internally the event's calendar, but private when the calendar is published. Signed-off-by: Thomas Citharel <tcit@tcit.fr>
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php18
-rw-r--r--apps/dav/lib/CalDAV/CalendarObject.php6
-rw-r--r--apps/dav/lib/CalDAV/PublicCalendar.php18
-rw-r--r--apps/dav/lib/CalDAV/PublicCalendarObject.php27
-rw-r--r--apps/dav/tests/unit/CalDAV/CalDavBackendTest.php4
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarTest.php55
-rw-r--r--apps/dav/tests/unit/CalDAV/PublicCalendarTest.php65
7 files changed, 144 insertions, 49 deletions
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 27750913105..7d7dea86600 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -131,6 +131,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
public const CLASSIFICATION_PUBLIC = 0;
public const CLASSIFICATION_PRIVATE = 1;
public const CLASSIFICATION_CONFIDENTIAL = 2;
+ public const CLASSIFICATION_PUBLISHED_PRIVATE = 3;
+ public const CLASSIFICATION_PUBLISHED_CONFIDENTIAL = 4;
/**
* List of CalDAV properties, and how they map to database field names and their type
@@ -3133,15 +3135,13 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
if ($component->CLASS) {
- $classification = CalDavBackend::CLASSIFICATION_PRIVATE;
- switch ($component->CLASS->getValue()) {
- case 'PUBLIC':
- $classification = CalDavBackend::CLASSIFICATION_PUBLIC;
- break;
- case 'CONFIDENTIAL':
- $classification = CalDavBackend::CLASSIFICATION_CONFIDENTIAL;
- break;
- }
+ $classification = match ($component->CLASS->getValue()) {
+ 'PUBLIC' => CalDavBackend::CLASSIFICATION_PUBLIC,
+ 'CONFIDENTIAL' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL,
+ 'X-NEXTCLOUD-CLASS-PUBLISHED-PRIVATE' => CalDavBackend::CLASSIFICATION_PUBLISHED_PRIVATE,
+ 'X-NEXTCLOUD-CLASS-PUBLISHED-CONFIDENTIAL' => CalDavBackend::CLASSIFICATION_PUBLISHED_CONFIDENTIAL,
+ default => CalDavBackend::CLASSIFICATION_PRIVATE,
+ };
}
return [
'etag' => md5($calendarData),
diff --git a/apps/dav/lib/CalDAV/CalendarObject.php b/apps/dav/lib/CalDAV/CalendarObject.php
index 02178b4236f..253f85e88e3 100644
--- a/apps/dav/lib/CalDAV/CalendarObject.php
+++ b/apps/dav/lib/CalDAV/CalendarObject.php
@@ -76,7 +76,7 @@ class CalendarObject extends \Sabre\CalDAV\CalendarObject {
* @param Component\VCalendar $vObject
* @return void
*/
- private function createConfidentialObject(Component\VCalendar $vObject): void {
+ protected function createConfidentialObject(Component\VCalendar $vObject): void {
/** @var Component $vElement */
$vElements = array_filter($vObject->getComponents(), static function ($vElement) {
return $vElement instanceof Component\VEvent || $vElement instanceof Component\VJournal || $vElement instanceof Component\VTodo;
@@ -117,7 +117,7 @@ class CalendarObject extends \Sabre\CalDAV\CalendarObject {
* @param Component\VCalendar $vObject
* @return void
*/
- private function removeVAlarms(Component\VCalendar $vObject) {
+ protected function removeVAlarms(Component\VCalendar $vObject) {
$subcomponents = $vObject->getComponents();
foreach ($subcomponents as $subcomponent) {
@@ -128,7 +128,7 @@ class CalendarObject extends \Sabre\CalDAV\CalendarObject {
/**
* @return bool
*/
- private function canWrite() {
+ protected function canWrite() {
if (isset($this->calendarInfo['{http://owncloud.org/ns}read-only'])) {
return !$this->calendarInfo['{http://owncloud.org/ns}read-only'];
}
diff --git a/apps/dav/lib/CalDAV/PublicCalendar.php b/apps/dav/lib/CalDAV/PublicCalendar.php
index 9af6e544165..2697861c23f 100644
--- a/apps/dav/lib/CalDAV/PublicCalendar.php
+++ b/apps/dav/lib/CalDAV/PublicCalendar.php
@@ -21,7 +21,7 @@ class PublicCalendar extends Calendar {
if (!$obj) {
throw new NotFound('Calendar object not found');
}
- if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
+ if (in_array($obj['classification'], [CalDavBackend::CLASSIFICATION_PRIVATE, CalDavBackend::CLASSIFICATION_PUBLISHED_PRIVATE], true)) {
throw new NotFound('Calendar object not found');
}
$obj['acl'] = $this->getChildACL();
@@ -36,7 +36,7 @@ class PublicCalendar extends Calendar {
$objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']);
$children = [];
foreach ($objs as $obj) {
- if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
+ if (in_array($obj['classification'], [CalDavBackend::CLASSIFICATION_PRIVATE, CalDavBackend::CLASSIFICATION_PUBLISHED_PRIVATE], true)) {
continue;
}
$obj['acl'] = $this->getChildACL();
@@ -53,7 +53,7 @@ class PublicCalendar extends Calendar {
$objs = $this->caldavBackend->getMultipleCalendarObjects($this->calendarInfo['id'], $paths);
$children = [];
foreach ($objs as $obj) {
- if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
+ if (in_array($obj['classification'], [CalDavBackend::CLASSIFICATION_PRIVATE, CalDavBackend::CLASSIFICATION_PUBLISHED_PRIVATE], true)) {
continue;
}
$obj['acl'] = $this->getChildACL();
@@ -62,6 +62,18 @@ class PublicCalendar extends Calendar {
return $children;
}
+ public function childExists($name) {
+ $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
+ if (!$obj) {
+ return false;
+ }
+ if (in_array($obj['classification'], [CalDavBackend::CLASSIFICATION_PRIVATE, CalDavBackend::CLASSIFICATION_PUBLISHED_PRIVATE], true) && $this->isShared()) {
+ return false;
+ }
+
+ return true;
+ }
+
/**
* public calendars are always shared
* @return bool
diff --git a/apps/dav/lib/CalDAV/PublicCalendarObject.php b/apps/dav/lib/CalDAV/PublicCalendarObject.php
index 2ab40b94347..40eefc35600 100644
--- a/apps/dav/lib/CalDAV/PublicCalendarObject.php
+++ b/apps/dav/lib/CalDAV/PublicCalendarObject.php
@@ -6,9 +6,36 @@
*/
namespace OCA\DAV\CalDAV;
+use Sabre\VObject\Reader;
+
class PublicCalendarObject extends CalendarObject {
/**
+ * @inheritdoc
+ */
+ public function get() {
+ $data = parent::get();
+
+ if (!$this->isShared()) {
+ return $data;
+ }
+
+ $vObject = Reader::read($data);
+
+ // remove VAlarms if calendar is shared read-only
+ if (!$this->canWrite()) {
+ $this->removeVAlarms($vObject);
+ }
+
+ // shows as busy if event is declared confidential or external confidential
+ if (in_array($this->objectData['classification'], [CalDavBackend::CLASSIFICATION_CONFIDENTIAL, CalDavBackend::CLASSIFICATION_PUBLISHED_CONFIDENTIAL], true)) {
+ $this->createConfidentialObject($vObject);
+ }
+
+ return $vObject->serialize();
+ }
+
+ /**
* public calendars are always shared
* @return bool
*/
diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
index f9205d5d322..33211e8e52d 100644
--- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
@@ -736,6 +736,10 @@ EOS;
'CLASS:CONFIDENTIAL' => [CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:CONFIDENTIAL\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
+ 'CLASS:X-NEXTCLOUD-CLASS-PUBLISHED-PRIVATE' => [CalDavBackend::CLASSIFICATION_PUBLISHED_PRIVATE, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:X-NEXTCLOUD-CLASS-PUBLISHED-PRIVATE\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
+
+ 'CLASS:X-NEXTCLOUD-CLASS-PUBLISHED-CONFIDENTIAL' => [CalDavBackend::CLASSIFICATION_PUBLISHED_CONFIDENTIAL, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:X-NEXTCLOUD-CLASS-PUBLISHED-CONFIDENTIAL\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
+
'no class set -> public' => [CalDavBackend::CLASSIFICATION_PUBLIC, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nTRANSP:OPAQUE\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
'unknown class -> private' => [CalDavBackend::CLASSIFICATION_PRIVATE, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:VERTRAULICH\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"],
diff --git a/apps/dav/tests/unit/CalDAV/CalendarTest.php b/apps/dav/tests/unit/CalDAV/CalendarTest.php
index b0d3c35bfe7..d6f91af8fa4 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarTest.php
@@ -271,19 +271,26 @@ class CalendarTest extends TestCase {
$calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC];
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
+ $calObject3 = ['uri' => 'event-3', 'classification' => CalDavBackend::CLASSIFICATION_PUBLISHED_PRIVATE];
+ $calObject4 = ['uri' => 'event-4', 'classification' => CalDavBackend::CLASSIFICATION_PUBLISHED_CONFIDENTIAL];
/** @var CalDavBackend&MockObject $backend */
$backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
- $calObject0, $calObject1, $calObject2
+ $calObject0, $calObject1, $calObject2, $calObject3, $calObject4
]);
$backend->expects($this->any())->method('getMultipleCalendarObjects')
- ->with(666, ['event-0', 'event-1', 'event-2'])
+ ->with(666, ['event-0', 'event-1', 'event-2', 'event-3', 'event-4'])
->willReturn([
- $calObject0, $calObject1, $calObject2
+ $calObject0, $calObject1, $calObject2, $calObject3, $calObject4
]);
- $backend->expects($this->any())->method('getCalendarObject')
- ->willReturn($calObject2)->with(666, 'event-2');
+ $matcher = $this->exactly(2);
+ $backend->expects($matcher)->method('getCalendarObject')
+ ->willReturnCallback(fn (int $key, string $uri) =>
+ match ([$key, $uri]) {
+ [666, 'event-2'] => $calObject2,
+ [666, 'event-3'] => $calObject3,
+ });
$backend->expects($this->any())->method('applyShareAcl')->willReturnArgument(1);
$calendarInfo = [
@@ -297,11 +304,12 @@ class CalendarTest extends TestCase {
}
$c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config, $this->logger);
$children = $c->getChildren();
- $this->assertEquals($expectedChildren, count($children));
- $children = $c->getMultipleChildren(['event-0', 'event-1', 'event-2']);
- $this->assertEquals($expectedChildren, count($children));
+ $this->assertCount($expectedChildren, $children);
+ $children = $c->getMultipleChildren(['event-0', 'event-1', 'event-2', 'event-3', 'event-4']);
+ $this->assertCount($expectedChildren, $children);
$this->assertEquals(!$isShared, $c->childExists('event-2'));
+ $this->assertTrue($c->childExists('event-3'));
}
#[\PHPUnit\Framework\Attributes\DataProvider('providesConfidentialClassificationData')]
@@ -354,19 +362,26 @@ EOD;
$calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC];
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'calendardata' => $calData];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
+ $calObject3 = ['uri' => 'event-3', 'classification' => CalDavBackend::CLASSIFICATION_PUBLISHED_CONFIDENTIAL, 'calendardata' => $calData];
+ $calObject4 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PUBLISHED_PRIVATE];
/** @var CalDavBackend&MockObject $backend */
$backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
- $calObject0, $calObject1, $calObject2
+ $calObject0, $calObject1, $calObject2, $calObject3, $calObject4
]);
$backend->expects($this->any())->method('getMultipleCalendarObjects')
- ->with(666, ['event-0', 'event-1', 'event-2'])
+ ->with(666, ['event-0', 'event-1', 'event-2', 'event-3', 'event-4'])
->willReturn([
- $calObject0, $calObject1, $calObject2
+ $calObject0, $calObject1, $calObject2, $calObject3, $calObject4
]);
- $backend->expects($this->any())->method('getCalendarObject')
- ->willReturn($calObject1)->with(666, 'event-1');
+ $matcher = $this->exactly(3);
+ $backend->expects($matcher)->method('getCalendarObject')
+ ->willReturnCallback(fn (int $key, string $uri) =>
+ match ([$key, $uri]) {
+ [666, 'event-1'] => $calObject1,
+ [666, 'event-3'] => $calObject3,
+ });
$backend->expects($this->any())->method('applyShareAcl')->willReturnArgument(1);
$calendarInfo = [
@@ -377,7 +392,7 @@ EOD;
];
$c = new Calendar($backend, $calendarInfo, $this->l10n, $this->config, $this->logger);
- $this->assertEquals(count($c->getChildren()), $expectedChildren);
+ $this->assertCount($expectedChildren, $c->getChildren());
// test private event
$privateEvent = $c->getChild('event-1');
@@ -397,6 +412,14 @@ EOD;
$this->assertEquals('Test Event', $event->VEVENT->SUMMARY->getValue());
}
+ // test published private event
+ $publishedPrivateEvent = $c->getChild('event-3');
+ $publishedCalData = $publishedPrivateEvent->get();
+ $publishedEvent = Reader::read($publishedCalData);
+
+ $this->assertNotEquals('Busy', $publishedEvent->VEVENT->SUMMARY->getValue());
+ $this->assertEquals('Test Event', $publishedEvent->VEVENT->SUMMARY->getValue());
+
// Test l10n
$l10n = $this->createMock(IL10N::class);
if ($isShared) {
@@ -422,8 +445,8 @@ EOD;
public static function providesConfidentialClassificationData(): array {
return [
- [3, false],
- [2, true]
+ [5, false],
+ [4, true]
];
}
diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
index 98153a067fb..b2489f5dc0b 100644
--- a/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
@@ -17,23 +17,30 @@ use Sabre\VObject\Reader;
class PublicCalendarTest extends CalendarTest {
#[\PHPUnit\Framework\Attributes\DataProvider('providesConfidentialClassificationData')]
- public function testPrivateClassification(int $expectedChildren, bool $isShared): void {
+ public function testPrivateClassification(int int $expectedChildren, bool bool $isShared): void {
$calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC];
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
+ $calObject3 = ['uri' => 'event-3', 'classification' => CalDavBackend::CLASSIFICATION_PUBLISHED_PRIVATE];
+ $calObject4 = ['uri' => 'event-4', 'classification' => CalDavBackend::CLASSIFICATION_PUBLISHED_CONFIDENTIAL];
- /** @var CalDavBackend&MockObject $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
+ /** @var MockObject | CalDavBackend $backend */
+ $backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
- $calObject0, $calObject1, $calObject2
+ $calObject0, $calObject1, $calObject2, $calObject3, $calObject4
]);
$backend->expects($this->any())->method('getMultipleCalendarObjects')
- ->with(666, ['event-0', 'event-1', 'event-2'])
+ ->with(666, ['event-0', 'event-1', 'event-2', 'event-3', 'event-4'])
->willReturn([
- $calObject0, $calObject1, $calObject2
+ $calObject0, $calObject1, $calObject2, $calObject3, $calObject4
]);
- $backend->expects($this->any())->method('getCalendarObject')
- ->willReturn($calObject2)->with(666, 'event-2');
+ $matcher = $this->exactly(2);
+ $backend->expects($matcher)->method('getCalendarObject')
+ ->willReturnCallback(fn (int $key, string $uri) =>
+ match ([$key, $uri]) {
+ [666, 'event-2'] => $calObject2,
+ [666, 'event-3'] => $calObject3,
+ });
$backend->expects($this->any())->method('applyShareAcl')->willReturnArgument(1);
$calendarInfo = [
@@ -48,15 +55,16 @@ class PublicCalendarTest extends CalendarTest {
$logger = $this->createMock(LoggerInterface::class);
$c = new PublicCalendar($backend, $calendarInfo, $this->l10n, $config, $logger);
$children = $c->getChildren();
- $this->assertEquals(2, count($children));
- $children = $c->getMultipleChildren(['event-0', 'event-1', 'event-2']);
- $this->assertEquals(2, count($children));
+ $this->assertEquals(3, count($children));
+ $children = $c->getMultipleChildren(['event-0', 'event-1', 'event-2', 'event-3', 'event-4']);
+ $this->assertEquals(3, count($children));
$this->assertFalse($c->childExists('event-2'));
+ $this->assertFalse($c->childExists('event-3'));
}
#[\PHPUnit\Framework\Attributes\DataProvider('providesConfidentialClassificationData')]
- public function testConfidentialClassification(int $expectedChildren, bool $isShared): void {
+ public function testConfidentialClassification(int int $expectedChildren, bool bool $isShared): void {
$start = '20160609';
$end = '20160610';
@@ -105,19 +113,26 @@ EOD;
$calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC];
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'calendardata' => $calData];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
+ $calObject3 = ['uri' => 'event-3', 'classification' => CalDavBackend::CLASSIFICATION_PUBLISHED_CONFIDENTIAL, 'calendardata' => $calData];
+ $calObject4 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PUBLISHED_PRIVATE];
/** @var CalDavBackend&MockObject $backend */
$backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
- $calObject0, $calObject1, $calObject2
+ $calObject0, $calObject1, $calObject2, $calObject3, $calObject4
]);
$backend->expects($this->any())->method('getMultipleCalendarObjects')
- ->with(666, ['event-0', 'event-1', 'event-2'])
+ ->with(666, ['event-0', 'event-1', 'event-2', 'event-3', 'event-4'])
->willReturn([
- $calObject0, $calObject1, $calObject2
+ $calObject0, $calObject1, $calObject2, $calObject3, $calObject4
]);
- $backend->expects($this->any())->method('getCalendarObject')
- ->willReturn($calObject1)->with(666, 'event-1');
+ $matcher = $this->exactly(2);
+ $backend->expects($matcher)->method('getCalendarObject')
+ ->willReturnCallback(fn (int $key, string $uri) =>
+ match ([$key, $uri]) {
+ [666, 'event-1'] => $calObject1,
+ [666, 'event-3'] => $calObject3,
+ });
$backend->expects($this->any())->method('applyShareAcl')->willReturnArgument(1);
$calendarInfo = [
@@ -132,7 +147,7 @@ EOD;
$logger = $this->createMock(LoggerInterface::class);
$c = new PublicCalendar($backend, $calendarInfo, $this->l10n, $config, $logger);
- $this->assertEquals(count($c->getChildren()), 2);
+ $this->assertCount(3, $c->getChildren());
// test private event
$privateEvent = $c->getChild('event-1');
@@ -147,5 +162,19 @@ EOD;
$this->assertArrayNotHasKey('LOCATION', $event->VEVENT);
$this->assertArrayNotHasKey('DESCRIPTION', $event->VEVENT);
$this->assertArrayNotHasKey('ORGANIZER', $event->VEVENT);
+
+ // test published private event
+ $privateEvent = $c->getChild('event-3');
+ $calData = $privateEvent->get();
+ $event = Reader::read($calData);
+
+ $this->assertEquals($start, $event->VEVENT->DTSTART->getValue());
+ $this->assertEquals($end, $event->VEVENT->DTEND->getValue());
+
+ $this->assertEquals('Busy', $event->VEVENT->SUMMARY->getValue());
+ $this->assertArrayNotHasKey('ATTENDEE', $event->VEVENT);
+ $this->assertArrayNotHasKey('LOCATION', $event->VEVENT);
+ $this->assertArrayNotHasKey('DESCRIPTION', $event->VEVENT);
+ $this->assertArrayNotHasKey('ORGANIZER', $event->VEVENT);
}
}