├── .gitignore ├── Dockerfile ├── composer.json ├── composer.lock ├── controllers ├── train_carriages.php └── train_routes.php ├── docs ├── auth.md └── install.md ├── examples ├── index.php ├── station_code.php ├── train_carriages.php ├── train_routes.php ├── train_routes_params.php ├── train_routes_return.php ├── train_routes_transfer.php └── train_station_list.php ├── phpunit.xml ├── readme.md ├── screens ├── trainCarriages.png ├── trainRoute.png ├── trainRouteReturn.png └── trainStationList.png ├── src └── Rzd │ ├── Api.php │ ├── Config.php │ └── Query.php └── tests └── ApiTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | .idea 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM composer:lts 2 | WORKDIR /app 3 | COPY . /app 4 | RUN composer install 5 | EXPOSE 8000 6 | CMD [ "php", "-S", "0.0.0.0:8000", "-t", "controllers" ] 7 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visavi/rzd-api", 3 | "description": "rzd api", 4 | "keywords": ["rzd", "api", "train", "ticket"], 5 | "homepage": "https://visavi.net", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Alexander Grigorev", 10 | "email": "admin@visavi.net", 11 | "homepage": "https://visavi.net" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=8.0", 16 | "ext-json": "*", 17 | "ext-curl": "*", 18 | "ext-mbstring": "*", 19 | "guzzlehttp/guzzle": "^7.8" 20 | }, 21 | "require-dev": { 22 | "phpunit/phpunit": "^9.6", 23 | "symfony/var-dumper": "^v7.0" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "Rzd\\": "src/Rzd/" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /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": "3a08f0851dea899ffb7d6e5488bc69e7", 8 | "packages": [ 9 | { 10 | "name": "guzzlehttp/guzzle", 11 | "version": "7.8.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/guzzle/guzzle.git", 15 | "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", 20 | "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "ext-json": "*", 25 | "guzzlehttp/promises": "^1.5.3 || ^2.0.1", 26 | "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", 27 | "php": "^7.2.5 || ^8.0", 28 | "psr/http-client": "^1.0", 29 | "symfony/deprecation-contracts": "^2.2 || ^3.0" 30 | }, 31 | "provide": { 32 | "psr/http-client-implementation": "1.0" 33 | }, 34 | "require-dev": { 35 | "bamarni/composer-bin-plugin": "^1.8.2", 36 | "ext-curl": "*", 37 | "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", 38 | "php-http/message-factory": "^1.1", 39 | "phpunit/phpunit": "^8.5.36 || ^9.6.15", 40 | "psr/log": "^1.1 || ^2.0 || ^3.0" 41 | }, 42 | "suggest": { 43 | "ext-curl": "Required for CURL handler support", 44 | "ext-intl": "Required for Internationalized Domain Name (IDN) support", 45 | "psr/log": "Required for using the Log middleware" 46 | }, 47 | "type": "library", 48 | "extra": { 49 | "bamarni-bin": { 50 | "bin-links": true, 51 | "forward-command": false 52 | } 53 | }, 54 | "autoload": { 55 | "files": [ 56 | "src/functions_include.php" 57 | ], 58 | "psr-4": { 59 | "GuzzleHttp\\": "src/" 60 | } 61 | }, 62 | "notification-url": "https://packagist.org/downloads/", 63 | "license": [ 64 | "MIT" 65 | ], 66 | "authors": [ 67 | { 68 | "name": "Graham Campbell", 69 | "email": "hello@gjcampbell.co.uk", 70 | "homepage": "https://github.com/GrahamCampbell" 71 | }, 72 | { 73 | "name": "Michael Dowling", 74 | "email": "mtdowling@gmail.com", 75 | "homepage": "https://github.com/mtdowling" 76 | }, 77 | { 78 | "name": "Jeremy Lindblom", 79 | "email": "jeremeamia@gmail.com", 80 | "homepage": "https://github.com/jeremeamia" 81 | }, 82 | { 83 | "name": "George Mponos", 84 | "email": "gmponos@gmail.com", 85 | "homepage": "https://github.com/gmponos" 86 | }, 87 | { 88 | "name": "Tobias Nyholm", 89 | "email": "tobias.nyholm@gmail.com", 90 | "homepage": "https://github.com/Nyholm" 91 | }, 92 | { 93 | "name": "Márk Sági-Kazár", 94 | "email": "mark.sagikazar@gmail.com", 95 | "homepage": "https://github.com/sagikazarmark" 96 | }, 97 | { 98 | "name": "Tobias Schultze", 99 | "email": "webmaster@tubo-world.de", 100 | "homepage": "https://github.com/Tobion" 101 | } 102 | ], 103 | "description": "Guzzle is a PHP HTTP client library", 104 | "keywords": [ 105 | "client", 106 | "curl", 107 | "framework", 108 | "http", 109 | "http client", 110 | "psr-18", 111 | "psr-7", 112 | "rest", 113 | "web service" 114 | ], 115 | "support": { 116 | "issues": "https://github.com/guzzle/guzzle/issues", 117 | "source": "https://github.com/guzzle/guzzle/tree/7.8.1" 118 | }, 119 | "funding": [ 120 | { 121 | "url": "https://github.com/GrahamCampbell", 122 | "type": "github" 123 | }, 124 | { 125 | "url": "https://github.com/Nyholm", 126 | "type": "github" 127 | }, 128 | { 129 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", 130 | "type": "tidelift" 131 | } 132 | ], 133 | "time": "2023-12-03T20:35:24+00:00" 134 | }, 135 | { 136 | "name": "guzzlehttp/promises", 137 | "version": "2.0.2", 138 | "source": { 139 | "type": "git", 140 | "url": "https://github.com/guzzle/promises.git", 141 | "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" 142 | }, 143 | "dist": { 144 | "type": "zip", 145 | "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", 146 | "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", 147 | "shasum": "" 148 | }, 149 | "require": { 150 | "php": "^7.2.5 || ^8.0" 151 | }, 152 | "require-dev": { 153 | "bamarni/composer-bin-plugin": "^1.8.2", 154 | "phpunit/phpunit": "^8.5.36 || ^9.6.15" 155 | }, 156 | "type": "library", 157 | "extra": { 158 | "bamarni-bin": { 159 | "bin-links": true, 160 | "forward-command": false 161 | } 162 | }, 163 | "autoload": { 164 | "psr-4": { 165 | "GuzzleHttp\\Promise\\": "src/" 166 | } 167 | }, 168 | "notification-url": "https://packagist.org/downloads/", 169 | "license": [ 170 | "MIT" 171 | ], 172 | "authors": [ 173 | { 174 | "name": "Graham Campbell", 175 | "email": "hello@gjcampbell.co.uk", 176 | "homepage": "https://github.com/GrahamCampbell" 177 | }, 178 | { 179 | "name": "Michael Dowling", 180 | "email": "mtdowling@gmail.com", 181 | "homepage": "https://github.com/mtdowling" 182 | }, 183 | { 184 | "name": "Tobias Nyholm", 185 | "email": "tobias.nyholm@gmail.com", 186 | "homepage": "https://github.com/Nyholm" 187 | }, 188 | { 189 | "name": "Tobias Schultze", 190 | "email": "webmaster@tubo-world.de", 191 | "homepage": "https://github.com/Tobion" 192 | } 193 | ], 194 | "description": "Guzzle promises library", 195 | "keywords": [ 196 | "promise" 197 | ], 198 | "support": { 199 | "issues": "https://github.com/guzzle/promises/issues", 200 | "source": "https://github.com/guzzle/promises/tree/2.0.2" 201 | }, 202 | "funding": [ 203 | { 204 | "url": "https://github.com/GrahamCampbell", 205 | "type": "github" 206 | }, 207 | { 208 | "url": "https://github.com/Nyholm", 209 | "type": "github" 210 | }, 211 | { 212 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", 213 | "type": "tidelift" 214 | } 215 | ], 216 | "time": "2023-12-03T20:19:20+00:00" 217 | }, 218 | { 219 | "name": "guzzlehttp/psr7", 220 | "version": "2.6.2", 221 | "source": { 222 | "type": "git", 223 | "url": "https://github.com/guzzle/psr7.git", 224 | "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" 225 | }, 226 | "dist": { 227 | "type": "zip", 228 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", 229 | "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", 230 | "shasum": "" 231 | }, 232 | "require": { 233 | "php": "^7.2.5 || ^8.0", 234 | "psr/http-factory": "^1.0", 235 | "psr/http-message": "^1.1 || ^2.0", 236 | "ralouphie/getallheaders": "^3.0" 237 | }, 238 | "provide": { 239 | "psr/http-factory-implementation": "1.0", 240 | "psr/http-message-implementation": "1.0" 241 | }, 242 | "require-dev": { 243 | "bamarni/composer-bin-plugin": "^1.8.2", 244 | "http-interop/http-factory-tests": "^0.9", 245 | "phpunit/phpunit": "^8.5.36 || ^9.6.15" 246 | }, 247 | "suggest": { 248 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" 249 | }, 250 | "type": "library", 251 | "extra": { 252 | "bamarni-bin": { 253 | "bin-links": true, 254 | "forward-command": false 255 | } 256 | }, 257 | "autoload": { 258 | "psr-4": { 259 | "GuzzleHttp\\Psr7\\": "src/" 260 | } 261 | }, 262 | "notification-url": "https://packagist.org/downloads/", 263 | "license": [ 264 | "MIT" 265 | ], 266 | "authors": [ 267 | { 268 | "name": "Graham Campbell", 269 | "email": "hello@gjcampbell.co.uk", 270 | "homepage": "https://github.com/GrahamCampbell" 271 | }, 272 | { 273 | "name": "Michael Dowling", 274 | "email": "mtdowling@gmail.com", 275 | "homepage": "https://github.com/mtdowling" 276 | }, 277 | { 278 | "name": "George Mponos", 279 | "email": "gmponos@gmail.com", 280 | "homepage": "https://github.com/gmponos" 281 | }, 282 | { 283 | "name": "Tobias Nyholm", 284 | "email": "tobias.nyholm@gmail.com", 285 | "homepage": "https://github.com/Nyholm" 286 | }, 287 | { 288 | "name": "Márk Sági-Kazár", 289 | "email": "mark.sagikazar@gmail.com", 290 | "homepage": "https://github.com/sagikazarmark" 291 | }, 292 | { 293 | "name": "Tobias Schultze", 294 | "email": "webmaster@tubo-world.de", 295 | "homepage": "https://github.com/Tobion" 296 | }, 297 | { 298 | "name": "Márk Sági-Kazár", 299 | "email": "mark.sagikazar@gmail.com", 300 | "homepage": "https://sagikazarmark.hu" 301 | } 302 | ], 303 | "description": "PSR-7 message implementation that also provides common utility methods", 304 | "keywords": [ 305 | "http", 306 | "message", 307 | "psr-7", 308 | "request", 309 | "response", 310 | "stream", 311 | "uri", 312 | "url" 313 | ], 314 | "support": { 315 | "issues": "https://github.com/guzzle/psr7/issues", 316 | "source": "https://github.com/guzzle/psr7/tree/2.6.2" 317 | }, 318 | "funding": [ 319 | { 320 | "url": "https://github.com/GrahamCampbell", 321 | "type": "github" 322 | }, 323 | { 324 | "url": "https://github.com/Nyholm", 325 | "type": "github" 326 | }, 327 | { 328 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", 329 | "type": "tidelift" 330 | } 331 | ], 332 | "time": "2023-12-03T20:05:35+00:00" 333 | }, 334 | { 335 | "name": "psr/http-client", 336 | "version": "1.0.3", 337 | "source": { 338 | "type": "git", 339 | "url": "https://github.com/php-fig/http-client.git", 340 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" 341 | }, 342 | "dist": { 343 | "type": "zip", 344 | "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", 345 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", 346 | "shasum": "" 347 | }, 348 | "require": { 349 | "php": "^7.0 || ^8.0", 350 | "psr/http-message": "^1.0 || ^2.0" 351 | }, 352 | "type": "library", 353 | "extra": { 354 | "branch-alias": { 355 | "dev-master": "1.0.x-dev" 356 | } 357 | }, 358 | "autoload": { 359 | "psr-4": { 360 | "Psr\\Http\\Client\\": "src/" 361 | } 362 | }, 363 | "notification-url": "https://packagist.org/downloads/", 364 | "license": [ 365 | "MIT" 366 | ], 367 | "authors": [ 368 | { 369 | "name": "PHP-FIG", 370 | "homepage": "https://www.php-fig.org/" 371 | } 372 | ], 373 | "description": "Common interface for HTTP clients", 374 | "homepage": "https://github.com/php-fig/http-client", 375 | "keywords": [ 376 | "http", 377 | "http-client", 378 | "psr", 379 | "psr-18" 380 | ], 381 | "support": { 382 | "source": "https://github.com/php-fig/http-client" 383 | }, 384 | "time": "2023-09-23T14:17:50+00:00" 385 | }, 386 | { 387 | "name": "psr/http-factory", 388 | "version": "1.0.2", 389 | "source": { 390 | "type": "git", 391 | "url": "https://github.com/php-fig/http-factory.git", 392 | "reference": "e616d01114759c4c489f93b099585439f795fe35" 393 | }, 394 | "dist": { 395 | "type": "zip", 396 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", 397 | "reference": "e616d01114759c4c489f93b099585439f795fe35", 398 | "shasum": "" 399 | }, 400 | "require": { 401 | "php": ">=7.0.0", 402 | "psr/http-message": "^1.0 || ^2.0" 403 | }, 404 | "type": "library", 405 | "extra": { 406 | "branch-alias": { 407 | "dev-master": "1.0.x-dev" 408 | } 409 | }, 410 | "autoload": { 411 | "psr-4": { 412 | "Psr\\Http\\Message\\": "src/" 413 | } 414 | }, 415 | "notification-url": "https://packagist.org/downloads/", 416 | "license": [ 417 | "MIT" 418 | ], 419 | "authors": [ 420 | { 421 | "name": "PHP-FIG", 422 | "homepage": "https://www.php-fig.org/" 423 | } 424 | ], 425 | "description": "Common interfaces for PSR-7 HTTP message factories", 426 | "keywords": [ 427 | "factory", 428 | "http", 429 | "message", 430 | "psr", 431 | "psr-17", 432 | "psr-7", 433 | "request", 434 | "response" 435 | ], 436 | "support": { 437 | "source": "https://github.com/php-fig/http-factory/tree/1.0.2" 438 | }, 439 | "time": "2023-04-10T20:10:41+00:00" 440 | }, 441 | { 442 | "name": "psr/http-message", 443 | "version": "2.0", 444 | "source": { 445 | "type": "git", 446 | "url": "https://github.com/php-fig/http-message.git", 447 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" 448 | }, 449 | "dist": { 450 | "type": "zip", 451 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", 452 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", 453 | "shasum": "" 454 | }, 455 | "require": { 456 | "php": "^7.2 || ^8.0" 457 | }, 458 | "type": "library", 459 | "extra": { 460 | "branch-alias": { 461 | "dev-master": "2.0.x-dev" 462 | } 463 | }, 464 | "autoload": { 465 | "psr-4": { 466 | "Psr\\Http\\Message\\": "src/" 467 | } 468 | }, 469 | "notification-url": "https://packagist.org/downloads/", 470 | "license": [ 471 | "MIT" 472 | ], 473 | "authors": [ 474 | { 475 | "name": "PHP-FIG", 476 | "homepage": "https://www.php-fig.org/" 477 | } 478 | ], 479 | "description": "Common interface for HTTP messages", 480 | "homepage": "https://github.com/php-fig/http-message", 481 | "keywords": [ 482 | "http", 483 | "http-message", 484 | "psr", 485 | "psr-7", 486 | "request", 487 | "response" 488 | ], 489 | "support": { 490 | "source": "https://github.com/php-fig/http-message/tree/2.0" 491 | }, 492 | "time": "2023-04-04T09:54:51+00:00" 493 | }, 494 | { 495 | "name": "ralouphie/getallheaders", 496 | "version": "3.0.3", 497 | "source": { 498 | "type": "git", 499 | "url": "https://github.com/ralouphie/getallheaders.git", 500 | "reference": "120b605dfeb996808c31b6477290a714d356e822" 501 | }, 502 | "dist": { 503 | "type": "zip", 504 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", 505 | "reference": "120b605dfeb996808c31b6477290a714d356e822", 506 | "shasum": "" 507 | }, 508 | "require": { 509 | "php": ">=5.6" 510 | }, 511 | "require-dev": { 512 | "php-coveralls/php-coveralls": "^2.1", 513 | "phpunit/phpunit": "^5 || ^6.5" 514 | }, 515 | "type": "library", 516 | "autoload": { 517 | "files": [ 518 | "src/getallheaders.php" 519 | ] 520 | }, 521 | "notification-url": "https://packagist.org/downloads/", 522 | "license": [ 523 | "MIT" 524 | ], 525 | "authors": [ 526 | { 527 | "name": "Ralph Khattar", 528 | "email": "ralph.khattar@gmail.com" 529 | } 530 | ], 531 | "description": "A polyfill for getallheaders.", 532 | "support": { 533 | "issues": "https://github.com/ralouphie/getallheaders/issues", 534 | "source": "https://github.com/ralouphie/getallheaders/tree/develop" 535 | }, 536 | "time": "2019-03-08T08:55:37+00:00" 537 | }, 538 | { 539 | "name": "symfony/deprecation-contracts", 540 | "version": "v3.4.0", 541 | "source": { 542 | "type": "git", 543 | "url": "https://github.com/symfony/deprecation-contracts.git", 544 | "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" 545 | }, 546 | "dist": { 547 | "type": "zip", 548 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", 549 | "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", 550 | "shasum": "" 551 | }, 552 | "require": { 553 | "php": ">=8.1" 554 | }, 555 | "type": "library", 556 | "extra": { 557 | "branch-alias": { 558 | "dev-main": "3.4-dev" 559 | }, 560 | "thanks": { 561 | "name": "symfony/contracts", 562 | "url": "https://github.com/symfony/contracts" 563 | } 564 | }, 565 | "autoload": { 566 | "files": [ 567 | "function.php" 568 | ] 569 | }, 570 | "notification-url": "https://packagist.org/downloads/", 571 | "license": [ 572 | "MIT" 573 | ], 574 | "authors": [ 575 | { 576 | "name": "Nicolas Grekas", 577 | "email": "p@tchwork.com" 578 | }, 579 | { 580 | "name": "Symfony Community", 581 | "homepage": "https://symfony.com/contributors" 582 | } 583 | ], 584 | "description": "A generic function and convention to trigger deprecation notices", 585 | "homepage": "https://symfony.com", 586 | "support": { 587 | "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" 588 | }, 589 | "funding": [ 590 | { 591 | "url": "https://symfony.com/sponsor", 592 | "type": "custom" 593 | }, 594 | { 595 | "url": "https://github.com/fabpot", 596 | "type": "github" 597 | }, 598 | { 599 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 600 | "type": "tidelift" 601 | } 602 | ], 603 | "time": "2023-05-23T14:45:45+00:00" 604 | } 605 | ], 606 | "packages-dev": [ 607 | { 608 | "name": "doctrine/instantiator", 609 | "version": "2.0.0", 610 | "source": { 611 | "type": "git", 612 | "url": "https://github.com/doctrine/instantiator.git", 613 | "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" 614 | }, 615 | "dist": { 616 | "type": "zip", 617 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", 618 | "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", 619 | "shasum": "" 620 | }, 621 | "require": { 622 | "php": "^8.1" 623 | }, 624 | "require-dev": { 625 | "doctrine/coding-standard": "^11", 626 | "ext-pdo": "*", 627 | "ext-phar": "*", 628 | "phpbench/phpbench": "^1.2", 629 | "phpstan/phpstan": "^1.9.4", 630 | "phpstan/phpstan-phpunit": "^1.3", 631 | "phpunit/phpunit": "^9.5.27", 632 | "vimeo/psalm": "^5.4" 633 | }, 634 | "type": "library", 635 | "autoload": { 636 | "psr-4": { 637 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 638 | } 639 | }, 640 | "notification-url": "https://packagist.org/downloads/", 641 | "license": [ 642 | "MIT" 643 | ], 644 | "authors": [ 645 | { 646 | "name": "Marco Pivetta", 647 | "email": "ocramius@gmail.com", 648 | "homepage": "https://ocramius.github.io/" 649 | } 650 | ], 651 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 652 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 653 | "keywords": [ 654 | "constructor", 655 | "instantiate" 656 | ], 657 | "support": { 658 | "issues": "https://github.com/doctrine/instantiator/issues", 659 | "source": "https://github.com/doctrine/instantiator/tree/2.0.0" 660 | }, 661 | "funding": [ 662 | { 663 | "url": "https://www.doctrine-project.org/sponsorship.html", 664 | "type": "custom" 665 | }, 666 | { 667 | "url": "https://www.patreon.com/phpdoctrine", 668 | "type": "patreon" 669 | }, 670 | { 671 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 672 | "type": "tidelift" 673 | } 674 | ], 675 | "time": "2022-12-30T00:23:10+00:00" 676 | }, 677 | { 678 | "name": "myclabs/deep-copy", 679 | "version": "1.11.1", 680 | "source": { 681 | "type": "git", 682 | "url": "https://github.com/myclabs/DeepCopy.git", 683 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" 684 | }, 685 | "dist": { 686 | "type": "zip", 687 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", 688 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", 689 | "shasum": "" 690 | }, 691 | "require": { 692 | "php": "^7.1 || ^8.0" 693 | }, 694 | "conflict": { 695 | "doctrine/collections": "<1.6.8", 696 | "doctrine/common": "<2.13.3 || >=3,<3.2.2" 697 | }, 698 | "require-dev": { 699 | "doctrine/collections": "^1.6.8", 700 | "doctrine/common": "^2.13.3 || ^3.2.2", 701 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 702 | }, 703 | "type": "library", 704 | "autoload": { 705 | "files": [ 706 | "src/DeepCopy/deep_copy.php" 707 | ], 708 | "psr-4": { 709 | "DeepCopy\\": "src/DeepCopy/" 710 | } 711 | }, 712 | "notification-url": "https://packagist.org/downloads/", 713 | "license": [ 714 | "MIT" 715 | ], 716 | "description": "Create deep copies (clones) of your objects", 717 | "keywords": [ 718 | "clone", 719 | "copy", 720 | "duplicate", 721 | "object", 722 | "object graph" 723 | ], 724 | "support": { 725 | "issues": "https://github.com/myclabs/DeepCopy/issues", 726 | "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" 727 | }, 728 | "funding": [ 729 | { 730 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 731 | "type": "tidelift" 732 | } 733 | ], 734 | "time": "2023-03-08T13:26:56+00:00" 735 | }, 736 | { 737 | "name": "nikic/php-parser", 738 | "version": "v4.18.0", 739 | "source": { 740 | "type": "git", 741 | "url": "https://github.com/nikic/PHP-Parser.git", 742 | "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" 743 | }, 744 | "dist": { 745 | "type": "zip", 746 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", 747 | "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", 748 | "shasum": "" 749 | }, 750 | "require": { 751 | "ext-tokenizer": "*", 752 | "php": ">=7.0" 753 | }, 754 | "require-dev": { 755 | "ircmaxell/php-yacc": "^0.0.7", 756 | "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" 757 | }, 758 | "bin": [ 759 | "bin/php-parse" 760 | ], 761 | "type": "library", 762 | "extra": { 763 | "branch-alias": { 764 | "dev-master": "4.9-dev" 765 | } 766 | }, 767 | "autoload": { 768 | "psr-4": { 769 | "PhpParser\\": "lib/PhpParser" 770 | } 771 | }, 772 | "notification-url": "https://packagist.org/downloads/", 773 | "license": [ 774 | "BSD-3-Clause" 775 | ], 776 | "authors": [ 777 | { 778 | "name": "Nikita Popov" 779 | } 780 | ], 781 | "description": "A PHP parser written in PHP", 782 | "keywords": [ 783 | "parser", 784 | "php" 785 | ], 786 | "support": { 787 | "issues": "https://github.com/nikic/PHP-Parser/issues", 788 | "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" 789 | }, 790 | "time": "2023-12-10T21:03:43+00:00" 791 | }, 792 | { 793 | "name": "phar-io/manifest", 794 | "version": "2.0.3", 795 | "source": { 796 | "type": "git", 797 | "url": "https://github.com/phar-io/manifest.git", 798 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53" 799 | }, 800 | "dist": { 801 | "type": "zip", 802 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", 803 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53", 804 | "shasum": "" 805 | }, 806 | "require": { 807 | "ext-dom": "*", 808 | "ext-phar": "*", 809 | "ext-xmlwriter": "*", 810 | "phar-io/version": "^3.0.1", 811 | "php": "^7.2 || ^8.0" 812 | }, 813 | "type": "library", 814 | "extra": { 815 | "branch-alias": { 816 | "dev-master": "2.0.x-dev" 817 | } 818 | }, 819 | "autoload": { 820 | "classmap": [ 821 | "src/" 822 | ] 823 | }, 824 | "notification-url": "https://packagist.org/downloads/", 825 | "license": [ 826 | "BSD-3-Clause" 827 | ], 828 | "authors": [ 829 | { 830 | "name": "Arne Blankerts", 831 | "email": "arne@blankerts.de", 832 | "role": "Developer" 833 | }, 834 | { 835 | "name": "Sebastian Heuer", 836 | "email": "sebastian@phpeople.de", 837 | "role": "Developer" 838 | }, 839 | { 840 | "name": "Sebastian Bergmann", 841 | "email": "sebastian@phpunit.de", 842 | "role": "Developer" 843 | } 844 | ], 845 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 846 | "support": { 847 | "issues": "https://github.com/phar-io/manifest/issues", 848 | "source": "https://github.com/phar-io/manifest/tree/2.0.3" 849 | }, 850 | "time": "2021-07-20T11:28:43+00:00" 851 | }, 852 | { 853 | "name": "phar-io/version", 854 | "version": "3.2.1", 855 | "source": { 856 | "type": "git", 857 | "url": "https://github.com/phar-io/version.git", 858 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 859 | }, 860 | "dist": { 861 | "type": "zip", 862 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 863 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 864 | "shasum": "" 865 | }, 866 | "require": { 867 | "php": "^7.2 || ^8.0" 868 | }, 869 | "type": "library", 870 | "autoload": { 871 | "classmap": [ 872 | "src/" 873 | ] 874 | }, 875 | "notification-url": "https://packagist.org/downloads/", 876 | "license": [ 877 | "BSD-3-Clause" 878 | ], 879 | "authors": [ 880 | { 881 | "name": "Arne Blankerts", 882 | "email": "arne@blankerts.de", 883 | "role": "Developer" 884 | }, 885 | { 886 | "name": "Sebastian Heuer", 887 | "email": "sebastian@phpeople.de", 888 | "role": "Developer" 889 | }, 890 | { 891 | "name": "Sebastian Bergmann", 892 | "email": "sebastian@phpunit.de", 893 | "role": "Developer" 894 | } 895 | ], 896 | "description": "Library for handling version information and constraints", 897 | "support": { 898 | "issues": "https://github.com/phar-io/version/issues", 899 | "source": "https://github.com/phar-io/version/tree/3.2.1" 900 | }, 901 | "time": "2022-02-21T01:04:05+00:00" 902 | }, 903 | { 904 | "name": "phpunit/php-code-coverage", 905 | "version": "9.2.29", 906 | "source": { 907 | "type": "git", 908 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 909 | "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" 910 | }, 911 | "dist": { 912 | "type": "zip", 913 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", 914 | "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", 915 | "shasum": "" 916 | }, 917 | "require": { 918 | "ext-dom": "*", 919 | "ext-libxml": "*", 920 | "ext-xmlwriter": "*", 921 | "nikic/php-parser": "^4.15", 922 | "php": ">=7.3", 923 | "phpunit/php-file-iterator": "^3.0.3", 924 | "phpunit/php-text-template": "^2.0.2", 925 | "sebastian/code-unit-reverse-lookup": "^2.0.2", 926 | "sebastian/complexity": "^2.0", 927 | "sebastian/environment": "^5.1.2", 928 | "sebastian/lines-of-code": "^1.0.3", 929 | "sebastian/version": "^3.0.1", 930 | "theseer/tokenizer": "^1.2.0" 931 | }, 932 | "require-dev": { 933 | "phpunit/phpunit": "^9.3" 934 | }, 935 | "suggest": { 936 | "ext-pcov": "PHP extension that provides line coverage", 937 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 938 | }, 939 | "type": "library", 940 | "extra": { 941 | "branch-alias": { 942 | "dev-master": "9.2-dev" 943 | } 944 | }, 945 | "autoload": { 946 | "classmap": [ 947 | "src/" 948 | ] 949 | }, 950 | "notification-url": "https://packagist.org/downloads/", 951 | "license": [ 952 | "BSD-3-Clause" 953 | ], 954 | "authors": [ 955 | { 956 | "name": "Sebastian Bergmann", 957 | "email": "sebastian@phpunit.de", 958 | "role": "lead" 959 | } 960 | ], 961 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 962 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 963 | "keywords": [ 964 | "coverage", 965 | "testing", 966 | "xunit" 967 | ], 968 | "support": { 969 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 970 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", 971 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" 972 | }, 973 | "funding": [ 974 | { 975 | "url": "https://github.com/sebastianbergmann", 976 | "type": "github" 977 | } 978 | ], 979 | "time": "2023-09-19T04:57:46+00:00" 980 | }, 981 | { 982 | "name": "phpunit/php-file-iterator", 983 | "version": "3.0.6", 984 | "source": { 985 | "type": "git", 986 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 987 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" 988 | }, 989 | "dist": { 990 | "type": "zip", 991 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 992 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 993 | "shasum": "" 994 | }, 995 | "require": { 996 | "php": ">=7.3" 997 | }, 998 | "require-dev": { 999 | "phpunit/phpunit": "^9.3" 1000 | }, 1001 | "type": "library", 1002 | "extra": { 1003 | "branch-alias": { 1004 | "dev-master": "3.0-dev" 1005 | } 1006 | }, 1007 | "autoload": { 1008 | "classmap": [ 1009 | "src/" 1010 | ] 1011 | }, 1012 | "notification-url": "https://packagist.org/downloads/", 1013 | "license": [ 1014 | "BSD-3-Clause" 1015 | ], 1016 | "authors": [ 1017 | { 1018 | "name": "Sebastian Bergmann", 1019 | "email": "sebastian@phpunit.de", 1020 | "role": "lead" 1021 | } 1022 | ], 1023 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1024 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1025 | "keywords": [ 1026 | "filesystem", 1027 | "iterator" 1028 | ], 1029 | "support": { 1030 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 1031 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" 1032 | }, 1033 | "funding": [ 1034 | { 1035 | "url": "https://github.com/sebastianbergmann", 1036 | "type": "github" 1037 | } 1038 | ], 1039 | "time": "2021-12-02T12:48:52+00:00" 1040 | }, 1041 | { 1042 | "name": "phpunit/php-invoker", 1043 | "version": "3.1.1", 1044 | "source": { 1045 | "type": "git", 1046 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 1047 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" 1048 | }, 1049 | "dist": { 1050 | "type": "zip", 1051 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 1052 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 1053 | "shasum": "" 1054 | }, 1055 | "require": { 1056 | "php": ">=7.3" 1057 | }, 1058 | "require-dev": { 1059 | "ext-pcntl": "*", 1060 | "phpunit/phpunit": "^9.3" 1061 | }, 1062 | "suggest": { 1063 | "ext-pcntl": "*" 1064 | }, 1065 | "type": "library", 1066 | "extra": { 1067 | "branch-alias": { 1068 | "dev-master": "3.1-dev" 1069 | } 1070 | }, 1071 | "autoload": { 1072 | "classmap": [ 1073 | "src/" 1074 | ] 1075 | }, 1076 | "notification-url": "https://packagist.org/downloads/", 1077 | "license": [ 1078 | "BSD-3-Clause" 1079 | ], 1080 | "authors": [ 1081 | { 1082 | "name": "Sebastian Bergmann", 1083 | "email": "sebastian@phpunit.de", 1084 | "role": "lead" 1085 | } 1086 | ], 1087 | "description": "Invoke callables with a timeout", 1088 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 1089 | "keywords": [ 1090 | "process" 1091 | ], 1092 | "support": { 1093 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 1094 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" 1095 | }, 1096 | "funding": [ 1097 | { 1098 | "url": "https://github.com/sebastianbergmann", 1099 | "type": "github" 1100 | } 1101 | ], 1102 | "time": "2020-09-28T05:58:55+00:00" 1103 | }, 1104 | { 1105 | "name": "phpunit/php-text-template", 1106 | "version": "2.0.4", 1107 | "source": { 1108 | "type": "git", 1109 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1110 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" 1111 | }, 1112 | "dist": { 1113 | "type": "zip", 1114 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 1115 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 1116 | "shasum": "" 1117 | }, 1118 | "require": { 1119 | "php": ">=7.3" 1120 | }, 1121 | "require-dev": { 1122 | "phpunit/phpunit": "^9.3" 1123 | }, 1124 | "type": "library", 1125 | "extra": { 1126 | "branch-alias": { 1127 | "dev-master": "2.0-dev" 1128 | } 1129 | }, 1130 | "autoload": { 1131 | "classmap": [ 1132 | "src/" 1133 | ] 1134 | }, 1135 | "notification-url": "https://packagist.org/downloads/", 1136 | "license": [ 1137 | "BSD-3-Clause" 1138 | ], 1139 | "authors": [ 1140 | { 1141 | "name": "Sebastian Bergmann", 1142 | "email": "sebastian@phpunit.de", 1143 | "role": "lead" 1144 | } 1145 | ], 1146 | "description": "Simple template engine.", 1147 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1148 | "keywords": [ 1149 | "template" 1150 | ], 1151 | "support": { 1152 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 1153 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" 1154 | }, 1155 | "funding": [ 1156 | { 1157 | "url": "https://github.com/sebastianbergmann", 1158 | "type": "github" 1159 | } 1160 | ], 1161 | "time": "2020-10-26T05:33:50+00:00" 1162 | }, 1163 | { 1164 | "name": "phpunit/php-timer", 1165 | "version": "5.0.3", 1166 | "source": { 1167 | "type": "git", 1168 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1169 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" 1170 | }, 1171 | "dist": { 1172 | "type": "zip", 1173 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 1174 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 1175 | "shasum": "" 1176 | }, 1177 | "require": { 1178 | "php": ">=7.3" 1179 | }, 1180 | "require-dev": { 1181 | "phpunit/phpunit": "^9.3" 1182 | }, 1183 | "type": "library", 1184 | "extra": { 1185 | "branch-alias": { 1186 | "dev-master": "5.0-dev" 1187 | } 1188 | }, 1189 | "autoload": { 1190 | "classmap": [ 1191 | "src/" 1192 | ] 1193 | }, 1194 | "notification-url": "https://packagist.org/downloads/", 1195 | "license": [ 1196 | "BSD-3-Clause" 1197 | ], 1198 | "authors": [ 1199 | { 1200 | "name": "Sebastian Bergmann", 1201 | "email": "sebastian@phpunit.de", 1202 | "role": "lead" 1203 | } 1204 | ], 1205 | "description": "Utility class for timing", 1206 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1207 | "keywords": [ 1208 | "timer" 1209 | ], 1210 | "support": { 1211 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 1212 | "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" 1213 | }, 1214 | "funding": [ 1215 | { 1216 | "url": "https://github.com/sebastianbergmann", 1217 | "type": "github" 1218 | } 1219 | ], 1220 | "time": "2020-10-26T13:16:10+00:00" 1221 | }, 1222 | { 1223 | "name": "phpunit/phpunit", 1224 | "version": "9.6.15", 1225 | "source": { 1226 | "type": "git", 1227 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1228 | "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" 1229 | }, 1230 | "dist": { 1231 | "type": "zip", 1232 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", 1233 | "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", 1234 | "shasum": "" 1235 | }, 1236 | "require": { 1237 | "doctrine/instantiator": "^1.3.1 || ^2", 1238 | "ext-dom": "*", 1239 | "ext-json": "*", 1240 | "ext-libxml": "*", 1241 | "ext-mbstring": "*", 1242 | "ext-xml": "*", 1243 | "ext-xmlwriter": "*", 1244 | "myclabs/deep-copy": "^1.10.1", 1245 | "phar-io/manifest": "^2.0.3", 1246 | "phar-io/version": "^3.0.2", 1247 | "php": ">=7.3", 1248 | "phpunit/php-code-coverage": "^9.2.28", 1249 | "phpunit/php-file-iterator": "^3.0.5", 1250 | "phpunit/php-invoker": "^3.1.1", 1251 | "phpunit/php-text-template": "^2.0.3", 1252 | "phpunit/php-timer": "^5.0.2", 1253 | "sebastian/cli-parser": "^1.0.1", 1254 | "sebastian/code-unit": "^1.0.6", 1255 | "sebastian/comparator": "^4.0.8", 1256 | "sebastian/diff": "^4.0.3", 1257 | "sebastian/environment": "^5.1.3", 1258 | "sebastian/exporter": "^4.0.5", 1259 | "sebastian/global-state": "^5.0.1", 1260 | "sebastian/object-enumerator": "^4.0.3", 1261 | "sebastian/resource-operations": "^3.0.3", 1262 | "sebastian/type": "^3.2", 1263 | "sebastian/version": "^3.0.2" 1264 | }, 1265 | "suggest": { 1266 | "ext-soap": "To be able to generate mocks based on WSDL files", 1267 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 1268 | }, 1269 | "bin": [ 1270 | "phpunit" 1271 | ], 1272 | "type": "library", 1273 | "extra": { 1274 | "branch-alias": { 1275 | "dev-master": "9.6-dev" 1276 | } 1277 | }, 1278 | "autoload": { 1279 | "files": [ 1280 | "src/Framework/Assert/Functions.php" 1281 | ], 1282 | "classmap": [ 1283 | "src/" 1284 | ] 1285 | }, 1286 | "notification-url": "https://packagist.org/downloads/", 1287 | "license": [ 1288 | "BSD-3-Clause" 1289 | ], 1290 | "authors": [ 1291 | { 1292 | "name": "Sebastian Bergmann", 1293 | "email": "sebastian@phpunit.de", 1294 | "role": "lead" 1295 | } 1296 | ], 1297 | "description": "The PHP Unit Testing framework.", 1298 | "homepage": "https://phpunit.de/", 1299 | "keywords": [ 1300 | "phpunit", 1301 | "testing", 1302 | "xunit" 1303 | ], 1304 | "support": { 1305 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 1306 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy", 1307 | "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15" 1308 | }, 1309 | "funding": [ 1310 | { 1311 | "url": "https://phpunit.de/sponsors.html", 1312 | "type": "custom" 1313 | }, 1314 | { 1315 | "url": "https://github.com/sebastianbergmann", 1316 | "type": "github" 1317 | }, 1318 | { 1319 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 1320 | "type": "tidelift" 1321 | } 1322 | ], 1323 | "time": "2023-12-01T16:55:19+00:00" 1324 | }, 1325 | { 1326 | "name": "sebastian/cli-parser", 1327 | "version": "1.0.1", 1328 | "source": { 1329 | "type": "git", 1330 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 1331 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" 1332 | }, 1333 | "dist": { 1334 | "type": "zip", 1335 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", 1336 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", 1337 | "shasum": "" 1338 | }, 1339 | "require": { 1340 | "php": ">=7.3" 1341 | }, 1342 | "require-dev": { 1343 | "phpunit/phpunit": "^9.3" 1344 | }, 1345 | "type": "library", 1346 | "extra": { 1347 | "branch-alias": { 1348 | "dev-master": "1.0-dev" 1349 | } 1350 | }, 1351 | "autoload": { 1352 | "classmap": [ 1353 | "src/" 1354 | ] 1355 | }, 1356 | "notification-url": "https://packagist.org/downloads/", 1357 | "license": [ 1358 | "BSD-3-Clause" 1359 | ], 1360 | "authors": [ 1361 | { 1362 | "name": "Sebastian Bergmann", 1363 | "email": "sebastian@phpunit.de", 1364 | "role": "lead" 1365 | } 1366 | ], 1367 | "description": "Library for parsing CLI options", 1368 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 1369 | "support": { 1370 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 1371 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" 1372 | }, 1373 | "funding": [ 1374 | { 1375 | "url": "https://github.com/sebastianbergmann", 1376 | "type": "github" 1377 | } 1378 | ], 1379 | "time": "2020-09-28T06:08:49+00:00" 1380 | }, 1381 | { 1382 | "name": "sebastian/code-unit", 1383 | "version": "1.0.8", 1384 | "source": { 1385 | "type": "git", 1386 | "url": "https://github.com/sebastianbergmann/code-unit.git", 1387 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" 1388 | }, 1389 | "dist": { 1390 | "type": "zip", 1391 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", 1392 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", 1393 | "shasum": "" 1394 | }, 1395 | "require": { 1396 | "php": ">=7.3" 1397 | }, 1398 | "require-dev": { 1399 | "phpunit/phpunit": "^9.3" 1400 | }, 1401 | "type": "library", 1402 | "extra": { 1403 | "branch-alias": { 1404 | "dev-master": "1.0-dev" 1405 | } 1406 | }, 1407 | "autoload": { 1408 | "classmap": [ 1409 | "src/" 1410 | ] 1411 | }, 1412 | "notification-url": "https://packagist.org/downloads/", 1413 | "license": [ 1414 | "BSD-3-Clause" 1415 | ], 1416 | "authors": [ 1417 | { 1418 | "name": "Sebastian Bergmann", 1419 | "email": "sebastian@phpunit.de", 1420 | "role": "lead" 1421 | } 1422 | ], 1423 | "description": "Collection of value objects that represent the PHP code units", 1424 | "homepage": "https://github.com/sebastianbergmann/code-unit", 1425 | "support": { 1426 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 1427 | "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" 1428 | }, 1429 | "funding": [ 1430 | { 1431 | "url": "https://github.com/sebastianbergmann", 1432 | "type": "github" 1433 | } 1434 | ], 1435 | "time": "2020-10-26T13:08:54+00:00" 1436 | }, 1437 | { 1438 | "name": "sebastian/code-unit-reverse-lookup", 1439 | "version": "2.0.3", 1440 | "source": { 1441 | "type": "git", 1442 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1443 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" 1444 | }, 1445 | "dist": { 1446 | "type": "zip", 1447 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1448 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1449 | "shasum": "" 1450 | }, 1451 | "require": { 1452 | "php": ">=7.3" 1453 | }, 1454 | "require-dev": { 1455 | "phpunit/phpunit": "^9.3" 1456 | }, 1457 | "type": "library", 1458 | "extra": { 1459 | "branch-alias": { 1460 | "dev-master": "2.0-dev" 1461 | } 1462 | }, 1463 | "autoload": { 1464 | "classmap": [ 1465 | "src/" 1466 | ] 1467 | }, 1468 | "notification-url": "https://packagist.org/downloads/", 1469 | "license": [ 1470 | "BSD-3-Clause" 1471 | ], 1472 | "authors": [ 1473 | { 1474 | "name": "Sebastian Bergmann", 1475 | "email": "sebastian@phpunit.de" 1476 | } 1477 | ], 1478 | "description": "Looks up which function or method a line of code belongs to", 1479 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1480 | "support": { 1481 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 1482 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" 1483 | }, 1484 | "funding": [ 1485 | { 1486 | "url": "https://github.com/sebastianbergmann", 1487 | "type": "github" 1488 | } 1489 | ], 1490 | "time": "2020-09-28T05:30:19+00:00" 1491 | }, 1492 | { 1493 | "name": "sebastian/comparator", 1494 | "version": "4.0.8", 1495 | "source": { 1496 | "type": "git", 1497 | "url": "https://github.com/sebastianbergmann/comparator.git", 1498 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a" 1499 | }, 1500 | "dist": { 1501 | "type": "zip", 1502 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", 1503 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a", 1504 | "shasum": "" 1505 | }, 1506 | "require": { 1507 | "php": ">=7.3", 1508 | "sebastian/diff": "^4.0", 1509 | "sebastian/exporter": "^4.0" 1510 | }, 1511 | "require-dev": { 1512 | "phpunit/phpunit": "^9.3" 1513 | }, 1514 | "type": "library", 1515 | "extra": { 1516 | "branch-alias": { 1517 | "dev-master": "4.0-dev" 1518 | } 1519 | }, 1520 | "autoload": { 1521 | "classmap": [ 1522 | "src/" 1523 | ] 1524 | }, 1525 | "notification-url": "https://packagist.org/downloads/", 1526 | "license": [ 1527 | "BSD-3-Clause" 1528 | ], 1529 | "authors": [ 1530 | { 1531 | "name": "Sebastian Bergmann", 1532 | "email": "sebastian@phpunit.de" 1533 | }, 1534 | { 1535 | "name": "Jeff Welch", 1536 | "email": "whatthejeff@gmail.com" 1537 | }, 1538 | { 1539 | "name": "Volker Dusch", 1540 | "email": "github@wallbash.com" 1541 | }, 1542 | { 1543 | "name": "Bernhard Schussek", 1544 | "email": "bschussek@2bepublished.at" 1545 | } 1546 | ], 1547 | "description": "Provides the functionality to compare PHP values for equality", 1548 | "homepage": "https://github.com/sebastianbergmann/comparator", 1549 | "keywords": [ 1550 | "comparator", 1551 | "compare", 1552 | "equality" 1553 | ], 1554 | "support": { 1555 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 1556 | "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" 1557 | }, 1558 | "funding": [ 1559 | { 1560 | "url": "https://github.com/sebastianbergmann", 1561 | "type": "github" 1562 | } 1563 | ], 1564 | "time": "2022-09-14T12:41:17+00:00" 1565 | }, 1566 | { 1567 | "name": "sebastian/complexity", 1568 | "version": "2.0.2", 1569 | "source": { 1570 | "type": "git", 1571 | "url": "https://github.com/sebastianbergmann/complexity.git", 1572 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" 1573 | }, 1574 | "dist": { 1575 | "type": "zip", 1576 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", 1577 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", 1578 | "shasum": "" 1579 | }, 1580 | "require": { 1581 | "nikic/php-parser": "^4.7", 1582 | "php": ">=7.3" 1583 | }, 1584 | "require-dev": { 1585 | "phpunit/phpunit": "^9.3" 1586 | }, 1587 | "type": "library", 1588 | "extra": { 1589 | "branch-alias": { 1590 | "dev-master": "2.0-dev" 1591 | } 1592 | }, 1593 | "autoload": { 1594 | "classmap": [ 1595 | "src/" 1596 | ] 1597 | }, 1598 | "notification-url": "https://packagist.org/downloads/", 1599 | "license": [ 1600 | "BSD-3-Clause" 1601 | ], 1602 | "authors": [ 1603 | { 1604 | "name": "Sebastian Bergmann", 1605 | "email": "sebastian@phpunit.de", 1606 | "role": "lead" 1607 | } 1608 | ], 1609 | "description": "Library for calculating the complexity of PHP code units", 1610 | "homepage": "https://github.com/sebastianbergmann/complexity", 1611 | "support": { 1612 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 1613 | "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" 1614 | }, 1615 | "funding": [ 1616 | { 1617 | "url": "https://github.com/sebastianbergmann", 1618 | "type": "github" 1619 | } 1620 | ], 1621 | "time": "2020-10-26T15:52:27+00:00" 1622 | }, 1623 | { 1624 | "name": "sebastian/diff", 1625 | "version": "4.0.5", 1626 | "source": { 1627 | "type": "git", 1628 | "url": "https://github.com/sebastianbergmann/diff.git", 1629 | "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" 1630 | }, 1631 | "dist": { 1632 | "type": "zip", 1633 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", 1634 | "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", 1635 | "shasum": "" 1636 | }, 1637 | "require": { 1638 | "php": ">=7.3" 1639 | }, 1640 | "require-dev": { 1641 | "phpunit/phpunit": "^9.3", 1642 | "symfony/process": "^4.2 || ^5" 1643 | }, 1644 | "type": "library", 1645 | "extra": { 1646 | "branch-alias": { 1647 | "dev-master": "4.0-dev" 1648 | } 1649 | }, 1650 | "autoload": { 1651 | "classmap": [ 1652 | "src/" 1653 | ] 1654 | }, 1655 | "notification-url": "https://packagist.org/downloads/", 1656 | "license": [ 1657 | "BSD-3-Clause" 1658 | ], 1659 | "authors": [ 1660 | { 1661 | "name": "Sebastian Bergmann", 1662 | "email": "sebastian@phpunit.de" 1663 | }, 1664 | { 1665 | "name": "Kore Nordmann", 1666 | "email": "mail@kore-nordmann.de" 1667 | } 1668 | ], 1669 | "description": "Diff implementation", 1670 | "homepage": "https://github.com/sebastianbergmann/diff", 1671 | "keywords": [ 1672 | "diff", 1673 | "udiff", 1674 | "unidiff", 1675 | "unified diff" 1676 | ], 1677 | "support": { 1678 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1679 | "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" 1680 | }, 1681 | "funding": [ 1682 | { 1683 | "url": "https://github.com/sebastianbergmann", 1684 | "type": "github" 1685 | } 1686 | ], 1687 | "time": "2023-05-07T05:35:17+00:00" 1688 | }, 1689 | { 1690 | "name": "sebastian/environment", 1691 | "version": "5.1.5", 1692 | "source": { 1693 | "type": "git", 1694 | "url": "https://github.com/sebastianbergmann/environment.git", 1695 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" 1696 | }, 1697 | "dist": { 1698 | "type": "zip", 1699 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1700 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1701 | "shasum": "" 1702 | }, 1703 | "require": { 1704 | "php": ">=7.3" 1705 | }, 1706 | "require-dev": { 1707 | "phpunit/phpunit": "^9.3" 1708 | }, 1709 | "suggest": { 1710 | "ext-posix": "*" 1711 | }, 1712 | "type": "library", 1713 | "extra": { 1714 | "branch-alias": { 1715 | "dev-master": "5.1-dev" 1716 | } 1717 | }, 1718 | "autoload": { 1719 | "classmap": [ 1720 | "src/" 1721 | ] 1722 | }, 1723 | "notification-url": "https://packagist.org/downloads/", 1724 | "license": [ 1725 | "BSD-3-Clause" 1726 | ], 1727 | "authors": [ 1728 | { 1729 | "name": "Sebastian Bergmann", 1730 | "email": "sebastian@phpunit.de" 1731 | } 1732 | ], 1733 | "description": "Provides functionality to handle HHVM/PHP environments", 1734 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1735 | "keywords": [ 1736 | "Xdebug", 1737 | "environment", 1738 | "hhvm" 1739 | ], 1740 | "support": { 1741 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1742 | "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" 1743 | }, 1744 | "funding": [ 1745 | { 1746 | "url": "https://github.com/sebastianbergmann", 1747 | "type": "github" 1748 | } 1749 | ], 1750 | "time": "2023-02-03T06:03:51+00:00" 1751 | }, 1752 | { 1753 | "name": "sebastian/exporter", 1754 | "version": "4.0.5", 1755 | "source": { 1756 | "type": "git", 1757 | "url": "https://github.com/sebastianbergmann/exporter.git", 1758 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" 1759 | }, 1760 | "dist": { 1761 | "type": "zip", 1762 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", 1763 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", 1764 | "shasum": "" 1765 | }, 1766 | "require": { 1767 | "php": ">=7.3", 1768 | "sebastian/recursion-context": "^4.0" 1769 | }, 1770 | "require-dev": { 1771 | "ext-mbstring": "*", 1772 | "phpunit/phpunit": "^9.3" 1773 | }, 1774 | "type": "library", 1775 | "extra": { 1776 | "branch-alias": { 1777 | "dev-master": "4.0-dev" 1778 | } 1779 | }, 1780 | "autoload": { 1781 | "classmap": [ 1782 | "src/" 1783 | ] 1784 | }, 1785 | "notification-url": "https://packagist.org/downloads/", 1786 | "license": [ 1787 | "BSD-3-Clause" 1788 | ], 1789 | "authors": [ 1790 | { 1791 | "name": "Sebastian Bergmann", 1792 | "email": "sebastian@phpunit.de" 1793 | }, 1794 | { 1795 | "name": "Jeff Welch", 1796 | "email": "whatthejeff@gmail.com" 1797 | }, 1798 | { 1799 | "name": "Volker Dusch", 1800 | "email": "github@wallbash.com" 1801 | }, 1802 | { 1803 | "name": "Adam Harvey", 1804 | "email": "aharvey@php.net" 1805 | }, 1806 | { 1807 | "name": "Bernhard Schussek", 1808 | "email": "bschussek@gmail.com" 1809 | } 1810 | ], 1811 | "description": "Provides the functionality to export PHP variables for visualization", 1812 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 1813 | "keywords": [ 1814 | "export", 1815 | "exporter" 1816 | ], 1817 | "support": { 1818 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1819 | "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" 1820 | }, 1821 | "funding": [ 1822 | { 1823 | "url": "https://github.com/sebastianbergmann", 1824 | "type": "github" 1825 | } 1826 | ], 1827 | "time": "2022-09-14T06:03:37+00:00" 1828 | }, 1829 | { 1830 | "name": "sebastian/global-state", 1831 | "version": "5.0.6", 1832 | "source": { 1833 | "type": "git", 1834 | "url": "https://github.com/sebastianbergmann/global-state.git", 1835 | "reference": "bde739e7565280bda77be70044ac1047bc007e34" 1836 | }, 1837 | "dist": { 1838 | "type": "zip", 1839 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", 1840 | "reference": "bde739e7565280bda77be70044ac1047bc007e34", 1841 | "shasum": "" 1842 | }, 1843 | "require": { 1844 | "php": ">=7.3", 1845 | "sebastian/object-reflector": "^2.0", 1846 | "sebastian/recursion-context": "^4.0" 1847 | }, 1848 | "require-dev": { 1849 | "ext-dom": "*", 1850 | "phpunit/phpunit": "^9.3" 1851 | }, 1852 | "suggest": { 1853 | "ext-uopz": "*" 1854 | }, 1855 | "type": "library", 1856 | "extra": { 1857 | "branch-alias": { 1858 | "dev-master": "5.0-dev" 1859 | } 1860 | }, 1861 | "autoload": { 1862 | "classmap": [ 1863 | "src/" 1864 | ] 1865 | }, 1866 | "notification-url": "https://packagist.org/downloads/", 1867 | "license": [ 1868 | "BSD-3-Clause" 1869 | ], 1870 | "authors": [ 1871 | { 1872 | "name": "Sebastian Bergmann", 1873 | "email": "sebastian@phpunit.de" 1874 | } 1875 | ], 1876 | "description": "Snapshotting of global state", 1877 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1878 | "keywords": [ 1879 | "global state" 1880 | ], 1881 | "support": { 1882 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1883 | "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" 1884 | }, 1885 | "funding": [ 1886 | { 1887 | "url": "https://github.com/sebastianbergmann", 1888 | "type": "github" 1889 | } 1890 | ], 1891 | "time": "2023-08-02T09:26:13+00:00" 1892 | }, 1893 | { 1894 | "name": "sebastian/lines-of-code", 1895 | "version": "1.0.3", 1896 | "source": { 1897 | "type": "git", 1898 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 1899 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" 1900 | }, 1901 | "dist": { 1902 | "type": "zip", 1903 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", 1904 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", 1905 | "shasum": "" 1906 | }, 1907 | "require": { 1908 | "nikic/php-parser": "^4.6", 1909 | "php": ">=7.3" 1910 | }, 1911 | "require-dev": { 1912 | "phpunit/phpunit": "^9.3" 1913 | }, 1914 | "type": "library", 1915 | "extra": { 1916 | "branch-alias": { 1917 | "dev-master": "1.0-dev" 1918 | } 1919 | }, 1920 | "autoload": { 1921 | "classmap": [ 1922 | "src/" 1923 | ] 1924 | }, 1925 | "notification-url": "https://packagist.org/downloads/", 1926 | "license": [ 1927 | "BSD-3-Clause" 1928 | ], 1929 | "authors": [ 1930 | { 1931 | "name": "Sebastian Bergmann", 1932 | "email": "sebastian@phpunit.de", 1933 | "role": "lead" 1934 | } 1935 | ], 1936 | "description": "Library for counting the lines of code in PHP source code", 1937 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 1938 | "support": { 1939 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 1940 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" 1941 | }, 1942 | "funding": [ 1943 | { 1944 | "url": "https://github.com/sebastianbergmann", 1945 | "type": "github" 1946 | } 1947 | ], 1948 | "time": "2020-11-28T06:42:11+00:00" 1949 | }, 1950 | { 1951 | "name": "sebastian/object-enumerator", 1952 | "version": "4.0.4", 1953 | "source": { 1954 | "type": "git", 1955 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1956 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" 1957 | }, 1958 | "dist": { 1959 | "type": "zip", 1960 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", 1961 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", 1962 | "shasum": "" 1963 | }, 1964 | "require": { 1965 | "php": ">=7.3", 1966 | "sebastian/object-reflector": "^2.0", 1967 | "sebastian/recursion-context": "^4.0" 1968 | }, 1969 | "require-dev": { 1970 | "phpunit/phpunit": "^9.3" 1971 | }, 1972 | "type": "library", 1973 | "extra": { 1974 | "branch-alias": { 1975 | "dev-master": "4.0-dev" 1976 | } 1977 | }, 1978 | "autoload": { 1979 | "classmap": [ 1980 | "src/" 1981 | ] 1982 | }, 1983 | "notification-url": "https://packagist.org/downloads/", 1984 | "license": [ 1985 | "BSD-3-Clause" 1986 | ], 1987 | "authors": [ 1988 | { 1989 | "name": "Sebastian Bergmann", 1990 | "email": "sebastian@phpunit.de" 1991 | } 1992 | ], 1993 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1994 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1995 | "support": { 1996 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1997 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" 1998 | }, 1999 | "funding": [ 2000 | { 2001 | "url": "https://github.com/sebastianbergmann", 2002 | "type": "github" 2003 | } 2004 | ], 2005 | "time": "2020-10-26T13:12:34+00:00" 2006 | }, 2007 | { 2008 | "name": "sebastian/object-reflector", 2009 | "version": "2.0.4", 2010 | "source": { 2011 | "type": "git", 2012 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 2013 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" 2014 | }, 2015 | "dist": { 2016 | "type": "zip", 2017 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 2018 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 2019 | "shasum": "" 2020 | }, 2021 | "require": { 2022 | "php": ">=7.3" 2023 | }, 2024 | "require-dev": { 2025 | "phpunit/phpunit": "^9.3" 2026 | }, 2027 | "type": "library", 2028 | "extra": { 2029 | "branch-alias": { 2030 | "dev-master": "2.0-dev" 2031 | } 2032 | }, 2033 | "autoload": { 2034 | "classmap": [ 2035 | "src/" 2036 | ] 2037 | }, 2038 | "notification-url": "https://packagist.org/downloads/", 2039 | "license": [ 2040 | "BSD-3-Clause" 2041 | ], 2042 | "authors": [ 2043 | { 2044 | "name": "Sebastian Bergmann", 2045 | "email": "sebastian@phpunit.de" 2046 | } 2047 | ], 2048 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 2049 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 2050 | "support": { 2051 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 2052 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" 2053 | }, 2054 | "funding": [ 2055 | { 2056 | "url": "https://github.com/sebastianbergmann", 2057 | "type": "github" 2058 | } 2059 | ], 2060 | "time": "2020-10-26T13:14:26+00:00" 2061 | }, 2062 | { 2063 | "name": "sebastian/recursion-context", 2064 | "version": "4.0.5", 2065 | "source": { 2066 | "type": "git", 2067 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 2068 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" 2069 | }, 2070 | "dist": { 2071 | "type": "zip", 2072 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 2073 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 2074 | "shasum": "" 2075 | }, 2076 | "require": { 2077 | "php": ">=7.3" 2078 | }, 2079 | "require-dev": { 2080 | "phpunit/phpunit": "^9.3" 2081 | }, 2082 | "type": "library", 2083 | "extra": { 2084 | "branch-alias": { 2085 | "dev-master": "4.0-dev" 2086 | } 2087 | }, 2088 | "autoload": { 2089 | "classmap": [ 2090 | "src/" 2091 | ] 2092 | }, 2093 | "notification-url": "https://packagist.org/downloads/", 2094 | "license": [ 2095 | "BSD-3-Clause" 2096 | ], 2097 | "authors": [ 2098 | { 2099 | "name": "Sebastian Bergmann", 2100 | "email": "sebastian@phpunit.de" 2101 | }, 2102 | { 2103 | "name": "Jeff Welch", 2104 | "email": "whatthejeff@gmail.com" 2105 | }, 2106 | { 2107 | "name": "Adam Harvey", 2108 | "email": "aharvey@php.net" 2109 | } 2110 | ], 2111 | "description": "Provides functionality to recursively process PHP variables", 2112 | "homepage": "https://github.com/sebastianbergmann/recursion-context", 2113 | "support": { 2114 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 2115 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" 2116 | }, 2117 | "funding": [ 2118 | { 2119 | "url": "https://github.com/sebastianbergmann", 2120 | "type": "github" 2121 | } 2122 | ], 2123 | "time": "2023-02-03T06:07:39+00:00" 2124 | }, 2125 | { 2126 | "name": "sebastian/resource-operations", 2127 | "version": "3.0.3", 2128 | "source": { 2129 | "type": "git", 2130 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 2131 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" 2132 | }, 2133 | "dist": { 2134 | "type": "zip", 2135 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 2136 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", 2137 | "shasum": "" 2138 | }, 2139 | "require": { 2140 | "php": ">=7.3" 2141 | }, 2142 | "require-dev": { 2143 | "phpunit/phpunit": "^9.0" 2144 | }, 2145 | "type": "library", 2146 | "extra": { 2147 | "branch-alias": { 2148 | "dev-master": "3.0-dev" 2149 | } 2150 | }, 2151 | "autoload": { 2152 | "classmap": [ 2153 | "src/" 2154 | ] 2155 | }, 2156 | "notification-url": "https://packagist.org/downloads/", 2157 | "license": [ 2158 | "BSD-3-Clause" 2159 | ], 2160 | "authors": [ 2161 | { 2162 | "name": "Sebastian Bergmann", 2163 | "email": "sebastian@phpunit.de" 2164 | } 2165 | ], 2166 | "description": "Provides a list of PHP built-in functions that operate on resources", 2167 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 2168 | "support": { 2169 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues", 2170 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" 2171 | }, 2172 | "funding": [ 2173 | { 2174 | "url": "https://github.com/sebastianbergmann", 2175 | "type": "github" 2176 | } 2177 | ], 2178 | "time": "2020-09-28T06:45:17+00:00" 2179 | }, 2180 | { 2181 | "name": "sebastian/type", 2182 | "version": "3.2.1", 2183 | "source": { 2184 | "type": "git", 2185 | "url": "https://github.com/sebastianbergmann/type.git", 2186 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" 2187 | }, 2188 | "dist": { 2189 | "type": "zip", 2190 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 2191 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 2192 | "shasum": "" 2193 | }, 2194 | "require": { 2195 | "php": ">=7.3" 2196 | }, 2197 | "require-dev": { 2198 | "phpunit/phpunit": "^9.5" 2199 | }, 2200 | "type": "library", 2201 | "extra": { 2202 | "branch-alias": { 2203 | "dev-master": "3.2-dev" 2204 | } 2205 | }, 2206 | "autoload": { 2207 | "classmap": [ 2208 | "src/" 2209 | ] 2210 | }, 2211 | "notification-url": "https://packagist.org/downloads/", 2212 | "license": [ 2213 | "BSD-3-Clause" 2214 | ], 2215 | "authors": [ 2216 | { 2217 | "name": "Sebastian Bergmann", 2218 | "email": "sebastian@phpunit.de", 2219 | "role": "lead" 2220 | } 2221 | ], 2222 | "description": "Collection of value objects that represent the types of the PHP type system", 2223 | "homepage": "https://github.com/sebastianbergmann/type", 2224 | "support": { 2225 | "issues": "https://github.com/sebastianbergmann/type/issues", 2226 | "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" 2227 | }, 2228 | "funding": [ 2229 | { 2230 | "url": "https://github.com/sebastianbergmann", 2231 | "type": "github" 2232 | } 2233 | ], 2234 | "time": "2023-02-03T06:13:03+00:00" 2235 | }, 2236 | { 2237 | "name": "sebastian/version", 2238 | "version": "3.0.2", 2239 | "source": { 2240 | "type": "git", 2241 | "url": "https://github.com/sebastianbergmann/version.git", 2242 | "reference": "c6c1022351a901512170118436c764e473f6de8c" 2243 | }, 2244 | "dist": { 2245 | "type": "zip", 2246 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", 2247 | "reference": "c6c1022351a901512170118436c764e473f6de8c", 2248 | "shasum": "" 2249 | }, 2250 | "require": { 2251 | "php": ">=7.3" 2252 | }, 2253 | "type": "library", 2254 | "extra": { 2255 | "branch-alias": { 2256 | "dev-master": "3.0-dev" 2257 | } 2258 | }, 2259 | "autoload": { 2260 | "classmap": [ 2261 | "src/" 2262 | ] 2263 | }, 2264 | "notification-url": "https://packagist.org/downloads/", 2265 | "license": [ 2266 | "BSD-3-Clause" 2267 | ], 2268 | "authors": [ 2269 | { 2270 | "name": "Sebastian Bergmann", 2271 | "email": "sebastian@phpunit.de", 2272 | "role": "lead" 2273 | } 2274 | ], 2275 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 2276 | "homepage": "https://github.com/sebastianbergmann/version", 2277 | "support": { 2278 | "issues": "https://github.com/sebastianbergmann/version/issues", 2279 | "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" 2280 | }, 2281 | "funding": [ 2282 | { 2283 | "url": "https://github.com/sebastianbergmann", 2284 | "type": "github" 2285 | } 2286 | ], 2287 | "time": "2020-09-28T06:39:44+00:00" 2288 | }, 2289 | { 2290 | "name": "symfony/polyfill-mbstring", 2291 | "version": "v1.28.0", 2292 | "source": { 2293 | "type": "git", 2294 | "url": "https://github.com/symfony/polyfill-mbstring.git", 2295 | "reference": "42292d99c55abe617799667f454222c54c60e229" 2296 | }, 2297 | "dist": { 2298 | "type": "zip", 2299 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", 2300 | "reference": "42292d99c55abe617799667f454222c54c60e229", 2301 | "shasum": "" 2302 | }, 2303 | "require": { 2304 | "php": ">=7.1" 2305 | }, 2306 | "provide": { 2307 | "ext-mbstring": "*" 2308 | }, 2309 | "suggest": { 2310 | "ext-mbstring": "For best performance" 2311 | }, 2312 | "type": "library", 2313 | "extra": { 2314 | "branch-alias": { 2315 | "dev-main": "1.28-dev" 2316 | }, 2317 | "thanks": { 2318 | "name": "symfony/polyfill", 2319 | "url": "https://github.com/symfony/polyfill" 2320 | } 2321 | }, 2322 | "autoload": { 2323 | "files": [ 2324 | "bootstrap.php" 2325 | ], 2326 | "psr-4": { 2327 | "Symfony\\Polyfill\\Mbstring\\": "" 2328 | } 2329 | }, 2330 | "notification-url": "https://packagist.org/downloads/", 2331 | "license": [ 2332 | "MIT" 2333 | ], 2334 | "authors": [ 2335 | { 2336 | "name": "Nicolas Grekas", 2337 | "email": "p@tchwork.com" 2338 | }, 2339 | { 2340 | "name": "Symfony Community", 2341 | "homepage": "https://symfony.com/contributors" 2342 | } 2343 | ], 2344 | "description": "Symfony polyfill for the Mbstring extension", 2345 | "homepage": "https://symfony.com", 2346 | "keywords": [ 2347 | "compatibility", 2348 | "mbstring", 2349 | "polyfill", 2350 | "portable", 2351 | "shim" 2352 | ], 2353 | "support": { 2354 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" 2355 | }, 2356 | "funding": [ 2357 | { 2358 | "url": "https://symfony.com/sponsor", 2359 | "type": "custom" 2360 | }, 2361 | { 2362 | "url": "https://github.com/fabpot", 2363 | "type": "github" 2364 | }, 2365 | { 2366 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2367 | "type": "tidelift" 2368 | } 2369 | ], 2370 | "time": "2023-07-28T09:04:16+00:00" 2371 | }, 2372 | { 2373 | "name": "symfony/var-dumper", 2374 | "version": "v7.0.0", 2375 | "source": { 2376 | "type": "git", 2377 | "url": "https://github.com/symfony/var-dumper.git", 2378 | "reference": "cf0220fc7607476fd0d001ab3ed9e830d1fdda56" 2379 | }, 2380 | "dist": { 2381 | "type": "zip", 2382 | "url": "https://api.github.com/repos/symfony/var-dumper/zipball/cf0220fc7607476fd0d001ab3ed9e830d1fdda56", 2383 | "reference": "cf0220fc7607476fd0d001ab3ed9e830d1fdda56", 2384 | "shasum": "" 2385 | }, 2386 | "require": { 2387 | "php": ">=8.2", 2388 | "symfony/polyfill-mbstring": "~1.0" 2389 | }, 2390 | "conflict": { 2391 | "symfony/console": "<6.4" 2392 | }, 2393 | "require-dev": { 2394 | "ext-iconv": "*", 2395 | "symfony/console": "^6.4|^7.0", 2396 | "symfony/http-kernel": "^6.4|^7.0", 2397 | "symfony/process": "^6.4|^7.0", 2398 | "symfony/uid": "^6.4|^7.0", 2399 | "twig/twig": "^3.0.4" 2400 | }, 2401 | "bin": [ 2402 | "Resources/bin/var-dump-server" 2403 | ], 2404 | "type": "library", 2405 | "autoload": { 2406 | "files": [ 2407 | "Resources/functions/dump.php" 2408 | ], 2409 | "psr-4": { 2410 | "Symfony\\Component\\VarDumper\\": "" 2411 | }, 2412 | "exclude-from-classmap": [ 2413 | "/Tests/" 2414 | ] 2415 | }, 2416 | "notification-url": "https://packagist.org/downloads/", 2417 | "license": [ 2418 | "MIT" 2419 | ], 2420 | "authors": [ 2421 | { 2422 | "name": "Nicolas Grekas", 2423 | "email": "p@tchwork.com" 2424 | }, 2425 | { 2426 | "name": "Symfony Community", 2427 | "homepage": "https://symfony.com/contributors" 2428 | } 2429 | ], 2430 | "description": "Provides mechanisms for walking through any arbitrary PHP variable", 2431 | "homepage": "https://symfony.com", 2432 | "keywords": [ 2433 | "debug", 2434 | "dump" 2435 | ], 2436 | "support": { 2437 | "source": "https://github.com/symfony/var-dumper/tree/v7.0.0" 2438 | }, 2439 | "funding": [ 2440 | { 2441 | "url": "https://symfony.com/sponsor", 2442 | "type": "custom" 2443 | }, 2444 | { 2445 | "url": "https://github.com/fabpot", 2446 | "type": "github" 2447 | }, 2448 | { 2449 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2450 | "type": "tidelift" 2451 | } 2452 | ], 2453 | "time": "2023-11-27T12:39:18+00:00" 2454 | }, 2455 | { 2456 | "name": "theseer/tokenizer", 2457 | "version": "1.2.2", 2458 | "source": { 2459 | "type": "git", 2460 | "url": "https://github.com/theseer/tokenizer.git", 2461 | "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" 2462 | }, 2463 | "dist": { 2464 | "type": "zip", 2465 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", 2466 | "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", 2467 | "shasum": "" 2468 | }, 2469 | "require": { 2470 | "ext-dom": "*", 2471 | "ext-tokenizer": "*", 2472 | "ext-xmlwriter": "*", 2473 | "php": "^7.2 || ^8.0" 2474 | }, 2475 | "type": "library", 2476 | "autoload": { 2477 | "classmap": [ 2478 | "src/" 2479 | ] 2480 | }, 2481 | "notification-url": "https://packagist.org/downloads/", 2482 | "license": [ 2483 | "BSD-3-Clause" 2484 | ], 2485 | "authors": [ 2486 | { 2487 | "name": "Arne Blankerts", 2488 | "email": "arne@blankerts.de", 2489 | "role": "Developer" 2490 | } 2491 | ], 2492 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 2493 | "support": { 2494 | "issues": "https://github.com/theseer/tokenizer/issues", 2495 | "source": "https://github.com/theseer/tokenizer/tree/1.2.2" 2496 | }, 2497 | "funding": [ 2498 | { 2499 | "url": "https://github.com/theseer", 2500 | "type": "github" 2501 | } 2502 | ], 2503 | "time": "2023-11-20T00:12:19+00:00" 2504 | } 2505 | ], 2506 | "aliases": [], 2507 | "minimum-stability": "stable", 2508 | "stability-flags": [], 2509 | "prefer-stable": false, 2510 | "prefer-lowest": false, 2511 | "platform": { 2512 | "php": ">=8.0", 2513 | "ext-json": "*", 2514 | "ext-curl": "*", 2515 | "ext-mbstring": "*" 2516 | }, 2517 | "platform-dev": [], 2518 | "plugin-api-version": "2.6.0" 2519 | } 2520 | -------------------------------------------------------------------------------- /controllers/train_carriages.php: -------------------------------------------------------------------------------- 1 | setUserAgent('Mozilla 5'); 5 | $config->setReferer('https://rzd.ru'); 6 | $api = new Rzd\Api($config); 7 | $tomorrow = new DateTime('tomorrow'); 8 | $params = [ 9 | 'code0' => $_GET['code0'], 10 | 'code1' => $_GET['code1'], 11 | 'tnum0' => $_GET['tnum0'], 12 | 'time0' => $_GET['time0'], 13 | 'dt0' => $_GET['dt0'] ?? $tomorrow->format('d.m.Y'), 14 | 'dir' => $_GET['dir'] ?? 0, 15 | ]; 16 | header('Content-type: application/json'); 17 | echo $api->trainCarriages($params); 18 | ?> 19 | -------------------------------------------------------------------------------- /controllers/train_routes.php: -------------------------------------------------------------------------------- 1 | setUserAgent('Mozilla 5'); 5 | $config->setReferer('https://rzd.ru'); 6 | $api = new Rzd\Api($config); 7 | $tomorrow = new DateTime('tomorrow'); 8 | $params = [ 9 | 'code0' => $_GET['code0'], 10 | 'code1' => $_GET['code1'], 11 | 'dir' => $_GET['dir'] ?? 0, 12 | 'tfl' => $_GET['tfl'] ?? 3, 13 | 'checkSeats' => $_GET['checkSeats'] ?? 1, 14 | 'dt0' => $_GET['dt0'] ?? $tomorrow->format('d.m.Y'), 15 | 'md' => $_GET['md'] ?? 0, 16 | ]; 17 | header('Content-type: application/json'); 18 | echo $api->trainRoutes($params); 19 | ?> 20 | -------------------------------------------------------------------------------- /docs/auth.md: -------------------------------------------------------------------------------- 1 | # Описание интерфейса пользователя 2 | ## [DEPRECATED] Вырезано в версии 3.0 3 | 4 | В качестве исходного класса используется class Auth 5 | 6 | Для запросов через curl используется класс php-curl-class (https://github.com/php-curl-class/php-curl-class) 7 | 8 | ### Установка 9 | Заполните логин и пароль от сайта https://rzd.ru в файле bootstrap.php 10 | 11 | ### Авторизация 12 | Процесс авторизации на сайте простой, для этого достаточно отправить пароль и логин на страницу https://pass.rzd.ru/timetable/j_security_check/ru 13 | 14 | Узнать прошла ли авторизация можно прочитав куки AuthFlag - если параметр установлен в true, то результат авторизации успешный или запросив страницу с данными пользователя 15 | 16 | Эту проверку реализует метод login в классе Auth 17 | 18 | public function login() 19 | 20 | Возвращает результат авторизации boolean (true/false) 21 | 22 | ### Получение данных пользователя 23 | Данный функционал заложен в методе getProfile() 24 | 25 | * На выходе массив с данными пользователя 26 | -------------------------------------------------------------------------------- /docs/install.md: -------------------------------------------------------------------------------- 1 | # Установка 2 | 3 | Это конечно не весь список возможностей, здесь сделан только вывод самой актуальной информации, в виде json массива, по мере возможностей буду дополнять данный функционал 4 | 5 | * Для установки нужно запустить composer, который автоматически подгрузит нужные для работы классы 6 | * Запустите через консоль в директории вашего проекта 7 | ```sh 8 | composer require visavi/rzd-api 9 | ``` 10 | 11 | * [DEPRECATED] Для демонстрации пользовательского интерфеса установите логин и пароль ($username и $password) в файле examples/user_login.php от сайта rzd.ru 12 | 13 | ### Пример работы 14 | Для просмотра возможностей API зайдите на главную страницу examples/index.php 15 | 16 | ### Запуск тестов 17 | ```sh 18 | vendor/bin/phpunit 19 | ``` 20 | 21 | ### Реализованные классы 22 | 23 | * Query.php - состоит из 5 методов, 24 | * get - Получает данные, может как принимать данные GET так и отправлять POST (PATCH, PUT, DELETE) 25 | * run - Вспомогательный метод, запрашивает данные, получает сессию и куки для повторного запроса 26 | * getRid - Вспомогательный метод, получает уникальный ключ RID (REQUEST_ID) 27 | 28 | * Api.php 29 | * trainRoutes - Получение маршрутов в одну точку 30 | * trainRoutesReturn - Получение маршрутов туда-обратно 31 | * trainCarriages - Получение списка вагонов выбранного поезда 32 | * trainStationList - Получение списка станций в пути следования выбранного маршрута 33 | * stationCode - Получение списка кодов станций (Поиск по первым символам города) 34 | -------------------------------------------------------------------------------- /examples/index.php: -------------------------------------------------------------------------------- 1 |

