Signed-off-by: Thomas Citharel <tcit@tcit.fr>tags/v19.0.0beta6
@@ -30,6 +30,7 @@ use OCA\DAV\CalDAV\Activity\Provider\Event; | |||
use OCA\DAV\CalDAV\CalDavBackend; | |||
use OCP\Activity\IEvent; | |||
use OCP\Activity\IManager as IActivityManager; | |||
use OCP\App\IAppManager; | |||
use OCP\IGroup; | |||
use OCP\IGroupManager; | |||
use OCP\IUser; | |||
@@ -52,15 +53,14 @@ class Backend { | |||
/** @var IUserSession */ | |||
protected $userSession; | |||
/** | |||
* @param IActivityManager $activityManager | |||
* @param IGroupManager $groupManager | |||
* @param IUserSession $userSession | |||
*/ | |||
public function __construct(IActivityManager $activityManager, IGroupManager $groupManager, IUserSession $userSession) { | |||
/** @var IAppManager */ | |||
protected $appManager; | |||
public function __construct(IActivityManager $activityManager, IGroupManager $groupManager, IUserSession $userSession, IAppManager $appManager) { | |||
$this->activityManager = $activityManager; | |||
$this->groupManager = $groupManager; | |||
$this->userSession = $userSession; | |||
$this->appManager = $appManager; | |||
} | |||
/** | |||
@@ -435,29 +435,40 @@ class Backend { | |||
$users = $this->getUsersForShares($shares); | |||
$users[] = $owner; | |||
foreach ($users as $user) { | |||
// Users for share can return the owner itself if the calendar is published | |||
foreach (array_unique($users) as $user) { | |||
if ($classification === CalDavBackend::CLASSIFICATION_PRIVATE && $user !== $owner) { | |||
// Private events are only shown to the owner | |||
continue; | |||
} | |||
$params = [ | |||
'actor' => $event->getAuthor(), | |||
'calendar' => [ | |||
'id' => (int) $calendarData['id'], | |||
'uri' => $calendarData['uri'], | |||
'name' => $calendarData['{DAV:}displayname'], | |||
], | |||
'object' => [ | |||
'id' => $object['id'], | |||
'name' => $classification === CalDavBackend::CLASSIFICATION_CONFIDENTIAL && $user !== $owner ? 'Busy' : $object['name'], | |||
'classified' => $classification === CalDavBackend::CLASSIFICATION_CONFIDENTIAL && $user !== $owner, | |||
], | |||
]; | |||
if ($object['type'] === 'event' && strpos($action, Event::SUBJECT_OBJECT_DELETE) === false && $this->appManager->isEnabledForUser('calendar')) { | |||
$params['object']['link']['object_uri'] = $objectData['uri']; | |||
$params['object']['link']['calendar_uri'] = $calendarData['uri']; | |||
$params['object']['link']['owner'] = $owner; | |||
} | |||
$event->setAffectedUser($user) | |||
->setSubject( | |||
$user === $currentUser ? $action . '_self' : $action, | |||
[ | |||
'actor' => $event->getAuthor(), | |||
'calendar' => [ | |||
'id' => (int) $calendarData['id'], | |||
'uri' => $calendarData['uri'], | |||
'name' => $calendarData['{DAV:}displayname'], | |||
], | |||
'object' => [ | |||
'id' => $object['id'], | |||
'name' => $classification === CalDavBackend::CLASSIFICATION_CONFIDENTIAL && $user !== $owner ? 'Busy' : $object['name'], | |||
'classified' => $classification === CalDavBackend::CLASSIFICATION_CONFIDENTIAL && $user !== $owner, | |||
], | |||
] | |||
$params | |||
); | |||
$this->activityManager->publish($event); | |||
} | |||
} | |||
@@ -496,11 +507,11 @@ class Backend { | |||
protected function getUsersForShares(array $shares) { | |||
$users = $groups = []; | |||
foreach ($shares as $share) { | |||
$prinical = explode('/', $share['{http://owncloud.org/ns}principal']); | |||
if ($prinical[1] === 'users') { | |||
$users[] = $prinical[2]; | |||
} elseif ($prinical[1] === 'groups') { | |||
$groups[] = $prinical[2]; | |||
$principal = explode('/', $share['{http://owncloud.org/ns}principal']); | |||
if ($principal[1] === 'users') { | |||
$users[] = $principal[2]; | |||
} elseif ($principal[1] === 'groups') { | |||
$groups[] = $principal[2]; | |||
} | |||
} | |||
@@ -3,6 +3,7 @@ | |||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @author Joas Schilling <coding@schilljs.com> | |||
* @author Thomas Citharel <nextcloud@tcit.fr> | |||
* | |||
* @license GNU AGPL version 3 or any later version | |||
* | |||
@@ -29,6 +30,7 @@ use OCP\Activity\IProvider; | |||
use OCP\IGroup; | |||
use OCP\IGroupManager; | |||
use OCP\IL10N; | |||
use OCP\IURLGenerator; | |||
use OCP\IUser; | |||
use OCP\IUserManager; | |||
@@ -46,13 +48,18 @@ abstract class Base implements IProvider { | |||
/** @var string[] */ | |||
protected $groupDisplayNames = []; | |||
/** @var IURLGenerator */ | |||
protected $url; | |||
/** | |||
* @param IUserManager $userManager | |||
* @param IGroupManager $groupManager | |||
* @param IURLGenerator $urlGenerator | |||
*/ | |||
public function __construct(IUserManager $userManager, IGroupManager $groupManager) { | |||
public function __construct(IUserManager $userManager, IGroupManager $groupManager, IURLGenerator $urlGenerator) { | |||
$this->userManager = $userManager; | |||
$this->groupManager = $groupManager; | |||
$this->url = $urlGenerator; | |||
} | |||
/** | |||
@@ -71,22 +78,6 @@ abstract class Base implements IProvider { | |||
->setRichSubject($subject, $parameters); | |||
} | |||
/** | |||
* @param array $eventData | |||
* @return array | |||
*/ | |||
protected function generateObjectParameter($eventData) { | |||
if (!is_array($eventData) || !isset($eventData['id']) || !isset($eventData['name'])) { | |||
throw new \InvalidArgumentException(); | |||
} | |||
return [ | |||
'type' => 'calendar-event', | |||
'id' => $eventData['id'], | |||
'name' => $eventData['name'], | |||
]; | |||
} | |||
/** | |||
* @param array $data | |||
* @param IL10N $l |
@@ -52,9 +52,6 @@ class Calendar extends Base { | |||
/** @var IL10N */ | |||
protected $l; | |||
/** @var IURLGenerator */ | |||
protected $url; | |||
/** @var IManager */ | |||
protected $activityManager; | |||
@@ -70,9 +67,8 @@ class Calendar extends Base { | |||
* @param IEventMerger $eventMerger | |||
*/ | |||
public function __construct(IFactory $languageFactory, IURLGenerator $url, IManager $activityManager, IUserManager $userManager, IGroupManager $groupManager, IEventMerger $eventMerger) { | |||
parent::__construct($userManager, $groupManager); | |||
parent::__construct($userManager, $groupManager, $url); | |||
$this->languageFactory = $languageFactory; | |||
$this->url = $url; | |||
$this->activityManager = $activityManager; | |||
$this->eventMerger = $eventMerger; | |||
} |
@@ -4,6 +4,7 @@ | |||
* | |||
* @author Joas Schilling <coding@schilljs.com> | |||
* @author Julius Härtl <jus@bitgrid.net> | |||
* @author Thomas Citharel <nextcloud@tcit.fr> | |||
* | |||
* @license GNU AGPL version 3 or any later version | |||
* | |||
@@ -24,9 +25,11 @@ | |||
namespace OCA\DAV\CalDAV\Activity\Provider; | |||
use OC_App; | |||
use OCP\Activity\IEvent; | |||
use OCP\Activity\IEventMerger; | |||
use OCP\Activity\IManager; | |||
use OCP\App\IAppManager; | |||
use OCP\IGroupManager; | |||
use OCP\IL10N; | |||
use OCP\IURLGenerator; | |||
@@ -44,15 +47,15 @@ class Event extends Base { | |||
/** @var IL10N */ | |||
protected $l; | |||
/** @var IURLGenerator */ | |||
protected $url; | |||
/** @var IManager */ | |||
protected $activityManager; | |||
/** @var IEventMerger */ | |||
protected $eventMerger; | |||
/** @var IAppManager */ | |||
protected $appManager; | |||
/** | |||
* @param IFactory $languageFactory | |||
* @param IURLGenerator $url | |||
@@ -60,13 +63,50 @@ class Event extends Base { | |||
* @param IUserManager $userManager | |||
* @param IGroupManager $groupManager | |||
* @param IEventMerger $eventMerger | |||
* @param IAppManager $appManager | |||
*/ | |||
public function __construct(IFactory $languageFactory, IURLGenerator $url, IManager $activityManager, IUserManager $userManager, IGroupManager $groupManager, IEventMerger $eventMerger) { | |||
parent::__construct($userManager, $groupManager); | |||
public function __construct(IFactory $languageFactory, IURLGenerator $url, IManager $activityManager, IUserManager $userManager, IGroupManager $groupManager, IEventMerger $eventMerger, IAppManager $appManager) { | |||
parent::__construct($userManager, $groupManager, $url); | |||
$this->languageFactory = $languageFactory; | |||
$this->url = $url; | |||
$this->activityManager = $activityManager; | |||
$this->eventMerger = $eventMerger; | |||
$this->appManager = $appManager; | |||
} | |||
/** | |||
* @param array $eventData | |||
* @return array | |||
*/ | |||
protected function generateObjectParameter(array $eventData) { | |||
if (!isset($eventData['id']) || !isset($eventData['name'])) { | |||
throw new \InvalidArgumentException(); | |||
} | |||
$params = [ | |||
'type' => 'calendar-event', | |||
'id' => $eventData['id'], | |||
'name' => $eventData['name'], | |||
]; | |||
if (isset($eventData['link']) && is_array($eventData['link']) && $this->appManager->isEnabledForUser('calendar')) { | |||
try { | |||
// The calendar app needs to be manually loaded for the routes to be loaded | |||
OC_App::loadApp('calendar'); | |||
$linkData = $eventData['link']; | |||
$objectId = base64_encode('/remote.php/dav/calendars/' . $linkData['owner'] . '/' . $linkData['calendar_uri'] . '/' . $linkData['object_uri']); | |||
$link = [ | |||
'view' => 'dayGridMonth', | |||
'timeRange' => 'now', | |||
'mode' => 'sidebar', | |||
'objectId' => $objectId, | |||
'recurrenceId' => 'next' | |||
]; | |||
$params['link'] = $this->url->linkToRouteAbsolute('calendar.view.indexview.timerange.edit', $link); | |||
} catch (\Exception $error) { | |||
// Do nothing | |||
} | |||
} | |||
return $params; | |||
} | |||
/** |
@@ -29,40 +29,47 @@ use OCA\DAV\CalDAV\Activity\Backend; | |||
use OCA\DAV\CalDAV\Activity\Provider\Calendar; | |||
use OCP\Activity\IEvent; | |||
use OCP\Activity\IManager; | |||
use OCP\App\IAppManager; | |||
use OCP\IGroup; | |||
use OCP\IGroupManager; | |||
use OCP\IUser; | |||
use OCP\IUserSession; | |||
use PHPUnit\Framework\MockObject\MockObject; | |||
use Test\TestCase; | |||
class BackendTest extends TestCase { | |||
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IManager|MockObject */ | |||
protected $activityManager; | |||
/** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IGroupManager|MockObject */ | |||
protected $groupManager; | |||
/** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IUserSession|MockObject */ | |||
protected $userSession; | |||
/** @var IAppManager|MockObject */ | |||
protected $appManager; | |||
protected function setUp(): void { | |||
parent::setUp(); | |||
$this->activityManager = $this->createMock(IManager::class); | |||
$this->groupManager = $this->createMock(IGroupManager::class); | |||
$this->userSession = $this->createMock(IUserSession::class); | |||
$this->appManager = $this->createMock(IAppManager::class); | |||
} | |||
/** | |||
* @param array $methods | |||
* @return Backend|\PHPUnit_Framework_MockObject_MockObject | |||
* @return Backend|MockObject | |||
*/ | |||
protected function getBackend(array $methods = []) { | |||
if (empty($methods)) { | |||
return new Backend( | |||
$this->activityManager, | |||
$this->groupManager, | |||
$this->userSession | |||
$this->userSession, | |||
$this->appManager | |||
); | |||
} else { | |||
return $this->getMockBuilder(Backend::class) | |||
@@ -70,6 +77,7 @@ class BackendTest extends TestCase { | |||
$this->activityManager, | |||
$this->groupManager, | |||
$this->userSession, | |||
$this->appManager, | |||
]) | |||
->setMethods($methods) | |||
->getMock(); | |||
@@ -339,7 +347,7 @@ class BackendTest extends TestCase { | |||
/** | |||
* @param string[] $users | |||
* @return IUser[]|\PHPUnit_Framework_MockObject_MockObject[] | |||
* @return IUser[]|MockObject[] | |||
*/ | |||
protected function getUsers(array $users) { | |||
$list = []; | |||
@@ -351,7 +359,7 @@ class BackendTest extends TestCase { | |||
/** | |||
* @param string $uid | |||
* @return IUser|\PHPUnit_Framework_MockObject_MockObject | |||
* @return IUser|MockObject | |||
*/ | |||
protected function getUserMock($uid) { | |||
$user = $this->createMock(IUser::class); |
@@ -5,6 +5,7 @@ | |||
* @author Joas Schilling <coding@schilljs.com> | |||
* @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> | |||
* @author Roeland Jago Douma <roeland@famdouma.nl> | |||
* @author Thomas Citharel <nextcloud@tcit.fr> | |||
* | |||
* @license GNU AGPL version 3 or any later version | |||
* | |||
@@ -30,29 +31,36 @@ use OCP\Activity\IEvent; | |||
use OCP\Activity\IProvider; | |||
use OCP\IGroupManager; | |||
use OCP\IL10N; | |||
use OCP\IURLGenerator; | |||
use OCP\IUser; | |||
use OCP\IUserManager; | |||
use PHPUnit\Framework\MockObject\MockObject; | |||
use Test\TestCase; | |||
class BaseTest extends TestCase { | |||
/** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IUserManager|MockObject */ | |||
protected $userManager; | |||
/** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IGroupManager|MockObject */ | |||
protected $groupManager; | |||
/** @var IProvider|Base|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IURLGenerator|MockObject */ | |||
protected $url; | |||
/** @var IProvider|Base|MockObject */ | |||
protected $provider; | |||
protected function setUp(): void { | |||
parent::setUp(); | |||
$this->userManager = $this->createMock(IUserManager::class); | |||
$this->groupManager = $this->createMock(IGroupManager::class); | |||
$this->url = $this->createMock(IURLGenerator::class); | |||
$this->provider = $this->getMockBuilder(Base::class) | |||
->setConstructorArgs([ | |||
$this->userManager, | |||
$this->groupManager | |||
$this->groupManager, | |||
$this->url, | |||
]) | |||
->setMethods(['parse']) | |||
->getMock(); | |||
@@ -71,7 +79,7 @@ class BaseTest extends TestCase { | |||
* @param array $parameters | |||
* @param string $parsedSubject | |||
*/ | |||
public function testSetSubjects($subject, array $parameters, $parsedSubject) { | |||
public function testSetSubjects(string $subject, array $parameters, string $parsedSubject) { | |||
$event = $this->createMock(IEvent::class); | |||
$event->expects($this->once()) | |||
->method('setRichSubject') | |||
@@ -85,44 +93,6 @@ class BaseTest extends TestCase { | |||
$this->invokePrivate($this->provider, 'setSubjects', [$event, $subject, $parameters]); | |||
} | |||
public function dataGenerateObjectParameter() { | |||
return [ | |||
[23, 'c1'], | |||
[42, 'c2'], | |||
]; | |||
} | |||
/** | |||
* @dataProvider dataGenerateObjectParameter | |||
* @param int $id | |||
* @param string $name | |||
*/ | |||
public function testGenerateObjectParameter($id, $name) { | |||
$this->assertEquals([ | |||
'type' => 'calendar-event', | |||
'id' => $id, | |||
'name' => $name, | |||
], $this->invokePrivate($this->provider, 'generateObjectParameter', [['id' => $id, 'name' => $name]])); | |||
} | |||
public function dataGenerateObjectParameterThrows() { | |||
return [ | |||
['event'], | |||
[['name' => 'event']], | |||
[['id' => 42]], | |||
]; | |||
} | |||
/** | |||
* @dataProvider dataGenerateObjectParameterThrows | |||
* @param mixed $eventData | |||
*/ | |||
public function testGenerateObjectParameterThrows($eventData) { | |||
$this->expectException(\InvalidArgumentException::class); | |||
$this->invokePrivate($this->provider, 'generateObjectParameter', [$eventData]); | |||
} | |||
public function dataGenerateCalendarParameter() { | |||
return [ | |||
[['id' => 23, 'uri' => 'foo', 'name' => 'bar'], 'bar'], | |||
@@ -137,7 +107,7 @@ class BaseTest extends TestCase { | |||
* @param array $data | |||
* @param string $name | |||
*/ | |||
public function testGenerateCalendarParameter(array $data, $name) { | |||
public function testGenerateCalendarParameter(array $data, string $name) { | |||
$l = $this->createMock(IL10N::class); | |||
$l->expects($this->any()) | |||
->method('t') | |||
@@ -164,7 +134,7 @@ class BaseTest extends TestCase { | |||
* @param int $id | |||
* @param string $name | |||
*/ | |||
public function testGenerateLegacyCalendarParameter($id, $name) { | |||
public function testGenerateLegacyCalendarParameter(int $id, string $name) { | |||
$this->assertEquals([ | |||
'type' => 'calendar', | |||
'id' => $id, | |||
@@ -183,7 +153,7 @@ class BaseTest extends TestCase { | |||
* @dataProvider dataGenerateGroupParameter | |||
* @param string $gid | |||
*/ | |||
public function testGenerateGroupParameter($gid) { | |||
public function testGenerateGroupParameter(string $gid) { | |||
$this->assertEquals([ | |||
'type' => 'user-group', | |||
'id' => $gid, | |||
@@ -208,7 +178,7 @@ class BaseTest extends TestCase { | |||
* @param string $displayName | |||
* @param IUser|null $user | |||
*/ | |||
public function testGenerateUserParameter($uid, $displayName, $user) { | |||
public function testGenerateUserParameter(string $uid, string $displayName, ?IUser $user) { | |||
$this->userManager->expects($this->once()) | |||
->method('get') | |||
->with($uid) |
@@ -0,0 +1,164 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2020 Thomas Citharel <nextcloud@tcit.fr> | |||
* | |||
* @author Thomas Citharel <nextcloud@tcit.fr> | |||
* | |||
* @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\Activity\Provider; | |||
use InvalidArgumentException; | |||
use OCA\DAV\CalDAV\Activity\Provider\Base; | |||
use OCA\DAV\CalDAV\Activity\Provider\Event; | |||
use OCP\Activity\IEventMerger; | |||
use OCP\Activity\IManager; | |||
use OCP\Activity\IProvider; | |||
use OCP\App\IAppManager; | |||
use OCP\IGroupManager; | |||
use OCP\IURLGenerator; | |||
use OCP\IUserManager; | |||
use OCP\L10N\IFactory; | |||
use PHPUnit\Framework\MockObject\MockObject; | |||
use Test\TestCase; | |||
use TypeError; | |||
class EventTest extends TestCase { | |||
/** @var IUserManager|MockObject */ | |||
protected $userManager; | |||
/** @var IGroupManager|MockObject */ | |||
protected $groupManager; | |||
/** @var IURLGenerator|MockObject */ | |||
protected $url; | |||
/** @var IProvider|Base|MockObject */ | |||
protected $provider; | |||
/** @var IAppManager|MockObject */ | |||
protected $appManager; | |||
/** @var IFactory|MockObject */ | |||
protected $i10nFactory; | |||
/** @var IManager|MockObject */ | |||
protected $activityManager; | |||
/** @var IEventMerger|MockObject */ | |||
protected $eventMerger; | |||
protected function setUp(): void { | |||
parent::setUp(); | |||
$this->i10nFactory = $this->createMock(IFactory::class); | |||
$this->userManager = $this->createMock(IUserManager::class); | |||
$this->groupManager = $this->createMock(IGroupManager::class); | |||
$this->activityManager = $this->createMock(IManager::class); | |||
$this->url = $this->createMock(IURLGenerator::class); | |||
$this->appManager = $this->createMock(IAppManager::class); | |||
$this->eventMerger = $this->createMock(IEventMerger::class); | |||
$this->provider = $this->getMockBuilder(Event::class) | |||
->setConstructorArgs([ | |||
$this->i10nFactory, | |||
$this->url, | |||
$this->activityManager, | |||
$this->userManager, | |||
$this->groupManager, | |||
$this->eventMerger, | |||
$this->appManager | |||
]) | |||
->setMethods(['parse']) | |||
->getMock(); | |||
} | |||
public function dataGenerateObjectParameter() { | |||
$link = [ | |||
'object_uri' => 'someuuid.ics', | |||
'calendar_uri' => 'personal', | |||
'owner' => 'someuser' | |||
]; | |||
return [ | |||
[23, 'c1', $link, true], | |||
[23, 'c1', $link, false], | |||
[42, 'c2', null], | |||
]; | |||
} | |||
/** | |||
* @dataProvider dataGenerateObjectParameter | |||
* @param int $id | |||
* @param string $name | |||
* @param array|null $link | |||
* @param bool $calendarAppEnabled | |||
*/ | |||
public function testGenerateObjectParameter(int $id, string $name, ?array $link, bool $calendarAppEnabled = true) { | |||
if ($link) { | |||
$generatedLink = [ | |||
'view' => 'dayGridMonth', | |||
'timeRange' => 'now', | |||
'mode' => 'sidebar', | |||
'objectId' => base64_encode('/remote.php/dav/calendars/' . $link['owner'] . '/' . $link['calendar_uri'] . '/' . $link['object_uri']), | |||
'recurrenceId' => 'next' | |||
]; | |||
$this->appManager->expects($this->once()) | |||
->method('isEnabledForUser') | |||
->with('calendar') | |||
->willReturn($calendarAppEnabled); | |||
if ($calendarAppEnabled) { | |||
$this->url->expects($this->once()) | |||
->method('linkToRouteAbsolute') | |||
->with('calendar.view.indexview.timerange.edit', $generatedLink) | |||
->willReturn('fullLink'); | |||
} | |||
} | |||
$objectParameter = ['id' => $id, 'name' => $name]; | |||
if ($link) { | |||
$objectParameter['link'] = $link; | |||
} | |||
$result = [ | |||
'type' => 'calendar-event', | |||
'id' => $id, | |||
'name' => $name, | |||
]; | |||
if ($link && $calendarAppEnabled) { | |||
$result['link'] = 'fullLink'; | |||
} | |||
$this->assertEquals($result, $this->invokePrivate($this->provider, 'generateObjectParameter', [$objectParameter])); | |||
} | |||
public function dataGenerateObjectParameterThrows() { | |||
return [ | |||
['event', TypeError::class], | |||
[['name' => 'event']], | |||
[['id' => 42]], | |||
]; | |||
} | |||
/** | |||
* @dataProvider dataGenerateObjectParameterThrows | |||
* @param mixed $eventData | |||
* @param string $exception | |||
*/ | |||
public function testGenerateObjectParameterThrows($eventData, string $exception = InvalidArgumentException::class) { | |||
$this->expectException($exception); | |||
$this->invokePrivate($this->provider, 'generateObjectParameter', [$eventData]); | |||
} | |||
} |
@@ -154,6 +154,12 @@ class Definitions { | |||
'description' => 'The display name of the event which should be used in the visual representation', | |||
'example' => 'Workout', | |||
], | |||
'link' => [ | |||
'since' => '19.0.0', | |||
'required' => false, | |||
'description' => 'A link to the page displaying the calendar', | |||
'example' => 'http://localhost/index.php/apps/calendar/dayGridMonth/2020-01-20/edit/sidebar/base64string/1579046400' | |||
] | |||
], | |||
], | |||
'call' => [ |