Validator.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OC\RichObjectStrings;
  8. use OCP\RichObjectStrings\Definitions;
  9. use OCP\RichObjectStrings\InvalidObjectExeption;
  10. use OCP\RichObjectStrings\IValidator;
  11. /**
  12. * Class Validator
  13. *
  14. * @psalm-import-type RichObjectParameter from IValidator
  15. * @package OCP\RichObjectStrings
  16. * @since 11.0.0
  17. */
  18. class Validator implements IValidator {
  19. protected array $requiredParameters = [];
  20. public function __construct(
  21. protected Definitions $definitions,
  22. ) {
  23. }
  24. /**
  25. * @param string $subject
  26. * @param array<non-empty-string, RichObjectParameter> $parameters
  27. * @throws InvalidObjectExeption
  28. * @since 11.0.0
  29. */
  30. public function validate(string $subject, array $parameters): void {
  31. $matches = [];
  32. $result = preg_match_all('/\{(' . self::PLACEHOLDER_REGEX . ')\}/', $subject, $matches);
  33. if ($result === false) {
  34. throw new InvalidObjectExeption();
  35. }
  36. if (!empty($matches[1])) {
  37. foreach ($matches[1] as $parameter) {
  38. if (!isset($parameters[$parameter])) {
  39. throw new InvalidObjectExeption('Parameter is undefined');
  40. }
  41. }
  42. }
  43. foreach ($parameters as $placeholder => $parameter) {
  44. if (!\is_string($placeholder) || !preg_match('/^(' . self::PLACEHOLDER_REGEX . ')$/i', $placeholder)) {
  45. throw new InvalidObjectExeption('Parameter key is invalid');
  46. }
  47. if (!\is_array($parameter)) {
  48. throw new InvalidObjectExeption('Parameter is malformed');
  49. }
  50. $this->validateParameter($parameter);
  51. }
  52. }
  53. /**
  54. * @param array $parameter
  55. * @throws InvalidObjectExeption
  56. */
  57. protected function validateParameter(array $parameter): void {
  58. if (!isset($parameter['type'])) {
  59. throw new InvalidObjectExeption('Object type is undefined');
  60. }
  61. $definition = $this->definitions->getDefinition($parameter['type']);
  62. $requiredParameters = $this->getRequiredParameters($parameter['type'], $definition);
  63. $missingKeys = array_diff($requiredParameters, array_keys($parameter));
  64. if (!empty($missingKeys)) {
  65. throw new InvalidObjectExeption('Object is invalid, missing keys:' . json_encode($missingKeys));
  66. }
  67. foreach ($parameter as $key => $value) {
  68. if (!is_string($key)) {
  69. throw new InvalidObjectExeption('Object is invalid, key ' . $key . ' is not a string');
  70. }
  71. if (!is_string($value)) {
  72. throw new InvalidObjectExeption('Object is invalid, value ' . $value . ' is not a string');
  73. }
  74. }
  75. }
  76. /**
  77. * @param string $type
  78. * @param array $definition
  79. * @return string[]
  80. */
  81. protected function getRequiredParameters(string $type, array $definition): array {
  82. if (isset($this->requiredParameters[$type])) {
  83. return $this->requiredParameters[$type];
  84. }
  85. $this->requiredParameters[$type] = [];
  86. foreach ($definition['parameters'] as $parameter => $data) {
  87. if ($data['required']) {
  88. $this->requiredParameters[$type][] = $parameter;
  89. }
  90. }
  91. return $this->requiredParameters[$type];
  92. }
  93. }