Примеры запросов

2 | 3 |
4 | Обращаем внимание на то, что по новым условиям RZD.RU дату отправки нужно указывать с учетом часового пояса станции отправления 5 |
6 | 7 |

В каждый запрос можно добавлять свои параметры (Все параметры не обязательны)

8 | 9 |
 10 | $config = new Rzd\Config();
 11 | 
 12 | // Устанавливаем язык
 13 | $config->setLanguage('en');
 14 | 
 15 | // Добавляем прокси
 16 | $config->setProxy('https://username:password@192.168.16.1:10');
 17 | 
 18 | // Изменяем userAgent
 19 | $config->setUserAgent('Mozilla 5');
 20 | 
 21 | // Изменяем referer
 22 | $config->setReferer('https://rzd.ru');
 23 | 
 24 | $api = new Rzd\Api($config);
 25 | 
26 | 27 |

Выбор маршрута в одну сторону

28 | Просмотр
29 | В примере выполняется поиск маршрута САНКТ-ПЕТЕРБУРГ - МОСКВА (только с билетами) на завтра 30 | 31 |
 32 | $params = [
 33 |     'dir'        => 0,
 34 |     'tfl'        => 3,
 35 |     'checkSeats' => 1,
 36 |     'code0'      => '2004000',
 37 |     'code1'      => '2000000',
 38 |     'dt0'        => 'Дата отправления',
 39 | ];
 40 | 
 41 | $routes = $api->trainRoutes($params)
 42 | 
