├── .laminas-ci.json ├── COPYRIGHT.md ├── src ├── Exception │ ├── ExceptionInterface.php │ ├── RecursionException.php │ ├── RuntimeException.php │ ├── BadMethodCallException.php │ └── InvalidArgumentException.php ├── Expr.php ├── Json.php ├── Decoder.php └── Encoder.php ├── phpcs.xml.dist ├── LICENSE.md ├── composer.json ├── README.md └── composer.lock /.laminas-ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_php_platform_requirements": { 3 | "8.4": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /COPYRIGHT.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/) 2 | -------------------------------------------------------------------------------- /src/Exception/ExceptionInterface.php: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | src 17 | test 18 | 19 | 20 | 21 | 22 | 23 | src/ 24 | 25 | 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | - Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | - Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | - Neither the name of Laminas Foundation nor the names of its contributors may 14 | be used to endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /src/Expr.php: -------------------------------------------------------------------------------- 1 | 17 | * $foo = array( 18 | * 'integer' => 9, 19 | * 'string' => 'test string', 20 | * 'function' => Laminas\Json\Expr( 21 | * 'function () { window.alert("javascript function encoded by Laminas\Json\Json") }' 22 | * ), 23 | * ); 24 | * 25 | * echo Laminas\Json\Json::encode($foo, false, ['enableJsonExprFinder' => true]); 26 | * 27 | * 28 | * The above returns the following JSON (formatted for readability): 29 | * 30 | * 31 | * { 32 | * "integer": 9, 33 | * "string": "test string", 34 | * "function": function () {window.alert("javascript function encoded by Laminas\Json\Json")} 35 | * } 36 | * 37 | */ 38 | class Expr implements Stringable 39 | { 40 | /** 41 | * Storage for javascript expression. 42 | * 43 | * @var string 44 | */ 45 | protected $expression; 46 | 47 | /** 48 | * @param string $expression The expression to represent. 49 | */ 50 | public function __construct($expression) 51 | { 52 | $this->expression = (string) $expression; 53 | } 54 | 55 | /** 56 | * Cast to string 57 | * 58 | * @return string holded javascript expression. 59 | */ 60 | public function __toString(): string 61 | { 62 | return $this->expression; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laminas/laminas-json", 3 | "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", 4 | "license": "BSD-3-Clause", 5 | "keywords": [ 6 | "laminas", 7 | "json" 8 | ], 9 | "homepage": "https://laminas.dev", 10 | "support": { 11 | "docs": "https://docs.laminas.dev/laminas-json/", 12 | "issues": "https://github.com/laminas/laminas-json/issues", 13 | "source": "https://github.com/laminas/laminas-json", 14 | "rss": "https://github.com/laminas/laminas-json/releases.atom", 15 | "chat": "https://laminas.dev/chat", 16 | "forum": "https://discourse.laminas.dev" 17 | }, 18 | "config": { 19 | "sort-packages": true, 20 | "allow-plugins": { 21 | "dealerdirect/phpcodesniffer-composer-installer": true 22 | } 23 | }, 24 | "abandoned": true, 25 | "require": { 26 | "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" 27 | }, 28 | "require-dev": { 29 | "laminas/laminas-coding-standard": "~2.4.0", 30 | "laminas/laminas-stdlib": "^2.7.7 || ^3.19", 31 | "phpunit/phpunit": "^9.5.25" 32 | }, 33 | "suggest": { 34 | "laminas/laminas-json-server": "For implementing JSON-RPC servers", 35 | "laminas/laminas-xml2json": "For converting XML documents to JSON" 36 | }, 37 | "autoload": { 38 | "psr-4": { 39 | "Laminas\\Json\\": "src/" 40 | } 41 | }, 42 | "autoload-dev": { 43 | "psr-4": { 44 | "LaminasTest\\Json\\": "test/" 45 | } 46 | }, 47 | "scripts": { 48 | "check": [ 49 | "@cs-check", 50 | "@test" 51 | ], 52 | "cs-check": "phpcs", 53 | "cs-fix": "phpcbf", 54 | "test": "phpunit --colors=always", 55 | "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" 56 | }, 57 | "conflict": { 58 | "zendframework/zend-json": "*" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # laminas-json 2 | 3 | > [!CAUTION] 4 | > This package is **abandoned** and will receive no further development. 5 | > 6 | > See the Technical Steering Committee [meeting minutes](https://github.com/laminas/technical-steering-committee/blob/main/meetings/minutes/2024-11-04-TSC-Minutes.md#archive--abandon-various-legacy-libraries). 7 | 8 | > ## 🇷🇺 Русским гражданам 9 | > 10 | > Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм. 11 | > 12 | > У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую. 13 | > 14 | > Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!" 15 | > 16 | > ## 🇺🇸 To Citizens of Russia 17 | > 18 | > We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism. 19 | > 20 | > One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences. 21 | > 22 | > You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!" 23 | 24 | `Laminas\Json` provides convenience methods for serializing native PHP to JSON and 25 | decoding JSON to native PHP. For more information on JSON, visit the JSON 26 | [project site](http://www.json.org/). 27 | 28 | ## Installation 29 | 30 | Run the following to install this library: 31 | 32 | ```bash 33 | $ composer require laminas/laminas-json 34 | ``` 35 | 36 | ## Documentation 37 | 38 | Browse the documentation online at https://docs.laminas.dev/laminas-json/ 39 | -------------------------------------------------------------------------------- /src/Json.php: -------------------------------------------------------------------------------- 1 | toJson(); 102 | } 103 | 104 | if (method_exists($valueToEncode, 'toArray')) { 105 | return static::encode($valueToEncode->toArray(), $cycleCheck, $options); 106 | } 107 | } 108 | 109 | // Pre-process and replace javascript expressions with placeholders 110 | $javascriptExpressions = new SplQueue(); 111 | if ( 112 | isset($options['enableJsonExprFinder']) 113 | && $options['enableJsonExprFinder'] === true 114 | ) { 115 | $valueToEncode = static::recursiveJsonExprFinder($valueToEncode, $javascriptExpressions); 116 | } 117 | 118 | // Encoding 119 | $prettyPrint = isset($options['prettyPrint']) && ($options['prettyPrint'] === true); 120 | $encodedResult = self::encodeValue($valueToEncode, $cycleCheck, $options, $prettyPrint); 121 | 122 | // Post-process to revert back any Laminas\Json\Expr instances. 123 | $encodedResult = self::injectJavascriptExpressions($encodedResult, $javascriptExpressions); 124 | 125 | return $encodedResult; 126 | } 127 | 128 | /** 129 | * Discover and replace javascript expressions with temporary placeholders. 130 | * 131 | * Check each value to determine if it is a Laminas\Json\Expr; if so, replace the value with 132 | * a magic key and add the javascript expression to the queue. 133 | * 134 | * NOTE this method is recursive. 135 | * 136 | * NOTE: This method is used internally by the encode method. 137 | * 138 | * @see encode 139 | * 140 | * @param mixed $value a string - object property to be encoded 141 | * @param null|string|int $currentKey 142 | * @return mixed 143 | */ 144 | protected static function recursiveJsonExprFinder( 145 | mixed $value, 146 | SplQueue $javascriptExpressions, 147 | $currentKey = null 148 | ) { 149 | if ($value instanceof Expr) { 150 | // TODO: Optimize with ascii keys, if performance is bad 151 | $magicKey = "____" . $currentKey . "_" . count($javascriptExpressions); 152 | 153 | $javascriptExpressions->enqueue([ 154 | // If currentKey is integer, encodeUnicodeString call is not required. 155 | 'magicKey' => is_int($currentKey) ? $magicKey : Encoder::encodeUnicodeString($magicKey), 156 | 'value' => $value, 157 | ]); 158 | 159 | return $magicKey; 160 | } 161 | 162 | if (is_array($value)) { 163 | foreach ($value as $k => $v) { 164 | $value[$k] = static::recursiveJsonExprFinder($value[$k], $javascriptExpressions, $k); 165 | } 166 | return $value; 167 | } 168 | 169 | if (is_object($value)) { 170 | foreach ($value as $k => $v) { 171 | $value->$k = static::recursiveJsonExprFinder($value->$k, $javascriptExpressions, $k); 172 | } 173 | return $value; 174 | } 175 | 176 | return $value; 177 | } 178 | 179 | /** 180 | * Pretty-print JSON string 181 | * 182 | * Use 'indent' option to select indentation string; by default, four 183 | * spaces are used. 184 | * 185 | * @param string $json Original JSON string 186 | * @param array $options Encoding options 187 | * @return string 188 | */ 189 | public static function prettyPrint($json, array $options = []) 190 | { 191 | $indentString = $options['indent'] ?? ' '; 192 | 193 | $json = trim($json); 194 | $length = strlen($json); 195 | $stack = []; 196 | 197 | $result = ''; 198 | $inLiteral = false; 199 | 200 | for ($i = 0; $i < $length; ++$i) { 201 | switch ($json[$i]) { 202 | case '{': 203 | case '[': 204 | if ($inLiteral) { 205 | break; 206 | } 207 | 208 | $stack[] = $json[$i]; 209 | 210 | $result .= $json[$i]; 211 | while (isset($json[$i + 1]) && preg_match('/\s/', $json[$i + 1])) { 212 | ++$i; 213 | } 214 | if (isset($json[$i + 1]) && $json[$i + 1] !== '}' && $json[$i + 1] !== ']') { 215 | $result .= "\n" . str_repeat($indentString, count($stack)); 216 | } 217 | 218 | continue 2; 219 | case '}': 220 | case ']': 221 | if ($inLiteral) { 222 | break; 223 | } 224 | 225 | $last = end($stack); 226 | if ( 227 | ($last === '{' && $json[$i] === '}') 228 | || ($last === '[' && $json[$i] === ']') 229 | ) { 230 | array_pop($stack); 231 | } 232 | 233 | $result .= $json[$i]; 234 | while (isset($json[$i + 1]) && preg_match('/\s/', $json[$i + 1])) { 235 | ++$i; 236 | } 237 | if (isset($json[$i + 1]) && ($json[$i + 1] === '}' || $json[$i + 1] === ']')) { 238 | $result .= "\n" . str_repeat($indentString, count($stack) - 1); 239 | } 240 | 241 | continue 2; 242 | case '"': 243 | $result .= '"'; 244 | 245 | if (! $inLiteral) { 246 | $inLiteral = true; 247 | } else { 248 | $backslashes = 0; 249 | $n = $i; 250 | while ($json[--$n] === '\\') { 251 | ++$backslashes; 252 | } 253 | 254 | if (($backslashes % 2) === 0) { 255 | $inLiteral = false; 256 | 257 | while (isset($json[$i + 1]) && preg_match('/\s/', $json[$i + 1])) { 258 | ++$i; 259 | } 260 | 261 | if (isset($json[$i + 1]) && ($json[$i + 1] === '}' || $json[$i + 1] === ']')) { 262 | $result .= "\n" . str_repeat($indentString, count($stack) - 1); 263 | } 264 | } 265 | } 266 | continue 2; 267 | case ':': 268 | if (! $inLiteral) { 269 | $result .= ': '; 270 | continue 2; 271 | } 272 | break; 273 | case ',': 274 | if (! $inLiteral) { 275 | $result .= ',' . "\n" . str_repeat($indentString, count($stack)); 276 | continue 2; 277 | } 278 | break; 279 | default: 280 | if (! $inLiteral && preg_match('/\s/', $json[$i])) { 281 | continue 2; 282 | } 283 | break; 284 | } 285 | 286 | $result .= $json[$i]; 287 | 288 | if ($inLiteral) { 289 | continue; 290 | } 291 | 292 | while (isset($json[$i + 1]) && preg_match('/\s/', $json[$i + 1])) { 293 | ++$i; 294 | } 295 | 296 | if (isset($json[$i + 1]) && ($json[$i + 1] === '}' || $json[$i + 1] === ']')) { 297 | $result .= "\n" . str_repeat($indentString, count($stack) - 1); 298 | } 299 | } 300 | 301 | return $result; 302 | } 303 | 304 | /** 305 | * Decode a value using the PHP built-in json_decode function. 306 | * 307 | * @param string $encodedValue 308 | * @param int $objectDecodeType 309 | * @return mixed 310 | * @throws RuntimeException 311 | */ 312 | private static function decodeViaPhpBuiltIn($encodedValue, $objectDecodeType) 313 | { 314 | $decoded = json_decode($encodedValue, (bool) $objectDecodeType); 315 | 316 | switch (json_last_error()) { 317 | case JSON_ERROR_NONE: 318 | return $decoded; 319 | case JSON_ERROR_DEPTH: 320 | throw new RuntimeException('Decoding failed: Maximum stack depth exceeded'); 321 | case JSON_ERROR_CTRL_CHAR: 322 | throw new RuntimeException('Decoding failed: Unexpected control character found'); 323 | case JSON_ERROR_SYNTAX: 324 | throw new RuntimeException('Decoding failed: Syntax error'); 325 | default: 326 | throw new RuntimeException('Decoding failed'); 327 | } 328 | } 329 | 330 | /** 331 | * Encode a value to JSON. 332 | * 333 | * Intermediary step between injecting JavaScript expressions. 334 | * 335 | * Delegates to either the PHP built-in json_encode operation, or the 336 | * Encoder component, based on availability of the built-in and/or whether 337 | * or not the component encoder is requested. 338 | * 339 | * @param bool $cycleCheck 340 | * @param array $options 341 | * @param bool $prettyPrint 342 | * @return string 343 | */ 344 | private static function encodeValue(mixed $valueToEncode, $cycleCheck, array $options, $prettyPrint) 345 | { 346 | if (function_exists('json_encode') && static::$useBuiltinEncoderDecoder !== true) { 347 | return self::encodeViaPhpBuiltIn($valueToEncode, $prettyPrint); 348 | } 349 | 350 | return self::encodeViaEncoder($valueToEncode, $cycleCheck, $options, $prettyPrint); 351 | } 352 | 353 | /** 354 | * Encode a value to JSON using the PHP built-in json_encode function. 355 | * 356 | * Uses the encoding options: 357 | * 358 | * - JSON_HEX_TAG 359 | * - JSON_HEX_APOS 360 | * - JSON_HEX_QUOT 361 | * - JSON_HEX_AMP 362 | * 363 | * If $prettyPrint is boolean true, also uses JSON_PRETTY_PRINT. 364 | * 365 | * @param bool $prettyPrint 366 | * @return string|false Boolean false return value if json_encode is not 367 | * available, or the $useBuiltinEncoderDecoder flag is enabled. 368 | */ 369 | private static function encodeViaPhpBuiltIn(mixed $valueToEncode, $prettyPrint = false) 370 | { 371 | if (! function_exists('json_encode') || static::$useBuiltinEncoderDecoder === true) { 372 | return false; 373 | } 374 | 375 | $encodeOptions = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP; 376 | 377 | if ($prettyPrint) { 378 | $encodeOptions |= JSON_PRETTY_PRINT; 379 | } 380 | 381 | return json_encode($valueToEncode, $encodeOptions); 382 | } 383 | 384 | /** 385 | * Encode a value to JSON using the Encoder class. 386 | * 387 | * Passes the value, cycle check flag, and options to Encoder::encode(). 388 | * 389 | * Once the result is returned, determines if pretty printing is required, 390 | * and, if so, returns the result of that operation, otherwise returning 391 | * the encoded value. 392 | * 393 | * @param bool $cycleCheck 394 | * @param array $options 395 | * @param bool $prettyPrint 396 | * @return string 397 | */ 398 | private static function encodeViaEncoder(mixed $valueToEncode, $cycleCheck, array $options, $prettyPrint) 399 | { 400 | $encodedResult = Encoder::encode($valueToEncode, $cycleCheck, $options); 401 | 402 | if ($prettyPrint) { 403 | return self::prettyPrint($encodedResult, ['indent' => ' ']); 404 | } 405 | 406 | return $encodedResult; 407 | } 408 | 409 | /** 410 | * Inject javascript expressions into the encoded value. 411 | * 412 | * Loops through each, substituting the "magicKey" of each with its 413 | * associated value. 414 | * 415 | * @param string $encodedValue 416 | * @return string 417 | */ 418 | private static function injectJavascriptExpressions($encodedValue, SplQueue $javascriptExpressions) 419 | { 420 | foreach ($javascriptExpressions as $expression) { 421 | $encodedValue = str_replace( 422 | sprintf('"%s"', $expression['magicKey']), 423 | $expression['value'], 424 | (string) $encodedValue 425 | ); 426 | } 427 | 428 | return $encodedValue; 429 | } 430 | } 431 | -------------------------------------------------------------------------------- /src/Decoder.php: -------------------------------------------------------------------------------- 1 | = 0x20) && ($ordChrsC <= 0x7F): 122 | $utf8 .= $chrs[$i]; 123 | break; 124 | case ($ordChrsC & 0xE0) === 0xC0: 125 | // characters U-00000080 - U-000007FF, mask 110XXXXX 126 | //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 127 | $utf8 .= substr($chrs, $i, 2); 128 | ++$i; 129 | break; 130 | case ($ordChrsC & 0xF0) === 0xE0: 131 | // characters U-00000800 - U-0000FFFF, mask 1110XXXX 132 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 133 | $utf8 .= substr($chrs, $i, 3); 134 | $i += 2; 135 | break; 136 | case ($ordChrsC & 0xF8) === 0xF0: 137 | // characters U-00010000 - U-001FFFFF, mask 11110XXX 138 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 139 | $utf8 .= substr($chrs, $i, 4); 140 | $i += 3; 141 | break; 142 | case ($ordChrsC & 0xFC) === 0xF8: 143 | // characters U-00200000 - U-03FFFFFF, mask 111110XX 144 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 145 | $utf8 .= substr($chrs, $i, 5); 146 | $i += 4; 147 | break; 148 | case ($ordChrsC & 0xFE) === 0xFC: 149 | // characters U-04000000 - U-7FFFFFFF, mask 1111110X 150 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 151 | $utf8 .= substr($chrs, $i, 6); 152 | $i += 5; 153 | break; 154 | } 155 | } 156 | 157 | return $utf8; 158 | } 159 | 160 | /** 161 | * Constructor 162 | * 163 | * @param string $source String source to decode 164 | * @param int $decodeType How objects should be decoded -- see 165 | * {@link Json::TYPE_ARRAY} and {@link Json::TYPE_OBJECT} for * valid 166 | * values 167 | * @throws InvalidArgumentException 168 | */ 169 | protected function __construct($source, $decodeType) 170 | { 171 | // Set defaults 172 | $this->source = self::decodeUnicodeString($source); 173 | $this->sourceLength = strlen($this->source); 174 | $this->token = self::EOF; 175 | $this->offset = 0; 176 | 177 | $this->decodeType = match ($decodeType) { 178 | Json::TYPE_ARRAY, Json::TYPE_OBJECT => $decodeType, 179 | default => throw new InvalidArgumentException(sprintf( 180 | 'Unknown decode type "%s", please use one of the Json::TYPE_* constants', 181 | $decodeType 182 | )), 183 | }; 184 | 185 | // Set pointer at first token 186 | $this->getNextToken(); 187 | } 188 | 189 | /** 190 | * Decode a JSON source string. 191 | * 192 | * Decodes a JSON encoded string; the value returned will be one of the 193 | * following: 194 | * 195 | * - integer 196 | * - float 197 | * - boolean 198 | * - null 199 | * - stdClass 200 | * - array 201 | * - array of one or more of the above types 202 | * 203 | * By default, decoded objects will be returned as a stdClass object; 204 | * to return associative arrays instead, pass {@link Json::TYPE_ARRAY} 205 | * to the $objectDecodeType parameter. 206 | * 207 | * @param string $source String to be decoded. 208 | * @param int $objectDecodeType How objects should be decoded; should be 209 | * either or {@link Json::TYPE_ARRAY} or {@link Json::TYPE_OBJECT}; 210 | * defaults to Json::TYPE_OBJECT. 211 | * @return mixed 212 | */ 213 | public static function decode($source, $objectDecodeType = Json::TYPE_OBJECT) 214 | { 215 | $decoder = new static($source, $objectDecodeType); 216 | return $decoder->decodeValue(); 217 | } 218 | 219 | /** 220 | * Recursive routine for supported toplevel types. 221 | * 222 | * @return mixed 223 | */ 224 | protected function decodeValue() 225 | { 226 | switch ($this->token) { 227 | case self::DATUM: 228 | $result = $this->tokenValue; 229 | $this->getNextToken(); 230 | return $result; 231 | case self::LBRACE: 232 | return $this->decodeObject(); 233 | case self::LBRACKET: 234 | return $this->decodeArray(); 235 | default: 236 | return; 237 | } 238 | } 239 | 240 | /** 241 | * Decodes an object of the form { "attribute: value, "attribute2" : value, ... } 242 | * 243 | * If Laminas\Json\Encoder was used to encode the original object, then 244 | * a special attribute called __className will specify a class 245 | * name with which to wrap the data contained within the encoded source. 246 | * 247 | * Decodes to either an array or stdClass object, based on the value of 248 | * {@link $decodeType}. If invalid $decodeType present, returns as an 249 | * array. 250 | * 251 | * @return array|stdClass 252 | * @throws RuntimeException 253 | */ 254 | protected function decodeObject() 255 | { 256 | $members = []; 257 | $tok = $this->getNextToken(); 258 | 259 | while ($tok && $tok !== self::RBRACE) { 260 | if ($tok !== self::DATUM || ! is_string($this->tokenValue)) { 261 | throw new RuntimeException(sprintf('Missing key in object encoding: %s', $this->source)); 262 | } 263 | 264 | $key = $this->tokenValue; 265 | $tok = $this->getNextToken(); 266 | 267 | if ($tok !== self::COLON) { 268 | throw new RuntimeException(sprintf('Missing ":" in object encoding: %s', $this->source)); 269 | } 270 | 271 | $this->getNextToken(); 272 | $members[$key] = $this->decodeValue(); 273 | $tok = $this->token; 274 | 275 | if ($tok === self::RBRACE) { 276 | break; 277 | } 278 | 279 | if ($tok !== self::COMMA) { 280 | throw new RuntimeException(sprintf('Missing "," in object encoding: %s', $this->source)); 281 | } 282 | 283 | $tok = $this->getNextToken(); 284 | } 285 | 286 | switch ($this->decodeType) { 287 | case Json::TYPE_OBJECT: 288 | // Create new stdClass and populate with $members 289 | $result = new stdClass(); 290 | foreach ($members as $key => $value) { 291 | if ($key === '') { 292 | $key = '_empty_'; 293 | } 294 | $result->$key = $value; 295 | } 296 | break; 297 | case Json::TYPE_ARRAY: 298 | // intentionally fall-through 299 | default: 300 | $result = $members; 301 | break; 302 | } 303 | 304 | $this->getNextToken(); 305 | return $result; 306 | } 307 | 308 | /** 309 | * Decodes the JSON array format [element, element2, ..., elementN] 310 | * 311 | * @return array 312 | * @throws RuntimeException 313 | */ 314 | protected function decodeArray() 315 | { 316 | $result = []; 317 | $tok = $this->getNextToken(); // Move past the '[' 318 | $index = 0; 319 | 320 | while ($tok && $tok !== self::RBRACKET) { 321 | $result[$index++] = $this->decodeValue(); 322 | 323 | $tok = $this->token; 324 | 325 | if ($tok === self::RBRACKET || ! $tok) { 326 | break; 327 | } 328 | 329 | if ($tok !== self::COMMA) { 330 | throw new RuntimeException(sprintf('Missing "," in array encoding: %s', $this->source)); 331 | } 332 | 333 | $tok = $this->getNextToken(); 334 | } 335 | 336 | $this->getNextToken(); 337 | return $result; 338 | } 339 | 340 | /** 341 | * Removes whitespace characters from the source input. 342 | */ 343 | protected function eatWhitespace() 344 | { 345 | if ( 346 | preg_match('/([\t\b\f\n\r ])*/s', $this->source, $matches, PREG_OFFSET_CAPTURE, $this->offset) 347 | && $matches[0][1] === $this->offset 348 | ) { 349 | $this->offset += strlen($matches[0][0]); 350 | } 351 | } 352 | 353 | /** 354 | * Retrieves the next token from the source stream. 355 | * 356 | * @return int Token constant value specified in class definition. 357 | * @throws RuntimeException 358 | */ 359 | protected function getNextToken() 360 | { 361 | $this->token = self::EOF; 362 | $this->tokenValue = null; 363 | $this->eatWhitespace(); 364 | 365 | if ($this->offset >= $this->sourceLength) { 366 | return self::EOF; 367 | } 368 | 369 | $str = $this->source; 370 | $strLength = $this->sourceLength; 371 | $i = $this->offset; 372 | $start = $i; 373 | 374 | switch ($str[$i]) { 375 | case '{': 376 | $this->token = self::LBRACE; 377 | break; 378 | case '}': 379 | $this->token = self::RBRACE; 380 | break; 381 | case '[': 382 | $this->token = self::LBRACKET; 383 | break; 384 | case ']': 385 | $this->token = self::RBRACKET; 386 | break; 387 | case ',': 388 | $this->token = self::COMMA; 389 | break; 390 | case ':': 391 | $this->token = self::COLON; 392 | break; 393 | case '"': 394 | $result = ''; 395 | do { 396 | $i++; 397 | if ($i >= $strLength) { 398 | break; 399 | } 400 | 401 | $chr = $str[$i]; 402 | 403 | if ($chr === '"') { 404 | break; 405 | } 406 | 407 | if ($chr !== '\\') { 408 | $result .= $chr; 409 | continue; 410 | } 411 | 412 | $i++; 413 | 414 | if ($i >= $strLength) { 415 | break; 416 | } 417 | 418 | $chr = $str[$i]; 419 | match ($chr) { 420 | '"' => $result .= '"', 421 | '\\' => $result .= '\\', 422 | '/' => $result .= '/', 423 | 'b' => $result .= "\x08", 424 | 'f' => $result .= "\x0c", 425 | 'n' => $result .= "\x0a", 426 | 'r' => $result .= "\x0d", 427 | 't' => $result .= "\x09", 428 | '\'' => $result .= '\'', 429 | default => throw new RuntimeException(sprintf('Illegal escape sequence "%s"', $chr)), 430 | }; 431 | } while ($i < $strLength); 432 | 433 | $this->token = self::DATUM; 434 | $this->tokenValue = $result; 435 | break; 436 | case 't': 437 | if (($i + 3) < $strLength && $start === strpos($str, "true", $start)) { 438 | $this->token = self::DATUM; 439 | } 440 | $this->tokenValue = true; 441 | $i += 3; 442 | break; 443 | case 'f': 444 | if (($i + 4) < $strLength && $start === strpos($str, "false", $start)) { 445 | $this->token = self::DATUM; 446 | } 447 | $this->tokenValue = false; 448 | $i += 4; 449 | break; 450 | case 'n': 451 | if (($i + 3) < $strLength && $start === strpos($str, "null", $start)) { 452 | $this->token = self::DATUM; 453 | } 454 | $this->tokenValue = null; 455 | $i += 3; 456 | break; 457 | } 458 | 459 | if ($this->token !== self::EOF) { 460 | $this->offset = $i + 1; // Consume the last token character 461 | return $this->token; 462 | } 463 | 464 | $chr = $str[$i]; 465 | 466 | if ($chr !== '-' && $chr !== '.' && ($chr < '0' || $chr > '9')) { 467 | throw new RuntimeException('Illegal Token'); 468 | } 469 | 470 | if ( 471 | preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s', $str, $matches, PREG_OFFSET_CAPTURE, $start) 472 | && $matches[0][1] === $start 473 | ) { 474 | $datum = $matches[0][0]; 475 | 476 | if (! is_numeric($datum)) { 477 | throw new RuntimeException(sprintf('Illegal number format: %s', $datum)); 478 | } 479 | 480 | if (preg_match('/^0\d+$/', $datum)) { 481 | throw new RuntimeException(sprintf('Octal notation not supported by JSON (value: %o)', $datum)); 482 | } 483 | 484 | $val = intval($datum); 485 | $fVal = floatval($datum); 486 | 487 | // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedEqualOperator 488 | $this->tokenValue = $val == $fVal ? $val : $fVal; 489 | $this->token = self::DATUM; 490 | $this->offset = $start + strlen($datum); 491 | } 492 | 493 | return $this->token; 494 | } 495 | 496 | /** 497 | * Convert a string from one UTF-16 char to one UTF-8 char. 498 | * 499 | * Normally should be handled by mb_convert_encoding, but provides a slower 500 | * PHP-only method for installations that lack the multibyte string 501 | * extension. 502 | * 503 | * This method is from the Solar Framework by Paul M. Jones. 504 | * 505 | * @link http://solarphp.com 506 | * 507 | * @param string $utf16 UTF-16 character 508 | * @return string UTF-8 character 509 | */ 510 | protected static function utf162utf8($utf16) 511 | { 512 | // Check for mb extension otherwise do by hand. 513 | if (function_exists('mb_convert_encoding')) { 514 | return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); 515 | } 516 | 517 | $bytes = (ord($utf16[0]) << 8) | ord($utf16[1]); 518 | return match (true) { 519 | // This case should never be reached, because we are in ASCII range; 520 | // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 521 | (0x7F & $bytes) === $bytes => chr(0x7F & $bytes), 522 | 523 | // Return a 2-byte UTF-8 character; 524 | // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 525 | (0x07FF & $bytes) === $bytes => chr(0xC0 | (($bytes >> 6) & 0x1F)) 526 | . chr(0x80 | ($bytes & 0x3F)), 527 | 528 | // Return a 3-byte UTF-8 character; 529 | // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 530 | (0xFFFF & $bytes) === $bytes => chr(0xE0 | (($bytes >> 12) & 0x0F)) 531 | . chr(0x80 | (($bytes >> 6) & 0x3F)) 532 | . chr(0x80 | ($bytes & 0x3F)), 533 | 534 | // ignoring UTF-32 for now, sorry 535 | default => '', 536 | }; 537 | } 538 | } 539 | -------------------------------------------------------------------------------- /src/Encoder.php: -------------------------------------------------------------------------------- 1 | jsonSerialize(); 71 | } 72 | 73 | return $encoder->encodeValue($value); 74 | } 75 | 76 | /** 77 | * Encode a value to JSON. 78 | * 79 | * Recursive method which determines the type of value to be encoded 80 | * and then dispatches to the appropriate method. 81 | * 82 | * $values are either 83 | * - objects (returns from {@link encodeObject()}) 84 | * - arrays (returns from {@link encodeArray()}) 85 | * - scalars (returns from {@link encodeDatum()}) 86 | * 87 | * @param mixed $value The value to be encoded. 88 | * @return string Encoded value. 89 | */ 90 | protected function encodeValue(mixed &$value) 91 | { 92 | if (is_object($value)) { 93 | return $this->encodeObject($value); 94 | } 95 | 96 | if (is_array($value)) { 97 | return $this->encodeArray($value); 98 | } 99 | 100 | return $this->encodeDatum($value); 101 | } 102 | 103 | /** 104 | * Encode an object to JSON by encoding each of the public properties. 105 | * 106 | * A special property is added to the JSON object called '__className' that 107 | * contains the classname of $value; this can be used by consumers of the 108 | * resulting JSON to cast to the specific class. 109 | * 110 | * @param object $value 111 | * @return string 112 | * @throws RecursionException If recursive checks are enabled and the 113 | * object has been serialized previously. 114 | */ 115 | protected function encodeObject(&$value) 116 | { 117 | if ($this->cycleCheck) { 118 | if ($this->wasVisited($value)) { 119 | if ( 120 | ! isset($this->options['silenceCyclicalExceptions']) 121 | || $this->options['silenceCyclicalExceptions'] !== true 122 | ) { 123 | throw new RecursionException(sprintf( 124 | 'Cycles not supported in JSON encoding; cycle introduced by class "%s"', 125 | $value::class 126 | )); 127 | } 128 | 129 | return '"* RECURSION (' . str_replace('\\', '\\\\', $value::class) . ') *"'; 130 | } 131 | 132 | $this->visited[] = $value; 133 | } 134 | 135 | $props = ''; 136 | 137 | if (method_exists($value, 'toJson')) { 138 | $props = ',' . preg_replace("/^\{(.*)\}$/", "\\1", $value->toJson()); 139 | } else { 140 | if ($value instanceof IteratorAggregate) { 141 | $propCollection = $value->getIterator(); 142 | } elseif ($value instanceof Iterator) { 143 | $propCollection = $value; 144 | } else { 145 | $propCollection = get_object_vars($value); 146 | } 147 | 148 | foreach ($propCollection as $name => $propValue) { 149 | if (! isset($propValue)) { 150 | continue; 151 | } 152 | 153 | $props .= ',' 154 | . $this->encodeValue($name) 155 | . ':' 156 | . $this->encodeValue($propValue); 157 | } 158 | } 159 | 160 | $className = $value::class; 161 | return '{"__className":' 162 | . $this->encodeString($className) 163 | . $props . '}'; 164 | } 165 | 166 | /** 167 | * Determine if an object has been serialized already. 168 | * 169 | * @return bool 170 | */ 171 | protected function wasVisited(mixed &$value) 172 | { 173 | if (in_array($value, $this->visited, true)) { 174 | return true; 175 | } 176 | 177 | return false; 178 | } 179 | 180 | /** 181 | * JSON encode an array value. 182 | * 183 | * Recursively encodes each value of an array and returns a JSON encoded 184 | * array string. 185 | * 186 | * Arrays are defined as integer-indexed arrays starting at index 0, where 187 | * the last index is (count($array) -1); any deviation from that is 188 | * considered an associative array, and will be passed to 189 | * {@link encodeAssociativeArray()}. 190 | * 191 | * @param array $array 192 | * @return string 193 | */ 194 | protected function encodeArray($array) 195 | { 196 | // Check for associative array 197 | if (! empty($array) && (array_keys($array) !== range(0, count($array) - 1))) { 198 | // Associative array 199 | return $this->encodeAssociativeArray($array); 200 | } 201 | 202 | // Indexed array 203 | $tmpArray = []; 204 | $result = '['; 205 | $length = count($array); 206 | 207 | for ($i = 0; $i < $length; $i++) { 208 | $tmpArray[] = $this->encodeValue($array[$i]); 209 | } 210 | 211 | $result .= implode(',', $tmpArray); 212 | $result .= ']'; 213 | 214 | return $result; 215 | } 216 | 217 | /** 218 | * Encode an associative array to JSON. 219 | * 220 | * JSON does not have a concept of associative arrays; as such, we encode 221 | * them to objects. 222 | * 223 | * @param array $array Array to encode. 224 | * @return string 225 | */ 226 | protected function encodeAssociativeArray($array) 227 | { 228 | $tmpArray = []; 229 | $result = '{'; 230 | 231 | foreach ($array as $key => $value) { 232 | $tmpArray[] = sprintf( 233 | '%s:%s', 234 | $this->encodeString((string) $key), 235 | $this->encodeValue($value) 236 | ); 237 | } 238 | 239 | $result .= implode(',', $tmpArray); 240 | $result .= '}'; 241 | return $result; 242 | } 243 | 244 | /** 245 | * JSON encode a scalar data type (string, number, boolean, null). 246 | * 247 | * If value type is not a string, number, boolean, or null, the string 248 | * 'null' is returned. 249 | * 250 | * @return string 251 | */ 252 | protected function encodeDatum(mixed $value) 253 | { 254 | if (is_int($value) || is_float($value)) { 255 | return str_replace(',', '.', (string) $value); 256 | } 257 | 258 | if (is_string($value)) { 259 | return $this->encodeString($value); 260 | } 261 | 262 | if (is_bool($value)) { 263 | return $value ? 'true' : 'false'; 264 | } 265 | 266 | return 'null'; 267 | } 268 | 269 | /** 270 | * JSON encode a string value by escaping characters as necessary. 271 | * 272 | * @param string $string 273 | * @return string 274 | */ 275 | protected function encodeString($string) 276 | { 277 | // @codingStandardsIgnoreStart 278 | // Escape these characters with a backslash or unicode escape: 279 | // " \ / \n \r \t \b \f 280 | $search = ['\\', "\n", "\t", "\r", "\b", "\f", '"', '\'', '&', '<', '>', '/']; 281 | $replace = ['\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\\u0022', '\\u0027', '\\u0026', '\\u003C', '\\u003E', '\\/']; 282 | $string = str_replace($search, $replace, $string); 283 | // @codingStandardsIgnoreEnd 284 | 285 | // Escape certain ASCII characters: 286 | // 0x08 => \b 287 | // 0x0c => \f 288 | $string = str_replace([chr(0x08), chr(0x0C)], ['\b', '\f'], $string); 289 | $string = self::encodeUnicodeString($string); 290 | 291 | return '"' . $string . '"'; 292 | } 293 | 294 | /** 295 | * Encode the constants associated with the ReflectionClass parameter. 296 | * 297 | * The encoding format is based on the class2 format. 298 | * 299 | * @return string Encoded constant block in class2 format 300 | */ 301 | private static function encodeConstants(ReflectionClass $class) 302 | { 303 | $result = "constants:{"; 304 | $constants = $class->getConstants(); 305 | 306 | if (empty($constants)) { 307 | return $result . '}'; 308 | } 309 | 310 | $tmpArray = []; 311 | foreach ($constants as $key => $value) { 312 | $tmpArray[] = sprintf('%s: %s', $key, self::encode($value)); 313 | } 314 | 315 | $result .= implode(', ', $tmpArray); 316 | 317 | return $result . "}"; 318 | } 319 | 320 | /** 321 | * Encode the public methods of the ReflectionClass in the class2 format 322 | * 323 | * @return string Encoded method fragment. 324 | */ 325 | private static function encodeMethods(ReflectionClass $class) 326 | { 327 | $result = 'methods:{'; 328 | $started = false; 329 | 330 | foreach ($class->getMethods() as $method) { 331 | if (! $method->isPublic() || ! $method->isUserDefined()) { 332 | continue; 333 | } 334 | 335 | if ($started) { 336 | $result .= ','; 337 | } 338 | $started = true; 339 | 340 | $result .= sprintf('%s:function(', $method->getName()); 341 | 342 | if ('__construct' === $method->getName()) { 343 | $result .= '){}'; 344 | continue; 345 | } 346 | 347 | $argsStarted = false; 348 | $argNames = "var argNames=["; 349 | 350 | foreach ($method->getParameters() as $param) { 351 | if ($argsStarted) { 352 | $result .= ','; 353 | } 354 | 355 | $result .= $param->getName(); 356 | 357 | if ($argsStarted) { 358 | $argNames .= ','; 359 | } 360 | 361 | $argNames .= sprintf('"%s"', $param->getName()); 362 | $argsStarted = true; 363 | } 364 | $argNames .= "];"; 365 | 366 | $result .= "){" 367 | . $argNames 368 | . 'var result = ZAjaxEngine.invokeRemoteMethod(' 369 | . "this, '" 370 | . $method->getName() 371 | . "',argNames,arguments);" 372 | . 'return(result);}'; 373 | } 374 | 375 | return $result . "}"; 376 | } 377 | 378 | /** 379 | * Encode the public properties of the ReflectionClass in the class2 format. 380 | * 381 | * @return string Encode properties list 382 | */ 383 | private static function encodeVariables(ReflectionClass $class) 384 | { 385 | $propValues = get_class_vars($class->getName()); 386 | $result = "variables:{"; 387 | $tmpArray = []; 388 | 389 | foreach ($class->getProperties() as $prop) { 390 | if (! $prop->isPublic()) { 391 | continue; 392 | } 393 | 394 | $name = $prop->getName(); 395 | $tmpArray[] = sprintf('%s:%s', $name, self::encode($propValues[$name])); 396 | } 397 | 398 | $result .= implode(',', $tmpArray); 399 | 400 | return $result . "}"; 401 | } 402 | 403 | /** 404 | * Encodes the given $className into the class2 model of encoding PHP classes into JavaScript class2 classes. 405 | * 406 | * NOTE: Currently only public methods and variables are proxied onto the 407 | * client machine 408 | * 409 | * @param string $className The name of the class, the class must be 410 | * instantiable using a null constructor. 411 | * @param string $package Optional package name appended to JavaScript 412 | * proxy class name. 413 | * @return string The class2 (JavaScript) encoding of the class. 414 | * @throws InvalidArgumentException 415 | */ 416 | public static function encodeClass($className, $package = '') 417 | { 418 | $class = new ReflectionClass($className); 419 | if (! $class->isInstantiable()) { 420 | throw new InvalidArgumentException(sprintf( 421 | '"%s" must be instantiable', 422 | $className 423 | )); 424 | } 425 | 426 | return sprintf( 427 | 'Class.create(\'%s%s\',{%s,%s,%s});', 428 | $package, 429 | $className, 430 | self::encodeConstants($class), 431 | self::encodeMethods($class), 432 | self::encodeVariables($class) 433 | ); 434 | } 435 | 436 | /** 437 | * Encode several classes at once. 438 | * 439 | * Returns JSON encoded classes, using {@link encodeClass()}. 440 | * 441 | * @param string[] $classNames 442 | * @param string $package 443 | * @return string 444 | */ 445 | public static function encodeClasses(array $classNames, $package = '') 446 | { 447 | $result = ''; 448 | foreach ($classNames as $className) { 449 | $result .= static::encodeClass($className, $package); 450 | } 451 | 452 | return $result; 453 | } 454 | 455 | /** 456 | * Encode Unicode Characters to \u0000 ASCII syntax. 457 | * 458 | * This algorithm was originally developed for the Solar Framework by Paul 459 | * M. Jones. 460 | * 461 | * @link http://solarphp.com/ 462 | * @link https://github.com/solarphp/core/blob/master/Solar/Json.php 463 | * 464 | * @param string $value 465 | * @return string 466 | */ 467 | public static function encodeUnicodeString($value) 468 | { 469 | $strlenVar = strlen($value); 470 | $ascii = ""; 471 | 472 | // Iterate over every character in the string, escaping with a slash or 473 | // encoding to UTF-8 where necessary. 474 | for ($i = 0; $i < $strlenVar; $i++) { 475 | $ordVarC = ord($value[$i]); 476 | 477 | switch (true) { 478 | case ($ordVarC >= 0x20) && ($ordVarC <= 0x7F): 479 | // characters U-00000000 - U-0000007F (same as ASCII) 480 | $ascii .= $value[$i]; 481 | break; 482 | 483 | case ($ordVarC & 0xE0) === 0xC0: 484 | // characters U-00000080 - U-000007FF, mask 110XXXXX 485 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 486 | $char = pack('C*', $ordVarC, ord($value[$i + 1])); 487 | $i += 1; 488 | $utf16 = self::utf82utf16($char); 489 | $ascii .= sprintf('\u%04s', bin2hex($utf16)); 490 | break; 491 | 492 | case ($ordVarC & 0xF0) === 0xE0: 493 | // characters U-00000800 - U-0000FFFF, mask 1110XXXX 494 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 495 | $char = pack( 496 | 'C*', 497 | $ordVarC, 498 | ord($value[$i + 1]), 499 | ord($value[$i + 2]) 500 | ); 501 | $i += 2; 502 | $utf16 = self::utf82utf16($char); 503 | $ascii .= sprintf('\u%04s', bin2hex($utf16)); 504 | break; 505 | 506 | case ($ordVarC & 0xF8) === 0xF0: 507 | // characters U-00010000 - U-001FFFFF, mask 11110XXX 508 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 509 | $char = pack( 510 | 'C*', 511 | $ordVarC, 512 | ord($value[$i + 1]), 513 | ord($value[$i + 2]), 514 | ord($value[$i + 3]) 515 | ); 516 | $i += 3; 517 | $utf16 = self::utf82utf16($char); 518 | $ascii .= sprintf('\u%04s', bin2hex($utf16)); 519 | break; 520 | 521 | case ($ordVarC & 0xFC) === 0xF8: 522 | // characters U-00200000 - U-03FFFFFF, mask 111110XX 523 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 524 | $char = pack( 525 | 'C*', 526 | $ordVarC, 527 | ord($value[$i + 1]), 528 | ord($value[$i + 2]), 529 | ord($value[$i + 3]), 530 | ord($value[$i + 4]) 531 | ); 532 | $i += 4; 533 | $utf16 = self::utf82utf16($char); 534 | $ascii .= sprintf('\u%04s', bin2hex($utf16)); 535 | break; 536 | 537 | case ($ordVarC & 0xFE) === 0xFC: 538 | // characters U-04000000 - U-7FFFFFFF, mask 1111110X 539 | // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 540 | $char = pack( 541 | 'C*', 542 | $ordVarC, 543 | ord($value[$i + 1]), 544 | ord($value[$i + 2]), 545 | ord($value[$i + 3]), 546 | ord($value[$i + 4]), 547 | ord($value[$i + 5]) 548 | ); 549 | $i += 5; 550 | $utf16 = self::utf82utf16($char); 551 | $ascii .= sprintf('\u%04s', bin2hex($utf16)); 552 | break; 553 | } 554 | } 555 | 556 | return $ascii; 557 | } 558 | 559 | /** 560 | * Convert a string from one UTF-8 char to one UTF-16 char. 561 | * 562 | * Normally should be handled by mb_convert_encoding, but provides a slower 563 | * PHP-only method for installations that lack the multibyte string 564 | * extension. 565 | * 566 | * This method is from the Solar Framework by Paul M. Jones. 567 | * 568 | * @link http://solarphp.com 569 | * 570 | * @param string $utf8 UTF-8 character 571 | * @return string UTF-16 character 572 | */ 573 | protected static function utf82utf16($utf8) 574 | { 575 | // Check for mb extension otherwise do by hand. 576 | if (function_exists('mb_convert_encoding')) { 577 | return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); 578 | } 579 | return match (strlen($utf8)) { 580 | // This case should never be reached, because we are in ASCII range; 581 | // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 582 | 1 => $utf8, 583 | 584 | // Return a UTF-16 character from a 2-byte UTF-8 char; 585 | // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 586 | 2 => chr(0x07 & (ord($utf8[0]) >> 2)) . chr((0xC0 & (ord($utf8[0]) << 6)) | (0x3F & ord($utf8[1]))), 587 | 588 | // Return a UTF-16 character from a 3-byte UTF-8 char; 589 | // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 590 | 3 => chr((0xF0 & (ord($utf8[0]) << 4)) 591 | | (0x0F & (ord($utf8[1]) >> 2))) . chr((0xC0 & (ord($utf8[1]) << 6)) 592 | | (0x7F & ord($utf8[2]))), 593 | 594 | // ignoring UTF-32 for now, sorry 595 | default => '', 596 | }; 597 | } 598 | } 599 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "cc2a865b63a5f1c025c814ec3c253e06", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "dealerdirect/phpcodesniffer-composer-installer", 12 | "version": "v0.7.2", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", 16 | "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", 21 | "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "composer-plugin-api": "^1.0 || ^2.0", 26 | "php": ">=5.3", 27 | "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" 28 | }, 29 | "require-dev": { 30 | "composer/composer": "*", 31 | "php-parallel-lint/php-parallel-lint": "^1.3.1", 32 | "phpcompatibility/php-compatibility": "^9.0" 33 | }, 34 | "type": "composer-plugin", 35 | "extra": { 36 | "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" 37 | }, 38 | "autoload": { 39 | "psr-4": { 40 | "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" 41 | } 42 | }, 43 | "notification-url": "https://packagist.org/downloads/", 44 | "license": [ 45 | "MIT" 46 | ], 47 | "authors": [ 48 | { 49 | "name": "Franck Nijhof", 50 | "email": "franck.nijhof@dealerdirect.com", 51 | "homepage": "http://www.frenck.nl", 52 | "role": "Developer / IT Manager" 53 | }, 54 | { 55 | "name": "Contributors", 56 | "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" 57 | } 58 | ], 59 | "description": "PHP_CodeSniffer Standards Composer Installer Plugin", 60 | "homepage": "http://www.dealerdirect.com", 61 | "keywords": [ 62 | "PHPCodeSniffer", 63 | "PHP_CodeSniffer", 64 | "code quality", 65 | "codesniffer", 66 | "composer", 67 | "installer", 68 | "phpcbf", 69 | "phpcs", 70 | "plugin", 71 | "qa", 72 | "quality", 73 | "standard", 74 | "standards", 75 | "style guide", 76 | "stylecheck", 77 | "tests" 78 | ], 79 | "support": { 80 | "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", 81 | "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" 82 | }, 83 | "time": "2022-02-04T12:51:07+00:00" 84 | }, 85 | { 86 | "name": "doctrine/instantiator", 87 | "version": "2.0.0", 88 | "source": { 89 | "type": "git", 90 | "url": "https://github.com/doctrine/instantiator.git", 91 | "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" 92 | }, 93 | "dist": { 94 | "type": "zip", 95 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", 96 | "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", 97 | "shasum": "" 98 | }, 99 | "require": { 100 | "php": "^8.1" 101 | }, 102 | "require-dev": { 103 | "doctrine/coding-standard": "^11", 104 | "ext-pdo": "*", 105 | "ext-phar": "*", 106 | "phpbench/phpbench": "^1.2", 107 | "phpstan/phpstan": "^1.9.4", 108 | "phpstan/phpstan-phpunit": "^1.3", 109 | "phpunit/phpunit": "^9.5.27", 110 | "vimeo/psalm": "^5.4" 111 | }, 112 | "type": "library", 113 | "autoload": { 114 | "psr-4": { 115 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 116 | } 117 | }, 118 | "notification-url": "https://packagist.org/downloads/", 119 | "license": [ 120 | "MIT" 121 | ], 122 | "authors": [ 123 | { 124 | "name": "Marco Pivetta", 125 | "email": "ocramius@gmail.com", 126 | "homepage": "https://ocramius.github.io/" 127 | } 128 | ], 129 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 130 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 131 | "keywords": [ 132 | "constructor", 133 | "instantiate" 134 | ], 135 | "support": { 136 | "issues": "https://github.com/doctrine/instantiator/issues", 137 | "source": "https://github.com/doctrine/instantiator/tree/2.0.0" 138 | }, 139 | "funding": [ 140 | { 141 | "url": "https://www.doctrine-project.org/sponsorship.html", 142 | "type": "custom" 143 | }, 144 | { 145 | "url": "https://www.patreon.com/phpdoctrine", 146 | "type": "patreon" 147 | }, 148 | { 149 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 150 | "type": "tidelift" 151 | } 152 | ], 153 | "time": "2022-12-30T00:23:10+00:00" 154 | }, 155 | { 156 | "name": "laminas/laminas-coding-standard", 157 | "version": "2.4.0", 158 | "source": { 159 | "type": "git", 160 | "url": "https://github.com/laminas/laminas-coding-standard.git", 161 | "reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc" 162 | }, 163 | "dist": { 164 | "type": "zip", 165 | "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/eb076dd86aa93dd424856b150c9b6f76c1fdfabc", 166 | "reference": "eb076dd86aa93dd424856b150c9b6f76c1fdfabc", 167 | "shasum": "" 168 | }, 169 | "require": { 170 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7", 171 | "php": "^7.4 || ^8.0", 172 | "slevomat/coding-standard": "^7.0", 173 | "squizlabs/php_codesniffer": "^3.6", 174 | "webimpress/coding-standard": "^1.2" 175 | }, 176 | "conflict": { 177 | "phpstan/phpdoc-parser": ">=1.6.0" 178 | }, 179 | "type": "phpcodesniffer-standard", 180 | "autoload": { 181 | "psr-4": { 182 | "LaminasCodingStandard\\": "src/LaminasCodingStandard/" 183 | } 184 | }, 185 | "notification-url": "https://packagist.org/downloads/", 186 | "license": [ 187 | "BSD-3-Clause" 188 | ], 189 | "description": "Laminas Coding Standard", 190 | "homepage": "https://laminas.dev", 191 | "keywords": [ 192 | "Coding Standard", 193 | "laminas" 194 | ], 195 | "support": { 196 | "chat": "https://laminas.dev/chat", 197 | "docs": "https://docs.laminas.dev/laminas-coding-standard/", 198 | "forum": "https://discourse.laminas.dev", 199 | "issues": "https://github.com/laminas/laminas-coding-standard/issues", 200 | "rss": "https://github.com/laminas/laminas-coding-standard/releases.atom", 201 | "source": "https://github.com/laminas/laminas-coding-standard" 202 | }, 203 | "funding": [ 204 | { 205 | "url": "https://funding.communitybridge.org/projects/laminas-project", 206 | "type": "community_bridge" 207 | } 208 | ], 209 | "time": "2022-08-24T17:45:47+00:00" 210 | }, 211 | { 212 | "name": "laminas/laminas-stdlib", 213 | "version": "3.19.0", 214 | "source": { 215 | "type": "git", 216 | "url": "https://github.com/laminas/laminas-stdlib.git", 217 | "reference": "6a192dd0882b514e45506f533b833b623b78fff3" 218 | }, 219 | "dist": { 220 | "type": "zip", 221 | "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/6a192dd0882b514e45506f533b833b623b78fff3", 222 | "reference": "6a192dd0882b514e45506f533b833b623b78fff3", 223 | "shasum": "" 224 | }, 225 | "require": { 226 | "php": "~8.1.0 || ~8.2.0 || ~8.3.0" 227 | }, 228 | "conflict": { 229 | "zendframework/zend-stdlib": "*" 230 | }, 231 | "require-dev": { 232 | "laminas/laminas-coding-standard": "^2.5", 233 | "phpbench/phpbench": "^1.2.15", 234 | "phpunit/phpunit": "^10.5.8", 235 | "psalm/plugin-phpunit": "^0.18.4", 236 | "vimeo/psalm": "^5.20.0" 237 | }, 238 | "type": "library", 239 | "autoload": { 240 | "psr-4": { 241 | "Laminas\\Stdlib\\": "src/" 242 | } 243 | }, 244 | "notification-url": "https://packagist.org/downloads/", 245 | "license": [ 246 | "BSD-3-Clause" 247 | ], 248 | "description": "SPL extensions, array utilities, error handlers, and more", 249 | "homepage": "https://laminas.dev", 250 | "keywords": [ 251 | "laminas", 252 | "stdlib" 253 | ], 254 | "support": { 255 | "chat": "https://laminas.dev/chat", 256 | "docs": "https://docs.laminas.dev/laminas-stdlib/", 257 | "forum": "https://discourse.laminas.dev", 258 | "issues": "https://github.com/laminas/laminas-stdlib/issues", 259 | "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", 260 | "source": "https://github.com/laminas/laminas-stdlib" 261 | }, 262 | "funding": [ 263 | { 264 | "url": "https://funding.communitybridge.org/projects/laminas-project", 265 | "type": "community_bridge" 266 | } 267 | ], 268 | "time": "2024-01-19T12:39:49+00:00" 269 | }, 270 | { 271 | "name": "myclabs/deep-copy", 272 | "version": "1.11.1", 273 | "source": { 274 | "type": "git", 275 | "url": "https://github.com/myclabs/DeepCopy.git", 276 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" 277 | }, 278 | "dist": { 279 | "type": "zip", 280 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", 281 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", 282 | "shasum": "" 283 | }, 284 | "require": { 285 | "php": "^7.1 || ^8.0" 286 | }, 287 | "conflict": { 288 | "doctrine/collections": "<1.6.8", 289 | "doctrine/common": "<2.13.3 || >=3,<3.2.2" 290 | }, 291 | "require-dev": { 292 | "doctrine/collections": "^1.6.8", 293 | "doctrine/common": "^2.13.3 || ^3.2.2", 294 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 295 | }, 296 | "type": "library", 297 | "autoload": { 298 | "files": [ 299 | "src/DeepCopy/deep_copy.php" 300 | ], 301 | "psr-4": { 302 | "DeepCopy\\": "src/DeepCopy/" 303 | } 304 | }, 305 | "notification-url": "https://packagist.org/downloads/", 306 | "license": [ 307 | "MIT" 308 | ], 309 | "description": "Create deep copies (clones) of your objects", 310 | "keywords": [ 311 | "clone", 312 | "copy", 313 | "duplicate", 314 | "object", 315 | "object graph" 316 | ], 317 | "support": { 318 | "issues": "https://github.com/myclabs/DeepCopy/issues", 319 | "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" 320 | }, 321 | "funding": [ 322 | { 323 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 324 | "type": "tidelift" 325 | } 326 | ], 327 | "time": "2023-03-08T13:26:56+00:00" 328 | }, 329 | { 330 | "name": "nikic/php-parser", 331 | "version": "v4.17.1", 332 | "source": { 333 | "type": "git", 334 | "url": "https://github.com/nikic/PHP-Parser.git", 335 | "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" 336 | }, 337 | "dist": { 338 | "type": "zip", 339 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", 340 | "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", 341 | "shasum": "" 342 | }, 343 | "require": { 344 | "ext-tokenizer": "*", 345 | "php": ">=7.0" 346 | }, 347 | "require-dev": { 348 | "ircmaxell/php-yacc": "^0.0.7", 349 | "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" 350 | }, 351 | "bin": [ 352 | "bin/php-parse" 353 | ], 354 | "type": "library", 355 | "extra": { 356 | "branch-alias": { 357 | "dev-master": "4.9-dev" 358 | } 359 | }, 360 | "autoload": { 361 | "psr-4": { 362 | "PhpParser\\": "lib/PhpParser" 363 | } 364 | }, 365 | "notification-url": "https://packagist.org/downloads/", 366 | "license": [ 367 | "BSD-3-Clause" 368 | ], 369 | "authors": [ 370 | { 371 | "name": "Nikita Popov" 372 | } 373 | ], 374 | "description": "A PHP parser written in PHP", 375 | "keywords": [ 376 | "parser", 377 | "php" 378 | ], 379 | "support": { 380 | "issues": "https://github.com/nikic/PHP-Parser/issues", 381 | "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" 382 | }, 383 | "time": "2023-08-13T19:53:39+00:00" 384 | }, 385 | { 386 | "name": "phar-io/manifest", 387 | "version": "2.0.3", 388 | "source": { 389 | "type": "git", 390 | "url": "https://github.com/phar-io/manifest.git", 391 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53" 392 | }, 393 | "dist": { 394 | "type": "zip", 395 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", 396 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53", 397 | "shasum": "" 398 | }, 399 | "require": { 400 | "ext-dom": "*", 401 | "ext-phar": "*", 402 | "ext-xmlwriter": "*", 403 | "phar-io/version": "^3.0.1", 404 | "php": "^7.2 || ^8.0" 405 | }, 406 | "type": "library", 407 | "extra": { 408 | "branch-alias": { 409 | "dev-master": "2.0.x-dev" 410 | } 411 | }, 412 | "autoload": { 413 | "classmap": [ 414 | "src/" 415 | ] 416 | }, 417 | "notification-url": "https://packagist.org/downloads/", 418 | "license": [ 419 | "BSD-3-Clause" 420 | ], 421 | "authors": [ 422 | { 423 | "name": "Arne Blankerts", 424 | "email": "arne@blankerts.de", 425 | "role": "Developer" 426 | }, 427 | { 428 | "name": "Sebastian Heuer", 429 | "email": "sebastian@phpeople.de", 430 | "role": "Developer" 431 | }, 432 | { 433 | "name": "Sebastian Bergmann", 434 | "email": "sebastian@phpunit.de", 435 | "role": "Developer" 436 | } 437 | ], 438 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 439 | "support": { 440 | "issues": "https://github.com/phar-io/manifest/issues", 441 | "source": "https://github.com/phar-io/manifest/tree/2.0.3" 442 | }, 443 | "time": "2021-07-20T11:28:43+00:00" 444 | }, 445 | { 446 | "name": "phar-io/version", 447 | "version": "3.2.1", 448 | "source": { 449 | "type": "git", 450 | "url": "https://github.com/phar-io/version.git", 451 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 452 | }, 453 | "dist": { 454 | "type": "zip", 455 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 456 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 457 | "shasum": "" 458 | }, 459 | "require": { 460 | "php": "^7.2 || ^8.0" 461 | }, 462 | "type": "library", 463 | "autoload": { 464 | "classmap": [ 465 | "src/" 466 | ] 467 | }, 468 | "notification-url": "https://packagist.org/downloads/", 469 | "license": [ 470 | "BSD-3-Clause" 471 | ], 472 | "authors": [ 473 | { 474 | "name": "Arne Blankerts", 475 | "email": "arne@blankerts.de", 476 | "role": "Developer" 477 | }, 478 | { 479 | "name": "Sebastian Heuer", 480 | "email": "sebastian@phpeople.de", 481 | "role": "Developer" 482 | }, 483 | { 484 | "name": "Sebastian Bergmann", 485 | "email": "sebastian@phpunit.de", 486 | "role": "Developer" 487 | } 488 | ], 489 | "description": "Library for handling version information and constraints", 490 | "support": { 491 | "issues": "https://github.com/phar-io/version/issues", 492 | "source": "https://github.com/phar-io/version/tree/3.2.1" 493 | }, 494 | "time": "2022-02-21T01:04:05+00:00" 495 | }, 496 | { 497 | "name": "phpstan/phpdoc-parser", 498 | "version": "1.5.1", 499 | "source": { 500 | "type": "git", 501 | "url": "https://github.com/phpstan/phpdoc-parser.git", 502 | "reference": "981cc368a216c988e862a75e526b6076987d1b50" 503 | }, 504 | "dist": { 505 | "type": "zip", 506 | "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/981cc368a216c988e862a75e526b6076987d1b50", 507 | "reference": "981cc368a216c988e862a75e526b6076987d1b50", 508 | "shasum": "" 509 | }, 510 | "require": { 511 | "php": "^7.2 || ^8.0" 512 | }, 513 | "require-dev": { 514 | "php-parallel-lint/php-parallel-lint": "^1.2", 515 | "phpstan/extension-installer": "^1.0", 516 | "phpstan/phpstan": "^1.5", 517 | "phpstan/phpstan-strict-rules": "^1.0", 518 | "phpunit/phpunit": "^9.5", 519 | "symfony/process": "^5.2" 520 | }, 521 | "type": "library", 522 | "autoload": { 523 | "psr-4": { 524 | "PHPStan\\PhpDocParser\\": [ 525 | "src/" 526 | ] 527 | } 528 | }, 529 | "notification-url": "https://packagist.org/downloads/", 530 | "license": [ 531 | "MIT" 532 | ], 533 | "description": "PHPDoc parser with support for nullable, intersection and generic types", 534 | "support": { 535 | "issues": "https://github.com/phpstan/phpdoc-parser/issues", 536 | "source": "https://github.com/phpstan/phpdoc-parser/tree/1.5.1" 537 | }, 538 | "time": "2022-05-05T11:32:40+00:00" 539 | }, 540 | { 541 | "name": "phpunit/php-code-coverage", 542 | "version": "9.2.29", 543 | "source": { 544 | "type": "git", 545 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 546 | "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" 547 | }, 548 | "dist": { 549 | "type": "zip", 550 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", 551 | "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", 552 | "shasum": "" 553 | }, 554 | "require": { 555 | "ext-dom": "*", 556 | "ext-libxml": "*", 557 | "ext-xmlwriter": "*", 558 | "nikic/php-parser": "^4.15", 559 | "php": ">=7.3", 560 | "phpunit/php-file-iterator": "^3.0.3", 561 | "phpunit/php-text-template": "^2.0.2", 562 | "sebastian/code-unit-reverse-lookup": "^2.0.2", 563 | "sebastian/complexity": "^2.0", 564 | "sebastian/environment": "^5.1.2", 565 | "sebastian/lines-of-code": "^1.0.3", 566 | "sebastian/version": "^3.0.1", 567 | "theseer/tokenizer": "^1.2.0" 568 | }, 569 | "require-dev": { 570 | "phpunit/phpunit": "^9.3" 571 | }, 572 | "suggest": { 573 | "ext-pcov": "PHP extension that provides line coverage", 574 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 575 | }, 576 | "type": "library", 577 | "extra": { 578 | "branch-alias": { 579 | "dev-master": "9.2-dev" 580 | } 581 | }, 582 | "autoload": { 583 | "classmap": [ 584 | "src/" 585 | ] 586 | }, 587 | "notification-url": "https://packagist.org/downloads/", 588 | "license": [ 589 | "BSD-3-Clause" 590 | ], 591 | "authors": [ 592 | { 593 | "name": "Sebastian Bergmann", 594 | "email": "sebastian@phpunit.de", 595 | "role": "lead" 596 | } 597 | ], 598 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 599 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 600 | "keywords": [ 601 | "coverage", 602 | "testing", 603 | "xunit" 604 | ], 605 | "support": { 606 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 607 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", 608 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" 609 | }, 610 | "funding": [ 611 | { 612 | "url": "https://github.com/sebastianbergmann", 613 | "type": "github" 614 | } 615 | ], 616 | "time": "2023-09-19T04:57:46+00:00" 617 | }, 618 | { 619 | "name": "phpunit/php-file-iterator", 620 | "version": "3.0.6", 621 | "source": { 622 | "type": "git", 623 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 624 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" 625 | }, 626 | "dist": { 627 | "type": "zip", 628 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 629 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 630 | "shasum": "" 631 | }, 632 | "require": { 633 | "php": ">=7.3" 634 | }, 635 | "require-dev": { 636 | "phpunit/phpunit": "^9.3" 637 | }, 638 | "type": "library", 639 | "extra": { 640 | "branch-alias": { 641 | "dev-master": "3.0-dev" 642 | } 643 | }, 644 | "autoload": { 645 | "classmap": [ 646 | "src/" 647 | ] 648 | }, 649 | "notification-url": "https://packagist.org/downloads/", 650 | "license": [ 651 | "BSD-3-Clause" 652 | ], 653 | "authors": [ 654 | { 655 | "name": "Sebastian Bergmann", 656 | "email": "sebastian@phpunit.de", 657 | "role": "lead" 658 | } 659 | ], 660 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 661 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 662 | "keywords": [ 663 | "filesystem", 664 | "iterator" 665 | ], 666 | "support": { 667 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 668 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" 669 | }, 670 | "funding": [ 671 | { 672 | "url": "https://github.com/sebastianbergmann", 673 | "type": "github" 674 | } 675 | ], 676 | "time": "2021-12-02T12:48:52+00:00" 677 | }, 678 | { 679 | "name": "phpunit/php-invoker", 680 | "version": "3.1.1", 681 | "source": { 682 | "type": "git", 683 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 684 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" 685 | }, 686 | "dist": { 687 | "type": "zip", 688 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 689 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 690 | "shasum": "" 691 | }, 692 | "require": { 693 | "php": ">=7.3" 694 | }, 695 | "require-dev": { 696 | "ext-pcntl": "*", 697 | "phpunit/phpunit": "^9.3" 698 | }, 699 | "suggest": { 700 | "ext-pcntl": "*" 701 | }, 702 | "type": "library", 703 | "extra": { 704 | "branch-alias": { 705 | "dev-master": "3.1-dev" 706 | } 707 | }, 708 | "autoload": { 709 | "classmap": [ 710 | "src/" 711 | ] 712 | }, 713 | "notification-url": "https://packagist.org/downloads/", 714 | "license": [ 715 | "BSD-3-Clause" 716 | ], 717 | "authors": [ 718 | { 719 | "name": "Sebastian Bergmann", 720 | "email": "sebastian@phpunit.de", 721 | "role": "lead" 722 | } 723 | ], 724 | "description": "Invoke callables with a timeout", 725 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 726 | "keywords": [ 727 | "process" 728 | ], 729 | "support": { 730 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 731 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" 732 | }, 733 | "funding": [ 734 | { 735 | "url": "https://github.com/sebastianbergmann", 736 | "type": "github" 737 | } 738 | ], 739 | "time": "2020-09-28T05:58:55+00:00" 740 | }, 741 | { 742 | "name": "phpunit/php-text-template", 743 | "version": "2.0.4", 744 | "source": { 745 | "type": "git", 746 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 747 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" 748 | }, 749 | "dist": { 750 | "type": "zip", 751 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 752 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 753 | "shasum": "" 754 | }, 755 | "require": { 756 | "php": ">=7.3" 757 | }, 758 | "require-dev": { 759 | "phpunit/phpunit": "^9.3" 760 | }, 761 | "type": "library", 762 | "extra": { 763 | "branch-alias": { 764 | "dev-master": "2.0-dev" 765 | } 766 | }, 767 | "autoload": { 768 | "classmap": [ 769 | "src/" 770 | ] 771 | }, 772 | "notification-url": "https://packagist.org/downloads/", 773 | "license": [ 774 | "BSD-3-Clause" 775 | ], 776 | "authors": [ 777 | { 778 | "name": "Sebastian Bergmann", 779 | "email": "sebastian@phpunit.de", 780 | "role": "lead" 781 | } 782 | ], 783 | "description": "Simple template engine.", 784 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 785 | "keywords": [ 786 | "template" 787 | ], 788 | "support": { 789 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 790 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" 791 | }, 792 | "funding": [ 793 | { 794 | "url": "https://github.com/sebastianbergmann", 795 | "type": "github" 796 | } 797 | ], 798 | "time": "2020-10-26T05:33:50+00:00" 799 | }, 800 | { 801 | "name": "phpunit/php-timer", 802 | "version": "5.0.3", 803 | "source": { 804 | "type": "git", 805 | "url": "https://github.com/sebastianbergmann/php-timer.git", 806 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" 807 | }, 808 | "dist": { 809 | "type": "zip", 810 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 811 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 812 | "shasum": "" 813 | }, 814 | "require": { 815 | "php": ">=7.3" 816 | }, 817 | "require-dev": { 818 | "phpunit/phpunit": "^9.3" 819 | }, 820 | "type": "library", 821 | "extra": { 822 | "branch-alias": { 823 | "dev-master": "5.0-dev" 824 | } 825 | }, 826 | "autoload": { 827 | "classmap": [ 828 | "src/" 829 | ] 830 | }, 831 | "notification-url": "https://packagist.org/downloads/", 832 | "license": [ 833 | "BSD-3-Clause" 834 | ], 835 | "authors": [ 836 | { 837 | "name": "Sebastian Bergmann", 838 | "email": "sebastian@phpunit.de", 839 | "role": "lead" 840 | } 841 | ], 842 | "description": "Utility class for timing", 843 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 844 | "keywords": [ 845 | "timer" 846 | ], 847 | "support": { 848 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 849 | "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" 850 | }, 851 | "funding": [ 852 | { 853 | "url": "https://github.com/sebastianbergmann", 854 | "type": "github" 855 | } 856 | ], 857 | "time": "2020-10-26T13:16:10+00:00" 858 | }, 859 | { 860 | "name": "phpunit/phpunit", 861 | "version": "9.6.13", 862 | "source": { 863 | "type": "git", 864 | "url": "https://github.com/sebastianbergmann/phpunit.git", 865 | "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be" 866 | }, 867 | "dist": { 868 | "type": "zip", 869 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f3d767f7f9e191eab4189abe41ab37797e30b1be", 870 | "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be", 871 | "shasum": "" 872 | }, 873 | "require": { 874 | "doctrine/instantiator": "^1.3.1 || ^2", 875 | "ext-dom": "*", 876 | "ext-json": "*", 877 | "ext-libxml": "*", 878 | "ext-mbstring": "*", 879 | "ext-xml": "*", 880 | "ext-xmlwriter": "*", 881 | "myclabs/deep-copy": "^1.10.1", 882 | "phar-io/manifest": "^2.0.3", 883 | "phar-io/version": "^3.0.2", 884 | "php": ">=7.3", 885 | "phpunit/php-code-coverage": "^9.2.28", 886 | "phpunit/php-file-iterator": "^3.0.5", 887 | "phpunit/php-invoker": "^3.1.1", 888 | "phpunit/php-text-template": "^2.0.3", 889 | "phpunit/php-timer": "^5.0.2", 890 | "sebastian/cli-parser": "^1.0.1", 891 | "sebastian/code-unit": "^1.0.6", 892 | "sebastian/comparator": "^4.0.8", 893 | "sebastian/diff": "^4.0.3", 894 | "sebastian/environment": "^5.1.3", 895 | "sebastian/exporter": "^4.0.5", 896 | "sebastian/global-state": "^5.0.1", 897 | "sebastian/object-enumerator": "^4.0.3", 898 | "sebastian/resource-operations": "^3.0.3", 899 | "sebastian/type": "^3.2", 900 | "sebastian/version": "^3.0.2" 901 | }, 902 | "suggest": { 903 | "ext-soap": "To be able to generate mocks based on WSDL files", 904 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 905 | }, 906 | "bin": [ 907 | "phpunit" 908 | ], 909 | "type": "library", 910 | "extra": { 911 | "branch-alias": { 912 | "dev-master": "9.6-dev" 913 | } 914 | }, 915 | "autoload": { 916 | "files": [ 917 | "src/Framework/Assert/Functions.php" 918 | ], 919 | "classmap": [ 920 | "src/" 921 | ] 922 | }, 923 | "notification-url": "https://packagist.org/downloads/", 924 | "license": [ 925 | "BSD-3-Clause" 926 | ], 927 | "authors": [ 928 | { 929 | "name": "Sebastian Bergmann", 930 | "email": "sebastian@phpunit.de", 931 | "role": "lead" 932 | } 933 | ], 934 | "description": "The PHP Unit Testing framework.", 935 | "homepage": "https://phpunit.de/", 936 | "keywords": [ 937 | "phpunit", 938 | "testing", 939 | "xunit" 940 | ], 941 | "support": { 942 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 943 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy", 944 | "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.13" 945 | }, 946 | "funding": [ 947 | { 948 | "url": "https://phpunit.de/sponsors.html", 949 | "type": "custom" 950 | }, 951 | { 952 | "url": "https://github.com/sebastianbergmann", 953 | "type": "github" 954 | }, 955 | { 956 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 957 | "type": "tidelift" 958 | } 959 | ], 960 | "time": "2023-09-19T05:39:22+00:00" 961 | }, 962 | { 963 | "name": "sebastian/cli-parser", 964 | "version": "1.0.1", 965 | "source": { 966 | "type": "git", 967 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 968 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" 969 | }, 970 | "dist": { 971 | "type": "zip", 972 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", 973 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", 974 | "shasum": "" 975 | }, 976 | "require": { 977 | "php": ">=7.3" 978 | }, 979 | "require-dev": { 980 | "phpunit/phpunit": "^9.3" 981 | }, 982 | "type": "library", 983 | "extra": { 984 | "branch-alias": { 985 | "dev-master": "1.0-dev" 986 | } 987 | }, 988 | "autoload": { 989 | "classmap": [ 990 | "src/" 991 | ] 992 | }, 993 | "notification-url": "https://packagist.org/downloads/", 994 | "license": [ 995 | "BSD-3-Clause" 996 | ], 997 | "authors": [ 998 | { 999 | "name": "Sebastian Bergmann", 1000 | "email": "sebastian@phpunit.de", 1001 | "role": "lead" 1002 | } 1003 | ], 1004 | "description": "Library for parsing CLI options", 1005 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 1006 | "support": { 1007 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 1008 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" 1009 | }, 1010 | "funding": [ 1011 | { 1012 | "url": "https://github.com/sebastianbergmann", 1013 | "type": "github" 1014 | } 1015 | ], 1016 | "time": "2020-09-28T06:08:49+00:00" 1017 | }, 1018 | { 1019 | "name": "sebastian/code-unit", 1020 | "version": "1.0.8", 1021 | "source": { 1022 | "type": "git", 1023 | "url": "https://github.com/sebastianbergmann/code-unit.git", 1024 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" 1025 | }, 1026 | "dist": { 1027 | "type": "zip", 1028 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", 1029 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", 1030 | "shasum": "" 1031 | }, 1032 | "require": { 1033 | "php": ">=7.3" 1034 | }, 1035 | "require-dev": { 1036 | "phpunit/phpunit": "^9.3" 1037 | }, 1038 | "type": "library", 1039 | "extra": { 1040 | "branch-alias": { 1041 | "dev-master": "1.0-dev" 1042 | } 1043 | }, 1044 | "autoload": { 1045 | "classmap": [ 1046 | "src/" 1047 | ] 1048 | }, 1049 | "notification-url": "https://packagist.org/downloads/", 1050 | "license": [ 1051 | "BSD-3-Clause" 1052 | ], 1053 | "authors": [ 1054 | { 1055 | "name": "Sebastian Bergmann", 1056 | "email": "sebastian@phpunit.de", 1057 | "role": "lead" 1058 | } 1059 | ], 1060 | "description": "Collection of value objects that represent the PHP code units", 1061 | "homepage": "https://github.com/sebastianbergmann/code-unit", 1062 | "support": { 1063 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 1064 | "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" 1065 | }, 1066 | "funding": [ 1067 | { 1068 | "url": "https://github.com/sebastianbergmann", 1069 | "type": "github" 1070 | } 1071 | ], 1072 | "time": "2020-10-26T13:08:54+00:00" 1073 | }, 1074 | { 1075 | "name": "sebastian/code-unit-reverse-lookup", 1076 | "version": "2.0.3", 1077 | "source": { 1078 | "type": "git", 1079 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1080 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" 1081 | }, 1082 | "dist": { 1083 | "type": "zip", 1084 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1085 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1086 | "shasum": "" 1087 | }, 1088 | "require": { 1089 | "php": ">=7.3" 1090 | }, 1091 | "require-dev": { 1092 | "phpunit/phpunit": "^9.3" 1093 | }, 1094 | "type": "library", 1095 | "extra": { 1096 | "branch-alias": { 1097 | "dev-master": "2.0-dev" 1098 | } 1099 | }, 1100 | "autoload": { 1101 | "classmap": [ 1102 | "src/" 1103 | ] 1104 | }, 1105 | "notification-url": "https://packagist.org/downloads/", 1106 | "license": [ 1107 | "BSD-3-Clause" 1108 | ], 1109 | "authors": [ 1110 | { 1111 | "name": "Sebastian Bergmann", 1112 | "email": "sebastian@phpunit.de" 1113 | } 1114 | ], 1115 | "description": "Looks up which function or method a line of code belongs to", 1116 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1117 | "support": { 1118 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 1119 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" 1120 | }, 1121 | "funding": [ 1122 | { 1123 | "url": "https://github.com/sebastianbergmann", 1124 | "type": "github" 1125 | } 1126 | ], 1127 | "time": "2020-09-28T05:30:19+00:00" 1128 | }, 1129 | { 1130 | "name": "sebastian/comparator", 1131 | "version": "4.0.8", 1132 | "source": { 1133 | "type": "git", 1134 | "url": "https://github.com/sebastianbergmann/comparator.git", 1135 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a" 1136 | }, 1137 | "dist": { 1138 | "type": "zip", 1139 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", 1140 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a", 1141 | "shasum": "" 1142 | }, 1143 | "require": { 1144 | "php": ">=7.3", 1145 | "sebastian/diff": "^4.0", 1146 | "sebastian/exporter": "^4.0" 1147 | }, 1148 | "require-dev": { 1149 | "phpunit/phpunit": "^9.3" 1150 | }, 1151 | "type": "library", 1152 | "extra": { 1153 | "branch-alias": { 1154 | "dev-master": "4.0-dev" 1155 | } 1156 | }, 1157 | "autoload": { 1158 | "classmap": [ 1159 | "src/" 1160 | ] 1161 | }, 1162 | "notification-url": "https://packagist.org/downloads/", 1163 | "license": [ 1164 | "BSD-3-Clause" 1165 | ], 1166 | "authors": [ 1167 | { 1168 | "name": "Sebastian Bergmann", 1169 | "email": "sebastian@phpunit.de" 1170 | }, 1171 | { 1172 | "name": "Jeff Welch", 1173 | "email": "whatthejeff@gmail.com" 1174 | }, 1175 | { 1176 | "name": "Volker Dusch", 1177 | "email": "github@wallbash.com" 1178 | }, 1179 | { 1180 | "name": "Bernhard Schussek", 1181 | "email": "bschussek@2bepublished.at" 1182 | } 1183 | ], 1184 | "description": "Provides the functionality to compare PHP values for equality", 1185 | "homepage": "https://github.com/sebastianbergmann/comparator", 1186 | "keywords": [ 1187 | "comparator", 1188 | "compare", 1189 | "equality" 1190 | ], 1191 | "support": { 1192 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 1193 | "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" 1194 | }, 1195 | "funding": [ 1196 | { 1197 | "url": "https://github.com/sebastianbergmann", 1198 | "type": "github" 1199 | } 1200 | ], 1201 | "time": "2022-09-14T12:41:17+00:00" 1202 | }, 1203 | { 1204 | "name": "sebastian/complexity", 1205 | "version": "2.0.2", 1206 | "source": { 1207 | "type": "git", 1208 | "url": "https://github.com/sebastianbergmann/complexity.git", 1209 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" 1210 | }, 1211 | "dist": { 1212 | "type": "zip", 1213 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", 1214 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", 1215 | "shasum": "" 1216 | }, 1217 | "require": { 1218 | "nikic/php-parser": "^4.7", 1219 | "php": ">=7.3" 1220 | }, 1221 | "require-dev": { 1222 | "phpunit/phpunit": "^9.3" 1223 | }, 1224 | "type": "library", 1225 | "extra": { 1226 | "branch-alias": { 1227 | "dev-master": "2.0-dev" 1228 | } 1229 | }, 1230 | "autoload": { 1231 | "classmap": [ 1232 | "src/" 1233 | ] 1234 | }, 1235 | "notification-url": "https://packagist.org/downloads/", 1236 | "license": [ 1237 | "BSD-3-Clause" 1238 | ], 1239 | "authors": [ 1240 | { 1241 | "name": "Sebastian Bergmann", 1242 | "email": "sebastian@phpunit.de", 1243 | "role": "lead" 1244 | } 1245 | ], 1246 | "description": "Library for calculating the complexity of PHP code units", 1247 | "homepage": "https://github.com/sebastianbergmann/complexity", 1248 | "support": { 1249 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 1250 | "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" 1251 | }, 1252 | "funding": [ 1253 | { 1254 | "url": "https://github.com/sebastianbergmann", 1255 | "type": "github" 1256 | } 1257 | ], 1258 | "time": "2020-10-26T15:52:27+00:00" 1259 | }, 1260 | { 1261 | "name": "sebastian/diff", 1262 | "version": "4.0.5", 1263 | "source": { 1264 | "type": "git", 1265 | "url": "https://github.com/sebastianbergmann/diff.git", 1266 | "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" 1267 | }, 1268 | "dist": { 1269 | "type": "zip", 1270 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", 1271 | "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", 1272 | "shasum": "" 1273 | }, 1274 | "require": { 1275 | "php": ">=7.3" 1276 | }, 1277 | "require-dev": { 1278 | "phpunit/phpunit": "^9.3", 1279 | "symfony/process": "^4.2 || ^5" 1280 | }, 1281 | "type": "library", 1282 | "extra": { 1283 | "branch-alias": { 1284 | "dev-master": "4.0-dev" 1285 | } 1286 | }, 1287 | "autoload": { 1288 | "classmap": [ 1289 | "src/" 1290 | ] 1291 | }, 1292 | "notification-url": "https://packagist.org/downloads/", 1293 | "license": [ 1294 | "BSD-3-Clause" 1295 | ], 1296 | "authors": [ 1297 | { 1298 | "name": "Sebastian Bergmann", 1299 | "email": "sebastian@phpunit.de" 1300 | }, 1301 | { 1302 | "name": "Kore Nordmann", 1303 | "email": "mail@kore-nordmann.de" 1304 | } 1305 | ], 1306 | "description": "Diff implementation", 1307 | "homepage": "https://github.com/sebastianbergmann/diff", 1308 | "keywords": [ 1309 | "diff", 1310 | "udiff", 1311 | "unidiff", 1312 | "unified diff" 1313 | ], 1314 | "support": { 1315 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1316 | "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" 1317 | }, 1318 | "funding": [ 1319 | { 1320 | "url": "https://github.com/sebastianbergmann", 1321 | "type": "github" 1322 | } 1323 | ], 1324 | "time": "2023-05-07T05:35:17+00:00" 1325 | }, 1326 | { 1327 | "name": "sebastian/environment", 1328 | "version": "5.1.5", 1329 | "source": { 1330 | "type": "git", 1331 | "url": "https://github.com/sebastianbergmann/environment.git", 1332 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" 1333 | }, 1334 | "dist": { 1335 | "type": "zip", 1336 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1337 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1338 | "shasum": "" 1339 | }, 1340 | "require": { 1341 | "php": ">=7.3" 1342 | }, 1343 | "require-dev": { 1344 | "phpunit/phpunit": "^9.3" 1345 | }, 1346 | "suggest": { 1347 | "ext-posix": "*" 1348 | }, 1349 | "type": "library", 1350 | "extra": { 1351 | "branch-alias": { 1352 | "dev-master": "5.1-dev" 1353 | } 1354 | }, 1355 | "autoload": { 1356 | "classmap": [ 1357 | "src/" 1358 | ] 1359 | }, 1360 | "notification-url": "https://packagist.org/downloads/", 1361 | "license": [ 1362 | "BSD-3-Clause" 1363 | ], 1364 | "authors": [ 1365 | { 1366 | "name": "Sebastian Bergmann", 1367 | "email": "sebastian@phpunit.de" 1368 | } 1369 | ], 1370 | "description": "Provides functionality to handle HHVM/PHP environments", 1371 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1372 | "keywords": [ 1373 | "Xdebug", 1374 | "environment", 1375 | "hhvm" 1376 | ], 1377 | "support": { 1378 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1379 | "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" 1380 | }, 1381 | "funding": [ 1382 | { 1383 | "url": "https://github.com/sebastianbergmann", 1384 | "type": "github" 1385 | } 1386 | ], 1387 | "time": "2023-02-03T06:03:51+00:00" 1388 | }, 1389 | { 1390 | "name": "sebastian/exporter", 1391 | "version": "4.0.5", 1392 | "source": { 1393 | "type": "git", 1394 | "url": "https://github.com/sebastianbergmann/exporter.git", 1395 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" 1396 | }, 1397 | "dist": { 1398 | "type": "zip", 1399 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", 1400 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", 1401 | "shasum": "" 1402 | }, 1403 | "require": { 1404 | "php": ">=7.3", 1405 | "sebastian/recursion-context": "^4.0" 1406 | }, 1407 | "require-dev": { 1408 | "ext-mbstring": "*", 1409 | "phpunit/phpunit": "^9.3" 1410 | }, 1411 | "type": "library", 1412 | "extra": { 1413 | "branch-alias": { 1414 | "dev-master": "4.0-dev" 1415 | } 1416 | }, 1417 | "autoload": { 1418 | "classmap": [ 1419 | "src/" 1420 | ] 1421 | }, 1422 | "notification-url": "https://packagist.org/downloads/", 1423 | "license": [ 1424 | "BSD-3-Clause" 1425 | ], 1426 | "authors": [ 1427 | { 1428 | "name": "Sebastian Bergmann", 1429 | "email": "sebastian@phpunit.de" 1430 | }, 1431 | { 1432 | "name": "Jeff Welch", 1433 | "email": "whatthejeff@gmail.com" 1434 | }, 1435 | { 1436 | "name": "Volker Dusch", 1437 | "email": "github@wallbash.com" 1438 | }, 1439 | { 1440 | "name": "Adam Harvey", 1441 | "email": "aharvey@php.net" 1442 | }, 1443 | { 1444 | "name": "Bernhard Schussek", 1445 | "email": "bschussek@gmail.com" 1446 | } 1447 | ], 1448 | "description": "Provides the functionality to export PHP variables for visualization", 1449 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 1450 | "keywords": [ 1451 | "export", 1452 | "exporter" 1453 | ], 1454 | "support": { 1455 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1456 | "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" 1457 | }, 1458 | "funding": [ 1459 | { 1460 | "url": "https://github.com/sebastianbergmann", 1461 | "type": "github" 1462 | } 1463 | ], 1464 | "time": "2022-09-14T06:03:37+00:00" 1465 | }, 1466 | { 1467 | "name": "sebastian/global-state", 1468 | "version": "5.0.6", 1469 | "source": { 1470 | "type": "git", 1471 | "url": "https://github.com/sebastianbergmann/global-state.git", 1472 | "reference": "bde739e7565280bda77be70044ac1047bc007e34" 1473 | }, 1474 | "dist": { 1475 | "type": "zip", 1476 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", 1477 | "reference": "bde739e7565280bda77be70044ac1047bc007e34", 1478 | "shasum": "" 1479 | }, 1480 | "require": { 1481 | "php": ">=7.3", 1482 | "sebastian/object-reflector": "^2.0", 1483 | "sebastian/recursion-context": "^4.0" 1484 | }, 1485 | "require-dev": { 1486 | "ext-dom": "*", 1487 | "phpunit/phpunit": "^9.3" 1488 | }, 1489 | "suggest": { 1490 | "ext-uopz": "*" 1491 | }, 1492 | "type": "library", 1493 | "extra": { 1494 | "branch-alias": { 1495 | "dev-master": "5.0-dev" 1496 | } 1497 | }, 1498 | "autoload": { 1499 | "classmap": [ 1500 | "src/" 1501 | ] 1502 | }, 1503 | "notification-url": "https://packagist.org/downloads/", 1504 | "license": [ 1505 | "BSD-3-Clause" 1506 | ], 1507 | "authors": [ 1508 | { 1509 | "name": "Sebastian Bergmann", 1510 | "email": "sebastian@phpunit.de" 1511 | } 1512 | ], 1513 | "description": "Snapshotting of global state", 1514 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1515 | "keywords": [ 1516 | "global state" 1517 | ], 1518 | "support": { 1519 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1520 | "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" 1521 | }, 1522 | "funding": [ 1523 | { 1524 | "url": "https://github.com/sebastianbergmann", 1525 | "type": "github" 1526 | } 1527 | ], 1528 | "time": "2023-08-02T09:26:13+00:00" 1529 | }, 1530 | { 1531 | "name": "sebastian/lines-of-code", 1532 | "version": "1.0.3", 1533 | "source": { 1534 | "type": "git", 1535 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 1536 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" 1537 | }, 1538 | "dist": { 1539 | "type": "zip", 1540 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", 1541 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", 1542 | "shasum": "" 1543 | }, 1544 | "require": { 1545 | "nikic/php-parser": "^4.6", 1546 | "php": ">=7.3" 1547 | }, 1548 | "require-dev": { 1549 | "phpunit/phpunit": "^9.3" 1550 | }, 1551 | "type": "library", 1552 | "extra": { 1553 | "branch-alias": { 1554 | "dev-master": "1.0-dev" 1555 | } 1556 | }, 1557 | "autoload": { 1558 | "classmap": [ 1559 | "src/" 1560 | ] 1561 | }, 1562 | "notification-url": "https://packagist.org/downloads/", 1563 | "license": [ 1564 | "BSD-3-Clause" 1565 | ], 1566 | "authors": [ 1567 | { 1568 | "name": "Sebastian Bergmann", 1569 | "email": "sebastian@phpunit.de", 1570 | "role": "lead" 1571 | } 1572 | ], 1573 | "description": "Library for counting the lines of code in PHP source code", 1574 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 1575 | "support": { 1576 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 1577 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" 1578 | }, 1579 | "funding": [ 1580 | { 1581 | "url": "https://github.com/sebastianbergmann", 1582 | "type": "github" 1583 | } 1584 | ], 1585 | "time": "2020-11-28T06:42:11+00:00" 1586 | }, 1587 | { 1588 | "name": "sebastian/object-enumerator", 1589 | "version": "4.0.4", 1590 | "source": { 1591 | "type": "git", 1592 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1593 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" 1594 | }, 1595 | "dist": { 1596 | "type": "zip", 1597 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", 1598 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", 1599 | "shasum": "" 1600 | }, 1601 | "require": { 1602 | "php": ">=7.3", 1603 | "sebastian/object-reflector": "^2.0", 1604 | "sebastian/recursion-context": "^4.0" 1605 | }, 1606 | "require-dev": { 1607 | "phpunit/phpunit": "^9.3" 1608 | }, 1609 | "type": "library", 1610 | "extra": { 1611 | "branch-alias": { 1612 | "dev-master": "4.0-dev" 1613 | } 1614 | }, 1615 | "autoload": { 1616 | "classmap": [ 1617 | "src/" 1618 | ] 1619 | }, 1620 | "notification-url": "https://packagist.org/downloads/", 1621 | "license": [ 1622 | "BSD-3-Clause" 1623 | ], 1624 | "authors": [ 1625 | { 1626 | "name": "Sebastian Bergmann", 1627 | "email": "sebastian@phpunit.de" 1628 | } 1629 | ], 1630 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1631 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1632 | "support": { 1633 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1634 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" 1635 | }, 1636 | "funding": [ 1637 | { 1638 | "url": "https://github.com/sebastianbergmann", 1639 | "type": "github" 1640 | } 1641 | ], 1642 | "time": "2020-10-26T13:12:34+00:00" 1643 | }, 1644 | { 1645 | "name": "sebastian/object-reflector", 1646 | "version": "2.0.4", 1647 | "source": { 1648 | "type": "git", 1649 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1650 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" 1651 | }, 1652 | "dist": { 1653 | "type": "zip", 1654 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 1655 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 1656 | "shasum": "" 1657 | }, 1658 | "require": { 1659 | "php": ">=7.3" 1660 | }, 1661 | "require-dev": { 1662 | "phpunit/phpunit": "^9.3" 1663 | }, 1664 | "type": "library", 1665 | "extra": { 1666 | "branch-alias": { 1667 | "dev-master": "2.0-dev" 1668 | } 1669 | }, 1670 | "autoload": { 1671 | "classmap": [ 1672 | "src/" 1673 | ] 1674 | }, 1675 | "notification-url": "https://packagist.org/downloads/", 1676 | "license": [ 1677 | "BSD-3-Clause" 1678 | ], 1679 | "authors": [ 1680 | { 1681 | "name": "Sebastian Bergmann", 1682 | "email": "sebastian@phpunit.de" 1683 | } 1684 | ], 1685 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1686 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1687 | "support": { 1688 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 1689 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" 1690 | }, 1691 | "funding": [ 1692 | { 1693 | "url": "https://github.com/sebastianbergmann", 1694 | "type": "github" 1695 | } 1696 | ], 1697 | "time": "2020-10-26T13:14:26+00:00" 1698 | }, 1699 | { 1700 | "name": "sebastian/recursion-context", 1701 | "version": "4.0.5", 1702 | "source": { 1703 | "type": "git", 1704 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1705 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" 1706 | }, 1707 | "dist": { 1708 | "type": "zip", 1709 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 1710 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 1711 | "shasum": "" 1712 | }, 1713 | "require": { 1714 | "php": ">=7.3" 1715 | }, 1716 | "require-dev": { 1717 | "phpunit/phpunit": "^9.3" 1718 | }, 1719 | "type": "library", 1720 | "extra": { 1721 | "branch-alias": { 1722 | "dev-master": "4.0-dev" 1723 | } 1724 | }, 1725 | "autoload": { 1726 | "classmap": [ 1727 | "src/" 1728 | ] 1729 | }, 1730 | "notification-url": "https://packagist.org/downloads/", 1731 | "license": [ 1732 | "BSD-3-Clause" 1733 | ], 1734 | "authors": [ 1735 | { 1736 | "name": "Sebastian Bergmann", 1737 | "email": "sebastian@phpunit.de" 1738 | }, 1739 | { 1740 | "name": "Jeff Welch", 1741 | "email": "whatthejeff@gmail.com" 1742 | }, 1743 | { 1744 | "name": "Adam Harvey", 1745 | "email": "aharvey@php.net" 1746 | } 1747 | ], 1748 | "description": "Provides functionality to recursively process PHP variables", 1749 | "homepage": "https://github.com/sebastianbergmann/recursion-context", 1750 | "support": { 1751 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1752 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" 1753 | }, 1754 | "funding": [ 1755 | { 1756 | "url": "https://github.com/sebastianbergmann", 1757 | "type": "github" 1758 | } 1759 | ], 1760 | "time": "2023-02-03T06:07:39+00:00" 1761 | }, 1762 | { 1763 | "name": "sebastian/resource-operations", 1764 | "version": "3.0.3", 1765 | "source": { 1766 | "type": "git", 1767 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1768 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" 1769 | }, 1770 | "dist": { 1771 | "type": "zip", 1772 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 1773 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 1774 | "shasum": "" 1775 | }, 1776 | "require": { 1777 | "php": ">=7.3" 1778 | }, 1779 | "require-dev": { 1780 | "phpunit/phpunit": "^9.0" 1781 | }, 1782 | "type": "library", 1783 | "extra": { 1784 | "branch-alias": { 1785 | "dev-master": "3.0-dev" 1786 | } 1787 | }, 1788 | "autoload": { 1789 | "classmap": [ 1790 | "src/" 1791 | ] 1792 | }, 1793 | "notification-url": "https://packagist.org/downloads/", 1794 | "license": [ 1795 | "BSD-3-Clause" 1796 | ], 1797 | "authors": [ 1798 | { 1799 | "name": "Sebastian Bergmann", 1800 | "email": "sebastian@phpunit.de" 1801 | } 1802 | ], 1803 | "description": "Provides a list of PHP built-in functions that operate on resources", 1804 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1805 | "support": { 1806 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues", 1807 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" 1808 | }, 1809 | "funding": [ 1810 | { 1811 | "url": "https://github.com/sebastianbergmann", 1812 | "type": "github" 1813 | } 1814 | ], 1815 | "time": "2020-09-28T06:45:17+00:00" 1816 | }, 1817 | { 1818 | "name": "sebastian/type", 1819 | "version": "3.2.1", 1820 | "source": { 1821 | "type": "git", 1822 | "url": "https://github.com/sebastianbergmann/type.git", 1823 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" 1824 | }, 1825 | "dist": { 1826 | "type": "zip", 1827 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 1828 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 1829 | "shasum": "" 1830 | }, 1831 | "require": { 1832 | "php": ">=7.3" 1833 | }, 1834 | "require-dev": { 1835 | "phpunit/phpunit": "^9.5" 1836 | }, 1837 | "type": "library", 1838 | "extra": { 1839 | "branch-alias": { 1840 | "dev-master": "3.2-dev" 1841 | } 1842 | }, 1843 | "autoload": { 1844 | "classmap": [ 1845 | "src/" 1846 | ] 1847 | }, 1848 | "notification-url": "https://packagist.org/downloads/", 1849 | "license": [ 1850 | "BSD-3-Clause" 1851 | ], 1852 | "authors": [ 1853 | { 1854 | "name": "Sebastian Bergmann", 1855 | "email": "sebastian@phpunit.de", 1856 | "role": "lead" 1857 | } 1858 | ], 1859 | "description": "Collection of value objects that represent the types of the PHP type system", 1860 | "homepage": "https://github.com/sebastianbergmann/type", 1861 | "support": { 1862 | "issues": "https://github.com/sebastianbergmann/type/issues", 1863 | "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" 1864 | }, 1865 | "funding": [ 1866 | { 1867 | "url": "https://github.com/sebastianbergmann", 1868 | "type": "github" 1869 | } 1870 | ], 1871 | "time": "2023-02-03T06:13:03+00:00" 1872 | }, 1873 | { 1874 | "name": "sebastian/version", 1875 | "version": "3.0.2", 1876 | "source": { 1877 | "type": "git", 1878 | "url": "https://github.com/sebastianbergmann/version.git", 1879 | "reference": "c6c1022351a901512170118436c764e473f6de8c" 1880 | }, 1881 | "dist": { 1882 | "type": "zip", 1883 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", 1884 | "reference": "c6c1022351a901512170118436c764e473f6de8c", 1885 | "shasum": "" 1886 | }, 1887 | "require": { 1888 | "php": ">=7.3" 1889 | }, 1890 | "type": "library", 1891 | "extra": { 1892 | "branch-alias": { 1893 | "dev-master": "3.0-dev" 1894 | } 1895 | }, 1896 | "autoload": { 1897 | "classmap": [ 1898 | "src/" 1899 | ] 1900 | }, 1901 | "notification-url": "https://packagist.org/downloads/", 1902 | "license": [ 1903 | "BSD-3-Clause" 1904 | ], 1905 | "authors": [ 1906 | { 1907 | "name": "Sebastian Bergmann", 1908 | "email": "sebastian@phpunit.de", 1909 | "role": "lead" 1910 | } 1911 | ], 1912 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1913 | "homepage": "https://github.com/sebastianbergmann/version", 1914 | "support": { 1915 | "issues": "https://github.com/sebastianbergmann/version/issues", 1916 | "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" 1917 | }, 1918 | "funding": [ 1919 | { 1920 | "url": "https://github.com/sebastianbergmann", 1921 | "type": "github" 1922 | } 1923 | ], 1924 | "time": "2020-09-28T06:39:44+00:00" 1925 | }, 1926 | { 1927 | "name": "slevomat/coding-standard", 1928 | "version": "7.2.1", 1929 | "source": { 1930 | "type": "git", 1931 | "url": "https://github.com/slevomat/coding-standard.git", 1932 | "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90" 1933 | }, 1934 | "dist": { 1935 | "type": "zip", 1936 | "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/aff06ae7a84e4534bf6f821dc982a93a5d477c90", 1937 | "reference": "aff06ae7a84e4534bf6f821dc982a93a5d477c90", 1938 | "shasum": "" 1939 | }, 1940 | "require": { 1941 | "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", 1942 | "php": "^7.2 || ^8.0", 1943 | "phpstan/phpdoc-parser": "^1.5.1", 1944 | "squizlabs/php_codesniffer": "^3.6.2" 1945 | }, 1946 | "require-dev": { 1947 | "phing/phing": "2.17.3", 1948 | "php-parallel-lint/php-parallel-lint": "1.3.2", 1949 | "phpstan/phpstan": "1.4.10|1.7.1", 1950 | "phpstan/phpstan-deprecation-rules": "1.0.0", 1951 | "phpstan/phpstan-phpunit": "1.0.0|1.1.1", 1952 | "phpstan/phpstan-strict-rules": "1.2.3", 1953 | "phpunit/phpunit": "7.5.20|8.5.21|9.5.20" 1954 | }, 1955 | "type": "phpcodesniffer-standard", 1956 | "extra": { 1957 | "branch-alias": { 1958 | "dev-master": "7.x-dev" 1959 | } 1960 | }, 1961 | "autoload": { 1962 | "psr-4": { 1963 | "SlevomatCodingStandard\\": "SlevomatCodingStandard" 1964 | } 1965 | }, 1966 | "notification-url": "https://packagist.org/downloads/", 1967 | "license": [ 1968 | "MIT" 1969 | ], 1970 | "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", 1971 | "support": { 1972 | "issues": "https://github.com/slevomat/coding-standard/issues", 1973 | "source": "https://github.com/slevomat/coding-standard/tree/7.2.1" 1974 | }, 1975 | "funding": [ 1976 | { 1977 | "url": "https://github.com/kukulich", 1978 | "type": "github" 1979 | }, 1980 | { 1981 | "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", 1982 | "type": "tidelift" 1983 | } 1984 | ], 1985 | "time": "2022-05-25T10:58:12+00:00" 1986 | }, 1987 | { 1988 | "name": "squizlabs/php_codesniffer", 1989 | "version": "3.7.2", 1990 | "source": { 1991 | "type": "git", 1992 | "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", 1993 | "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" 1994 | }, 1995 | "dist": { 1996 | "type": "zip", 1997 | "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", 1998 | "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", 1999 | "shasum": "" 2000 | }, 2001 | "require": { 2002 | "ext-simplexml": "*", 2003 | "ext-tokenizer": "*", 2004 | "ext-xmlwriter": "*", 2005 | "php": ">=5.4.0" 2006 | }, 2007 | "require-dev": { 2008 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" 2009 | }, 2010 | "bin": [ 2011 | "bin/phpcs", 2012 | "bin/phpcbf" 2013 | ], 2014 | "type": "library", 2015 | "extra": { 2016 | "branch-alias": { 2017 | "dev-master": "3.x-dev" 2018 | } 2019 | }, 2020 | "notification-url": "https://packagist.org/downloads/", 2021 | "license": [ 2022 | "BSD-3-Clause" 2023 | ], 2024 | "authors": [ 2025 | { 2026 | "name": "Greg Sherwood", 2027 | "role": "lead" 2028 | } 2029 | ], 2030 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 2031 | "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", 2032 | "keywords": [ 2033 | "phpcs", 2034 | "standards", 2035 | "static analysis" 2036 | ], 2037 | "support": { 2038 | "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", 2039 | "source": "https://github.com/squizlabs/PHP_CodeSniffer", 2040 | "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" 2041 | }, 2042 | "funding": [ 2043 | { 2044 | "url": "https://github.com/PHPCSStandards", 2045 | "type": "github" 2046 | }, 2047 | { 2048 | "url": "https://github.com/jrfnl", 2049 | "type": "github" 2050 | }, 2051 | { 2052 | "url": "https://opencollective.com/php_codesniffer", 2053 | "type": "open_collective" 2054 | } 2055 | ], 2056 | "time": "2023-02-22T23:07:41+00:00" 2057 | }, 2058 | { 2059 | "name": "theseer/tokenizer", 2060 | "version": "1.2.1", 2061 | "source": { 2062 | "type": "git", 2063 | "url": "https://github.com/theseer/tokenizer.git", 2064 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" 2065 | }, 2066 | "dist": { 2067 | "type": "zip", 2068 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", 2069 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", 2070 | "shasum": "" 2071 | }, 2072 | "require": { 2073 | "ext-dom": "*", 2074 | "ext-tokenizer": "*", 2075 | "ext-xmlwriter": "*", 2076 | "php": "^7.2 || ^8.0" 2077 | }, 2078 | "type": "library", 2079 | "autoload": { 2080 | "classmap": [ 2081 | "src/" 2082 | ] 2083 | }, 2084 | "notification-url": "https://packagist.org/downloads/", 2085 | "license": [ 2086 | "BSD-3-Clause" 2087 | ], 2088 | "authors": [ 2089 | { 2090 | "name": "Arne Blankerts", 2091 | "email": "arne@blankerts.de", 2092 | "role": "Developer" 2093 | } 2094 | ], 2095 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 2096 | "support": { 2097 | "issues": "https://github.com/theseer/tokenizer/issues", 2098 | "source": "https://github.com/theseer/tokenizer/tree/1.2.1" 2099 | }, 2100 | "funding": [ 2101 | { 2102 | "url": "https://github.com/theseer", 2103 | "type": "github" 2104 | } 2105 | ], 2106 | "time": "2021-07-28T10:34:58+00:00" 2107 | }, 2108 | { 2109 | "name": "webimpress/coding-standard", 2110 | "version": "1.3.1", 2111 | "source": { 2112 | "type": "git", 2113 | "url": "https://github.com/webimpress/coding-standard.git", 2114 | "reference": "b26557e2386711ecb74f22718f4b4bde5ddbc899" 2115 | }, 2116 | "dist": { 2117 | "type": "zip", 2118 | "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/b26557e2386711ecb74f22718f4b4bde5ddbc899", 2119 | "reference": "b26557e2386711ecb74f22718f4b4bde5ddbc899", 2120 | "shasum": "" 2121 | }, 2122 | "require": { 2123 | "php": "^7.3 || ^8.0", 2124 | "squizlabs/php_codesniffer": "^3.7.2" 2125 | }, 2126 | "require-dev": { 2127 | "phpunit/phpunit": "^9.6.4" 2128 | }, 2129 | "type": "phpcodesniffer-standard", 2130 | "extra": { 2131 | "dev-master": "1.2.x-dev", 2132 | "dev-develop": "1.3.x-dev" 2133 | }, 2134 | "autoload": { 2135 | "psr-4": { 2136 | "WebimpressCodingStandard\\": "src/WebimpressCodingStandard/" 2137 | } 2138 | }, 2139 | "notification-url": "https://packagist.org/downloads/", 2140 | "license": [ 2141 | "BSD-2-Clause" 2142 | ], 2143 | "description": "Webimpress Coding Standard", 2144 | "keywords": [ 2145 | "Coding Standard", 2146 | "PSR-2", 2147 | "phpcs", 2148 | "psr-12", 2149 | "webimpress" 2150 | ], 2151 | "support": { 2152 | "issues": "https://github.com/webimpress/coding-standard/issues", 2153 | "source": "https://github.com/webimpress/coding-standard/tree/1.3.1" 2154 | }, 2155 | "funding": [ 2156 | { 2157 | "url": "https://github.com/michalbundyra", 2158 | "type": "github" 2159 | } 2160 | ], 2161 | "time": "2023-03-09T15:05:18+00:00" 2162 | } 2163 | ], 2164 | "aliases": [], 2165 | "minimum-stability": "stable", 2166 | "stability-flags": [], 2167 | "prefer-stable": false, 2168 | "prefer-lowest": false, 2169 | "platform": { 2170 | "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" 2171 | }, 2172 | "platform-dev": [], 2173 | "plugin-api-version": "2.6.0" 2174 | } 2175 | --------------------------------------------------------------------------------