Allow apps to provide Calendars in user's calendarHome

Signed-off-by: Georg Ehrke <developer@georgehrke.com>
pull/19196/head
Georg Ehrke 4 years ago
parent a1fc233fcb
commit b46e5cb270
No known key found for this signature in database
GPG Key ID: 9D98FD9380A1CB43

@ -42,6 +42,8 @@ return array(
'OCA\\DAV\\CalDAV\\CalendarObject' => $baseDir . '/../lib/CalDAV/CalendarObject.php',
'OCA\\DAV\\CalDAV\\CalendarRoot' => $baseDir . '/../lib/CalDAV/CalendarRoot.php',
'OCA\\DAV\\CalDAV\\ICSExportPlugin\\ICSExportPlugin' => $baseDir . '/../lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php',
'OCA\\DAV\\CalDAV\\Integration\\ExternalCalendar' => $baseDir . '/../lib/CalDAV/Integration/ExternalCalendar.php',
'OCA\\DAV\\CalDAV\\Integration\\ICalendarProvider' => $baseDir . '/../lib/CalDAV/Integration/ICalendarProvider.php',
'OCA\\DAV\\CalDAV\\InvitationResponse\\InvitationResponseServer' => $baseDir . '/../lib/CalDAV/InvitationResponse/InvitationResponseServer.php',
'OCA\\DAV\\CalDAV\\Outbox' => $baseDir . '/../lib/CalDAV/Outbox.php',
'OCA\\DAV\\CalDAV\\Plugin' => $baseDir . '/../lib/CalDAV/Plugin.php',

@ -57,6 +57,8 @@ class ComposerStaticInitDAV
'OCA\\DAV\\CalDAV\\CalendarObject' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarObject.php',
'OCA\\DAV\\CalDAV\\CalendarRoot' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarRoot.php',
'OCA\\DAV\\CalDAV\\ICSExportPlugin\\ICSExportPlugin' => __DIR__ . '/..' . '/../lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php',
'OCA\\DAV\\CalDAV\\Integration\\ExternalCalendar' => __DIR__ . '/..' . '/../lib/CalDAV/Integration/ExternalCalendar.php',
'OCA\\DAV\\CalDAV\\Integration\\ICalendarProvider' => __DIR__ . '/..' . '/../lib/CalDAV/Integration/ICalendarProvider.php',
'OCA\\DAV\\CalDAV\\InvitationResponse\\InvitationResponseServer' => __DIR__ . '/..' . '/../lib/CalDAV/InvitationResponse/InvitationResponseServer.php',
'OCA\\DAV\\CalDAV\\Outbox' => __DIR__ . '/..' . '/../lib/CalDAV/Outbox.php',
'OCA\\DAV\\CalDAV\\Plugin' => __DIR__ . '/..' . '/../lib/CalDAV/Plugin.php',

@ -25,6 +25,7 @@
namespace OCA\DAV\AppInfo;
use OC\ServerContainer;
use OCA\DAV\CalDAV\Integration\ICalendarProvider;
use OCP\App\IAppManager;
use OCP\AppFramework\QueryException;
@ -58,6 +59,13 @@ class PluginManager {
*/
private $collections = null;
/**
* Calendar plugins
*
* @var array
*/
private $calendarPlugins = null;
/**
* Contstruct a PluginManager
*
@ -93,11 +101,24 @@ class PluginManager {
return $this->collections;
}
/**
* Returns an array of app-registered calendar plugins
*
* @return array
*/
public function getCalendarPlugins():array {
if (null === $this->calendarPlugins) {
$this->populate();
}
return $this->calendarPlugins;
}
/**
* Retrieve plugin and collection list and populate attributes
*/
private function populate() {
$this->plugins = [];
$this->calendarPlugins = [];
$this->collections = [];
foreach ($this->appManager->getInstalledApps() as $app) {
// load plugins and collections from info.xml
@ -107,6 +128,7 @@ class PluginManager {
}
$this->loadSabrePluginsFromInfoXml($this->extractPluginList($info));
$this->loadSabreCollectionsFromInfoXml($this->extractCollectionList($info));
$this->loadSabreCalendarPluginsFromInfoXml($this->extractCalendarPluginList($info));
}
}
@ -140,6 +162,21 @@ class PluginManager {
return [];
}
private function extractCalendarPluginList(array $array):array {
if (isset($array['sabre']) && is_array($array['sabre'])) {
if (isset($array['sabre']['calendar-plugins']) && is_array($array['sabre']['calendar-plugins'])) {
if (isset($array['sabre']['calendar-plugins']['plugin'])) {
$items = $array['sabre']['calendar-plugins']['plugin'];
if (!is_array($items)) {
$items = [$items];
}
return $items;
}
}
}
return [];
}
private function loadSabrePluginsFromInfoXml(array $plugins) {
foreach ($plugins as $plugin) {
try {
@ -168,4 +205,24 @@ class PluginManager {
}
}
private function loadSabreCalendarPluginsFromInfoXml(array $calendarPlugins):void {
foreach ($calendarPlugins as $calendarPlugin) {
try {
$instantiatedCalendarPlugin = $this->container->query($calendarPlugin);
} catch (QueryException $e) {
if (class_exists($calendarPlugin)) {
$instantiatedCalendarPlugin = new $calendarPlugin();
} else {
throw new \Exception("Sabre calendar-plugin class '$calendarPlugin' is unknown and could not be loaded");
}
}
if (!($instantiatedCalendarPlugin instanceof ICalendarProvider)) {
throw new \Exception("Sabre calendar-plugin class '$calendarPlugin' does not implement ICalendarProvider interface");
}
$this->calendarPlugins[] = $instantiatedCalendarPlugin;
}
}
}

@ -26,6 +26,9 @@
namespace OCA\DAV\CalDAV;
use OCA\DAV\AppInfo\PluginManager;
use OCA\DAV\CalDAV\Integration\ExternalCalendar;
use OCA\DAV\CalDAV\Integration\ICalendarProvider;
use Sabre\CalDAV\Backend\BackendInterface;
use Sabre\CalDAV\Backend\NotificationSupport;
use Sabre\CalDAV\Backend\SchedulingSupport;
@ -44,6 +47,9 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
/** @var \OCP\IConfig */
private $config;
/** @var PluginManager */
private $pluginManager;
/** @var bool */
private $returnCachedSubscriptions=false;
@ -51,6 +57,10 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
parent::__construct($caldavBackend, $principalInfo);
$this->l10n = \OC::$server->getL10N('dav');
$this->config = \OC::$server->getConfig();
$this->pluginManager = new PluginManager(
\OC::$server,
\OC::$server->getAppManager()
);
}
/**
@ -66,7 +76,7 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
function createExtendedCollection($name, MkCol $mkCol) {
$reservedNames = [BirthdayService::BIRTHDAY_CALENDAR_URI];
if (in_array($name, $reservedNames)) {
if (\in_array($name, $reservedNames, true) || ExternalCalendar::doesViolateReservedName($name)) {
throw new MethodNotAllowed('The resource you tried to create has a reserved name');
}
@ -104,6 +114,14 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
}
}
foreach ($this->pluginManager->getCalendarPlugins() as $calendarPlugin) {
/** @var ICalendarProvider $calendarPlugin */
$calendars = $calendarPlugin->fetchAllForCalendarHome($this->principalInfo['uri']);
foreach ($calendars as $calendar) {
$objects[] = $calendar;
}
}
return $objects;
}
@ -139,7 +157,21 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
return new Subscription($this->caldavBackend, $subscription);
}
}
}
if (ExternalCalendar::isAppGeneratedCalendar($name)) {
[$appId, $calendarUri] = ExternalCalendar::splitAppGeneratedCalendarUri($name);
foreach ($this->pluginManager->getCalendarPlugins() as $calendarPlugin) {
/** @var ICalendarProvider $calendarPlugin */
if ($calendarPlugin->getAppId() !== $appId) {
continue;
}
if ($calendarPlugin->hasCalendarInCalendarHome($this->principalInfo['uri'], $calendarUri)) {
return $calendarPlugin->getCalendarInCalendarHome($this->principalInfo['uri'], $calendarUri);
}
}
}
throw new NotFound('Node with name \'' . $name . '\' could not be found');
@ -155,7 +187,7 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
return $this->caldavBackend->calendarSearch($principalUri, $filters, $limit, $offset);
}
public function enableCachedSubscriptionsForThisRequest() {
$this->returnCachedSubscriptions = true;
}