43 | 44 |

Выбор маршрута в одну сторону c измененными параметрами

45 | Просмотр
46 | В примере выполняется аналогичный поиск маршрута SANKT-PETERBURG - MOSKVA (только с билетами) на завтра, но с установленными параметрами:
47 |
 48 | Язык: en
 49 | UserAgent: Mozilla 5
 50 | Referer: rzd.ru
 51 | 
52 | 53 |

Выбор маршрута туда-обратно

54 | Просмотр
55 | В примере выполняется поиск маршрута САНКТ-ПЕТЕРБУРГ - МОСКВА (только с билетами) на завтра туда и через 5 дней обратно 56 | 57 |
 58 | $params = [
 59 |     'dir'        => 1,
 60 |     'tfl'        => 3,
 61 |     'checkSeats' => 1,
 62 |     'code0'      => '2004000',
 63 |     'code1'      => '2000000',
 64 |     'dt0'        => 'Дата отправления',
 65 |     'dt1'        => 'Дата возврата',
 66 | ];
 67 | 
 68 | $routes = $api->trainRoutesReturn($params);
 69 | 
70 | 71 |

Выбор маршрута в одну сторону с пересадками

72 | Просмотр
73 | В примере выполняется поиск маршрута НОВЫЙ УРЕНГОЙ - АБАКАН (только с билетами) (с пересадками) на завтра 74 | 75 |
 76 | $params = [
 77 |     'dir'        => 0,
 78 |     'tfl'        => 3,
 79 |     'checkSeats' => 1,
 80 |     'code0'      => '2030319',
 81 |     'code1'      => '2038230',
 82 |     'dt0'        => 'Дата отправления',
 83 |     'md'         => 1,
 84 | ];
 85 | 
 86 | $routes = $api->trainRoutes($params)
 87 | 
