Allow apps to provide Calendars in user's calendarHome
Signed-off-by: Georg Ehrke <developer@georgehrke.com>
This commit is contained in:
parent
a1fc233fcb
commit
b46e5cb270
|
@ -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…
Reference in New Issue