Merge pull request #20371 from owncloud/add-caldav-2

Introducing CalDAV into core
This commit is contained in:
Thomas Müller 2015-11-18 16:32:19 +01:00
commit d8b73fde1a
8 changed files with 1988 additions and 7 deletions

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>

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/>

View File

@ -1,8 +1,10 @@
<?php
use OCA\DAV\Command\CreateAddressBook;
use OCA\DAV\Command\CreateCalendar;
$dbConnection = \OC::$server->getDatabaseConnection();
$userManager = OC::$server->getUserManager();
/** @var Symfony\Component\Console\Application $application */
$application->add(new CreateAddressBook($userManager, $dbConnection));
$application->add(new CreateCalendar($userManager, $dbConnection));

View File

@ -0,0 +1,52 @@
<?php
namespace OCA\DAV\Command;
use OCA\DAV\CalDAV\CalDavBackend;
use OCP\IDBConnection;
use OCP\IUserManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CreateCalendar extends Command {
/** @var IUserManager */
protected $userManager;
/** @var \OCP\IDBConnection */
protected $dbConnection;
/**
* @param IUserManager $userManager
* @param IDBConnection $dbConnection
*/
function __construct(IUserManager $userManager, IDBConnection $dbConnection) {
parent::__construct();
$this->userManager = $userManager;
$this->dbConnection = $dbConnection;
}
protected function configure() {
$this
->setName('dav:create-calendar')
->setDescription('Create a dav calendar')
->addArgument('user',
InputArgument::REQUIRED,
'User for whom the calendar will be created')
->addArgument('name',
InputArgument::REQUIRED,
'Name of the calendar');
}
protected function execute(InputInterface $input, OutputInterface $output) {
$user = $input->getArgument('user');
if (!$this->userManager->userExists($user)) {
throw new \InvalidArgumentException("User <$user> in unknown.");
}
$name = $input->getArgument('name');
$caldav = new CalDavBackend($this->dbConnection);
$caldav->createCalendar("principals/$user", $name, []);
}
}

File diff suppressed because it is too large Load Diff

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);

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());
// Finder on OS X requires Class 2 WebDAV support (locking), since we do

View File

@ -0,0 +1,348 @@
<?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\CalDAV\Property\SupportedCalendarComponentSet;
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', [
'{http://apple.com/ns/ical/}calendar-color' => '#1C4587FF'
]);
$calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
$this->assertEquals(1, count($calendars));
$this->assertEquals(self::UNIT_TEST_USER, $calendars[0]['principaluri']);
/** @var SupportedCalendarComponentSet $components */
$components = $calendars[0]['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set'];
$this->assertEquals(['VEVENT','VTODO'], $components->getValue());
$color = $calendars[0]['{http://apple.com/ns/ical/}calendar-color'];
$this->assertEquals('#1C4587FF', $color);
$this->assertEquals('Example', $calendars[0]['uri']);
$this->assertEquals('Example', $calendars[0]['{DAV:}displayname']);
$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));
}
public function testScheduling() {
$this->backend->createSchedulingObject(self::UNIT_TEST_USER, 'Sample Schedule', '');
$sos = $this->backend->getSchedulingObjects(self::UNIT_TEST_USER);
$this->assertEquals(1, count($sos));
$so = $this->backend->getSchedulingObject(self::UNIT_TEST_USER, 'Sample Schedule');
$this->assertNotNull($so);
$this->backend->deleteSchedulingObject(self::UNIT_TEST_USER, 'Sample Schedule');
$sos = $this->backend->getSchedulingObjects(self::UNIT_TEST_USER);
$this->assertEquals(0, count($sos));
}
}