Browse Source

Introducing CalDAV into core

tags/v9.0beta1
Thomas Müller 8 years ago
parent
commit
2b13c5db0f

+ 387
- 0
apps/dav/appinfo/database.xml View File

@@ -183,4 +183,391 @@ CREATE TABLE addressbookchanges (
</declaration>
</table>


<!--
CREATE TABLE calendarobjects (
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
calendardata MEDIUMBLOB,
uri VARBINARY(200),
calendarid INTEGER UNSIGNED NOT NULL,
lastmodified INT(11) UNSIGNED,
etag VARBINARY(32),
size INT(11) UNSIGNED NOT NULL,
componenttype VARBINARY(8),
firstoccurence INT(11) UNSIGNED,
lastoccurence INT(11) UNSIGNED,
uid VARBINARY(200),
UNIQUE(calendarid, uri)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-->
<table>
<name>*dbprefix*calendarobjects</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<autoincrement>1</autoincrement>
<unsigned>true</unsigned>
<length>11</length>
</field>
<field>
<name>calendardata</name>
<type>blob</type>
</field>
<field>
<name>uri</name>
<type>text</type>
</field>
<field>
<name>calendarid</name>
<type>integer</type>
<unsigned>true</unsigned>
<notnull>true</notnull>
</field>
<field>
<name>lastmodified</name>
<type>integer</type>
<unsigned>true</unsigned>
</field>
<field>
<name>etag</name>
<type>text</type>
<length>32</length>
</field>
<field>
<name>size</name>
<type>integer</type>
<notnull>true</notnull>
<unsigned>true</unsigned>
<length>11</length>
</field>
<field>
<name>componenttype</name>
<type>text</type>
</field>
<field>
<name>firstoccurence</name>
<type>integer</type>
<unsigned>true</unsigned>
</field>
<field>
<name>lastoccurence</name>
<type>integer</type>
<unsigned>true</unsigned>
</field>
<field>
<name>uid</name>
<type>text</type>
</field>
<index>
<name>calobjects_index</name>
<unique>true</unique>
<field>
<name>calendarid</name>
</field>
<field>
<name>uri</name>
</field>
</index>
</declaration>
</table>
<!--
CREATE TABLE calendars (
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
principaluri VARBINARY(100),
displayname VARCHAR(100),
uri VARBINARY(200),
synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1',
description TEXT,
calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0',
calendarcolor VARBINARY(10),
timezone TEXT,
components VARBINARY(20),
transparent TINYINT(1) NOT NULL DEFAULT '0',
UNIQUE(principaluri, uri)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-->
<table>
<name>*dbprefix*calendars</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<autoincrement>1</autoincrement>
<unsigned>true</unsigned>
<length>11</length>
</field>
<field>
<name>principaluri</name>
<type>text</type>
</field>
<field>
<name>displayname</name>
<type>text</type>
</field>
<field>
<name>uri</name>
<type>text</type>
</field>
<field>
<name>synctoken</name>
<type>integer</type>
<default>1</default>
<notnull>true</notnull>
<unsigned>true</unsigned>
</field>
<field>
<name>description</name>
<type>text</type>
</field>
<field>
<name>calendarorder</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<unsigned>true</unsigned>
</field>
<field>
<name>calendarcolor</name>
<type>text</type>
</field>
<field>
<name>timezone</name>
<type>text</type>
</field>
<field>
<name>components</name>
<type>text</type>
</field>
<field>
<name>transparent</name>
<type>integer</type>
<length>1</length>
<notnull>true</notnull>
<default>0</default>
</field>
<index>
<name>calendars_index</name>
<unique>true</unique>
<field>
<name>principaluri</name>
</field>
<field>
<name>uri</name>
</field>
</index>
</declaration>
</table>
<!--
CREATE TABLE calendarchanges (
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
uri VARBINARY(200) NOT NULL,
synctoken INT(11) UNSIGNED NOT NULL,
calendarid INT(11) UNSIGNED NOT NULL,
operation TINYINT(1) NOT NULL,
INDEX calendarid_synctoken (calendarid, synctoken)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-->
<table>
<name>*dbprefix*calendarchanges</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<autoincrement>1</autoincrement>
<unsigned>true</unsigned>
<length>11</length>
</field>
<field>
<name>uri</name>
<type>text</type>
</field>
<field>
<name>synctoken</name>
<type>integer</type>
<default>1</default>
<notnull>true</notnull>
<unsigned>true</unsigned>
</field>
<field>
<name>calendarid</name>
<type>integer</type>
<notnull>true</notnull>
</field>
<field>
<name>operation</name>
<type>integer</type>
<notnull>true</notnull>
<length>1</length>
</field>

<index>
<name>calendarid_synctoken</name>
<field>
<name>calendarid</name>
</field>
<field>
<name>synctoken</name>
</field>
</index>

</declaration>
</table>

<!--
CREATE TABLE calendarsubscriptions (
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
uri VARBINARY(200) NOT NULL,
principaluri VARBINARY(100) NOT NULL,
source TEXT,
displayname VARCHAR(100),
refreshrate VARCHAR(10),
calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0',
calendarcolor VARBINARY(10),
striptodos TINYINT(1) NULL,
stripalarms TINYINT(1) NULL,
stripattachments TINYINT(1) NULL,
lastmodified INT(11) UNSIGNED,
UNIQUE(principaluri, uri)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-->
<table>
<name>*dbprefix*calendarsubscriptions</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<autoincrement>1</autoincrement>
<unsigned>true</unsigned>
<length>11</length>
</field>
<field>
<name>uri</name>
<type>text</type>
</field>
<field>
<name>principaluri</name>
<type>text</type>
</field>
<field>
<name>source</name>
<type>text</type>
</field>
<field>
<name>displayname</name>
<type>text</type>
<length>100</length>
</field>
<field>
<name>refreshrate</name>
<type>text</type>
<length>10</length>
</field>
<field>
<name>calendarorder</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<unsigned>true</unsigned>
</field>
<field>
<name>calendarcolor</name>
<type>text</type>
</field>
<field>
<name>striptodos</name>
<type>integer</type>
<length>1</length>
</field>
<field>
<name>stripalarms</name>
<type>integer</type>
<length>1</length>
</field>
<field>
<name>stripattachments</name>
<type>integer</type>
<length>1</length>
</field>
<field>
<name>lastmodified</name>
<type>integer</type>
<unsigned>true</unsigned>
</field>
<index>
<name>calsub_index</name>
<unique>true</unique>
<field>
<name>principaluri</name>
</field>
<field>
<name>uri</name>
</field>
</index>
</declaration>
</table>
<!--
CREATE TABLE schedulingobjects (
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
principaluri VARBINARY(255),
calendardata MEDIUMBLOB,
uri VARBINARY(200),
lastmodified INT(11) UNSIGNED,
etag VARBINARY(32),
size INT(11) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-->

<table>
<name>*dbprefix*schedulingobjects</name>
<declaration>
<field>
<name>id</name>
<type>integer</type>
<default>0</default>
<notnull>true</notnull>
<autoincrement>1</autoincrement>
<unsigned>true</unsigned>
<length>11</length>
</field>
<field>
<name>principaluri</name>
<type>text</type>
</field>
<field>
<name>calendardata</name>
<type>blob</type>
</field>
<field>
<name>uri</name>
<type>text</type>
</field>
<field>
<name>lastmodified</name>
<type>integer</type>
<unsigned>true</unsigned>
</field>
<field>
<name>etag</name>
<type>text</type>
<length>32</length>
</field>
<field>
<name>size</name>
<type>integer</type>
<notnull>true</notnull>
<unsigned>true</unsigned>
<length>11</length>
</field>

</declaration>
</table>
</database>

+ 1
- 1
apps/dav/appinfo/info.xml View File

@@ -5,7 +5,7 @@
<description>ownCloud WebDAV endpoint</description>
<licence>AGPL</licence>
<author>owncloud.org</author>
<version>0.1.2</version>
<version>0.1.3</version>
<requiremin>9.0</requiremin>
<shipped>true</shipped>
<standalone/>

+ 1136
- 0
apps/dav/lib/caldav/caldavbackend.php
File diff suppressed because it is too large
View File


+ 13
- 6
apps/dav/lib/rootcollection.php View File

@@ -2,8 +2,10 @@

namespace OCA\DAV;

use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\Connector\Sabre\Principal;
use Sabre\CalDAV\CalendarRoot;
use Sabre\CalDAV\Principal\Collection;
use Sabre\CardDAV\AddressBookRoot;
use Sabre\DAV\SimpleCollection;
@@ -12,9 +14,10 @@ class RootCollection extends SimpleCollection {

public function __construct() {
$config = \OC::$server->getConfig();
$db = \OC::$server->getDatabaseConnection();
$principalBackend = new Principal(
$config,
\OC::$server->getUserManager()
$config,
\OC::$server->getUserManager()
);
// as soon as debug mode is enabled we allow listing of principals
$disableListing = !$config->getSystemValue('debug', false);
@@ -24,14 +27,18 @@ class RootCollection extends SimpleCollection {
$principalCollection->disableListing = $disableListing;
$filesCollection = new Files\RootCollection($principalBackend);
$filesCollection->disableListing = $disableListing;
$cardDavBackend = new CardDavBackend(\OC::$server->getDatabaseConnection());
$caldavBackend = new CalDavBackend($db);
$calendarRoot = new CalendarRoot($principalBackend, $caldavBackend);
$calendarRoot->disableListing = $disableListing;
$cardDavBackend = new CardDavBackend($db);
$addressBookRoot = new AddressBookRoot($principalBackend, $cardDavBackend);
$addressBookRoot->disableListing = $disableListing;

$children = [
$principalCollection,
$filesCollection,
$addressBookRoot,
$principalCollection,
$filesCollection,
$calendarRoot,
$addressBookRoot,
];

parent::__construct('root', $children);

+ 10
- 0
apps/dav/lib/server.php View File

@@ -33,8 +33,18 @@ class Server {
$this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig()));
$this->server->addPlugin(new Plugin($authBackend, 'ownCloud'));

// calendar plugins
$this->server->addPlugin(new \Sabre\CalDAV\Plugin());
$this->server->addPlugin(new \Sabre\DAVACL\Plugin());
$this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
$senderEmail = \OCP\Util::getDefaultEmailAddress('no-reply');
$this->server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin());
$this->server->addPlugin(new \Sabre\CalDAV\Schedule\IMipPlugin($senderEmail));
$this->server->addPlugin(new \Sabre\CalDAV\SharingPlugin());
$this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
$this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin());

// addressbook plugins
$this->server->addPlugin(new \Sabre\CardDAV\Plugin());

// wait with registering these until auth is handled and the filesystem is setup

+ 325
- 0
apps/dav/tests/unit/caldav/caldavbackendtest.php View File

@@ -0,0 +1,325 @@
<?php
/**
* @author Lukas Reschke <lukas@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace Tests\Connector\Sabre;

use DateTime;
use DateTimeZone;
use OCA\DAV\CalDAV\CalDavBackend;
use Sabre\DAV\Property\Href;
use Sabre\DAV\PropPatch;
use Test\TestCase;

/**
* Class CalDavBackendTest
*
* @group DB
*
* @package Tests\Connector\Sabre
*/
class CalDavBackendTest extends TestCase {

/** @var CalDavBackend */
private $backend;

const UNIT_TEST_USER = 'caldav-unit-test';


public function setUp() {
parent::setUp();

$db = \OC::$server->getDatabaseConnection();
$this->backend = new CalDavBackend($db);

$this->tearDown();
}

public function tearDown() {
parent::tearDown();

if (is_null($this->backend)) {
return;
}
$books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
foreach ($books as $book) {
$this->backend->deleteCalendar($book['id']);
}
$subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER);
foreach ($subscriptions as $subscription) {
$this->backend->deleteSubscription($subscription['id']);
}
}

public function testCalendarOperations() {

$calendarId = $this->createTestCalendar();

// update it's display name
$patch = new PropPatch([
'{DAV:}displayname' => 'Unit test',
'{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar used for unit testing'
]);
$this->backend->updateCalendar($calendarId, $patch);
$patch->commit();
$books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
$this->assertEquals(1, count($books));
$this->assertEquals('Unit test', $books[0]['{DAV:}displayname']);
$this->assertEquals('Calendar used for unit testing', $books[0]['{urn:ietf:params:xml:ns:caldav}calendar-description']);

// delete the address book
$this->backend->deleteCalendar($books[0]['id']);
$books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
$this->assertEquals(0, count($books));
}

public function testCalendarObjectsOperations() {

$calendarId = $this->createTestCalendar();

// create a card
$uri = $this->getUniqueID('calobj');
$calData = <<<'EOD'
BEGIN:VCALENDAR
VERSION:2.0
PRODID:ownCloud Calendar
BEGIN:VEVENT
CREATED;VALUE=DATE-TIME:20130910T125139Z
UID:47d15e3ec8
LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
SUMMARY:Test Event
DTSTART;VALUE=DATE-TIME:20130912T130000Z
DTEND;VALUE=DATE-TIME:20130912T140000Z
CLASS:PUBLIC
END:VEVENT
END:VCALENDAR
EOD;

$this->backend->createCalendarObject($calendarId, $uri, $calData);

// get all the cards
$calendarObjects = $this->backend->getCalendarObjects($calendarId);
$this->assertEquals(1, count($calendarObjects));
$this->assertEquals($calendarId, $calendarObjects[0]['calendarid']);

// get the cards
$calendarObject = $this->backend->getCalendarObject($calendarId, $uri);
$this->assertNotNull($calendarObject);
$this->assertArrayHasKey('id', $calendarObject);
$this->assertArrayHasKey('uri', $calendarObject);
$this->assertArrayHasKey('lastmodified', $calendarObject);
$this->assertArrayHasKey('etag', $calendarObject);
$this->assertArrayHasKey('size', $calendarObject);
$this->assertEquals($calData, $calendarObject['calendardata']);

// update the card
$calData = <<<'EOD'
BEGIN:VCALENDAR
VERSION:2.0
PRODID:ownCloud Calendar
BEGIN:VEVENT
CREATED;VALUE=DATE-TIME:20130910T125139Z
UID:47d15e3ec8
LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
SUMMARY:Test Event
DTSTART;VALUE=DATE-TIME:20130912T130000Z
DTEND;VALUE=DATE-TIME:20130912T140000Z
END:VEVENT
END:VCALENDAR
EOD;
$this->backend->updateCalendarObject($calendarId, $uri, $calData);
$calendarObject = $this->backend->getCalendarObject($calendarId, $uri);
$this->assertEquals($calData, $calendarObject['calendardata']);

// delete the card
$this->backend->deleteCalendarObject($calendarId, $uri);
$calendarObjects = $this->backend->getCalendarObjects($calendarId);
$this->assertEquals(0, count($calendarObjects));
}

public function testMultiCalendarObjects() {

$calendarId = $this->createTestCalendar();

// create an event
$calData = <<<'EOD'
BEGIN:VCALENDAR
VERSION:2.0
PRODID:ownCloud Calendar
BEGIN:VEVENT
CREATED;VALUE=DATE-TIME:20130910T125139Z
UID:47d15e3ec8
LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
SUMMARY:Test Event
DTSTART;VALUE=DATE-TIME:20130912T130000Z
DTEND;VALUE=DATE-TIME:20130912T140000Z
CLASS:PUBLIC
END:VEVENT
END:VCALENDAR
EOD;
$uri0 = $this->getUniqueID('card');
$this->backend->createCalendarObject($calendarId, $uri0, $calData);
$uri1 = $this->getUniqueID('card');
$this->backend->createCalendarObject($calendarId, $uri1, $calData);
$uri2 = $this->getUniqueID('card');
$this->backend->createCalendarObject($calendarId, $uri2, $calData);

// get all the cards
$calendarObjects = $this->backend->getCalendarObjects($calendarId);
$this->assertEquals(3, count($calendarObjects));

// get the cards
$calendarObjects = $this->backend->getMultipleCalendarObjects($calendarId, [$uri1, $uri2]);
$this->assertEquals(2, count($calendarObjects));
foreach($calendarObjects as $card) {
$this->assertArrayHasKey('id', $card);
$this->assertArrayHasKey('uri', $card);
$this->assertArrayHasKey('lastmodified', $card);
$this->assertArrayHasKey('etag', $card);
$this->assertArrayHasKey('size', $card);
$this->assertEquals($calData, $card['calendardata']);
}

// delete the card
$this->backend->deleteCalendarObject($calendarId, $uri0);
$this->backend->deleteCalendarObject($calendarId, $uri1);
$this->backend->deleteCalendarObject($calendarId, $uri2);
$calendarObjects = $this->backend->getCalendarObjects($calendarId);
$this->assertEquals(0, count($calendarObjects));
}

/**
* @dataProvider providesCalendarQueryParameters
*/
public function testCalendarQuery($expectedEventsInResult, $propFilters, $compFilter) {
$calendarId = $this->createTestCalendar();
$events = [];
$events[0] = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z');
$events[1] = $this->createEvent($calendarId, '20130912T150000Z', '20130912T170000Z');
$events[2] = $this->createEvent($calendarId, '20130912T173000Z', '20130912T220000Z');

$result = $this->backend->calendarQuery($calendarId, [
'name' => '',
'prop-filters' => $propFilters,
'comp-filters' => $compFilter
]);

$expectedEventsInResult = array_map(function($index) use($events) {
return $events[$index];
}, $expectedEventsInResult);
$this->assertEquals($expectedEventsInResult, $result, '', 0.0, 10, true);
}

public function testGetCalendarObjectByUID() {
$calendarId = $this->createTestCalendar();
$this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z');

$co = $this->backend->getCalendarObjectByUID(self::UNIT_TEST_USER, '47d15e3ec8');
$this->assertNotNull($co);
}

public function providesCalendarQueryParameters() {
return [
'all' => [[0, 1, 2], [], []],
'only-todos' => [[], ['name' => 'VTODO'], []],
'only-events' => [[0, 1, 2], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => null], 'prop-filters' => []]],],
'start' => [[1, 2], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC')), 'end' => null], 'prop-filters' => []]],],
'end' => [[0], [], [['name' => 'VEVENT', 'is-not-defined' => false, 'comp-filters' => [], 'time-range' => ['start' => null, 'end' => new DateTime('2013-09-12 14:00:00', new DateTimeZone('UTC'))], 'prop-filters' => []]],],
];
}

private function createTestCalendar() {
$this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []);
$calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
$this->assertEquals(1, count($calendars));
$this->assertEquals(self::UNIT_TEST_USER, $calendars[0]['principaluri']);
$this->assertEquals('Example', $calendars[0]['uri']);
$calendarId = $calendars[0]['id'];

return $calendarId;
}

private function createEvent($calendarId, $start = '20130912T130000Z', $end = '20130912T140000Z') {

$calData = <<<EOD
BEGIN:VCALENDAR
VERSION:2.0
PRODID:ownCloud Calendar
BEGIN:VEVENT
CREATED;VALUE=DATE-TIME:20130910T125139Z
UID:47d15e3ec8
LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z
DTSTAMP;VALUE=DATE-TIME:20130910T125139Z
SUMMARY:Test Event
DTSTART;VALUE=DATE-TIME:$start
DTEND;VALUE=DATE-TIME:$end
CLASS:PUBLIC
END:VEVENT
END:VCALENDAR
EOD;
$uri0 = $this->getUniqueID('event');
$this->backend->createCalendarObject($calendarId, $uri0, $calData);

return $uri0;
}

public function testSyncSupport() {
$calendarId = $this->createTestCalendar();

// fist call without synctoken
$changes = $this->backend->getChangesForCalendar($calendarId, '', 1);
$syncToken = $changes['syncToken'];

// add a change
$event = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z');

// look for changes
$changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 1);
$this->assertEquals($event, $changes['added'][0]);
}

public function testSubscriptions() {
$id = $this->backend->createSubscription(self::UNIT_TEST_USER, 'Subscription', [
'{http://calendarserver.org/ns/}source' => new Href('test-source')
]);

$subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER);
$this->assertEquals(1, count($subscriptions));
$this->assertEquals($id, $subscriptions[0]['id']);

$patch = new PropPatch([
'{DAV:}displayname' => 'Unit test',
]);
$this->backend->updateSubscription($id, $patch);
$patch->commit();

$subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER);
$this->assertEquals(1, count($subscriptions));
$this->assertEquals($id, $subscriptions[0]['id']);
$this->assertEquals('Unit test', $subscriptions[0]['{DAV:}displayname']);

$this->backend->deleteSubscription($id);
$subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER);
$this->assertEquals(0, count($subscriptions));
}

}

Loading…
Cancel
Save