PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/personal_collection_movies/vendor/symfony/symfony/src/Symfony/Component/Validator/Constraints/UuidValidator.php

https://gitlab.com/luchoman08/personal_collection_mv
PHP | 249 lines | 134 code | 45 blank | 70 comment | 23 complexity | c54d70a405896365e5027dd21d4520cf MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Validator\Constraints;
  11. use Symfony\Component\Validator\Constraint;
  12. use Symfony\Component\Validator\ConstraintValidator;
  13. use Symfony\Component\Validator\Exception\UnexpectedTypeException;
  14. /**
  15. * Validates whether the value is a valid UUID per RFC 4122.
  16. *
  17. * @author Colin O'Dell <colinodell@gmail.com>
  18. * @author Bernhard Schussek <bschussek@gmail.com>
  19. *
  20. * @see http://tools.ietf.org/html/rfc4122
  21. * @see https://en.wikipedia.org/wiki/Universally_unique_identifier
  22. */
  23. class UuidValidator extends ConstraintValidator
  24. {
  25. // The strict pattern matches UUIDs like this:
  26. // xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
  27. // Roughly speaking:
  28. // x = any hexadecimal character
  29. // M = any allowed version {1..5}
  30. // N = any allowed variant {8, 9, a, b}
  31. const STRICT_LENGTH = 36;
  32. const STRICT_FIRST_HYPHEN_POSITION = 8;
  33. const STRICT_LAST_HYPHEN_POSITION = 23;
  34. const STRICT_VERSION_POSITION = 14;
  35. const STRICT_VARIANT_POSITION = 19;
  36. // The loose pattern validates similar yet non-compliant UUIDs.
  37. // Hyphens are completely optional. If present, they should only appear
  38. // between every fourth character:
  39. // xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx
  40. // xxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxx
  41. // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  42. // The value can also be wrapped with characters like []{}:
  43. // {xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx}
  44. // Neither the version nor the variant is validated by this pattern.
  45. const LOOSE_MAX_LENGTH = 39;
  46. const LOOSE_FIRST_HYPHEN_POSITION = 4;
  47. /**
  48. * {@inheritdoc}
  49. */
  50. public function validate($value, Constraint $constraint)
  51. {
  52. if (null === $value || '' === $value) {
  53. return;
  54. }
  55. if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
  56. throw new UnexpectedTypeException($value, 'string');
  57. }
  58. $value = (string) $value;
  59. if ($constraint->strict) {
  60. $this->validateStrict($value, $constraint);
  61. return;
  62. }
  63. $this->validateLoose($value, $constraint);
  64. }
  65. private function validateLoose($value, Uuid $constraint)
  66. {
  67. // Error priority:
  68. // 1. ERROR_INVALID_CHARACTERS
  69. // 2. ERROR_INVALID_HYPHEN_PLACEMENT
  70. // 3. ERROR_TOO_SHORT/ERROR_TOO_LONG
  71. // Trim any wrapping characters like [] or {} used by some legacy systems
  72. $trimmed = trim($value, '[]{}');
  73. // Position of the next expected hyphen
  74. $h = self::LOOSE_FIRST_HYPHEN_POSITION;
  75. // Expected length
  76. $l = self::LOOSE_MAX_LENGTH;
  77. for ($i = 0; $i < $l; ++$i) {
  78. // Check length
  79. if (!isset($trimmed{$i})) {
  80. $this->context->buildViolation($constraint->message)
  81. ->setParameter('{{ value }}', $this->formatValue($value))
  82. ->setCode(Uuid::TOO_SHORT_ERROR)
  83. ->addViolation();
  84. return;
  85. }
  86. // Hyphens must occur every fifth position
  87. // xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx
  88. // ^ ^ ^ ^ ^ ^ ^
  89. if ('-' === $trimmed{$i}) {
  90. if ($i !== $h) {
  91. $this->context->buildViolation($constraint->message)
  92. ->setParameter('{{ value }}', $this->formatValue($value))
  93. ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR)
  94. ->addViolation();
  95. return;
  96. }
  97. $h += 5;
  98. continue;
  99. }
  100. // Missing hyphens are ignored
  101. if ($i === $h) {
  102. $h += 4;
  103. --$l;
  104. }
  105. // Check characters
  106. if (!ctype_xdigit($trimmed{$i})) {
  107. $this->context->buildViolation($constraint->message)
  108. ->setParameter('{{ value }}', $this->formatValue($value))
  109. ->setCode(Uuid::INVALID_CHARACTERS_ERROR)
  110. ->addViolation();
  111. return;
  112. }
  113. }
  114. // Check length again
  115. if (isset($trimmed{$i})) {
  116. $this->context->buildViolation($constraint->message)
  117. ->setParameter('{{ value }}', $this->formatValue($value))
  118. ->setCode(Uuid::TOO_LONG_ERROR)
  119. ->addViolation();
  120. }
  121. }
  122. private function validateStrict($value, Uuid $constraint)
  123. {
  124. // Error priority:
  125. // 1. ERROR_INVALID_CHARACTERS
  126. // 2. ERROR_INVALID_HYPHEN_PLACEMENT
  127. // 3. ERROR_TOO_SHORT/ERROR_TOO_LONG
  128. // 4. ERROR_INVALID_VERSION
  129. // 5. ERROR_INVALID_VARIANT
  130. // Position of the next expected hyphen
  131. $h = self::STRICT_FIRST_HYPHEN_POSITION;
  132. for ($i = 0; $i < self::STRICT_LENGTH; ++$i) {
  133. // Check length
  134. if (!isset($value{$i})) {
  135. $this->context->buildViolation($constraint->message)
  136. ->setParameter('{{ value }}', $this->formatValue($value))
  137. ->setCode(Uuid::TOO_SHORT_ERROR)
  138. ->addViolation();
  139. return;
  140. }
  141. // Check hyphen placement
  142. // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  143. // ^ ^ ^ ^
  144. if ('-' === $value{$i}) {
  145. if ($i !== $h) {
  146. $this->context->buildViolation($constraint->message)
  147. ->setParameter(
  148. '{{ value }}',
  149. $this->formatValue($value)
  150. )
  151. ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR)
  152. ->addViolation();
  153. return;
  154. }
  155. // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  156. // ^
  157. if ($h < self::STRICT_LAST_HYPHEN_POSITION) {
  158. $h += 5;
  159. }
  160. continue;
  161. }
  162. // Check characters
  163. if (!ctype_xdigit($value{$i})) {
  164. $this->context->buildViolation($constraint->message)
  165. ->setParameter('{{ value }}', $this->formatValue($value))
  166. ->setCode(Uuid::INVALID_CHARACTERS_ERROR)
  167. ->addViolation();
  168. return;
  169. }
  170. // Missing hyphen
  171. if ($i === $h) {
  172. $this->context->buildViolation($constraint->message)
  173. ->setParameter('{{ value }}', $this->formatValue($value))
  174. ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR)
  175. ->addViolation();
  176. return;
  177. }
  178. }
  179. // Check length again
  180. if (isset($value{$i})) {
  181. $this->context->buildViolation($constraint->message)
  182. ->setParameter('{{ value }}', $this->formatValue($value))
  183. ->setCode(Uuid::TOO_LONG_ERROR)
  184. ->addViolation();
  185. }
  186. // Check version
  187. if (!in_array($value{self::STRICT_VERSION_POSITION}, $constraint->versions)) {
  188. $this->context->buildViolation($constraint->message)
  189. ->setParameter('{{ value }}', $this->formatValue($value))
  190. ->setCode(Uuid::INVALID_VERSION_ERROR)
  191. ->addViolation();
  192. }
  193. // Check variant - first two bits must equal "10"
  194. // 0b10xx
  195. // & 0b1100 (12)
  196. // = 0b1000 (8)
  197. if ((hexdec($value{self::STRICT_VARIANT_POSITION}) & 12) !== 8) {
  198. $this->context->buildViolation($constraint->message)
  199. ->setParameter('{{ value }}', $this->formatValue($value))
  200. ->setCode(Uuid::INVALID_VARIANT_ERROR)
  201. ->addViolation();
  202. }
  203. }
  204. }