Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 1 | <?php |
| 2 | |
| 3 | /* |
| 4 | * This file is part of the Symfony package. |
| 5 | * |
| 6 | * (c) Fabien Potencier <fabien@symfony.com> |
| 7 | * |
| 8 | * For the full copyright and license information, please view the LICENSE |
| 9 | * file that was distributed with this source code. |
| 10 | */ |
| 11 | |
| 12 | namespace Symfony\Polyfill\Ctype; |
| 13 | |
| 14 | /** |
| 15 | * Ctype implementation through regex. |
| 16 | * |
| 17 | * @internal |
| 18 | * |
| 19 | * @author Gert de Pagter <BackEndTea@gmail.com> |
| 20 | */ |
| 21 | final class Ctype |
| 22 | { |
| 23 | /** |
| 24 | * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise. |
| 25 | * |
| 26 | * @see https://php.net/ctype-alnum |
| 27 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 28 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 29 | * |
| 30 | * @return bool |
| 31 | */ |
| 32 | public static function ctype_alnum($text) |
| 33 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 34 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 35 | |
| 36 | return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text); |
| 37 | } |
| 38 | |
| 39 | /** |
| 40 | * Returns TRUE if every character in text is a letter, FALSE otherwise. |
| 41 | * |
| 42 | * @see https://php.net/ctype-alpha |
| 43 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 44 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 45 | * |
| 46 | * @return bool |
| 47 | */ |
| 48 | public static function ctype_alpha($text) |
| 49 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 50 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 51 | |
| 52 | return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text); |
| 53 | } |
| 54 | |
| 55 | /** |
| 56 | * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise. |
| 57 | * |
| 58 | * @see https://php.net/ctype-cntrl |
| 59 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 60 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 61 | * |
| 62 | * @return bool |
| 63 | */ |
| 64 | public static function ctype_cntrl($text) |
| 65 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 66 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 67 | |
| 68 | return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text); |
| 69 | } |
| 70 | |
| 71 | /** |
| 72 | * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise. |
| 73 | * |
| 74 | * @see https://php.net/ctype-digit |
| 75 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 76 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 77 | * |
| 78 | * @return bool |
| 79 | */ |
| 80 | public static function ctype_digit($text) |
| 81 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 82 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 83 | |
| 84 | return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text); |
| 85 | } |
| 86 | |
| 87 | /** |
| 88 | * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise. |
| 89 | * |
| 90 | * @see https://php.net/ctype-graph |
| 91 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 92 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 93 | * |
| 94 | * @return bool |
| 95 | */ |
| 96 | public static function ctype_graph($text) |
| 97 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 98 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 99 | |
| 100 | return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text); |
| 101 | } |
| 102 | |
| 103 | /** |
| 104 | * Returns TRUE if every character in text is a lowercase letter. |
| 105 | * |
| 106 | * @see https://php.net/ctype-lower |
| 107 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 108 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 109 | * |
| 110 | * @return bool |
| 111 | */ |
| 112 | public static function ctype_lower($text) |
| 113 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 114 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 115 | |
| 116 | return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text); |
| 117 | } |
| 118 | |
| 119 | /** |
| 120 | * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all. |
| 121 | * |
| 122 | * @see https://php.net/ctype-print |
| 123 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 124 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 125 | * |
| 126 | * @return bool |
| 127 | */ |
| 128 | public static function ctype_print($text) |
| 129 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 130 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 131 | |
| 132 | return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text); |
| 133 | } |
| 134 | |
| 135 | /** |
| 136 | * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise. |
| 137 | * |
| 138 | * @see https://php.net/ctype-punct |
| 139 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 140 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 141 | * |
| 142 | * @return bool |
| 143 | */ |
| 144 | public static function ctype_punct($text) |
| 145 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 146 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 147 | |
| 148 | return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text); |
| 149 | } |
| 150 | |
| 151 | /** |
| 152 | * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters. |
| 153 | * |
| 154 | * @see https://php.net/ctype-space |
| 155 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 156 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 157 | * |
| 158 | * @return bool |
| 159 | */ |
| 160 | public static function ctype_space($text) |
| 161 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 162 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 163 | |
| 164 | return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text); |
| 165 | } |
| 166 | |
| 167 | /** |
| 168 | * Returns TRUE if every character in text is an uppercase letter. |
| 169 | * |
| 170 | * @see https://php.net/ctype-upper |
| 171 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 172 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 173 | * |
| 174 | * @return bool |
| 175 | */ |
| 176 | public static function ctype_upper($text) |
| 177 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 178 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 179 | |
| 180 | return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text); |
| 181 | } |
| 182 | |
| 183 | /** |
| 184 | * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise. |
| 185 | * |
| 186 | * @see https://php.net/ctype-xdigit |
| 187 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 188 | * @param mixed $text |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 189 | * |
| 190 | * @return bool |
| 191 | */ |
| 192 | public static function ctype_xdigit($text) |
| 193 | { |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 194 | $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 195 | |
| 196 | return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text); |
| 197 | } |
| 198 | |
| 199 | /** |
| 200 | * Converts integers to their char versions according to normal ctype behaviour, if needed. |
| 201 | * |
| 202 | * If an integer between -128 and 255 inclusive is provided, |
| 203 | * it is interpreted as the ASCII value of a single character |
| 204 | * (negative values have 256 added in order to allow characters in the Extended ASCII range). |
| 205 | * Any other integer is interpreted as a string containing the decimal digits of the integer. |
| 206 | * |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 207 | * @param mixed $int |
| 208 | * @param string $function |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 209 | * |
| 210 | * @return mixed |
| 211 | */ |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 212 | private static function convert_int_to_char_for_ctype($int, $function) |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 213 | { |
| 214 | if (!\is_int($int)) { |
| 215 | return $int; |
| 216 | } |
| 217 | |
| 218 | if ($int < -128 || $int > 255) { |
| 219 | return (string) $int; |
| 220 | } |
| 221 | |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 222 | if (\PHP_VERSION_ID >= 80100) { |
| 223 | @trigger_error($function.'(): Argument of type int will be interpreted as string in the future', \E_USER_DEPRECATED); |
| 224 | } |
| 225 | |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame] | 226 | if ($int < 0) { |
| 227 | $int += 256; |
| 228 | } |
| 229 | |
| 230 | return \chr($int); |
| 231 | } |
| 232 | } |