@ -0,0 +1,132 @@
<?php
/**
* @copyright 2020, Georg Ehrke <oc.list@georgehrke.com>
*
* @author Georg Ehrke <oc.list@georgehrke.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\DAV\CalDAV\Integration;
use Sabre\CalDAV;
use Sabre\DAV;
/**
* Class ExternalCalendar
*
* @package OCA\DAV\CalDAV\Integration
* @since 19.0.0
*/
abstract class ExternalCalendar implements CalDAV\ICalendar, DAV\IProperties {
/** @var string */
private const PREFIX = 'app-generated';
/**
* @var string
*
* Double dash is a valid delimiter,
* because it will always split the calendarURIs correctly:
* - our prefix contains only one dash and won't be split
* - appIds are not allowed to contain dashes as per spec:
* > must contain only lowercase ASCII characters and underscore
* - explode has a limit of three, so even if the app-generated
* calendar uri has double dashes, it won't be split
*/
private const DELIMITER = '--';
/** @var string */
private $appId;
/** @var string */
private $calendarUri;
/**
* ExternalCalendar constructor.
*
* @param string $appId
* @param string $calendarUri
*/
public function __construct(string $appId, string $calendarUri) {
$this->appId = $appId;
$this->calendarUri = $calendarUri;
}
/**
* @inheritDoc
*/
final public function getName() {
return implode(self::DELIMITER, [
self::PREFIX,
$this->appId,
$this->calendarUri,
]);
}
/**
* @inheritDoc
*/
final public function setName($name) {
throw new DAV\Exception\MethodNotAllowed('Renaming calendars is not yet supported');
}
/**
* @inheritDoc
*/
final public function createDirectory($name) {
throw new DAV\Exception\MethodNotAllowed('Creating collections in calendar objects is not allowed');
}
/**
* Checks whether the calendar uri is app-generated
*
* @param string $calendarUri
* @return bool
*/
public static function isAppGeneratedCalendar(string $calendarUri):bool {
return strpos($calendarUri, self::PREFIX) === 0 && substr_count($calendarUri, self::DELIMITER) >= 2;
}
/**
* Splits an app-generated calendar-uri into appId and calendarUri
*
* @param string $calendarUri
* @return array
*/
public static function splitAppGeneratedCalendarUri(string $calendarUri):array {
$array = array_slice(explode(self::DELIMITER, $calendarUri, 3), 1);
// Check the array has expected amount of elements
// and none of them is an empty string
if (\count($array) !== 2 || \in_array('', $array, true)) {
throw new \InvalidArgumentException('Provided calendar uri was not app-generated');
}
return $array;
}
/**
* Checks whether a calendar-name, the user wants to create, violates
* the reserved name for calendar uris
*
* @param string $calendarUri
* @return bool
*/
public static function doesViolateReservedName(string $calendarUri):bool {
return strpos($calendarUri, self::PREFIX) === 0;
}
}