88 | 89 |

Выбор вагонов

90 | Просмотр
91 | В примере выполняется просмотр всех вагонов в поезде с направлением САНКТ-ПЕТЕРБУРГ - МОСКВА на завтра 92 | 93 |
 94 | $params = [
 95 |     'dir'   => 0,
 96 |     'code0' => '2004000',
 97 |     'code1' => '2000000',
 98 |     'dt0'   => 'Дата отправления',
 99 |     'time0' => 'Время отправления',
100 |     'tnum0' => 'Номер вагона',
101 | ];
102 | 
103 | $carriages = $api->trainCarriages($params)
104 | 
105 | 106 |

Просмотр станций

107 | Просмотр
108 | В примере выполняется поиск всех станций остановок для поезда номер 072E на завтра 109 | 110 |
111 | $params = [
112 |     'trainNumber' => '054Г',
113 |     'depDate'     => 'Дата отправления',
114 | ];
115 | 
116 | $stations = $api->trainStationList($params);
117 | 
118 | 119 | 120 |

Просмотр списка кодов станций

121 | Просмотр
122 | В примере выполняется поиск кодов станций начинающихся с ЧЕБ 123 | 124 |
125 | $api = new Rzd\Api();
126 | 
127 | $params = [
128 |     'stationNamePart' => 'ЧЕБ',
129 |     'compactMode'     => 'y',
130 | ];
131 | 
132 | $stations = $api->stationCode($params);
133 | 
134 | -------------------------------------------------------------------------------- /examples/station_code.php: -------------------------------------------------------------------------------- 1 | 'ЧЕБ', 8 | 'compactMode' => 'y', 9 | ]; 10 | 11 | $stations = $api->stationCode($params); 12 | 13 | if ($stations) { 14 | echo $stations; 15 | } else { 16 | echo 'Не найдено совпадений!'; 17 | } 18 | -------------------------------------------------------------------------------- /examples/train_carriages.php: -------------------------------------------------------------------------------- 1 | modify('+1 day'); 8 | 9 | // Получаем актуальный маршрут 10 | $params = [ 11 | 'dir' => 0, 12 | 'tfl' => 3, 13 | 'checkSeats' => 1, 14 | 'code0' => '2004000', 15 | 'code1' => '2000000', 16 | 'dt0' => $date0->format('d.m.Y'), 17 | ]; 18 | $routes = json_decode($api->trainRoutes($params)); 19 | 20 | if ($routes) { 21 | $params = [ 22 | 'dir' => 0, 23 | 'code0' => '2004000', 24 | 'code1' => '2000000', 25 | 'dt0' => $routes[0]->date0, 26 | 'time0' => $routes[0]->time0, 27 | 'tnum0' => $routes[0]->number, 28 | ]; 29 | 30 | echo $api->trainCarriages($params); 31 | 32 | } else { 33 | echo 'Не удалось найти маршрут'; 34 | } 35 | -------------------------------------------------------------------------------- /examples/train_routes.php: -------------------------------------------------------------------------------- 1 | modify('+1 day'); 7 | 8 | $params = [ 9 | 'dir' => 0, 10 | 'tfl' => 3, 11 | 'checkSeats' => 1, 12 | 'code0' => '2004000', 13 | 'code1' => '2000000', 14 | 'dt0' => $date0->format('d.m.Y'), 15 | ]; 16 | 17 | $api = new Rzd\Api(); 18 | 19 | echo $api->trainRoutes($params); 20 | -------------------------------------------------------------------------------- /examples/train_routes_params.php: -------------------------------------------------------------------------------- 1 | setLanguage('en'); 9 | 10 | // Изменяем userAgent 11 | $config->setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.2'); 12 | 13 | // Изменяем referer 14 | $config->setReferer('https://ticket.rzd.ru/'); 15 | 16 | // Enable debug mode 17 | //$config->setDebugMode(true); 18 | 19 | // Enable proxy 20 | //$config->setProxy('https://username:password@192.168.16.1:10'); 21 | 22 | $start = new DateTime(); 23 | $date0 = $start->modify('+1 day'); 24 | 25 | $params = [ 26 | 'dir' => 0, 27 | 'tfl' => 3, 28 | 'checkSeats' => 1, 29 | 'code0' => '2004000', 30 | 'code1' => '2000000', 31 | 'dt0' => $date0->format('d.m.Y'), 32 | ]; 33 | 34 | $api = new Rzd\Api($config); 35 | 36 | echo $api->trainRoutes($params); 37 | -------------------------------------------------------------------------------- /examples/train_routes_return.php: -------------------------------------------------------------------------------- 1 | modify('+1 day'); 7 | $date1 = $start->modify('+5 day'); 8 | 9 | $params = [ 10 | 'dir' => 1, 11 | 'tfl' => 3, 12 | 'checkSeats' => 1, 13 | 'code0' => '2004000', 14 | 'code1' => '2000000', 15 | 'dt0' => $date0->format('d.m.Y'), 16 | 'dt1' => $date1->format('d.m.Y'), 17 | ]; 18 | 19 | $api = new Rzd\Api(); 20 | 21 | echo $api->trainRoutesReturn($params); 22 | -------------------------------------------------------------------------------- /examples/train_routes_transfer.php: -------------------------------------------------------------------------------- 1 | modify('+1 day'); 7 | 8 | $params = [ 9 | 'dir' => 0, 10 | 'tfl' => 3, 11 | 'checkSeats' => 1, 12 | 'code0' => '2030319', 13 | 'code1' => '2038230', 14 | 'dt0' => $date0->format('d.m.Y'), 15 | 'md' => 1, 16 | ]; 17 | 18 | $api = new Rzd\Api(); 19 | 20 | echo $api->trainRoutes($params); 21 | -------------------------------------------------------------------------------- /examples/train_station_list.php: -------------------------------------------------------------------------------- 1 | modify('+1 day'); 8 | 9 | $params = [ 10 | 'trainNumber' => '054Г', 11 | 'depDate' => $date0->format('d.m.Y'), 12 | ]; 13 | 14 | echo $api->trainStationList($params); 15 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | tests 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Api сайта rzd.ru 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/visavi/rzd-api/v/stable)](https://packagist.org/packages/visavi/rzd-api) 4 | [![Total Downloads](https://poser.pugx.org/visavi/rzd-api/downloads)](https://packagist.org/packages/visavi/rzd-api) 5 | [![Latest Unstable Version](https://poser.pugx.org/visavi/rzd-api/v/unstable)](https://packagist.org/packages/visavi/rzd-api) 6 | [![License](https://poser.pugx.org/visavi/rzd-api/license)](https://packagist.org/packages/visavi/rzd-api) 7 | 8 | [Описание установки](https://github.com/visavi/rzd-api/blob/master/docs/install.md) 9 | 10 | [Описание интерфейса пользователя](https://github.com/visavi/rzd-api/blob/master/docs/auth.md) 11 | 12 | ### Что умеет Api 13 | * Получает маршруты в одну точку 14 | * Получает маршруты туда-обратно 15 | * Получает список вагонов выбранного поезда 16 | * Получает список станций в пути следования выбранного маршрута 17 | * Получает список кодов станций (Поиск по первым символам города) 18 | 19 | ### Демонстрация возможностей 20 | 21 | #### Быстрый способ (Docker) 22 | 23 | ```commandline 24 | docker run -p 8000:8000 --rm --name rzd-api -v $(pwd):/app-it pavelsr/rzd-api 25 | curl -s 'http://127.0.0.1:8000/train_routes.php?code0=2004000&code1=2000000' 26 | ``` 27 | 28 | Если вы предпочитаете Github Container Registry вы можете также использовать образ `ghcr.io/pavelsr/rzd-api:latest` 29 | 30 | #### Локальная установка 31 | 32 | Скачайте архив, распакуйте и перейдите в директорию 33 | 34 | Установите необходимые зависимости 35 | ```sh 36 | composer install 37 | ``` 38 | 39 | И запустите встроенный веб-сервер 40 | ```sh 41 | php -S localhost:8000 -t examples 42 | ``` 43 | 44 | ### Пример запроса 45 | ```php 46 | setLanguage('en'); 52 | 53 | // Set userAgent 54 | $config->setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1'); 55 | 56 | // Set referer 57 | $config->setReferer('https://ticket.rzd.ru/'); 58 | 59 | // Enable debug mode 60 | $config->setDebugMode(true); 61 | 62 | // Set proxy 63 | $config->setProxy('https://username:password@192.168.16.1:10'); 64 | 65 | // Set timeout 66 | $config->setTimeout(10); 67 | 68 | //$config не обязателен 69 | $api = new Rzd\Api($config); 70 | 71 | // В примере выполняется поиск маршрута САНКТ-ПЕТЕРБУРГ - МОСКВА (только с билетами) на завтра 72 | $params = [ 73 | 'dir' => 0, // 0 - только в один конец, 1 - туда-обратно 74 | 'tfl' => 3, // 3 - поезда и электрички, 2 - электрички, 1 - поезда 75 | 'checkSeats' => 1, // 1 - только с билетами, 0 - все поезда 76 | //'withoutSeats' => 'y', // Если checkSeats = 0, то этот параметр тоже необходим 77 | // Коды станций можно получить отдельным запросом 78 | 'code0' => '2004000', // код станции отправления 79 | 'code1' => '2000000', // код станции прибытия 80 | 'dt0' => 'дата на завтра d.m.Y', 81 | 'md' => 0, // 0 - без пересадок, 1 - с пересадками 82 | ]; 83 | 84 | $routes = $api->trainRoutes($params); 85 | ``` 86 | 87 | ### Процесс приобретения билетов на сайте pass.rzd.ru разделен на несколько этапов 88 | 89 | #### Открытая часть 90 | Выбор маршрута - выбор поезда - выбор вагона 91 | 92 | #### Закрытая часть 93 | * Информация о пассажирах - Проверка заказа - Оплата заказа - Подтверждение заказа 94 | 95 | ### Этапы 96 | * В первом этапе пользователь указывают станцию отправления и станцию прибытия поезда, а также дату желаемой поездки. 97 | В этот момент на сайте pass.rzd.ru происходит отправка ajax-запроса, с которым мы и будем работать, запрос возвращает сформированный JSON пакет с ответом, в нем и находится требуемая нами информация или сообщение об ошибке 98 | 99 | * Во втором этапе мы можем выбрать необходимый нам поезд и получить полную информацию о свободных местах 100 | 101 | * В третьем этапе необходимо выбрать места и заполнить данные необходимые на оплаты и регистрации на сайте 102 | 103 | Допустимые запросы через Curl (POST и GET) 104 | Для обхода защиты сайта необходимо предварительно отправить запрос для получения cookies и номера идентификатора RID (REQUEST_ID) 105 | Вторым запросом подставляем уникальный идентификатор RID и отправляем cookie 106 | 107 | ### Ответы с сайта 108 | Статус ответа содержится в переменной result 109 | RID - означает что сайт выдал нам уникальный идентификатор и куки 110 | OK - получен полный ответ с запрошенными нами данными 111 | Во всех остальных ответах Error или FAIL означает ошибку получения данных 112 | 113 | ### Получение cookie 114 | Каждый запрос к сайту должен содержать куки примерного вида: 115 | * lang=ru - текущий язык 116 | * JSESSIONID=0000w74wcMhGMfeoE6ibmsh4i4W:17obq9kpt - уникальный ключ 117 | * AuthFlag=false - авторизован ли пользователь на сайте 118 | 119 | ## Пример запроса 120 | 121 | Все запросы идут на адрес http://pass.rzd.ru/timetable/public/ru?layer_id=подкатегория&ключ=значение 122 | 123 | Где подкатегория это 124 | * 5827 - выбор маршрута (Получения списка поездов) 125 | * 5764 - детальная информация выбранному по поезду, список вагонов 126 | * 5804 - просмотр маршрута со всеми остановками (Вроде больше не работает, реализовано по-другому) 127 | 128 | ### Первый запрос 129 | https://pass.rzd.ru/timetable/public/ru?layer_id=5827&dir=0&tfl=3&checkSeats=1&code0={{code_from}}&dt0={{date}}&code1={{code_to}}&dt1={{date}} 130 | 131 | ### Второй и следующие запросы 132 | https://pass.rzd.ru/timetable/public/ru?layer_id=5827&rid={{rid}} 133 | 134 | Второй запрос выполняется с уже полученным нами уникальным идентификатором который хранит в себе данные предыдущего запроса и куками 135 | Поэтому в целях оптимизации можно не отправлять некоторые параметры указанные нами в первом запросе 136 | 137 | ## Реализованные запросы 138 | 139 | Необходимо реализовать отдачу данных через ajax-запросы, в текущих примерах это не реализовано 140 | 141 | ### trainRoutes - получает маршруты поездов, количество свободных мест, цены итд в нем в один конец 142 | 143 | ![Маршруты](https://github.com/visavi/rzd-api/blob/master/screens/trainRoute.png) 144 | 145 | Принимает параметры 146 | обязательные параметр при первом запросе 147 | * layer_id - подкатегория (5827) 148 | 149 | Необязательные параметр при повторном запросе 150 | * dir - 0 - только в один конец, 1 - туда-обратно 151 | * tfl - 3 - поезда и электрички, 2 - электрички, 1 - поезда 152 | * checkSeats - 0, 1 - поиск в поездах только если есть свободные места 153 | * code0 - код станции отправления 154 | * code1 - код станции прибытия 155 | * dt0 - дата отправления 156 | * md - маршруты с пересадками (1 - с пересадками, 0 - только прямые рейсы) 157 | 158 | Возвращает массив поездов и свободных мест 159 | * from - название станции отправления (САНКТ-ПЕТЕРБУРГ) 160 | * where - название станции прибытия (КИРОВ ПАСС) 161 | * date - дата отправления (27.03.2016) 162 | * fromCode - код станции отправления (2004000) 163 | * whereCode - код станции прибытия (2060600) 164 | 165 | Массив поездов содержит 166 | * date0 - дата отправления 167 | * date1 - дата прибытия 168 | * time0 - время отправления 169 | * time1 - время прибытия 170 | * route0 - код станции отправления С-ПЕТ-ЛАД 171 | * route1 - код станции прибытия ТЮМЕНЬ 172 | * number - номер поезда 173 | * timeInWay - время в пути 174 | * brand - Название поезда (Демидовский экспресс) 175 | * carrier - тип поезда ФПК (Фирменный) 176 | 177 | * cars - массив свободных мест купе, плацкарт и люкс 178 | * cars.freeSeats - кол. свободных мест 179 | * cars.itype 180 | * cars.servCls - класс обслуживания (2Ю, 2Ж и т.д.) 181 | * cars.tariff - стоимость билета 182 | * cars.pt - баллы 183 | * cars.typeLoc - полное наименование (Плацкартный, СВ, Купе, Люкс) 184 | * cars.type - сокращенное наименование (Купе, плац, люкс) 185 | * cars.disabledPerson - флаг обозначающий места для инвалидов 186 | 187 | ### trainRoutesReturn - получает маршруты поездов, количество свободных мест, цены итд, туда-обратно 188 | ![Поезда](https://github.com/visavi/rzd-api/blob/master/screens/trainRouteReturn.png) 189 | 190 | Принимает параметры 191 | обязательные параметр при первом запросе 192 | * layer_id - подкатегория (5827) 193 | 194 | Необязательные параметр при повторном запросе 195 | * dir - 0 только в один конец, 1 - туда-обратно 196 | * tfl - тип поезда (3 - поезда и электрички, 2 - электрички, 1 - поезда) 197 | * checkSeats поиск только с билетами (1 - с билетами, 0 - все поезда) 198 | * code0 - код станции отправления 199 | * code1 - код станции прибытия 200 | * dt0 - дата отправления 201 | * dt1 - дата возвращения 202 | 203 | Ответы точно такие же как и в методе trainRoutes, только содержит 2 массива, в первом - туда, во-втором - обратно 204 | 205 | ### trainCarriages - получает список вагонов, свободные места, схема вагона, стоимость билетов, тип и класс обслуживания 206 | ![Вагоны](https://github.com/visavi/rzd-api/blob/master/screens/trainCarriages.png) 207 | 208 | Необязательные параметр при повторном запросе 209 | * dir - 0 только в один конец, 1 - туда-обратно 210 | * code0 - код станции отправления 211 | * code1 - код станции прибытия 212 | * dt0 - дата отправления (28.03.2016) 213 | * time0 - время отправления (15:30) 214 | * tnum0 - номер поезда (072Е) 215 | 216 | Возвращает следующий массив вагонов 217 | * Стандартный ответ из запросов выше 218 | * cnumber - номер вагона 219 | * type - тип вагона 220 | * typeLoc - полное наименование (Плацкартный, СВ, Купе, Люкс) 221 | * clsType - 2Л, 2Э 222 | * tariff - стоимость билета 223 | * tariffServ - сервис сбор 224 | 225 | * seats - массив мест (верхние, верхние боковые, нижние, нижние боковые итд) 226 | * seats.*.places - список свободных мест 227 | * seats.*.tariff - цены за место 228 | * seats.type - сокр. наименование мест (up) 229 | * seats.free - количество мест 230 | * seats.label - полное наименование мест (Верхние) 231 | 232 | * schemes схемы вагонов 233 | * html - json массив информация о схеме вагонов 234 | * image - ссылка на картинку 235 | 236 | * insuranceCompany - массив с компаниями страхователями и правилами страхования 237 | * shortName - наименование организации 238 | * offerUrl - ссылка на файл с правилами, обычно PDF файл 239 | 240 | ### trainStationList - получение списка всех станций в текущем маршруте движения 241 | ![Станции](https://github.com/visavi/rzd-api/blob/master/screens/trainStationList.png) 242 | 243 | Пример запроса https://pass.rzd.ru/ticket/services/route/basicRoute?STRUCTURE_ID=704&trainNumber=054Г&depDate=13.03.2016 244 | 245 | Принимает параметры 246 | Необязательные параметр при повторном запросе 247 | * trainNumber - номер поезда 054Г 248 | * depDate - дата отправления 13.03.2016 249 | 250 | Возвращает следующий массив станций 251 | * Station - название станции 252 | * Code - код станции 253 | * ArvTime - время прибытия 254 | * WaitingTime - время стоянки 255 | * DepTime - время отправления 256 | * Distance - пройденная дистанция 257 | 258 | ### stationCode - Получение списка кодов станций 259 | 260 | Принимает параметры 261 | * stationNamePart - часть названия станции, минимум 2 символа 262 | * compactMode - по умолчанию 'y' 263 | 264 | Возвращает массив найденных данных 265 | * station - имя станции 266 | * code - код станции 267 | 268 | К примеру при значении stationNamePart = 'ЧЕБ' будут возващены все станции начинающиеся на ЧЕБ (11 станций) 269 | 270 | ### License 271 | 272 | The class is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT) 273 | -------------------------------------------------------------------------------- /screens/trainCarriages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visavi/rzd-api/2196c6ffe6265b91a66282a597abd23c9cecc486/screens/trainCarriages.png -------------------------------------------------------------------------------- /screens/trainRoute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visavi/rzd-api/2196c6ffe6265b91a66282a597abd23c9cecc486/screens/trainRoute.png -------------------------------------------------------------------------------- /screens/trainRouteReturn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visavi/rzd-api/2196c6ffe6265b91a66282a597abd23c9cecc486/screens/trainRouteReturn.png -------------------------------------------------------------------------------- /screens/trainStationList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visavi/rzd-api/2196c6ffe6265b91a66282a597abd23c9cecc486/screens/trainStationList.png -------------------------------------------------------------------------------- /src/Rzd/Api.php: -------------------------------------------------------------------------------- 1 | lang = $config->getLanguage(); 44 | $this->path .= $this->lang; 45 | $this->query = new Query($config); 46 | } 47 | 48 | /** 49 | * Получает маршруты в 1 точку 50 | * 51 | * @param array $params Массив параметров 52 | * 53 | * @return string 54 | * @throws GuzzleException|JsonException 55 | */ 56 | public function trainRoutes(array $params): string 57 | { 58 | $layer = [ 59 | 'layer_id' => static::ROUTES_LAYER, 60 | ]; 61 | $routes = $this->query->get($this->path, $layer + $params); 62 | 63 | return json_encode($routes->tp[0]->list, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE); 64 | } 65 | 66 | /** 67 | * Получает маршруты туда-обратно 68 | * 69 | * @param array $params Массив параметров 70 | * 71 | * @return string 72 | * @throws GuzzleException|JsonException 73 | */ 74 | public function trainRoutesReturn(array $params): string 75 | { 76 | $layer = [ 77 | 'layer_id' => static::ROUTES_LAYER, 78 | ]; 79 | $routes = $this->query->get($this->path, $layer + $params); 80 | 81 | return json_encode([ 82 | 'forward' => $routes->tp[0]->list, 83 | 'back' => $routes->tp[1]->list, 84 | ], 85 | JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE 86 | ); 87 | } 88 | 89 | /** 90 | * Получение списка вагонов 91 | * 92 | * @param array $params Массив параметров 93 | * 94 | * @return string 95 | * @throws GuzzleException|JsonException 96 | */ 97 | public function trainCarriages(array $params): string 98 | { 99 | $layer = [ 100 | 'layer_id' => static::CARRIAGES_LAYER, 101 | ]; 102 | $carriages = $this->query->get($this->path, $layer + $params); 103 | 104 | return json_encode([ 105 | 'cars' => $carriages->lst[0]->cars ?? null, 106 | 'functionBlocks' => $carriages->lst[0]->functionBlocks ?? null, 107 | 'schemes' => $carriages->schemes ?? null, 108 | 'companies' => $carriages->insuranceCompany ?? null, 109 | ], 110 | JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE 111 | ); 112 | 113 | } 114 | 115 | /** 116 | * Получение списка станций 117 | * 118 | * @param array $params Массив параметров 119 | * 120 | * @return string 121 | * @throws GuzzleException|JsonException 122 | */ 123 | public function trainStationList(array $params): string 124 | { 125 | $layer = [ 126 | 'STRUCTURE_ID' => static::STATIONS_STRUCTURE_ID, 127 | ]; 128 | $stations = $this->query->get($this->stationListPath, $layer + $params); 129 | 130 | return json_encode([ 131 | 'train' => $stations->data->trainInfo, 132 | 'routes' => $stations->data->routes, 133 | ], 134 | JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE 135 | ); 136 | } 137 | 138 | /** 139 | * Получение списка кодов станций 140 | * 141 | * @param array $params Массив параметров 142 | * 143 | * @return string 144 | * @throws GuzzleException|JsonException 145 | */ 146 | public function stationCode(array $params): string 147 | { 148 | $lang = [ 149 | 'lang' => $this->lang, 150 | ]; 151 | 152 | $routes = $this->query->get($this->suggestionPath, $lang + $params, 'GET'); 153 | $stations = []; 154 | 155 | if ($routes) { 156 | foreach ($routes as $station) { 157 | if (mb_stristr($station->n, $params['stationNamePart'])) { 158 | $stations[] = [ 159 | 'station' => $station->n, 160 | 'code' => $station->c, 161 | ]; 162 | } 163 | } 164 | } 165 | 166 | return json_encode($stations, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/Rzd/Config.php: -------------------------------------------------------------------------------- 1 | language = $language; 22 | } 23 | 24 | /** 25 | * Get Language 26 | * 27 | * @return string 28 | */ 29 | public function getLanguage(): string 30 | { 31 | return $this->language; 32 | } 33 | 34 | /** 35 | * Set debug mode 36 | * 37 | * @param bool $debug 38 | */ 39 | public function setDebugMode(bool $debug): void 40 | { 41 | $this->debug = $debug; 42 | } 43 | 44 | /** 45 | * Get debug mode 46 | * 47 | * @return bool 48 | */ 49 | public function getDebugMode(): bool 50 | { 51 | return $this->debug; 52 | } 53 | 54 | /** 55 | * Get timeout 56 | * 57 | * @return float 58 | */ 59 | public function getTimeout(): float 60 | { 61 | return $this->timeout; 62 | } 63 | 64 | /** 65 | * Set timeout 66 | * 67 | * @param float $timeout 68 | */ 69 | public function setTimeout(float $timeout): void 70 | { 71 | $this->timeout = $timeout; 72 | } 73 | 74 | /** 75 | * Set Proxy 76 | * 77 | * @param string $proxy 78 | */ 79 | public function setProxy(string $proxy): void 80 | { 81 | $this->proxy = $proxy; 82 | } 83 | 84 | /** 85 | * Get Proxy 86 | * 87 | * @return string|null 88 | */ 89 | public function getProxy(): ?string 90 | { 91 | return $this->proxy; 92 | } 93 | 94 | /** 95 | * Set User Agent 96 | * 97 | * @param string $userAgent 98 | */ 99 | public function setUserAgent(string $userAgent): void 100 | { 101 | $this->userAgent = $userAgent; 102 | } 103 | 104 | /** 105 | * Get User Agent 106 | * 107 | * @return string|null 108 | */ 109 | public function getUserAgent(): ?string 110 | { 111 | return $this->userAgent; 112 | } 113 | 114 | /** 115 | * Set Referer 116 | * 117 | * @param string $referer 118 | */ 119 | public function setReferer(string $referer): void 120 | { 121 | $this->referer = $referer; 122 | } 123 | 124 | /** 125 | * Set Referer 126 | * 127 | * @return string|null 128 | */ 129 | public function getReferer(): ?string 130 | { 131 | return $this->referer; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/Rzd/Query.php: -------------------------------------------------------------------------------- 1 | client = new Client([ 25 | 'timeout' => $this->config->getTimeout(), 26 | 'proxy' => $this->config->getProxy(), 27 | 'cookie' => true, 28 | 'verify' => false, 29 | 'allow_redirects' => true, 30 | ]); 31 | 32 | $this->headers = [ 33 | 'Accept' => 'application/json', 34 | ]; 35 | 36 | if ($userAgent = $this->config->getUserAgent()) { 37 | $this->headers['User-Agent'] = $userAgent; 38 | } 39 | 40 | if ($referer = $this->config->getReferer()) { 41 | $this->headers['Referer'] = $referer; 42 | } 43 | 44 | $this->cookieJar = new CookieJar(); 45 | } 46 | 47 | /** 48 | * Получает данные 49 | * 50 | * @param string $path Путь к странице 51 | * @param array $params Массив данных если необходимы параметры 52 | * @param string $method Метод отправки данных 53 | * 54 | * @return array|object 55 | * @throws GuzzleException 56 | */ 57 | public function get(string $path, array $params = [], string $method = 'POST'): mixed 58 | { 59 | return $this->run($path, $params, $method); 60 | } 61 | 62 | /** 63 | * Запрашивает данные 64 | * 65 | * @param string $path Путь к странице 66 | * @param array $params Массив параметров 67 | * @param string $method Тип запроса 68 | * 69 | * @return array|object 70 | * @throws GuzzleException 71 | * @throws Exception 72 | */ 73 | protected function run(string $path, array $params, string $method): mixed 74 | { 75 | $i = 0; 76 | do { 77 | if (isset($rid)) { 78 | $params += ['rid' => $rid]; 79 | } 80 | 81 | $options = [ 82 | 'debug' => $this->config->getDebugMode(), 83 | 'headers' => $this->headers, 84 | 'cookies' => $this->cookieJar, 85 | ]; 86 | 87 | $data = $method === 'GET' ? ['query' => $params] : ['form_params' => $params]; 88 | $response = $this->client->request($method, $path, $data + $options); 89 | 90 | $content = $response->getBody()->getContents(); 91 | $content = json_decode($content, false, 512, JSON_THROW_ON_ERROR); 92 | 93 | $result = $content->result ?? 'OK'; 94 | 95 | switch ($result) { 96 | case 'RID': 97 | case 'REQUEST_ID': 98 | $rid = $this->getRid($content); 99 | sleep(1); 100 | break; 101 | 102 | case 'OK': 103 | if (isset($content->tp[0]->msgList[0]->message)) { 104 | throw new RuntimeException($content->tp[0]->msgList[0]->message); 105 | } 106 | break 2; 107 | 108 | default: 109 | throw new RuntimeException($response->message ?? 'Failed to get request data!'); 110 | } 111 | 112 | $i++; 113 | } while ($i < 10); 114 | 115 | return $content; 116 | } 117 | 118 | /** 119 | * Получает уникальный ключ RID 120 | * 121 | * @param object $content 122 | * 123 | * @return string 124 | * @throws Exception 125 | */ 126 | protected function getRid(object $content): string 127 | { 128 | foreach (['rid', 'RID'] as $rid) { 129 | if (isset($content->$rid)) { 130 | return $content->$rid; 131 | } 132 | } 133 | 134 | throw new RuntimeException('Rid not found!'); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /tests/ApiTest.php: -------------------------------------------------------------------------------- 1 | api = new Api(); 15 | 16 | $start = new DateTime(); 17 | $this->date0 = $start->modify('+1 day'); 18 | $this->date1 = $start->modify('+5 day'); 19 | } 20 | 21 | /** 22 | * Тест получения маршрутов 23 | * 24 | * @runInSeparateProcess 25 | */ 26 | public function testTrainRoutes(): void 27 | { 28 | $params = [ 29 | 'dir' => 0, 30 | 'tfl' => 3, 31 | 'checkSeats' => 1, 32 | 'code0' => '2004000', 33 | 'code1' => '2000000', 34 | 'dt0' => $this->date0->format('d.m.Y'), 35 | ]; 36 | 37 | $trainRoutes = $this->api->trainRoutes($params); 38 | 39 | $this->assertIsArray($trainRoutes); 40 | $this->assertObjectHasAttribute('route0', $trainRoutes[0]); 41 | $this->assertSame('С-ПЕТЕР-ГЛ', $trainRoutes[0]->route0); 42 | } 43 | 44 | /** 45 | * Тест получения маршрутов туда-обратно 46 | * 47 | * @runInSeparateProcess 48 | */ 49 | public function testTrainRoutesReturn(): void 50 | { 51 | $params = [ 52 | 'dir' => 1, 53 | 'tfl' => 3, 54 | 'checkSeats' => 1, 55 | 'code0' => '2004000', 56 | 'code1' => '2000000', 57 | 'dt0' => $this->date0->format('d.m.Y'), 58 | 'dt1' => $this->date1->format('d.m.Y'), 59 | ]; 60 | 61 | $trainRoutesReturn = $this->api->trainRoutesReturn($params); 62 | 63 | $this->assertIsArray($trainRoutesReturn['forward']); 64 | $this->assertIsArray($trainRoutesReturn['back']); 65 | $this->assertObjectHasAttribute('route0', $trainRoutesReturn['forward'][0]); 66 | $this->assertSame('С-ПЕТЕР-ГЛ', $trainRoutesReturn['forward'][0]->route0); 67 | } 68 | 69 | /** 70 | * Тест получения вагонов 71 | * 72 | * @runInSeparateProcess 73 | */ 74 | public function testTrainCarriages(): void 75 | { 76 | $params = [ 77 | 'dir' => 0, 78 | 'tfl' => 3, 79 | 'checkSeats' => 1, 80 | 'code0' => '2004000', 81 | 'code1' => '2000000', 82 | 'dt0' => $this->date0->format('d.m.Y'), 83 | ]; 84 | 85 | $routes = $this->api->trainRoutes($params); 86 | 87 | if ($routes) { 88 | $params = [ 89 | 'dir' => 0, 90 | 'code0' => '2004000', 91 | 'code1' => '2000000', 92 | 'dt0' => $routes[0]->date0, 93 | 'time0' => $routes[0]->time0, 94 | 'tnum0' => $routes[0]->number, 95 | ]; 96 | 97 | $trainCarriages = $this->api->trainCarriages($params); 98 | 99 | $this->assertIsArray($trainCarriages); 100 | $this->assertArrayHasKey('cars', $trainCarriages); 101 | $this->assertObjectHasAttribute('cnumber', $trainCarriages['cars'][0]); 102 | } 103 | } 104 | 105 | /** 106 | * Тест просмотра станций 107 | * 108 | * @runInSeparateProcess 109 | */ 110 | public function testTrainStationList(): void 111 | { 112 | $params = [ 113 | 'trainNumber' => '054Г', 114 | 'depDate' => $this->date0->format('d.m.Y'), 115 | ]; 116 | 117 | $trainStationList = $this->api->trainStationList($params); 118 | 119 | $this->assertIsArray($trainStationList); 120 | $this->assertArrayHasKey('train', $trainStationList); 121 | $this->assertArrayHasKey('routes', $trainStationList); 122 | $this->assertSame('054Г', $trainStationList['train']->number); 123 | } 124 | 125 | /** 126 | * Тест кодов станций 127 | * 128 | * @runInSeparateProcess 129 | */ 130 | public function testStationCode(): void 131 | { 132 | $params = [ 133 | 'stationNamePart' => 'ЧЕБ', 134 | 'compactMode' => 'y', 135 | ]; 136 | 137 | $stationCode = $this->api->stationCode($params); 138 | 139 | $this->assertIsArray($stationCode); 140 | 141 | $cities = []; 142 | foreach($stationCode as $station) { 143 | $cities[] = $station['station']; 144 | } 145 | 146 | $this->assertContains('ЧЕБОКСАРЫ', $cities); 147 | } 148 | } 149 | --------------------------------------------------------------------------------