diff options
Diffstat (limited to 'lib/private/RichObjectStrings')
-rw-r--r-- | lib/private/RichObjectStrings/RichTextFormatter.php | 36 | ||||
-rw-r--r-- | lib/private/RichObjectStrings/Validator.php | 109 |
2 files changed, 145 insertions, 0 deletions
diff --git a/lib/private/RichObjectStrings/RichTextFormatter.php b/lib/private/RichObjectStrings/RichTextFormatter.php new file mode 100644 index 00000000000..9c9ddf94fa9 --- /dev/null +++ b/lib/private/RichObjectStrings/RichTextFormatter.php @@ -0,0 +1,36 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\RichObjectStrings; + +use OCP\RichObjectStrings\IRichTextFormatter; + +class RichTextFormatter implements IRichTextFormatter { + /** + * @throws \InvalidArgumentException if a parameter has no name or no type + */ + public function richToParsed(string $message, array $parameters): string { + $placeholders = []; + $replacements = []; + foreach ($parameters as $placeholder => $parameter) { + $placeholders[] = '{' . $placeholder . '}'; + foreach (['name','type'] as $requiredField) { + if (!isset($parameter[$requiredField]) || !is_string($parameter[$requiredField])) { + throw new \InvalidArgumentException("Invalid rich object, {$requiredField} field is missing"); + } + } + $replacements[] = match($parameter['type']) { + 'user' => '@' . $parameter['name'], + 'file' => $parameter['path'] ?? $parameter['name'], + default => $parameter['name'], + }; + } + return str_replace($placeholders, $replacements, $message); + } +} diff --git a/lib/private/RichObjectStrings/Validator.php b/lib/private/RichObjectStrings/Validator.php new file mode 100644 index 00000000000..adc4a8710f7 --- /dev/null +++ b/lib/private/RichObjectStrings/Validator.php @@ -0,0 +1,109 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\RichObjectStrings; + +use OCP\RichObjectStrings\Definitions; +use OCP\RichObjectStrings\InvalidObjectExeption; +use OCP\RichObjectStrings\IValidator; + +/** + * Class Validator + * + * @psalm-import-type RichObjectParameter from IValidator + * @package OCP\RichObjectStrings + * @since 11.0.0 + */ +class Validator implements IValidator { + protected array $requiredParameters = []; + + public function __construct( + protected Definitions $definitions, + ) { + } + + /** + * @param string $subject + * @param array<non-empty-string, RichObjectParameter> $parameters + * @throws InvalidObjectExeption + * @since 11.0.0 + */ + public function validate(string $subject, array $parameters): void { + $matches = []; + $result = preg_match_all('/\{(' . self::PLACEHOLDER_REGEX . ')\}/', $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'); + } + } + } + + foreach ($parameters as $placeholder => $parameter) { + if (!\is_string($placeholder) || !preg_match('/^(' . self::PLACEHOLDER_REGEX . ')$/i', $placeholder)) { + throw new InvalidObjectExeption('Parameter key is invalid'); + } + if (!\is_array($parameter)) { + throw new InvalidObjectExeption('Parameter is malformed'); + } + + $this->validateParameter($placeholder, $parameter); + } + } + + /** + * @param array $parameter + * @throws InvalidObjectExeption + */ + protected function validateParameter(string $placeholder, array $parameter): void { + if (!isset($parameter['type'])) { + throw new InvalidObjectExeption('Object type is undefined'); + } + + $definition = $this->definitions->getDefinition($parameter['type']); + $requiredParameters = $this->getRequiredParameters($parameter['type'], $definition); + + $missingKeys = array_diff($requiredParameters, array_keys($parameter)); + if (!empty($missingKeys)) { + throw new InvalidObjectExeption('Object for placeholder ' . $placeholder . ' is invalid, missing keys:' . json_encode($missingKeys)); + } + + foreach ($parameter as $key => $value) { + if (!is_string($key)) { + throw new InvalidObjectExeption('Object for placeholder ' . $placeholder . ' is invalid, key ' . $key . ' is not a string'); + } + if (!is_string($value)) { + throw new InvalidObjectExeption('Object for placeholder ' . $placeholder . ' is invalid, value ' . $value . ' for key ' . $key . ' is not a string'); + } + } + } + + /** + * @param string $type + * @param array $definition + * @return string[] + */ + protected function getRequiredParameters(string $type, array $definition): array { + if (isset($this->requiredParameters[$type])) { + return $this->requiredParameters[$type]; + } + + $this->requiredParameters[$type] = []; + foreach ($definition['parameters'] as $parameter => $data) { + if ($data['required']) { + $this->requiredParameters[$type][] = $parameter; + } + } + + return $this->requiredParameters[$type]; + } +} |