Php83.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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\Polyfill\Php83;
  11. /**
  12. * @author Ion Bazan <ion.bazan@gmail.com>
  13. * @author Pierre Ambroise <pierre27.ambroise@gmail.com>
  14. *
  15. * @internal
  16. */
  17. final class Php83
  18. {
  19. private const JSON_MAX_DEPTH = 0x7FFFFFFF; // see https://www.php.net/manual/en/function.json-decode.php
  20. public static function json_validate(string $json, int $depth = 512, int $flags = 0): bool
  21. {
  22. if (0 !== $flags && \defined('JSON_INVALID_UTF8_IGNORE') && \JSON_INVALID_UTF8_IGNORE !== $flags) {
  23. throw new \ValueError('json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE)');
  24. }
  25. if ($depth <= 0) {
  26. throw new \ValueError('json_validate(): Argument #2 ($depth) must be greater than 0');
  27. }
  28. if ($depth > self::JSON_MAX_DEPTH) {
  29. throw new \ValueError(\sprintf('json_validate(): Argument #2 ($depth) must be less than %d', self::JSON_MAX_DEPTH));
  30. }
  31. json_decode($json, true, $depth, $flags);
  32. return \JSON_ERROR_NONE === json_last_error();
  33. }
  34. /** @return string|false */
  35. public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null)
  36. {
  37. if (null === $encoding) {
  38. $encoding = mb_internal_encoding();
  39. }
  40. $errorToTrigger = null;
  41. try {
  42. if (!@mb_check_encoding('', $encoding)) {
  43. $errorToTrigger = \sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding);
  44. }
  45. } catch (\ValueError $e) {
  46. $errorToTrigger = \sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding);
  47. }
  48. if (null === $errorToTrigger && mb_strlen($pad_string, $encoding) <= 0) {
  49. $errorToTrigger = 'mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string';
  50. }
  51. if (null === $errorToTrigger && !\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) {
  52. $errorToTrigger = 'mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH';
  53. }
  54. if (null !== $errorToTrigger) {
  55. if (80000 > \PHP_VERSION_ID) {
  56. trigger_error($errorToTrigger, \E_USER_WARNING);
  57. return false;
  58. }
  59. throw new \ValueError($errorToTrigger);
  60. }
  61. $paddingRequired = $length - mb_strlen($string, $encoding);
  62. if ($paddingRequired < 1) {
  63. return $string;
  64. }
  65. switch ($pad_type) {
  66. case \STR_PAD_LEFT:
  67. return mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string;
  68. case \STR_PAD_RIGHT:
  69. return $string.mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding);
  70. default:
  71. $leftPaddingLength = floor($paddingRequired / 2);
  72. $rightPaddingLength = $paddingRequired - $leftPaddingLength;
  73. return mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding);
  74. }
  75. }
  76. public static function str_increment(string $string): string
  77. {
  78. if ('' === $string) {
  79. throw new \ValueError('str_increment(): Argument #1 ($string) cannot be empty');
  80. }
  81. if (!preg_match('/^[a-zA-Z0-9]+$/', $string)) {
  82. throw new \ValueError('str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters');
  83. }
  84. for ($i = \strlen($string) - 1; $i >= 0; --$i) {
  85. $char = $string[$i];
  86. if ('z' === $char) {
  87. $string[$i] = 'a';
  88. continue;
  89. }
  90. if ('Z' === $char) {
  91. $string[$i] = 'A';
  92. continue;
  93. }
  94. if ('9' === $char) {
  95. $string[$i] = '0';
  96. continue;
  97. }
  98. $string[$i] = \chr(\ord($char) + 1);
  99. return $string;
  100. }
  101. switch ($string[0]) {
  102. case 'a': return 'a'.$string;
  103. case 'A': return 'A'.$string;
  104. }
  105. return '1'.$string;
  106. }
  107. public static function str_decrement(string $string): string
  108. {
  109. if ('' === $string) {
  110. throw new \ValueError('str_decrement(): Argument #1 ($string) cannot be empty');
  111. }
  112. if (!preg_match('/^[a-zA-Z0-9]+$/', $string)) {
  113. throw new \ValueError('str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters');
  114. }
  115. if (preg_match('/\A(?:0[aA0]?|[aA])\z/', $string)) {
  116. throw new \ValueError(\sprintf('str_decrement(): Argument #1 ($string) "%s" is out of decrement range', $string));
  117. }
  118. if (!\in_array(substr($string, -1), ['A', 'a', '0'], true)) {
  119. return implode('', \array_slice(str_split($string), 0, -1)).\chr(\ord(substr($string, -1)) - 1);
  120. }
  121. $carry = '';
  122. $decremented = '';
  123. for ($i = \strlen($string) - 1; $i >= 0; --$i) {
  124. $char = $string[$i];
  125. switch ($char) {
  126. case 'A':
  127. if ('' !== $carry) {
  128. $decremented = $carry.$decremented;
  129. $carry = '';
  130. }
  131. $carry = 'Z';
  132. break;
  133. case 'a':
  134. if ('' !== $carry) {
  135. $decremented = $carry.$decremented;
  136. $carry = '';
  137. }
  138. $carry = 'z';
  139. break;
  140. case '0':
  141. if ('' !== $carry) {
  142. $decremented = $carry.$decremented;
  143. $carry = '';
  144. }
  145. $carry = '9';
  146. break;
  147. case '1':
  148. if ('' !== $carry) {
  149. $decremented = $carry.$decremented;
  150. $carry = '';
  151. }
  152. break;
  153. default:
  154. if ('' !== $carry) {
  155. $decremented = $carry.$decremented;
  156. $carry = '';
  157. }
  158. if (!\in_array($char, ['A', 'a', '0'], true)) {
  159. $decremented = \chr(\ord($char) - 1).$decremented;
  160. }
  161. }
  162. }
  163. return $decremented;
  164. }
  165. }