diff options
author | Morris Jobke <hey@morrisjobke.de> | 2016-10-27 15:30:58 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-27 15:30:58 +0200 |
commit | d4969abc9d306b5b5539f4e7722fc5ee1c722082 (patch) | |
tree | b495bf61e890e8aed244e9cff50fde4e9c38ca86 | |
parent | ba2b274fccdeb06ea9ddba0590644653e073d934 (diff) | |
parent | ced3aeacb1aadfe592894ea666f0aa8777932597 (diff) | |
download | nextcloud-server-d4969abc9d306b5b5539f4e7722fc5ee1c722082.tar.gz nextcloud-server-d4969abc9d306b5b5539f4e7722fc5ee1c722082.zip |
Merge pull request #1800 from nextcloud/nextcloud-rich-object-strings
Nextcloud rich object strings
-rw-r--r-- | apps/federatedfilesharing/appinfo/app.php | 3 | ||||
-rw-r--r-- | apps/federatedfilesharing/lib/Notifier.php | 132 | ||||
-rw-r--r-- | lib/composer/composer/autoload_classmap.php | 3 | ||||
-rw-r--r-- | lib/composer/composer/autoload_static.php | 3 | ||||
-rw-r--r-- | lib/private/AppFramework/DependencyInjection/DIContainer.php | 6 | ||||
-rw-r--r-- | lib/private/Notification/Manager.php | 5 | ||||
-rw-r--r-- | lib/private/Notification/Notification.php | 64 | ||||
-rw-r--r-- | lib/private/RichObjectStrings/Validator.php | 108 | ||||
-rw-r--r-- | lib/public/Notification/INotification.php | 21 | ||||
-rw-r--r-- | lib/public/RichObjectStrings/IValidator.php | 39 | ||||
-rw-r--r-- | lib/public/RichObjectStrings/InvalidObjectExeption.php | 31 | ||||
-rw-r--r-- | lib/public/RichObjectStrings/definitions.json | 228 | ||||
-rw-r--r-- | tests/lib/Notification/NotificationTest.php | 50 | ||||
-rw-r--r-- | tests/lib/RichObjectStrings/ValidatorTest.php | 53 |
14 files changed, 709 insertions, 37 deletions
diff --git a/apps/federatedfilesharing/appinfo/app.php b/apps/federatedfilesharing/appinfo/app.php index f54c47b7829..7f4e4601977 100644 --- a/apps/federatedfilesharing/appinfo/app.php +++ b/apps/federatedfilesharing/appinfo/app.php @@ -32,7 +32,8 @@ $app->registerSettings(); $manager = \OC::$server->getNotificationManager(); $manager->registerNotifier(function() { return new Notifier( - \OC::$server->getL10NFactory() + \OC::$server->getL10NFactory(), + \OC::$server->getContactsManager() ); }, function() use ($l) { return [ diff --git a/apps/federatedfilesharing/lib/Notifier.php b/apps/federatedfilesharing/lib/Notifier.php index 62816ee929b..2cbbea2da42 100644 --- a/apps/federatedfilesharing/lib/Notifier.php +++ b/apps/federatedfilesharing/lib/Notifier.php @@ -24,18 +24,28 @@ namespace OCA\FederatedFileSharing; +use OC\HintException; +use OC\Share\Helper; +use OCP\Contacts\IManager; +use OCP\L10N\IFactory; use OCP\Notification\INotification; use OCP\Notification\INotifier; class Notifier implements INotifier { - /** @var \OCP\L10N\IFactory */ + /** @var IFactory */ protected $factory; + /** @var IManager */ + protected $contactsManager; + /** @var array */ + protected $federatedContacts; /** - * @param \OCP\L10N\IFactory $factory + * @param IFactory $factory + * @param IManager $contactsManager */ - public function __construct(\OCP\L10N\IFactory $factory) { + public function __construct(IFactory $factory, IManager $contactsManager) { $this->factory = $factory; + $this->contactsManager = $contactsManager; } /** @@ -58,11 +68,34 @@ class Notifier implements INotifier { $params = $notification->getSubjectParameters(); if ($params[0] !== $params[1] && $params[1] !== null) { $notification->setParsedSubject( - (string) $l->t('You received "/%3$s" as a remote share from %1$s (on behalf of %2$s)', $params) + $l->t('You received "%3$s" as a remote share from %1$s (on behalf of %2$s)', $params) + ); + $notification->setRichSubject( + $l->t('You received {share} as a remote share from {user} (on behalf of {behalf})'), + [ + 'share' => [ + 'type' => 'pending-federated-share', + 'id' => $notification->getObjectId(), + 'name' => $params[2], + ], + 'user' => $this->createRemoteUser($params[0]), + 'behalf' => $this->createRemoteUser($params[1]), + ] ); } else { $notification->setParsedSubject( - (string)$l->t('You received "/%3$s" as a remote share from %1$s', $params) + $l->t('You received "%3$s" as a remote share from %1$s', $params) + ); + $notification->setRichSubject( + $l->t('You received {share} as a remote share from {user}'), + [ + 'share' => [ + 'type' => 'pending-federated-share', + 'id' => $notification->getObjectId(), + 'name' => $params[2], + ], + 'user' => $this->createRemoteUser($params[0]), + ] ); } @@ -92,4 +125,93 @@ class Notifier implements INotifier { throw new \InvalidArgumentException(); } } + + /** + * @param string $cloudId + * @return array + */ + protected function createRemoteUser($cloudId) { + $displayName = $cloudId; + try { + list($user, $server) = Helper::splitUserRemote($cloudId); + $displayName = $this->getDisplayName($user, $server); + } catch (HintException $e) { + $user = $cloudId; + $server = ''; + } + + return [ + 'type' => 'user', + 'id' => $user, + 'name' => $displayName, + 'server' => $server, + ]; + } + + /** + * Try to find the user in the contacts + * + * @param string $user + * @param string $server + * @return string + * @throws \OutOfBoundsException when there is no contact for the id + */ + protected function getDisplayName($user, $server) { + $server = strtolower(rtrim($server, '/')); + + if (strpos($server, 'http://') === 0) { + $server = substr($server, strlen('http://')); + } else if (strpos($server, 'https://') === 0) { + $server = substr($server, strlen('https://')); + } + + try { + return $this->getDisplayNameFromContact($user . '@' . $server); + } catch (\OutOfBoundsException $e) { + } + + try { + $this->getDisplayNameFromContact($user . '@http://' . $server); + } catch (\OutOfBoundsException $e) { + } + + try { + $this->getDisplayNameFromContact($user . '@https://' . $server); + } catch (\OutOfBoundsException $e) { + } + + return $user . '@' . $server; + } + + /** + * Try to find the user in the contacts + * + * @param string $federatedCloudId + * @return string + * @throws \OutOfBoundsException when there is no contact for the id + */ + protected function getDisplayNameFromContact($federatedCloudId) { + if (isset($this->federatedContacts[$federatedCloudId])) { + if ($this->federatedContacts[$federatedCloudId] !== '') { + return $this->federatedContacts[$federatedCloudId]; + } else { + throw new \OutOfBoundsException('No contact found for federated cloud id'); + } + } + + $addressBookEntries = $this->contactsManager->search($federatedCloudId, ['CLOUD']); + foreach ($addressBookEntries as $entry) { + if (isset($entry['CLOUD'])) { + foreach ($entry['CLOUD'] as $cloudID) { + if ($cloudID === $federatedCloudId) { + $this->federatedContacts[$federatedCloudId] = $entry['FN']; + return $entry['FN']; + } + } + } + } + + $this->federatedContacts[$federatedCloudId] = ''; + throw new \OutOfBoundsException('No contact found for federated cloud id'); + } } diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 1332a570a27..532a6f39848 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -200,6 +200,8 @@ return array( 'OCP\\PreConditionNotMetException' => $baseDir . '/lib/public/PreConditionNotMetException.php', 'OCP\\Preview\\IProvider' => $baseDir . '/lib/public/Preview/IProvider.php', 'OCP\\Response' => $baseDir . '/lib/public/Response.php', + 'OCP\\RichObjectStrings\\IValidator' => $baseDir . '/lib/public/RichObjectStrings/IValidator.php', + 'OCP\\RichObjectStrings\\InvalidObjectExeption' => $baseDir . '/lib/public/RichObjectStrings/InvalidObjectExeption.php', 'OCP\\Route\\IRoute' => $baseDir . '/lib/public/Route/IRoute.php', 'OCP\\Route\\IRouter' => $baseDir . '/lib/public/Route/IRouter.php', 'OCP\\SabrePluginEvent' => $baseDir . '/lib/public/SabrePluginEvent.php', @@ -663,6 +665,7 @@ return array( 'OC\\Repair\\SqliteAutoincrement' => $baseDir . '/lib/private/Repair/SqliteAutoincrement.php', 'OC\\Repair\\UpdateCertificateStore' => $baseDir . '/lib/private/Repair/UpdateCertificateStore.php', 'OC\\Repair\\UpdateOutdatedOcsIds' => $baseDir . '/lib/private/Repair/UpdateOutdatedOcsIds.php', + 'OC\\RichObjectStrings\\Validator' => $baseDir . '/lib/private/RichObjectStrings/Validator.php', 'OC\\Route\\CachingRouter' => $baseDir . '/lib/private/Route/CachingRouter.php', 'OC\\Route\\Route' => $baseDir . '/lib/private/Route/Route.php', 'OC\\Route\\Router' => $baseDir . '/lib/private/Route/Router.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index c9bdc5305fe..c0a3e9b50c6 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -230,6 +230,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\PreConditionNotMetException' => __DIR__ . '/../../..' . '/lib/public/PreConditionNotMetException.php', 'OCP\\Preview\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Preview/IProvider.php', 'OCP\\Response' => __DIR__ . '/../../..' . '/lib/public/Response.php', + 'OCP\\RichObjectStrings\\IValidator' => __DIR__ . '/../../..' . '/lib/public/RichObjectStrings/IValidator.php', + 'OCP\\RichObjectStrings\\InvalidObjectExeption' => __DIR__ . '/../../..' . '/lib/public/RichObjectStrings/InvalidObjectExeption.php', 'OCP\\Route\\IRoute' => __DIR__ . '/../../..' . '/lib/public/Route/IRoute.php', 'OCP\\Route\\IRouter' => __DIR__ . '/../../..' . '/lib/public/Route/IRouter.php', 'OCP\\SabrePluginEvent' => __DIR__ . '/../../..' . '/lib/public/SabrePluginEvent.php', @@ -693,6 +695,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Repair\\SqliteAutoincrement' => __DIR__ . '/../../..' . '/lib/private/Repair/SqliteAutoincrement.php', 'OC\\Repair\\UpdateCertificateStore' => __DIR__ . '/../../..' . '/lib/private/Repair/UpdateCertificateStore.php', 'OC\\Repair\\UpdateOutdatedOcsIds' => __DIR__ . '/../../..' . '/lib/private/Repair/UpdateOutdatedOcsIds.php', + 'OC\\RichObjectStrings\\Validator' => __DIR__ . '/../../..' . '/lib/private/RichObjectStrings/Validator.php', 'OC\\Route\\CachingRouter' => __DIR__ . '/../../..' . '/lib/private/Route/CachingRouter.php', 'OC\\Route\\Route' => __DIR__ . '/../../..' . '/lib/private/Route/Route.php', 'OC\\Route\\Router' => __DIR__ . '/../../..' . '/lib/private/Route/Router.php', diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index 8fe9b4dca03..671093ff08b 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -44,10 +44,12 @@ use OC\AppFramework\Middleware\Security\SecurityMiddleware; use OC\AppFramework\Middleware\SessionMiddleware; use OC\AppFramework\Utility\SimpleContainer; use OC\Core\Middleware\TwoFactorMiddleware; +use OC\RichObjectStrings\Validator; use OCP\AppFramework\IApi; use OCP\AppFramework\IAppContainer; use OCP\Files\IAppData; use OCP\Files\Mount\IMountManager; +use OCP\RichObjectStrings\IValidator; class DIContainer extends SimpleContainer implements IAppContainer { @@ -330,6 +332,10 @@ class DIContainer extends SimpleContainer implements IAppContainer { return $this->getServer()->getEncryptionManager(); }); + $this->registerService(IValidator::class, function($c) { + return $c->query(Validator::class); + }); + /** * App Framework APIs diff --git a/lib/private/Notification/Manager.php b/lib/private/Notification/Manager.php index ec831cf9793..4b57db4bac9 100644 --- a/lib/private/Notification/Manager.php +++ b/lib/private/Notification/Manager.php @@ -24,6 +24,7 @@ namespace OC\Notification; +use OC\RichObjectStrings\Validator; use OCP\Notification\IApp; use OCP\Notification\IManager; use OCP\Notification\INotification; @@ -149,7 +150,9 @@ class Manager implements IManager { * @since 8.2.0 */ public function createNotification() { - return new Notification(); + return new Notification( + new Validator() + ); } /** diff --git a/lib/private/Notification/Notification.php b/lib/private/Notification/Notification.php index 7bf4b9a74cf..7346f35f966 100644 --- a/lib/private/Notification/Notification.php +++ b/lib/private/Notification/Notification.php @@ -26,8 +26,14 @@ namespace OC\Notification; use OCP\Notification\IAction; use OCP\Notification\INotification; +use OCP\RichObjectStrings\InvalidObjectExeption; +use OCP\RichObjectStrings\IValidator; class Notification implements INotification { + + /** @var IValidator */ + protected $richValidator; + /** @var string */ protected $app; @@ -53,6 +59,12 @@ class Notification implements INotification { protected $subjectParsed; /** @var string */ + protected $subjectRich; + + /** @var array */ + protected $subjectRichParameters; + + /** @var string */ protected $message; /** @var array */ @@ -81,8 +93,11 @@ class Notification implements INotification { /** * Constructor + * + * @param IValidator $richValidator */ - public function __construct() { + public function __construct(IValidator $richValidator) { + $this->richValidator = $richValidator; $this->app = ''; $this->user = ''; $this->dateTime = new \DateTime(); @@ -92,6 +107,8 @@ class Notification implements INotification { $this->subject = ''; $this->subjectParameters = []; $this->subjectParsed = ''; + $this->subjectRich = ''; + $this->subjectRichParameters = []; $this->message = ''; $this->messageParameters = []; $this->messageParsed = ''; @@ -262,6 +279,43 @@ class Notification implements INotification { } /** + * @param string $subject + * @param array $parameters + * @return $this + * @throws \InvalidArgumentException if the subject or parameters are invalid + * @since 9.2.0 + */ + public function setRichSubject($subject, array $parameters = []) { + if (!is_string($subject) || $subject === '') { + throw new \InvalidArgumentException('The given parsed subject is invalid'); + } + $this->subjectRich = $subject; + + if (!is_array($parameters)) { + throw new \InvalidArgumentException('The given subject parameters are invalid'); + } + $this->subjectRichParameters = $parameters; + + return $this; + } + + /** + * @return string + * @since 9.2.0 + */ + public function getRichSubject() { + return $this->subjectRich; + } + + /** + * @return array[] + * @since 9.2.0 + */ + public function getRichSubjectParameters() { + return $this->subjectRichParameters; + } + + /** * @param string $message * @param array $parameters * @return $this @@ -454,6 +508,14 @@ class Notification implements INotification { * @since 8.2.0 */ public function isValidParsed() { + if ($this->getRichSubject() !== '' || !empty($this->getRichSubjectParameters())) { + try { + $this->richValidator->validate($this->getRichSubject(), $this->getRichSubjectParameters()); + } catch (InvalidObjectExeption $e) { + return false; + } + } + return $this->isValidCommon() && diff --git a/lib/private/RichObjectStrings/Validator.php b/lib/private/RichObjectStrings/Validator.php new file mode 100644 index 00000000000..2729b4a3f1b --- /dev/null +++ b/lib/private/RichObjectStrings/Validator.php @@ -0,0 +1,108 @@ +<?php +/** + * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.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 OC\RichObjectStrings; + + +use OCP\RichObjectStrings\InvalidObjectExeption; +use OCP\RichObjectStrings\IValidator; + +/** + * Class Validator + * + * @package OCP\RichObjectStrings + * @since 9.2.0 + */ +class Validator implements IValidator { + + /** @var array[] */ + protected $definitions; + + /** @var array[] */ + protected $requiredParameters = []; + + /** + * Constructor + */ + public function __construct() { + $this->definitions = json_decode(file_get_contents(__DIR__ . '/../../public/RichObjectStrings/definitions.json'), true); + } + + /** + * @param string $subject + * @param array[] $parameters + * @throws InvalidObjectExeption + * @since 9.2.0 + */ + public function validate($subject, array $parameters) { + $matches = []; + $result = preg_match_all('/\{([a-z0-9]+)\}/i', $subject, $matches); + + if ($result === false) { + throw new InvalidObjectExeption(); + } + + if (!empty($matches[1])) { + foreach ($matches[1] as $parameter) { + if (!isset($parameters[$parameter])) { + throw new InvalidObjectExeption('Parameter is undefined'); + } else { + $this->validateParameter($parameters[$parameter]); + } + } + } + } + + /** + * @param array $parameter + * @throws InvalidObjectExeption + */ + protected function validateParameter(array $parameter) { + if (!isset($parameter['type']) || !isset($this->definitions[$parameter['type']])) { + throw new InvalidObjectExeption('Object type is undefined'); + } + + $requiredParameters = $this->getRequiredParameters($parameter['type']); + $missingKeys = array_diff($requiredParameters, array_keys($parameter)); + if (!empty($missingKeys)) { + throw new InvalidObjectExeption('Object is invalid'); + } + } + + /** + * @param string $type + * @return string[] + */ + protected function getRequiredParameters($type) { + if (isset($this->requiredParameters[$type])) { + return $this->requiredParameters[$type]; + } + + $this->requiredParameters[$type] = []; + foreach ($this->definitions[$type]['parameters'] as $parameter => $data) { + if ($data['required']) { + $this->requiredParameters[$type][] = $parameter; + } + } + + return $this->requiredParameters[$type]; + } +} diff --git a/lib/public/Notification/INotification.php b/lib/public/Notification/INotification.php index fd16876a666..3a8bde0a375 100644 --- a/lib/public/Notification/INotification.php +++ b/lib/public/Notification/INotification.php @@ -128,6 +128,27 @@ interface INotification { public function getParsedSubject(); /** + * @param string $subject + * @param array $parameters + * @return $this + * @throws \InvalidArgumentException if the subject or parameters are invalid + * @since 9.2.0 + */ + public function setRichSubject($subject, array $parameters = []); + + /** + * @return string + * @since 9.2.0 + */ + public function getRichSubject(); + + /** + * @return array[] + * @since 9.2.0 + */ + public function getRichSubjectParameters(); + + /** * @param string $message * @param array $parameters * @return $this diff --git a/lib/public/RichObjectStrings/IValidator.php b/lib/public/RichObjectStrings/IValidator.php new file mode 100644 index 00000000000..bba098bdfc1 --- /dev/null +++ b/lib/public/RichObjectStrings/IValidator.php @@ -0,0 +1,39 @@ +<?php +/** + * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.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 OCP\RichObjectStrings; + +/** + * Class Validator + * + * @package OCP\RichObjectStrings + * @since 9.2.0 + */ +interface IValidator { + + /** + * @param string $subject + * @param array[] $parameters + * @throws InvalidObjectExeption + * @since 9.2.0 + */ + public function validate($subject, array $parameters); +} diff --git a/lib/public/RichObjectStrings/InvalidObjectExeption.php b/lib/public/RichObjectStrings/InvalidObjectExeption.php new file mode 100644 index 00000000000..8bf597ebe90 --- /dev/null +++ b/lib/public/RichObjectStrings/InvalidObjectExeption.php @@ -0,0 +1,31 @@ +<?php +/** + * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.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 OCP\RichObjectStrings; + +/** + * Class InvalidObjectExeption + * + * @package OCP\RichObjectStrings + * @since 9.2.0 + */ +class InvalidObjectExeption extends \InvalidArgumentException { +} diff --git a/lib/public/RichObjectStrings/definitions.json b/lib/public/RichObjectStrings/definitions.json new file mode 100644 index 00000000000..222f6615cf4 --- /dev/null +++ b/lib/public/RichObjectStrings/definitions.json @@ -0,0 +1,228 @@ +{ + "addressbook": { + "author": "Nextcloud", + "app": "dav", + "since": "9.2.0", + "parameters": { + "id": { + "since": "9.2.0", + "required": true, + "description": "The id used to identify the addressbook on the instance", + "example": "42" + }, + "name": { + "since": "9.2.0", + "required": true, + "description": "The display name of the addressbook which should be used in the visual representation", + "example": "Contacts" + } + } + }, + "addressbook-contact": { + "author": "Nextcloud", + "app": "dav", + "since": "9.2.0", + "parameters": { + "id": { + "since": "9.2.0", + "required": true, + "description": "The id used to identify the contact on the instance", + "example": "42" + }, + "name": { + "since": "9.2.0", + "required": true, + "description": "The display name of the contact which should be used in the visual representation", + "example": "John Doe" + } + } + }, + "announcement": { + "author": "Joas Schilling", + "app": "announcementcenter", + "since": "9.2.0", + "parameters": { + "id": { + "since": "9.2.0", + "required": true, + "description": "The id used to identify the announcement on the instance", + "example": "42" + }, + "name": { + "since": "9.2.0", + "required": true, + "description": "The announcement subject which should be used in the visual representation", + "example": "file.txt" + }, + "link": { + "since": "9.2.0", + "required": false, + "description": "The full URL to the file", + "example": "http://localhost/index.php/apps/announcements/#23" + } + } + }, + "calendar": { + "author": "Nextcloud", + "app": "dav", + "since": "9.2.0", + "parameters": { + "id": { + "since": "9.2.0", + "required": true, + "description": "The id used to identify the calendar on the instance", + "example": "42" + }, + "name": { + "since": "9.2.0", + "required": true, + "description": "The display name of the calendar which should be used in the visual representation", + "example": "Personal" + } + } + }, + "calendar-event": { + "author": "Nextcloud", + "app": "dav", + "since": "9.2.0", + "parameters": { + "id": { + "since": "9.2.0", + "required": true, + "description": "The id used to identify the event on the instance", + "example": "42" + }, + "name": { + "since": "9.2.0", + "required": true, + "description": "The display name of the event which should be used in the visual representation", + "example": "Workout" + } + } + }, + "file": { + "author": "Nextcloud", + "app": "dav", + "since": "9.2.0", + "parameters": { + "id": { + "since": "9.2.0", + "required": true, + "description": "The id used to identify the file on the instance", + "example": "42" + }, + "name": { + "since": "9.2.0", + "required": true, + "description": "The file name which should be used in the visual representation", + "example": "file.txt" + }, + "path": { + "since": "9.2.0", + "required": true, + "description": "The full path of the file for the user", + "example": "path/to/file.txt" + }, + "link": { + "since": "9.2.0", + "required": false, + "description": "The full URL to the file", + "example": "http://localhost/index.php/f/42" + } + } + }, + "pending-federated-share": { + "author": "Nextcloud", + "app": "dav", + "since": "9.2.0", + "parameters": { + "id": { + "since": "9.2.0", + "required": true, + "description": "The id used to identify the federated share on the instance", + "example": "42" + }, + "name": { + "since": "9.2.0", + "required": true, + "description": "The name of the shared item which should be used in the visual representation", + "example": "file.txt" + } + } + }, + "systemtag": { + "author": "Nextcloud", + "app": "core", + "since": "9.2.0", + "parameters": { + "id": { + "since": "9.2.0", + "required": true, + "description": "The id used to identify the systemtag on the instance", + "example": "23" + }, + "name": { + "since": "9.2.0", + "required": true, + "description": "The display name of the systemtag which should be used in the visual representation", + "example": "Project 1" + }, + "visibility": { + "since": "9.2.0", + "required": true, + "description": "If the user can see the systemtag", + "example": "1" + }, + "assignable": { + "since": "9.2.0", + "required": true, + "description": "If the user can assign the systemtag", + "example": "0" + } + } + }, + "user": { + "author": "Nextcloud", + "app": "core", + "since": "9.2.0", + "parameters": { + "id": { + "since": "9.2.0", + "required": true, + "description": "The id used to identify the user on the instance", + "example": "johndoe" + }, + "name": { + "since": "9.2.0", + "required": true, + "description": "The display name of the user which should be used in the visual representation", + "example": "John Doe" + }, + "server": { + "since": "9.2.0", + "required": false, + "description": "The URL of the instance the user lives on", + "example": "localhost" + } + } + }, + "user-group": { + "author": "Nextcloud", + "app": "core", + "since": "9.2.0", + "parameters": { + "id": { + "since": "9.2.0", + "required": true, + "description": "The id used to identify the group on the instance", + "example": "supportteam" + }, + "name": { + "since": "9.2.0", + "required": true, + "description": "The display name of the group which should be used in the visual representation", + "example": "Support Team" + } + } + } +} diff --git a/tests/lib/Notification/NotificationTest.php b/tests/lib/Notification/NotificationTest.php index 77d9e989cf1..eabed273608 100644 --- a/tests/lib/Notification/NotificationTest.php +++ b/tests/lib/Notification/NotificationTest.php @@ -23,16 +23,21 @@ namespace Test\Notification; use OC\Notification\Notification; +use OCP\Notification\IAction; use OCP\Notification\INotification; +use OCP\RichObjectStrings\IValidator; use Test\TestCase; class NotificationTest extends TestCase { /** @var INotification */ protected $notification; + /** @var IValidator|\PHPUnit_Framework_MockObject_MockObject */ + protected $validator; public function setUp() { parent::setUp(); - $this->notification = new Notification(); + $this->validator = $this->createMock(IValidator::class); + $this->notification = new Notification($this->validator); } protected function dataValidString($maxLength) { @@ -416,14 +421,12 @@ class NotificationTest extends TestCase { public function testCreateAction() { $action = $this->notification->createAction(); - $this->assertInstanceOf('OCP\Notification\IAction', $action); + $this->assertInstanceOf(IAction::class, $action); } public function testAddAction() { /** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ - $action = $this->getMockBuilder('OCP\Notification\IAction') - ->disableOriginalConstructor() - ->getMock(); + $action = $this->createMock(IAction::class); $action->expects($this->once()) ->method('isValid') ->willReturn(true); @@ -441,9 +444,7 @@ class NotificationTest extends TestCase { */ public function testAddActionInvalid() { /** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ - $action = $this->getMockBuilder('OCP\Notification\IAction') - ->disableOriginalConstructor() - ->getMock(); + $action = $this->createMock(IAction::class); $action->expects($this->once()) ->method('isValid') ->willReturn(false); @@ -455,9 +456,7 @@ class NotificationTest extends TestCase { public function testAddActionSecondPrimary() { /** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ - $action = $this->getMockBuilder('OCP\Notification\IAction') - ->disableOriginalConstructor() - ->getMock(); + $action = $this->createMock(IAction::class); $action->expects($this->exactly(2)) ->method('isValid') ->willReturn(true); @@ -473,9 +472,7 @@ class NotificationTest extends TestCase { public function testAddParsedAction() { /** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ - $action = $this->getMockBuilder('OCP\Notification\IAction') - ->disableOriginalConstructor() - ->getMock(); + $action = $this->createMock(IAction::class); $action->expects($this->once()) ->method('isValidParsed') ->willReturn(true); @@ -493,9 +490,7 @@ class NotificationTest extends TestCase { */ public function testAddParsedActionInvalid() { /** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ - $action = $this->getMockBuilder('OCP\Notification\IAction') - ->disableOriginalConstructor() - ->getMock(); + $action = $this->createMock(IAction::class); $action->expects($this->once()) ->method('isValidParsed') ->willReturn(false); @@ -507,9 +502,7 @@ class NotificationTest extends TestCase { public function testAddActionSecondParsedPrimary() { /** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ - $action = $this->getMockBuilder('OCP\Notification\IAction') - ->disableOriginalConstructor() - ->getMock(); + $action = $this->createMock(IAction::class); $action->expects($this->exactly(2)) ->method('isValidParsed') ->willReturn(true); @@ -525,9 +518,7 @@ class NotificationTest extends TestCase { public function testAddActionParsedPrimaryEnd() { /** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ - $action1 = $this->getMockBuilder('OCP\Notification\IAction') - ->disableOriginalConstructor() - ->getMock(); + $action1 = $this->createMock(IAction::class); $action1->expects($this->exactly(2)) ->method('isValidParsed') ->willReturn(true); @@ -535,9 +526,7 @@ class NotificationTest extends TestCase { ->method('isPrimary') ->willReturn(false); /** @var \OCP\Notification\IAction|\PHPUnit_Framework_MockObject_MockObject $action */ - $action2 = $this->getMockBuilder('OCP\Notification\IAction') - ->disableOriginalConstructor() - ->getMock(); + $action2 = $this->createMock(IAction::class); $action2->expects($this->once()) ->method('isValidParsed') ->willReturn(true); @@ -570,12 +559,13 @@ class NotificationTest extends TestCase { */ public function testIsValid($isValidCommon, $subject, $expected) { /** @var \OCP\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */ - $notification = $this->getMockBuilder('\OC\Notification\Notification') + $notification = $this->getMockBuilder(Notification::class) ->setMethods([ 'isValidCommon', 'getSubject', 'getParsedSubject', ]) + ->setConstructorArgs([$this->validator]) ->getMock(); $notification->expects($this->once()) @@ -602,12 +592,13 @@ class NotificationTest extends TestCase { */ public function testIsParsedValid($isValidCommon, $subject, $expected) { /** @var \OCP\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */ - $notification = $this->getMockBuilder('\OC\Notification\Notification') + $notification = $this->getMockBuilder(Notification::class) ->setMethods([ 'isValidCommon', 'getParsedSubject', 'getSubject', ]) + ->setConstructorArgs([$this->validator]) ->getMock(); $notification->expects($this->once()) @@ -648,7 +639,7 @@ class NotificationTest extends TestCase { */ public function testIsValidCommon($app, $user, $timestamp, $objectType, $objectId, $expected) { /** @var \OCP\Notification\INotification|\PHPUnit_Framework_MockObject_MockObject $notification */ - $notification = $this->getMockBuilder('\OC\Notification\Notification') + $notification = $this->getMockBuilder(Notification::class) ->setMethods([ 'getApp', 'getUser', @@ -656,6 +647,7 @@ class NotificationTest extends TestCase { 'getObjectType', 'getObjectId', ]) + ->setConstructorArgs([$this->validator]) ->getMock(); $notification->expects($this->any()) diff --git a/tests/lib/RichObjectStrings/ValidatorTest.php b/tests/lib/RichObjectStrings/ValidatorTest.php new file mode 100644 index 00000000000..b97388ab8e0 --- /dev/null +++ b/tests/lib/RichObjectStrings/ValidatorTest.php @@ -0,0 +1,53 @@ +<?php +/** + * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.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 Test\RichObjectStrings; + + +use OC\RichObjectStrings\Validator; +use Test\TestCase; + +class ValidatorTest extends TestCase { + + public function test() { + $v = new Validator(); + $v->validate('test', []); + $v->validate('test {string1} test {foo} test {bar}.', [ + 'string1' => [ + 'type' => 'user', + 'id' => 'johndoe', + 'name' => 'John Doe', + ], + 'foo' => [ + 'type' => 'user-group', + 'id' => 'sample', + 'name' => 'Sample Group', + ], + 'bar' => [ + 'type' => 'file', + 'id' => '42', + 'name' => 'test.txt', + 'path' => 'path/to/test.txt', + ], + ]); + } + +} |