From 20986488505616654177da1f861238f0232656fa Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 12 Oct 2016 12:08:42 +0200 Subject: [PATCH] Add Rich Object Definitions and a validator Signed-off-by: Joas Schilling --- .../DependencyInjection/DIContainer.php | 6 + lib/private/RichObjectStrings/Validator.php | 108 +++++++++ lib/public/RichObjectStrings/IValidator.php | 39 ++++ .../InvalidObjectExeption.php | 31 +++ lib/public/RichObjectStrings/definitions.json | 209 ++++++++++++++++++ tests/lib/RichObjectStrings/ValidatorTest.php | 53 +++++ 6 files changed, 446 insertions(+) create mode 100644 lib/private/RichObjectStrings/Validator.php create mode 100644 lib/public/RichObjectStrings/IValidator.php create mode 100644 lib/public/RichObjectStrings/InvalidObjectExeption.php create mode 100644 lib/public/RichObjectStrings/definitions.json create mode 100644 tests/lib/RichObjectStrings/ValidatorTest.php diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index 21d5eaa950..b2fdf86d9c 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/RichObjectStrings/Validator.php b/lib/private/RichObjectStrings/Validator.php new file mode 100644 index 0000000000..2729b4a3f1 --- /dev/null +++ b/lib/private/RichObjectStrings/Validator.php @@ -0,0 +1,108 @@ + + * + * @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 . + * + */ + +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/RichObjectStrings/IValidator.php b/lib/public/RichObjectStrings/IValidator.php new file mode 100644 index 0000000000..bba098bdfc --- /dev/null +++ b/lib/public/RichObjectStrings/IValidator.php @@ -0,0 +1,39 @@ + + * + * @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 . + * + */ + +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 0000000000..8bf597ebe9 --- /dev/null +++ b/lib/public/RichObjectStrings/InvalidObjectExeption.php @@ -0,0 +1,31 @@ + + * + * @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 . + * + */ + +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 0000000000..581572eb34 --- /dev/null +++ b/lib/public/RichObjectStrings/definitions.json @@ -0,0 +1,209 @@ +{ + "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" + } + } + }, + "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/RichObjectStrings/ValidatorTest.php b/tests/lib/RichObjectStrings/ValidatorTest.php new file mode 100644 index 0000000000..b97388ab8e --- /dev/null +++ b/tests/lib/RichObjectStrings/ValidatorTest.php @@ -0,0 +1,53 @@ + + * + * @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 . + * + */ + +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', + ], + ]); + } + +}