@ -0,0 +1,73 @@
<?php
/**
* @copyright 2020, Georg Ehrke <oc.list@georgehrke.com>
*
* @author Georg Ehrke <oc.list@georgehrke.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\DAV\CalDAV\Integration;
use Sabre\CalDAV\ICalendar;
/**
* Interface ICalendarProvider
*
* @package OCA\DAV\CalDAV\Integration
* @since 19.0.0
*/
interface ICalendarProvider {
/**
* Provides the appId of the plugin
*
* @since 19.0.0
* @return string AppId
*/
public function getAppId(): string;
/**
* Fetches all calendars for a given principal uri
*
* @since 19.0.0
* @param string $principalUri E.g. principals/users/user1
* @return ExternalCalendar[] Array of all calendars
*/
public function fetchAllForCalendarHome(string $principalUri): array;
/**
* Checks whether plugin has a calendar for a given principalUri and calendarUri
*
* @since 19.0.0
* @param string $principalUri E.g. principals/users/user1
* @param string $calendarUri E.g. personal
* @return bool True if calendar for principalUri and calendarUri exists, false otherwise
*/
public function hasCalendarInCalendarHome(string $principalUri, string $calendarUri): bool;
/**
* Fetches a calendar for a given principalUri and calendarUri
* Returns null if calendar does not exist
*
* @since 19.0.0
* @param string $principalUri E.g. principals/users/user1
* @param string $calendarUri E.g. personal
* @return ExternalCalendar|null Calendar if it exists, null otherwise
*/
public function getCalendarInCalendarHome(string $principalUri, string $calendarUri): ?ExternalCalendar;
}

