And add tests to handle schedule-default-calendar-URL Signed-off-by: Thomas Citharel <tcit@tcit.fr>tags/v19.0.0beta3
@@ -92,7 +92,7 @@ if ($debugging) { | |||
$server->addPlugin(new \Sabre\DAV\Sync\Plugin()); | |||
$server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); | |||
$server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin()); | |||
$server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig())); | |||
if ($sendInvitations) { | |||
$server->addPlugin(\OC::$server->query(\OCA\DAV\CalDAV\Schedule\IMipPlugin::class)); |
@@ -49,6 +49,7 @@ use OCA\DAV\HookManager; | |||
use OCP\AppFramework\App; | |||
use OCP\Calendar\IManager as ICalendarManager; | |||
use OCP\Contacts\IManager as IContactsManager; | |||
use OCP\IConfig; | |||
use OCP\IUser; | |||
use Symfony\Component\EventDispatcher\GenericEvent; | |||
@@ -244,6 +245,19 @@ class Application extends App { | |||
$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createCalendarObject', $listener); | |||
$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateCalendarObject', $listener); | |||
$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendarObject', $listener); | |||
/** | |||
* In case the user has set their default calendar to this one | |||
*/ | |||
$dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendar', function (GenericEvent $event) { | |||
/** @var IConfig $config */ | |||
$config = $this->getContainer()->getServer()->getConfig(); | |||
$principalUri = $event->getArgument('calendarData')['principaluri']; | |||
if (strpos($principalUri, 'principals/users') === 0) { | |||
list(, $UID) = \Sabre\Uri\split($principalUri); | |||
$config->deleteUserValue($UID, 'dav', 'defaultCalendar'); | |||
} | |||
}); | |||
} | |||
public function getSyncService() { |
@@ -84,7 +84,7 @@ class InvitationResponseServer { | |||
// calendar plugins | |||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin()); | |||
$this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); | |||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin()); | |||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig())); | |||
$this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin()); | |||
$this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin()); | |||
//$this->server->addPlugin(new \OCA\DAV\DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest())); |
@@ -29,6 +29,7 @@ namespace OCA\DAV\CalDAV\Schedule; | |||
use DateTimeZone; | |||
use OCA\DAV\CalDAV\CalDavBackend; | |||
use OCA\DAV\CalDAV\CalendarHome; | |||
use OCP\IConfig; | |||
use Sabre\CalDAV\ICalendar; | |||
use Sabre\DAV\INode; | |||
use Sabre\DAV\IProperties; | |||
@@ -47,15 +48,31 @@ use Sabre\VObject\ITip; | |||
use Sabre\VObject\Parameter; | |||
use Sabre\VObject\Property; | |||
use Sabre\VObject\Reader; | |||
use function \Sabre\Uri\split; | |||
class Plugin extends \Sabre\CalDAV\Schedule\Plugin { | |||
/** | |||
* @var IConfig | |||
*/ | |||
private $config; | |||
/** @var ITip\Message[] */ | |||
private $schedulingResponses = []; | |||
/** @var string|null */ | |||
private $pathOfCalendarObjectChange = null; | |||
public const CALENDAR_USER_TYPE = '{' . self::NS_CALDAV . '}calendar-user-type'; | |||
public const SCHEDULE_DEFAULT_CALENDAR_URL = '{' . Plugin::NS_CALDAV . '}schedule-default-calendar-URL'; | |||
/** | |||
* @param IConfig $config | |||
*/ | |||
public function __construct(IConfig $config) { | |||
$this->config = $config; | |||
} | |||
/** | |||
* Initializes the plugin | |||
* | |||
@@ -81,13 +98,12 @@ class Plugin extends \Sabre\CalDAV\Schedule\Plugin { | |||
public function propFind(PropFind $propFind, INode $node) { | |||
if ($node instanceof IPrincipal) { | |||
// overwrite Sabre/Dav's implementation | |||
$propFind->handle('{' . self::NS_CALDAV . '}calendar-user-type', function () use ($node) { | |||
$propFind->handle(self::CALENDAR_USER_TYPE, function () use ($node) { | |||
if ($node instanceof IProperties) { | |||
$calendarUserType = '{' . self::NS_CALDAV . '}calendar-user-type'; | |||
$props = $node->getProperties([$calendarUserType]); | |||
$props = $node->getProperties([self::CALENDAR_USER_TYPE]); | |||
if (isset($props[$calendarUserType])) { | |||
return $props[$calendarUserType]; | |||
if (isset($props[self::CALENDAR_USER_TYPE])) { | |||
return $props[self::CALENDAR_USER_TYPE]; | |||
} | |||
} | |||
@@ -261,7 +277,7 @@ EOF; | |||
*/ | |||
public function propFindDefaultCalendarUrl(PropFind $propFind, INode $node) { | |||
if ($node instanceof IPrincipal) { | |||
$propFind->handle('{' . self::NS_CALDAV . '}schedule-default-calendar-URL', function () use ($node) { | |||
$propFind->handle(self::SCHEDULE_DEFAULT_CALENDAR_URL, function () use ($node) { | |||
/** @var \OCA\DAV\CalDAV\Plugin $caldavPlugin */ | |||
$caldavPlugin = $this->server->getPlugin('caldav'); | |||
$principalUrl = $node->getPrincipalUrl(); | |||
@@ -272,12 +288,13 @@ EOF; | |||
} | |||
if (strpos($principalUrl, 'principals/users') === 0) { | |||
$uri = CalDavBackend::PERSONAL_CALENDAR_URI; | |||
$displayname = CalDavBackend::PERSONAL_CALENDAR_NAME; | |||
list(, $userId) = split($principalUrl); | |||
$uri = $this->config->getUserValue($userId, 'dav', 'defaultCalendar', CalDavBackend::PERSONAL_CALENDAR_URI); | |||
$displayName = CalDavBackend::PERSONAL_CALENDAR_NAME; | |||
} elseif (strpos($principalUrl, 'principals/calendar-resources') === 0 || | |||
strpos($principalUrl, 'principals/calendar-rooms') === 0) { | |||
$uri = CalDavBackend::RESOURCE_BOOKING_CALENDAR_URI; | |||
$displayname = CalDavBackend::RESOURCE_BOOKING_CALENDAR_NAME; | |||
$displayName = CalDavBackend::RESOURCE_BOOKING_CALENDAR_NAME; | |||
} else { | |||
// How did we end up here? | |||
// TODO - throw exception or just ignore? | |||
@@ -288,7 +305,7 @@ EOF; | |||
$calendarHome = $this->server->tree->getNodeForPath($calendarHomePath); | |||
if (!$calendarHome->childExists($uri)) { | |||
$calendarHome->getCalDAVBackend()->createCalendar($principalUrl, $uri, [ | |||
'{DAV:}displayname' => $displayname, | |||
'{DAV:}displayname' => $displayName, | |||
]); | |||
} | |||
@@ -151,7 +151,7 @@ class Server { | |||
if ($this->requestIsForSubtree(['calendars', 'public-calendars', 'system-calendars', 'principals'])) { | |||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin()); | |||
$this->server->addPlugin(new \OCA\DAV\CalDAV\ICSExportPlugin\ICSExportPlugin(\OC::$server->getConfig(), \OC::$server->getLogger())); | |||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin()); | |||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig())); | |||
if (\OC::$server->getConfig()->getAppValue('dav', 'sendInvitations', 'yes') === 'yes') { | |||
$this->server->addPlugin(\OC::$server->query(\OCA\DAV\CalDAV\Schedule\IMipPlugin::class)); | |||
} |
@@ -25,28 +25,68 @@ | |||
namespace OCA\DAV\Tests\unit\CalDAV\Schedule; | |||
use OCA\DAV\CalDAV\CalDavBackend; | |||
use OCA\DAV\CalDAV\CalendarHome; | |||
use OCA\DAV\CalDAV\Plugin as CalDAVPlugin; | |||
use OCA\DAV\CalDAV\Schedule\Plugin; | |||
use OCP\IConfig; | |||
use PHPUnit\Framework\MockObject\MockObject; | |||
use Sabre\DAV\PropFind; | |||
use Sabre\DAV\Server; | |||
use Sabre\DAV\Tree; | |||
use Sabre\DAV\Xml\Property\Href; | |||
use Sabre\DAV\Xml\Property\LocalHref; | |||
use Sabre\DAVACL\IPrincipal; | |||
use Sabre\HTTP\ResponseInterface; | |||
use Sabre\VObject\Parameter; | |||
use Sabre\VObject\Property\ICalendar\CalAddress; | |||
use Sabre\Xml\Service; | |||
use Test\TestCase; | |||
class PluginTest extends TestCase { | |||
/** @var Plugin */ | |||
private $plugin; | |||
/** @var Server|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var Server|MockObject */ | |||
private $server; | |||
/** @var IConfig|MockObject */ | |||
private $config; | |||
protected function setUp(): void { | |||
parent::setUp(); | |||
$this->server = $this->createMock(Server::class); | |||
$this->config = $this->createMock(IConfig::class); | |||
$response = $this->getMockBuilder(ResponseInterface::class) | |||
->disableOriginalConstructor() | |||
->getMock(); | |||
$this->plugin = new Plugin(); | |||
$this->server->httpResponse = $response; | |||
$this->server->xml = new Service(); | |||
$this->plugin = new Plugin($this->config); | |||
$this->plugin->initialize($this->server); | |||
} | |||
public function testInitialize() { | |||
$plugin = new Plugin($this->config); | |||
$this->server->expects($this->at(7)) | |||
->method('on') | |||
->with('propFind', [$plugin, 'propFindDefaultCalendarUrl'], 90); | |||
$this->server->expects($this->at(8)) | |||
->method('on') | |||
->with('afterWriteContent', [$plugin, 'dispatchSchedulingResponses']); | |||
$this->server->expects($this->at(9)) | |||
->method('on') | |||
->with('afterCreateFile', [$plugin, 'dispatchSchedulingResponses']); | |||
$plugin->initialize($this->server); | |||
} | |||
public function testGetAddressesForPrincipal() { | |||
$href = $this->createMock(Href::class); | |||
$href | |||
@@ -125,4 +165,183 @@ class PluginTest extends TestCase { | |||
$this->assertFalse($this->invokePrivate($this->plugin, 'getAttendeeRSVP', [$property2])); | |||
$this->assertFalse($this->invokePrivate($this->plugin, 'getAttendeeRSVP', [$property3])); | |||
} | |||
public function propFindDefaultCalendarUrlProvider(): array { | |||
return [ | |||
[ | |||
'principals/users/myuser', | |||
'calendars/myuser', | |||
false, | |||
CalDavBackend::PERSONAL_CALENDAR_URI, | |||
CalDavBackend::PERSONAL_CALENDAR_NAME, | |||
true | |||
], | |||
[ | |||
'principals/users/myuser', | |||
'calendars/myuser', | |||
false, | |||
CalDavBackend::PERSONAL_CALENDAR_URI, | |||
CalDavBackend::PERSONAL_CALENDAR_NAME, | |||
false | |||
], | |||
[ | |||
'principals/users/myuser', | |||
null, | |||
false, | |||
CalDavBackend::PERSONAL_CALENDAR_URI, | |||
CalDavBackend::PERSONAL_CALENDAR_NAME, | |||
true | |||
], | |||
[ | |||
'principals/users/myuser', | |||
'calendars/myuser', | |||
false, | |||
CalDavBackend::PERSONAL_CALENDAR_URI, | |||
CalDavBackend::PERSONAL_CALENDAR_NAME, | |||
true, | |||
false, | |||
], | |||
[ | |||
'principals/users/myuser', | |||
'calendars/myuser', | |||
false, | |||
'my_other_calendar', | |||
'My Other Calendar', | |||
true | |||
], | |||
[ | |||
'principals/calendar-resources', | |||
'system-calendars/calendar-resources/myuser', | |||
true, | |||
CalDavBackend::RESOURCE_BOOKING_CALENDAR_URI, | |||
CalDavBackend::RESOURCE_BOOKING_CALENDAR_NAME, | |||
true | |||
], | |||
[ | |||
'principals/calendar-resources', | |||
'system-calendars/calendar-resources/myuser', | |||
true, | |||
CalDavBackend::RESOURCE_BOOKING_CALENDAR_URI, | |||
CalDavBackend::RESOURCE_BOOKING_CALENDAR_NAME, | |||
false | |||
], | |||
[ | |||
'principals/something-else', | |||
'calendars/whatever', | |||
false, | |||
CalDavBackend::PERSONAL_CALENDAR_URI, | |||
CalDavBackend::PERSONAL_CALENDAR_NAME, | |||
true | |||
], | |||
]; | |||
} | |||
/** | |||
* @dataProvider propFindDefaultCalendarUrlProvider | |||
* @param string $principalUri | |||
* @param string $calendarHome | |||
* @param bool $isResource | |||
* @param string $calendarUri | |||
* @param string $displayName | |||
* @param bool $exists | |||
* @param bool $propertiesForPath | |||
*/ | |||
public function testPropFindDefaultCalendarUrl(string $principalUri, ?string $calendarHome, bool $isResource, string $calendarUri, string $displayName, bool $exists, bool $propertiesForPath = true) { | |||
/** @var PropFind $propFind */ | |||
$propFind = new PropFind( | |||
$principalUri, | |||
[ | |||
Plugin::SCHEDULE_DEFAULT_CALENDAR_URL | |||
], | |||
0 | |||
); | |||
/** @var IPrincipal|MockObject $node */ | |||
$node = $this->getMockBuilder(IPrincipal::class) | |||
->disableOriginalConstructor() | |||
->getMock(); | |||
$node->expects($this->once()) | |||
->method('getPrincipalUrl') | |||
->with() | |||
->willReturn($principalUri); | |||
$calDAVPlugin = $this->getMockBuilder(CalDAVPlugin::class) | |||
->disableOriginalConstructor() | |||
->getMock(); | |||
$calDAVPlugin->expects($this->once()) | |||
->method('getCalendarHomeForPrincipal') | |||
->willReturn($calendarHome); | |||
$this->server->expects($this->once()) | |||
->method('getPlugin') | |||
->with('caldav') | |||
->willReturn($calDAVPlugin); | |||
if (!$calendarHome) { | |||
$this->plugin->propFindDefaultCalendarUrl($propFind, $node); | |||
$this->assertNull($propFind->get(Plugin::SCHEDULE_DEFAULT_CALENDAR_URL)); | |||
return; | |||
} | |||
if ($principalUri === 'principals/something-else') { | |||
$this->plugin->propFindDefaultCalendarUrl($propFind, $node); | |||
$this->assertNull($propFind->get(Plugin::SCHEDULE_DEFAULT_CALENDAR_URL)); | |||
return; | |||
} | |||
if (!$isResource) { | |||
$this->config->expects($this->once()) | |||
->method('getUserValue') | |||
->with('myuser', 'dav', 'defaultCalendar', CalDavBackend::PERSONAL_CALENDAR_URI) | |||
->willReturn($calendarUri); | |||
} | |||
$calendarHomeObject = $this->createMock(CalendarHome::class); | |||
$calendarHomeObject->expects($this->once()) | |||
->method('childExists') | |||
->with($calendarUri) | |||
->willReturn($exists); | |||
if (!$exists) { | |||
$calendarBackend = $this->createMock(CalDavBackend::class); | |||
$calendarBackend->expects($this->once()) | |||
->method('createCalendar') | |||
->with($principalUri, $calendarUri, [ | |||
'{DAV:}displayname' => $displayName, | |||
]); | |||
$calendarHomeObject->expects($this->once()) | |||
->method('getCalDAVBackend') | |||
->with() | |||
->willReturn($calendarBackend); | |||
} | |||
/** @var Tree|MockObject $tree */ | |||
$tree = $this->createMock(Tree::class); | |||
$tree->expects($this->once()) | |||
->method('getNodeForPath') | |||
->with($calendarHome) | |||
->willReturn($calendarHomeObject); | |||
$this->server->tree = $tree; | |||
$properties = $propertiesForPath ? [ | |||
['href' => '/remote.php/dav/' . $calendarHome . '/' . $calendarUri] | |||
] : []; | |||
$this->server->expects($this->once()) | |||
->method('getPropertiesForPath') | |||
->with($calendarHome .'/' . $calendarUri, [], 1) | |||
->willReturn($properties); | |||
$this->plugin->propFindDefaultCalendarUrl($propFind, $node); | |||
if (!$propertiesForPath) { | |||
$this->assertNull($propFind->get(Plugin::SCHEDULE_DEFAULT_CALENDAR_URL)); | |||
return; | |||
} | |||
/** @var LocalHref $result */ | |||
$result = $propFind->get(Plugin::SCHEDULE_DEFAULT_CALENDAR_URL); | |||
$this->assertEquals('/remote.php/dav/'. $calendarHome . '/' . $calendarUri, $result->getHref()); | |||
} | |||
} |