@ -28,6 +28,7 @@ namespace OCA\DAV\Tests\unit\AppInfo;
use OC\App\AppManager;
use OC\ServerContainer;
use OCA\DAV\AppInfo\PluginManager;
use OCA\DAV\CalDAV\Integration\ICalendarProvider;
use Test\TestCase;
/**
@ -53,6 +54,12 @@ class PluginManagerTest extends TestCase {
'\OCA\DAV\ADavApp\PluginTwo',
],
],
'calendar-plugins' => [
'plugin' => [
'\OCA\DAV\ADavApp\CalendarPluginOne',
'\OCA\DAV\ADavApp\CalendarPluginTwo',
],
],
'collections' => [
'collection' => [
'\OCA\DAV\ADavApp\CollectionOne',
@ -67,6 +74,9 @@ class PluginManagerTest extends TestCase {
'plugins' => [
'plugin' => '\OCA\DAV\ADavApp2\PluginOne',
],
'calendar-plugins' => [
'plugin' => '\OCA\DAV\ADavApp2\CalendarPluginOne',
],
'collections' => [
'collection' => '\OCA\DAV\ADavApp2\CollectionOne',
],
@ -81,13 +91,20 @@ class PluginManagerTest extends TestCase {
$pluginManager = new PluginManager($server, $appManager);
$calendarPlugin1 = $this->createMock(ICalendarProvider::class);
$calendarPlugin2 = $this->createMock(ICalendarProvider::class);
$calendarPlugin3 = $this->createMock(ICalendarProvider::class);
$server->method('query')
->will($this->returnValueMap([
['\OCA\DAV\ADavApp\PluginOne', true, 'dummyplugin1'],
['\OCA\DAV\ADavApp\PluginTwo', true, 'dummyplugin2'],
['\OCA\DAV\ADavApp\CalendarPluginOne', true, $calendarPlugin1],
['\OCA\DAV\ADavApp\CalendarPluginTwo', true, $calendarPlugin2],
['\OCA\DAV\ADavApp\CollectionOne', true, 'dummycollection1'],
['\OCA\DAV\ADavApp\CollectionTwo', true, 'dummycollection2'],
['\OCA\DAV\ADavApp2\PluginOne', true, 'dummy2plugin1'],
['\OCA\DAV\ADavApp2\CalendarPluginOne', true, $calendarPlugin3],
['\OCA\DAV\ADavApp2\CollectionOne', true, 'dummy2collection1'],
]));
@ -96,6 +113,11 @@ class PluginManagerTest extends TestCase {
'dummyplugin2',
'dummy2plugin1',
];
$expectedCalendarPlugins = [
$calendarPlugin1,
$calendarPlugin2,
$calendarPlugin3,
];
$expectedCollections = [
'dummycollection1',
'dummycollection2',
@ -103,6 +125,7 @@ class PluginManagerTest extends TestCase {
];
$this->assertEquals($expectedPlugins, $pluginManager->getAppPlugins());
$this->assertEquals($expectedCalendarPlugins, $pluginManager->getCalendarPlugins());
$this->assertEquals($expectedCollections, $pluginManager->getAppCollections());
}
}

@ -24,8 +24,14 @@
namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\AppInfo\PluginManager;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\CalendarHome;
use OCA\DAV\CalDAV\Integration\ExternalCalendar;
use OCA\DAV\CalDAV\Integration\ICalendarProvider;
use OCA\DAV\CalDAV\Outbox;
use Sabre\CalDAV\Schedule\Inbox;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\MkCol;
use Test\TestCase;
@ -37,6 +43,9 @@ class CalendarHomeTest extends TestCase {
/** @var array */
private $principalInfo = [];
/** @var PluginManager */
private $pluginManager;
/** @var CalendarHome */
private $calendarHome;
@ -47,9 +56,16 @@ class CalendarHomeTest extends TestCase {
$this->principalInfo = [
'uri' => 'user-principal-123',
];
$this->pluginManager = $this->createMock(PluginManager::class);
$this->calendarHome = new CalendarHome($this->backend,
$this->principalInfo);
// Replace PluginManager with our mock
$reflection = new \ReflectionClass($this->calendarHome);
$reflectionProperty = $reflection->getProperty('pluginManager');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->calendarHome, $this->pluginManager);
}
public function testCreateCalendarValidName() {
@ -69,7 +85,6 @@ class CalendarHomeTest extends TestCase {
$this->calendarHome->createExtendedCollection('name123', $mkCol);
}
public function testCreateCalendarReservedName() {
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('The resource you tried to create has a reserved name');
@ -79,4 +94,136 @@ class CalendarHomeTest extends TestCase {
$this->calendarHome->createExtendedCollection('contact_birthdays', $mkCol);
}
public function testCreateCalendarReservedNameAppGenerated() {
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('The resource you tried to create has a reserved name');
/** @var MkCol | \PHPUnit_Framework_MockObject_MockObject $mkCol */
$mkCol = $this->createMock(MkCol::class);
$this->calendarHome->createExtendedCollection('app-generated--example--foo-1', $mkCol);
}
public function testGetChildren():void {
$this->backend
->expects($this->at(0))
->method('getCalendarsForUser')
->with('user-principal-123')
->willReturn([]);
$this->backend
->expects($this->at(1))
->method('getSubscriptionsForUser')
->with('user-principal-123')
->willReturn([]);
$calendarPlugin1 = $this->createMock(ICalendarProvider::class);
$calendarPlugin1
->expects($this->once())
->method('fetchAllForCalendarHome')
->with('user-principal-123')
->willReturn(['plugin1calendar1', 'plugin1calendar2']);
$calendarPlugin2 = $this->createMock(ICalendarProvider::class);
$calendarPlugin2
->expects($this->once())
->method('fetchAllForCalendarHome')
->with('user-principal-123')
->willReturn(['plugin2calendar1', 'plugin2calendar2']);
$this->pluginManager
->expects($this->once())
->method('getCalendarPlugins')
->with()
->willReturn([$calendarPlugin1, $calendarPlugin2]);
$actual = $this->calendarHome->getChildren();
$this->assertCount(6, $actual);
$this->assertInstanceOf(Inbox::class, $actual[0]);
$this->assertInstanceOf(Outbox::class, $actual[1]);
$this->assertEquals('plugin1calendar1', $actual[2]);
$this->assertEquals('plugin1calendar2', $actual[3]);
$this->assertEquals('plugin2calendar1', $actual[4]);
$this->assertEquals('plugin2calendar2', $actual[5]);
}
public function testGetChildNonAppGenerated():void {
$this->backend
->expects($this->at(0))
->method('getCalendarsForUser')
->with('user-principal-123')
->willReturn([]);
$this->backend
->expects($this->at(1))
->method('getSubscriptionsForUser')
->with('user-principal-123')
->willReturn([]);
$this->pluginManager
->expects($this->never())
->method('getCalendarPlugins');
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
$this->expectExceptionMessage('Node with name \'personal\' could not be found');
$this->calendarHome->getChild('personal');
}
public function testGetChildAppGenerated():void {
$this->backend
->expects($this->at(0))
->method('getCalendarsForUser')
->with('user-principal-123')
->willReturn([]);
$this->backend
->expects($this->at(1))
->method('getSubscriptionsForUser')
->with('user-principal-123')
->willReturn([]);
$calendarPlugin1 = $this->createMock(ICalendarProvider::class);
$calendarPlugin1
->expects($this->once())
->method('getAppId')
->with()
->willReturn('calendar_plugin_1');
$calendarPlugin1
->expects($this->never())
->method('hasCalendarInCalendarHome');
$calendarPlugin1
->expects($this->never())
->method('getCalendarInCalendarHome');
$externalCalendarMock = $this->createMock(ExternalCalendar::class);
$calendarPlugin2 = $this->createMock(ICalendarProvider::class);
$calendarPlugin2
->expects($this->once())
->method('getAppId')
->with()
->willReturn('calendar_plugin_2');
$calendarPlugin2
->expects($this->once())
->method('hasCalendarInCalendarHome')
->with('user-principal-123', 'calendar-uri-from-backend')
->willReturn(true);
$calendarPlugin2
->expects($this->once())
->method('getCalendarInCalendarHome')
->with('user-principal-123', 'calendar-uri-from-backend')
->willReturn($externalCalendarMock);
$this->pluginManager
->expects($this->once())
->method('getCalendarPlugins')
->with()
->willReturn([$calendarPlugin1, $calendarPlugin2]);
$actual = $this->calendarHome->getChild('app-generated--calendar_plugin_2--calendar-uri-from-backend');
$this->assertEquals($externalCalendarMock, $actual);
}
}

@ -0,0 +1,119 @@
<?php
/**
* @copyright 2020, Georg Ehrke <oc.list@georgehrke.com>
*
* @author Georg Ehrke <oc.list@georgehrke.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\DAV\Tests\unit\CalDAV\Integration;
use OCA\DAV\CalDAV\Integration\ExternalCalendar;
use Test\TestCase;
class ExternalCalendarTest extends TestCase {
private $abstractExternalCalendar;
protected function setUp(): void {
parent::setUp();
$this->abstractExternalCalendar =
$this->getMockForAbstractClass(ExternalCalendar::class, ['example-app-id', 'calendar-uri-in-backend']);
}
public function testGetName():void {
// Check that the correct name is returned
$this->assertEquals('app-generated--example-app-id--calendar-uri-in-backend',
$this->abstractExternalCalendar->getName());
// Check that the method is final and can't be overriden by other classes
$reflectionMethod = new \ReflectionMethod(ExternalCalendar::class, 'getName');
$this->assertTrue($reflectionMethod->isFinal());
}
public function testSetName():void {
// Check that the method is final and can't be overriden by other classes
$reflectionMethod = new \ReflectionMethod(ExternalCalendar::class, 'setName');
$this->assertTrue($reflectionMethod->isFinal());
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('Renaming calendars is not yet supported');
$this->abstractExternalCalendar->setName('other-name');
}
public function createDirectory():void {
// Check that the method is final and can't be overriden by other classes
$reflectionMethod = new \ReflectionMethod(ExternalCalendar::class, 'createDirectory');
$this->assertTrue($reflectionMethod->isFinal());
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('Creating collections in calendar objects is not allowed');
$this->abstractExternalCalendar->createDirectory('other-name');
}
public function testIsAppGeneratedCalendar():void {
$this->assertFalse(ExternalCalendar::isAppGeneratedCalendar('personal'));
$this->assertFalse(ExternalCalendar::isAppGeneratedCalendar('work'));
$this->assertFalse(ExternalCalendar::isAppGeneratedCalendar('contact_birthdays'));
$this->assertFalse(ExternalCalendar::isAppGeneratedCalendar('company'));
$this->assertFalse(ExternalCalendar::isAppGeneratedCalendar('app-generated'));
$this->assertFalse(ExternalCalendar::isAppGeneratedCalendar('app-generated--example'));
$this->assertTrue(ExternalCalendar::isAppGeneratedCalendar('app-generated--deck--board-1'));
$this->assertTrue(ExternalCalendar::isAppGeneratedCalendar('app-generated--example--foo-2'));
$this->assertTrue(ExternalCalendar::isAppGeneratedCalendar('app-generated--example--foo--2'));
}
/**
* @dataProvider splitAppGeneratedCalendarUriDataProvider
*/
public function testSplitAppGeneratedCalendarUriInvalid(string $name):void {
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Provided calendar uri was not app-generated');
ExternalCalendar::splitAppGeneratedCalendarUri($name);
}
public function splitAppGeneratedCalendarUriDataProvider():array {
return [
['personal'],
['foo_shared_by_admin'],
['contact_birthdays'],
];
}
public function testSplitAppGeneratedCalendarUri():void {
$this->assertEquals(['deck', 'board-1'], ExternalCalendar::splitAppGeneratedCalendarUri('app-generated--deck--board-1'));
$this->assertEquals(['example', 'foo-2'], ExternalCalendar::splitAppGeneratedCalendarUri('app-generated--example--foo-2'));
$this->assertEquals(['example', 'foo--2'], ExternalCalendar::splitAppGeneratedCalendarUri('app-generated--example--foo--2'));
}
public function testDoesViolateReservedName():void {
$this->assertFalse(ExternalCalendar::doesViolateReservedName('personal'));
$this->assertFalse(ExternalCalendar::doesViolateReservedName('work'));
$this->assertFalse(ExternalCalendar::doesViolateReservedName('contact_birthdays'));
$this->assertFalse(ExternalCalendar::doesViolateReservedName('company'));
$this->assertTrue(ExternalCalendar::doesViolateReservedName('app-generated'));
$this->assertTrue(ExternalCalendar::doesViolateReservedName('app-generated-calendar'));
$this->assertTrue(ExternalCalendar::doesViolateReservedName('app-generated--deck-123'));
}
}
Loading…
Cancel
Save