diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..c443d85 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1,4 @@ +repo_token: RTlXy2H8wGT3YFreCvVwE9FDSvoIzgvAo +coverage_clover: tests/logs/clover.xml +json_path: tests/logs/coveralls-upload.json +service_name: travis-ci \ No newline at end of file diff --git a/.env b/.env index 5582050..a4744f6 100644 --- a/.env +++ b/.env @@ -25,5 +25,15 @@ APP_SECRET=c165ffa974b09ac4d1bd06daf956753b # For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" # For a PostgreSQL database, use: "postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11&charset=utf8" # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml -DATABASE_URL=mysql://root@127.0.0.1:3306/tle?serverVersion=5.7 +DATABASE_URL=mysql://root:root@localhost:3306/tle?serverVersion=8 ###< doctrine/doctrine-bundle ### + +###> sentry/sentry-symfony ### +SENTRY_DSN= +###< sentry/sentry-symfony ### + +###> symfony/lock ### +# Choose one of the stores below +# postgresql+advisory://db_user:db_password@localhost/db_name +LOCK_DSN=semaphore +###< symfony/lock ### diff --git a/.env.test b/.env.test index d048686..410d981 100644 --- a/.env.test +++ b/.env.test @@ -2,4 +2,4 @@ KERNEL_CLASS='App\Kernel' APP_SECRET='$ecretf0rt3st' SYMFONY_DEPRECATIONS_HELPER=999999 -PANTHER_APP_ENV=panther +DATABASE_URL=mysql://root:root@localhost:3306/tle?serverVersion=8 diff --git a/.gitignore b/.gitignore index e56d049..e108fb4 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,7 @@ .phpunit .phpunit.result.cache /phpunit.xml +coverage ###< symfony/phpunit-bridge ### + +public/index.html diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..603c2b0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,31 @@ +language: php + +services: + - mysql + +cache: + directories: + - $HOME/.composer/cache + +branches: + only: + - master + +matrix: + include: + - php: 7.4 + +before_install: + - composer require satooshi/php-coveralls + +install: + - composer install + +script: + - php bin/phpunit --coverage-clover ./tests/logs/clover.xml + +after_script: + - export CI_BUILD_NUMBER="$TRAVIS_BUILD_NUMBER" + - export CI_PULL_REQUEST="$TRAVIS_PULL_REQUEST" + - export CI_BRANCH="$TRAVIS_BRANCH" + - php vendor/satooshi/php-coveralls/bin/php-coveralls -vv --coverage_clover ./tests/logs/clover.xml diff --git a/README.md b/README.md index b94f9a4..76aa52e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,37 @@ -#TLE API - -![status](https://badgen.net/uptime-robot/status/m781499721-d42767e28cc71aea507fb087) -![status](https://badgen.net/uptime-robot/month/m781499721-d42767e28cc71aea507fb087) -![status](https://badgen.net/uptime-robot/response/m781499721-d42767e28cc71aea507fb087) +# TLE API + + + +![coverage](https://badgen.net/coveralls/c/github/ivanstan/tle-api) +![status](https://badgen.net/uptime-robot/status/m781499721-d42767e28cc71aea507fb087) +![status](https://badgen.net/uptime-robot/month/m781499721-d42767e28cc71aea507fb087) +![status](https://badgen.net/uptime-robot/response/m781499721-d42767e28cc71aea507fb087) + +Code repository that powers TLE API backend, listed on NASA API catalog +https://api.nasa.gov/ + +API provides up to date two line element set records, the data is updated +daily from [CelesTrak](https://celestrak.com/) and served in JSON format. A two-line element set (TLE) +is a data format encoding a list of orbital elements of an +Earth-orbiting object for a given point in time. + +## Usage +Further documentation and response examples are available at: +https://tle.ivanstanojevic.me/ + +### Available endpoints +The TLE API consists of two endpoints `GET http://tle.ivanstanojevic.me` + +| Endpoint | Description | +|----------|:------:| +| `GET /api/tle?search={query}` | Perform search by satellite name | +| `GET /api/tle/{id}` | Retrieve a single TLE record where id is satellite number | + +Example query +http://tle.ivanstanojevic.me/api/tle + +# Client libraries + +* JavaScript https://github.com/ivanstan/tle.js +* PHP https://github.com/ivanstan/tle-php +* C# https://github.com/nichols-t/TLE.NET diff --git a/bin/console b/bin/console index 5d5c80f..a9fa7b0 100644 --- a/bin/console +++ b/bin/console @@ -27,7 +27,7 @@ if ($input->hasParameterOption('--no-debug', true)) { putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0'); } -require dirname(__DIR__).'/config/bootstrap.php'; +require dirname(__DIR__).'/etc/bootstrap.php'; if ($_SERVER['APP_DEBUG']) { umask(0000); diff --git a/composer.json b/composer.json index 91a68f9..72e66ab 100644 --- a/composer.json +++ b/composer.json @@ -1,76 +1,109 @@ -{ - "type": "project", - "license": "proprietary", - "require": { - "php": "^7.4", - "ext-ctype": "*", - "ext-iconv": "*", - "ext-json": "*", - "symfony/apache-pack": "^1.0", - "symfony/asset": "5.0.*", - "symfony/browser-kit": "5.0.*", - "symfony/console": "5.0.*", - "symfony/dotenv": "5.0.*", - "symfony/flex": "^1.3.1", - "symfony/framework-bundle": "5.0.*", - "symfony/orm-pack": "^1.0", - "symfony/serializer": "5.0.*", - "symfony/twig-bundle": "5.0.*", - "symfony/yaml": "5.0.*" - }, - "require-dev": { - "doctrine/doctrine-fixtures-bundle": "^3.1", - "symfony/maker-bundle": "^1.9", - "symfony/phpunit-bridge": "^5.0" - }, - "config": { - "preferred-install": { - "*": "dist" - }, - "sort-packages": true, - "optimize-autoloader": true - }, - "autoload": { - "psr-4": { - "App\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "App\\Tests\\": "tests/" - } - }, - "replace": { - "paragonie/random_compat": "2.*", - "symfony/polyfill-ctype": "*", - "symfony/polyfill-iconv": "*", - "symfony/polyfill-php72": "*", - "symfony/polyfill-php71": "*", - "symfony/polyfill-php70": "*", - "symfony/polyfill-php56": "*" - }, - "scripts": { - "auto-scripts": { - "cache:clear": "symfony-cmd", - "assets:install %PUBLIC_DIR%": "symfony-cmd", - "doctrine:migrations:migrate --no-interaction": "symfony-cmd", - "cache:warmup": "symfony-cmd" - }, - "post-install-cmd": [ - "@auto-scripts" - ], - "post-update-cmd": [ - "@auto-scripts" - ] - }, - "conflict": { - "symfony/symfony": "*" - }, - "extra": { - "public-dir": "./", - "symfony": { - "allow-contrib": false, - "require": "5.0.*" - } - } -} +{ + "name": "ivanstan/tle-backend", + "description": "TLE API backend", + "type": "project", + "license": "proprietary", + "version": "1.3.2", + "require": { + "php": "^8.0", + "ext-ctype": "*", + "ext-dom": "*", + "ext-iconv": "*", + "ext-json": "*", + "beberlei/doctrineextensions": "^1.3", + "ivanstan/tle-php": "dev-master", + "myclabs/php-enum": "^1.7", + "sentry/sentry-symfony": "^4.0", + "symfony/apache-pack": "^1.0", + "symfony/asset": "5.3.*", + "symfony/browser-kit": "5.3.*", + "symfony/console": "5.3.*", + "symfony/css-selector": "5.3.*", + "symfony/dotenv": "5.3.*", + "symfony/flex": "^1.3.1", + "symfony/framework-bundle": "5.3.*", + "symfony/monolog-bundle": "^3.7", + "symfony/orm-pack": "^1.1", + "symfony/property-access": "5.3.*", + "symfony/rate-limiter": "5.3.*", + "symfony/serializer": "5.3.*", + "symfony/yaml": "5.3.*" + }, + "require-dev": { + "roave/security-advisories": "dev-latest", + "doctrine/doctrine-fixtures-bundle": "^3.1", + "symfony/phpunit-bridge": "^5.3" + }, + "config": { + "preferred-install": { + "*": "auto" + }, + "sort-packages": true, + "optimize-autoloader": true + }, + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "App\\Tests\\": "tests/" + }, + "files": [ + "lib/predict/Predict.php", + "lib/predict/Predict/Time.php", + "lib/predict/Predict/Math.php", + "lib/predict/Predict/Pass.php", + "lib/predict/Predict/PassDetail.php", + "lib/predict/Predict/Vector.php", + "lib/predict/Predict/Geodetic.php", + "lib/predict/Predict/ObsSet.php", + "lib/predict/Predict/Solar.php", + "lib/predict/Predict/SGPObs.php", + "lib/predict/Predict/SGPSDP.php", + "lib/predict/Predict.php", + "lib/predict/Predict/Sat.php", + "lib/predict/Predict/QTH.php", + "lib/predict/Predict/Time.php", + "lib/predict/Predict/TLE.php", + "lib/predict/Predict/SGSDPStatic.php", + "lib/predict/Predict/SGSDPStatic.php", + "lib/predict/Predict/DeepArg.php", + "lib/predict/Predict/DeepStatic.php" + ] + }, + "replace": { + "paragonie/random_compat": "2.*", + "symfony/polyfill-ctype": "*", + "symfony/polyfill-iconv": "*", + "symfony/polyfill-php72": "*", + "symfony/polyfill-php71": "*", + "symfony/polyfill-php70": "*", + "symfony/polyfill-php56": "*" + }, + "scripts": { + "auto-scripts": { + "cache:clear": "symfony-cmd", + "cache:warmup": "symfony-cmd" + }, + "post-install-cmd": [ + "@auto-scripts" + ], + "post-update-cmd": [ + "@auto-scripts" + ], + "test": "php bin/phpunit --coverage-text", + "deploy": "dep deploy" + }, + "conflict": { + "symfony/symfony": "*" + }, + "extra": { + "public-dir": "./public", + "symfony": { + "allow-contrib": false, + "require": "5.3.*" + } + } +} diff --git a/composer.lock b/composer.lock index 568f416..33d5f75 100644 --- a/composer.lock +++ b/composer.lock @@ -4,36 +4,232 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ad45ae0642275997354a798821f94a16", + "content-hash": "71e846a8b6688a9e07c24696b2d0ad75", "packages": [ { - "name": "doctrine/annotations", - "version": "v1.8.0", + "name": "beberlei/doctrineextensions", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" + "url": "https://github.com/beberlei/DoctrineExtensions.git", + "reference": "008f162f191584a6c37c03a803f718802ba9dd9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", - "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", + "url": "https://api.github.com/repos/beberlei/DoctrineExtensions/zipball/008f162f191584a6c37c03a803f718802ba9dd9a", + "reference": "008f162f191584a6c37c03a803f718802ba9dd9a", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", - "php": "^7.1" + "doctrine/orm": "^2.7", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.14", + "nesbot/carbon": "*", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "symfony/yaml": "^4.2 || ^5.0", + "zf1/zend-date": "^1.12", + "zf1/zend-registry": "^1.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "DoctrineExtensions\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Steve Lacey", + "email": "steve@steve.ly" + } + ], + "description": "A set of extensions to Doctrine 2 that add support for additional query functions available in MySQL, Oracle, PostgreSQL and SQLite.", + "keywords": [ + "database", + "doctrine", + "orm" + ], + "support": { + "source": "https://github.com/beberlei/DoctrineExtensions/tree/v1.3.0" + }, + "time": "2020-11-29T07:37:23+00:00" + }, + { + "name": "clue/stream-filter", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/clue/stream-filter.git", + "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/stream-filter/zipball/aeb7d8ea49c7963d3b581378955dbf5bc49aa320", + "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320", + "shasum": "" + }, + "require": { + "php": ">=5.3" }, "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^7.5" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" }, "type": "library", + "autoload": { + "psr-4": { + "Clue\\StreamFilter\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "A simple and modern approach to stream filtering in PHP", + "homepage": "https://github.com/clue/php-stream-filter", + "keywords": [ + "bucket brigade", + "callback", + "filter", + "php_user_filter", + "stream", + "stream_filter_append", + "stream_filter_register" + ], + "support": { + "issues": "https://github.com/clue/stream-filter/issues", + "source": "https://github.com/clue/stream-filter/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2020-10-02T12:38:20+00:00" + }, + { + "name": "composer/package-versions-deprecated", + "version": "1.11.99.2", + "source": { + "type": "git", + "url": "https://github.com/composer/package-versions-deprecated.git", + "reference": "c6522afe5540d5fc46675043d3ed5a45a740b27c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/c6522afe5540d5fc46675043d3ed5a45a740b27c", + "reference": "c6522afe5540d5fc46675043d3ed5a45a740b27c", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1.0 || ^2.0", + "php": "^7 || ^8" + }, + "replace": { + "ocramius/package-versions": "1.11.99" + }, + "require-dev": { + "composer/composer": "^1.9.3 || ^2.0@dev", + "ext-zip": "^1.13", + "phpunit/phpunit": "^6.5 || ^7" + }, + "type": "composer-plugin", "extra": { + "class": "PackageVersions\\Installer", "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "support": { + "issues": "https://github.com/composer/package-versions-deprecated/issues", + "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" } + ], + "time": "2021-05-24T07:46:03+00:00" + }, + { + "name": "doctrine/annotations", + "version": "1.13.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f", + "reference": "e6e7b7d5b45a2f2abc5460cc6396480b2b1d321f", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" + }, + "require-dev": { + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^6.0 || ^8.1", + "phpstan/phpstan": "^0.12.20", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", + "symfony/cache": "^4.4 || ^5.2" }, + "type": "library", "autoload": { "psr-4": { "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" @@ -66,50 +262,53 @@ } ], "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", "keywords": [ "annotations", "docblock", "parser" ], - "time": "2019-10-01T18:55:10+00:00" + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/1.13.1" + }, + "time": "2021-05-16T18:07:53+00:00" }, { "name": "doctrine/cache", - "version": "1.10.0", + "version": "1.11.3", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62" + "reference": "3bb5588cec00a0268829cc4a518490df6741af9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/382e7f4db9a12dc6c19431743a2b096041bcdd62", - "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62", + "url": "https://api.github.com/repos/doctrine/cache/zipball/3bb5588cec00a0268829cc4a518490df6741af9d", + "reference": "3bb5588cec00a0268829cc4a518490df6741af9d", "shasum": "" }, "require": { - "php": "~7.1" + "php": "~7.1 || ^8.0" }, "conflict": { - "doctrine/common": ">2.2,<2.4" + "doctrine/common": ">2.2,<2.4", + "psr/cache": ">=3" }, "require-dev": { "alcaeus/mongo-php-adapter": "^1.1", - "doctrine/coding-standard": "^6.0", + "cache/integration-tests": "dev-master", + "doctrine/coding-standard": "^8.0", "mongodb/mongodb": "^1.1", - "phpunit/phpunit": "^7.0", - "predis/predis": "~1.0" + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "predis/predis": "~1.0", + "psr/cache": "^1.0 || ^2.0", + "symfony/cache": "^4.4 || ^5.2" }, "suggest": { "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" @@ -154,37 +353,50 @@ "redis", "xcache" ], - "time": "2019-11-29T15:36:20+00:00" + "support": { + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/1.11.3" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", + "type": "tidelift" + } + ], + "time": "2021-05-25T09:01:55+00:00" }, { "name": "doctrine/collections", - "version": "1.6.4", + "version": "1.6.7", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7" + "reference": "55f8b799269a1a472457bd1a41b4f379d4cfba4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", - "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", + "url": "https://api.github.com/repos/doctrine/collections/zipball/55f8b799269a1a472457bd1a41b4f379d4cfba4a", + "reference": "55f8b799269a1a472457bd1a41b4f379d4cfba4a", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.1.3 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^6.0", "phpstan/phpstan-shim": "^0.9.2", "phpunit/phpunit": "^7.0", - "vimeo/psalm": "^3.2.2" + "vimeo/psalm": "^3.8.1" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" @@ -224,47 +436,40 @@ "iterators", "php" ], - "time": "2019-11-13T13:07:11+00:00" + "support": { + "issues": "https://github.com/doctrine/collections/issues", + "source": "https://github.com/doctrine/collections/tree/1.6.7" + }, + "time": "2020-07-27T17:53:49+00:00" }, { "name": "doctrine/common", - "version": "v2.11.0", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/doctrine/common.git", - "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff" + "reference": "a036d90c303f3163b5be8b8fde9b6755b2be4a3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", - "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", + "url": "https://api.github.com/repos/doctrine/common/zipball/a036d90c303f3163b5be8b8fde9b6755b2be4a3a", + "reference": "a036d90c303f3163b5be8b8fde9b6755b2be4a3a", "shasum": "" }, "require": { - "doctrine/annotations": "^1.0", - "doctrine/cache": "^1.0", - "doctrine/collections": "^1.0", - "doctrine/event-manager": "^1.0", - "doctrine/inflector": "^1.0", - "doctrine/lexer": "^1.0", - "doctrine/persistence": "^1.1", - "doctrine/reflection": "^1.0", - "php": "^7.1" + "doctrine/persistence": "^2.0", + "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^1.0", - "phpstan/phpstan": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpunit/phpunit": "^7.0", + "doctrine/coding-standard": "^6.0 || ^8.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^7.5.20 || ^8.5 || ^9.0", "squizlabs/php_codesniffer": "^3.0", - "symfony/phpunit-bridge": "^4.0.5" + "symfony/phpunit-bridge": "^4.0.5", + "vimeo/psalm": "^4.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.11.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Common\\": "lib/Doctrine/Common" @@ -300,41 +505,62 @@ "email": "ocramius@gmail.com" } ], - "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.", "homepage": "https://www.doctrine-project.org/projects/common.html", "keywords": [ "common", "doctrine", "php" ], - "time": "2019-09-10T10:10:14+00:00" + "support": { + "issues": "https://github.com/doctrine/common/issues", + "source": "https://github.com/doctrine/common/tree/3.1.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcommon", + "type": "tidelift" + } + ], + "time": "2021-02-10T20:18:51+00:00" }, { "name": "doctrine/dbal", - "version": "v2.10.0", + "version": "2.13.1", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934" + "reference": "c800380457948e65bbd30ba92cc17cda108bf8c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/0c9a646775ef549eb0a213a4f9bd4381d9b4d934", - "reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/c800380457948e65bbd30ba92cc17cda108bf8c9", + "reference": "c800380457948e65bbd30ba92cc17cda108bf8c9", "shasum": "" }, "require": { "doctrine/cache": "^1.0", + "doctrine/deprecations": "^0.5.3", "doctrine/event-manager": "^1.0", "ext-pdo": "*", - "php": "^7.2" + "php": "^7.1 || ^8" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "jetbrains/phpstorm-stubs": "^2019.1", - "phpstan/phpstan": "^0.11.3", - "phpunit/phpunit": "^8.4.1", - "symfony/console": "^2.0.5|^3.0|^4.0|^5.0" + "doctrine/coding-standard": "8.2.0", + "jetbrains/phpstorm-stubs": "2020.2", + "phpstan/phpstan": "0.12.81", + "phpunit/phpunit": "^7.5.20|^8.5|9.5.0", + "squizlabs/php_codesniffer": "3.6.0", + "symfony/console": "^2.0.5|^3.0|^4.0|^5.0", + "vimeo/psalm": "4.6.4" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -343,12 +569,6 @@ "bin/doctrine-dbal" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.10.x-dev", - "dev-develop": "3.0.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" @@ -399,62 +619,126 @@ "sqlserver", "sqlsrv" ], - "time": "2019-11-03T16:50:43+00:00" + "support": { + "issues": "https://github.com/doctrine/dbal/issues", + "source": "https://github.com/doctrine/dbal/tree/2.13.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", + "type": "tidelift" + } + ], + "time": "2021-04-17T17:30:19+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "v0.5.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "9504165960a1f83cc1480e2be1dd0a0478561314" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/9504165960a1f83cc1480e2be1dd0a0478561314", + "reference": "9504165960a1f83cc1480e2be1dd0a0478561314", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0|^7.0|^8.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v0.5.3" + }, + "time": "2021-03-21T12:59:47+00:00" }, { "name": "doctrine/doctrine-bundle", - "version": "2.0.6", + "version": "2.4.1", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442" + "reference": "7f472cc85eba050a83fcf38cece87b868877d7e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0ef972d3b730f975c80db9fffa4b2a0258c91442", - "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/7f472cc85eba050a83fcf38cece87b868877d7e2", + "reference": "7f472cc85eba050a83fcf38cece87b868877d7e2", "shasum": "" }, "require": { - "doctrine/dbal": "^2.9.0", - "doctrine/persistence": "^1.3.3", - "jdorn/sql-formatter": "^1.2.16", - "php": "^7.1", - "symfony/cache": "^4.3.3|^5.0", - "symfony/config": "^4.3.3|^5.0", - "symfony/console": "^3.4.30|^4.3.3|^5.0", - "symfony/dependency-injection": "^4.3.3|^5.0", - "symfony/doctrine-bridge": "^4.3.7|^5.0", - "symfony/framework-bundle": "^3.4.30|^4.3.3|^5.0", + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/dbal": "^2.9.0|^3.0", + "doctrine/persistence": "^1.3.3|^2.0", + "doctrine/sql-formatter": "^1.0.1", + "php": "^7.1 || ^8.0", + "symfony/cache": "^4.3.3|^5.0|^6.0", + "symfony/config": "^4.4.3|^5.0|^6.0", + "symfony/console": "^3.4.30|^4.3.3|^5.0|^6.0", + "symfony/dependency-injection": "^4.3.3|^5.0|^6.0", + "symfony/deprecation-contracts": "^2.1", + "symfony/doctrine-bridge": "^4.4.22|^5.2.7|^6.0", + "symfony/framework-bundle": "^3.4.30|^4.3.3|^5.0|^6.0", "symfony/service-contracts": "^1.1.1|^2.0" }, "conflict": { - "doctrine/orm": "<2.6", + "doctrine/orm": "<2.9", "twig/twig": "<1.34|>=2.0,<2.4" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "doctrine/orm": "^2.6", - "ocramius/proxy-manager": "^2.1", - "phpunit/phpunit": "^7.5", - "symfony/phpunit-bridge": "^4.2", - "symfony/property-info": "^4.3.3|^5.0", - "symfony/twig-bridge": "^3.4.30|^4.3.3|^5.0", - "symfony/validator": "^3.4.30|^4.3.3|^5.0", - "symfony/web-profiler-bundle": "^3.4.30|^4.3.3|^5.0", - "symfony/yaml": "^3.4.30|^4.3.3|^5.0", - "twig/twig": "^1.34|^2.12" + "doctrine/coding-standard": "^9.0", + "doctrine/orm": "^2.9", + "friendsofphp/proxy-manager-lts": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.3", + "psalm/plugin-phpunit": "^0.15.1", + "psalm/plugin-symfony": "^2.3.0", + "symfony/phpunit-bridge": "^5.2|^6.0", + "symfony/property-info": "^4.3.3|^5.0|^6.0", + "symfony/proxy-manager-bridge": "^3.4|^4.3.3|^5.0|^6.0", + "symfony/security-bundle": "^4.4|^5.0|^6.0", + "symfony/twig-bridge": "^3.4.30|^4.3.3|^5.0|^6.0", + "symfony/validator": "^3.4.30|^4.3.3|^5.0|^6.0", + "symfony/web-profiler-bundle": "^3.4.30|^4.3.3|^5.0|^6.0", + "symfony/yaml": "^3.4.30|^4.3.3|^5.0|^6.0", + "twig/twig": "^1.34|^2.12|^3.0", + "vimeo/psalm": "^4.7" }, "suggest": { "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", + "ext-pdo": "*", "symfony/web-profiler-bundle": "To use the data collector." }, "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Bundle\\DoctrineBundle\\": "" @@ -490,34 +774,52 @@ "orm", "persistence" ], - "time": "2019-12-19T13:47:07+00:00" + "support": { + "issues": "https://github.com/doctrine/DoctrineBundle/issues", + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.4.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-bundle", + "type": "tidelift" + } + ], + "time": "2021-06-01T18:38:32+00:00" }, { "name": "doctrine/doctrine-migrations-bundle", - "version": "2.1.2", + "version": "2.2.2", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", - "reference": "856437e8de96a70233e1f0cc2352fc8dd15a899d" + "reference": "85f0b847174daf243362c7da80efe1539be64f47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/856437e8de96a70233e1f0cc2352fc8dd15a899d", - "reference": "856437e8de96a70233e1f0cc2352fc8dd15a899d", + "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/85f0b847174daf243362c7da80efe1539be64f47", + "reference": "85f0b847174daf243362c7da80efe1539be64f47", "shasum": "" }, "require": { "doctrine/doctrine-bundle": "~1.0|~2.0", "doctrine/migrations": "^2.2", - "php": "^7.1", + "php": "^7.1|^8.0", "symfony/framework-bundle": "~3.4|~4.0|~5.0" }, "require-dev": { - "doctrine/coding-standard": "^5.0", + "doctrine/coding-standard": "^8.0", "mikey179/vfsstream": "^1.6", - "phpstan/phpstan": "^0.9.2", - "phpstan/phpstan-strict-rules": "^0.9", - "phpunit/phpunit": "^6.4|^7.0" + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "symfony-bundle", "extra": { @@ -558,24 +860,42 @@ "migrations", "schema" ], - "time": "2019-11-13T12:57:41+00:00" + "support": { + "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", + "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/2.2.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-migrations-bundle", + "type": "tidelift" + } + ], + "time": "2020-12-23T15:06:17+00:00" }, { "name": "doctrine/event-manager", - "version": "1.1.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "629572819973f13486371cb611386eb17851e85c" + "reference": "41370af6a30faa9dc0368c4a6814d596e81aba7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/629572819973f13486371cb611386eb17851e85c", - "reference": "629572819973f13486371cb611386eb17851e85c", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/41370af6a30faa9dc0368c4a6814d596e81aba7f", + "reference": "41370af6a30faa9dc0368c4a6814d596e81aba7f", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "conflict": { "doctrine/common": "<2.9@dev" @@ -634,37 +954,59 @@ "event system", "events" ], - "time": "2019-11-10T09:48:07+00:00" + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/1.1.x" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", + "type": "tidelift" + } + ], + "time": "2020-05-29T18:28:51+00:00" }, { "name": "doctrine/inflector", - "version": "1.3.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" + "reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", - "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/9cf661f4eb38f7c881cac67c75ea9b00bf97b210", + "reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.2 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^6.2" + "doctrine/coding-standard": "^7.0", + "phpstan/phpstan": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-strict-rules": "^0.11", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" } }, "notification-url": "https://packagist.org/downloads/", @@ -693,48 +1035,67 @@ "email": "schmittjoh@gmail.com" } ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", - "homepage": "http://www.doctrine-project.org", + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", "keywords": [ "inflection", - "pluralize", - "singularize", - "string" + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.x" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } ], - "time": "2019-10-30T19:59:35+00:00" + "time": "2020-05-29T15:13:26+00:00" }, { "name": "doctrine/instantiator", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^6.0", + "doctrine/coding-standard": "^8.0", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" + "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" @@ -748,7 +1109,7 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "homepage": "https://ocramius.github.io/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", @@ -757,24 +1118,42 @@ "constructor", "instantiate" ], - "time": "2019-10-21T16:45:58+00:00" - }, + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-11-10T18:47:58+00:00" + }, { "name": "doctrine/lexer", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" + "reference": "e864bbf5904cb8f5bb334f99209b48018522f042" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", - "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042", + "reference": "e864bbf5904cb8f5bb334f99209b48018522f042", "shasum": "" }, "require": { - "php": "^7.2" + "php": "^7.2 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^6.0", @@ -819,41 +1198,59 @@ "parser", "php" ], - "time": "2019-10-30T14:39:59+00:00" + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2020-05-25T17:44:05+00:00" }, { "name": "doctrine/migrations", - "version": "2.2.0", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "8e124252d2f6be1124017d746d5994dd4095d66f" + "reference": "c4c46f7064f6e7795bd7f26549579918b46790fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/8e124252d2f6be1124017d746d5994dd4095d66f", - "reference": "8e124252d2f6be1124017d746d5994dd4095d66f", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/c4c46f7064f6e7795bd7f26549579918b46790fa", + "reference": "c4c46f7064f6e7795bd7f26549579918b46790fa", "shasum": "" }, "require": { + "composer/package-versions-deprecated": "^1.8", "doctrine/dbal": "^2.9", - "ocramius/package-versions": "^1.3", - "ocramius/proxy-manager": "^2.0.2", - "php": "^7.1", - "symfony/console": "^3.4||^4.0||^5.0", + "friendsofphp/proxy-manager-lts": "^1.0", + "php": "^7.1 || ^8.0", + "symfony/console": "^3.4||^4.4.16||^5.0", "symfony/stopwatch": "^3.4||^4.0||^5.0" }, "require-dev": { - "doctrine/coding-standard": "^6.0", + "doctrine/coding-standard": "^8.2", "doctrine/orm": "^2.6", "ext-pdo_sqlite": "*", "jdorn/sql-formatter": "^1.1", "mikey179/vfsstream": "^1.6", - "phpstan/phpstan": "^0.10", - "phpstan/phpstan-deprecation-rules": "^0.10", - "phpstan/phpstan-phpunit": "^0.10", - "phpstan/phpstan-strict-rules": "^0.10", - "phpunit/phpunit": "^7.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", "symfony/process": "^3.4||^4.0||^5.0", "symfony/yaml": "^3.4||^4.0||^5.0" }, @@ -901,52 +1298,75 @@ "migrations", "php" ], - "time": "2019-11-13T11:06:31+00:00" + "support": { + "issues": "https://github.com/doctrine/migrations/issues", + "source": "https://github.com/doctrine/migrations/tree/2.3.3" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations", + "type": "tidelift" + } + ], + "time": "2021-03-14T10:22:48+00:00" }, { "name": "doctrine/orm", - "version": "v2.7.0", + "version": "2.9.2", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62" + "reference": "75b4b88c5b7cebc24ed7251a20c2a5aa027300e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/4d763ca4c925f647b248b9fa01b5f47aa3685d62", - "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62", + "url": "https://api.github.com/repos/doctrine/orm/zipball/75b4b88c5b7cebc24ed7251a20c2a5aa027300e1", + "reference": "75b4b88c5b7cebc24ed7251a20c2a5aa027300e1", "shasum": "" }, "require": { - "doctrine/annotations": "^1.8", - "doctrine/cache": "^1.9.1", + "composer/package-versions-deprecated": "^1.8", + "doctrine/annotations": "^1.13", + "doctrine/cache": "^1.11.3|^2.0.3", "doctrine/collections": "^1.5", - "doctrine/common": "^2.11", - "doctrine/dbal": "^2.9.3", + "doctrine/common": "^3.0.3", + "doctrine/dbal": "^2.13.0", + "doctrine/deprecations": "^0.5.3", "doctrine/event-manager": "^1.1", + "doctrine/inflector": "^1.4|^2.0", "doctrine/instantiator": "^1.3", - "doctrine/persistence": "^1.2", + "doctrine/lexer": "^1.0", + "doctrine/persistence": "^2.2", "ext-pdo": "*", - "php": "^7.1", - "symfony/console": "^3.0|^4.0|^5.0" + "php": "^7.1|^8.0", + "psr/cache": "^1 || ^2 || ^3", + "symfony/console": "^3.0|^4.0|^5.0|^6.0" }, "require-dev": { - "doctrine/coding-standard": "^5.0", - "phpunit/phpunit": "^7.5", - "symfony/yaml": "^3.4|^4.0|^5.0" + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^0.12.83", + "phpunit/phpunit": "^7.5|^8.5|^9.4", + "squizlabs/php_codesniffer": "3.6.0", + "symfony/cache": "^4.4|^5.2", + "symfony/yaml": "^3.4|^4.0|^5.0|^6.0", + "vimeo/psalm": "4.7.0" }, "suggest": { + "symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0", "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" }, "bin": [ "bin/doctrine" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\ORM\\": "lib/Doctrine/ORM" @@ -984,44 +1404,48 @@ "database", "orm" ], - "time": "2019-11-19T08:38:05+00:00" + "support": { + "issues": "https://github.com/doctrine/orm/issues", + "source": "https://github.com/doctrine/orm/tree/2.9.2" + }, + "time": "2021-05-31T09:53:14+00:00" }, { "name": "doctrine/persistence", - "version": "1.3.3", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "99b196bbd4715a94fa100fac664a351ffa46d6a5" + "reference": "d138f3ab5f761055cab1054070377cfd3222e368" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/99b196bbd4715a94fa100fac664a351ffa46d6a5", - "reference": "99b196bbd4715a94fa100fac664a351ffa46d6a5", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/d138f3ab5f761055cab1054070377cfd3222e368", + "reference": "d138f3ab5f761055cab1054070377cfd3222e368", "shasum": "" }, "require": { "doctrine/annotations": "^1.0", - "doctrine/cache": "^1.0", + "doctrine/cache": "^1.11 || ^2.0", "doctrine/collections": "^1.0", + "doctrine/deprecations": "^0.5.3", "doctrine/event-manager": "^1.0", - "doctrine/reflection": "^1.0", - "php": "^7.1" + "php": "^7.1 || ^8.0", + "psr/cache": "^1.0|^2.0|^3.0" }, "conflict": { "doctrine/common": "<2.10@dev" }, "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan": "^0.11", - "phpunit/phpunit": "^7.0" + "composer/package-versions-deprecated": "^1.11", + "doctrine/coding-standard": "^6.0 || ^9.0", + "doctrine/common": "^3.0", + "phpstan/phpstan": "0.12.84", + "phpunit/phpunit": "^7.5.20 || ^8.0 || ^9.0", + "symfony/cache": "^4.4|^5.0", + "vimeo/psalm": "4.7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Common\\": "lib/Doctrine/Common", @@ -1067,44 +1491,44 @@ "orm", "persistence" ], - "time": "2019-12-13T10:43:02+00:00" + "support": { + "issues": "https://github.com/doctrine/persistence/issues", + "source": "https://github.com/doctrine/persistence/tree/2.2.1" + }, + "time": "2021-05-19T07:07:01+00:00" }, { - "name": "doctrine/reflection", - "version": "v1.0.0", + "name": "doctrine/sql-formatter", + "version": "1.1.1", "source": { "type": "git", - "url": "https://github.com/doctrine/reflection.git", - "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" + "url": "https://github.com/doctrine/sql-formatter.git", + "reference": "56070bebac6e77230ed7d306ad13528e60732871" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", - "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/56070bebac6e77230ed7d306ad13528e60732871", + "reference": "56070bebac6e77230ed7d306ad13528e60732871", "shasum": "" }, "require": { - "doctrine/annotations": "^1.0", - "ext-tokenizer": "*", - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^4.0", - "doctrine/common": "^2.8", - "phpstan/phpstan": "^0.9.2", - "phpstan/phpstan-phpunit": "^0.9.4", - "phpunit/phpunit": "^7.0", - "squizlabs/php_codesniffer": "^3.0" + "bamarni/composer-bin-plugin": "^1.4" }, + "bin": [ + "bin/sql-formatter" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" + "Doctrine\\SqlFormatter\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1113,67 +1537,64 @@ ], "authors": [ { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "http://jeremydorn.com/" } ], - "description": "Doctrine Reflection component", - "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/doctrine/sql-formatter/", "keywords": [ - "reflection" + "highlight", + "sql" ], - "time": "2018-06-14T14:45:07+00:00" + "support": { + "issues": "https://github.com/doctrine/sql-formatter/issues", + "source": "https://github.com/doctrine/sql-formatter/tree/1.1.x" + }, + "time": "2020-07-30T16:57:33+00:00" }, { - "name": "jdorn/sql-formatter", - "version": "v1.2.17", + "name": "friendsofphp/proxy-manager-lts", + "version": "v1.0.5", "source": { "type": "git", - "url": "https://github.com/jdorn/sql-formatter.git", - "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc" + "url": "https://github.com/FriendsOfPHP/proxy-manager-lts.git", + "reference": "006aa5d32f887a4db4353b13b5b5095613e0611f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jdorn/sql-formatter/zipball/64990d96e0959dff8e059dfcdc1af130728d92bc", - "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc", + "url": "https://api.github.com/repos/FriendsOfPHP/proxy-manager-lts/zipball/006aa5d32f887a4db4353b13b5b5095613e0611f", + "reference": "006aa5d32f887a4db4353b13b5b5095613e0611f", "shasum": "" }, "require": { - "php": ">=5.2.4" + "laminas/laminas-code": "~3.4.1|^4.0", + "php": ">=7.1", + "symfony/filesystem": "^4.4.17|^5.0|^6.0" + }, + "conflict": { + "laminas/laminas-stdlib": "<3.2.1", + "zendframework/zend-stdlib": "<3.2.1" + }, + "replace": { + "ocramius/proxy-manager": "^2.1" }, "require-dev": { - "phpunit/phpunit": "3.7.*" + "ext-phar": "*", + "symfony/phpunit-bridge": "^5.2|^6.0" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" + "thanks": { + "name": "ocramius/proxy-manager", + "url": "https://github.com/Ocramius/ProxyManager" } }, "autoload": { - "classmap": [ - "lib" - ] + "psr-4": { + "ProxyManager\\": "src/ProxyManager" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1181,56 +1602,82 @@ ], "authors": [ { - "name": "Jeremy Dorn", - "email": "jeremy@jeremydorn.com", - "homepage": "http://jeremydorn.com/" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.io/" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" } ], - "description": "a PHP SQL highlighting library", - "homepage": "https://github.com/jdorn/sql-formatter/", + "description": "Adding support for a wider range of PHP versions to ocramius/proxy-manager", + "homepage": "https://github.com/FriendsOfPHP/proxy-manager-lts", "keywords": [ - "highlight", - "sql" + "aop", + "lazy loading", + "proxy", + "proxy pattern", + "service proxies" ], - "time": "2014-01-12T16:20:24+00:00" + "support": { + "issues": "https://github.com/FriendsOfPHP/proxy-manager-lts/issues", + "source": "https://github.com/FriendsOfPHP/proxy-manager-lts/tree/v1.0.5" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ocramius/proxy-manager", + "type": "tidelift" + } + ], + "time": "2021-05-22T16:11:15+00:00" }, { - "name": "ocramius/package-versions", - "version": "1.5.1", + "name": "guzzlehttp/guzzle", + "version": "6.5.5", "source": { "type": "git", - "url": "https://github.com/Ocramius/PackageVersions.git", - "reference": "1d32342b8c1eb27353c8887c366147b4c2da673c" + "url": "https://github.com/guzzle/guzzle.git", + "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/1d32342b8c1eb27353c8887c366147b4c2da673c", - "reference": "1d32342b8c1eb27353c8887c366147b4c2da673c", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/9d4290de1cfd701f38099ef7e183b64b4b7b0c5e", + "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0.0", - "php": "^7.3.0" + "ext-json": "*", + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.6.1", + "php": ">=5.5", + "symfony/polyfill-intl-idn": "^1.17.0" }, "require-dev": { - "composer/composer": "^1.8.6", - "doctrine/coding-standard": "^6.0.0", - "ext-zip": "*", - "infection/infection": "^0.13.4", - "phpunit/phpunit": "^8.2.5", - "vimeo/psalm": "^3.4.9" + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.1" }, - "type": "composer-plugin", + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", "extra": { - "class": "PackageVersions\\Installer", "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "6.5-dev" } }, "autoload": { "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } + "GuzzleHttp\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1238,65 +1685,61 @@ ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "time": "2019-07-17T15:49:50+00:00" + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/6.5" + }, + "time": "2020-06-16T21:01:06+00:00" }, { - "name": "ocramius/proxy-manager", - "version": "2.5.1", + "name": "guzzlehttp/promises", + "version": "1.4.1", "source": { "type": "git", - "url": "https://github.com/Ocramius/ProxyManager.git", - "reference": "b7bac968eef945322d1e28d7e833b6a549a6da27" + "url": "https://github.com/guzzle/promises.git", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/b7bac968eef945322d1e28d7e833b6a549a6da27", - "reference": "b7bac968eef945322d1e28d7e833b6a549a6da27", + "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d", "shasum": "" }, "require": { - "ocramius/package-versions": "^1.5.1", - "php": "^7.4.0", - "zendframework/zend-code": "^3.3.1" - }, - "conflict": { - "doctrine/annotations": "<1.6.1", - "zendframework/zend-stdlib": "<3.2.1" + "php": ">=5.5" }, "require-dev": { - "couscous/couscous": "^1.7.2", - "doctrine/coding-standard": "^6.0.0", - "ext-phar": "*", - "infection/infection": "^0.13.4", - "nikic/php-parser": "^4.2.2", - "phpbench/phpbench": "^0.16.9", - "phpunit/phpunit": "^8.3.3", - "slevomat/coding-standard": "^5.0.4", - "squizlabs/php_codesniffer": "^3.4.2", - "symfony/console": "^4.3.3", - "vimeo/psalm": "3.4.11" - }, - "suggest": { - "ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects", - "zendframework/zend-json": "To have the JsonRpc adapter (Remote Object feature)", - "zendframework/zend-soap": "To have the Soap adapter (Remote Object feature)", - "zendframework/zend-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)" + "symfony/phpunit-bridge": "^4.4 || ^5.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "1.4-dev" } }, "autoload": { "psr-4": { - "ProxyManager\\": "src/ProxyManager" - } + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1304,49 +1747,63 @@ ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.io/" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies", - "homepage": "https://github.com/Ocramius/ProxyManager", + "description": "Guzzle promises library", "keywords": [ - "aop", - "lazy loading", - "proxy", - "proxy pattern", - "service proxies" + "promise" ], - "time": "2019-12-17T09:22:43+00:00" + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.4.1" + }, + "time": "2021-03-07T09:25:29+00:00" }, { - "name": "psr/cache", - "version": "1.0.1", + "name": "guzzlehttp/psr7", + "version": "1.8.2", "source": { "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + "url": "https://github.com/guzzle/psr7.git", + "reference": "dc960a912984efb74d0a90222870c72c87f10c91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91", + "reference": "dc960a912984efb74d0a90222870c72c87f10c91", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-zlib": "*", + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.7-dev" } }, "autoload": { "psr-4": { - "Psr\\Cache\\": "src/" - } + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1354,44 +1811,61 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" } ], - "description": "Common interface for caching libraries", + "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ - "cache", - "psr", - "psr-6" + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" ], - "time": "2016-08-06T20:24:11+00:00" + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/1.8.2" + }, + "time": "2021-04-26T09:17:50+00:00" }, { - "name": "psr/container", + "name": "http-interop/http-factory-guzzle", "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + "url": "https://github.com/http-interop/http-factory-guzzle.git", + "reference": "34861658efb9899a6618cef03de46e2a52c80fc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "url": "https://api.github.com/repos/http-interop/http-factory-guzzle/zipball/34861658efb9899a6618cef03de46e2a52c80fc0", + "reference": "34861658efb9899a6618cef03de46e2a52c80fc0", "shasum": "" }, "require": { - "php": ">=5.3.0" + "guzzlehttp/psr7": "^1.4.2", + "psr/http-factory": "^1.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "provide": { + "psr/http-factory-implementation": "^1.0" }, + "require-dev": { + "http-interop/http-factory-tests": "^0.5", + "phpunit/phpunit": "^6.5" + }, + "type": "library", "autoload": { "psr-4": { - "Psr\\Container\\": "src/" + "Http\\Factory\\Guzzle\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1404,43 +1878,47 @@ "homepage": "http://www.php-fig.org/" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "An HTTP Factory using Guzzle PSR7", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "factory", + "http", + "psr-17", + "psr-7" ], - "time": "2017-02-14T16:28:37+00:00" + "support": { + "issues": "https://github.com/http-interop/http-factory-guzzle/issues", + "source": "https://github.com/http-interop/http-factory-guzzle/tree/master" + }, + "time": "2018-07-31T19:32:56+00:00" }, { - "name": "psr/event-dispatcher", - "version": "1.0.0", + "name": "ivanstan/tle-php", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + "url": "https://github.com/ivanstan/tle-php.git", + "reference": "45255e18e2730938e8428f4f232d1943b9893991" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "url": "https://api.github.com/repos/ivanstan/tle-php/zipball/45255e18e2730938e8428f4f232d1943b9893991", + "reference": "45255e18e2730938e8428f4f232d1943b9893991", "shasum": "" }, "require": { - "php": ">=7.2.0" + "ext-json": "*", + "guzzlehttp/guzzle": "^6.5", + "myclabs/php-enum": "^1.7", + "php": "^7.4|^8.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "require-dev": { + "phpunit/phpunit": "^8" }, + "default-branch": true, + "type": "library", "autoload": { "psr-4": { - "Psr\\EventDispatcher\\": "src/" + "Ivanstan\\Tle\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1449,44 +1927,51 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Ivan Stanojevic", + "email": "ivan.stanojevic@protonmail.com" } ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "time": "2019-01-08T18:20:26+00:00" + "description": "TLE Framework written in PHP and client to NASA TLE API.", + "support": { + "issues": "https://github.com/ivanstan/tle-php/issues", + "source": "https://github.com/ivanstan/tle-php/tree/master" + }, + "time": "2021-05-27T19:24:24+00:00" }, { - "name": "psr/log", - "version": "1.1.2", + "name": "jean85/pretty-package-versions", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "694492c653c518456af2805f04eec445b997ed1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/694492c653c518456af2805f04eec445b997ed1f", + "reference": "694492c653c518456af2805f04eec445b997ed1f", "shasum": "" }, "require": { - "php": ">=5.3.0" + "composer-runtime-api": "^2.0.0", + "php": "^7.1|^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.17", + "jean85/composer-provided-replaced-stub-package": "^1.0", + "phpstan/phpstan": "^0.12.66", + "phpunit/phpunit": "^7.5|^8.5|^9.4", + "vimeo/psalm": "^4.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Jean85\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1495,212 +1980,283 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "A library to get pretty versions strings of installed dependencies", "keywords": [ - "log", - "psr", - "psr-3" + "composer", + "package", + "release", + "versions" ], - "time": "2019-11-01T11:05:21+00:00" + "support": { + "issues": "https://github.com/Jean85/pretty-package-versions/issues", + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.4" + }, + "time": "2021-05-26T08:46:42+00:00" }, { - "name": "symfony/apache-pack", - "version": "v1.0.1", + "name": "laminas/laminas-code", + "version": "4.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/apache-pack.git", - "reference": "3aa5818d73ad2551281fc58a75afd9ca82622e6c" + "url": "https://github.com/laminas/laminas-code.git", + "reference": "1beb4447f9efd26041eba7eff50614e798c353fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/apache-pack/zipball/3aa5818d73ad2551281fc58a75afd9ca82622e6c", - "reference": "3aa5818d73ad2551281fc58a75afd9ca82622e6c", + "url": "https://api.github.com/repos/laminas/laminas-code/zipball/1beb4447f9efd26041eba7eff50614e798c353fd", + "reference": "1beb4447f9efd26041eba7eff50614e798c353fd", "shasum": "" }, - "type": "symfony-pack", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A pack for Apache support in Symfony", - "time": "2017-12-12T01:46:35+00:00" - }, - { - "name": "symfony/asset", - "version": "v5.0.2", + "require": { + "laminas/laminas-eventmanager": "^3.3", + "php": "^7.4 || ~8.0.0" + }, + "conflict": { + "phpspec/prophecy": "<1.9.0" + }, + "replace": { + "zendframework/zend-code": "self.version" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4", + "ext-phar": "*", + "laminas/laminas-coding-standard": "^2.1.4", + "laminas/laminas-stdlib": "^3.3.0", + "phpunit/phpunit": "^9.4.2", + "psalm/plugin-phpunit": "^0.14.0", + "vimeo/psalm": "^4.3.1" + }, + "suggest": { + "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", + "laminas/laminas-stdlib": "Laminas\\Stdlib component", + "laminas/laminas-zendframework-bridge": "A bridge with Zend Framework" + }, + "type": "library", + "autoload": { + "psr-4": { + "Laminas\\Code\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Extensions to the PHP Reflection API, static code scanning, and code generation", + "homepage": "https://laminas.dev", + "keywords": [ + "code", + "laminas", + "laminasframework" + ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-code/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-code/issues", + "rss": "https://github.com/laminas/laminas-code/releases.atom", + "source": "https://github.com/laminas/laminas-code" + }, + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2021-05-12T12:41:03+00:00" + }, + { + "name": "laminas/laminas-eventmanager", + "version": "3.3.1", "source": { "type": "git", - "url": "https://github.com/symfony/asset.git", - "reference": "6b66969b9f5cd53c1ce69bdc651aa962f211b6b6" + "url": "https://github.com/laminas/laminas-eventmanager.git", + "reference": "966c859b67867b179fde1eff0cd38df51472ce4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset/zipball/6b66969b9f5cd53c1ce69bdc651aa962f211b6b6", - "reference": "6b66969b9f5cd53c1ce69bdc651aa962f211b6b6", + "url": "https://api.github.com/repos/laminas/laminas-eventmanager/zipball/966c859b67867b179fde1eff0cd38df51472ce4a", + "reference": "966c859b67867b179fde1eff0cd38df51472ce4a", "shasum": "" }, "require": { - "php": "^7.2.5" + "laminas/laminas-zendframework-bridge": "^1.0", + "php": "^7.3 || ^8.0" + }, + "replace": { + "zendframework/zend-eventmanager": "^3.2.1" }, "require-dev": { - "symfony/http-foundation": "^4.4|^5.0", - "symfony/http-kernel": "^4.4|^5.0" + "container-interop/container-interop": "^1.1", + "laminas/laminas-coding-standard": "~1.0.0", + "laminas/laminas-stdlib": "^2.7.3 || ^3.0", + "phpbench/phpbench": "^0.17.1", + "phpunit/phpunit": "^8.5.8" }, "suggest": { - "symfony/http-foundation": "" + "container-interop/container-interop": "^1.1, to use the lazy listeners feature", + "laminas/laminas-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Component\\Asset\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Laminas\\EventManager\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, + "description": "Trigger and listen to events within a PHP application", + "homepage": "https://laminas.dev", + "keywords": [ + "event", + "eventmanager", + "events", + "laminas" + ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-eventmanager/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-eventmanager/issues", + "rss": "https://github.com/laminas/laminas-eventmanager/releases.atom", + "source": "https://github.com/laminas/laminas-eventmanager" + }, + "funding": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" } ], - "description": "Symfony Asset Component", - "homepage": "https://symfony.com", - "time": "2019-11-18T17:27:11+00:00" + "time": "2021-03-08T15:24:29+00:00" }, { - "name": "symfony/browser-kit", - "version": "v5.0.2", + "name": "laminas/laminas-zendframework-bridge", + "version": "1.2.0", "source": { "type": "git", - "url": "https://github.com/symfony/browser-kit.git", - "reference": "a195f83b0ba20e622a5baa726af96826b8f5616b" + "url": "https://github.com/laminas/laminas-zendframework-bridge.git", + "reference": "6cccbddfcfc742eb02158d6137ca5687d92cee32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/a195f83b0ba20e622a5baa726af96826b8f5616b", - "reference": "a195f83b0ba20e622a5baa726af96826b8f5616b", + "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6cccbddfcfc742eb02158d6137ca5687d92cee32", + "reference": "6cccbddfcfc742eb02158d6137ca5687d92cee32", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/dom-crawler": "^4.4|^5.0" + "php": "^7.3 || ^8.0" }, "require-dev": { - "symfony/css-selector": "^4.4|^5.0", - "symfony/http-client": "^4.4|^5.0", - "symfony/mime": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0" - }, - "suggest": { - "symfony/process": "" + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3", + "psalm/plugin-phpunit": "^0.15.1", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.6" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "5.0-dev" + "laminas": { + "module": "Laminas\\ZendFrameworkBridge" } }, "autoload": { + "files": [ + "src/autoload.php" + ], "psr-4": { - "Symfony\\Component\\BrowserKit\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Laminas\\ZendFrameworkBridge\\": "src//" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, + "description": "Alias legacy ZF class names to Laminas Project equivalents.", + "keywords": [ + "ZendFramework", + "autoloading", + "laminas", + "zf" + ], + "support": { + "forum": "https://discourse.laminas.dev/", + "issues": "https://github.com/laminas/laminas-zendframework-bridge/issues", + "rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom", + "source": "https://github.com/laminas/laminas-zendframework-bridge" + }, + "funding": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" } ], - "description": "Symfony BrowserKit Component", - "homepage": "https://symfony.com", - "time": "2019-11-18T17:27:11+00:00" + "time": "2021-02-25T21:54:58+00:00" }, { - "name": "symfony/cache", - "version": "v5.0.2", + "name": "monolog/monolog", + "version": "2.2.0", "source": { "type": "git", - "url": "https://github.com/symfony/cache.git", - "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9" + "url": "https://github.com/Seldaek/monolog.git", + "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/6e8d978878ae5de705ec9fabbb6011cc18776bc9", - "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1cb1cde8e8dd0f70cc0fe51354a59acad9302084", + "reference": "1cb1cde8e8dd0f70cc0fe51354a59acad9302084", "shasum": "" }, "require": { - "php": "^7.2.5", - "psr/cache": "~1.0", - "psr/log": "~1.0", - "symfony/cache-contracts": "^1.1.7|^2", - "symfony/service-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0" - }, - "conflict": { - "doctrine/dbal": "<2.5", - "symfony/dependency-injection": "<4.4", - "symfony/http-kernel": "<4.4", - "symfony/var-dumper": "<4.4" + "php": ">=7.2", + "psr/log": "^1.0.1" }, "provide": { - "psr/cache-implementation": "1.0", - "psr/simple-cache-implementation": "1.0", - "symfony/cache-implementation": "1.0" + "psr/log-implementation": "1.0.0" }, "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/cache": "~1.6", - "doctrine/dbal": "~2.5", - "predis/predis": "~1.1", - "psr/simple-cache": "^1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0" + "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7", + "graylog2/gelf-php": "^1.4.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4", + "php-console/php-console": "^3.1.3", + "phpspec/prophecy": "^1.6.1", + "phpstan/phpstan": "^0.12.59", + "phpunit/phpunit": "^8.5", + "predis/predis": "^1.1", + "rollbar/rollbar": "^1.3", + "ruflin/elastica": ">=0.90 <7.0.1", + "swiftmailer/swiftmailer": "^5.3|^6.0" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "php-console/php-console": "Allow sending log messages to Google Chrome", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "2.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Cache\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Monolog\\": "src/Monolog" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1708,52 +2264,61 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" } ], - "description": "Symfony Cache component with PSR-6, PSR-16, and tags", - "homepage": "https://symfony.com", + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", "keywords": [ - "caching", - "psr6" + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } ], - "time": "2019-12-12T13:03:32+00:00" + "time": "2020-12-14T13:15:25+00:00" }, { - "name": "symfony/cache-contracts", - "version": "v2.0.1", + "name": "myclabs/php-enum", + "version": "1.8.0", "source": { "type": "git", - "url": "https://github.com/symfony/cache-contracts.git", - "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16" + "url": "https://github.com/myclabs/php-enum.git", + "reference": "46cf3d8498b095bd33727b13fd5707263af99421" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", - "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/46cf3d8498b095bd33727b13fd5707263af99421", + "reference": "46cf3d8498b095bd33727b13fd5707263af99421", "shasum": "" }, "require": { - "php": "^7.2.5", - "psr/cache": "^1.0" + "ext-json": "*", + "php": "^7.3 || ^8.0" }, - "suggest": { - "symfony/cache-implementation": "" + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.5.1" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Contracts\\Cache\\": "" + "MyCLabs\\Enum\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1762,71 +2327,81 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" } ], - "description": "Generic abstractions related to caching", - "homepage": "https://symfony.com", + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "enum" + ], + "support": { + "issues": "https://github.com/myclabs/php-enum/issues", + "source": "https://github.com/myclabs/php-enum/tree/1.8.0" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", + "type": "tidelift" + } ], - "time": "2019-11-18T17:27:11+00:00" + "time": "2021-02-15T16:11:48+00:00" }, { - "name": "symfony/config", - "version": "v5.0.2", + "name": "php-http/client-common", + "version": "2.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "7f930484966350906185ba0a604728f7898b7ba0" + "url": "https://github.com/php-http/client-common.git", + "reference": "e37e46c610c87519753135fb893111798c69076a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/7f930484966350906185ba0a604728f7898b7ba0", - "reference": "7f930484966350906185ba0a604728f7898b7ba0", + "url": "https://api.github.com/repos/php-http/client-common/zipball/e37e46c610c87519753135fb893111798c69076a", + "reference": "e37e46c610c87519753135fb893111798c69076a", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/filesystem": "^4.4|^5.0", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/finder": "<4.4" + "php": "^7.1 || ^8.0", + "php-http/httplug": "^2.0", + "php-http/message": "^1.6", + "php-http/message-factory": "^1.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "symfony/options-resolver": "^2.6 || ^3.4.20 || ~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0", + "symfony/polyfill-php80": "^1.17" }, "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/messenger": "^4.4|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/yaml": "^4.4|^5.0" + "doctrine/instantiator": "^1.1", + "guzzlehttp/psr7": "^1.4", + "nyholm/psr7": "^1.2", + "phpspec/phpspec": "^5.1 || ^6.0", + "phpspec/prophecy": "^1.10.2", + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3" }, "suggest": { - "symfony/yaml": "To use the yaml reference dumper" + "ext-json": "To detect JSON responses with the ContentTypePlugin", + "ext-libxml": "To detect XML responses with the ContentTypePlugin", + "php-http/cache-plugin": "PSR-6 Cache plugin", + "php-http/logger-plugin": "PSR-3 Logger plugin", + "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "2.3.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Http\\Client\\Common\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1834,75 +2409,64 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "Symfony Config Component", - "homepage": "https://symfony.com", - "time": "2019-12-18T13:50:31+00:00" + "description": "Common HTTP Client implementations and tools for HTTPlug", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "common", + "http", + "httplug" + ], + "support": { + "issues": "https://github.com/php-http/client-common/issues", + "source": "https://github.com/php-http/client-common/tree/2.3.0" + }, + "time": "2020-07-21T10:04:13+00:00" }, { - "name": "symfony/console", - "version": "v5.0.2", + "name": "php-http/discovery", + "version": "1.14.0", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47" + "url": "https://github.com/php-http/discovery.git", + "reference": "778f722e29250c1fac0bbdef2c122fa5d038c9eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/fe6e3cd889ca64172d7a742a2eb058541404ef47", - "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47", + "url": "https://api.github.com/repos/php-http/discovery/zipball/778f722e29250c1fac0bbdef2c122fa5d038c9eb", + "reference": "778f722e29250c1fac0bbdef2c122fa5d038c9eb", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", - "symfony/service-contracts": "^1.1|^2" + "php": "^7.1 || ^8.0" }, "conflict": { - "symfony/dependency-injection": "<4.4", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0" + "nyholm/psr7": "<1.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/lock": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0" + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1", + "puli/composer-plugin": "1.0.0-beta10" }, "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "1.9-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Http\\Discovery\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1910,72 +2474,61 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2019-12-17T13:20:22+00:00" + "description": "Finds installed HTTPlug implementations and PSR-7 message factories", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr7" + ], + "support": { + "issues": "https://github.com/php-http/discovery/issues", + "source": "https://github.com/php-http/discovery/tree/1.14.0" + }, + "time": "2021-06-01T14:30:21+00:00" }, { - "name": "symfony/dependency-injection", - "version": "v5.0.2", + "name": "php-http/httplug", + "version": "2.2.0", "source": { "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2" + "url": "https://github.com/php-http/httplug.git", + "reference": "191a0a1b41ed026b717421931f8d3bd2514ffbf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f9dbfbf487d08f60b1c83220edcd16559d1e40a2", - "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2", + "url": "https://api.github.com/repos/php-http/httplug/zipball/191a0a1b41ed026b717421931f8d3bd2514ffbf9", + "reference": "191a0a1b41ed026b717421931f8d3bd2514ffbf9", "shasum": "" }, "require": { - "php": "^7.2.5", - "psr/container": "^1.0", - "symfony/service-contracts": "^1.1.6|^2" - }, - "conflict": { - "symfony/config": "<5.0", - "symfony/finder": "<4.4", - "symfony/proxy-manager-bridge": "<4.4", - "symfony/yaml": "<4.4" - }, - "provide": { - "psr/container-implementation": "1.0", - "symfony/service-implementation": "1.0" + "php": "^7.1 || ^8.0", + "php-http/promise": "^1.1", + "psr/http-client": "^1.0", + "psr/http-message": "^1.0" }, "require-dev": { - "symfony/config": "^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" + "friends-of-phpspec/phpspec-code-coverage": "^4.1", + "phpspec/phpspec": "^5.1 || ^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Http\\Client\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1983,94 +2536,76 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], - "description": "Symfony DependencyInjection Component", - "homepage": "https://symfony.com", - "time": "2019-12-19T16:01:11+00:00" + "description": "HTTPlug, the HTTP client abstraction for PHP", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "http" + ], + "support": { + "issues": "https://github.com/php-http/httplug/issues", + "source": "https://github.com/php-http/httplug/tree/master" + }, + "time": "2020-07-13T15:43:23+00:00" }, { - "name": "symfony/doctrine-bridge", - "version": "v5.0.2", + "name": "php-http/message", + "version": "1.11.1", "source": { "type": "git", - "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2" + "url": "https://github.com/php-http/message.git", + "reference": "887734d9c515ad9a564f6581a682fff87a6253cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/0bdb2d31741cacacb95130d28fbac939c4d574f2", - "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2", + "url": "https://api.github.com/repos/php-http/message/zipball/887734d9c515ad9a564f6581a682fff87a6253cc", + "reference": "887734d9c515ad9a564f6581a682fff87a6253cc", "shasum": "" }, "require": { - "doctrine/event-manager": "~1.0", - "doctrine/persistence": "^1.3", - "php": "^7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2" + "clue/stream-filter": "^1.5", + "php": "^7.1 || ^8.0", + "php-http/message-factory": "^1.0.2", + "psr/http-message": "^1.0" }, - "conflict": { - "phpunit/phpunit": "<5.4.3", - "symfony/dependency-injection": "<4.4", - "symfony/form": "<5", - "symfony/http-kernel": "<5", - "symfony/messenger": "<4.4", - "symfony/property-info": "<5", - "symfony/security-bundle": "<5", - "symfony/security-core": "<5", - "symfony/validator": "<5.0.2" + "provide": { + "php-http/message-factory-implementation": "1.0" }, "require-dev": { - "doctrine/annotations": "~1.7", - "doctrine/cache": "~1.6", - "doctrine/collections": "~1.0", - "doctrine/data-fixtures": "1.0.*", - "doctrine/dbal": "~2.4", - "doctrine/orm": "^2.6.3", - "doctrine/reflection": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/form": "^5.0", - "symfony/http-kernel": "^5.0", - "symfony/messenger": "^4.4|^5.0", - "symfony/property-access": "^4.4|^5.0", - "symfony/property-info": "^5.0", - "symfony/proxy-manager-bridge": "^4.4|^5.0", - "symfony/security-core": "^5.0", - "symfony/stopwatch": "^4.4|^5.0", - "symfony/translation": "^4.4|^5.0", - "symfony/validator": "^5.0.2", - "symfony/var-dumper": "^4.4|^5.0" + "ergebnis/composer-normalize": "^2.6", + "ext-zlib": "*", + "guzzlehttp/psr7": "^1.0", + "laminas/laminas-diactoros": "^2.0", + "phpspec/phpspec": "^5.1 || ^6.3", + "slim/slim": "^3.0" }, "suggest": { - "doctrine/data-fixtures": "", - "doctrine/dbal": "", - "doctrine/orm": "", - "symfony/form": "", - "symfony/property-info": "", - "symfony/validator": "" + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "laminas/laminas-diactoros": "Used with Diactoros Factories", + "slim/slim": "Used with Slim Framework PSR-7 implementation" }, - "type": "symfony-bridge", + "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "1.10-dev" } }, "autoload": { "psr-4": { - "Symfony\\Bridge\\Doctrine\\": "" + "Http\\Message\\": "src/" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "src/filters.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2079,60 +2614,51 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "Symfony Doctrine Bridge", - "homepage": "https://symfony.com", - "time": "2019-12-19T12:10:29+00:00" + "description": "HTTP Message related tools", + "homepage": "http://php-http.org", + "keywords": [ + "http", + "message", + "psr-7" + ], + "support": { + "issues": "https://github.com/php-http/message/issues", + "source": "https://github.com/php-http/message/tree/1.11.1" + }, + "time": "2021-05-24T18:11:08+00:00" }, { - "name": "symfony/dom-crawler", - "version": "v5.0.2", + "name": "php-http/message-factory", + "version": "v1.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/dom-crawler.git", - "reference": "0a0a73a0836926898b6fcd6817fe697487a73d97" + "url": "https://github.com/php-http/message-factory.git", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/0a0a73a0836926898b6fcd6817fe697487a73d97", - "reference": "0a0a73a0836926898b6fcd6817fe697487a73d97", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "masterminds/html5": "<2.6" - }, - "require-dev": { - "masterminds/html5": "^2.6", - "symfony/css-selector": "^4.4|^5.0" - }, - "suggest": { - "symfony/css-selector": "" + "php": ">=5.4", + "psr/http-message": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "1.0-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\DomCrawler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Http\\Message\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2140,51 +2666,56 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "Symfony DomCrawler Component", - "homepage": "https://symfony.com", - "time": "2019-11-18T17:27:11+00:00" + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "stream", + "uri" + ], + "support": { + "issues": "https://github.com/php-http/message-factory/issues", + "source": "https://github.com/php-http/message-factory/tree/master" + }, + "time": "2015-12-19T14:08:53+00:00" }, { - "name": "symfony/dotenv", - "version": "v5.0.2", + "name": "php-http/promise", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/symfony/dotenv.git", - "reference": "7e1bc9024edd9157264e388080df2533306894d3" + "url": "https://github.com/php-http/promise.git", + "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/7e1bc9024edd9157264e388080df2533306894d3", - "reference": "7e1bc9024edd9157264e388080df2533306894d3", + "url": "https://api.github.com/repos/php-http/promise/zipball/4c4c1f9b7289a2ec57cde7f1e9762a5789506f88", + "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88", "shasum": "" }, "require": { - "php": "^7.2.5" + "php": "^7.1 || ^8.0" }, "require-dev": { - "symfony/process": "^4.4|^5.0" + "friends-of-phpspec/phpspec-code-coverage": "^4.3.2", + "phpspec/phpspec": "^5.1.2 || ^6.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "1.1-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Dotenv\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Http\\Promise\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2192,59 +2723,52 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "Registers environment variables from a .env file", - "homepage": "https://symfony.com", + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", "keywords": [ - "dotenv", - "env", - "environment" + "promise" ], - "time": "2019-12-19T16:01:11+00:00" + "support": { + "issues": "https://github.com/php-http/promise/issues", + "source": "https://github.com/php-http/promise/tree/1.1.0" + }, + "time": "2020-07-07T09:29:14+00:00" }, { - "name": "symfony/error-handler", - "version": "v5.0.2", + "name": "psr/cache", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/error-handler.git", - "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5" + "url": "https://github.com/php-fig/cache.git", + "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/460863313bd3212d7c38e1b40602cbcfeeeea4a5", - "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5", + "url": "https://api.github.com/repos/php-fig/cache/zipball/213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", + "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", "shasum": "" }, "require": { - "php": "^7.2.5", - "psr/log": "^1.0", - "symfony/var-dumper": "^4.4|^5.0" - }, - "require-dev": { - "symfony/http-kernel": "^4.4|^5.0", - "symfony/serializer": "^4.4|^5.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\ErrorHandler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Psr\\Cache\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2252,69 +2776,43 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "Symfony ErrorHandler Component", - "homepage": "https://symfony.com", - "time": "2019-12-16T14:48:47+00:00" + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/2.0.0" + }, + "time": "2021-02-03T23:23:37+00:00" }, { - "name": "symfony/event-dispatcher", - "version": "v5.0.2", + "name": "psr/container", + "version": "1.1.1", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "7b738a51645e10f864cc25c24d232fb03f37b475" + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7b738a51645e10f864cc25c24d232fb03f37b475", - "reference": "7b738a51645e10f864cc25c24d232fb03f37b475", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/event-dispatcher-contracts": "^2" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^4.4|^5.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "php": ">=7.2.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Psr\\Container\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2322,48 +2820,51 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2019-11-18T17:27:11+00:00" + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" + }, + "time": "2021-03-05T17:36:06+00:00" }, { - "name": "symfony/event-dispatcher-contracts", - "version": "v2.0.1", + "name": "psr/event-dispatcher", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "af23c2584d4577d54661c434446fb8fbed6025dd" + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/af23c2584d4577d54661c434446fb8fbed6025dd", - "reference": "af23c2584d4577d54661c434446fb8fbed6025dd", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", "shasum": "" }, "require": { - "php": "^7.2.5", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" + "php": ">=7.2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" + "Psr\\EventDispatcher\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2372,57 +2873,50 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", + "description": "Standard interfaces for event handling.", "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "events", + "psr", + "psr-14" ], - "time": "2019-11-18T17:27:11+00:00" + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" }, { - "name": "symfony/filesystem", - "version": "v5.0.2", + "name": "psr/http-client", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6" + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/1d71f670bc5a07b9ccc97dc44f932177a322d4e6", - "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/polyfill-ctype": "~1.8" + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Psr\\Http\\Client\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2430,47 +2924,3007 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "sentry/sdk", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/getsentry/sentry-php-sdk.git", + "reference": "f03133b067fdf03fed09ff03daf3f1d68f5f3673" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/f03133b067fdf03fed09ff03daf3f1d68f5f3673", + "reference": "f03133b067fdf03fed09ff03daf3f1d68f5f3673", + "shasum": "" + }, + "require": { + "http-interop/http-factory-guzzle": "^1.0", + "sentry/sentry": "^3.1", + "symfony/http-client": "^4.3|^5.0" + }, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Sentry", + "email": "accounts@sentry.io" + } + ], + "description": "This is a metapackage shipping sentry/sentry with a recommended HTTP client.", + "homepage": "http://sentry.io", + "keywords": [ + "crash-reporting", + "crash-reports", + "error-handler", + "error-monitoring", + "log", + "logging", + "sentry" + ], + "support": { + "source": "https://github.com/getsentry/sentry-php-sdk/tree/3.1.0" + }, + "funding": [ + { + "url": "https://sentry.io/", + "type": "custom" + }, + { + "url": "https://sentry.io/pricing/", + "type": "custom" + } + ], + "time": "2020-12-01T10:31:45+00:00" + }, + { + "name": "sentry/sentry", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/getsentry/sentry-php.git", + "reference": "3bb122f9fc2bc43a4646e37db79eaf115b35b047" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/3bb122f9fc2bc43a4646e37db79eaf115b35b047", + "reference": "3bb122f9fc2bc43a4646e37db79eaf115b35b047", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "guzzlehttp/promises": "^1.4", + "guzzlehttp/psr7": "^1.7", + "jean85/pretty-package-versions": "^1.5|^2.0.1", + "php": "^7.2|^8.0", + "php-http/async-client-implementation": "^1.0", + "php-http/client-common": "^1.5|^2.0", + "php-http/discovery": "^1.6.1", + "php-http/httplug": "^1.1|^2.0", + "php-http/message": "^1.5", + "psr/http-factory": "^1.0", + "psr/http-message-implementation": "^1.0", + "psr/log": "^1.0", + "symfony/options-resolver": "^3.4.43|^4.4.11|^5.0.11", + "symfony/polyfill-php80": "^1.17", + "symfony/polyfill-uuid": "^1.13.1" + }, + "conflict": { + "php-http/client-common": "1.8.0", + "raven/raven": "*" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.17", + "http-interop/http-factory-guzzle": "^1.0", + "monolog/monolog": "^1.3|^2.0", + "nikic/php-parser": "^4.10.3", + "php-http/mock-client": "^1.3", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^8.5.13|^9.4", + "symfony/phpunit-bridge": "^5.2", + "vimeo/psalm": "^4.2" + }, + "suggest": { + "monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Sentry\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sentry", + "email": "accounts@sentry.io" + } + ], + "description": "A PHP SDK for Sentry (http://sentry.io)", + "homepage": "http://sentry.io", + "keywords": [ + "crash-reporting", + "crash-reports", + "error-handler", + "error-monitoring", + "log", + "logging", + "sentry" + ], + "support": { + "issues": "https://github.com/getsentry/sentry-php/issues", + "source": "https://github.com/getsentry/sentry-php/tree/3.3.0" + }, + "funding": [ + { + "url": "https://sentry.io/", + "type": "custom" + }, + { + "url": "https://sentry.io/pricing/", + "type": "custom" + } + ], + "time": "2021-05-25T18:32:24+00:00" + }, + { + "name": "sentry/sentry-symfony", + "version": "4.1.3", + "source": { + "type": "git", + "url": "https://github.com/getsentry/sentry-symfony.git", + "reference": "d0b85df21f65499db87341648541a526a1f7960d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/getsentry/sentry-symfony/zipball/d0b85df21f65499db87341648541a526a1f7960d", + "reference": "d0b85df21f65499db87341648541a526a1f7960d", + "shasum": "" + }, + "require": { + "jean85/pretty-package-versions": "^1.5 || ^2.0", + "php": "^7.2||^8.0", + "php-http/discovery": "^1.11", + "sentry/sdk": "^3.1", + "symfony/cache-contracts": "^2.4", + "symfony/config": "^3.4.44||^4.4.20||^5.0.11", + "symfony/console": "^3.4.44||^4.4.20||^5.0.11", + "symfony/dependency-injection": "^3.4.44||^4.4.20||^5.0.11", + "symfony/event-dispatcher": "^3.4.44||^4.4.20||^5.0.11", + "symfony/http-kernel": "^3.4.44||^4.4.20||^5.0.11", + "symfony/polyfill-php80": "^1.22", + "symfony/psr-http-message-bridge": "^1.2||^2.0", + "symfony/security-core": "^3.4.44||^4.4.20||^5.0.11" + }, + "require-dev": { + "doctrine/dbal": "^2.10||^3.0", + "doctrine/doctrine-bundle": "^1.12||^2.0", + "friendsofphp/php-cs-fixer": "^2.18", + "jangregor/phpstan-prophecy": "^0.8", + "monolog/monolog": "^1.3||^2.0", + "phpspec/prophecy": "!=1.11.0", + "phpspec/prophecy-phpunit": "^1.1||^2.0", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^8.5||^9.0", + "symfony/browser-kit": "^3.4.44||^4.4.20||^5.0.11", + "symfony/cache": "^3.4.44||^4.4.20||^5.0.11", + "symfony/dom-crawler": "^3.4.44||^4.4.20||^5.0.11", + "symfony/framework-bundle": "^3.4.44||^4.4.20||^5.0.11", + "symfony/messenger": "^4.4.20||^5.0.11", + "symfony/monolog-bundle": "^3.4", + "symfony/phpunit-bridge": "^5.2.6", + "symfony/twig-bundle": "^3.4.44||^4.4.20||^5.0.11", + "symfony/yaml": "^3.4.44||^4.4.20||^5.0.11", + "vimeo/psalm": "^4.3" + }, + "suggest": { + "doctrine/doctrine-bundle": "Allow distributed tracing of database queries using Sentry.", + "monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler.", + "symfony/cache": "Allow distributed tracing of cache pools using Sentry.", + "symfony/twig-bundle": "Allow distributed tracing of Twig template rendering using Sentry." + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev", + "releases/3.2.x": "3.2.x-dev", + "releases/2.x": "2.x-dev", + "releases/1.x": "1.x-dev" + } + }, + "autoload": { + "files": [ + "src/aliases.php" + ], + "psr-4": { + "Sentry\\SentryBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "David Cramer", + "email": "dcramer@gmail.com" + }, + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "Symfony integration for Sentry (http://getsentry.com)", + "homepage": "http://getsentry.com", + "keywords": [ + "errors", + "logging", + "sentry", + "symfony" + ], + "support": { + "issues": "https://github.com/getsentry/sentry-symfony/issues", + "source": "https://github.com/getsentry/sentry-symfony/tree/4.1.3" + }, + "funding": [ + { + "url": "https://sentry.io/", + "type": "custom" + }, + { + "url": "https://sentry.io/pricing/", + "type": "custom" + } + ], + "time": "2021-05-31T07:54:49+00:00" + }, + { + "name": "symfony/apache-pack", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/apache-pack.git", + "reference": "3aa5818d73ad2551281fc58a75afd9ca82622e6c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/apache-pack/zipball/3aa5818d73ad2551281fc58a75afd9ca82622e6c", + "reference": "3aa5818d73ad2551281fc58a75afd9ca82622e6c", + "shasum": "" + }, + "type": "symfony-pack", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A pack for Apache support in Symfony", + "support": { + "issues": "https://github.com/symfony/apache-pack/issues", + "source": "https://github.com/symfony/apache-pack/tree/master" + }, + "time": "2017-12-12T01:46:35+00:00" + }, + { + "name": "symfony/asset", + "version": "v5.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/asset.git", + "reference": "9bd222a8fdd13ecca91384e403247103198f80a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/asset/zipball/9bd222a8fdd13ecca91384e403247103198f80a1", + "reference": "9bd222a8fdd13ecca91384e403247103198f80a1", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/http-foundation": "<5.3" + }, + "require-dev": { + "symfony/http-client": "^4.4|^5.0", + "symfony/http-foundation": "^5.3", + "symfony/http-kernel": "^4.4|^5.0" + }, + "suggest": { + "symfony/http-foundation": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Asset\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/asset/tree/v5.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-07-21T12:40:44+00:00" + }, + { + "name": "symfony/browser-kit", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "379984e25eee9811b0a25a2105e1a2b3b8d9b734" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/379984e25eee9811b0a25a2105e1a2b3b8d9b734", + "reference": "379984e25eee9811b0a25a2105e1a2b3b8d9b734", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/dom-crawler": "^4.4|^5.0" + }, + "require-dev": { + "symfony/css-selector": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/browser-kit/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/cache", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "44fd0f97d1fb198d344f22379dfc56af2221e608" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/44fd0f97d1fb198d344f22379dfc56af2221e608", + "reference": "44fd0f97d1fb198d344f22379dfc56af2221e608", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/cache": "^1.0|^2.0", + "psr/log": "^1.1", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php80": "^1.15", + "symfony/service-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" + }, + "conflict": { + "doctrine/dbal": "<2.10", + "symfony/dependency-injection": "<4.4", + "symfony/http-kernel": "<4.4", + "symfony/var-dumper": "<4.4" + }, + "provide": { + "psr/cache-implementation": "1.0|2.0", + "psr/simple-cache-implementation": "1.0", + "symfony/cache-implementation": "1.0|2.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "^1.6|^2.0", + "doctrine/dbal": "^2.10|^3.0", + "predis/predis": "^1.1", + "psr/simple-cache": "^1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/filesystem": "^4.4|^5.0", + "symfony/http-kernel": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an extended PSR-6, PSR-16 (and tags) implementation", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "support": { + "source": "https://github.com/symfony/cache/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "c0446463729b89dd4fa62e9aeecc80287323615d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/c0446463729b89dd4fa62e9aeecc80287323615d", + "reference": "c0446463729b89dd4fa62e9aeecc80287323615d", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/cache": "^1.0|^2.0|^3.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/cache-contracts/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-23T23:28:01+00:00" + }, + { + "name": "symfony/config", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "9f4a448c2d7fd2c90882dfff930b627ddbe16810" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/9f4a448c2d7fd2c90882dfff930b627ddbe16810", + "reference": "9f4a448c2d7fd2c90882dfff930b627ddbe16810", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/filesystem": "^4.4|^5.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.15", + "symfony/polyfill-php81": "^1.22" + }, + "conflict": { + "symfony/finder": "<4.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/config/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/console", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "058553870f7809087fa80fa734704a21b9bcaeb2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/058553870f7809087fa80fa734704a21b9bcaeb2", + "reference": "058553870f7809087fa80fa734704a21b9bcaeb2", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php80": "^1.15", + "symfony/service-contracts": "^1.1|^2", + "symfony/string": "^5.1" + }, + "conflict": { + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "fcd0b29a7a0b1bb5bfbedc6231583d77fea04814" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/fcd0b29a7a0b1bb5bfbedc6231583d77fea04814", + "reference": "fcd0b29a7a0b1bb5bfbedc6231583d77fea04814", + "shasum": "" + }, + "require": { + "php": ">=7.2.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:40:38+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "94d973cb742d8c5c5dcf9534220e6b73b09af1d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/94d973cb742d8c5c5dcf9534220e6b73b09af1d4", + "reference": "94d973cb742d8c5c5dcf9534220e6b73b09af1d4", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1.1", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php80": "^1.15", + "symfony/service-contracts": "^1.1.6|^2" + }, + "conflict": { + "ext-psr": "<1.1|>=2", + "symfony/config": "<5.3", + "symfony/finder": "<4.4", + "symfony/proxy-manager-bridge": "<4.4", + "symfony/yaml": "<4.4" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0|2.0" + }, + "require-dev": { + "symfony/config": "^5.3", + "symfony/expression-language": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows you to standardize and centralize the way objects are constructed in your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dependency-injection/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:57:12+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-23T23:28:01+00:00" + }, + { + "name": "symfony/doctrine-bridge", + "version": "v5.3.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/doctrine-bridge.git", + "reference": "29516dcc8165bc7e2339182a9360ea7d3471fb03" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/29516dcc8165bc7e2339182a9360ea7d3471fb03", + "reference": "29516dcc8165bc7e2339182a9360ea7d3471fb03", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "~1.0", + "doctrine/persistence": "^2", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.15", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "doctrine/dbal": "<2.10", + "phpunit/phpunit": "<5.4.3", + "symfony/dependency-injection": "<4.4", + "symfony/form": "<5.1", + "symfony/http-kernel": "<5", + "symfony/messenger": "<4.4", + "symfony/property-info": "<5", + "symfony/security-bundle": "<5", + "symfony/security-core": "<5.3", + "symfony/validator": "<5.2" + }, + "require-dev": { + "composer/package-versions-deprecated": "^1.8", + "doctrine/annotations": "^1.10.4", + "doctrine/collections": "~1.0", + "doctrine/data-fixtures": "^1.1", + "doctrine/dbal": "^2.10|^3.0", + "doctrine/orm": "^2.7.3", + "symfony/cache": "^5.1", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/doctrine-messenger": "^5.1", + "symfony/expression-language": "^4.4|^5.0", + "symfony/form": "^5.1.3", + "symfony/http-kernel": "^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.0", + "symfony/property-info": "^5.0", + "symfony/proxy-manager-bridge": "^4.4|^5.0", + "symfony/security-core": "^5.3", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/uid": "^5.1", + "symfony/validator": "^5.2", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "doctrine/data-fixtures": "", + "doctrine/dbal": "", + "doctrine/orm": "", + "symfony/form": "", + "symfony/property-info": "", + "symfony/validator": "" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Doctrine\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides integration for Doctrine with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/doctrine-bridge/tree/v5.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-06-01T15:43:02+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "55fff62b19f413f897a752488ade1bc9c8a19cdd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/55fff62b19f413f897a752488ade1bc9c8a19cdd", + "reference": "55fff62b19f413f897a752488ade1bc9c8a19cdd", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "masterminds/html5": "<2.6" + }, + "require-dev": { + "masterminds/html5": "^2.6", + "symfony/css-selector": "^4.4|^5.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases DOM navigation for HTML and XML documents", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dom-crawler/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/dotenv", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dotenv.git", + "reference": "1ac423fcc9548709077f90aca26c733cdb7e6e5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/1ac423fcc9548709077f90aca26c733cdb7e6e5c", + "reference": "1ac423fcc9548709077f90aca26c733cdb7e6e5c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1" + }, + "require-dev": { + "symfony/process": "^4.4|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Dotenv\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Registers environment variables from a .env file", + "homepage": "https://symfony.com", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "source": "https://github.com/symfony/dotenv/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T12:52:38+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "0e6768b8c0dcef26df087df2bbbaa143867a59b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/0e6768b8c0dcef26df087df2bbbaa143867a59b2", + "reference": "0e6768b8c0dcef26df087df2bbbaa143867a59b2", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/log": "^1.0", + "symfony/polyfill-php80": "^1.15", + "symfony/var-dumper": "^4.4|^5.0" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.1", + "symfony/http-kernel": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "67a5f354afa8e2f231081b3fa11a5912f933c3ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/67a5f354afa8e2f231081b3fa11a5912f933c3ce", + "reference": "67a5f354afa8e2f231081b3fa11a5912f933c3ce", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/event-dispatcher-contracts": "^2", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/error-handler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^4.4|^5.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/69fee1ad2332a7cbab3aca13591953da9cdb7a11", + "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-23T23:28:01+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "348116319d7fb7d1faa781d26a48922428013eb2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/348116319d7fb7d1faa781d26a48922428013eb2", + "reference": "348116319d7fb7d1faa781d26a48922428013eb2", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6", + "reference": "0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6", + "shasum": "" + }, + "require": { + "php": ">=7.2.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T12:52:38+00:00" + }, + { + "name": "symfony/flex", + "version": "v1.13.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/flex.git", + "reference": "2597d0dda8042c43eed44a9cd07236b897e427d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/flex/zipball/2597d0dda8042c43eed44a9cd07236b897e427d7", + "reference": "2597d0dda8042c43eed44a9cd07236b897e427d7", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": ">=7.1" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "symfony/dotenv": "^4.4|^5.0", + "symfony/filesystem": "^4.4|^5.0", + "symfony/phpunit-bridge": "^4.4|^5.0", + "symfony/process": "^3.4|^4.4|^5.0" + }, + "type": "composer-plugin", + "extra": { + "branch-alias": { + "dev-main": "1.13-dev" + }, + "class": "Symfony\\Flex\\Flex" + }, + "autoload": { + "psr-4": { + "Symfony\\Flex\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien.potencier@gmail.com" + } + ], + "description": "Composer plugin for Symfony", + "support": { + "issues": "https://github.com/symfony/flex/issues", + "source": "https://github.com/symfony/flex/tree/v1.13.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-19T07:19:15+00:00" + }, + { + "name": "symfony/framework-bundle", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "99196372c703b8cc97ee61d63d98acbf9896d425" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/99196372c703b8cc97ee61d63d98acbf9896d425", + "reference": "99196372c703b8cc97ee61d63d98acbf9896d425", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": ">=7.2.5", + "symfony/cache": "^5.2", + "symfony/config": "^5.3", + "symfony/dependency-injection": "^5.3", + "symfony/deprecation-contracts": "^2.1", + "symfony/error-handler": "^4.4.1|^5.0.1", + "symfony/event-dispatcher": "^5.1", + "symfony/filesystem": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/http-foundation": "^5.3", + "symfony/http-kernel": "^5.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.15", + "symfony/routing": "^5.3" + }, + "conflict": { + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "phpunit/phpunit": "<5.4.3", + "symfony/asset": "<5.3", + "symfony/browser-kit": "<4.4", + "symfony/console": "<5.2.5", + "symfony/dom-crawler": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/form": "<5.2", + "symfony/http-client": "<4.4", + "symfony/lock": "<4.4", + "symfony/mailer": "<5.2", + "symfony/messenger": "<4.4", + "symfony/mime": "<4.4", + "symfony/property-access": "<5.3", + "symfony/property-info": "<4.4", + "symfony/security-core": "<5.3", + "symfony/security-csrf": "<5.3", + "symfony/serializer": "<5.2", + "symfony/stopwatch": "<4.4", + "symfony/translation": "<5.3", + "symfony/twig-bridge": "<4.4", + "symfony/twig-bundle": "<4.4", + "symfony/validator": "<5.2", + "symfony/web-profiler-bundle": "<4.4", + "symfony/workflow": "<5.2" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4", + "doctrine/cache": "^1.0|^2.0", + "doctrine/persistence": "^1.3|^2.0", + "paragonie/sodium_compat": "^1.8", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/allmysms-notifier": "^5.3", + "symfony/asset": "^5.3", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/clickatell-notifier": "^5.3", + "symfony/console": "^5.2", + "symfony/css-selector": "^4.4|^5.0", + "symfony/discord-notifier": "^5.3", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/dotenv": "^5.1", + "symfony/esendex-notifier": "^5.3", + "symfony/expression-language": "^4.4|^5.0", + "symfony/fake-chat-notifier": "^5.3", + "symfony/fake-sms-notifier": "^5.3", + "symfony/firebase-notifier": "^5.3", + "symfony/form": "^5.2", + "symfony/free-mobile-notifier": "^5.3", + "symfony/gatewayapi-notifier": "^5.3", + "symfony/gitter-notifier": "^5.3", + "symfony/google-chat-notifier": "^5.3", + "symfony/http-client": "^4.4|^5.0", + "symfony/infobip-notifier": "^5.3", + "symfony/iqsms-notifier": "^5.3", + "symfony/light-sms-notifier": "^5.3", + "symfony/linked-in-notifier": "^5.3", + "symfony/lock": "^4.4|^5.0", + "symfony/mailer": "^5.2", + "symfony/mattermost-notifier": "^5.3", + "symfony/message-bird-notifier": "^5.3", + "symfony/messenger": "^5.2", + "symfony/microsoft-teams-notifier": "^5.3", + "symfony/mime": "^4.4|^5.0", + "symfony/mobyt-notifier": "^5.3", + "symfony/nexmo-notifier": "^5.3", + "symfony/notifier": "^5.3", + "symfony/octopush-notifier": "^5.3", + "symfony/ovh-cloud-notifier": "^5.3", + "symfony/phpunit-bridge": "^5.3", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "^4.4|^5.0", + "symfony/property-info": "^4.4|^5.0", + "symfony/rate-limiter": "^5.2", + "symfony/rocket-chat-notifier": "^5.3", + "symfony/security-bundle": "^5.3", + "symfony/sendinblue-notifier": "^5.3", + "symfony/serializer": "^5.2", + "symfony/sinch-notifier": "^5.3", + "symfony/slack-notifier": "^5.3", + "symfony/sms-biuras-notifier": "^5.3", + "symfony/smsapi-notifier": "^5.3", + "symfony/spot-hit-notifier": "^5.3", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/string": "^5.0", + "symfony/telegram-notifier": "^5.3", + "symfony/translation": "^5.3", + "symfony/twig-bundle": "^4.4|^5.0", + "symfony/twilio-notifier": "^5.3", + "symfony/validator": "^5.2", + "symfony/web-link": "^4.4|^5.0", + "symfony/workflow": "^5.2", + "symfony/yaml": "^4.4|^5.0", + "symfony/zulip-notifier": "^5.3", + "twig/twig": "^2.10|^3.0" + }, + "suggest": { + "ext-apcu": "For best performance of the system caches", + "symfony/console": "For using the console commands", + "symfony/form": "For using forms", + "symfony/property-info": "For using the property_info service", + "symfony/serializer": "For using the serializer service", + "symfony/validator": "For using validation", + "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", + "symfony/yaml": "For using the debug:config and lint:yaml commands" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\FrameworkBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/framework-bundle/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-31T10:12:54+00:00" + }, + { + "name": "symfony/http-client", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "ef85ca5fa7a4f9c57592fab49faeccdf22b13136" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/ef85ca5fa7a4f9c57592fab49faeccdf22b13136", + "reference": "ef85ca5fa7a4f9c57592fab49faeccdf22b13136", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/log": "^1.0", + "symfony/deprecation-contracts": "^2.1", + "symfony/http-client-contracts": "^2.4", + "symfony/polyfill-php73": "^1.11", + "symfony/polyfill-php80": "^1.15", + "symfony/service-contracts": "^1.0|^2" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "2.4" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/http-kernel": "^4.4.13|^5.1.5", + "symfony/process": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-client/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "7e82f6084d7cae521a75ef2cb5c9457bbda785f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/7e82f6084d7cae521a75ef2cb5c9457bbda785f4", + "reference": "7e82f6084d7cae521a75ef2cb5c9457bbda785f4", + "shasum": "" + }, + "require": { + "php": ">=7.2.5" + }, + "suggest": { + "symfony/http-client-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-04-11T23:07:08+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v5.3.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "8827b90cf8806e467124ad476acd15216c2fceb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8827b90cf8806e467124ad476acd15216c2fceb6", + "reference": "8827b90cf8806e467124ad476acd15216c2fceb6", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php80": "^1.15" + }, + "require-dev": { + "predis/predis": "~1.0", + "symfony/cache": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0" + }, + "suggest": { + "symfony/mime": "To use the file extension guesser" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v5.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-06-02T09:32:00+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v5.3.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "74eb022e3bac36b3d3a897951a98759f2b32b864" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/74eb022e3bac36b3d3a897951a98759f2b32b864", + "reference": "74eb022e3bac36b3d3a897951a98759f2b32b864", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/log": "~1.0", + "symfony/deprecation-contracts": "^2.1", + "symfony/error-handler": "^4.4|^5.0", + "symfony/event-dispatcher": "^5.0", + "symfony/http-client-contracts": "^1.1|^2", + "symfony/http-foundation": "^5.3", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "symfony/browser-kit": "<4.4", + "symfony/cache": "<5.0", + "symfony/config": "<5.0", + "symfony/console": "<4.4", + "symfony/dependency-injection": "<5.3", + "symfony/doctrine-bridge": "<5.0", + "symfony/form": "<5.0", + "symfony/http-client": "<5.0", + "symfony/mailer": "<5.0", + "symfony/messenger": "<5.0", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<5.0", + "symfony/validator": "<5.0", + "twig/twig": "<2.13" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dependency-injection": "^5.3", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/routing": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "twig/twig": "^2.13|^3.0.4" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v5.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-06-02T10:07:12+00:00" + }, + { + "name": "symfony/lock", + "version": "v5.3.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/lock.git", + "reference": "cf21749b2733508f0e1031c0a531cefa3efca0b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/lock/zipball/cf21749b2733508f0e1031c0a531cefa3efca0b8", + "reference": "cf21749b2733508f0e1031c0a531cefa3efca0b8", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/log": "~1.0", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "doctrine/dbal": "<2.10" + }, + "require-dev": { + "doctrine/dbal": "^2.10|^3.0", + "mongodb/mongodb": "~1.1", + "predis/predis": "~1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Lock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jérémy Derussé", + "email": "jeremy@derusse.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Creates and manages locks, a mechanism to provide exclusive access to a shared resource", + "homepage": "https://symfony.com", + "keywords": [ + "cas", + "flock", + "locking", + "mutex", + "redlock", + "semaphore" + ], + "support": { + "source": "https://github.com/symfony/lock/tree/v5.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-06-01T18:47:32+00:00" + }, + { + "name": "symfony/monolog-bridge", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/monolog-bridge.git", + "reference": "84841557874df015ef2843aa16ac63d09f97c7b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/84841557874df015ef2843aa16ac63d09f97c7b9", + "reference": "84841557874df015ef2843aa16ac63d09f97c7b9", + "shasum": "" + }, + "require": { + "monolog/monolog": "^1.25.1|^2", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/http-kernel": "^5.3", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "symfony/console": "<4.4", + "symfony/http-foundation": "<5.3" + }, + "require-dev": { + "symfony/console": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/mailer": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/security-core": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "symfony/console": "For the possibility to show log messages in console commands depending on verbosity settings.", + "symfony/http-kernel": "For using the debugging handlers together with the response life cycle of the HTTP kernel.", + "symfony/var-dumper": "For using the debugging handlers like the console handler or the log server handler." + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Monolog\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides integration for Monolog with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/monolog-bridge/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/monolog-bundle", + "version": "v3.7.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/monolog-bundle.git", + "reference": "4054b2e940a25195ae15f0a49ab0c51718922eb4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/4054b2e940a25195ae15f0a49ab0c51718922eb4", + "reference": "4054b2e940a25195ae15f0a49ab0c51718922eb4", + "shasum": "" + }, + "require": { + "monolog/monolog": "~1.22 || ~2.0", + "php": ">=7.1.3", + "symfony/config": "~4.4 || ^5.0", + "symfony/dependency-injection": "^4.4 || ^5.0", + "symfony/http-kernel": "~4.4 || ^5.0", + "symfony/monolog-bridge": "~4.4 || ^5.0" + }, + "require-dev": { + "symfony/console": "~4.4 || ^5.0", + "symfony/phpunit-bridge": "^5.1", + "symfony/yaml": "~4.4 || ^5.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\MonologBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony MonologBundle", + "homepage": "https://symfony.com", + "keywords": [ + "log", + "logging" + ], + "support": { + "issues": "https://github.com/symfony/monolog-bundle/issues", + "source": "https://github.com/symfony/monolog-bundle/tree/v3.7.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-31T07:20:47+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/162e886ca035869866d233a2bfef70cc28f9bbe5", + "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.15" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/orm-pack", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/orm-pack.git", + "reference": "7dd2ed9ba6d7af79f90bdc77522605d40463e533" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/orm-pack/zipball/7dd2ed9ba6d7af79f90bdc77522605d40463e533", + "reference": "7dd2ed9ba6d7af79f90bdc77522605d40463e533", + "shasum": "" + }, + "require": { + "composer/package-versions-deprecated": "*", + "doctrine/doctrine-bundle": "^2", + "doctrine/doctrine-migrations-bundle": "^2", + "doctrine/orm": "^2" + }, + "type": "symfony-pack", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A pack for the Doctrine ORM", + "support": { + "issues": "https://github.com/symfony/orm-pack/issues", + "source": "https://github.com/symfony/orm-pack/tree/master" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-07-08T14:31:54+00:00" + }, + { + "name": "symfony/password-hasher", + "version": "v5.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/password-hasher.git", + "reference": "d487faef0347d5351d3e361e123a73496595509f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/d487faef0347d5351d3e361e123a73496595509f", + "reference": "d487faef0347d5351d3e361e123a73496595509f", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "symfony/security-core": "<5.3" + }, + "require-dev": { + "symfony/console": "^5", + "symfony/security-core": "^5.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PasswordHasher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Robin Chalas", + "email": "robin.chalas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides password hashing utilities", + "homepage": "https://symfony.com", + "keywords": [ + "hashing", + "password" + ], + "support": { + "source": "https://github.com/symfony/password-hasher/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.23.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/24b72c6baa32c746a4d0840147c9715e42bb68ab", + "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Filesystem Component", + "description": "Symfony polyfill for intl's grapheme_* functions", "homepage": "https://symfony.com", - "time": "2019-11-26T23:25:11+00:00" + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-27T09:17:38+00:00" }, { - "name": "symfony/finder", - "version": "v5.0.2", + "name": "symfony/polyfill-intl-idn", + "version": "v1.23.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "17874dd8ab9a19422028ad56172fb294287a701b" + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "65bd267525e82759e7d8c4e8ceea44f398838e65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/17874dd8ab9a19422028ad56172fb294287a701b", - "reference": "17874dd8ab9a19422028ad56172fb294287a701b", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/65bd267525e82759e7d8c4e8ceea44f398838e65", + "reference": "65bd267525e82759e7d8c4e8ceea44f398838e65", "shasum": "" }, "require": { - "php": "^7.2.5" + "php": ">=7.1", + "symfony/polyfill-intl-normalizer": "^1.10", + "symfony/polyfill-php72": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Finder\\": "" + "Symfony\\Polyfill\\Intl\\Idn\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2479,177 +5933,326 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", "homepage": "https://symfony.com", - "time": "2019-11-18T17:27:11+00:00" + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-27T09:27:20+00:00" }, { - "name": "symfony/flex", - "version": "v1.6.0", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.23.0", "source": { "type": "git", - "url": "https://github.com/symfony/flex.git", - "reference": "952f45d1c5077e658cb16a61d11603bee873f968" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/952f45d1c5077e658cb16a61d11603bee873f968", - "reference": "952f45d1c5077e658cb16a61d11603bee873f968", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", + "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0", - "php": "^7.0" + "php": ">=7.1" }, - "require-dev": { - "composer/composer": "^1.0.2", - "symfony/dotenv": "^3.4|^4.0|^5.0", - "symfony/phpunit-bridge": "^3.4.19|^4.1.8|^5.0", - "symfony/process": "^2.7|^3.0|^4.0|^5.0" + "suggest": { + "ext-intl": "For best performance" }, - "type": "composer-plugin", + "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5-dev" + "dev-main": "1.23-dev" }, - "class": "Symfony\\Flex\\Flex" + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } }, "autoload": { "psr-4": { - "Symfony\\Flex\\": "src" + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-19T12:13:01+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.23.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1", + "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien.potencier@gmail.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Composer plugin for Symfony", - "time": "2019-12-13T18:05:11+00:00" + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-27T09:27:20+00:00" }, { - "name": "symfony/framework-bundle", - "version": "v5.0.2", + "name": "symfony/polyfill-php73", + "version": "v1.23.0", "source": { "type": "git", - "url": "https://github.com/symfony/framework-bundle.git", - "reference": "36e51776b231d8e224da4ce4c60079540acd1c55" + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/36e51776b231d8e224da4ce4c60079540acd1c55", - "reference": "36e51776b231d8e224da4ce4c60079540acd1c55", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010", + "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010", "shasum": "" }, "require": { - "ext-xml": "*", - "php": "^7.2.5", - "symfony/cache": "^4.4|^5.0", - "symfony/config": "^5.0", - "symfony/dependency-injection": "^5.0.1", - "symfony/error-handler": "^4.4.1|^5.0.1", - "symfony/filesystem": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/http-kernel": "^5.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/routing": "^5.0" + "php": ">=7.1" }, - "conflict": { - "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.0", - "phpdocumentor/type-resolver": "<0.2.1", - "phpunit/phpunit": "<5.4.3", - "symfony/asset": "<4.4", - "symfony/browser-kit": "<4.4", - "symfony/console": "<4.4", - "symfony/dom-crawler": "<4.4", - "symfony/dotenv": "<4.4", - "symfony/form": "<4.4", - "symfony/http-client": "<4.4", - "symfony/lock": "<4.4", - "symfony/mailer": "<4.4", - "symfony/messenger": "<4.4", - "symfony/mime": "<4.4", - "symfony/property-info": "<4.4", - "symfony/serializer": "<4.4", - "symfony/stopwatch": "<4.4", - "symfony/translation": "<5.0", - "symfony/twig-bridge": "<4.4", - "symfony/twig-bundle": "<4.4", - "symfony/validator": "<4.4", - "symfony/web-profiler-bundle": "<4.4", - "symfony/workflow": "<4.4" + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } }, - "require-dev": { - "doctrine/annotations": "~1.7", - "doctrine/cache": "~1.0", - "paragonie/sodium_compat": "^1.8", - "phpdocumentor/reflection-docblock": "^3.0|^4.0", - "symfony/asset": "^4.4|^5.0", - "symfony/browser-kit": "^4.4|^5.0", - "symfony/console": "^4.4|^5.0", - "symfony/css-selector": "^4.4|^5.0", - "symfony/dom-crawler": "^4.4|^5.0", - "symfony/dotenv": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/form": "^4.4|^5.0", - "symfony/http-client": "^4.4|^5.0", - "symfony/lock": "^4.4|^5.0", - "symfony/mailer": "^4.4|^5.0", - "symfony/messenger": "^4.4|^5.0", - "symfony/mime": "^4.4|^5.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^4.4|^5.0", - "symfony/property-info": "^4.4|^5.0", - "symfony/security-csrf": "^4.4|^5.0", - "symfony/security-http": "^4.4|^5.0", - "symfony/serializer": "^4.4|^5.0", - "symfony/stopwatch": "^4.4|^5.0", - "symfony/string": "~5.0.0", - "symfony/translation": "^5.0", - "symfony/twig-bundle": "^4.4|^5.0", - "symfony/validator": "^4.4|^5.0", - "symfony/web-link": "^4.4|^5.0", - "symfony/workflow": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0", - "twig/twig": "^2.10|^3.0" + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-19T12:13:01+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.23.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0" }, - "suggest": { - "ext-apcu": "For best performance of the system caches", - "symfony/console": "For using the console commands", - "symfony/form": "For using forms", - "symfony/property-info": "For using the property_info service", - "symfony/serializer": "For using the serializer service", - "symfony/validator": "For using validation", - "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", - "symfony/yaml": "For using the debug:config and lint:yaml commands" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0", + "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0", + "shasum": "" }, - "type": "symfony-bundle", + "require": { + "php": ">=7.1" + }, + "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { - "Symfony\\Bundle\\FrameworkBundle\\": "" + "Symfony\\Polyfill\\Php80\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2658,53 +6261,81 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony FrameworkBundle", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", - "time": "2019-12-17T10:33:13+00:00" + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-19T12:13:01+00:00" }, { - "name": "symfony/http-foundation", - "version": "v5.0.2", + "name": "symfony/polyfill-php81", + "version": "v1.23.0", "source": { "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "e66119f3de95efc359483f810c4c3e6436279436" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5dd7f6be6e62d86ba6f3154cf40e78936367978b", - "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/e66119f3de95efc359483f810c4c3e6436279436", + "reference": "e66119f3de95efc359483f810c4c3e6436279436", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/mime": "^4.4|^5.0", - "symfony/polyfill-mbstring": "~1.1" - }, - "require-dev": { - "predis/predis": "~1.0", - "symfony/expression-language": "^4.4|^5.0" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" + "Symfony\\Polyfill\\Php81\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2713,94 +6344,77 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony HttpFoundation Component", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", - "time": "2019-12-19T16:01:11+00:00" + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-21T13:25:03+00:00" }, { - "name": "symfony/http-kernel", - "version": "v5.0.2", + "name": "symfony/polyfill-uuid", + "version": "v1.23.0", "source": { "type": "git", - "url": "https://github.com/symfony/http-kernel.git", - "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e" + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "9165effa2eb8a31bb3fa608df9d529920d21ddd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/00ce30602f3f690e66a63c327743d7b26c723b2e", - "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/9165effa2eb8a31bb3fa608df9d529920d21ddd9", + "reference": "9165effa2eb8a31bb3fa608df9d529920d21ddd9", "shasum": "" }, "require": { - "php": "^7.2.5", - "psr/log": "~1.0", - "symfony/error-handler": "^4.4|^5.0", - "symfony/event-dispatcher": "^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-php73": "^1.9" - }, - "conflict": { - "symfony/browser-kit": "<4.4", - "symfony/cache": "<5.0", - "symfony/config": "<5.0", - "symfony/dependency-injection": "<4.4", - "symfony/doctrine-bridge": "<5.0", - "symfony/form": "<5.0", - "symfony/http-client": "<5.0", - "symfony/mailer": "<5.0", - "symfony/messenger": "<5.0", - "symfony/translation": "<5.0", - "symfony/twig-bridge": "<5.0", - "symfony/validator": "<5.0", - "twig/twig": "<2.4" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "require-dev": { - "psr/cache": "~1.0", - "symfony/browser-kit": "^4.4|^5.0", - "symfony/config": "^5.0", - "symfony/console": "^4.4|^5.0", - "symfony/css-selector": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/dom-crawler": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/routing": "^4.4|^5.0", - "symfony/stopwatch": "^4.4|^5.0", - "symfony/translation": "^4.4|^5.0", - "symfony/translation-contracts": "^1.1|^2", - "twig/twig": "^2.4|^3.0" + "php": ">=7.1" }, "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" + "ext-uuid": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { - "Symfony\\Component\\HttpKernel\\": "" + "Symfony\\Polyfill\\Uuid\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2809,53 +6423,71 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony HttpKernel Component", + "description": "Symfony polyfill for uuid functions", "homepage": "https://symfony.com", - "time": "2019-12-19T18:35:03+00:00" + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-19T12:13:01+00:00" }, { - "name": "symfony/mime", - "version": "v5.0.2", + "name": "symfony/property-access", + "version": "v5.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/mime.git", - "reference": "0e6a4ced216e49d457eddcefb61132173a876d79" + "url": "https://github.com/symfony/property-access.git", + "reference": "8988399a556cffb0fba9bb3603f8d1ba4543eceb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/0e6a4ced216e49d457eddcefb61132173a876d79", - "reference": "0e6a4ced216e49d457eddcefb61132173a876d79", + "url": "https://api.github.com/repos/symfony/property-access/zipball/8988399a556cffb0fba9bb3603f8d1ba4543eceb", + "reference": "8988399a556cffb0fba9bb3603f8d1ba4543eceb", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0" - }, - "conflict": { - "symfony/mailer": "<4.4" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php80": "^1.15", + "symfony/property-info": "^5.2" }, "require-dev": { - "egulias/email-validator": "^2.1.10", - "symfony/dependency-injection": "^4.4|^5.0" + "symfony/cache": "^4.4|^5.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } + "suggest": { + "psr/cache-implementation": "To cache access methods." }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Mime\\": "" + "Symfony\\Component\\PropertyAccess\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -2875,76 +6507,83 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "A library to manipulate MIME messages", + "description": "Provides functions to read and write from/to an object or array using a simple string notation", "homepage": "https://symfony.com", "keywords": [ - "mime", - "mime-type" + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property path", + "reflection" ], - "time": "2019-11-30T14:12:50+00:00" - }, - { - "name": "symfony/orm-pack", - "version": "v1.0.7", - "source": { - "type": "git", - "url": "https://github.com/symfony/orm-pack.git", - "reference": "c57f5e05232ca40626eb9fa52a32bc8565e9231c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/orm-pack/zipball/c57f5e05232ca40626eb9fa52a32bc8565e9231c", - "reference": "c57f5e05232ca40626eb9fa52a32bc8565e9231c", - "shasum": "" - }, - "require": { - "doctrine/doctrine-bundle": "^1.6.10|^2.0", - "doctrine/doctrine-migrations-bundle": "^1.3|^2.0", - "doctrine/orm": "^2.5.11", - "php": "^7.0" + "support": { + "source": "https://github.com/symfony/property-access/tree/v5.3.0" }, - "type": "symfony-pack", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "description": "A pack for the Doctrine ORM", - "time": "2019-10-18T05:41:09+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { - "name": "symfony/polyfill-intl-idn", - "version": "v1.13.1", + "name": "symfony/property-info", + "version": "v5.3.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46" + "url": "https://github.com/symfony/property-info.git", + "reference": "6f8bff281f215dbf41929c7ec6f8309cdc0912cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6f9c239e61e1b0c9229a28ff89a812dc449c3d46", - "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46", + "url": "https://api.github.com/repos/symfony/property-info/zipball/6f8bff281f215dbf41929c7ec6f8309cdc0912cf", + "reference": "6f8bff281f215dbf41929c7ec6f8309cdc0912cf", "shasum": "" }, "require": { - "php": ">=5.3.3", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php72": "^1.9" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php80": "^1.15", + "symfony/string": "^5.1" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/dependency-injection": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "^1.10.4", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/cache": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0" }, "suggest": { - "ext-intl": "For best performance" + "phpdocumentor/reflection-docblock": "To use the PHPDoc", + "psr/cache-implementation": "To cache results", + "symfony/doctrine-bridge": "To use Doctrine metadata", + "symfony/serializer": "To use Serializer metadata" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" + "Symfony\\Component\\PropertyInfo\\": "" }, - "files": [ - "bootstrap.php" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2953,58 +6592,87 @@ ], "authors": [ { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "description": "Extracts information about PHP class' properties using metadata of popular sources", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "idn", - "intl", - "polyfill", - "portable", - "shim" + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" + ], + "support": { + "source": "https://github.com/symfony/property-info/tree/v5.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2019-11-27T13:56:44+00:00" + "time": "2021-05-31T12:40:48+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.13.1", + "name": "symfony/psr-http-message-bridge", + "version": "v2.1.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" + "url": "https://github.com/symfony/psr-http-message-bridge.git", + "reference": "81db2d4ae86e9f0049828d9343a72b9523884e5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", - "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/81db2d4ae86e9f0049828d9343a72b9523884e5d", + "reference": "81db2d4ae86e9f0049828d9343a72b9523884e5d", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1", + "psr/http-message": "^1.0", + "symfony/http-foundation": "^4.4 || ^5.0" + }, + "require-dev": { + "nyholm/psr7": "^1.1", + "psr/log": "^1.1", + "symfony/browser-kit": "^4.4 || ^5.0", + "symfony/config": "^4.4 || ^5.0", + "symfony/event-dispatcher": "^4.4 || ^5.0", + "symfony/framework-bundle": "^4.4 || ^5.0", + "symfony/http-kernel": "^4.4 || ^5.0", + "symfony/phpunit-bridge": "^4.4.19 || ^5.2" }, "suggest": { - "ext-mbstring": "For best performance" + "nyholm/psr7": "For a super lightweight PSR-7/17 implementation" }, - "type": "library", + "type": "symfony-bridge", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-main": "2.1-dev" } }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" + "Symfony\\Bridge\\PsrHttpMessage\\": "" }, - "files": [ - "bootstrap.php" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3013,57 +6681,71 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "homepage": "http://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", + "description": "PSR HTTP message bridge", + "homepage": "http://symfony.com", "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" + "http", + "http-message", + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/symfony/psr-http-message-bridge/issues", + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2019-11-27T14:18:11+00:00" + "time": "2021-02-17T10:35:25+00:00" }, { - "name": "symfony/polyfill-php73", - "version": "v1.13.1", + "name": "symfony/rate-limiter", + "version": "v5.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f" + "url": "https://github.com/symfony/rate-limiter.git", + "reference": "e9226c91163495ff0b655cdae0fff682e869640b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/4b0e2222c55a25b4541305a053013d5647d3a25f", - "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f", + "url": "https://api.github.com/repos/symfony/rate-limiter/zipball/e9226c91163495ff0b655cdae0fff682e869640b", + "reference": "e9226c91163495ff0b655cdae0fff682e869640b", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.2.5", + "symfony/lock": "^5.2", + "symfony/options-resolver": "^5.1" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" + "Symfony\\Component\\RateLimiter\\": "" }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3072,68 +6754,80 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Wouter de Jong", + "email": "wouter@wouterj.nl" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "description": "Provides a Token Bucket implementation to rate limit input and output in your application", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" + "limiter", + "rate-limiter" + ], + "support": { + "source": "https://github.com/symfony/rate-limiter/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2019-11-27T16:25:15+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/routing", - "version": "v5.0.2", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301" + "reference": "368e81376a8e049c37cb80ae87dbfbf411279199" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/120c5fa4f4ef5466cbb510ece8126e0007285301", - "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301", + "url": "https://api.github.com/repos/symfony/routing/zipball/368e81376a8e049c37cb80ae87dbfbf411279199", + "reference": "368e81376a8e049c37cb80ae87dbfbf411279199", "shasum": "" }, "require": { - "php": "^7.2.5" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php80": "^1.15" }, "conflict": { - "symfony/config": "<5.0", + "doctrine/annotations": "<1.12", + "symfony/config": "<5.3", "symfony/dependency-injection": "<4.4", "symfony/yaml": "<4.4" }, "require-dev": { - "doctrine/annotations": "~1.2", + "doctrine/annotations": "^1.12", "psr/log": "~1.0", - "symfony/config": "^5.0", + "symfony/config": "^5.3", "symfony/dependency-injection": "^4.4|^5.0", "symfony/expression-language": "^4.4|^5.0", "symfony/http-foundation": "^4.4|^5.0", "symfony/yaml": "^4.4|^5.0" }, "suggest": { - "doctrine/annotations": "For using the annotation loader", "symfony/config": "For using the all-in-one router or any loader", "symfony/expression-language": "For using expression matching", "symfony/http-foundation": "For using a Symfony Request object", "symfony/yaml": "For using the YAML loader" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Routing\\": "" @@ -3156,7 +6850,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Routing Component", + "description": "Maps an HTTP request to a set of configuration variables", "homepage": "https://symfony.com", "keywords": [ "router", @@ -3164,67 +6858,78 @@ "uri", "url" ], - "time": "2019-12-12T13:03:32+00:00" + "support": { + "source": "https://github.com/symfony/routing/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" }, { - "name": "symfony/serializer", - "version": "v5.0.2", + "name": "symfony/security-core", + "version": "v5.3.1", "source": { "type": "git", - "url": "https://github.com/symfony/serializer.git", - "reference": "3cfc478c102f2d3bcf60edd339cd9c3cb446a576" + "url": "https://github.com/symfony/security-core.git", + "reference": "22714af1f701937a0a0bd3e3ec2a761baed3f2d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/3cfc478c102f2d3bcf60edd339cd9c3cb446a576", - "reference": "3cfc478c102f2d3bcf60edd339cd9c3cb446a576", + "url": "https://api.github.com/repos/symfony/security-core/zipball/22714af1f701937a0a0bd3e3ec2a761baed3f2d0", + "reference": "22714af1f701937a0a0bd3e3ec2a761baed3f2d0", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/polyfill-ctype": "~1.8" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/event-dispatcher-contracts": "^1.1|^2", + "symfony/password-hasher": "^5.3", + "symfony/polyfill-php80": "^1.15", + "symfony/service-contracts": "^1.1.6|^2" }, "conflict": { - "phpdocumentor/type-resolver": "<0.2.1", - "symfony/dependency-injection": "<4.4", - "symfony/property-access": "<4.4", - "symfony/property-info": "<4.4", - "symfony/yaml": "<4.4" + "symfony/event-dispatcher": "<4.4", + "symfony/http-foundation": "<5.3", + "symfony/ldap": "<4.4", + "symfony/security-guard": "<4.4", + "symfony/validator": "<5.2" }, "require-dev": { - "doctrine/annotations": "~1.0", - "doctrine/cache": "~1.0", - "phpdocumentor/reflection-docblock": "^3.2|^4.0", + "psr/cache": "^1.0|^2.0|^3.0", + "psr/container": "^1.0|^2.0", + "psr/log": "~1.0", "symfony/cache": "^4.4|^5.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/error-handler": "^4.4|^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/mime": "^4.4|^5.0", - "symfony/property-access": "^4.4|^5.0", - "symfony/property-info": "^4.4|^5.0", - "symfony/validator": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0" + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^5.3", + "symfony/ldap": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/validator": "^5.2" }, "suggest": { - "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", - "doctrine/cache": "For using the default cached annotation reader and metadata cache.", - "psr/cache-implementation": "For using the metadata cache.", - "symfony/config": "For using the XML mapping loader.", - "symfony/mime": "For using a MIME type guesser within the DataUriNormalizer.", - "symfony/property-access": "For using the ObjectNormalizer.", - "symfony/property-info": "To deserialize relations.", - "symfony/yaml": "For using the default YAML mapping loader." + "psr/container-implementation": "To instantiate the Security class", + "symfony/event-dispatcher": "", + "symfony/expression-language": "For using the expression voter", + "symfony/http-foundation": "", + "symfony/ldap": "For using LDAP integration", + "symfony/validator": "For using the user password constraint" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Component\\Serializer\\": "" + "Symfony\\Component\\Security\\Core\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -3244,95 +6949,89 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Serializer Component", + "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", - "time": "2019-12-16T11:08:25+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "144c5e51266b281231e947b51223ba14acf1a749" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", - "reference": "144c5e51266b281231e947b51223ba14acf1a749", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "psr/container": "^1.0" + "support": { + "source": "https://github.com/symfony/security-core/tree/v5.3.1" }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "time": "2019-11-18T17:27:11+00:00" + "time": "2021-06-01T15:43:02+00:00" }, { - "name": "symfony/stopwatch", - "version": "v5.0.2", + "name": "symfony/serializer", + "version": "v5.3.1", "source": { "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "d410282956706e0b08681a5527447a8e6b6f421e" + "url": "https://github.com/symfony/serializer.git", + "reference": "ebb3dc397af77a08d734eea7305e0b2ec8c5e875" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/d410282956706e0b08681a5527447a8e6b6f421e", - "reference": "d410282956706e0b08681a5527447a8e6b6f421e", + "url": "https://api.github.com/repos/symfony/serializer/zipball/ebb3dc397af77a08d734eea7305e0b2ec8c5e875", + "reference": "ebb3dc397af77a08d734eea7305e0b2ec8c5e875", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/service-contracts": "^1.0|^2" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.15" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } + "conflict": { + "doctrine/annotations": "<1.12", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/dependency-injection": "<4.4", + "symfony/property-access": "<4.4", + "symfony/property-info": "<5.3", + "symfony/yaml": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "^1.12", + "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0", + "symfony/cache": "^4.4|^5.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/error-handler": "^4.4|^5.0", + "symfony/filesystem": "^4.4|^5.0", + "symfony/form": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/property-access": "^4.4.9|^5.0.9", + "symfony/property-info": "^5.3", + "symfony/uid": "^5.1", + "symfony/validator": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0", + "symfony/var-exporter": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "psr/cache-implementation": "For using the metadata cache.", + "symfony/config": "For using the XML mapping loader.", + "symfony/mime": "For using a MIME type guesser within the DataUriNormalizer.", + "symfony/property-access": "For using the ObjectNormalizer.", + "symfony/property-info": "To deserialize relations.", + "symfony/var-exporter": "For using the metadata compiler.", + "symfony/yaml": "For using the default YAML mapping loader." }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" + "Symfony\\Component\\Serializer\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -3352,39 +7051,61 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Stopwatch Component", + "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", - "time": "2019-11-18T17:27:11+00:00" + "support": { + "source": "https://github.com/symfony/serializer/tree/v5.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-06-02T09:36:17+00:00" }, { - "name": "symfony/translation-contracts", - "version": "v2.0.1", + "name": "symfony/service-contracts", + "version": "v2.4.0", "source": { "type": "git", - "url": "https://github.com/symfony/translation-contracts.git", - "reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/8cc682ac458d75557203b2f2f14b0b92e1c744ed", - "reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", "shasum": "" }, "require": { - "php": "^7.2.5" + "php": ">=7.2.5", + "psr/container": "^1.1" }, "suggest": { - "symfony/translation-implementation": "" + "symfony/service-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "2.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { "psr-4": { - "Symfony\\Contracts\\Translation\\": "" + "Symfony\\Contracts\\Service\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -3401,7 +7122,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to translation", + "description": "Generic abstractions related to writing services", "homepage": "https://symfony.com", "keywords": [ "abstractions", @@ -3411,86 +7132,47 @@ "interoperability", "standards" ], - "time": "2019-11-18T17:27:11+00:00" + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-04-01T10:43:52+00:00" }, { - "name": "symfony/twig-bridge", - "version": "v5.0.2", + "name": "symfony/stopwatch", + "version": "v5.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/twig-bridge.git", - "reference": "abbaeee38ff39651e335c55be40752be2ddd0976" + "url": "https://github.com/symfony/stopwatch.git", + "reference": "313d02f59d6543311865007e5ff4ace05b35ee65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/abbaeee38ff39651e335c55be40752be2ddd0976", - "reference": "abbaeee38ff39651e335c55be40752be2ddd0976", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/313d02f59d6543311865007e5ff4ace05b35ee65", + "reference": "313d02f59d6543311865007e5ff4ace05b35ee65", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/translation-contracts": "^1.1|^2", - "twig/twig": "^2.10|^3.0" - }, - "conflict": { - "symfony/console": "<4.4", - "symfony/form": "<5.0", - "symfony/http-foundation": "<4.4", - "symfony/http-kernel": "<4.4", - "symfony/translation": "<5.0", - "symfony/workflow": "<4.4" - }, - "require-dev": { - "egulias/email-validator": "^2.1.10", - "symfony/asset": "^4.4|^5.0", - "symfony/console": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/form": "^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/http-kernel": "^4.4|^5.0", - "symfony/mime": "^4.4|^5.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/routing": "^4.4|^5.0", - "symfony/security-acl": "^2.8|^3.0", - "symfony/security-core": "^4.4|^5.0", - "symfony/security-csrf": "^4.4|^5.0", - "symfony/security-http": "^4.4|^5.0", - "symfony/stopwatch": "^4.4|^5.0", - "symfony/translation": "^5.0", - "symfony/web-link": "^4.4|^5.0", - "symfony/workflow": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0", - "twig/cssinliner-extra": "^2.12", - "twig/inky-extra": "^2.12", - "twig/markdown-extra": "^2.12" - }, - "suggest": { - "symfony/asset": "For using the AssetExtension", - "symfony/expression-language": "For using the ExpressionExtension", - "symfony/finder": "", - "symfony/form": "For using the FormExtension", - "symfony/http-kernel": "For using the HttpKernelExtension", - "symfony/routing": "For using the RoutingExtension", - "symfony/security-core": "For using the SecurityExtension", - "symfony/security-csrf": "For using the CsrfExtension", - "symfony/security-http": "For using the LogoutUrlExtension", - "symfony/stopwatch": "For using the StopwatchExtension", - "symfony/translation": "For using the TranslationExtension", - "symfony/var-dumper": "For using the DumpExtension", - "symfony/web-link": "For using the WebLinkExtension", - "symfony/yaml": "For using the YamlExtension" - }, - "type": "symfony-bridge", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } + "php": ">=7.2.5", + "symfony/service-contracts": "^1.0|^2" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Bridge\\Twig\\": "" + "Symfony\\Component\\Stopwatch\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -3510,63 +7192,63 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Twig Bridge", + "description": "Provides a way to profile code", "homepage": "https://symfony.com", - "time": "2019-12-18T16:23:52+00:00" + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" }, { - "name": "symfony/twig-bundle", - "version": "v5.0.2", + "name": "symfony/string", + "version": "v5.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/twig-bundle.git", - "reference": "a54f6db9d452aa06a77e9f8562974a61e15bfa42" + "url": "https://github.com/symfony/string.git", + "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/a54f6db9d452aa06a77e9f8562974a61e15bfa42", - "reference": "a54f6db9d452aa06a77e9f8562974a61e15bfa42", + "url": "https://api.github.com/repos/symfony/string/zipball/a9a0f8b6aafc5d2d1c116dcccd1573a95153515b", + "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/config": "^4.4|^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/http-kernel": "^5.0", + "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8", - "symfony/twig-bridge": "^5.0", - "twig/twig": "^2.10|^3.0" - }, - "conflict": { - "symfony/dependency-injection": "<4.4", - "symfony/framework-bundle": "<5.0", - "symfony/translation": "<5.0" - }, - "require-dev": { - "doctrine/annotations": "~1.7", - "doctrine/cache": "~1.0", - "symfony/asset": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/form": "^4.4|^5.0", - "symfony/framework-bundle": "^5.0", - "symfony/routing": "^4.4|^5.0", - "symfony/stopwatch": "^4.4|^5.0", - "symfony/translation": "^5.0", - "symfony/web-link": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0" + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } + "require-dev": { + "symfony/error-handler": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Bundle\\TwigBundle\\": "" + "Symfony\\Component\\String\\": "" }, + "files": [ + "Resources/functions.php" + ], "exclude-from-classmap": [ "/Tests/" ] @@ -3577,35 +7259,61 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony TwigBundle", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", "homepage": "https://symfony.com", - "time": "2019-12-10T11:06:55+00:00" + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/var-dumper", - "version": "v5.0.2", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a" + "reference": "1d3953e627fe4b5f6df503f356b6545ada6351f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", - "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1d3953e627fe4b5f6df503f356b6545ada6351f3", + "reference": "1d3953e627fe4b5f6df503f356b6545ada6351f3", "shasum": "" }, "require": { - "php": "^7.2.5", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "^1.15" }, "conflict": { "phpunit/phpunit": "<5.4.3", @@ -3615,7 +7323,7 @@ "ext-iconv": "*", "symfony/console": "^4.4|^5.0", "symfony/process": "^4.4|^5.0", - "twig/twig": "^2.4|^3.0" + "twig/twig": "^2.13|^3.0.4" }, "suggest": { "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", @@ -3626,11 +7334,6 @@ "Resources/bin/var-dump-server" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { "files": [ "Resources/functions/dump.php" @@ -3656,40 +7359,53 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony mechanism for exploring and dumping PHP variables", + "description": "Provides mechanisms for walking through any arbitrary PHP variable", "homepage": "https://symfony.com", "keywords": [ "debug", "dump" ], - "time": "2019-12-18T13:50:31+00:00" + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-27T12:28:50+00:00" }, { "name": "symfony/var-exporter", - "version": "v5.0.2", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28" + "reference": "7a7c9dd972541f78e7815c03c0bae9f81e0e9dbb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", - "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/7a7c9dd972541f78e7815c03c0bae9f81e0e9dbb", + "reference": "7a7c9dd972541f78e7815c03c0bae9f81e0e9dbb", "shasum": "" }, "require": { - "php": "^7.2.5" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.15" }, "require-dev": { - "symfony/var-dumper": "^4.4|^5.0" + "symfony/var-dumper": "^4.4.9|^5.0.9" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\VarExporter\\": "" @@ -3712,7 +7428,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code", + "description": "Allows exporting any serializable PHP data structure to plain PHP code", "homepage": "https://symfony.com", "keywords": [ "clone", @@ -3722,24 +7438,42 @@ "instantiate", "serialize" ], - "time": "2019-12-01T08:48:26+00:00" + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:40:38+00:00" }, { "name": "symfony/yaml", - "version": "v5.0.2", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "847661e77afa48d99ecfa508e8b60f0b029a19c0" + "reference": "3bbcf262fceb3d8f48175302e6ba0ac96e3a5a11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/847661e77afa48d99ecfa508e8b60f0b029a19c0", - "reference": "847661e77afa48d99ecfa508e8b60f0b029a19c0", + "url": "https://api.github.com/repos/symfony/yaml/zipball/3bbcf262fceb3d8f48175302e6ba0ac96e3a5a11", + "reference": "3bbcf262fceb3d8f48175302e6ba0ac96e3a5a11", "shasum": "" }, "require": { - "php": "^7.2.5", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-ctype": "~1.8" }, "conflict": { @@ -3751,12 +7485,10 @@ "suggest": { "symfony/console": "For validating YAML files using the lint command" }, + "bin": [ + "Resources/bin/yaml-lint" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Yaml\\": "" @@ -3779,228 +7511,66 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Yaml Component", + "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", - "time": "2019-12-10T11:06:55+00:00" - }, - { - "name": "twig/twig", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "9b58bb8ac7a41d72fbb5a7dc643e07923e5ccc26" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/9b58bb8ac7a41d72fbb5a7dc643e07923e5ccc26", - "reference": "9b58bb8ac7a41d72fbb5a7dc643e07923e5ccc26", - "shasum": "" - }, - "require": { - "php": "^7.2.9", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3" - }, - "require-dev": { - "psr/container": "^1.0", - "symfony/debug": "^3.4|^4.2|^5.0", - "symfony/phpunit-bridge": "^4.4@dev|^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } + "support": { + "source": "https://github.com/symfony/yaml/tree/v5.3.0" }, - "autoload": { - "psr-4": { - "Twig\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ + "funding": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "name": "Twig Team", - "homepage": "https://twig.symfony.com/contributors", - "role": "Contributors" + "url": "https://github.com/fabpot", + "type": "github" }, { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "https://twig.symfony.com", - "keywords": [ - "templating" - ], - "time": "2019-11-15T20:38:32+00:00" - }, - { - "name": "zendframework/zend-code", - "version": "3.4.1", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-code.git", - "reference": "268040548f92c2bfcba164421c1add2ba43abaaa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-code/zipball/268040548f92c2bfcba164421c1add2ba43abaaa", - "reference": "268040548f92c2bfcba164421c1add2ba43abaaa", - "shasum": "" - }, - "require": { - "php": "^7.1", - "zendframework/zend-eventmanager": "^2.6 || ^3.0" - }, - "conflict": { - "phpspec/prophecy": "<1.9.0" - }, - "require-dev": { - "doctrine/annotations": "^1.7", - "ext-phar": "*", - "phpunit/phpunit": "^7.5.16 || ^8.4", - "zendframework/zend-coding-standard": "^1.0", - "zendframework/zend-stdlib": "^2.7 || ^3.0" - }, - "suggest": { - "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", - "zendframework/zend-stdlib": "Zend\\Stdlib component" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4.x-dev", - "dev-develop": "3.5.x-dev", - "dev-dev-4.0": "4.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\Code\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Extensions to the PHP Reflection API, static code scanning, and code generation", - "keywords": [ - "ZendFramework", - "code", - "zf" - ], - "time": "2019-12-10T19:21:15+00:00" - }, - { - "name": "zendframework/zend-eventmanager", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-eventmanager.git", - "reference": "a5e2583a211f73604691586b8406ff7296a946dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/a5e2583a211f73604691586b8406ff7296a946dd", - "reference": "a5e2583a211f73604691586b8406ff7296a946dd", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "athletic/athletic": "^0.1", - "container-interop/container-interop": "^1.1.0", - "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", - "zendframework/zend-coding-standard": "~1.0.0", - "zendframework/zend-stdlib": "^2.7.3 || ^3.0" - }, - "suggest": { - "container-interop/container-interop": "^1.1.0, to use the lazy listeners feature", - "zendframework/zend-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev", - "dev-develop": "3.3-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\EventManager\\": "src/" + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Trigger and listen to events within a PHP application", - "homepage": "https://github.com/zendframework/zend-eventmanager", - "keywords": [ - "event", - "eventmanager", - "events", - "zf2" ], - "time": "2018-04-25T15:33:34+00:00" + "time": "2021-05-26T17:43:10+00:00" } ], "packages-dev": [ { "name": "doctrine/data-fixtures", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/data-fixtures.git", - "reference": "608a35a3b5bcc4214d116603095f8b0c51091592" + "reference": "51d3d4880d28951fff42a635a2389f8c63baddc5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/608a35a3b5bcc4214d116603095f8b0c51091592", - "reference": "608a35a3b5bcc4214d116603095f8b0c51091592", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/51d3d4880d28951fff42a635a2389f8c63baddc5", + "reference": "51d3d4880d28951fff42a635a2389f8c63baddc5", "shasum": "" }, "require": { - "doctrine/common": "^2.11", - "php": "^7.2" + "doctrine/common": "^2.13|^3.0", + "doctrine/persistence": "^1.3.3|^2.0", + "php": "^7.2 || ^8.0" }, "conflict": { "doctrine/phpcr-odm": "<1.3.0" }, "require-dev": { - "alcaeus/mongo-php-adapter": "^1.1", - "doctrine/coding-standard": "^6.0", + "doctrine/coding-standard": "^8.2", "doctrine/dbal": "^2.5.4", - "doctrine/mongodb-odm": "^1.3.0", - "doctrine/orm": "^2.5.4", - "phpunit/phpunit": "^7.0" + "doctrine/mongodb-odm": "^1.3.0 || ^2.0.0", + "doctrine/orm": "^2.7.0", + "ext-sqlite3": "*", + "phpunit/phpunit": "^8.0" }, "suggest": { - "alcaeus/mongo-php-adapter": "For using MongoDB ODM with PHP 7", + "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", "doctrine/orm": "For loading ORM fixtures", "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures" @@ -4021,27 +7591,46 @@ "keywords": [ "database" ], - "time": "2019-10-30T20:03:18+00:00" + "support": { + "issues": "https://github.com/doctrine/data-fixtures/issues", + "source": "https://github.com/doctrine/data-fixtures/tree/1.5.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdata-fixtures", + "type": "tidelift" + } + ], + "time": "2021-01-23T10:20:43+00:00" }, { "name": "doctrine/doctrine-fixtures-bundle", - "version": "3.3.0", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", - "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70" + "reference": "870189619a7770f468ffb0b80925302e065a3b34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", - "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", + "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/870189619a7770f468ffb0b80925302e065a3b34", + "reference": "870189619a7770f468ffb0b80925302e065a3b34", "shasum": "" }, "require": { "doctrine/data-fixtures": "^1.3", "doctrine/doctrine-bundle": "^1.11|^2.0", "doctrine/orm": "^2.6.0", - "php": "^7.1", + "doctrine/persistence": "^1.3.7|^2.0", + "php": "^7.1 || ^8.0", "symfony/config": "^3.4|^4.3|^5.0", "symfony/console": "^3.4|^4.3|^5.0", "symfony/dependency-injection": "^3.4|^4.3|^5.0", @@ -4050,15 +7639,10 @@ }, "require-dev": { "doctrine/coding-standard": "^6.0", - "phpunit/phpunit": "^7.4", + "phpunit/phpunit": "^7.4 || ^8.0 || ^9.2", "symfony/phpunit-bridge": "^4.1|^5.0" }, "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "3.3.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Bundle\\FixturesBundle\\": "" @@ -4088,147 +7672,411 @@ "Fixture", "persistence" ], - "time": "2019-11-13T15:46:58+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.3.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "9a9981c347c5c49d6dfe5cf826bb882b824080dc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/9a9981c347c5c49d6dfe5cf826bb882b824080dc", - "reference": "9a9981c347c5c49d6dfe5cf826bb882b824080dc", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "0.0.5", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.3-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } + "support": { + "issues": "https://github.com/doctrine/DoctrineFixturesBundle/issues", + "source": "https://github.com/doctrine/DoctrineFixturesBundle/tree/3.4.0" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ + "funding": [ { - "name": "Nikita Popov" + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-fixtures-bundle", + "type": "tidelift" } ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "time": "2019-11-08T13:50:10+00:00" + "time": "2020-11-14T09:36:49+00:00" }, { - "name": "symfony/maker-bundle", - "version": "v1.14.3", + "name": "roave/security-advisories", + "version": "dev-latest", "source": { "type": "git", - "url": "https://github.com/symfony/maker-bundle.git", - "reference": "c864e7f9b8d1e1f5f60acc3beda11299f637aded" + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "9460a22455b82b353d2212fecedebcf73b141baa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/c864e7f9b8d1e1f5f60acc3beda11299f637aded", - "reference": "c864e7f9b8d1e1f5f60acc3beda11299f637aded", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/9460a22455b82b353d2212fecedebcf73b141baa", + "reference": "9460a22455b82b353d2212fecedebcf73b141baa", "shasum": "" }, - "require": { - "doctrine/inflector": "^1.2", - "nikic/php-parser": "^4.0", - "php": "^7.0.8", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/console": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/filesystem": "^3.4|^4.0|^5.0", - "symfony/finder": "^3.4|^4.0|^5.0", - "symfony/framework-bundle": "^3.4|^4.0|^5.0", - "symfony/http-kernel": "^3.4|^4.0|^5.0" - }, - "require-dev": { - "doctrine/doctrine-bundle": "^1.8|^2.0", - "doctrine/orm": "^2.3", - "friendsofphp/php-cs-fixer": "^2.8", - "friendsoftwig/twigcs": "^3.1.2", - "symfony/http-client": "^4.3|^5.0", - "symfony/phpunit-bridge": "^4.3|^5.0", - "symfony/process": "^3.4|^4.0|^5.0", - "symfony/security-core": "^3.4|^4.0|^5.0", - "symfony/yaml": "^3.4|^4.0|^5.0" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Bundle\\MakerBundle\\": "src/" - } - }, + "conflict": { + "3f/pygmentize": "<1.2", + "adodb/adodb-php": "<5.20.12", + "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", + "amphp/artax": "<1.0.6|>=2,<2.0.6", + "amphp/http": "<1.0.1", + "amphp/http-client": ">=4,<4.4", + "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6", + "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", + "aws/aws-sdk-php": ">=3,<3.2.1", + "bagisto/bagisto": "<0.1.5", + "barrelstrength/sprout-base-email": "<1.2.7", + "barrelstrength/sprout-forms": "<3.9", + "baserproject/basercms": ">=4,<=4.3.6|>=4.4,<4.4.1", + "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", + "bolt/bolt": "<3.7.2", + "bolt/core": "<4.1.13", + "brightlocal/phpwhois": "<=4.2.5", + "buddypress/buddypress": "<5.1.2", + "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.5.18|>=3.6,<3.6.15|>=3.7,<3.7.7", + "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cartalyst/sentry": "<=2.1.6", + "centreon/centreon": "<18.10.8|>=19,<19.4.5", + "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "codeigniter/framework": "<=3.0.6", + "composer/composer": "<1.10.22|>=2-alpha.1,<2.0.13", + "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/core": ">=2,<3.5.39", + "contao/core-bundle": ">=4,<4.4.52|>=4.5,<4.9.6|= 4.10.0", + "contao/listing-bundle": ">=4,<4.4.8", + "datadog/dd-trace": ">=0.30,<0.30.2", + "david-garcia/phpwhois": "<=4.3.1", + "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1", + "directmailteam/direct-mail": "<5.2.4", + "doctrine/annotations": ">=1,<1.2.7", + "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", + "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2", + "doctrine/doctrine-bundle": "<1.5.2", + "doctrine/doctrine-module": "<=0.7.1", + "doctrine/mongodb-odm": ">=1,<1.0.2", + "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", + "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", + "dolibarr/dolibarr": "<11.0.4", + "dompdf/dompdf": ">=0.6,<0.6.2", + "drupal/core": ">=7,<7.80|>=8,<8.9.14|>=9,<9.0.12|>=9.1,<9.1.7", + "drupal/drupal": ">=7,<7.80|>=8,<8.9.14|>=9,<9.0.12|>=9.1,<9.1.7", + "dweeves/magmi": "<=0.7.24", + "endroid/qr-code-bundle": "<3.4.2", + "enshrined/svg-sanitize": "<0.13.1", + "erusev/parsedown": "<1.7.2", + "ezsystems/demobundle": ">=5.4,<5.4.6.1", + "ezsystems/ez-support-tools": ">=2.2,<2.2.3", + "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", + "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", + "ezsystems/ezplatform": ">=1.7,<1.7.9.1|>=1.13,<1.13.5.1|>=2.5,<2.5.4", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6", + "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<=1.3.1", + "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<=1.3.1", + "ezsystems/ezplatform-user": ">=1,<1.0.1", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<=7.5.15.1", + "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.6|>=5.4,<5.4.14.2|>=2011,<2017.12.7.3|>=2018.6,<2018.6.1.4|>=2018.9,<2018.9.1.3|>=2019.3,<2019.3.5.1", + "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1", + "ezyang/htmlpurifier": "<4.1.1", + "facade/ignition": "<1.16.14|>=2,<2.4.2|>=2.5,<2.5.2", + "firebase/php-jwt": "<2", + "flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15", + "flarum/tags": "<=0.1-beta.13", + "fluidtypo3/vhs": "<5.1.1", + "fooman/tcpdf": "<6.2.22", + "forkcms/forkcms": "<5.8.3", + "fossar/tcpdf-parser": "<6.2.22", + "francoisjacquet/rosariosis": "<6.5.1", + "friendsofsymfony/oauth2-php": "<1.3", + "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", + "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", + "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", + "fuel/core": "<1.8.1", + "getgrav/grav": "<1.7.11", + "getkirby/cms": "<3.5.4", + "getkirby/panel": "<2.5.14", + "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", + "gree/jose": "<=2.2", + "gregwar/rst": "<1.0.3", + "guzzlehttp/guzzle": ">=4-rc.2,<4.2.4|>=5,<5.3.1|>=6,<6.2.1", + "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", + "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4", + "illuminate/database": "<6.20.26|>=7,<8.40", + "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "illuminate/view": ">=7,<7.1.2", + "impresscms/impresscms": "<=1.4.2", + "ivankristianto/phpwhois": "<=4.3", + "james-heinrich/getid3": "<1.9.9", + "joomla/archive": "<1.1.10", + "joomla/session": "<1.3.1", + "jsmitty12/phpwhois": "<5.1", + "kazist/phpwhois": "<=4.2.6", + "kitodo/presentation": "<3.1.2", + "klaviyo/magento2-extension": ">=1,<3", + "kreait/firebase-php": ">=3.2,<3.8.1", + "la-haute-societe/tcpdf": "<6.2.22", + "laravel/framework": "<6.20.26|>=7,<8.40", + "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", + "league/commonmark": "<0.18.3", + "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", + "librenms/librenms": "<21.1", + "livewire/livewire": ">2.2.4,<2.2.6", + "magento/community-edition": ">=2,<2.2.10|>=2.3,<2.3.3", + "magento/magento1ce": "<1.9.4.3", + "magento/magento1ee": ">=1,<1.14.4.3", + "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", + "marcwillmann/turn": "<0.3.3", + "mautic/core": "<3.3.2|= 2.13.1", + "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", + "mittwald/typo3_forum": "<1.2.1", + "monolog/monolog": ">=1.8,<1.12", + "moodle/moodle": "<3.5.17|>=3.7,<3.7.9|>=3.8,<3.8.8|>=3.9,<3.9.5|>=3.10,<3.10.2", + "namshi/jose": "<2.2", + "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.9.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", + "neos/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", + "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", + "nystudio107/craft-seomatic": "<3.3", + "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", + "october/backend": "<1.1.2", + "october/cms": "= 1.1.1|= 1.0.471|= 1.0.469|>=1.0.319,<1.0.469", + "october/october": ">=1.0.319,<1.0.466", + "october/rain": "<1.0.472|>=1.1,<1.1.2", + "onelogin/php-saml": "<2.10.4", + "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", + "opencart/opencart": "<=3.0.3.2", + "openid/php-openid": "<2.3", + "openmage/magento-lts": "<=19.4.12|>=20,<=20.0.8", + "orchid/platform": ">=9,<9.4.4", + "oro/crm": ">=1.7,<1.7.4", + "oro/platform": ">=1.7,<1.7.4", + "padraic/humbug_get_contents": "<1.1.2", + "pagarme/pagarme-php": ">=0,<3", + "paragonie/random_compat": "<2", + "passbolt/passbolt_api": "<2.11", + "paypal/merchant-sdk-php": "<3.12", + "pear/archive_tar": "<1.4.12", + "personnummer/personnummer": "<3.0.2", + "phanan/koel": "<5.1.4", + "phpfastcache/phpfastcache": ">=5,<5.0.13", + "phpmailer/phpmailer": "<6.1.6|>=6.1.8,<6.4.1", + "phpmussel/phpmussel": ">=1,<1.6", + "phpmyadmin/phpmyadmin": "<4.9.6|>=5,<5.0.3", + "phpoffice/phpexcel": "<1.8.2", + "phpoffice/phpspreadsheet": "<1.16", + "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7", + "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", + "phpwhois/phpwhois": "<=4.2.5", + "phpxmlrpc/extras": "<0.6.1", + "pimcore/pimcore": "<6.8.8", + "pocketmine/pocketmine-mp": "<3.15.4", + "pressbooks/pressbooks": "<5.18", + "prestashop/autoupgrade": ">=4,<4.10.1", + "prestashop/contactform": ">1.0.1,<4.3", + "prestashop/gamification": "<2.3.2", + "prestashop/productcomments": ">=4,<4.2.1", + "prestashop/ps_emailsubscription": "<2.6.1", + "prestashop/ps_facetedsearch": "<3.4.1", + "privatebin/privatebin": "<1.2.2|>=1.3,<1.3.2", + "propel/propel": ">=2-alpha.1,<=2-alpha.7", + "propel/propel1": ">=1,<=1.7.1", + "pterodactyl/panel": "<0.7.19|>=1-rc.0,<=1-rc.6", + "pusher/pusher-php-server": "<2.2.1", + "pwweb/laravel-core": "<=0.3.6-beta", + "rainlab/debugbar-plugin": "<3.1", + "rmccue/requests": ">=1.6,<1.8", + "robrichards/xmlseclibs": "<3.0.4", + "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", + "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", + "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", + "sensiolabs/connect": "<4.2.3", + "serluck/phpwhois": "<=4.2.6", + "shopware/core": "<=6.3.5.2", + "shopware/platform": "<=6.3.5.2", + "shopware/production": "<=6.3.5.2", + "shopware/shopware": "<=5.6.9", + "silverstripe/admin": ">=1.0.3,<1.0.4|>=1.1,<1.1.1", + "silverstripe/assets": ">=1,<1.4.7|>=1.5,<1.5.2", + "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4", + "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", + "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", + "silverstripe/framework": "<4.4.7|>=4.5,<4.5.4", + "silverstripe/graphql": ">=2,<2.0.5|>=3,<3.1.2|>=3.2,<3.2.4", + "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", + "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", + "silverstripe/subsites": ">=2,<2.1.1", + "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", + "silverstripe/userforms": "<3", + "simple-updates/phpwhois": "<=1", + "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", + "simplesamlphp/simplesamlphp": "<1.18.6", + "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplito/elliptic-php": "<1.0.6", + "slim/slim": "<2.6", + "smarty/smarty": "<3.1.39", + "socalnick/scn-social-auth": "<1.15.2", + "socialiteproviders/steam": "<1.1", + "spoonity/tcpdf": "<6.2.22", + "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", + "ssddanbrown/bookstack": "<0.29.2", + "stormpath/sdk": ">=0,<9.9.99", + "studio-42/elfinder": "<2.1.49", + "sulu/sulu": "<1.6.34|>=2,<2.0.10|>=2.1,<2.1.1", + "swiftmailer/swiftmailer": ">=4,<5.4.5", + "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", + "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/grid-bundle": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/resource-bundle": "<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", + "sylius/sylius": "<1.6.9|>=1.7,<1.7.9|>=1.8,<1.8.3", + "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99", + "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-versionedfiles": "<=2.0.3", + "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", + "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", + "symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5", + "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", + "symfony/mime": ">=4.3,<4.3.8", + "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/polyfill": ">=1,<1.10", + "symfony/polyfill-php55": ">=1,<1.10", + "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/routing": ">=2,<2.0.19", + "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", + "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", + "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", + "symfony/serializer": ">=2,<2.0.11", + "symfony/symfony": ">=2,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", + "symfony/translation": ">=2,<2.0.17", + "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", + "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", + "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", + "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "t3g/svg-sanitizer": "<1.0.3", + "tecnickcom/tcpdf": "<6.2.22", + "thelia/backoffice-default-template": ">=2.1,<2.1.2", + "thelia/thelia": ">=2.1-beta.1,<2.1.3", + "theonedemon/phpwhois": "<=4.2.5", + "titon/framework": ">=0,<9.9.99", + "truckersmp/phpwhois": "<=4.3.1", + "twig/twig": "<1.38|>=2,<2.7", + "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.25|>=10,<10.4.14|>=11,<11.1.1", + "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.25|>=10,<10.4.14|>=11,<11.1.1", + "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", + "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", + "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", + "ua-parser/uap-php": "<3.8", + "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", + "vrana/adminer": "<4.7.9", + "wallabag/tcpdf": "<6.2.22", + "wikimedia/parsoid": "<0.12.2", + "willdurand/js-translation-bundle": "<2.1.1", + "wp-cli/wp-cli": "<2.5", + "yii2mod/yii2-cms": "<1.9.2", + "yiisoft/yii": ">=1.1.14,<1.1.15", + "yiisoft/yii2": "<2.0.38", + "yiisoft/yii2-bootstrap": "<2.0.4", + "yiisoft/yii2-dev": "<2.0.15", + "yiisoft/yii2-elasticsearch": "<2.0.5", + "yiisoft/yii2-gii": "<2.0.4", + "yiisoft/yii2-jui": "<2.0.4", + "yiisoft/yii2-redis": "<2.0.8", + "yoast-seo-for-typo3/yoast_seo": "<7.2.1", + "yourls/yourls": "<1.7.4", + "zendesk/zendesk_api_client_php": "<2.2.11", + "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", + "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5", + "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", + "zendframework/zend-diactoros": ">=1,<1.8.4", + "zendframework/zend-feed": ">=1,<2.10.3", + "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-http": ">=1,<2.8.1", + "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", + "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2", + "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-session": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.9|>=2.3,<2.3.4", + "zendframework/zend-validator": ">=2.3,<2.3.6", + "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zendframework": "<2.5.1", + "zendframework/zendframework1": "<1.12.20", + "zendframework/zendopenid": ">=2,<2.0.2", + "zendframework/zendxml": ">=1,<1.0.1", + "zetacomponents/mail": "<1.8.2", + "zf-commons/zfc-user": "<1.2.2", + "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", + "zfr/zfr-oauth2-server-module": "<0.1.2", + "zoujingli/thinkadmin": "<6.0.22" + }, + "default-branch": true, + "type": "metapackage", "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "role": "maintainer" + }, + { + "name": "Ilya Tribusean", + "email": "slash3b@gmail.com", + "role": "maintainer" } ], - "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.", - "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html", - "keywords": [ - "code generator", - "generator", - "scaffold", - "scaffolding" + "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "support": { + "issues": "https://github.com/Roave/SecurityAdvisories/issues", + "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories", + "type": "tidelift" + } ], - "time": "2019-11-07T00:56:03+00:00" + "time": "2021-06-01T22:04:47+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v5.0.2", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "010cf42a81e7bec744edfdef5f76d6394f4906a7" + "reference": "15cab721487b7bf43ad545a1e7d0095782e26f8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/010cf42a81e7bec744edfdef5f76d6394f4906a7", - "reference": "010cf42a81e7bec744edfdef5f76d6394f4906a7", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/15cab721487b7bf43ad545a1e7d0095782e26f8c", + "reference": "15cab721487b7bf43ad545a1e7d0095782e26f8c", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": ">=7.1.3", + "symfony/deprecation-contracts": "^2.1" }, "conflict": { - "phpunit/phpunit": "<5.4.3" + "phpunit/phpunit": "<7.5|9.1.2" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0" }, "suggest": { "symfony/error-handler": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" @@ -4238,9 +8086,6 @@ ], "type": "symfony-bridge", "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - }, "thanks": { "name": "phpunit/phpunit", "url": "https://github.com/sebastianbergmann/phpunit" @@ -4271,21 +8116,43 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony PHPUnit Bridge", + "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", - "time": "2019-11-28T14:20:16+00:00" + "support": { + "source": "https://github.com/symfony/phpunit-bridge/tree/v5.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-26T17:57:12+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "ivanstan/tle-php": 20, + "roave/security-advisories": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.4", + "php": "^8.0", "ext-ctype": "*", + "ext-dom": "*", "ext-iconv": "*", "ext-json": "*" }, - "platform-dev": [] + "platform-dev": [], + "plugin-api-version": "2.0.0" } diff --git a/config/custom/general.json b/config/custom/general.json deleted file mode 100644 index e70dacc..0000000 --- a/config/custom/general.json +++ /dev/null @@ -1,210 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "TLE API", - "version": "1.3.0" - }, - "servers": [ - { - "url": "/" - } - ], - "paths": {}, - "components": { - "schemas": { - "ValueUnit": { - "properties": { - "value": { - "type": "float" - }, - "unit": { - "type": "string" - } - } - }, - "Pagination": { - "properties": { - "@id": { - "type": "string" - }, - "@type": { - "type": "string" - }, - "first": { - "type": "string" - }, - "previous": { - "type": "string" - }, - "next": { - "type": "string" - }, - "last": { - "type": "string" - } - }, - "type": "object" - }, - "Exception": { - "properties": { - "response": { - "properties": { - "code": { - "type": "integer" - }, - "message": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "METAR": { - "allOf": [ - { - "properties": { - "icao": { - "type": "string", - "example": "LYBE" - }, - "date": { - "type": "string", - "example": "2018-10-23T19:00:00+00:00" - }, - "temperature": { - "$ref": "#/components/schemas/ValueUnit" - }, - "dewPoint": { - "$ref": "#/components/schemas/ValueUnit" - }, - "pressure": { - "$ref": "#/components/schemas/ValueUnit" - }, - "raw": { - "type": "string", - "example": "METAR LYBE 171530Z 11004KT CAVOK 22/04 Q1018 NOSIG" - } - }, - "type": "object" - } - ] - }, - "TLE": { - "allOf": [ - { - "properties": { - "@id": { - "type": "string", - "example": "https://ivanstanojevic.me/api/tle/43630" - }, - "@type": { - "type": "string", - "example": "TleModel" - }, - "satelliteId": { - "type": "integer", - "example": "43630" - }, - "date": { - "type": "string", - "example": "2018-10-21T11:40:23+00:00" - }, - "name": { - "type": "string", - "example": "HTV-7 (KOUNOTORI 7)" - }, - "line1": { - "type": "string", - "example": "1 43630U 18073A 18285.64337553 .00002296 00000-0 42374-4 0 9998" - }, - "line2": { - "type": "string", - "example": "2 43630 51.6412 153.3949 0003517 275.8456 137.9883 15.53813372136786" - } - }, - "type": "object" - } - ] - } - }, - "responses": { - "404": { - "description": "Resource not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Exception" - }, - "example": { - "response": { - "code": 404, - "message": "Not found" - } - } - } - } - }, - "500": { - "description": "Server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Exception" - }, - "example": { - "response": { - "code": 500, - "message": "Server error" - } - } - } - } - } - }, - "parameters": { - "search": { - "name": "search", - "in": "query", - "description": "Search string", - "schema": { - "type": "string", - "default": "*" - } - }, - "sortDirection": { - "name": "sort-dir", - "in": "query", - "description": "Sort direction", - "schema": { - "type": "string", - "default": "asc", - "enum": [ - "asc", - "desc" - ] - } - }, - "pageNumber": { - "name": "page", - "in": "query", - "description": "Page number", - "schema": { - "type": "integer", - "default": 1, - "minimum": "1" - } - }, - "pageSize": { - "name": "page-size", - "in": "query", - "description": "Number of items per page", - "schema": { - "type": "integer", - "default": "50" - } - } - } - } -} diff --git a/config/custom/source.yaml b/config/custom/source.yaml deleted file mode 100644 index c442556..0000000 --- a/config/custom/source.yaml +++ /dev/null @@ -1,47 +0,0 @@ -- https://www.celestrak.com/NORAD/elements/tle-new.txt -- https://www.celestrak.com/NORAD/elements/stations.txt -- https://www.celestrak.com/NORAD/elements/visual.txt -- https://www.celestrak.com/NORAD/elements/active.txt -- https://www.celestrak.com/NORAD/elements/analyst.txt -- https://www.celestrak.com/NORAD/elements/1999-025.txt -- https://www.celestrak.com/NORAD/elements/iridium-33-debris.txt -- https://www.celestrak.com/NORAD/elements/cosmos-2251-debris.txt -- https://www.celestrak.com/NORAD/elements/2012-044.txt -- https://www.celestrak.com/NORAD/elements/weather.txt -- https://www.celestrak.com/NORAD/elements/noaa.txt -- https://www.celestrak.com/NORAD/elements/goes.txt -- https://www.celestrak.com/NORAD/elements/resource.txt -- https://www.celestrak.com/NORAD/elements/sarsat.txt -- https://www.celestrak.com/NORAD/elements/dmc.txt -- https://www.celestrak.com/NORAD/elements/tdrss.txt -- https://www.celestrak.com/NORAD/elements/argos.txt -- https://www.celestrak.com/NORAD/elements/planet.txt -- https://www.celestrak.com/NORAD/elements/spire.txt -- https://www.celestrak.com/NORAD/elements/geo.txt -- https://www.celestrak.com/NORAD/elements/intelsat.txt -- https://www.celestrak.com/NORAD/elements/ses.txt -- https://www.celestrak.com/NORAD/elements/iridium.txt -- https://www.celestrak.com/NORAD/elements/iridium-NEXT.txt -- https://www.celestrak.com/NORAD/elements/orbcomm.txt -- https://www.celestrak.com/NORAD/elements/globalstar.txt -- https://www.celestrak.com/NORAD/elements/amateur.txt -- https://www.celestrak.com/NORAD/elements/x-comm.txt -- https://www.celestrak.com/NORAD/elements/other-comm.txt -- https://www.celestrak.com/NORAD/elements/gorizont.txt -- https://www.celestrak.com/NORAD/elements/raduga.txt -- https://www.celestrak.com/NORAD/elements/molniya.txt -- https://www.celestrak.com/NORAD/elements/gps-ops.txt -- https://www.celestrak.com/NORAD/elements/glo-ops.txt -- https://www.celestrak.com/NORAD/elements/galileo.txt -- https://www.celestrak.com/NORAD/elements/beidou.txt -- https://www.celestrak.com/NORAD/elements/sbas.txt -- https://www.celestrak.com/NORAD/elements/nnss.txt -- https://www.celestrak.com/NORAD/elements/musson.txt -- https://www.celestrak.com/NORAD/elements/science.txt -- https://www.celestrak.com/NORAD/elements/geodetic.txt -- https://www.celestrak.com/NORAD/elements/engineering.txt -- https://www.celestrak.com/NORAD/elements/education.txt -- https://www.celestrak.com/NORAD/elements/military.txt -- https://www.celestrak.com/NORAD/elements/radar.txt -- https://www.celestrak.com/NORAD/elements/cubesat.txt -- https://www.celestrak.com/NORAD/elements/other.txt \ No newline at end of file diff --git a/config/custom/tle.json b/config/custom/tle.json deleted file mode 100644 index 1af51be..0000000 --- a/config/custom/tle.json +++ /dev/null @@ -1,313 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "TLE API", - "version": "1.3.0" - }, - "servers": [ - { - "url": "/" - } - ], - "paths": { - "/api/tle/{id}": { - "get": { - "summary": "Record", - "operationId": "tle-record", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "id", - "required": true, - "schema": { - "type": "integer" - } - } - ], - "responses": { - "200": { - "description": "Record found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TLE" - } - } - } - }, - "404": { - "$ref": "#/components/responses/404" - }, - "500": { - "$ref": "#/components/responses/500" - } - } - } - }, - "/api/tle": { - "get": { - "summary": "Collection", - "operationId": "tle-collection", - "parameters": [ - { - "$ref": "#/components/parameters/search" - }, - { - "name": "prn", - "in": "query", - "description": "Filter by pseudo-random noise.", - "schema": { - "type": "number", - "default": "null" - } - }, - { - "name": "sort", - "in": "query", - "description": "Sort field", - "schema": { - "type": "string", - "default": "name", - "enum": [ - "id", - "name" - ] - } - }, - { - "$ref": "#/components/parameters/sortDirection" - }, - { - "$ref": "#/components/parameters/pageNumber" - }, - { - "$ref": "#/components/parameters/pageSize" - } - ], - "responses": { - "200": { - "description": "Tle collection", - "content": { - "application/json": { - "schema": { - "properties": { - "@context": { - "type": "string", - "example": "http://www.w3.org/ns/hydra/context.jsonld" - }, - "@id": { - "type": "string", - "example": "https://ivanstanojevic.me/api/tle" - }, - "@type": { - "type": "string", - "example": "Collection" - }, - "totalItems": { - "type": "integer", - "example": "50" - }, - "member": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TLE" - } - }, - "parameters": { - "type": "array" - }, - "view": { - "type": "object", - "properties": { - "@id": { - "type": "string" - }, - "@type": { - "type": "string" - }, - "first": { - "type": "string" - }, - "previous": { - "type": "string" - }, - "next": { - "type": "string" - }, - "last": { - "type": "string" - } - } - } - }, - "type": "object" - } - } - } - }, - "500": { - "$ref": "#/components/responses/500" - } - } - } - } - }, - "components": { - "schemas": { - "Pagination": { - "properties": { - "@id": { - "type": "string" - }, - "@type": { - "type": "string" - }, - "first": { - "type": "string" - }, - "previous": { - "type": "string" - }, - "next": { - "type": "string" - }, - "last": { - "type": "string" - } - }, - "type": "object" - }, - "Exception": { - "properties": { - "response": { - "properties": { - "code": { - "type": "integer" - }, - "message": { - "type": "string" - } - }, - "type": "object" - } - }, - "type": "object" - }, - "TLE": { - "allOf": [ - { - "properties": { - "@id": { - "type": "string", - "example": "https://ivanstanojevic.me/api/tle/43630" - }, - "@type": { - "type": "string", - "example": "TleModel" - }, - "satelliteId": { - "type": "integer", - "example": "43630" - }, - "name": { - "type": "string", - "example": "HTV-7 (KOUNOTORI 7)" - }, - "date": { - "type": "string", - "example": "2018-10-21T11:40:23+00:00" - }, - "line1": { - "type": "string", - "example": "1 43630U 18073A 18285.64337553 .00002296 00000-0 42374-4 0 9998" - }, - "line2": { - "type": "string", - "example": "2 43630 51.6412 153.3949 0003517 275.8456 137.9883 15.53813372136786" - } - }, - "type": "object" - } - ] - } - }, - "responses": { - "404": { - "description": "Resource not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Exception" - }, - "example": { - "response": { - "code": 404, - "message": "Not found" - } - } - } - } - }, - "500": { - "description": "Server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Exception" - }, - "example": { - "response": { - "code": 500, - "message": "Server error" - } - } - } - } - } - }, - "parameters": { - "search": { - "name": "search", - "in": "query", - "description": "Search string", - "schema": { - "type": "string", - "default": "*" - } - }, - "sortDirection": { - "name": "sort-dir", - "in": "query", - "description": "Sort direction", - "schema": { - "type": "string", - "default": "asc", - "enum": [ - "asc", - "desc" - ] - } - }, - "pageNumber": { - "name": "page", - "in": "query", - "description": "Page number", - "schema": { - "type": "integer", - "default": 1, - "minimum": "1" - } - }, - "pageSize": { - "name": "page-size", - "in": "query", - "description": "Number of items per page", - "schema": { - "type": "integer", - "default": "50" - } - } - } - } -} diff --git a/config/packages/doctrine_migrations.yaml b/config/packages/doctrine_migrations.yaml deleted file mode 100644 index 3bf0fbc..0000000 --- a/config/packages/doctrine_migrations.yaml +++ /dev/null @@ -1,5 +0,0 @@ -doctrine_migrations: - dir_name: '%kernel.project_dir%/src/Migrations' - # namespace is arbitrary but should be different from App\Migrations - # as migrations classes should NOT be autoloaded - namespace: DoctrineMigrations diff --git a/config/packages/test/twig.yaml b/config/packages/test/twig.yaml deleted file mode 100644 index 8c6e0b4..0000000 --- a/config/packages/test/twig.yaml +++ /dev/null @@ -1,2 +0,0 @@ -twig: - strict_variables: true diff --git a/config/parameters.yaml b/config/parameters.yaml deleted file mode 100644 index 89b37f7..0000000 --- a/config/parameters.yaml +++ /dev/null @@ -1,2 +0,0 @@ -parameters: - app_name: 'TLE API' diff --git a/config/routes.yaml b/config/routes.yaml deleted file mode 100644 index c3283aa..0000000 --- a/config/routes.yaml +++ /dev/null @@ -1,3 +0,0 @@ -#index: -# path: / -# controller: App\Controller\DefaultController::index diff --git a/config/routes/annotations.yaml b/config/routes/annotations.yaml deleted file mode 100644 index d49a502..0000000 --- a/config/routes/annotations.yaml +++ /dev/null @@ -1,3 +0,0 @@ -controllers: - resource: ../../src/Controller/ - type: annotation diff --git a/config/routes/dev/framework.yaml b/config/routes/dev/framework.yaml deleted file mode 100644 index bcbbf13..0000000 --- a/config/routes/dev/framework.yaml +++ /dev/null @@ -1,3 +0,0 @@ -_errors: - resource: '@FrameworkBundle/Resources/config/routing/errors.xml' - prefix: /_error diff --git a/deploy.php b/deploy.php new file mode 100644 index 0000000..2995177 --- /dev/null +++ b/deploy.php @@ -0,0 +1,72 @@ +user('glutenfr') + ->port(2233) + ->stage('production') + ->set('deploy_path', '~/projects/tle.ivanstanojevic.me'); + +task('test', function () { + set('symfony_env', 'dev'); + runLocally('bin/phpunit'); +}); + +task('deploy:dump-env', function () { + run('cd {{release_path}} && {{bin/composer}} dump-env prod'); +}); + +task( + 'deploy', + [ + 'deploy:info', + 'deploy:prepare', + 'deploy:lock', + 'deploy:release', + 'deploy:update_code', + 'deploy:clear_paths', + 'deploy:create_cache_dir', + 'deploy:shared', + 'deploy:assets', + 'deploy:writable', + 'deploy:vendors', + 'deploy:cache:clear', + 'deploy:cache:warmup', + 'deploy:dump-env', + 'database:migrate', + 'deploy:symlink', + 'deploy:unlock', + 'cleanup', + ] +); + +before('deploy', 'test'); +after('deploy:failed', 'deploy:unlock'); diff --git a/config/bootstrap.php b/etc/bootstrap.php similarity index 86% rename from config/bootstrap.php rename to etc/bootstrap.php index 1a0c60f..452a4fb 100644 --- a/config/bootstrap.php +++ b/etc/bootstrap.php @@ -15,16 +15,16 @@ && ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'] ) { foreach ($env as $k => $v) { - $_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && 0 !== strpos($k, 'HTTP_') ? $_SERVER[$k] : $v); + $_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && strncmp($k, 'HTTP_', 5) !== 0 ? $_SERVER[$k] : $v); } -} elseif (!class_exists(Dotenv::class)) { - throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); -} else { +} elseif (class_exists(Dotenv::class)) { // load all the .env files - (new Dotenv(false))->loadEnv(dirname(__DIR__) . '/.env'); + (new Dotenv())->loadEnv(dirname(__DIR__) . '/.env'); +} else { + throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); } -if ('test' === $_SERVER['APP_ENV']) { +if ($_SERVER['APP_ENV'] === 'test') { $kernel = new Kernel($_SERVER['APP_ENV'], true); // create a "test" kernel $kernel->boot(); diff --git a/config/bundles.php b/etc/bundles.php similarity index 72% rename from config/bundles.php rename to etc/bundles.php index e1fa41c..190f48c 100644 --- a/config/bundles.php +++ b/etc/bundles.php @@ -4,7 +4,7 @@ Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], - Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], - Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], + Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], + Sentry\SentryBundle\SentryBundle::class => ['prod' => true], ]; diff --git a/etc/custom/source.yaml b/etc/custom/source.yaml new file mode 100644 index 0000000..79c1987 --- /dev/null +++ b/etc/custom/source.yaml @@ -0,0 +1,70 @@ +- 'https://celestrak.com/NORAD/elements/1999-025.txt' +- 'https://celestrak.com/NORAD/elements/2012-044.txt' +- 'https://celestrak.com/NORAD/elements/2019-006.txt' +- 'https://celestrak.com/NORAD/elements/active.txt' +- 'https://celestrak.com/NORAD/elements/amateur.txt' +- 'https://celestrak.com/NORAD/elements/analyst.txt' +- 'https://celestrak.com/NORAD/elements/argos.txt' +- 'https://celestrak.com/NORAD/elements/beidou.txt' +- 'https://celestrak.com/NORAD/elements/cosmos-2251-debris.txt' +- 'https://celestrak.com/NORAD/elements/cubesat.txt' +- 'https://celestrak.com/NORAD/elements/dmc.txt' +- 'https://celestrak.com/NORAD/elements/education.txt' +- 'https://celestrak.com/NORAD/elements/engineering.txt' +- 'https://celestrak.com/NORAD/elements/galileo.txt' +- 'https://celestrak.com/NORAD/elements/geo.txt' +- 'https://celestrak.com/NORAD/elements/geodetic.txt' +- 'https://celestrak.com/NORAD/elements/glo-ops.txt' +- 'https://celestrak.com/NORAD/elements/globalstar.txt' +- 'https://celestrak.com/NORAD/elements/gnss.txt' +- 'https://celestrak.com/NORAD/elements/goes.txt' +- 'https://celestrak.com/NORAD/elements/gorizont.txt' +- 'https://celestrak.com/NORAD/elements/gps-ops.txt' +- 'https://celestrak.com/NORAD/elements/intelsat.txt' +- 'https://celestrak.com/NORAD/elements/iridium-33-debris.txt' +- 'https://celestrak.com/NORAD/elements/iridium-NEXT.txt' +- 'https://celestrak.com/NORAD/elements/iridium.txt' +- 'https://celestrak.com/NORAD/elements/military.txt' +- 'https://celestrak.com/NORAD/elements/molniya.txt' +- 'https://celestrak.com/NORAD/elements/musson.txt' +- 'https://celestrak.com/NORAD/elements/nnss.txt' +- 'https://celestrak.com/NORAD/elements/noaa.txt' +- 'https://celestrak.com/NORAD/elements/oneweb.txt' +- 'https://celestrak.com/NORAD/elements/orbcomm.txt' +- 'https://celestrak.com/NORAD/elements/other-comm.txt' +- 'https://celestrak.com/NORAD/elements/other.txt' +- 'https://celestrak.com/NORAD/elements/planet.txt' +- 'https://celestrak.com/NORAD/elements/radar.txt' +- 'https://celestrak.com/NORAD/elements/raduga.txt' +- 'https://celestrak.com/NORAD/elements/resource.txt' +- 'https://celestrak.com/NORAD/elements/sarsat.txt' +- 'https://celestrak.com/NORAD/elements/satnogs.txt' +- 'https://celestrak.com/NORAD/elements/sbas.txt' +- 'https://celestrak.com/NORAD/elements/science.txt' +- 'https://celestrak.com/NORAD/elements/ses.txt' +- 'https://celestrak.com/NORAD/elements/spire.txt' +- 'https://celestrak.com/NORAD/elements/starlink.txt' +- 'https://celestrak.com/NORAD/elements/stations.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/cpf.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/glonass.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/gps.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/intelsat.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/iss.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/meteosat.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/oneweb.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/orbcomm.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/planet.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/ses.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/starlink-V1.0-20.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/starlink.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/telesat.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/testcase/glonass.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/testcase/glonass_2008_01_25_1300.txt' +- 'https://celestrak.com/NORAD/elements/supplemental/testcase/gps.txt' +- 'https://celestrak.com/NORAD/elements/swarm.txt' +- 'https://celestrak.com/NORAD/elements/tdrss.txt' +- 'https://celestrak.com/NORAD/elements/tle-new.txt' +- 'https://celestrak.com/NORAD/elements/visual.txt' +- 'https://celestrak.com/NORAD/elements/weather.txt' +- 'https://celestrak.com/NORAD/elements/x-comm.txt' +- 'https://celestrak.com/satcat/gpz.php' diff --git a/etc/custom/tle.json b/etc/custom/tle.json new file mode 100644 index 0000000..18927df --- /dev/null +++ b/etc/custom/tle.json @@ -0,0 +1,517 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "TLE API", + "version": "" + }, + "servers": [ + { + "url": "/" + } + ], + "paths": { + "/api/tle/{id}": { + "get": { + "summary": "Record", + "operationId": "record", + "description": "Return single TleModel for requested satellite id", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Satellite id", + "required": true, + "schema": { + "example": 43638, + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Resource found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TleModel" + } + } + } + }, + "404": { + "$ref": "#/components/responses/404" + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } + }, + "/api/tle": { + "get": { + "summary": "Collection", + "operationId": "collection", + "description": "Return collection of TleModels depending on requested parameters", + "parameters": [ + { + "$ref": "#/components/parameters/search" + }, + { + "name": "sort", + "in": "query", + "description": "Sort by", + "schema": { + "type": "string", + "default": "name", + "enum": [ + "id", + "name", + "popularity", + "inclination", + "eccentricity", + "period" + ] + } + }, + { + "$ref": "#/components/parameters/sortDirection" + }, + { + "$ref": "#/components/parameters/pageNumber" + }, + { + "$ref": "#/components/parameters/pageSize" + }, + { + "name": "eccentricity[gte]", + "in": "query", + "description": "Filter records with orbital eccentricity greater then or equal to the provided value", + "required": false, + "example": 1 + }, + { + "name": "eccentricity[lte]", + "in": "query", + "description": "Filter records with orbital eccentricity less then or equal to the provided value", + "required": false, + "example": 1 + }, + { + "name": "inclination[lt]", + "in": "query", + "description": "Filter records with posigrade orbital inclination", + "required": false, + "example": 90 + }, + { + "name": "inclination[gt]", + "in": "query", + "description": "Filter records with retrograde orbital inclination", + "required": false, + "example": 90 + }, + { + "name": "period[lt]", + "in": "query", + "description": "Filter records with orbital period less than specified", + "required": false, + "example": 255 + }, + { + "name": "period[gt]", + "in": "query", + "description": "Filter records with orbital period greater than specified", + "required": false, + "example": 255 + } + ], + "responses": { + "200": { + "description": "Resource found", + "content": { + "application/json": { + "schema": { + "properties": { + "@context": { + "type": "string", + "example": "http://www.w3.org/ns/hydra/context.jsonld" + }, + "@id": { + "type": "string", + "example": "https://tle.ivanstanojevic.me/api/tle" + }, + "@type": { + "type": "string", + "example": "Collection" + }, + "totalItems": { + "type": "integer", + "example": 10414 + }, + "member": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TleModel" + } + }, + "parameters": { + "type": "object" + }, + "view": { + "type": "object", + "properties": { + "@id": { + "type": "string" + }, + "@type": { + "type": "string" + }, + "first": { + "type": "string" + }, + "previous": { + "type": "string" + }, + "next": { + "type": "string" + }, + "last": { + "type": "string" + } + } + } + }, + "type": "object" + } + } + } + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } + }, + "/api/tle/{id}/propagate": { + "get": { + "summary": "Propagate (experimental)", + "description": "Return propagation result with satellite position and velocity using SGP4 or SDP4 algorithms", + "operationId": "propagate", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Target satellite id for which propagation is calculated", + "required": true, + "schema": { + "example": 43638, + "type": "integer" + } + }, + { + "name": "date", + "in": "query", + "description": "Target date and time", + "required": false, + "schema": { + "type": "string", + "example": "2021-04-20T16:28:40+00:00" + } + } + ], + "responses": { + "200": { + "description": "Resource found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Propagation" + } + } + } + }, + "404": { + "$ref": "#/components/responses/404" + }, + "500": { + "$ref": "#/components/responses/500" + } + } + } + } + }, + "components": { + "schemas": { + "Pagination": { + "properties": { + "@id": { + "type": "string" + }, + "@type": { + "type": "string" + }, + "first": { + "type": "string" + }, + "previous": { + "type": "string" + }, + "next": { + "type": "string" + }, + "last": { + "type": "string" + } + }, + "type": "object" + }, + "Exception": { + "properties": { + "response": { + "properties": { + "message": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "TleModel": { + "allOf": [ + { + "properties": { + "@context": { + "type": "string", + "example": "https://www.w3.org/ns/hydra/context.jsonld" + }, + "@id": { + "type": "string", + "example": "https://tle.ivanstanojevic.me/api/tle/43638" + }, + "@type": { + "type": "string", + "example": "TleModel" + }, + "satelliteId": { + "type": "integer", + "example": 43638 + }, + "name": { + "type": "string", + "example": "1998-067PN" + }, + "date": { + "type": "string", + "example": "2021-02-16T06:41:41+00:00" + }, + "line1": { + "type": "string", + "example": "1 43638U 98067PN 21047.27895714 .00025925 00000-0 18734-3 0 9990" + }, + "line2": { + "type": "string", + "example": "2 43638 51.6322 151.1192 0001883 262.5831 97.4954 15.73313437134937" + } + }, + "type": "object" + } + ] + }, + "Propagation": { + "properties": { + "@context": { + "type": "string", + "example": "https://www.w3.org/ns/hydra/context.jsonld" + }, + "@id": { + "type": "string", + "example": "https://tle.ivanstanojevic.me/api/tle/44859/propagate?date=2021-04-26T08:39:45+00:00" + }, + "@type": { + "type": "string", + "example": "SatellitePropagationResult" + }, + "tle": { + "$ref": "#/components/schemas/TleModel" + }, + "algorithm": { + "type": "string", + "enum": ["SGP4", "SDP4"], + "description": "Algorithm used for propagation. Determined based on mean motion.", + "example": "SGP4" + }, + "vector": { + "properties": { + "reference_frame": { + "type": "string", + "example": "ECI" + }, + "position": { + "properties": { + "x": { + "type": "number", + "example": -2450.396984017652 + }, + "y": { + "type": "number", + "example": 6101.198295995954 + }, + "z": { + "type": "number", + "example": -6032.216318229235 + }, + "r": { + "type": "number", + "example": 8922.819046481767 + }, + "unit": { + "type": "string", + "example": "km" + } + }, + "type": "object" + }, + + "velocity": { + "properties": { + "x": { + "type": "number", + "example": -0.1644949004552056 + }, + "y": { + "type": "number", + "example": 4.639904402973215 + }, + "z": { + "type": "number", + "example": 4.406398357056158 + }, + "r": { + "type": "number", + "example": 6.400946642651633 + }, + "unit": { + "type": "string", + "example": "km/s" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "geodetic": { + "properties": { + "latitude": { + "type": "number", + "example": -42.67210184042445 + }, + "longitude": { + "type": "number", + "example": 124.524923099869 + }, + "altitude": { + "type": "number", + "example": 2554.4740343929398 + } + }, + "type": "object" + }, + "parameters": { + "properties": { + "date": { + "type": "string", + "example": "2021-04-26T08:39:45+00:00" + }, + "satelliteId": { + "type": "string", + "example": "44859" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "responses": { + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Exception" + }, + "example": { + "response": { + "message": "Resource not found" + } + } + } + } + }, + "500": { + "description": "Server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Exception" + }, + "example": { + "response": { + "message": "Server has encountered an internal error" + } + } + } + } + } + }, + "parameters": { + "search": { + "name": "search", + "in": "query", + "description": "Search string", + "schema": { + "type": "string", + "default": "*" + } + }, + "sortDirection": { + "name": "sort-dir", + "in": "query", + "description": "Sort direction", + "schema": { + "type": "string", + "default": "asc", + "enum": [ + "asc", + "desc" + ] + } + }, + "pageNumber": { + "name": "page", + "in": "query", + "description": "Page number", + "schema": { + "type": "integer", + "default": 1, + "minimum": 1 + } + }, + "pageSize": { + "name": "page-size", + "in": "query", + "description": "Number of collection member per page", + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 100 + } + } + } + } +} diff --git a/config/packages/cache.yaml b/etc/packages/cache.yaml similarity index 100% rename from config/packages/cache.yaml rename to etc/packages/cache.yaml diff --git a/etc/packages/dev/monolog.yaml b/etc/packages/dev/monolog.yaml new file mode 100644 index 0000000..32039e9 --- /dev/null +++ b/etc/packages/dev/monolog.yaml @@ -0,0 +1,19 @@ +monolog: + handlers: + main: + type: stream + path: php://stderr + level: debug + channels: ["!event"] + # uncomment to get logging in your browser + # you may have to allow bigger header sizes in your Web server configuration + #firephp: + # type: firephp + # level: info + #chromephp: + # type: chromephp + # level: info + console: + type: console + process_psr_3_messages: false + channels: ["!event", "!doctrine", "!console"] diff --git a/config/packages/doctrine.yaml b/etc/packages/doctrine.yaml similarity index 58% rename from config/packages/doctrine.yaml rename to etc/packages/doctrine.yaml index 5e80e77..b5a2432 100644 --- a/config/packages/doctrine.yaml +++ b/etc/packages/doctrine.yaml @@ -1,6 +1,9 @@ doctrine: dbal: url: '%env(resolve:DATABASE_URL)%' + override_url: true + options: + 1002: 'SET sql_mode=(SELECT REPLACE(@@sql_mode, "ONLY_FULL_GROUP_BY", ""))' # IMPORTANT: You MUST configure your server version, # either here or in the DATABASE_URL env var (see .env file) @@ -16,3 +19,11 @@ doctrine: dir: '%kernel.project_dir%/src/Entity' prefix: 'App\Entity' alias: App + + dql: + string_functions: + DATE_FORMAT: DoctrineExtensions\Query\Mysql\DateFormat + CAST: DoctrineExtensions\Query\Mysql\Cast + IF: DoctrineExtensions\Query\Mysql\IfElse + numeric_functions: + ROUND: DoctrineExtensions\Query\Mysql\Round diff --git a/etc/packages/doctrine_migrations.yaml b/etc/packages/doctrine_migrations.yaml new file mode 100644 index 0000000..19b53d5 --- /dev/null +++ b/etc/packages/doctrine_migrations.yaml @@ -0,0 +1,3 @@ +doctrine_migrations: + migrations_paths: + App\Migrations: '%kernel.project_dir%/src/Migrations' diff --git a/config/packages/framework.yaml b/etc/packages/framework.yaml similarity index 100% rename from config/packages/framework.yaml rename to etc/packages/framework.yaml diff --git a/etc/packages/lock.yaml b/etc/packages/lock.yaml new file mode 100644 index 0000000..574879f --- /dev/null +++ b/etc/packages/lock.yaml @@ -0,0 +1,2 @@ +framework: + lock: '%env(LOCK_DSN)%' diff --git a/etc/packages/prod/deprecations.yaml b/etc/packages/prod/deprecations.yaml new file mode 100644 index 0000000..60026a1 --- /dev/null +++ b/etc/packages/prod/deprecations.yaml @@ -0,0 +1,8 @@ +# As of Symfony 5.1, deprecations are logged in the dedicated "deprecation" channel when it exists +#monolog: +# channels: [deprecation] +# handlers: +# deprecation: +# type: stream +# channels: [deprecation] +# path: php://stderr diff --git a/config/packages/prod/doctrine.yaml b/etc/packages/prod/doctrine.yaml similarity index 100% rename from config/packages/prod/doctrine.yaml rename to etc/packages/prod/doctrine.yaml diff --git a/etc/packages/prod/monolog.yaml b/etc/packages/prod/monolog.yaml new file mode 100644 index 0000000..2c02ad8 --- /dev/null +++ b/etc/packages/prod/monolog.yaml @@ -0,0 +1,17 @@ +monolog: + handlers: + main: + type: fingers_crossed + action_level: error + handler: nested + excluded_http_codes: [404, 405] + buffer_size: 50 # How many messages should be saved? Prevent memory leaks + nested: + type: stream + path: php://stderr + level: debug + formatter: monolog.formatter.json + console: + type: console + process_psr_3_messages: false + channels: ["!event", "!doctrine"] diff --git a/config/packages/prod/routing.yaml b/etc/packages/prod/routing.yaml similarity index 100% rename from config/packages/prod/routing.yaml rename to etc/packages/prod/routing.yaml diff --git a/etc/packages/prod/sentry.yaml b/etc/packages/prod/sentry.yaml new file mode 100644 index 0000000..76704fc --- /dev/null +++ b/etc/packages/prod/sentry.yaml @@ -0,0 +1,9 @@ +sentry: + dsn: '%env(SENTRY_DSN)%' + options: + before_send: 'App\Service\SentryCallbackBeforeSend' + environment: '%kernel.environment%' + release: '%env(string:key:version:json:file:COMPOSER_JSON)%' + messenger: + enabled: true # flushes Sentry messages at the end of each message handling + capture_soft_fails: true # captures exceptions marked for retry too diff --git a/etc/packages/rate_limiter.yaml b/etc/packages/rate_limiter.yaml new file mode 100644 index 0000000..a677d37 --- /dev/null +++ b/etc/packages/rate_limiter.yaml @@ -0,0 +1,7 @@ +framework: + rate_limiter: + anonymous_api: + policy: 'sliding_window' + limit: 500 + interval: '60 minutes' + lock_factory: null diff --git a/config/packages/routing.yaml b/etc/packages/routing.yaml similarity index 100% rename from config/packages/routing.yaml rename to etc/packages/routing.yaml diff --git a/config/packages/test/framework.yaml b/etc/packages/test/framework.yaml similarity index 100% rename from config/packages/test/framework.yaml rename to etc/packages/test/framework.yaml diff --git a/etc/packages/test/monolog.yaml b/etc/packages/test/monolog.yaml new file mode 100644 index 0000000..fc40641 --- /dev/null +++ b/etc/packages/test/monolog.yaml @@ -0,0 +1,12 @@ +monolog: + handlers: + main: + type: fingers_crossed + action_level: error + handler: nested + excluded_http_codes: [404, 405] + channels: ["!event"] + nested: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug diff --git a/etc/parameters.yaml b/etc/parameters.yaml new file mode 100644 index 0000000..1d32fae --- /dev/null +++ b/etc/parameters.yaml @@ -0,0 +1,3 @@ +parameters: + env(COMPOSER_JSON): "%kernel.project_dir%/composer.json" + version: '%env(string:key:version:json:file:COMPOSER_JSON)%' diff --git a/etc/routes.yaml b/etc/routes.yaml new file mode 100644 index 0000000..a9bbdc3 --- /dev/null +++ b/etc/routes.yaml @@ -0,0 +1,3 @@ +controllers: + resource: ../src/Controller/ + type: annotation diff --git a/config/services.yaml b/etc/services.yaml similarity index 100% rename from config/services.yaml rename to etc/services.yaml diff --git a/lib/predict/Predict.php b/lib/predict/Predict.php new file mode 100644 index 0000000..9615ca8 --- /dev/null +++ b/lib/predict/Predict.php @@ -0,0 +1,864 @@ + + John A. Magliacane, KD2BD. + + Comments, questions and bugreports should be submitted via + http://sourceforge.net/projects/gpredict/ + More details can be found at the project home page: + + http://gpredict.oz9aec.net/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, visit http://www.fsf.org/ +*/ + +/** + * The main Predict class. Contains constants for use by other classes, as well as + * the prediction logic. + */ +class Predict +{ + const de2ra = 1.74532925E-2; /* Degrees to Radians */ + const pi = 3.1415926535898; /* Pi */ + const pio2 = 1.5707963267949; /* Pi/2 */ + const x3pio2 = 4.71238898; /* 3*Pi/2 */ + const twopi = 6.2831853071796; /* 2*Pi */ + const e6a = 1.0E-6; + const tothrd = 6.6666667E-1; /* 2/3 */ + const xj2 = 1.0826158E-3; /* J2 Harmonic */ + const xj3 = -2.53881E-6; /* J3 Harmonic */ + const xj4 = -1.65597E-6; /* J4 Harmonic */ + const xke = 7.43669161E-2; + const xkmper = 6.378135E3; /* Earth radius km */ + const xmnpda = 1.44E3; /* Minutes per day */ + const km2mi = 0.621371; /* Kilometers per Mile */ + const ae = 1.0; + const ck2 = 5.413079E-4; + const ck4 = 6.209887E-7; + const __f = 3.352779E-3; + const ge = 3.986008E5; + const __s__ = 1.012229; + const qoms2t = 1.880279E-09; + const secday = 8.6400E4; /* Seconds per day */ + const omega_E = 1.0027379; + const omega_ER = 6.3003879; + const zns = 1.19459E-5; + const c1ss = 2.9864797E-6; + const zes = 1.675E-2; + const znl = 1.5835218E-4; + const c1l = 4.7968065E-7; + const zel = 5.490E-2; + const zcosis = 9.1744867E-1; + const zsinis = 3.9785416E-1; + const zsings = -9.8088458E-1; + const zcosgs = 1.945905E-1; + const zcoshs = 1; + const zsinhs = 0; + const q22 = 1.7891679E-6; + const q31 = 2.1460748E-6; + const q33 = 2.2123015E-7; + const g22 = 5.7686396; + const g32 = 9.5240898E-1; + const g44 = 1.8014998; + const g52 = 1.0508330; + const g54 = 4.4108898; + const root22 = 1.7891679E-6; + const root32 = 3.7393792E-7; + const root44 = 7.3636953E-9; + const root52 = 1.1428639E-7; + const root54 = 2.1765803E-9; + const thdt = 4.3752691E-3; + const rho = 1.5696615E-1; + const mfactor = 7.292115E-5; + const __sr__ = 6.96000E5; /*Solar radius - kilometers (IAU 76)*/ + const AU = 1.49597870E8; /*Astronomical unit - kilometers (IAU 76)*/ + + /* visibility constants */ + const SAT_VIS_NONE = 0; + const SAT_VIS_VISIBLE = 1; + const SAT_VIS_DAYLIGHT = 2; + const SAT_VIS_ECLIPSED = 3; + + /* preferences */ + public $minEle = 10; // Minimum elevation + public $timeRes = 10; // Pass details: time resolution + public $numEntries = 20; // Pass details: number of entries + public $threshold = -6; // Twilight threshold + + /** + * Predict the next pass. + * + * This function simply wraps the get_pass function using the current time + * as parameter. + * + * Note: the data in sat will be corrupt (future) and must be refreshed + * by the caller, if the caller will need it later on (eg. if the caller + * is GtkSatList). + * + * @param Predict_Sat $sat The satellite data. + * @param Predict_QTH $qth The observer data. + * @param int $maxdt The maximum number of days to look ahead. + * + * @return Predict_Pass Pointer instance or NULL if no pass can be + * found. + */ + public function get_next_pass(Predict_Sat $sat, Predict_QTH $qth, $maxdt) + { + /* get the current time and call the get_pass function */ + $now = Predict_Time::get_current_daynum(); + + return $this->get_pass($sat, $qth, $now, $maxdt); + } + + /** Predict first pass after a certain time. + * + * @param Predict_Sat $sat The satellite data. + * @param Predict_QTH $qth The observer's location data. + * @param float $start Starting time. + * @param int $maxdt The maximum number of days to look ahead (0 for no limit). + * + * @return Predict_Pass or NULL if there was an error. + * + * This function will find the first upcoming pass with AOS no earlier than + * t = start and no later than t = (start+maxdt). + * + * note For no time limit use maxdt = 0.0 + * + * note the data in sat will be corrupt (future) and must be refreshed + * by the caller, if the caller will need it later on + */ + public function get_pass(Predict_Sat $sat_in, Predict_QTH $qth, $start, $maxdt) + { + $aos = 0.0; /* time of AOS */ + $tca = 0.0; /* time of TCA */ + $los = 0.0; /* time of LOS */ + $dt = 0.0; /* time diff */ + $step = 0.0; /* time step */ + $t0 = $start; + $tres = 0.0; /* required time resolution */ + $max_el = 0.0; /* maximum elevation */ + $pass = null; + $detail = null; + $done = false; + $iter = 0; /* number of iterations */ + /* FIXME: watchdog */ + + /*copy sat_in to a working structure*/ + $sat = clone $sat_in; + $sat_working = clone $sat_in; + + /* get time resolution; sat-cfg stores it in seconds */ + $tres = $this->timeRes / 86400.0; + + /* loop until we find a pass with elevation > SAT_CFG_INT_PRED_MIN_EL + or we run out of time + FIXME: we should have a safety break + */ + while (!$done) { + /* Find los of next pass or of current pass */ + $los = $this->find_los($sat, $qth, $t0, $maxdt); // See if a pass is ongoing + $aos = $this->find_aos($sat, $qth, $t0, $maxdt); + /* sat_log_log(SAT_LOG_LEVEL_MSG, "%s:%s:%d: found aos %f and los %f for t0=%f", */ + /* __FILE__, */ + /* __FUNCTION__, */ + /* __LINE__, */ + /* aos, */ + /* los, */ + /* t0); */ + if ($aos > $los) { + // los is from an currently happening pass, find previous aos + $aos = $this->find_prev_aos($sat, $qth, $t0); + } + + /* aos = 0.0 means no aos */ + if ($aos == 0.0) { + $done = true; + } else if (($maxdt > 0.0) && ($aos > ($start + $maxdt)) ) { + /* check whether we are within time limits; + maxdt = 0 mean no time limit. + */ + $done = true; + } else { + //los = find_los (sat, qth, aos + 0.001, maxdt); // +1.5 min later + $dt = $los - $aos; + + /* get time step, which will give us the max number of entries */ + $step = $dt / $this->numEntries; + + /* but if this is smaller than the required resolution + we go with the resolution + */ + if ($step < $tres) { + $step = $tres; + } + + /* create a pass_t entry; FIXME: g_try_new in 2.8 */ + $pass = new Predict_Pass(); + + $pass->aos = $aos; + $pass->los = $los; + $pass->max_el = 0.0; + $pass->aos_az = 0.0; + $pass->los_az = 0.0; + $pass->maxel_az = 0.0; + $pass->vis = '---'; + $pass->satname = $sat->nickname; + $pass->details = array(); + + /* iterate over each time step */ + for ($t = $pass->aos; $t <= $pass->los; $t += $step) { + + /* calculate satellite data */ + $this->predict_calc($sat, $qth, $t); + + /* in the first iter we want to store + pass->aos_az + */ + if ($t == $pass->aos) { + $pass->aos_az = $sat->az; + $pass->orbit = $sat->orbit; + } + + /* append details to sat->details */ + $detail = new Predict_PassDetail(); + $detail->time = $t; + $detail->pos->x = $sat->pos->x; + $detail->pos->y = $sat->pos->y; + $detail->pos->z = $sat->pos->z; + $detail->pos->w = $sat->pos->w; + $detail->vel->x = $sat->vel->x; + $detail->vel->y = $sat->vel->y; + $detail->vel->z = $sat->vel->z; + $detail->vel->w = $sat->vel->w; + $detail->velo = $sat->velo; + $detail->az = $sat->az; + $detail->el = $sat->el; + $detail->range = $sat->range; + $detail->range_rate = $sat->range_rate; + $detail->lat = $sat->ssplat; + $detail->lon = $sat->ssplon; + $detail->alt = $sat->alt; + $detail->ma = $sat->ma; + $detail->phase = $sat->phase; + $detail->footprint = $sat->footprint; + $detail->orbit = $sat->orbit; + $detail->vis = $this->get_sat_vis($sat, $qth, $t); + + /* also store visibility "bit" */ + switch ($detail->vis) { + case self::SAT_VIS_VISIBLE: + $pass->vis[0] = 'V'; + break; + case self::SAT_VIS_DAYLIGHT: + $pass->vis[1] = 'D'; + break; + case self::SAT_VIS_ECLIPSED: + $pass->vis[2] = 'E'; + break; + default: + break; + } + + // Using an array, no need to prepend and reverse the list + // as gpredict does + $pass->details[] = $detail; + + // Look up apparent magnitude if this is a visible pass + if ($detail->vis === self::SAT_VIS_VISIBLE) { + $apmag = $sat->calculateApparentMagnitude($t, $qth); + if ($pass->max_apparent_magnitude === null || $apmag < $pass->max_apparent_magnitude) { + $pass->max_apparent_magnitude = $apmag; + } + } + + /* store elevation if greater than the + previously stored one + */ + if ($sat->el > $max_el) { + $max_el = $sat->el; + $tca = $t; + $pass->maxel_az = $sat->az; + } + + /* g_print ("TIME: %f\tAZ: %f\tEL: %f (MAX: %f)\n", */ + /* t, sat->az, sat->el, max_el); */ + } + + /* calculate satellite data */ + $this->predict_calc($sat, $qth, $pass->los); + /* store los_az, max_el and tca */ + $pass->los_az = $sat->az; + $pass->max_el = $max_el; + $pass->tca = $tca; + + /* check whether this pass is good */ + if ($max_el >= $this->minEle) { + $done = true; + } else { + $done = false; + $t0 = $los + 0.014; // +20 min + $pass = null; + } + + $iter++; + } + } + + return $pass; + } + + /** + * Calculate satellite visibility. + * + * @param Predict_Sat $sat The satellite structure. + * @param Predict_QTH $qth The QTH + * @param float $jul_utc The time at which the visibility should be calculated. + * + * @return int The visiblity constant, 0, 1, 2, or 3 (see above) + */ + public function get_sat_vis(Predict_Sat $sat, Predict_QTH $qth, $jul_utc) + { + /* gboolean sat_sun_status; + gdouble sun_el; + gdouble threshold; + gdouble eclipse_depth; + sat_vis_t vis = SAT_VIS_NONE; */ + + $eclipse_depth = 0.0; + $zero_vector = new Predict_Vector(); + $obs_geodetic = new Predict_Geodetic(); + + /* Solar ECI position vector */ + $solar_vector = new Predict_Vector(); + + /* Solar observed az and el vector */ + $solar_set = new Predict_ObsSet(); + + /* FIXME: could be passed as parameter */ + $obs_geodetic->lon = $qth->lon * self::de2ra; + $obs_geodetic->lat = $qth->lat * self::de2ra; + $obs_geodetic->alt = $qth->alt / 1000.0; + $obs_geodetic->theta = 0; + + Predict_Solar::Calculate_Solar_Position($jul_utc, $solar_vector); + Predict_SGPObs::Calculate_Obs($jul_utc, $solar_vector, $zero_vector, $obs_geodetic, $solar_set); + + if (Predict_Solar::Sat_Eclipsed($sat->pos, $solar_vector, $eclipse_depth)) { + /* satellite is eclipsed */ + $sat_sun_status = false; + } else { + /* satellite in sunlight => may be visible */ + $sat_sun_status = true; + } + + if ($sat_sun_status) { + $sun_el = Predict_Math::Degrees($solar_set->el); + + if ($sun_el <= $this->threshold && $sat->el >= 0.0) { + $vis = self::SAT_VIS_VISIBLE; + } else { + $vis = self::SAT_VIS_DAYLIGHT; + } + } else { + $vis = self::SAT_VIS_ECLIPSED; + } + + return $vis; + } + + /** Find the AOS time of the next pass. + * @author Alexandru Csete, OZ9AEC + * @author John A. Magliacane, KD2BD + * @param Predict_Sat $sat The satellite data. + * @param Predict_QTH $qth The observer's location (QTH) data. + * @param float $start The julian date where calculation should start. + * @param int $maxdt The upper time limit in days (0.0 = no limit) + * @return The julain date of the next AOS or 0.0 if the satellite has no AOS. + * + * This function finds the time of AOS for the first coming pass taking place + * no earlier that start. + * If the satellite is currently within range, the function first calls + * find_los to get the next LOS time. Then the calculations are done using + * the new start time. + * + */ + public function find_aos(Predict_Sat $sat, Predict_QTH $qth, $start, $maxdt) + { + $t = $start; + $aostime = 0.0; + + + /* make sure current sat values are + in sync with the time + */ + $this->predict_calc($sat, $qth, $start); + + /* check whether satellite has aos */ + if (($sat->otype == Predict_SGPSDP::ORBIT_TYPE_GEO) || + ($sat->otype == Predict_SGPSDP::ORBIT_TYPE_DECAYED) || + !$this->has_aos($sat, $qth)) { + + return 0.0; + } + + if ($sat->el > 0.0) { + $t = $this->find_los($sat, $qth, $start, $maxdt) + 0.014; // +20 min + } + + /* invalid time (potentially returned by find_los) */ + if ($t < 0.1) { + return 0.0; + } + + /* update satellite data */ + $this->predict_calc($sat, $qth, $t); + + /* use upper time limit */ + if ($maxdt > 0.0) { + + /* coarse time steps */ + while (($sat->el < -1.0) && ($t <= ($start + $maxdt))) { + $t -= 0.00035 * ($sat->el * (($sat->alt / 8400.0) + 0.46) - 2.0); + $this->predict_calc($sat, $qth, $t); + } + + /* fine steps */ + while (($aostime == 0.0) && ($t <= ($start + $maxdt))) { + + if (abs($sat->el) < 0.005) { + $aostime = $t; + } else { + $t -= $sat->el * sqrt($sat->alt) / 530000.0; + $this->predict_calc($sat, $qth, $t); + } + } + } else { + /* don't use upper time limit */ + + /* coarse time steps */ + while ($sat->el < -1.0) { + + $t -= 0.00035 * ($sat->el * (($sat->alt / 8400.0) + 0.46) - 2.0); + $this->predict_calc($sat, $qth, $t); + } + + /* fine steps */ + while ($aostime == 0.0) { + + if (abs($sat->el) < 0.005) { + $aostime = $t; + } else { + $t -= $sat->el * sqrt($sat->alt) / 530000.0; + $this->predict_calc($sat, $qth, $t); + } + + } + } + + return $aostime; + } + + /** SGP4SDP4 driver for doing AOS/LOS calculations. + * @param Predict_Sat $sat The satellite data. + * @param Predict_QTH $qth The QTH observer location data. + * @param float $t The time for calculation (Julian Date) + * + */ + public function predict_calc(Predict_Sat $sat, Predict_QTH $qth, $t) + { + $obs_set = new Predict_ObsSet(); + $sat_geodetic = new Predict_Geodetic(); + $obs_geodetic = new Predict_Geodetic(); + + $obs_geodetic->lon = $qth->lon * self::de2ra; + $obs_geodetic->lat = $qth->lat * self::de2ra; + $obs_geodetic->alt = $qth->alt / 1000.0; + $obs_geodetic->theta = 0; + + $sat->jul_utc = $t; + $sat->tsince = ($sat->jul_utc - $sat->jul_epoch) * self::xmnpda; + + /* call the norad routines according to the deep-space flag */ + $sgpsdp = Predict_SGPSDP::getInstance($sat); + if ($sat->flags & Predict_SGPSDP::DEEP_SPACE_EPHEM_FLAG) { + $sgpsdp->SDP4($sat, $sat->tsince); + } else { + $sgpsdp->SGP4($sat, $sat->tsince); + } + + Predict_Math::Convert_Sat_State($sat->pos, $sat->vel); + + /* get the velocity of the satellite */ + $sat->vel->w = sqrt($sat->vel->x * $sat->vel->x + $sat->vel->y * $sat->vel->y + $sat->vel->z * $sat->vel->z); + $sat->velo = $sat->vel->w; + Predict_SGPObs::Calculate_Obs($sat->jul_utc, $sat->pos, $sat->vel, $obs_geodetic, $obs_set); + Predict_SGPObs::Calculate_LatLonAlt($sat->jul_utc, $sat->pos, $sat_geodetic); + + while ($sat_geodetic->lon < -self::pi) { + $sat_geodetic->lon += self::twopi; + } + + while ($sat_geodetic->lon > (self::pi)) { + $sat_geodetic->lon -= self::twopi; + } + + $sat->az = Predict_Math::Degrees($obs_set->az); + $sat->el = Predict_Math::Degrees($obs_set->el); + $sat->range = $obs_set->range; + $sat->range_rate = $obs_set->range_rate; + $sat->ssplat = Predict_Math::Degrees($sat_geodetic->lat); + $sat->ssplon = Predict_Math::Degrees($sat_geodetic->lon); + $sat->alt = $sat_geodetic->alt; + $sat->ma = Predict_Math::Degrees($sat->phase); + $sat->ma *= 256.0 / 360.0; + $sat->phase = Predict_Math::Degrees($sat->phase); + + /* same formulas, but the one from predict is nicer */ + //sat->footprint = 2.0 * xkmper * acos (xkmper/sat->pos.w); + $sat->footprint = 12756.33 * acos(self::xkmper / (self::xkmper + $sat->alt)); + $age = $sat->jul_utc - $sat->jul_epoch; + $sat->orbit = floor(($sat->tle->xno * self::xmnpda / self::twopi + + $age * $sat->tle->bstar * self::ae) * $age + + $sat->tle->xmo / self::twopi) + $sat->tle->revnum - 1; + } + + /** Find the LOS time of the next pass. + * @author Alexandru Csete, OZ9AEC + * @author John A. Magliacane, KD2BD + * @param Predict_Sat $sat The satellite data. + * @param Predict_QTH $qth The QTH observer location data. + * @param float $start The time where calculation should start. (Julian Date) + * @param int $maxdt The upper time limit in days (0.0 = no limit) + * @return The time (julian date) of the next LOS or 0.0 if the satellite has no LOS. + * + * This function finds the time of LOS for the first coming pass taking place + * no earlier that start. + * If the satellite is currently out of range, the function first calls + * find_aos to get the next AOS time. Then the calculations are done using + * the new start time. + * The function has a built-in watchdog to ensure that we don't end up in + * lengthy loops. + * + */ + public function find_los(Predict_Sat $sat, Predict_QTH $qth, $start, $maxdt) + { + $t = $start; + $lostime = 0.0; + + + $this->predict_calc($sat, $qth, $start); + + /* check whether satellite has aos */ + if (($sat->otype == Predict_SGPSDP::ORBIT_TYPE_GEO) || + ($sat->otype == Predict_SGPSDP::ORBIT_TYPE_DECAYED) || + !$this->has_aos ($sat, $qth)) { + + return 0.0; + } + + if ($sat->el < 0.0) { + $t = $this->find_aos($sat, $qth, $start, $maxdt) + 0.001; // +1.5 min + } + + /* invalid time (potentially returned by find_aos) */ + if ($t < 0.01) { + return 0.0; + } + + /* update satellite data */ + $this->predict_calc($sat, $qth, $t); + + /* use upper time limit */ + if ($maxdt > 0.0) { + + /* coarse steps */ + while (($sat->el >= 1.0) && ($t <= ($start + $maxdt))) { + $t += cos(($sat->el - 1.0) * self::de2ra) * sqrt($sat->alt) / 25000.0; + $this->predict_calc($sat, $qth, $t); + } + + /* fine steps */ + while (($lostime == 0.0) && ($t <= ($start + $maxdt))) { + + $t += $sat->el * sqrt($sat->alt) / 502500.0; + $this->predict_calc($sat, $qth, $t); + + if (abs($sat->el) < 0.005) { + $lostime = $t; + } + } + } else { + /* don't use upper limit */ + + /* coarse steps */ + while ($sat->el >= 1.0) { + $t += cos(($sat->el - 1.0) * self::de2ra) * sqrt($sat->alt) / 25000.0; + $this->predict_calc($sat, $qth, $t); + } + + /* fine steps */ + while ($lostime == 0.0) { + + $t += $sat->el * sqrt($sat->alt) / 502500.0; + $this->predict_calc($sat, $qth, $t); + + if (abs($sat->el) < 0.005) + $lostime = $t; + } + } + + return $lostime; + } + + /** Find AOS time of current pass. + * @param Predict_Sat $sat The satellite to find AOS for. + * @param Predict_QTH $qth The ground station. + * @param float $start Start time, prefereably now. + * @return The time of the previous AOS or 0.0 if the satellite has no AOS. + * + * This function can be used to find the AOS time in the past of the + * current pass. + */ + public function find_prev_aos(Predict_Sat $sat, Predict_QTH $qth, $start) + { + $aostime = $start; + + /* make sure current sat values are + in sync with the time + */ + $this->predict_calc($sat, $qth, $start); + + /* check whether satellite has aos */ + if (($sat->otype == Predict_SGPSDP::ORBIT_TYPE_GEO) || + ($sat->otype == Predict_SGPSDP::ORBIT_TYPE_DECAYED) || + !$this->has_aos($sat, $qth)) { + + return 0.0; + } + + while ($sat->el >= 0.0) { + $aostime -= 0.0005; // 0.75 min + $this->predict_calc($sat, $qth, $aostime); + } + + return $aostime; + } + + /** Determine whether satellite ever reaches AOS. + * @author John A. Magliacane, KD2BD + * @author Alexandru Csete, OZ9AEC + * @param Predict_Sat $sat The satellite data. + * @param Predict_QTH $qth The observer's location data + * @return bool true if the satellite will reach AOS, false otherwise. + * + */ + public function has_aos(Predict_Sat $sat, Predict_QTH $qth) + { + $retcode = false; + + /* FIXME */ + if ($sat->meanmo == 0.0) { + $retcode = false; + } else { + + /* xincl is already in RAD by select_ephemeris */ + $lin = $sat->tle->xincl; + if ($lin >= self::pio2) { + $lin = self::pi - $lin; + } + + $sma = 331.25 * exp(log(1440.0 / $sat->meanmo) * (2.0 / 3.0)); + $apogee = $sma * (1.0 + $sat->tle->eo) - self::xkmper; + + if ((acos(self::xkmper / ($apogee + self::xkmper)) + ($lin)) > abs($qth->lat * self::de2ra)) { + $retcode = true; + } else { + $retcode = false; + } + } + + return $retcode; + } + + /** Predict passes after a certain time. + * + * + * This function calculates num upcoming passes with AOS no earlier + * than t = start and not later that t = (start+maxdt). The function will + * repeatedly call get_pass until + * the number of predicted passes is equal to num, the time has reached + * limit or the get_pass function returns NULL. + * + * note For no time limit use maxdt = 0.0 + * + * note the data in sat will be corrupt (future) and must be refreshed + * by the caller, if the caller will need it later on (eg. if the caller + * is GtkSatList). + * + * note Prepending to a singly linked list is much faster than appending. + * Therefore, the elements are prepended whereafter the GSList is + * reversed + * + * + * @param Predict_Sat $sat The satellite data + * @param Predict_QTH $qth The observer's location data + * @param float $start The start julian date + * @param int $maxdt The max # of days to look + * @param int $num The max # of passes to get + * @return array of Predict_Pass instances if found, empty array otherwise + */ + public function get_passes(Predict_Sat $sat, Predict_QTH $qth, $start, $maxdt, $num = 0) + { + $passes = array(); + + /* if no number has been specified + set it to something big */ + if ($num == 0) { + $num = 100; + } + + $t = $start; + + for ($i = 0; $i < $num; $i++) { + $pass = $this->get_pass($sat, $qth, $t, $maxdt); + + if ($pass != null) { + $passes[] = $pass; + $t = $pass->los + 0.014; // +20 min + + /* if maxdt > 0.0 check whether we have reached t = start+maxdt + if yes finish predictions + */ + if (($maxdt > 0.0) && ($t >= ($start + $maxdt))) { + $i = $num; + } + } else { + /* we can't get any more passes */ + $i = $num; + } + } + + return $passes; + } + + /** + * Filters out visible passes and adds the visible aos, tca, los, and + * corresponding az and ele for each. + * + * @param array $passes The passes returned from get_passes() + * + * @author Bill Shupp + * @return array + */ + public function filterVisiblePasses(array $passes) + { + $filtered = array(); + + foreach ($passes as $result) { + // Dummy check + if ($result->vis[0] != 'V') { + continue; + } + + $aos = false; + $aos_az = false; + $aos = false; + $tca = false; + $los_az = false; + $max_el = 0; + + foreach ($result->details as $detail) { + if ($detail->vis != Predict::SAT_VIS_VISIBLE) { + continue; + } + if ($detail->el < $this->minEle) { + continue; + } + + if ($aos == false) { + $aos = $detail->time; + $aos_az = $detail->az; + $aos_el = $detail->el; + $tca = $detail->time; + $los = $detail->time; + $los_az = $detail->az; + $los_el = $detail->el; + $max_el = $detail->el; + $max_el_az = $detail->el; + continue; + } + $los = $detail->time; + $los_az = $detail->az; + $los_el = $detail->el; + + if ($detail->el > $max_el) { + $tca = $detail->time; + $max_el = $detail->el; + $max_el_az = $detail->az; + } + } + + if ($aos === false) { + // Does not reach minimum elevation, skip + continue; + } + + $result->visible_aos = $aos; + $result->visible_aos_az = $aos_az; + $result->visible_aos_el = $aos_el; + $result->visible_tca = $tca; + $result->visible_max_el = $max_el; + $result->visible_max_el_az = $max_el_az; + $result->visible_los = $los; + $result->visible_los_az = $los_az; + $result->visible_los_el = $los_el; + + $filtered[] = $result; + } + + return $filtered; + } + + /** + * Translates aziumuth degrees to compass direction: + * + * N (0°), NNE (22.5°), NE (45°), ENE (67.5°), E (90°), ESE (112.5°), + * SE (135°), SSE (157.5°), S (180°), SSW (202.5°), SW (225°), + * WSW (247.5°), W (270°), WNW (292.5°), NW (315°), NNW (337.5°) + * + * @param int $az The azimuth in degrees, defaults to 0 + * + * @return string + */ + public static function azDegreesToDirection($az = 0) + { + $i = floor($az / 22.5); + $m = (22.5 * (2 * $i + 1)) / 2; + $i = ($az >= $m) ? $i + 1 : $i; + + return trim(substr('N NNENE ENEE ESESE SSES SSWSW WSWW WNWNW NNWN ', $i * 3, 3)); + } +} diff --git a/lib/predict/Predict/DeepArg.php b/lib/predict/Predict/DeepArg.php new file mode 100644 index 0000000..f29178f --- /dev/null +++ b/lib/predict/Predict/DeepArg.php @@ -0,0 +1,35 @@ + 0 ) { + return 1; + } else if ($arg < 0 ) { + return -1; + } else { + return 0; + } + } + + /* Returns the arcsine of the argument */ + public static function ArcSin($arg) + { + if (abs($arg) >= 1 ) { + return (self::Sign($arg) * Predict::pio2); + } else { + return(atan($arg / sqrt(1 - $arg * $arg))); + } + } + + /* Returns arccosine of rgument */ + public static function ArcCos($arg) + { + return Predict::pio2 - self::ArcSin($arg); + } + + /* Adds vectors v1 and v2 together to produce v3 */ + public static function Vec_Add(Predict_Vector $v1, Predict_Vector $v2, Predict_Vector $v3) + { + $v3->x = $v1->x + $v2->x; + $v3->y = $v1->y + $v2->y; + $v3->z = $v1->z + $v2->z; + + $v3->w = sqrt($v3->x * $v3->x + $v3->y * $v3->y + $v3->z * $v3->z); + } + + /* Subtracts vector v2 from v1 to produce v3 */ + public static function Vec_Sub(Predict_Vector $v1, Predict_Vector $v2, Predict_Vector $v3) + { + $v3->x = $v1->x - $v2->x; + $v3->y = $v1->y - $v2->y; + $v3->z = $v1->z - $v2->z; + + $v3->w = sqrt($v3->x * $v3->x + $v3->y * $v3->y + $v3->z * $v3->z); + } + + /* Multiplies the vector v1 by the scalar k to produce the vector v2 */ + public static function Scalar_Multiply($k, Predict_Vector $v1, Predict_Vector $v2) + { + $v2->x = $k * $v1->x; + $v2->y = $k * $v1->y; + $v2->z = $k * $v1->z; + $v2->w = abs($k) * $v1->w; + } + + /* Multiplies the vector v1 by the scalar k */ + public static function Scale_Vector($k, Predict_Vector $v) + { + $v->x *= $k; + $v->y *= $k; + $v->z *= $k; + + $v->w = sqrt($v->x * $v->x + $v->y * $v->y + $v->z * $v->z); + } + + /* Returns the dot product of two vectors */ + public static function Dot(Predict_Vector $v1, Predict_Vector $v2) + { + return ($v1->x * $v2->x + $v1->y * $v2->y + $v1->z * $v2->z); + } + + /* Calculates the angle between vectors v1 and v2 */ + public static function Angle(Predict_Vector $v1, Predict_Vector $v2) + { + $v1->w = sqrt($v1->x * $v1->x + $v1->y * $v1->y + $v1->z * $v1->z); + $v2->w = sqrt($v2->x * $v2->x + $v2->y * $v2->y + $v2->z * $v2->z); + return (self::ArcCos(self::Dot($v1, $v2) / ($v1->w * $v2->w))); + } + + /* Produces cross product of v1 and v2, and returns in v3 */ + public static function Cross(Predict_Vector $v1, Predict_Vector $v2 ,Predict_Vector $v3) + { + $v3->x = $v1->y * $v2->z - $v1->z * $v2->y; + $v3->y = $v1->z * $v2->x - $v1->x * $v2->z; + $v3->z = $v1->x * $v2->y - $v1->y * $v2->x; + + $v3->w = sqrt($v3->x * $v3->x + $v3->y * $v3->y + $v3->z * $v3->z); + } + + /* Normalizes a vector */ + public static function Normalize(Predict_Vector $v ) + { + $v->x /= $v->w; + $v->y /= $v->w; + $v->z /= $v->w; + } + + /* Four-quadrant arctan function */ + public static function AcTan($sinx, $cosx) + { + if ($cosx == 0) { + if ($sinx > 0) { + return Predict::pio2; + } else { + return Predict::x3pio2; + } + } else { + if ($cosx > 0) { + if ($sinx > 0) { + return atan($sinx / $cosx); + } else { + return Predict::twopi + atan($sinx / $cosx); + } + } else { + return Predict::pi + atan($sinx / $cosx); + } + } + } + + /* Returns mod 2pi of argument */ + public static function FMod2p($x) + { + $ret_val = $x; + $i = (int) ($ret_val / Predict::twopi); + $ret_val -= $i * Predict::twopi; + + if ($ret_val < 0) { + $ret_val += Predict::twopi; + } + + return $ret_val; + } + + /* Returns arg1 mod arg2 */ + public static function Modulus($arg1, $arg2) + { + $ret_val = $arg1; + $i = (int) ($ret_val / $arg2); + $ret_val -= $i * $arg2; + + if ($ret_val < 0) { + $ret_val += $arg2; + } + + return $ret_val; + } + + /* Returns fractional part of double argument */ + public static function Frac($arg) + { + return $arg - floor($arg); + } + + /* Converts the satellite's position and velocity */ + /* vectors from normalised values to km and km/sec */ + public static function Convert_Sat_State(Predict_Vector $pos, Predict_Vector $vel) + { + self::Scale_Vector(Predict::xkmper, $pos); + self::Scale_Vector(Predict::xkmper * Predict::xmnpda / Predict::secday, $vel); + } + + /* Returns angle in radians from arg in degrees */ + public static function Radians($arg) + { + return $arg * Predict::de2ra; + } + + /* Returns angle in degrees from arg in rads */ + public static function Degrees($arg) + { + return $arg / Predict::de2ra; + } +} diff --git a/lib/predict/Predict/ObsSet.php b/lib/predict/Predict/ObsSet.php new file mode 100644 index 0000000..9470b93 --- /dev/null +++ b/lib/predict/Predict/ObsSet.php @@ -0,0 +1,12 @@ +pos = new Predict_Vector(); + $this->vel = new Predict_Vector(); + } +} diff --git a/lib/predict/Predict/QTH.php b/lib/predict/Predict/QTH.php new file mode 100644 index 0000000..5ccd5d3 --- /dev/null +++ b/lib/predict/Predict/QTH.php @@ -0,0 +1,20 @@ +lat); /* Only run sin($geodetic->lat) once */ + + $geodetic->theta = Predict_Math::FMod2p(Predict_Time::ThetaG_JD($_time) + $geodetic->lon);/*LMST*/ + $c = 1 / sqrt(1 + Predict::__f * (Predict::__f - 2) * $sinGeodeticLat * $sinGeodeticLat); + $sq = (1 - Predict::__f) * (1 - Predict::__f) * $c; + $achcp = (Predict::xkmper * $c + $geodetic->alt) * cos($geodetic->lat); + $obs_pos->x = $achcp * cos($geodetic->theta); /*kilometers*/ + $obs_pos->y = $achcp * sin($geodetic->theta); + $obs_pos->z = (Predict::xkmper * $sq + $geodetic->alt) * $sinGeodeticLat; + $obs_vel->x = -Predict::mfactor * $obs_pos->y; /*kilometers/second*/ + $obs_vel->y = Predict::mfactor * $obs_pos->x; + $obs_vel->z = 0; + $obs_pos->w = sqrt($obs_pos->x * $obs_pos->x + $obs_pos->y * $obs_pos->y + $obs_pos->z * $obs_pos->z); + $obs_vel->w = sqrt($obs_vel->x * $obs_vel->x + $obs_vel->y * $obs_vel->y + $obs_vel->z * $obs_vel->z); + } + + /* Procedure Calculate_LatLonAlt will calculate the geodetic */ + /* position of an object given its ECI position pos and time. */ + /* It is intended to be used to determine the ground track of */ + /* a satellite. The calculations assume the earth to be an */ + /* oblate spheroid as defined in WGS '72. */ + public static function Calculate_LatLonAlt($_time, Predict_Vector $pos, Predict_Geodetic $geodetic) + { + /* Reference: The 1992 Astronomical Almanac, page K12. */ + + /* double r,e2,phi,c; */ + + $geodetic->theta = Predict_Math::AcTan($pos->y, $pos->x); /*radians*/ + $geodetic->lon = Predict_Math::FMod2p($geodetic->theta - Predict_Time::ThetaG_JD($_time)); /*radians*/ + $r = sqrt(($pos->x * $pos->x) + ($pos->y * $pos->y)); + $e2 = Predict::__f * (2 - Predict::__f); + $geodetic->lat = Predict_Math::AcTan($pos->z, $r); /*radians*/ + + do { + $phi = $geodetic->lat; + $sinPhi = sin($phi); + $c = 1 / sqrt(1 - $e2 * ($sinPhi * $sinPhi)); + $geodetic->lat = Predict_Math::AcTan($pos->z + Predict::xkmper * $c * $e2 * $sinPhi, $r); + } while (abs($geodetic->lat - $phi) >= 1E-10); + + $geodetic->alt = $r / cos($geodetic->lat) - Predict::xkmper * $c;/*kilometers*/ + + if ($geodetic->lat > Predict::pio2) { + $geodetic->lat -= Predict::twopi; + } + } + + /* The procedures Calculate_Obs and Calculate_RADec calculate */ + /* the *topocentric* coordinates of the object with ECI position, */ + /* {pos}, and velocity, {vel}, from location {geodetic} at {time}. */ + /* The {obs_set} returned for Calculate_Obs consists of azimuth, */ + /* elevation, range, and range rate (in that order) with units of */ + /* radians, radians, kilometers, and kilometers/second, respectively. */ + /* The WGS '72 geoid is used and the effect of atmospheric refraction */ + /* (under standard temperature and pressure) is incorporated into the */ + /* elevation calculation; the effect of atmospheric refraction on */ + /* range and range rate has not yet been quantified. */ + + /* The {obs_set} for Calculate_RADec consists of right ascension and */ + /* declination (in that order) in radians. Again, calculations are */ + /* based on *topocentric* position using the WGS '72 geoid and */ + /* incorporating atmospheric refraction. */ + public static function Calculate_Obs($_time, Predict_Vector $pos, Predict_Vector $vel, Predict_Geodetic $geodetic, Predict_ObsSet $obs_set) + { + $obs_pos = new Predict_Vector(); + $obs_vel = new Predict_Vector(); + $range = new Predict_Vector(); + $rgvel = new Predict_Vector(); + + self::Calculate_User_PosVel($_time, $geodetic, $obs_pos, $obs_vel); + + $range->x = $pos->x - $obs_pos->x; + $range->y = $pos->y - $obs_pos->y; + $range->z = $pos->z - $obs_pos->z; + + $rgvel->x = $vel->x - $obs_vel->x; + $rgvel->y = $vel->y - $obs_vel->y; + $rgvel->z = $vel->z - $obs_vel->z; + + $range->w = sqrt($range->x * $range->x + $range->y * $range->y + $range->z * $range->z); + + $sin_lat = sin($geodetic->lat); + $cos_lat = cos($geodetic->lat); + $sin_theta = sin($geodetic->theta); + $cos_theta = cos($geodetic->theta); + $top_s = $sin_lat * $cos_theta * $range->x + + $sin_lat * $sin_theta * $range->y + - $cos_lat * $range->z; + $top_e = -$sin_theta * $range->x + + $cos_theta * $range->y; + $top_z = $cos_lat * $cos_theta * $range->x + + $cos_lat * $sin_theta * $range->y + + $sin_lat * $range->z; + $azim = atan(-$top_e / $top_s); /*Azimuth*/ + if ($top_s > 0) { + $azim = $azim + Predict::pi; + } + if ($azim < 0 ) { + $azim = $azim + Predict::twopi; + } + $el = Predict_Math::ArcSin($top_z / $range->w); + $obs_set->az = $azim; /* Azimuth (radians) */ + $obs_set->el = $el; /* Elevation (radians)*/ + $obs_set->range = $range->w; /* Range (kilometers) */ + + /* Range Rate (kilometers/second)*/ + $obs_set->range_rate = Predict_Math::Dot($range, $rgvel) / $range->w; + + /* Corrections for atmospheric refraction */ + /* Reference: Astronomical Algorithms by Jean Meeus, pp. 101-104 */ + /* Correction is meaningless when apparent elevation is below horizon */ + // obs_set->el = obs_set->el + Radians((1.02/tan(Radians(Degrees(el)+ + // 10.3/(Degrees(el)+5.11))))/60); + if ($obs_set->el < 0) { + $obs_set->el = $el; /*Reset to true elevation*/ + } + } +} diff --git a/lib/predict/Predict/SGPSDP.php b/lib/predict/Predict/SGPSDP.php new file mode 100644 index 0000000..eed5e1c --- /dev/null +++ b/lib/predict/Predict/SGPSDP.php @@ -0,0 +1,1055 @@ +flags & self::SGP4_INITIALIZED_FLAG) { + $sat->flags |= self::SGP4_INITIALIZED_FLAG; + + /* Recover original mean motion (xnodp) and */ + /* semimajor axis (aodp) from input elements. */ + $a1 = pow(Predict::xke / $sat->tle->xno, Predict::tothrd); + $sat->sgps->cosio = cos($sat->tle->xincl); + $theta2 = $sat->sgps->cosio * $sat->sgps->cosio; + $sat->sgps->x3thm1 = 3 * $theta2 - 1.0; + $eosq = $sat->tle->eo * $sat->tle->eo; + $betao2 = 1 - $eosq; + $betao = sqrt($betao2); + $del1 = 1.5 * Predict::ck2 * $sat->sgps->x3thm1 / ($a1 * $a1 * $betao * $betao2); + $ao = $a1 * (1 - $del1 * (0.5 * Predict::tothrd + $del1 * (1 + 134.0 / 81.0 * $del1))); + $delo = 1.5 * Predict::ck2 * $sat->sgps->x3thm1 / ($ao * $ao * $betao * $betao2); + $sat->sgps->xnodp = $sat->tle->xno / (1.0 + $delo); + $sat->sgps->aodp = $ao / (1.0 - $delo); + + /* For perigee less than 220 kilometers, the "simple" flag is set */ + /* and the equations are truncated to linear variation in sqrt a */ + /* and quadratic variation in mean anomaly. Also, the c3 term, */ + /* the delta omega term, and the delta m term are dropped. */ + if (($sat->sgps->aodp * (1.0 - $sat->tle->eo) / Predict::ae) < (220.0 / Predict::xkmper + Predict::ae)) { + $sat->flags |= self::SIMPLE_FLAG; + } else { + $sat->flags &= ~self::SIMPLE_FLAG; + } + + /* For perigee below 156 km, the */ + /* values of s and qoms2t are altered. */ + $s4 = Predict::__s__; + $qoms24 = Predict::qoms2t; + $perige = ($sat->sgps->aodp * (1 - $sat->tle->eo) - Predict::ae) * Predict::xkmper; + if ($perige < 156.0) { + if ($perige <= 98.0) { + $s4 = 20.0; + } else { + $s4 = $perige - 78.0; + } + $qoms24 = pow((120.0 - $s4) * Predict::ae / Predict::xkmper, 4); + $s4 = $s4 / Predict::xkmper + Predict::ae; + }; /* FIXME FIXME: End of if(perige <= 98) NO WAY!!!! */ + + $pinvsq = 1.0 / ($sat->sgps->aodp * $sat->sgps->aodp * $betao2 * $betao2); + $tsi = 1.0 / ($sat->sgps->aodp - $s4); + $sat->sgps->eta = $sat->sgps->aodp * $sat->tle->eo * $tsi; + $etasq = $sat->sgps->eta * $sat->sgps->eta; + $eeta = $sat->tle->eo * $sat->sgps->eta; + $psisq = abs(1.0 - $etasq); + $coef = $qoms24 * pow($tsi, 4); + $coef1 = $coef / pow($psisq, 3.5); + $c2 = $coef1 * $sat->sgps->xnodp * ($sat->sgps->aodp * + (1.0 + 1.5 * $etasq + $eeta * (4.0 + $etasq)) + + 0.75 * Predict::ck2 * $tsi / $psisq * $sat->sgps->x3thm1 * + (8.0 + 3.0 * $etasq * (8 + $etasq))); + $sat->sgps->c1 = $c2 * $sat->tle->bstar; + $sat->sgps->sinio = sin($sat->tle->xincl); + $a3ovk2 = -Predict::xj3 / Predict::ck2 * pow(Predict::ae, 3); + $c3 = $coef * $tsi * $a3ovk2 * $sat->sgps->xnodp * Predict::ae * $sat->sgps->sinio / $sat->tle->eo; + $sat->sgps->x1mth2 = 1.0 - $theta2; + $sat->sgps->c4 = 2.0 * $sat->sgps->xnodp * $coef1 * $sat->sgps->aodp * $betao2 * + ($sat->sgps->eta * (2.0 + 0.5 * $etasq) + + $sat->tle->eo * (0.5 + 2.0 * $etasq) - + 2.0 * Predict::ck2 * $tsi / ($sat->sgps->aodp * $psisq) * + (-3.0 * $sat->sgps->x3thm1 * (1.0 - 2.0 * $eeta + $etasq * (1.5 - 0.5 * $eeta)) + + 0.75 * $sat->sgps->x1mth2 * (2.0 * $etasq - $eeta * (1.0 + $etasq)) * + cos(2.0 * $sat->tle->omegao))); + $sat->sgps->c5 = 2.0 * $coef1 * $sat->sgps->aodp * $betao2 * + (1.0 + 2.75 * ($etasq + $eeta) + $eeta * $etasq); + $theta4 = $theta2 * $theta2; + $temp1 = 3.0 * Predict::ck2 * $pinvsq * $sat->sgps->xnodp; + $temp2 = $temp1 * Predict::ck2 * $pinvsq; + $temp3 = 1.25 * Predict::ck4 * $pinvsq * $pinvsq * $sat->sgps->xnodp; + $sat->sgps->xmdot = $sat->sgps->xnodp + 0.5 * $temp1 * $betao * $sat->sgps->x3thm1 + + 0.0625 * $temp2 * $betao * (13.0 - 78.0 * $theta2 + 137.0 * $theta4); + $x1m5th = 1.0 - 5.0 * $theta2; + $sat->sgps->omgdot = -0.5 * $temp1 * $x1m5th + + 0.0625 * $temp2 * (7.0 - 114.0 * $theta2 + 395.0 * $theta4) + + $temp3 * (3.0 - 36.0 * $theta2 + 49.0 * $theta4); + $xhdot1 = -$temp1 * $sat->sgps->cosio; + $sat->sgps->xnodot = $xhdot1 + (0.5 * $temp2 * (4.0 - 19.0 * $theta2) + + 2.0 * $temp3 * (3.0 - 7.0 * $theta2)) * $sat->sgps->cosio; + $sat->sgps->omgcof = $sat->tle->bstar * $c3 * cos($sat->tle->omegao); + $sat->sgps->xmcof = -Predict::tothrd * $coef * $sat->tle->bstar * Predict::ae / $eeta; + $sat->sgps->xnodcf = 3.5 * $betao2 * $xhdot1 * $sat->sgps->c1; + $sat->sgps->t2cof = 1.5 * $sat->sgps->c1; + $sat->sgps->xlcof = 0.125 * $a3ovk2 * $sat->sgps->sinio * + (3.0 + 5.0 * $sat->sgps->cosio) / (1.0 + $sat->sgps->cosio); + $sat->sgps->aycof = 0.25 * $a3ovk2 * $sat->sgps->sinio; + $sat->sgps->delmo = pow(1.0 + $sat->sgps->eta * cos($sat->tle->xmo), 3); + $sat->sgps->sinmo = sin($sat->tle->xmo); + $sat->sgps->x7thm1 = 7.0 * $theta2 - 1.0; + if (~$sat->flags & self::SIMPLE_FLAG) { + $c1sq = $sat->sgps->c1 * $sat->sgps->c1; + $sat->sgps->d2 = 4.0 * $sat->sgps->aodp * $tsi * $c1sq; + $temp = $sat->sgps->d2 * $tsi * $sat->sgps->c1 / 3.0; + $sat->sgps->d3 = (17.0 * $sat->sgps->aodp + $s4) * $temp; + $sat->sgps->d4 = 0.5 * $temp * $sat->sgps->aodp * $tsi * + (221.0 * $sat->sgps->aodp + 31.0 * $s4) * $sat->sgps->c1; + $sat->sgps->t3cof = $sat->sgps->d2 + 2.0 * $c1sq; + $sat->sgps->t4cof = 0.25 * (3.0 * $sat->sgps->d3 + $sat->sgps->c1 * + (12.0 * $sat->sgps->d2 + 10.0 * $c1sq)); + $sat->sgps->t5cof = 0.2 * (3.0 * $sat->sgps->d4 + + 12.0 * $sat->sgps->c1 * $sat->sgps->d3 + + 6.0 * $sat->sgps->d2 * $sat->sgps->d2 + + 15.0 * $c1sq * (2.0 * $sat->sgps->d2 + $c1sq)); + }; /* End of if (isFlagClear(SIMPLE_FLAG)) */ + }; /* End of SGP4() initialization */ + + /* Update for secular gravity and atmospheric drag. */ + $xmdf = $sat->tle->xmo + $sat->sgps->xmdot * $tsince; + $omgadf = $sat->tle->omegao + $sat->sgps->omgdot * $tsince; + $xnoddf = $sat->tle->xnodeo + $sat->sgps->xnodot * $tsince; + $omega = $omgadf; + $xmp = $xmdf; + $tsq = $tsince * $tsince; + $xnode = $xnoddf + $sat->sgps->xnodcf * $tsq; + $tempa = 1.0 - $sat->sgps->c1 * $tsince; + $tempe = $sat->tle->bstar * $sat->sgps->c4 * $tsince; + $templ = $sat->sgps->t2cof * $tsq; + if (~$sat->flags & self::SIMPLE_FLAG) { + $delomg = $sat->sgps->omgcof * $tsince; + $delm = $sat->sgps->xmcof * (pow(1 + $sat->sgps->eta * cos($xmdf), 3) - $sat->sgps->delmo); + $temp = $delomg + $delm; + $xmp = $xmdf + $temp; + $omega = $omgadf - $temp; + $tcube = $tsq * $tsince; + $tfour = $tsince * $tcube; + $tempa = $tempa - $sat->sgps->d2 * $tsq - $sat->sgps->d3 * $tcube - $sat->sgps->d4 * $tfour; + $tempe = $tempe + $sat->tle->bstar * $sat->sgps->c5 * (sin($xmp) - $sat->sgps->sinmo); + $templ = $templ + $sat->sgps->t3cof * $tcube + $tfour * + ($sat->sgps->t4cof + $tsince * $sat->sgps->t5cof); + }; /* End of if (isFlagClear(SIMPLE_FLAG)) */ + + $a = $sat->sgps->aodp * pow($tempa, 2); + $e = $sat->tle->eo - $tempe; + $xl = $xmp + $omega + $xnode + $sat->sgps->xnodp * $templ; + $beta = sqrt(1.0 - ($e * $e)); + $xn = Predict::xke / pow($a, 1.5); + + /* Long period periodics */ + $axn = $e * cos($omega); + $temp = 1.0 / ($a * $beta * $beta); + $xll = $temp * $sat->sgps->xlcof * $axn; + $aynl = $temp * $sat->sgps->aycof; + $xlt = $xl + $xll; + $ayn = $e * sin($omega) + $aynl; + + /* Solve Kepler's' Equation */ + $capu = Predict_Math::FMod2p($xlt - $xnode); + $temp2 = $capu; + + $i = 0; + do { + $sinepw = sin($temp2); + $cosepw = cos($temp2); + $temp3 = $axn * $sinepw; + $temp4 = $ayn * $cosepw; + $temp5 = $axn * $cosepw; + $temp6 = $ayn * $sinepw; + $epw = ($capu - $temp4 + $temp3 - $temp2) / (1.0 - $temp5 - $temp6) + $temp2; + if (abs($epw - $temp2) <= Predict::e6a) { + break; + } + $temp2 = $epw; + } while ($i++ < 10); + + /* Short period preliminary quantities */ + $ecose = $temp5 + $temp6; + $esine = $temp3 - $temp4; + $elsq = $axn * $axn + $ayn * $ayn; + $temp = 1.0 - $elsq; + $pl = $a * $temp; + $r = $a * (1.0 - $ecose); + $temp1 = 1.0 / $r; + $rdot = Predict::xke * sqrt($a) * $esine * $temp1; + $rfdot = Predict::xke * sqrt($pl) * $temp1; + $temp2 = $a * $temp1; + $betal = sqrt($temp); + $temp3 = 1.0 / (1.0 + $betal); + $cosu = $temp2 * ($cosepw - $axn + $ayn * $esine * $temp3); + $sinu = $temp2 * ($sinepw - $ayn - $axn * $esine * $temp3); + $u = Predict_Math::AcTan($sinu, $cosu); + $sin2u = 2.0 * $sinu * $cosu; + $cos2u = 2.0 * $cosu * $cosu - 1.0; + $temp = 1.0 / $pl; + $temp1 = Predict::ck2 * $temp; + $temp2 = $temp1 * $temp; + + /* Update for short periodics */ + $rk = $r * (1.0 - 1.5 * $temp2 * $betal * $sat->sgps->x3thm1) + + 0.5 * $temp1 * $sat->sgps->x1mth2 * $cos2u; + $uk = $u - 0.25 * $temp2 * $sat->sgps->x7thm1 * $sin2u; + $xnodek = $xnode + 1.5 * $temp2 * $sat->sgps->cosio * $sin2u; + $xinck = $sat->tle->xincl + 1.5 * $temp2 * $sat->sgps->cosio * $sat->sgps->sinio * $cos2u; + $rdotk = $rdot - $xn * $temp1 * $sat->sgps->x1mth2 * $sin2u; + $rfdotk = $rfdot + $xn * $temp1 * ($sat->sgps->x1mth2 * $cos2u + 1.5 * $sat->sgps->x3thm1); + + + /* Orientation vectors */ + $sinuk = sin($uk); + $cosuk = cos($uk); + $sinik = sin($xinck); + $cosik = cos($xinck); + $sinnok = sin($xnodek); + $cosnok = cos($xnodek); + $xmx = -$sinnok * $cosik; + $xmy = $cosnok * $cosik; + $ux = $xmx * $sinuk + $cosnok * $cosuk; + $uy = $xmy * $sinuk + $sinnok * $cosuk; + $uz = $sinik * $sinuk; + $vx = $xmx * $cosuk - $cosnok * $sinuk; + $vy = $xmy * $cosuk - $sinnok * $sinuk; + $vz = $sinik * $cosuk; + + /* Position and velocity */ + $sat->pos->x = $rk * $ux; + $sat->pos->y = $rk * $uy; + $sat->pos->z = $rk * $uz; + $sat->vel->x = $rdotk * $ux + $rfdotk * $vx; + $sat->vel->y = $rdotk * $uy + $rfdotk * $vy; + $sat->vel->z = $rdotk * $uz + $rfdotk * $vz; + + $sat->phase = $xlt - $xnode - $omgadf + Predict::twopi; + if ($sat->phase < 0) { + $sat->phase += Predict::twopi; + } + $sat->phase = Predict_Math::FMod2p($sat->phase); + + $sat->tle->omegao1 = $omega; + $sat->tle->xincl1 = $xinck; + $sat->tle->xnodeo1 = $xnodek; + + } /*SGP4*/ + + /* SDP4 */ + /* This function is used to calculate the position and velocity */ + /* of deep-space (period > 225 minutes) satellites. tsince is */ + /* time since epoch in minutes, tle is a pointer to a tle_t */ + /* structure with Keplerian orbital elements and pos and vel */ + /* are vector_t structures returning ECI satellite position and */ + /* velocity. Use Convert_Sat_State() to convert to km and km/s. */ + public function SDP4(Predict_Sat $sat, $tsince) + { + /* Initialization */ + if (~$sat->flags & self::SDP4_INITIALIZED_FLAG) { + + $sat->flags |= self::SDP4_INITIALIZED_FLAG; + + /* Recover original mean motion (xnodp) and */ + /* semimajor axis (aodp) from input elements. */ + $a1 = pow(Predict::xke / $sat->tle->xno, Predict::tothrd); + $sat->deep_arg->cosio = cos($sat->tle->xincl); + $sat->deep_arg->theta2 = $sat->deep_arg->cosio * $sat->deep_arg->cosio; + $sat->sgps->x3thm1 = 3.0 * $sat->deep_arg->theta2 - 1.0; + $sat->deep_arg->eosq = $sat->tle->eo * $sat->tle->eo; + $sat->deep_arg->betao2 = 1.0 - $sat->deep_arg->eosq; + $sat->deep_arg->betao = sqrt($sat->deep_arg->betao2); + $del1 = 1.5 * Predict::ck2 * $sat->sgps->x3thm1 / + ($a1 * $a1 * $sat->deep_arg->betao * $sat->deep_arg->betao2); + $ao = $a1 * (1.0 - $del1 * (0.5 * Predict::tothrd + $del1 * (1.0 + 134.0 / 81.0 * $del1))); + $delo = 1.5 * Predict::ck2 * $sat->sgps->x3thm1 / + ($ao * $ao * $sat->deep_arg->betao * $sat->deep_arg->betao2); + $sat->deep_arg->xnodp = $sat->tle->xno / (1.0 + $delo); + $sat->deep_arg->aodp = $ao / (1.0 - $delo); + + /* For perigee below 156 km, the values */ + /* of s and qoms2t are altered. */ + $s4 = Predict::__s__; + $qoms24 = Predict::qoms2t; + $perige = ($sat->deep_arg->aodp * (1.0 - $sat->tle->eo) - Predict::ae) * Predict::xkmper; + if ($perige < 156.0) { + if ($perige <= 98.0) { + $s4 = 20.0; + } else { + $s4 = $perige - 78.0; + } + $qoms24 = pow((120.0 - $s4) * Predict::ae / Predict::xkmper, 4); + $s4 = $s4 / Predict::xkmper + Predict::ae; + } + $pinvsq = 1.0 / ($sat->deep_arg->aodp * $sat->deep_arg->aodp * + $sat->deep_arg->betao2 * $sat->deep_arg->betao2); + $sat->deep_arg->sing = sin($sat->tle->omegao); + $sat->deep_arg->cosg = cos($sat->tle->omegao); + $tsi = 1.0 / ($sat->deep_arg->aodp - $s4); + $eta = $sat->deep_arg->aodp * $sat->tle->eo * $tsi; + $etasq = $eta * $eta; + $eeta = $sat->tle->eo * $eta; + $psisq = abs(1.0 - $etasq); + $coef = $qoms24 * pow($tsi, 4); + $coef1 = $coef / pow($psisq, 3.5); + $c2 = $coef1 * $sat->deep_arg->xnodp * ($sat->deep_arg->aodp * + (1.0 + 1.5 * $etasq + $eeta * + (4.0 + $etasq)) + 0.75 * Predict::ck2 * $tsi / $psisq * + $sat->sgps->x3thm1 * (8.0 + 3.0 * $etasq * + (8.0 + $etasq))); + $sat->sgps->c1 = $sat->tle->bstar * $c2; + $sat->deep_arg->sinio = sin($sat->tle->xincl); + $a3ovk2 = -Predict::xj3 / Predict::ck2 * pow(Predict::ae, 3); + $sat->sgps->x1mth2 = 1.0 - $sat->deep_arg->theta2; + $sat->sgps->c4 = 2.0 * $sat->deep_arg->xnodp * $coef1 * + $sat->deep_arg->aodp * $sat->deep_arg->betao2 * + ($eta * (2.0 + 0.5 * $etasq) + $sat->tle->eo * + (0.5 + 2.0 * $etasq) - 2.0 * Predict::ck2 * $tsi / + ($sat->deep_arg->aodp * $psisq) * (-3.0 * $sat->sgps->x3thm1 * + (1.0 - 2.0 * $eeta + $etasq * + (1.5 - 0.5 * $eeta)) + + 0.75 * $sat->sgps->x1mth2 * + (2.0 * $etasq - $eeta * (1.0 + $etasq)) * + cos(2.0 * $sat->tle->omegao))); + $theta4 = $sat->deep_arg->theta2 * $sat->deep_arg->theta2; + $temp1 = 3.0 * Predict::ck2 * $pinvsq * $sat->deep_arg->xnodp; + $temp2 = $temp1 * Predict::ck2 * $pinvsq; + $temp3 = 1.25 * Predict::ck4 * $pinvsq * $pinvsq * $sat->deep_arg->xnodp; + $sat->deep_arg->xmdot = $sat->deep_arg->xnodp + 0.5 * $temp1 * $sat->deep_arg->betao * + $sat->sgps->x3thm1 + 0.0625 * $temp2 * $sat->deep_arg->betao * + (13.0 - 78.0 * $sat->deep_arg->theta2 + 137.0 * $theta4); + $x1m5th = 1.0 - 5.0 * $sat->deep_arg->theta2; + $sat->deep_arg->omgdot = -0.5 * $temp1 * $x1m5th + 0.0625 * $temp2 * + (7.0 - 114.0 * $sat->deep_arg->theta2 + 395.0 * $theta4) + + $temp3 * (3.0 - 36.0 * $sat->deep_arg->theta2 + 49.0 * $theta4); + $xhdot1 = -$temp1 * $sat->deep_arg->cosio; + $sat->deep_arg->xnodot = $xhdot1 + (0.5 * $temp2 * (4.0 - 19.0 * $sat->deep_arg->theta2) + + 2.0 * $temp3 * (3.0 - 7.0 * $sat->deep_arg->theta2)) * + $sat->deep_arg->cosio; + $sat->sgps->xnodcf = 3.5 * $sat->deep_arg->betao2 * $xhdot1 * $sat->sgps->c1; + $sat->sgps->t2cof = 1.5 * $sat->sgps->c1; + $sat->sgps->xlcof = 0.125 * $a3ovk2 * $sat->deep_arg->sinio * + (3.0 + 5.0 * $sat->deep_arg->cosio) / (1.0 + $sat->deep_arg->cosio); + $sat->sgps->aycof = 0.25 * $a3ovk2 * $sat->deep_arg->sinio; + $sat->sgps->x7thm1 = 7.0 * $sat->deep_arg->theta2 - 1.0; + + /* initialize Deep() */ + $this->Deep(self::dpinit, $sat); + }; /*End of SDP4() initialization */ + + /* Update for secular gravity and atmospheric drag */ + $xmdf = $sat->tle->xmo + $sat->deep_arg->xmdot * $tsince; + $sat->deep_arg->omgadf = $sat->tle->omegao + $sat->deep_arg->omgdot * $tsince; + $xnoddf = $sat->tle->xnodeo + $sat->deep_arg->xnodot * $tsince; + $tsq = $tsince * $tsince; + $sat->deep_arg->xnode = $xnoddf + $sat->sgps->xnodcf * $tsq; + $tempa = 1.0 - $sat->sgps->c1 * $tsince; + $tempe = $sat->tle->bstar * $sat->sgps->c4 * $tsince; + $templ = $sat->sgps->t2cof * $tsq; + $sat->deep_arg->xn = $sat->deep_arg->xnodp; + + /* Update for deep-space secular effects */ + $sat->deep_arg->xll = $xmdf; + $sat->deep_arg->t = $tsince; + + $this->Deep(self::dpsec, $sat); + + $xmdf = $sat->deep_arg->xll; + $a = pow(Predict::xke / $sat->deep_arg->xn, Predict::tothrd) * $tempa * $tempa; + $sat->deep_arg->em = $sat->deep_arg->em - $tempe; + $xmam = $xmdf + $sat->deep_arg->xnodp * $templ; + + /* Update for deep-space periodic effects */ + $sat->deep_arg->xll = $xmam; + + $this->Deep(self::dpper, $sat); + + $xmam = $sat->deep_arg->xll; + $xl = $xmam + $sat->deep_arg->omgadf + $sat->deep_arg->xnode; + $beta = sqrt(1.0 - $sat->deep_arg->em * $sat->deep_arg->em); + $sat->deep_arg->xn = Predict::xke / pow($a, 1.5); + + /* Long period periodics */ + $axn = $sat->deep_arg->em * cos($sat->deep_arg->omgadf); + $temp = 1.0 / ($a * $beta * $beta); + $xll = $temp * $sat->sgps->xlcof * $axn; + $aynl = $temp * $sat->sgps->aycof; + $xlt = $xl + $xll; + $ayn = $sat->deep_arg->em * sin($sat->deep_arg->omgadf) + $aynl; + + /* Solve Kepler's Equation */ + $capu = Predict_Math::FMod2p ($xlt - $sat->deep_arg->xnode); + $temp2 = $capu; + + $i = 0; + do { + $sinepw = sin($temp2); + $cosepw = cos($temp2); + $temp3 = $axn * $sinepw; + $temp4 = $ayn * $cosepw; + $temp5 = $axn * $cosepw; + $temp6 = $ayn * $sinepw; + $epw = ($capu - $temp4 + $temp3 - $temp2) / (1.0 - $temp5 - $temp6) + $temp2; + if (abs($epw - $temp2) <= Predict::e6a) { + break; + } + $temp2 = $epw; + } while ($i++ < 10); + + /* Short period preliminary quantities */ + $ecose = $temp5 + $temp6; + $esine = $temp3 - $temp4; + $elsq = $axn * $axn + $ayn * $ayn; + $temp = 1.0 - $elsq; + $pl = $a * $temp; + $r = $a * (1.0 - $ecose); + $temp1 = 1.0 / $r; + $rdot = Predict::xke * sqrt($a) * $esine * $temp1; + $rfdot = Predict::xke * sqrt($pl) * $temp1; + $temp2 = $a * $temp1; + $betal = sqrt($temp); + $temp3 = 1.0 / (1.0 + $betal); + $cosu = $temp2 * ($cosepw - $axn + $ayn * $esine * $temp3); + $sinu = $temp2 * ($sinepw - $ayn - $axn * $esine * $temp3); + $u = Predict_Math::AcTan($sinu, $cosu); + $sin2u = 2.0 * $sinu * $cosu; + $cos2u = 2.0 * $cosu * $cosu - 1.0; + $temp = 1.0 / $pl; + $temp1 = Predict::ck2 * $temp; + $temp2 = $temp1 * $temp; + + /* Update for short periodics */ + $rk = $r * (1.0 - 1.5 * $temp2 * $betal * $sat->sgps->x3thm1) + + 0.5 * $temp1 * $sat->sgps->x1mth2 * $cos2u; + $uk = $u - 0.25 * $temp2 * $sat->sgps->x7thm1 * $sin2u; + $xnodek = $sat->deep_arg->xnode + 1.5 * $temp2 * $sat->deep_arg->cosio * $sin2u; + $xinck = $sat->deep_arg->xinc + 1.5 * $temp2 * + $sat->deep_arg->cosio * $sat->deep_arg->sinio * $cos2u; + $rdotk = $rdot - $sat->deep_arg->xn * $temp1 * $sat->sgps->x1mth2 * $sin2u; + $rfdotk = $rfdot + $sat->deep_arg->xn * $temp1 * + ($sat->sgps->x1mth2 * $cos2u + 1.5 * $sat->sgps->x3thm1); + + /* Orientation vectors */ + $sinuk = sin($uk); + $cosuk = cos($uk); + $sinik = sin($xinck); + $cosik = cos($xinck); + $sinnok = sin($xnodek); + $cosnok = cos($xnodek); + $xmx = -$sinnok * $cosik; + $xmy = $cosnok * $cosik; + $ux = $xmx * $sinuk + $cosnok * $cosuk; + $uy = $xmy * $sinuk + $sinnok * $cosuk; + $uz = $sinik * $sinuk; + $vx = $xmx * $cosuk - $cosnok * $sinuk; + $vy = $xmy * $cosuk - $sinnok * $sinuk; + $vz = $sinik * $cosuk; + + /* Position and velocity */ + $sat->pos->x = $rk * $ux; + $sat->pos->y = $rk * $uy; + $sat->pos->z = $rk * $uz; + $sat->vel->x = $rdotk * $ux + $rfdotk * $vx; + $sat->vel->y = $rdotk * $uy + $rfdotk * $vy; + $sat->vel->z = $rdotk * $uz + $rfdotk * $vz; + + /* Phase in rads */ + $sat->phase = $xlt - $sat->deep_arg->xnode - $sat->deep_arg->omgadf + Predict::twopi; + if ($sat->phase < 0.0) { + $sat->phase += Predict::twopi; + } + $sat->phase = Predict_Math::FMod2p ($sat->phase); + + $sat->tle->omegao1 = $sat->deep_arg->omgadf; + $sat->tle->xincl1 = $sat->deep_arg->xinc; + $sat->tle->xnodeo1 = $sat->deep_arg->xnode; + } /* SDP4 */ + + + /* DEEP */ + /* This function is used by SDP4 to add lunar and solar */ + /* perturbation effects to deep-space orbit objects. */ + public function Deep($ientry, Predict_Sat $sat) + { + switch ($ientry) { + case self::dpinit : /* Entrance for deep space initialization */ + $sat->dps->thgr = Predict_Time::ThetaG($sat->tle->epoch, $sat->deep_arg); + $eq = $sat->tle->eo; + $sat->dps->xnq = $sat->deep_arg->xnodp; + $aqnv = 1.0 / $sat->deep_arg->aodp; + $sat->dps->xqncl = $sat->tle->xincl; + $xmao = $sat->tle->xmo; + $xpidot = $sat->deep_arg->omgdot + $sat->deep_arg->xnodot; + $sinq = sin($sat->tle->xnodeo); + $cosq = cos($sat->tle->xnodeo); + $sat->dps->omegaq = $sat->tle->omegao; + $sat->dps->preep = 0; + + /* Initialize lunar solar terms */ + $day = $sat->deep_arg->ds50 + 18261.5; /* Days since 1900 Jan 0.5 */ + if ($day != $sat->dps->preep) { + $sat->dps->preep = $day; + $xnodce = 4.5236020 - 9.2422029E-4 * $day; + $stem = sin($xnodce); + $ctem = cos($xnodce); + $sat->dps->zcosil = 0.91375164 - 0.03568096 * $ctem; + $sat->dps->zsinil = sqrt(1.0 - $sat->dps->zcosil * $sat->dps->zcosil); + $sat->dps->zsinhl = 0.089683511 * $stem / $sat->dps->zsinil; + $sat->dps->zcoshl = sqrt(1.0 - $sat->dps->zsinhl * $sat->dps->zsinhl); + $c = 4.7199672 + 0.22997150 * $day; + $gam = 5.8351514 + 0.0019443680 * $day; + $sat->dps->zmol = Predict_Math::FMod2p($c - $gam); + $zx = 0.39785416 * $stem / $sat->dps->zsinil; + $zy = $sat->dps->zcoshl * $ctem + 0.91744867 * $sat->dps->zsinhl * $stem; + $zx = Predict_Math::AcTan($zx, $zy); + $zx = $gam + $zx - $xnodce; + $sat->dps->zcosgl = cos($zx); + $sat->dps->zsingl = sin($zx); + $sat->dps->zmos = 6.2565837 + 0.017201977 * $day; + $sat->dps->zmos = Predict_Math::FMod2p($sat->dps->zmos); + } /* End if(day != preep) */ + + /* Do solar terms */ + $sat->dps->savtsn = 1E20; + $zcosg = Predict::zcosgs; + $zsing = Predict::zsings; + $zcosi = Predict::zcosis; + $zsini = Predict::zsinis; + $zcosh = $cosq; + $zsinh = $sinq; + $cc = Predict::c1ss; + $zn = Predict::zns; + $ze = Predict::zes; + $zmo = $sat->dps->zmos; + $xnoi = 1.0 / $sat->dps->xnq; + + /* Loop breaks when Solar terms are done a second */ + /* time, after Lunar terms are initialized */ + for(;;) { + /* Solar terms done again after Lunar terms are done */ + $a1 = $zcosg * $zcosh + $zsing * $zcosi * $zsinh; + $a3 = -$zsing * $zcosh + $zcosg * $zcosi * $zsinh; + $a7 = -$zcosg * $zsinh + $zsing * $zcosi * $zcosh; + $a8 = $zsing * $zsini; + $a9 = $zsing * $zsinh + $zcosg * $zcosi * $zcosh; + $a10 = $zcosg * $zsini; + $a2 = $sat->deep_arg->cosio * $a7 + $sat->deep_arg->sinio * $a8; + $a4 = $sat->deep_arg->cosio * $a9 + $sat->deep_arg->sinio * $a10; + $a5 = -$sat->deep_arg->sinio * $a7 + $sat->deep_arg->cosio * $a8; + $a6 = -$sat->deep_arg->sinio * $a9 + $sat->deep_arg->cosio * $a10; + $x1 = $a1 * $sat->deep_arg->cosg + $a2 * $sat->deep_arg->sing; + $x2 = $a3 * $sat->deep_arg->cosg + $a4 * $sat->deep_arg->sing; + $x3 = -$a1 * $sat->deep_arg->sing + $a2 * $sat->deep_arg->cosg; + $x4 = -$a3 * $sat->deep_arg->sing + $a4 * $sat->deep_arg->cosg; + $x5 = $a5 * $sat->deep_arg->sing; + $x6 = $a6 * $sat->deep_arg->sing; + $x7 = $a5 * $sat->deep_arg->cosg; + $x8 = $a6 * $sat->deep_arg->cosg; + $z31 = 12 * $x1 * $x1 - 3 * $x3 * $x3; + $z32 = 24 * $x1 * $x2 - 6 * $x3 * $x4; + $z33 = 12 * $x2 * $x2 - 3 * $x4 * $x4; + $z1 = 3 * ($a1 * $a1 + $a2 * $a2) + $z31 * $sat->deep_arg->eosq; + $z2 = 6 * ($a1 * $a3 + $a2 * $a4) + $z32 * $sat->deep_arg->eosq; + $z3 = 3 * ($a3 * $a3 + $a4 * $a4) + $z33 * $sat->deep_arg->eosq; + $z11 = -6 * $a1 * $a5 + $sat->deep_arg->eosq * (-24 * $x1 * $x7 - 6 * $x3 * $x5); + $z12 = -6 * ($a1 * $a6 + $a3 * $a5) + $sat->deep_arg->eosq * + (-24 * ($x2 * $x7 + $x1 * $x8) - 6 * ($x3 * $x6 + $x4 * $x5)); + $z13 = -6 * $a3 * $a6 + $sat->deep_arg->eosq * (-24 * $x2 * $x8 - 6 * $x4 * $x6); + $z21 = 6 * $a2 * $a5 + $sat->deep_arg->eosq * (24 * $x1 * $x5 - 6 * $x3 * $x7); + $z22 = 6 * ($a4 * $a5 + $a2 * $a6) + $sat->deep_arg->eosq * + (24 * ($x2 * $x5 + $x1 * $x6) - 6 * ($x4 * $x7 + $x3 * $x8)); + $z23 = 6 * $a4 * $a6 + $sat->deep_arg->eosq * (24 * $x2 * $x6 - 6 * $x4 * $x8); + $z1 = $z1 + $z1 + $sat->deep_arg->betao2 * $z31; + $z2 = $z2 + $z2 + $sat->deep_arg->betao2 * $z32; + $z3 = $z3 + $z3 + $sat->deep_arg->betao2 * $z33; + $s3 = $cc * $xnoi; + $s2 = -0.5 * $s3 / $sat->deep_arg->betao; + $s4 = $s3 * $sat->deep_arg->betao; + $s1 = -15 * $eq * $s4; + $s5 = $x1 * $x3 + $x2 * $x4; + $s6 = $x2 * $x3 + $x1 * $x4; + $s7 = $x2 * $x4 - $x1 * $x3; + $se = $s1 * $zn * $s5; + $si = $s2 * $zn * ($z11 + $z13); + $sl = -$zn * $s3 * ($z1 + $z3 - 14 - 6 * $sat->deep_arg->eosq); + $sgh = $s4 * $zn * ($z31 + $z33 - 6); + $sh = -$zn * $s2 * ($z21 + $z23); + if ($sat->dps->xqncl < 5.2359877E-2) { + $sh = 0; + } + $sat->dps->ee2 = 2 * $s1 * $s6; + $sat->dps->e3 = 2 * $s1 * $s7; + $sat->dps->xi2 = 2 * $s2 * $z12; + $sat->dps->xi3 = 2 * $s2 * ($z13 - $z11); + $sat->dps->xl2 = -2 * $s3 * $z2; + $sat->dps->xl3 = -2 * $s3 * ($z3 - $z1); + $sat->dps->xl4 = -2 * $s3 * (-21 - 9 * $sat->deep_arg->eosq) * $ze; + $sat->dps->xgh2 = 2 * $s4 * $z32; + $sat->dps->xgh3 = 2 * $s4 * ($z33 - $z31); + $sat->dps->xgh4 = -18 * $s4 * $ze; + $sat->dps->xh2 = -2 * $s2 * $z22; + $sat->dps->xh3 = -2 * $s2 * ($z23 - $z21); + + if ($sat->flags & self::LUNAR_TERMS_DONE_FLAG) { + break; + } + + /* Do lunar terms */ + $sat->dps->sse = $se; + $sat->dps->ssi = $si; + $sat->dps->ssl = $sl; + $sat->dps->ssh = $sh / $sat->deep_arg->sinio; + $sat->dps->ssg = $sgh - $sat->deep_arg->cosio * $sat->dps->ssh; + $sat->dps->se2 = $sat->dps->ee2; + $sat->dps->si2 = $sat->dps->xi2; + $sat->dps->sl2 = $sat->dps->xl2; + $sat->dps->sgh2 = $sat->dps->xgh2; + $sat->dps->sh2 = $sat->dps->xh2; + $sat->dps->se3 = $sat->dps->e3; + $sat->dps->si3 = $sat->dps->xi3; + $sat->dps->sl3 = $sat->dps->xl3; + $sat->dps->sgh3 = $sat->dps->xgh3; + $sat->dps->sh3 = $sat->dps->xh3; + $sat->dps->sl4 = $sat->dps->xl4; + $sat->dps->sgh4 = $sat->dps->xgh4; + $zcosg = $sat->dps->zcosgl; + $zsing = $sat->dps->zsingl; + $zcosi = $sat->dps->zcosil; + $zsini = $sat->dps->zsinil; + $zcosh = $sat->dps->zcoshl * $cosq + $sat->dps->zsinhl * $sinq; + $zsinh = $sinq * $sat->dps->zcoshl - $cosq * $sat->dps->zsinhl; + $zn = Predict::znl; + $cc = Predict::c1l; + $ze = Predict::zel; + $zmo = $sat->dps->zmol; + $sat->flags |= self::LUNAR_TERMS_DONE_FLAG; + } /* End of for(;;) */ + + $sat->dps->sse = $sat->dps->sse + $se; + $sat->dps->ssi = $sat->dps->ssi + $si; + $sat->dps->ssl = $sat->dps->ssl + $sl; + $sat->dps->ssg = $sat->dps->ssg + $sgh - $sat->deep_arg->cosio / $sat->deep_arg->sinio * $sh; + $sat->dps->ssh = $sat->dps->ssh + $sh / $sat->deep_arg->sinio; + + /* Geopotential resonance initialization for 12 hour orbits */ + $sat->flags &= ~self::RESONANCE_FLAG; + $sat->flags &= ~self::SYNCHRONOUS_FLAG; + + if (!(($sat->dps->xnq < 0.0052359877) && ($sat->dps->xnq > 0.0034906585))) { + if( ($sat->dps->xnq < 0.00826) || ($sat->dps->xnq > 0.00924) ) { + return; + } + if ($eq < 0.5) { + return; + } + $sat->flags |= self::RESONANCE_FLAG; + $eoc = $eq * $sat->deep_arg->eosq; + $g201 = -0.306 - ($eq - 0.64) * 0.440; + if ($eq <= 0.65) { + $g211 = 3.616 - 13.247 * $eq + 16.290 * $sat->deep_arg->eosq; + $g310 = -19.302 + 117.390 * $eq - 228.419 * + $sat->deep_arg->eosq + 156.591 * $eoc; + $g322 = -18.9068 + 109.7927 * $eq - 214.6334 * + $sat->deep_arg->eosq + 146.5816 * $eoc; + $g410 = -41.122 + 242.694 * $eq - 471.094 * + $sat->deep_arg->eosq + 313.953 * $eoc; + $g422 = -146.407 + 841.880 * $eq - 1629.014 * + $sat->deep_arg->eosq + 1083.435 * $eoc; + $g520 = -532.114 + 3017.977 * $eq - 5740 * + $sat->deep_arg->eosq + 3708.276 * $eoc; + } else { + $g211 = -72.099 + 331.819 * $eq - 508.738 * + $sat->deep_arg->eosq + 266.724 * $eoc; + $g310 = -346.844 + 1582.851 * $eq - 2415.925 * + $sat->deep_arg->eosq + 1246.113 * $eoc; + $g322 = -342.585 + 1554.908 * $eq - 2366.899 * + $sat->deep_arg->eosq + 1215.972 * $eoc; + $g410 = -1052.797 + 4758.686 * $eq - 7193.992 * + $sat->deep_arg->eosq + 3651.957 * $eoc; + $g422 = -3581.69 + 16178.11 * $eq - 24462.77 * + $sat->deep_arg->eosq+ 12422.52 * $eoc; + if ($eq <= 0.715) { + $g520 = 1464.74 - 4664.75 * $eq + 3763.64 * $sat->deep_arg->eosq; + } else { + $g520 = -5149.66 + 29936.92 * $eq - 54087.36 * + $sat->deep_arg->eosq + 31324.56 * $eoc; + } + } /* End if (eq <= 0.65) */ + + if ($eq < 0.7) { + $g533 = -919.2277 + 4988.61 * $eq - 9064.77 * + $sat->deep_arg->eosq + 5542.21 * $eoc; + $g521 = -822.71072 + 4568.6173 * $eq - 8491.4146 * + $sat->deep_arg->eosq + 5337.524 * $eoc; + $g532 = -853.666 + 4690.25 * $eq - 8624.77 * + $sat->deep_arg->eosq + 5341.4 * $eoc; + } + else { + $g533 = -37995.78 + 161616.52 * $eq - 229838.2* + $sat->deep_arg->eosq + 109377.94 * $eoc; + $g521 = -51752.104 + 218913.95 * $eq - 309468.16* + $sat->deep_arg->eosq + 146349.42 * $eoc; + $g532 = -40023.88 + 170470.89 * $eq - 242699.48* + $sat->deep_arg->eosq + 115605.82 * $eoc; + } /* End if (eq <= 0.7) */ + + $sini2 = $sat->deep_arg->sinio * $sat->deep_arg->sinio; + $f220 = 0.75 * (1 + 2 * $sat->deep_arg->cosio + $sat->deep_arg->theta2); + $f221 = 1.5 * $sini2; + $f321 = 1.875 * $sat->deep_arg->sinio * (1 - 2 * + $sat->deep_arg->cosio - 3 * $sat->deep_arg->theta2); + $f322 = -1.875 * $sat->deep_arg->sinio * (1 + 2* + $sat->deep_arg->cosio - 3 * $sat->deep_arg->theta2); + $f441 = 35 * $sini2 * $f220; + $f442 = 39.3750 * $sini2 * $sini2; + $f522 = 9.84375 * $sat->deep_arg->sinio * ($sini2 * (1 - 2 * $sat->deep_arg->cosio - 5 * + $sat->deep_arg->theta2) + 0.33333333 * (-2 + 4 * $sat->deep_arg->cosio + + 6 * $sat->deep_arg->theta2)); + $f523 = $sat->deep_arg->sinio * (4.92187512 * $sini2 * (-2 - 4 * + $sat->deep_arg->cosio + 10 * $sat->deep_arg->theta2) + 6.56250012 + * (1 + 2 * $sat->deep_arg->cosio - 3 * $sat->deep_arg->theta2)); + $f542 = 29.53125 * $sat->deep_arg->sinio * (2 - 8 * + $sat->deep_arg->cosio + $sat->deep_arg->theta2 * + (-12 + 8 * $sat->deep_arg->cosio + 10 * $sat->deep_arg->theta2)); + $f543 = 29.53125 * $sat->deep_arg->sinio * (-2 - 8 * $sat->deep_arg->cosio + + $sat->deep_arg->theta2 * (12 + 8 * $sat->deep_arg->cosio - 10 * + $sat->deep_arg->theta2)); + $xno2 = $sat->dps->xnq * $sat->dps->xnq; + $ainv2 = $aqnv * $aqnv; + $temp1 = 3 * $xno2 * $ainv2; + $temp = $temp1 * Predict::root22; + $sat->dps->d2201 = $temp * $f220 * $g201; + $sat->dps->d2211 = $temp * $f221 * $g211; + $temp1 = $temp1 * $aqnv; + $temp = $temp1 * Predict::root32; + $sat->dps->d3210 = $temp * $f321 * $g310; + $sat->dps->d3222 = $temp * $f322 * $g322; + $temp1 = $temp1 * $aqnv; + $temp = 2 * $temp1 * Predict::root44; + $sat->dps->d4410 = $temp * $f441 * $g410; + $sat->dps->d4422 = $temp * $f442 * $g422; + $temp1 = $temp1 * $aqnv; + $temp = $temp1 * Predict::root52; + $sat->dps->d5220 = $temp * $f522 * $g520; + $sat->dps->d5232 = $temp * $f523 * $g532; + $temp = 2 * $temp1 * Predict::root54; + $sat->dps->d5421 = $temp * $f542 * $g521; + $sat->dps->d5433 = $temp * $f543 * $g533; + $sat->dps->xlamo = $xmao + $sat->tle->xnodeo + $sat->tle->xnodeo - $sat->dps->thgr - $sat->dps->thgr; + $bfact = $sat->deep_arg->xmdot + $sat->deep_arg->xnodot + + $sat->deep_arg->xnodot - Predict::thdt - Predict::thdt; + $bfact = $bfact + $sat->dps->ssl + $sat->dps->ssh + $sat->dps->ssh; + } else { + $sat->flags |= self::RESONANCE_FLAG; + $sat->flags |= self::SYNCHRONOUS_FLAG; + /* Synchronous resonance terms initialization */ + $g200 = 1 + $sat->deep_arg->eosq * (-2.5 + 0.8125 * $sat->deep_arg->eosq); + $g310 = 1 + 2 * $sat->deep_arg->eosq; + $g300 = 1 + $sat->deep_arg->eosq * (-6 + 6.60937 * $sat->deep_arg->eosq); + $f220 = 0.75 * (1 + $sat->deep_arg->cosio) * (1 + $sat->deep_arg->cosio); + $f311 = 0.9375 * $sat->deep_arg->sinio * $sat->deep_arg->sinio * + (1 + 3 * $sat->deep_arg->cosio) - 0.75 * (1 + $sat->deep_arg->cosio); + $f330 = 1 + $sat->deep_arg->cosio; + $f330 = 1.875 * $f330 * $f330 * $f330; + $sat->dps->del1 = 3 * $sat->dps->xnq * $sat->dps->xnq * $aqnv * $aqnv; + $sat->dps->del2 = 2 * $sat->dps->del1 * $f220 * $g200 * Predict::q22; + $sat->dps->del3 = 3 * $sat->dps->del1 * $f330 * $g300 * Predict::q33 * $aqnv; + $sat->dps->del1 = $sat->dps->del1 * $f311 * $g310 * Predict::q31 * $aqnv; + $sat->dps->fasx2 = 0.13130908; + $sat->dps->fasx4 = 2.8843198; + $sat->dps->fasx6 = 0.37448087; + $sat->dps->xlamo = $xmao + $sat->tle->xnodeo + $sat->tle->omegao - $sat->dps->thgr; + $bfact = $sat->deep_arg->xmdot + $xpidot - Predict::thdt; + $bfact = $bfact + $sat->dps->ssl + $sat->dps->ssg + $sat->dps->ssh; + } /* End if( !(xnq < 0.0052359877) && (xnq > 0.0034906585) ) */ + + $sat->dps->xfact = $bfact - $sat->dps->xnq; + + /* Initialize integrator */ + $sat->dps->xli = $sat->dps->xlamo; + $sat->dps->xni = $sat->dps->xnq; + $sat->dps->atime = 0; + $sat->dps->stepp = 720; + $sat->dps->stepn = -720; + $sat->dps->step2 = 259200; + /* End case self::dpinit: */ + return; + + case self::dpsec: /* Entrance for deep space secular effects */ + $sat->deep_arg->xll = $sat->deep_arg->xll + $sat->dps->ssl * $sat->deep_arg->t; + $sat->deep_arg->omgadf = $sat->deep_arg->omgadf + $sat->dps->ssg * $sat->deep_arg->t; + $sat->deep_arg->xnode = $sat->deep_arg->xnode + $sat->dps->ssh * $sat->deep_arg->t; + $sat->deep_arg->em = $sat->tle->eo + $sat->dps->sse * $sat->deep_arg->t; + $sat->deep_arg->xinc = $sat->tle->xincl + $sat->dps->ssi * $sat->deep_arg->t; + if ($sat->deep_arg->xinc < 0) { + $sat->deep_arg->xinc = -$sat->deep_arg->xinc; + $sat->deep_arg->xnode = $sat->deep_arg->xnode + Predict::pi; + $sat->deep_arg->omgadf = $sat->deep_arg->omgadf - Predict::pi; + } + if(~$sat->flags & self::RESONANCE_FLAG ) { + return; + } + + do { + if ( ($sat->dps->atime == 0) || + (($sat->deep_arg->t >= 0) && ($sat->dps->atime < 0)) || + (($sat->deep_arg->t < 0) && ($sat->dps->atime >= 0)) ) { + /* Epoch restart */ + if ($sat->deep_arg->t >= 0) { + $delt = $sat->dps->stepp; + } else { + $delt = $sat->dps->stepn; + } + + $sat->dps->atime = 0; + $sat->dps->xni = $sat->dps->xnq; + $sat->dps->xli = $sat->dps->xlamo; + } else { + if (abs($sat->deep_arg->t) >= abs($sat->dps->atime)) { + if ($sat->deep_arg->t > 0) { + $delt = $sat->dps->stepp; + } else { + $delt = $sat->dps->stepn; + } + } + } + + do { + if (abs($sat->deep_arg->t - $sat->dps->atime) >= $sat->dps->stepp) { + $sat->flags |= self::DO_LOOP_FLAG; + $sat->flags &= ~self::EPOCH_RESTART_FLAG; + } + else { + $ft = $sat->deep_arg->t - $sat->dps->atime; + $sat->flags &= ~self::DO_LOOP_FLAG; + } + + if (abs($sat->deep_arg->t) < abs($sat->dps->atime)) { + if ($sat->deep_arg->t >= 0) { + $delt = $sat->dps->stepn; + } else { + $delt = $sat->dps->stepp; + } + $sat->flags |= (self::DO_LOOP_FLAG | self::EPOCH_RESTART_FLAG); + } + + /* Dot terms calculated */ + if ($sat->flags & self::SYNCHRONOUS_FLAG) { + $xndot = $sat->dps->del1 * sin($sat->dps->xli - $sat->dps->fasx2) + $sat->dps->del2 * sin(2 * ($sat->dps->xli - $sat->dps->fasx4)) + + $sat->dps->del3 * sin(3 * ($sat->dps->xli - $sat->dps->fasx6)); + $xnddt = $sat->dps->del1 * cos($sat->dps->xli - $sat->dps->fasx2) + 2 * $sat->dps->del2 * cos(2 * ($sat->dps->xli - $sat->dps->fasx4)) + + 3 * $sat->dps->del3 * cos(3 * ($sat->dps->xli - $sat->dps->fasx6)); + } else { + $xomi = $sat->dps->omegaq + $sat->deep_arg->omgdot * $sat->dps->atime; + $x2omi = $xomi + $xomi; + $x2li = $sat->dps->xli + $sat->dps->xli; + $xndot = $sat->dps->d2201 * sin($x2omi + $sat->dps->xli - Predict::g22) + + $sat->dps->d2211 * sin($sat->dps->xli - Predict::g22) + + $sat->dps->d3210 * sin($xomi + $sat->dps->xli - Predict::g32) + + $sat->dps->d3222 * sin(-$xomi + $sat->dps->xli - Predict::g32) + + $sat->dps->d4410 * sin($x2omi + $x2li- Predict::g44) + + $sat->dps->d4422 * sin($x2li- Predict::g44) + + $sat->dps->d5220 * sin($xomi + $sat->dps->xli- Predict::g52) + + $sat->dps->d5232 * sin(-$xomi + $sat->dps->xli- Predict::g52) + + $sat->dps->d5421 * sin($xomi + $x2li - Predict::g54) + + $sat->dps->d5433 * sin(-$xomi + $x2li - Predict::g54); + $xnddt = $sat->dps->d2201 * cos($x2omi + $sat->dps->xli- Predict::g22) + + $sat->dps->d2211 * cos($sat->dps->xli - Predict::g22) + + $sat->dps->d3210 * cos($xomi + $sat->dps->xli - Predict::g32) + + $sat->dps->d3222 * cos(-$xomi + $sat->dps->xli - Predict::g32) + + $sat->dps->d5220 * cos($xomi + $sat->dps->xli - Predict::g52) + + $sat->dps->d5232 * cos(-$xomi + $sat->dps->xli - Predict::g52) + + 2 * ($sat->dps->d4410 * cos($x2omi + $x2li - Predict::g44) + + $sat->dps->d4422 * cos($x2li - Predict::g44) + + $sat->dps->d5421 * cos($xomi + $x2li - Predict::g54) + + $sat->dps->d5433 * cos(-$xomi + $x2li - Predict::g54)); + } /* End of if (isFlagSet(SYNCHRONOUS_FLAG)) */ + + $xldot = $sat->dps->xni + $sat->dps->xfact; + $xnddt = $xnddt * $xldot; + + if ($sat->flags & self::DO_LOOP_FLAG) { + $sat->dps->xli = $sat->dps->xli + $xldot * $delt + $xndot * $sat->dps->step2; + $sat->dps->xni = $sat->dps->xni + $xndot * $delt + $xnddt * $sat->dps->step2; + $sat->dps->atime = $sat->dps->atime + $delt; + } + } while (($sat->flags & self::DO_LOOP_FLAG) && + (~$sat->flags & self::EPOCH_RESTART_FLAG)); + } + while (($sat->flags & self::DO_LOOP_FLAG) && ($sat->flags & self::EPOCH_RESTART_FLAG)); + + $sat->deep_arg->xn = $sat->dps->xni + $xndot * $ft + $xnddt * $ft * $ft * 0.5; + $xl = $sat->dps->xli + $xldot * $ft + $xndot * $ft * $ft * 0.5; + $temp = -$sat->deep_arg->xnode + $sat->dps->thgr + $sat->deep_arg->t * Predict::thdt; + + if (~$sat->flags & self::SYNCHRONOUS_FLAG) { + $sat->deep_arg->xll = $xl + $temp + $temp; + } else { + $sat->deep_arg->xll = $xl - $sat->deep_arg->omgadf + $temp; + } + + return; + /* End case dpsec: */ + + case self::dpper: /* Entrance for lunar-solar periodics */ + $sinis = sin($sat->deep_arg->xinc); + $cosis = cos($sat->deep_arg->xinc); + if (abs($sat->dps->savtsn - $sat->deep_arg->t) >= 30) { + $sat->dps->savtsn = $sat->deep_arg->t; + $zm = $sat->dps->zmos + Predict::zns * $sat->deep_arg->t; + $zf = $zm + 2 * Predict::zes * sin($zm); + $sinzf = sin($zf); + $f2 = 0.5 * $sinzf * $sinzf - 0.25; + $f3 = -0.5 * $sinzf * cos($zf); + $ses = $sat->dps->se2 * $f2 + $sat->dps->se3 * $f3; + $sis = $sat->dps->si2 * $f2 + $sat->dps->si3 * $f3; + $sls = $sat->dps->sl2 * $f2 + $sat->dps->sl3 * $f3 + $sat->dps->sl4 * $sinzf; + $sat->dps->sghs = $sat->dps->sgh2 * $f2 + $sat->dps->sgh3 * $f3 + $sat->dps->sgh4 * $sinzf; + $sat->dps->shs = $sat->dps->sh2 * $f2 + $sat->dps->sh3 * $f3; + $zm = $sat->dps->zmol + Predict::znl * $sat->deep_arg->t; + $zf = $zm + 2 * Predict::zel * sin($zm); + $sinzf = sin($zf); + $f2 = 0.5 * $sinzf * $sinzf - 0.25; + $f3 = -0.5 * $sinzf * cos($zf); + $sel = $sat->dps->ee2 * $f2 + $sat->dps->e3 * $f3; + $sil = $sat->dps->xi2 * $f2 + $sat->dps->xi3 * $f3; + $sll = $sat->dps->xl2 * $f2 + $sat->dps->xl3 * $f3 + $sat->dps->xl4 * $sinzf; + $sat->dps->sghl = $sat->dps->xgh2 * $f2 + $sat->dps->xgh3 * $f3 + $sat->dps->xgh4 * $sinzf; + $sat->dps->sh1 = $sat->dps->xh2 * $f2 + $sat->dps->xh3 * $f3; + $sat->dps->pe = $ses + $sel; + $sat->dps->pinc = $sis + $sil; + $sat->dps->pl = $sls + $sll; + } + + $pgh = $sat->dps->sghs + $sat->dps->sghl; + $ph = $sat->dps->shs + $sat->dps->sh1; + $sat->deep_arg->xinc = $sat->deep_arg->xinc + $sat->dps->pinc; + $sat->deep_arg->em = $sat->deep_arg->em + $sat->dps->pe; + + if ($sat->dps->xqncl >= 0.2) { + /* Apply periodics directly */ + $ph = $ph / $sat->deep_arg->sinio; + $pgh = $pgh - $sat->deep_arg->cosio * $ph; + $sat->deep_arg->omgadf = $sat->deep_arg->omgadf + $pgh; + $sat->deep_arg->xnode = $sat->deep_arg->xnode + $ph; + $sat->deep_arg->xll = $sat->deep_arg->xll + $sat->dps->pl; + } else { + /* Apply periodics with Lyddane modification */ + $sinok = sin($sat->deep_arg->xnode); + $cosok = cos($sat->deep_arg->xnode); + $alfdp = $sinis * $sinok; + $betdp = $sinis * $cosok; + $dalf = $ph * $cosok + $sat->dps->pinc * $cosis * $sinok; + $dbet = -$ph * $sinok + $sat->dps->pinc * $cosis * $cosok; + $alfdp = $alfdp + $dalf; + $betdp = $betdp + $dbet; + $sat->deep_arg->xnode = Predict_Math::FMod2p($sat->deep_arg->xnode); + $xls = $sat->deep_arg->xll + $sat->deep_arg->omgadf + $cosis * $sat->deep_arg->xnode; + $dls = $sat->dps->pl + $pgh - $sat->dps->pinc * $sat->deep_arg->xnode * $sinis; + $xls = $xls + $dls; + $xnoh = $sat->deep_arg->xnode; + $sat->deep_arg->xnode = Predict_Math::AcTan($alfdp, $betdp); + + /* This is a patch to Lyddane modification */ + /* suggested by Rob Matson. */ + if(abs($xnoh - $sat->deep_arg->xnode) > Predict::pi) { + if ($sat->deep_arg->xnode < $xnoh) { + $sat->deep_arg->xnode += Predict::twopi; + } else { + $sat->deep_arg->xnode -= Predict::twopi; + } + } + + $sat->deep_arg->xll = $sat->deep_arg->xll + $sat->dps->pl; + $sat->deep_arg->omgadf = $xls - $sat->deep_arg->xll - cos($sat->deep_arg->xinc) * + $sat->deep_arg->xnode; + } /* End case dpper: */ + return; + + } /* End switch(ientry) */ + + } /* End of Deep() */ + + /** + * Singleton + * + * @param Predict_Sat $sat The current satellite data instance + * + * @return Predict_SGPSDP + */ + public static function getInstance(Predict_Sat $sat) + { + static $instances = array(); + $catnr = $sat->tle->catnr; + if (!isset($instances[$catnr])) { + $instances[$catnr] = new self(); + } + return $instances[$catnr]; + } +} +?> diff --git a/lib/predict/Predict/SGSDPStatic.php b/lib/predict/Predict/SGSDPStatic.php new file mode 100644 index 0000000..12a43a4 --- /dev/null +++ b/lib/predict/Predict/SGSDPStatic.php @@ -0,0 +1,39 @@ +header); + $this->name = $headerParts[0]; + $this->nickname = $this->name; + $this->tle = $tle; + $this->pos = new Predict_Vector(); + $this->vel = new Predict_Vector(); + $this->sgps = new Predict_SGSDPStatic(); + $this->deep_arg = new Predict_DeepArg(); + $this->dps = new Predict_DeepStatic(); + + $this->select_ephemeris(); + $this->sat_data_init_sat($this); + } + + /* Selects the apropriate ephemeris type to be used */ + /* for predictions according to the data in the TLE */ + /* It also processes values in the tle set so that */ + /* they are apropriate for the sgp4/sdp4 routines */ + public function select_ephemeris() + { + /* Preprocess tle set */ + $this->tle->xnodeo *= Predict::de2ra; + $this->tle->omegao *= Predict::de2ra; + $this->tle->xmo *= Predict::de2ra; + $this->tle->xincl *= Predict::de2ra; + $temp = Predict::twopi / Predict::xmnpda / Predict::xmnpda; + + /* store mean motion before conversion */ + $this->meanmo = $this->tle->xno; + $this->tle->xno = $this->tle->xno * $temp * Predict::xmnpda; + $this->tle->xndt2o *= $temp; + $this->tle->xndd6o = $this->tle->xndd6o * $temp / Predict::xmnpda; + $this->tle->bstar /= Predict::ae; + + /* Period > 225 minutes is deep space */ + $dd1 = Predict::xke / $this->tle->xno; + $dd2 = Predict::tothrd; + $a1 = pow($dd1, $dd2); + $r1 = cos($this->tle->xincl); + $dd1 = 1.0 - $this->tle->eo * $this->tle->eo; + $temp = Predict::ck2 * 1.5 * ($r1 * $r1 * 3.0 - 1.0) / pow($dd1, 1.5); + $del1 = $temp / ($a1 * $a1); + $ao = $a1 * (1.0 - $del1 * (Predict::tothrd * 0.5 + $del1 * + ($del1 * 1.654320987654321 + 1.0))); + $delo = $temp / ($ao * $ao); + $xnodp = $this->tle->xno / ($delo + 1.0); + + /* Select a deep-space/near-earth ephemeris */ + if (Predict::twopi / $xnodp / Predict::xmnpda >= .15625) { + $this->flags |= Predict_SGPSDP::DEEP_SPACE_EPHEM_FLAG; + } else { + $this->flags &= ~Predict_SGPSDP::DEEP_SPACE_EPHEM_FLAG; + } + } + + /** Initialise satellite data. + * @param sat The satellite to initialise. + * @param qth Optional QTH info, use (0,0) if NULL. + * + * This function calculates the satellite data at t = 0, ie. epoch time + * The function is called automatically by gtk_sat_data_read_sat. + */ + public function sat_data_init_sat(Predict_Sat $sat, Predict_QTH $qth = null) + { + $obs_geodetic = new Predict_Geodetic(); + $obs_set = new Predict_ObsSet(); + $sat_geodetic = new Predict_Geodetic(); + /* double jul_utc, age; */ + + $jul_utc = Predict_Time::Julian_Date_of_Epoch($sat->tle->epoch); // => tsince = 0.0 + $sat->jul_epoch = $jul_utc; + + /* initialise observer location */ + if ($qth != null) { + $obs_geodetic->lon = $qth->lon * Predict::de2ra; + $obs_geodetic->lat = $qth->lat * Predict::de2ra; + $obs_geodetic->alt = $qth->alt / 1000.0; + $obs_geodetic->theta = 0; + } + else { + $obs_geodetic->lon = 0.0; + $obs_geodetic->lat = 0.0; + $obs_geodetic->alt = 0.0; + $obs_geodetic->theta = 0; + } + + /* execute computations */ + $sdpsgp = Predict_SGPSDP::getInstance($sat); + if ($sat->flags & Predict_SGPSDP::DEEP_SPACE_EPHEM_FLAG) { + $sdpsgp->SDP4($sat, 0.0); + } else { + $sdpsgp->SGP4($sat, 0.0); + } + + /* scale position and velocity to km and km/sec */ + Predict_Math::Convert_Sat_State($sat->pos, $sat->vel); + + /* get the velocity of the satellite */ + $sat->vel->w = sqrt($sat->vel->x * $sat->vel->x + $sat->vel->y * $sat->vel->y + $sat->vel->z * $sat->vel->z); + $sat->velo = $sat->vel->w; + Predict_SGPObs::Calculate_Obs($jul_utc, $sat->pos, $sat->vel, $obs_geodetic, $obs_set); + Predict_SGPObs::Calculate_LatLonAlt($jul_utc, $sat->pos, $sat_geodetic); + + while ($sat_geodetic->lon < -Predict::pi) { + $sat_geodetic->lon += Predict::twopi; + } + + while ($sat_geodetic->lon > Predict::pi) { + $sat_geodetic->lon -= Predict::twopi; + } + + $sat->az = Predict_Math::Degrees($obs_set->az); + $sat->el = Predict_Math::Degrees($obs_set->el); + $sat->range = $obs_set->range; + $sat->range_rate = $obs_set->range_rate; + $sat->ssplat = Predict_Math::Degrees($sat_geodetic->lat); + $sat->ssplon = Predict_Math::Degrees($sat_geodetic->lon); + $sat->alt = $sat_geodetic->alt; + $sat->ma = Predict_Math::Degrees($sat->phase); + $sat->ma *= 256.0 / 360.0; + $sat->footprint = 2.0 * Predict::xkmper * acos (Predict::xkmper/$sat->pos->w); + $age = 0.0; + $sat->orbit = floor(($sat->tle->xno * Predict::xmnpda / Predict::twopi + + $age * $sat->tle->bstar * Predict::ae) * $age + + $sat->tle->xmo / Predict::twopi) + $sat->tle->revnum - 1; + + /* orbit type */ + $sat->otype = $sat->get_orbit_type($sat); + } + + public function get_orbit_type(Predict_Sat $sat) + { + $orbit = Predict_SGPSDP::ORBIT_TYPE_UNKNOWN; + + if ($this->geostationary($sat)) { + $orbit = Predict_SGPSDP::ORBIT_TYPE_GEO; + } else if ($this->decayed($sat)) { + $orbit = Predict_SGPSDP::ORBIT_TYPE_DECAYED; + } else { + $orbit = Predict_SGPSDP::ORBIT_TYPE_UNKNOWN; + } + + return $orbit; + } + + + /** Determinte whether satellite is in geostationary orbit. + * @author John A. Magliacane, KD2BD + * @param sat Pointer to satellite data. + * @return TRUE if the satellite appears to be in geostationary orbit, + * FALSE otherwise. + * + * A satellite is in geostationary orbit if + * + * fabs (sat.meanmotion - 1.0027) < 0.0002 + * + * Note: Appearantly, the mean motion can deviate much more from 1.0027 than 0.0002 + */ + public function geostationary(Predict_Sat $sat) + { + if (abs($sat->meanmo - 1.0027) < 0.0002) { + return true; + } else { + return false; + } + } + + + /** Determine whether satellite has decayed. + * @author John A. Magliacane, KD2BD + * @author Alexandru Csete, OZ9AEC + * @param sat Pointer to satellite data. + * @return TRUE if the satellite appears to have decayed, FALSE otherwise. + * @bug Modified version of the predict code but it is not tested. + * + * A satellite is decayed if + * + * satepoch + ((16.666666 - sat.meanmo) / (10.0*fabs(sat.drag))) < "now" + * + */ + public function decayed(Predict_Sat $sat) + { + /* tle.xndt2o/(twopi/xmnpda/xmnpda) is the value before converted the + value matches up with the value in predict 2.2.3 */ + /*** FIXME decayed is treated as a static quantity. + It is time dependent. Also sat->jul_utc is often zero + when this function is called + ***/ + if ($sat->jul_epoch + ((16.666666 - $sat->meanmo) / + (10.0 * abs($sat->tle->xndt2o / (Predict::twopi / Predict::xmnpda / Predict::xmnpda)))) < $sat->jul_utc) { + return true; + } else { + return false; + } + } + + /** + * Experimental attempt at calculating apparent magnitude. Known intrinsic + * magnitudes are listed inside the function for now. + * + * @param float $time The daynum the satellite is calculated for + * @param Predict_QTH $qth The observer location + * + * @return null on failure, float otherwise + */ + public function calculateApparentMagnitude($time, Predict_QTH $qth) + { + // Recorded intrinsic magnitudes and their respective + // illumination and distance from heavens-above.com + static $intrinsicMagnitudes = array( + '25544' => array( + 'mag' => -1.3, + 'illum' => .5, + 'distance' => 1000, + ) + ); + + // Return null if we don't have a record of the intrinsic mag + if (!isset($intrinsicMagnitudes[$this->tle->catnr])) { + return null; + } + $imag = $intrinsicMagnitudes[$this->tle->catnr]; + + // Convert the observer's geodetic info to radians and km so + // we can compare vectors + $observerGeo = new Predict_Geodetic(); + $observerGeo->lat = Predict_Math::Radians($qth->lat); + $observerGeo->lon = Predict_Math::Radians($qth->lon); + $observerGeo->alt = $qth->alt * 1000; + + // Now determine the sun and observer positions + $observerPos = new Predict_Vector(); + $observerVel = new Predict_Vector(); + $solarVector = new Predict_Vector(); + Predict_Solar::Calculate_Solar_Position($time, $solarVector); + Predict_SGPObs::Calculate_User_PosVel($time, $observerGeo, $observerPos, $observerVel); + + // Determine the solar phase and and thus the percent illumination + $observerSatPos = new Predict_Vector(); + Predict_Math::Vec_Sub($this->pos, $observerPos, $observerSatPos); + $phaseAngle = Predict_Math::Degrees(Predict_Math::Angle($solarVector, $observerSatPos)); + $illum = $phaseAngle / 180; + + $illuminationChange = $illum / $imag['illum']; + $inverseSquareOfDistanceChange = pow(($imag['distance'] / $this->range), 2); + $changeInMagnitude = log( + $illuminationChange * $inverseSquareOfDistanceChange, + self::POGSONS_RATIO + ); + + return $imag['mag'] - $changeInMagnitude; + } +} diff --git a/lib/predict/Predict/Solar.php b/lib/predict/Predict/Solar.php new file mode 100644 index 0000000..06c2b9f --- /dev/null +++ b/lib/predict/Predict/Solar.php @@ -0,0 +1,106 @@ +x = $R * cos($Lsa); + $solar_vector->y = $R * sin($Lsa) * cos($eps); + $solar_vector->z = $R * sin($Lsa) * sin($eps); + $solar_vector->w = $R; + } + + /* Calculates stellite's eclipse status and depth */ + public static function Sat_Eclipsed(Predict_Vector $pos, Predict_Vector $sol, &$depth) + { + $Rho = new Predict_Vector(); + $earth = new Predict_Vector(); + + /* Determine partial eclipse */ + $sd_earth = Predict_Math::ArcSin(Predict::xkmper / $pos->w); + Predict_Math::Vec_Sub($sol, $pos, $Rho); + $sd_sun = Predict_Math::ArcSin(Predict::__sr__ / $Rho->w); + Predict_Math::Scalar_Multiply(-1, $pos, $earth); + $delta = Predict_Math::Angle($sol, $earth); + $depth = $sd_earth - $sd_sun - $delta; + + if ($sd_earth < $sd_sun) { + return 0; + } else if ($depth >= 0) { + return 1; + } else { + return 0; + } + } + + /** + * Finds the current location of the sun based on the observer location + * + * @param Predict_QTH $qth The observer location + * @param int $daynum The daynum or null to use the current daynum + * + * @return Predict_ObsSet + */ + public static function FindSun(Predict_QTH $qth, $daynum = null) + { + if ($daynum === null) { + $daynum = Predict_Time::get_current_daynum(); + } + + $obs_geodetic = new Predict_Geodetic(); + $obs_geodetic->lon = $qth->lon * Predict::de2ra; + $obs_geodetic->lat = $qth->lat * Predict::de2ra; + $obs_geodetic->alt = $qth->alt / 1000.0; + $obs_geodetic->theta = 0; + + $solar_vector = new Predict_Vector(); + $zero_vector = new Predict_Vector(); + $solar_set = new Predict_ObsSet(); + + self::Calculate_Solar_Position($daynum, $solar_vector); + Predict_SGPObs::Calculate_Obs( + $daynum, + $solar_vector, + $zero_vector, + $obs_geodetic, + $solar_set + ); + + $solar_set->az = Predict_Math::Degrees($solar_set->az); + $solar_set->el = Predict_Math::Degrees($solar_set->el); + + return $solar_set; + } +} diff --git a/lib/predict/Predict/TLE.php b/lib/predict/Predict/TLE.php new file mode 100644 index 0000000..4764f05 --- /dev/null +++ b/lib/predict/Predict/TLE.php @@ -0,0 +1,230 @@ +Good_Elements($line1, $line2)) { + throw new Predict_Exception('Invalid TLE contents'); + } + + $this->header = $header; + $this->line1 = $line1; + $this->line2 = $line2; + + /** Decode Card 1 **/ + /* Satellite's catalogue number */ + $this->catnr = (int) substr($line1, 2, 5); + + /* International Designator for satellite */ + $this->idesg = substr($line1, 9, 8); + + /* Epoch time; this is the complete, unconverted epoch. */ + /* Replace spaces with 0 before casting, as leading spaces are allowed */ + $this->epoch = (float) str_replace(' ', '0', substr($line1, 18, 14)); + + /* Now, convert the epoch time into year, day + and fraction of day, according to: + + YYDDD.FFFFFFFF + */ + + // Adjust for 2 digit year through 2056 + $this->epoch_year = (int) substr($line1, 18, 2); + if ($this->epoch_year > 56) { + $this->epoch_year = $this->epoch_year + 1900; + } else { + $this->epoch_year = $this->epoch_year + 2000; + } + + /* Epoch day */ + $this->epoch_day = (int) substr($line1, 20, 3); + + /* Epoch fraction of day */ + $this->epoch_fod = (float) substr($line1, 23, 9); + + + /* Satellite's First Time Derivative */ + $this->xndt2o = (float) substr($line1, 33, 10); + + /* Satellite's Second Time Derivative */ + $this->xndd6o = (float) (substr($line1, 44, 1) . '.' . substr($line1, 45, 5) . 'E' . substr($line1, 50, 2)); + + /* Satellite's bstar drag term + FIXME: How about buff[0] ???? + */ + $this->bstar = (float) (substr($line1, 53, 1) . '.' . substr($line1, 54, 5) . 'E' . substr($line1, 59, 2)); + + /* Element Number */ + $this->elset = (int) substr($line1, 64, 4); + + /** Decode Card 2 **/ + /* Satellite's Orbital Inclination (degrees) */ + $this->xincl = (float) substr($line2, 8, 8); + + /* Satellite's RAAN (degrees) */ + $this->xnodeo = (float) substr($line2, 17, 8); + + /* Satellite's Orbital Eccentricity */ + $this->eo = (float) ('.' . substr($line2, 26, 7)); + + /* Satellite's Argument of Perigee (degrees) */ + $this->omegao = (float) substr($line2, 34, 8); + + /* Satellite's Mean Anomaly of Orbit (degrees) */ + $this->xmo = (float) substr($line2, 43, 8); + + /* Satellite's Mean Motion (rev/day) */ + $this->xno = (float) substr($line2, 52, 11); + + /* Satellite's Revolution number at epoch */ + $this->revnum = (float) substr($line2, 63, 5); + } + + /* Calculates the checksum mod 10 of a line from a TLE set and */ + /* returns true if it compares with checksum in column 68, else false.*/ + /* tle_set is a character string holding the two lines read */ + /* from a text file containing NASA format Keplerian elements. */ + /* NOTE!!! The stuff about two lines is not quite true. + The function assumes that tle_set[0] is the begining + of the line and that there are 68 elements - see the consumer + */ + public function Checksum_Good($tle_set) + { + if (strlen($tle_set) < 69) { + return false; + } + + $checksum = 0; + + for ($i = 0; $i < 68; $i++) { + if (($tle_set[$i] >= '0') && ($tle_set[$i] <= '9')) { + $value = $tle_set[$i] - '0'; + } else if ($tle_set[$i] == '-' ) { + $value = 1; + } else { + $value = 0; + } + + $checksum += $value; + } + + $checksum %= 10; + $check_digit = $tle_set[68] - '0'; + + return $checksum == $check_digit; + } + + /* Carries out various checks on a TLE set to verify its validity */ + /* $line1 is the first line of the TLE, $line2 is the second line */ + /* from a text file containing NASA format Keplerian elements. */ + public function Good_Elements($line1, $line2) + { + /* Verify checksum of both lines of a TLE set */ + if (!$this->Checksum_Good($line1) || !$this->Checksum_Good($line2)) { + return false; + } + + /* Check the line number of each line */ + if (($line1[0] != '1') || ($line2[0] != '2')) { + return false; + } + + /* Verify that Satellite Number is same in both lines */ + if (strncmp($line1[2], $line2[2], 5) != 0) { + return false; + } + + /* Check that various elements are in the right place */ + if (($line1[23] != '.') || + ($line1[34] != '.') || + ($line2[11] != '.') || + ($line2[20] != '.') || + ($line2[37] != '.') || + ($line2[46] != '.') || + ($line2[54] != '.') || + (strncmp(substr($line1, 61), ' 0 ', 3) != 0)) { + + return false; + } + + return true; + } + + /** + * A function to allow checksum creation of a line. This is driven by + * the fact that some TLEs from SpaceTrack are missing checksum numbers. + * You can use this to create a checksum for a line, but you should + * probably have confidence that the TLE data itself is good. YMMV. + * + * @throws Predict_Exception if the line is not exactly 68 chars + * @return string + */ + static public function createChecksum($line) + { + if (strlen($line) != 68) { + throw Predict_Exception('Invalid line, needs to e 68 chars'); + } + + $checksum = 0; + + for ($i = 0; $i < 68; $i++) { + if (($line[$i] >= '0') && ($line[$i] <= '9')) { + $value = (int) $line[$i]; + } else if ($line[$i] == '-' ) { + $value = 1; + } else { + $value = 0; + } + + $checksum += $value; + } + + $checksum %= 10; + + return $checksum; + } +} diff --git a/lib/predict/Predict/Time.php b/lib/predict/Predict/Time.php new file mode 100644 index 0000000..b5c0d90 --- /dev/null +++ b/lib/predict/Predict/Time.php @@ -0,0 +1,229 @@ +ds50 = $jd - 2433281.5 + $UT; + + return Predict_Math::FMod2p(6.3003880987 * $deep_arg->ds50 + 1.72944494); + } + + /* See the ThetaG doc block above */ + public static function ThetaG_JD($jd) + { + /* Reference: The 1992 Astronomical Almanac, page B6. */ + $UT = Predict_Math::Frac($jd + 0.5); + $jd = $jd - $UT; + $TU = ($jd - 2451545.0) / 36525; + $GMST = 24110.54841 + $TU * (8640184.812866 + $TU * (0.093104 - $TU * 6.2E-6)); + $GMST = Predict_Math::Modulus($GMST + Predict::secday * Predict::omega_E * $UT, Predict::secday); + + return Predict::twopi * $GMST / Predict::secday; + } + + /** + * Read the system clock and return the current Julian day. From phpPredict + * + * @return float + */ + public static function get_current_daynum() { + // Gets the current decimal day number from microtime + + list($usec, $sec) = explode(' ', microtime()); + return self::unix2daynum($sec, $usec); + } + + /** + * Converts a standard unix timestamp and optional + * milliseconds to a daynum + * + * @param int $sec Seconds from the unix epoch + * @param int $usec Optional milliseconds + * + * @return float + */ + public static function unix2daynum($sec, $usec = 0) + { + $time = ((($sec + $usec) / 86400.0) - 3651.0); + return $time + 2444238.5; + } + + /* The function Delta_ET has been added to allow calculations on */ + /* the position of the sun. It provides the difference between UT */ + /* (approximately the same as UTC) and ET (now referred to as TDT).*/ + /* This function is based on a least squares fit of data from 1950 */ + /* to 1991 and will need to be updated periodically. */ + public static function Delta_ET($year) + { + /* Values determined using data from 1950-1991 in the 1990 + Astronomical Almanac. See DELTA_ET.WQ1 for details. */ + + $delta_et = 26.465 + 0.747622 * ($year - 1950) + + 1.886913 * sin(Predict::twopi * ($year - 1975) / 33); + + return $delta_et; + } + + /** + * Converts a daynum to a unix timestamp. From phpPredict. + * + * @param float $dn Julian Daynum + * + * @return float + */ + public static function daynum2unix($dn) { + // Converts a daynum to a UNIX timestamp + + return (86400.0 * ($dn - 2444238.5 + 3651.0)); + } + + /** + * Converts a daynum to a readable time format. + * + * @param float $dn The julian date + * @param string $zone The zone string, defaults to America/Los_Angeles + * @param string $format The date() function's format string. Defaults to m-d-Y H:i:s + * + * @return string + */ + public static function daynum2readable($dn, $zone = 'America/Los_Angeles', $format = 'm-d-Y H:i:s') + { + $unix = self::daynum2unix($dn); + $date = new DateTime("@" . round($unix)); + $dateTimezone = new DateTimezone($zone); + $date->setTimezone($dateTimezone); + return $date->format($format); + } + + public static function daynum2datetime($dn, $zone = 'UTC') + { + $unix = self::daynum2unix($dn); + $date = new DateTime("@" . round($unix)); + $dateTimezone = new DateTimezone($zone); + $date->setTimezone($dateTimezone); + return $date; + } + + /** + * Returns the unix timestamp of a TLE's epoch + * + * @param Predict_TLE $tle The TLE object + * + * @return int + */ + public static function getEpochTimeStamp(Predict_TLE $tle) + { + $year = $tle->epoch_year; + $day = $tle->epoch_day; + $sec = round(86400 * $tle->epoch_fod); + + $zone = new DateTimeZone('GMT'); + $date = new DateTime(); + $date->setTimezone($zone); + $date->setDate($year, 1, 1); + $date->setTime(0, 0, 0); + + return $date->format('U') + (86400 * $day) + $sec - 86400; + } +} diff --git a/lib/predict/Predict/Vector.php b/lib/predict/Predict/Vector.php new file mode 100644 index 0000000..8474905 --- /dev/null +++ b/lib/predict/Predict/Vector.php @@ -0,0 +1,13 @@ +save_run($xhprofData, $xhprofNameSpace); + } + register_shutdown_function('stop_xhprof_profiling'); +} + +$start = microtime(true); + +$predict = new Predict(); +$qth = new Predict_QTH(); +$qth->lat = 37.6550; +$qth->lon = -122.4070; +$qth->alt = 0; + +$tleFile = file('examples/iss.tle'); +$tle = new Predict_TLE($tleFile[0], $tleFile[1], $tleFile[2]); +$sat = new Predict_Sat($tle); +$now = Predict_Time::get_current_daynum(); + +$results = $predict->get_passes($sat, $qth, $now, 10); + +echo "Execution time: " . number_format((microtime(true) - $start) * 1000, 2) . "ms\n"; exit; diff --git a/lib/predict/examples/findsun.php b/lib/predict/examples/findsun.php new file mode 100644 index 0000000..1a3834f --- /dev/null +++ b/lib/predict/examples/findsun.php @@ -0,0 +1,31 @@ +lat = 37.786759; +$qth->lon = -122.405162; +$qth->alt = 10; // Altitude above sea level in meters + +$sunInfo = Predict_Solar::FindSun($qth, $daynum); + +$output = array( + 'elevation' => $sunInfo->el, + 'azimuth' => $sunInfo->az, + 'timestamp' => $time +); + +// output results +echo json_encode($output); diff --git a/lib/predict/examples/iss.tle b/lib/predict/examples/iss.tle new file mode 100644 index 0000000..e01670f --- /dev/null +++ b/lib/predict/examples/iss.tle @@ -0,0 +1,3 @@ +ISS (ZARYA) +1 25544U 98067A 21109.21251552 .00001445 00000-0 34486-4 0 9999 +2 25544 51.6452 274.4230 0002486 246.0034 286.0425 15.48900816279452 diff --git a/lib/predict/examples/solar_position.php b/lib/predict/examples/solar_position.php new file mode 100644 index 0000000..d07c4bc --- /dev/null +++ b/lib/predict/examples/solar_position.php @@ -0,0 +1,44 @@ +lat); +$solar_lon = Predict_Math::Degrees($solar_geodetic->lon); + +// Reverse values for night circle center +$dark_lat = -$solar_lat; +$dark_lon = -$solar_lon; + +$output = array( + 'solar_lat' => $solar_lat, + 'solar_lon' => $solar_lon, + 'dark_lat' => $dark_lat, + 'dark_lon' => $dark_lon, + 'timestamp' => $time +); + +// output results +var_dump(json_encode($output)); diff --git a/lib/predict/examples/visible_passes.php b/lib/predict/examples/visible_passes.php new file mode 100644 index 0000000..2741946 --- /dev/null +++ b/lib/predict/examples/visible_passes.php @@ -0,0 +1,74 @@ +alt = 0; // Altitude in meters + +// South San Francisco, example west of the meridian +$qth->lat = 37.6550; // Latitude North +$qth->lon = -122.4070; // Longitude East + +// Munich, example east of the meridian +// $qth->lat = 48.1505; // Lat North +// $qth->lon = 11.5809; // Lon East + +// The iss.tle file is the first 3 lines of +// http://celestrak.com/NORAD/elements/stations.txt +// Make sure you update this content, it goes out of date within a day or two +$tleFile = file('examples/iss.tle'); // Load up the ISS data file from NORAD +$tle = new Predict_TLE($tleFile[0], $tleFile[1], $tleFile[2]); // Instantiate it +$sat = new Predict_Sat($tle); // Load up the satellite data +$now = Predict_Time::get_current_daynum(); // get the current time as Julian Date (daynum) + +// You can modify some preferences in Predict(), the defaults are below +// +// $predict->minEle = 10; // Minimum elevation for a pass +// $predict->timeRes = 10; // Pass details: time resolution in seconds +// $predict->numEntries = 20; // Pass details: number of entries per pass +// $predict->threshold = -6; // Twilight threshold (sun must be at this lat or lower) + +// Get the passes and filter visible only, takes about 4 seconds for 10 days +$results = $predict->get_passes($sat, $qth, $now, 10); +$filtered = $predict->filterVisiblePasses($results); + +$zone = 'America/Los_Angeles'; // Pacific time zone +$format = 'm-d-Y H:i:s'; // Time format from PHP's date() function + +// Format the output similar to the heavens-above.com website +foreach ($filtered as $pass) { + echo "AOS Daynum: " . $pass->visible_aos . "\n"; + echo "AOS Time: " . Predict_Time::daynum2readable($pass->visible_aos, $zone, $format) . "\n"; + echo "AOS Az: " . $predict->azDegreesToDirection($pass->visible_aos_az) . "\n"; + echo "AOS El: " . round($pass->visible_aos_el) . "\n"; + echo "Max Time: " . Predict_Time::daynum2readable($pass->visible_tca, $zone, $format) . "\n"; + echo "Max Az: " . $predict->azDegreesToDirection($pass->visible_max_el_az) . "\n"; + echo "Max El: " . round($pass->visible_max_el) . "\n"; + echo "LOS Time: " . Predict_Time::daynum2readable($pass->visible_los, $zone, $format) . "\n"; + echo "LOS Az: " . $predict->azDegreesToDirection($pass->visible_los_az) . "\n"; + echo "LOS El: " . round($pass->visible_los_el) . "\n"; + echo "Magnitude: " . number_format($pass->max_apparent_magnitude, 1) . "\n"; + echo "\n"; +} + +// How long did this take? +echo "Execution time: " . number_format((microtime(true) - $start) * 1000, 2) . "ms\n"; exit; diff --git a/lib/predict/tests/Table.php b/lib/predict/tests/Table.php new file mode 100644 index 0000000..ce9d640 --- /dev/null +++ b/lib/predict/tests/Table.php @@ -0,0 +1,893 @@ + + * @author Jan Schneider + * @copyright 2002-2005 Richard Heyes + * @copyright 2006-2008 Jan Schneider + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version CVS: $Id: Table.php 268934 2008-11-13 10:35:34Z yunosh $ + * @link http://pear.php.net/package/Console_Table + */ + +define('CONSOLE_TABLE_HORIZONTAL_RULE', 1); +define('CONSOLE_TABLE_ALIGN_LEFT', -1); +define('CONSOLE_TABLE_ALIGN_CENTER', 0); +define('CONSOLE_TABLE_ALIGN_RIGHT', 1); +define('CONSOLE_TABLE_BORDER_ASCII', -1); + +/** + * The main class. + * + * @category Console + * @package Console_Table + * @author Jan Schneider + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @link http://pear.php.net/package/Console_Table + */ +class Console_Table +{ + /** + * The table headers. + * + * @var array + */ + var $_headers = array(); + + /** + * The data of the table. + * + * @var array + */ + var $_data = array(); + + /** + * The maximum number of columns in a row. + * + * @var integer + */ + var $_max_cols = 0; + + /** + * The maximum number of rows in the table. + * + * @var integer + */ + var $_max_rows = 0; + + /** + * Lengths of the columns, calculated when rows are added to the table. + * + * @var array + */ + var $_cell_lengths = array(); + + /** + * Heights of the rows. + * + * @var array + */ + var $_row_heights = array(); + + /** + * How many spaces to use to pad the table. + * + * @var integer + */ + var $_padding = 1; + + /** + * Column filters. + * + * @var array + */ + var $_filters = array(); + + /** + * Columns to calculate totals for. + * + * @var array + */ + var $_calculateTotals; + + /** + * Alignment of the columns. + * + * @var array + */ + var $_col_align = array(); + + /** + * Default alignment of columns. + * + * @var integer + */ + var $_defaultAlign; + + /** + * Character set of the data. + * + * @var string + */ + var $_charset = 'utf-8'; + + /** + * Border character. + * + * @var string + */ + var $_border = CONSOLE_TABLE_BORDER_ASCII; + + /** + * Whether the data has ANSI colors. + * + * @var boolean + */ + var $_ansiColor = false; + + /** + * Constructor. + * + * @param integer $align Default alignment. One of + * CONSOLE_TABLE_ALIGN_LEFT, + * CONSOLE_TABLE_ALIGN_CENTER or + * CONSOLE_TABLE_ALIGN_RIGHT. + * @param string $border The character used for table borders or + * CONSOLE_TABLE_BORDER_ASCII. + * @param integer $padding How many spaces to use to pad the table. + * @param string $charset A charset supported by the mbstring PHP + * extension. + * @param boolean $color Whether the data contains ansi color codes. + */ + function Console_Table($align = CONSOLE_TABLE_ALIGN_LEFT, + $border = CONSOLE_TABLE_BORDER_ASCII, $padding = 1, + $charset = null, $color = false) + { + $this->_defaultAlign = $align; + $this->_border = $border; + $this->_padding = $padding; + $this->_ansiColor = $color; + if ($this->_ansiColor) { + include_once 'Console/Color.php'; + } + if (!empty($charset)) { + $this->setCharset($charset); + } + } + + /** + * Converts an array to a table. + * + * @param array $headers Headers for the table. + * @param array $data A two dimensional array with the table + * data. + * @param boolean $returnObject Whether to return the Console_Table object + * instead of the rendered table. + * + * @static + * + * @return Console_Table|string A Console_Table object or the generated + * table. + */ + function fromArray($headers, $data, $returnObject = false) + { + if (!is_array($headers) || !is_array($data)) { + return false; + } + + $table = new Console_Table(); + $table->setHeaders($headers); + + foreach ($data as $row) { + $table->addRow($row); + } + + return $returnObject ? $table : $table->getTable(); + } + + /** + * Adds a filter to a column. + * + * Filters are standard PHP callbacks which are run on the data before + * table generation is performed. Filters are applied in the order they + * are added. The callback function must accept a single argument, which + * is a single table cell. + * + * @param integer $col Column to apply filter to. + * @param mixed &$callback PHP callback to apply. + * + * @return void + */ + function addFilter($col, &$callback) + { + $this->_filters[] = array($col, &$callback); + } + + /** + * Sets the charset of the provided table data. + * + * @param string $charset A charset supported by the mbstring PHP + * extension. + * + * @return void + */ + function setCharset($charset) + { + $locale = setlocale(LC_CTYPE, 0); + setlocale(LC_CTYPE, 'en_US'); + $this->_charset = strtolower($charset); + setlocale(LC_CTYPE, $locale); + } + + /** + * Sets the alignment for the columns. + * + * @param integer $col_id The column number. + * @param integer $align Alignment to set for this column. One of + * CONSOLE_TABLE_ALIGN_LEFT + * CONSOLE_TABLE_ALIGN_CENTER + * CONSOLE_TABLE_ALIGN_RIGHT. + * + * @return void + */ + function setAlign($col_id, $align = CONSOLE_TABLE_ALIGN_LEFT) + { + switch ($align) { + case CONSOLE_TABLE_ALIGN_CENTER: + $pad = STR_PAD_BOTH; + break; + case CONSOLE_TABLE_ALIGN_RIGHT: + $pad = STR_PAD_LEFT; + break; + default: + $pad = STR_PAD_RIGHT; + break; + } + $this->_col_align[$col_id] = $pad; + } + + /** + * Specifies which columns are to have totals calculated for them and + * added as a new row at the bottom. + * + * @param array $cols Array of column numbers (starting with 0). + * + * @return void + */ + function calculateTotalsFor($cols) + { + $this->_calculateTotals = $cols; + } + + /** + * Sets the headers for the columns. + * + * @param array $headers The column headers. + * + * @return void + */ + function setHeaders($headers) + { + $this->_headers = array(array_values($headers)); + $this->_updateRowsCols($headers); + } + + /** + * Adds a row to the table. + * + * @param array $row The row data to add. + * @param boolean $append Whether to append or prepend the row. + * + * @return void + */ + function addRow($row, $append = true) + { + if ($append) { + $this->_data[] = array_values($row); + } else { + array_unshift($this->_data, array_values($row)); + } + + $this->_updateRowsCols($row); + } + + /** + * Inserts a row after a given row number in the table. + * + * If $row_id is not given it will prepend the row. + * + * @param array $row The data to insert. + * @param integer $row_id Row number to insert before. + * + * @return void + */ + function insertRow($row, $row_id = 0) + { + array_splice($this->_data, $row_id, 0, array($row)); + + $this->_updateRowsCols($row); + } + + /** + * Adds a column to the table. + * + * @param array $col_data The data of the column. + * @param integer $col_id The column index to populate. + * @param integer $row_id If starting row is not zero, specify it here. + * + * @return void + */ + function addCol($col_data, $col_id = 0, $row_id = 0) + { + foreach ($col_data as $col_cell) { + $this->_data[$row_id++][$col_id] = $col_cell; + } + + $this->_updateRowsCols(); + $this->_max_cols = max($this->_max_cols, $col_id + 1); + } + + /** + * Adds data to the table. + * + * @param array $data A two dimensional array with the table data. + * @param integer $col_id Starting column number. + * @param integer $row_id Starting row number. + * + * @return void + */ + function addData($data, $col_id = 0, $row_id = 0) + { + foreach ($data as $row) { + if ($row === CONSOLE_TABLE_HORIZONTAL_RULE) { + $this->_data[$row_id] = CONSOLE_TABLE_HORIZONTAL_RULE; + $row_id++; + continue; + } + $starting_col = $col_id; + foreach ($row as $cell) { + $this->_data[$row_id][$starting_col++] = $cell; + } + $this->_updateRowsCols(); + $this->_max_cols = max($this->_max_cols, $starting_col); + $row_id++; + } + } + + /** + * Adds a horizontal seperator to the table. + * + * @return void + */ + function addSeparator() + { + $this->_data[] = CONSOLE_TABLE_HORIZONTAL_RULE; + } + + /** + * Returns the generated table. + * + * @return string The generated table. + */ + function getTable() + { + $this->_applyFilters(); + $this->_calculateTotals(); + $this->_validateTable(); + + return $this->_buildTable(); + } + + /** + * Calculates totals for columns. + * + * @return void + */ + function _calculateTotals() + { + if (empty($this->_calculateTotals)) { + return; + } + + $this->addSeparator(); + + $totals = array(); + foreach ($this->_data as $row) { + if (is_array($row)) { + foreach ($this->_calculateTotals as $columnID) { + $totals[$columnID] += $row[$columnID]; + } + } + } + + $this->_data[] = $totals; + $this->_updateRowsCols(); + } + + /** + * Applies any column filters to the data. + * + * @return void + */ + function _applyFilters() + { + if (empty($this->_filters)) { + return; + } + + foreach ($this->_filters as $filter) { + $column = $filter[0]; + $callback = $filter[1]; + + foreach ($this->_data as $row_id => $row_data) { + if ($row_data !== CONSOLE_TABLE_HORIZONTAL_RULE) { + $this->_data[$row_id][$column] = + call_user_func($callback, $row_data[$column]); + } + } + } + } + + /** + * Ensures that column and row counts are correct. + * + * @return void + */ + function _validateTable() + { + if (!empty($this->_headers)) { + $this->_calculateRowHeight(-1, $this->_headers[0]); + } + + for ($i = 0; $i < $this->_max_rows; $i++) { + for ($j = 0; $j < $this->_max_cols; $j++) { + if (!isset($this->_data[$i][$j]) && + (!isset($this->_data[$i]) || + $this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE)) { + $this->_data[$i][$j] = ''; + } + + } + $this->_calculateRowHeight($i, $this->_data[$i]); + + if ($this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE) { + ksort($this->_data[$i]); + } + + } + + $this->_splitMultilineRows(); + + // Update cell lengths. + for ($i = 0; $i < count($this->_headers); $i++) { + $this->_calculateCellLengths($this->_headers[$i]); + } + for ($i = 0; $i < $this->_max_rows; $i++) { + $this->_calculateCellLengths($this->_data[$i]); + } + + ksort($this->_data); + } + + /** + * Splits multiline rows into many smaller one-line rows. + * + * @return void + */ + function _splitMultilineRows() + { + ksort($this->_data); + $sections = array(&$this->_headers, &$this->_data); + $max_rows = array(count($this->_headers), $this->_max_rows); + $row_height_offset = array(-1, 0); + + for ($s = 0; $s <= 1; $s++) { + $inserted = 0; + $new_data = $sections[$s]; + + for ($i = 0; $i < $max_rows[$s]; $i++) { + // Process only rows that have many lines. + $height = $this->_row_heights[$i + $row_height_offset[$s]]; + if ($height > 1) { + // Split column data into one-liners. + $split = array(); + for ($j = 0; $j < $this->_max_cols; $j++) { + $split[$j] = preg_split('/\r?\n|\r/', + $sections[$s][$i][$j]); + } + + $new_rows = array(); + // Construct new 'virtual' rows - insert empty strings for + // columns that have less lines that the highest one. + for ($i2 = 0; $i2 < $height; $i2++) { + for ($j = 0; $j < $this->_max_cols; $j++) { + $new_rows[$i2][$j] = !isset($split[$j][$i2]) + ? '' + : $split[$j][$i2]; + } + } + + // Replace current row with smaller rows. $inserted is + // used to take account of bigger array because of already + // inserted rows. + array_splice($new_data, $i + $inserted, 1, $new_rows); + $inserted += count($new_rows) - 1; + } + } + + // Has the data been modified? + if ($inserted > 0) { + $sections[$s] = $new_data; + $this->_updateRowsCols(); + } + } + } + + /** + * Builds the table. + * + * @return string The generated table string. + */ + function _buildTable() + { + if (!count($this->_data)) { + return ''; + } + + $rule = $this->_border == CONSOLE_TABLE_BORDER_ASCII + ? '|' + : $this->_border; + $separator = $this->_getSeparator(); + + $return = array(); + for ($i = 0; $i < count($this->_data); $i++) { + for ($j = 0; $j < count($this->_data[$i]); $j++) { + if ($this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE && + $this->_strlen($this->_data[$i][$j]) < + $this->_cell_lengths[$j]) { + $this->_data[$i][$j] = $this->_strpad($this->_data[$i][$j], + $this->_cell_lengths[$j], + ' ', + $this->_col_align[$j]); + } + } + + if ($this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE) { + $row_begin = $rule . str_repeat(' ', $this->_padding); + $row_end = str_repeat(' ', $this->_padding) . $rule; + $implode_char = str_repeat(' ', $this->_padding) . $rule + . str_repeat(' ', $this->_padding); + $return[] = $row_begin + . implode($implode_char, $this->_data[$i]) . $row_end; + } elseif (!empty($separator)) { + $return[] = $separator; + } + + } + + $return = implode("\r\n", $return); + if (!empty($separator)) { + $return = $separator . "\r\n" . $return . "\r\n" . $separator; + } + $return .= "\r\n"; + + if (!empty($this->_headers)) { + $return = $this->_getHeaderLine() . "\r\n" . $return; + } + + return $return; + } + + /** + * Creates a horizontal separator for header separation and table + * start/end etc. + * + * @return string The horizontal separator. + */ + function _getSeparator() + { + if (!$this->_border) { + return; + } + + if ($this->_border == CONSOLE_TABLE_BORDER_ASCII) { + $rule = '-'; + $sect = '+'; + } else { + $rule = $sect = $this->_border; + } + + $return = array(); + foreach ($this->_cell_lengths as $cl) { + $return[] = str_repeat($rule, $cl); + } + + $row_begin = $sect . str_repeat($rule, $this->_padding); + $row_end = str_repeat($rule, $this->_padding) . $sect; + $implode_char = str_repeat($rule, $this->_padding) . $sect + . str_repeat($rule, $this->_padding); + + return $row_begin . implode($implode_char, $return) . $row_end; + } + + /** + * Returns the header line for the table. + * + * @return string The header line of the table. + */ + function _getHeaderLine() + { + // Make sure column count is correct + for ($j = 0; $j < count($this->_headers); $j++) { + for ($i = 0; $i < $this->_max_cols; $i++) { + if (!isset($this->_headers[$j][$i])) { + $this->_headers[$j][$i] = ''; + } + } + } + + for ($j = 0; $j < count($this->_headers); $j++) { + for ($i = 0; $i < count($this->_headers[$j]); $i++) { + if ($this->_strlen($this->_headers[$j][$i]) < + $this->_cell_lengths[$i]) { + $this->_headers[$j][$i] = + $this->_strpad($this->_headers[$j][$i], + $this->_cell_lengths[$i], + ' ', + $this->_col_align[$i]); + } + } + } + + $rule = $this->_border == CONSOLE_TABLE_BORDER_ASCII + ? '|' + : $this->_border; + $row_begin = $rule . str_repeat(' ', $this->_padding); + $row_end = str_repeat(' ', $this->_padding) . $rule; + $implode_char = str_repeat(' ', $this->_padding) . $rule + . str_repeat(' ', $this->_padding); + + $separator = $this->_getSeparator(); + if (!empty($separator)) { + $return[] = $separator; + } + for ($j = 0; $j < count($this->_headers); $j++) { + $return[] = $row_begin + . implode($implode_char, $this->_headers[$j]) . $row_end; + } + + return implode("\r\n", $return); + } + + /** + * Updates values for maximum columns and rows. + * + * @param array $rowdata Data array of a single row. + * + * @return void + */ + function _updateRowsCols($rowdata = array()) + { + // Update maximum columns. + $this->_max_cols = max($this->_max_cols, count($rowdata)); + + // Update maximum rows. + ksort($this->_data); + $keys = array_keys($this->_data); + $this->_max_rows = end($keys) + 1; + + switch ($this->_defaultAlign) { + case CONSOLE_TABLE_ALIGN_CENTER: + $pad = STR_PAD_BOTH; + break; + case CONSOLE_TABLE_ALIGN_RIGHT: + $pad = STR_PAD_LEFT; + break; + default: + $pad = STR_PAD_RIGHT; + break; + } + + // Set default column alignments + for ($i = count($this->_col_align); $i < $this->_max_cols; $i++) { + $this->_col_align[$i] = $pad; + } + } + + /** + * Calculates the maximum length for each column of a row. + * + * @param array $row The row data. + * + * @return void + */ + function _calculateCellLengths($row) + { + for ($i = 0; $i < count($row); $i++) { + if (!isset($this->_cell_lengths[$i])) { + $this->_cell_lengths[$i] = 0; + } + $this->_cell_lengths[$i] = max($this->_cell_lengths[$i], + $this->_strlen($row[$i])); + } + } + + /** + * Calculates the maximum height for all columns of a row. + * + * @param integer $row_number The row number. + * @param array $row The row data. + * + * @return void + */ + function _calculateRowHeight($row_number, $row) + { + if (!isset($this->_row_heights[$row_number])) { + $this->_row_heights[$row_number] = 1; + } + + // Do not process horizontal rule rows. + if ($row === CONSOLE_TABLE_HORIZONTAL_RULE) { + return; + } + + for ($i = 0, $c = count($row); $i < $c; ++$i) { + $lines = preg_split('/\r?\n|\r/', $row[$i]); + $this->_row_heights[$row_number] = max($this->_row_heights[$row_number], + count($lines)); + } + } + + /** + * Returns the character length of a string. + * + * @param string $str A multibyte or singlebyte string. + * + * @return integer The string length. + */ + function _strlen($str) + { + static $mbstring, $utf8; + + // Strip ANSI color codes if requested. + if ($this->_ansiColor) { + $str = Console_Color::strip($str); + } + + // Cache expensive function_exists() calls. + if (!isset($mbstring)) { + $mbstring = function_exists('mb_strlen'); + } + if (!isset($utf8)) { + $utf8 = function_exists('utf8_decode'); + } + + if ($utf8 && + ($this->_charset == strtolower('utf-8') || + $this->_charset == strtolower('utf8'))) { + return strlen(utf8_decode($str)); + } + if ($mbstring) { + return mb_strlen($str, $this->_charset); + } + + return strlen($str); + } + + /** + * Returns part of a string. + * + * @param string $string The string to be converted. + * @param integer $start The part's start position, zero based. + * @param integer $length The part's length. + * + * @return string The string's part. + */ + function _substr($string, $start, $length = null) + { + static $mbstring; + + // Cache expensive function_exists() calls. + if (!isset($mbstring)) { + $mbstring = function_exists('mb_substr'); + } + + if (is_null($length)) { + $length = $this->_strlen($string); + } + if ($mbstring) { + $ret = @mb_substr($string, $start, $length, $this->_charset); + if (!empty($ret)) { + return $ret; + } + } + return substr($string, $start, $length); + } + + /** + * Returns a string padded to a certain length with another string. + * + * This method behaves exactly like str_pad but is multibyte safe. + * + * @param string $input The string to be padded. + * @param integer $length The length of the resulting string. + * @param string $pad The string to pad the input string with. Must + * be in the same charset like the input string. + * @param const $type The padding type. One of STR_PAD_LEFT, + * STR_PAD_RIGHT, or STR_PAD_BOTH. + * + * @return string The padded string. + */ + function _strpad($input, $length, $pad = ' ', $type = STR_PAD_RIGHT) + { + $mb_length = $this->_strlen($input); + $sb_length = strlen($input); + $pad_length = $this->_strlen($pad); + + /* Return if we already have the length. */ + if ($mb_length >= $length) { + return $input; + } + + /* Shortcut for single byte strings. */ + if ($mb_length == $sb_length && $pad_length == strlen($pad)) { + return str_pad($input, $length, $pad, $type); + } + + switch ($type) { + case STR_PAD_LEFT: + $left = $length - $mb_length; + $output = $this->_substr(str_repeat($pad, ceil($left / $pad_length)), + 0, $left, $this->_charset) . $input; + break; + case STR_PAD_BOTH: + $left = floor(($length - $mb_length) / 2); + $right = ceil(($length - $mb_length) / 2); + $output = $this->_substr(str_repeat($pad, ceil($left / $pad_length)), + 0, $left, $this->_charset) . + $input . + $this->_substr(str_repeat($pad, ceil($right / $pad_length)), + 0, $right, $this->_charset); + break; + case STR_PAD_RIGHT: + $right = $length - $mb_length; + $output = $input . + $this->_substr(str_repeat($pad, ceil($right / $pad_length)), + 0, $right, $this->_charset); + break; + } + + return $output; + } + +} diff --git a/lib/predict/tests/test-001.php b/lib/predict/tests/test-001.php new file mode 100644 index 0000000..f9ab5e5 --- /dev/null +++ b/lib/predict/tests/test-001.php @@ -0,0 +1,133 @@ + 0.0, + 'x' => 2328.97048951, + 'y' => -5995.22076416, + 'z' => 1719.97067261, + 'vx' => 2.91207230, + 'vy' => -0.98341546, + 'vz' => -7.09081703 + ), + array( + 'step' => 360.0, + 'x' => 2456.10705566, + 'y' => -6071.93853760, + 'z' => 1222.89727783, + 'vx' => 2.67938992, + 'vy' => -0.44829041, + 'vz' => -7.22879231 + ), + array( + 'step' => 720.0, + 'x' => 2567.56195068, + 'y' => -6112.50384522, + 'z' => 713.96397400, + 'vx' => 2.44024599, + 'vy' => 0.09810869, + 'vz' => -7.31995916 + ), + array( + 'step' => 1080.0, + 'x' => 2663.09078980, + 'y' => -6115.48229980, + 'z' => 196.39640427, + 'vx' => 2.19611958, + 'vy' => 0.65241995, + 'vz' => -7.36282432 + ), + array( + 'step' => 1440.0, + 'x' => 2742.55133057, + 'y' => -6079.67144775, + 'z' => -326.38095856, + 'vx' => 1.94850229, + 'vy' => 1.21106251, + 'vz' => -7.35619372 + ) +); + +$headers = array( + 'step time', + 'label', + 'result', + 'expected', +); + +$data = array(); + + +$file = file('tests/test-001.tle'); +$tle = new Predict_TLE($file[0], $file[1], $file[2]); +$sat = new Predict_Sat($tle); +$sgpsdp = new Predict_SGPSDP(); + +$count = 0; +foreach ($expected as $e) { + $sgpsdp->SGP4($sat, $e['step']); + Predict_Math::Convert_Sat_State($sat->pos, $sat->vel); + + $count++; + $data[$count] = array(); + $data[$count][0] = $e['step']; + $data[$count][1] = 'X'; + $data[$count][2] = $sat->pos->x; + $data[$count][3] = $e['x']; + + $count++; + $data[$count] = array(); + $data[$count][0] = ''; + $data[$count][1] = 'Y'; + $data[$count][2] = $sat->pos->y; + $data[$count][3] = $e['y']; + + $count++; + $data[$count] = array(); + $data[$count][0] = ''; + $data[$count][1] = 'Z'; + $data[$count][2] = $sat->pos->z; + $data[$count][3] = $e['z']; + + $count++; + $data[$count] = array(); + $data[$count][0] = ''; + $data[$count][1] = 'VX'; + $data[$count][2] = $sat->vel->x; + $data[$count][3] = $e['vx']; + + $count++; + $data[$count] = array(); + $data[$count][0] = ''; + $data[$count][1] = 'VY'; + $data[$count][2] = $sat->vel->y; + $data[$count][3] = $e['vy']; + + $count++; + $data[$count] = array(); + $data[$count][0] = ''; + $data[$count][1] = 'VZ'; + $data[$count][2] = $sat->vel->z; + $data[$count][3] = $e['vz']; +} +// exit; + +$tbl = new Console_Table(); +$tbl->setHeaders($headers); +$tbl->addData($data); + +echo "DEEP_SPACE_EPHEM: " . ($sat->flags & Predict_SGPSDP::DEEP_SPACE_EPHEM_FLAG) . " (expected: 0)\n\n"; + +echo $tbl->getTable(); + +echo "Execution time: " . number_format((microtime(true) - $start) * 1000, 2) . "ms\n"; diff --git a/lib/predict/tests/test-001.tle b/lib/predict/tests/test-001.tle new file mode 100644 index 0000000..2d8ac4e --- /dev/null +++ b/lib/predict/tests/test-001.tle @@ -0,0 +1,3 @@ +TEST SAT SGP 001 +1 88888U 80275.98708465 .00073094 13844-3 66816-4 0 9 +2 88888 72.8435 115.9689 0086731 52.6988 110.5714 16.05824518 103 diff --git a/lib/predict/tests/test-002.php b/lib/predict/tests/test-002.php new file mode 100644 index 0000000..e491aa2 --- /dev/null +++ b/lib/predict/tests/test-002.php @@ -0,0 +1,135 @@ + 0.0, + 'x' => 7473.37066650, + 'y' => 428.95261765, + 'z' => 5828.74786377, + 'vx' => 5.1071513, + 'vy' => 6.44468284, + 'vz' => -0.18613096 + ), + array( + 'step' => 360.0, + 'x' => -3305.22537232, + 'y' => 32410.86328125, + 'z' => -24697.17675781, + 'vx' => -1.30113538, + 'vy' => -1.15131518, + 'vz' => -0.28333528 + ), + array( + 'step' => 720.0, + 'x' => 14271.28759766, + 'y' => 24110.46411133, + 'z' => -4725.76837158, + 'vx' => -0.32050445, + 'vy' => 2.67984074, + 'vz' => -2.08405289 + ), + array( + 'step' => 1080.0, + 'x' => -9990.05883789, + 'y' => 22717.35522461, + 'z' => -23616.890662501, + 'vx' => -1.01667246, + 'vy' => -2.29026759, + 'vz' => 0.72892364 + ), + array( + 'step' => 1440.0, + 'x' => 9787.86975097, + 'y' => 33753.34667969, + 'z' => -15030.81176758, + 'vx' => -1.09425966, + 'vy' => 0.92358845, + 'vz' => -1.52230928 + ) +); + +$headers = array( + 'step time', + 'label', + 'result', + 'expected', +); + +$data = array(); + + +$file = file('tests/test-002.tle'); +$tle = new Predict_TLE($file[0], $file[1], $file[2]); +$sat = new Predict_Sat($tle); +$sgpsdp = new Predict_SGPSDP(); + +$count = 0; +foreach ($expected as $e) { + $sgpsdp->SGP4($sat, $e['step']); + Predict_Math::Convert_Sat_State($sat->pos, $sat->vel); + + $count++; + $data[$count] = array(); + $data[$count][0] = $e['step']; + $data[$count][1] = 'X'; + $data[$count][2] = $sat->pos->x; + $data[$count][3] = $e['x']; + + $count++; + $data[$count] = array(); + $data[$count][0] = ''; + $data[$count][1] = 'Y'; + $data[$count][2] = $sat->pos->y; + $data[$count][3] = $e['y']; + + $count++; + $data[$count] = array(); + $data[$count][0] = ''; + $data[$count][1] = 'Z'; + $data[$count][2] = $sat->pos->z; + $data[$count][3] = $e['z']; + + $count++; + $data[$count] = array(); + $data[$count][0] = ''; + $data[$count][1] = 'VX'; + $data[$count][2] = $sat->vel->x; + $data[$count][3] = $e['vx']; + + $count++; + $data[$count] = array(); + $data[$count][0] = ''; + $data[$count][1] = 'VY'; + $data[$count][2] = $sat->vel->y; + $data[$count][3] = $e['vy']; + + $count++; + $data[$count] = array(); + $data[$count][0] = ''; + $data[$count][1] = 'VZ'; + $data[$count][2] = $sat->vel->z; + $data[$count][3] = $e['vz']; +} +// exit; + +$tbl = new Console_Table(); +$tbl->setHeaders($headers); +$tbl->addData($data); + + +echo "DEEP_SPACE_EPHEM: " . ($sat->flags & Predict_SGPSDP::DEEP_SPACE_EPHEM_FLAG) . " (expected: 64)\n\n"; + +echo $tbl->getTable(); + +echo "Execution time: " . number_format((microtime(true) - $start) * 1000, 2) . "ms\n"; diff --git a/lib/predict/tests/test-002.tle b/lib/predict/tests/test-002.tle new file mode 100644 index 0000000..e7faff7 --- /dev/null +++ b/lib/predict/tests/test-002.tle @@ -0,0 +1,4 @@ +TEST SAT SDP 001 +1 11801U 80230.29629788 .01431103 00000-0 14311-1 0 2 +2 11801 46.7916 230.4354 7318036 47.4722 10.4117 2.28537848 2 + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 5b7c820..47cc715 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,6 +1,6 @@ - + - + @@ -21,11 +21,18 @@ - - - src - - + + + ./src + + + + src/Migrations + src/Command + src/DataFixtures + src/Kernel.php + + diff --git a/public/.htaccess b/public/.htaccess index 37fbfb3..f98dab9 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -17,6 +17,37 @@ Options -MultiViews + + # Compress HTML, CSS, JavaScript, Text, XML and fonts + AddOutputFilterByType DEFLATE application/javascript + AddOutputFilterByType DEFLATE application/rss+xml + AddOutputFilterByType DEFLATE application/vnd.ms-fontobject + AddOutputFilterByType DEFLATE application/x-font + AddOutputFilterByType DEFLATE application/x-font-opentype + AddOutputFilterByType DEFLATE application/x-font-otf + AddOutputFilterByType DEFLATE application/x-font-truetype + AddOutputFilterByType DEFLATE application/x-font-ttf + AddOutputFilterByType DEFLATE application/x-javascript + AddOutputFilterByType DEFLATE application/xhtml+xml + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE font/opentype + AddOutputFilterByType DEFLATE font/otf + AddOutputFilterByType DEFLATE font/ttf + AddOutputFilterByType DEFLATE image/svg+xml + AddOutputFilterByType DEFLATE image/x-icon + AddOutputFilterByType DEFLATE text/css + AddOutputFilterByType DEFLATE text/html + AddOutputFilterByType DEFLATE text/javascript + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/xml + + # Remove browser bugs (only needed for really old browsers) + BrowserMatch ^Mozilla/4 gzip-only-text/html + BrowserMatch ^Mozilla/4\.0[678] no-gzip + BrowserMatch \bMSIE !no-gzip !gzip-only-text/html + Header append Vary User-Agent + + RewriteEngine On @@ -34,6 +65,9 @@ RewriteCond %{HTTP:Authorization} .+ RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] + RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] + RewriteRule ^ https://%1%{REQUEST_URI} [R=302,L] + # Redirect to URI without front controller to prevent duplicate content # (with and without `/index.php`). Only do this redirect on the initial # rewrite by Apache and not on subsequent cycles. Otherwise we would get an @@ -55,6 +89,8 @@ RewriteRule ^ %{ENV:BASE}/index.php [L] +Header add Access-Control-Allow-Origin "*" + # When mod_rewrite is not available, we instruct a temporary redirect of diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..33601c5 Binary files /dev/null and b/public/favicon.ico differ diff --git a/tests/.gitignore b/public/index.html similarity index 100% rename from tests/.gitignore rename to public/index.html diff --git a/public/index.php b/public/index.php index f094a9b..9ca9419 100644 --- a/public/index.php +++ b/public/index.php @@ -4,7 +4,7 @@ use Symfony\Component\ErrorHandler\Debug; use Symfony\Component\HttpFoundation\Request; -require dirname(__DIR__).'/config/bootstrap.php'; +require dirname(__DIR__).'/etc/bootstrap.php'; if ($_SERVER['APP_DEBUG']) { umask(0000); @@ -13,7 +13,7 @@ } if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? $_ENV['TRUSTED_PROXIES'] ?? false) { - Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST); + Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_FOR ^ Request::HEADER_X_FORWARDED_HOST); } if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? $_ENV['TRUSTED_HOSTS'] ?? false) { diff --git a/src/Command/CleanupCommand.php b/src/Command/CleanupCommand.php new file mode 100644 index 0000000..4e6c05c --- /dev/null +++ b/src/Command/CleanupCommand.php @@ -0,0 +1,33 @@ +setName('cleanup') + ->setDescription('Performs periodic cleanup on unused data'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $this->repository->removeBefore( + (new \DateTime())->sub(new \DateInterval('P2M')) + ); + + return Command::SUCCESS; + } +} diff --git a/src/Command/DoctrineReloadCommand.php b/src/Command/DoctrineReloadCommand.php index 784de82..3529bfe 100644 --- a/src/Command/DoctrineReloadCommand.php +++ b/src/Command/DoctrineReloadCommand.php @@ -11,8 +11,6 @@ final class DoctrineReloadCommand extends Command { - protected static $defaultName = 'doctrine:reload'; - private static array $choices = [ 'y' => 'Yes', 'n' => 'No', @@ -31,11 +29,18 @@ public function __construct($env) $this->env = $env; } + /** @noinspection PhpMissingParentCallCommonInspection */ protected function configure(): void { - $this->setDescription('Purge database, execute migrations and load fixtures'); + $this + ->setName('doctrine:reload') + ->setDescription('Purge database, execute migrations and load fixtures'); } + /** + * @noinspection PhpMissingParentCallCommonInspection + * @throws \Exception + */ protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); @@ -43,15 +48,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int $question = new ChoiceQuestion('All data will be lost. Do you wish to continue?', self::$choices, false); if (!\in_array($this->env, self::$envs, true)) { - $io->warning('This is intended only for use in dev environment.'); + $io->warning('This is intended only for use in dev or test environment.'); - return 1; + return Command::FAILURE; } $application = $this->getApplication(); if ($application === null) { - return 1; + throw new \RuntimeException('Application instance not found.'); } if ($input->getOption('no-interaction') || $helper->ask($input, $output, $question) === 'y') { @@ -74,6 +79,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $application->run(new ArrayInput($options)); } - return 0; + return Command::SUCCESS; } } diff --git a/src/Command/ImportTleCommand.php b/src/Command/ImportTleCommand.php index 4d099ff..e2692a3 100644 --- a/src/Command/ImportTleCommand.php +++ b/src/Command/ImportTleCommand.php @@ -4,14 +4,16 @@ use App\Entity\Tle; use App\Repository\TleRepository; -use App\Service\TleFile; use App\Service\Traits\FileSystemAwareTrait; -use App\ViewModel\Model\TleModel; use Doctrine\ORM\EntityManagerInterface; +use GuzzleHttp\Client; +use Ivanstan\Tle\Model\Tle as TleModel; +use Ivanstan\Tle\Model\TleFile; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Yaml\Yaml; @@ -20,11 +22,12 @@ final class ImportTleCommand extends Command use FileSystemAwareTrait; private const BATCH_SIZE = 50; - private const SOURCE = '/config/custom/source.yaml'; + private const OPTION_NO_PROGRESS = 'no-progress'; + + public const SOURCE = '/etc/custom/source.yaml'; private EntityManagerInterface $em; private TleRepository $repository; - private OutputInterface $output; private array $satellites = []; @@ -38,13 +41,15 @@ public function __construct(EntityManagerInterface $em, TleRepository $repositor /** @noinspection PhpMissingParentCallCommonInspection */ protected function configure(): void { - $this->setName('import:tle'); + $this->setName('import:tle') + ->addOption(self::OPTION_NO_PROGRESS, null, InputOption::VALUE_OPTIONAL, 'Hide progress bar', false); } /** @noinspection PhpMissingParentCallCommonInspection */ protected function execute(InputInterface $input, OutputInterface $output): int { - $this->output = $output; + $showProgress = $input->getOption(self::OPTION_NO_PROGRESS) === false; + $this->satellites = $this->repository->fetchAllIndexed(); $totalInsert = 0; @@ -52,20 +57,35 @@ protected function execute(InputInterface $input, OutputInterface $output): int $sources = Yaml::parseFile($this->getProjectDir() . self::SOURCE); - $progressBar = new ProgressBar($output, \count($sources)); - $progressBar->start(); + if ($showProgress) { + $progressBar = new ProgressBar($output, \count($sources)); + $progressBar->start(); + } foreach ($sources as $uri) { /** @noinspection DisconnectedForeachInstructionInspection */ - $progressBar->advance(); + if (isset($progressBar)) { + $progressBar->advance(); + } - $content = file_get_contents($uri); + try { + $response = (new Client())->request('GET', $uri); + } catch (\Exception $exception) { + $output->writeln( + \sprintf( + 'Unable to fetch resource "%s" with exception message "%s"', + $uri, + $exception->getMessage() + ) + ); + continue; + } - if (!$content) { + if (!$response->getBody()) { continue; } - $file = new TleFile($content); + $file = new TleFile($response->getBody()); $insert = []; $update = []; @@ -86,7 +106,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int } - $progressBar->finish(); + if (isset($progressBar)) { + $progressBar->finish(); + } $output->writeln(''); $output->writeln(''); @@ -110,7 +132,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int ); $table->render(); - return 0; + return Command::SUCCESS; } protected function toPersistent(TleModel $model): Tle @@ -127,11 +149,20 @@ protected function toPersistent(TleModel $model): Tle protected function flush(array $queue, $persistNew = null): void { $counter = 0; + /** @var TleModel $model */ foreach ($queue as $model) { - $tle = $this->toPersistent($model); - $this->satellites[$model->getId()] = $tle; + if (!$persistNew) { + /** @var Tle $existing */ + $existing = $this->satellites[$model->getId()]; + $existing->setName($model->getName()); + $existing->setId($model->getId()); + $existing->setLine1($model->getLine1()); + $existing->setLine2($model->getLine2()); + } if ($persistNew) { + $tle = $this->toPersistent($model); + $this->satellites[$model->getId()] = $tle; $this->em->persist($tle); } diff --git a/src/Command/TleCalculate.php b/src/Command/TleCalculate.php new file mode 100644 index 0000000..784f15b --- /dev/null +++ b/src/Command/TleCalculate.php @@ -0,0 +1,82 @@ +setDescription('Calculate and persist data in TleInformation entity'); + $this->addOption(self::OPTION_TLE, 't', InputOption::VALUE_REQUIRED, 'Calculate only for specified record'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $builder = $this->entityManager + ->createQueryBuilder() + ->select('tle') + ->from(Tle::class, 'tle'); + + $tle = $input->getOption(self::OPTION_TLE); + + if ($tle !== null) { + $builder->andWhere('tle.id = :tle'); + $builder->setParameter('tle', $tle); + } + + $repository = $this->entityManager->getRepository(TleInformation::class); + + /** @var Tle $tle */ + foreach ($builder->getQuery()->toIterable() as $i => $tle) { + $exists = true; + + $tleInformation = $repository->find($tle->getId()); + + if ($tleInformation === null) { + $exists = false; + $tleInformation = new TleInformation($tle); + } + + $tleModel = new \Ivanstan\Tle\Model\Tle($tle->getLine1(), $tle->getLine2(), $tle->getName()); + + $tleInformation->inclination = $tleModel->getInclination(); + $tleInformation->eccentricity = $tleModel->eccentricity(); + $tleInformation->period = $tleModel->period(); + $tleInformation->geostationary = (new GeostationaryOrbitTleSpecification())->isSatisfiedBy($tleModel); + $tleInformation->raan = $tleModel->raan(); + $tleInformation->semiMajorAxis = $tleModel->semiMajorAxis(); + + if (!$exists) { + $this->entityManager->persist($tleInformation); + } + + if (($i % self::BATCH_SIZE) === 0) { + $this->entityManager->flush(); + $this->entityManager->clear(); + } + } + + $this->entityManager->flush(); + + return Command::SUCCESS; + } +} diff --git a/src/Command/UpdateImportSources.php b/src/Command/UpdateImportSources.php new file mode 100644 index 0000000..6206d61 --- /dev/null +++ b/src/Command/UpdateImportSources.php @@ -0,0 +1,144 @@ +setName('tle:source'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $this->io = new SymfonyStyle($input, $output); + + $sourceFile = $this->getProjectDir() . ImportTleCommand::SOURCE; + + $this->sources = Yaml::parseFile($sourceFile); + + $newSources = $this->getSources(); + + $diff = array_diff($newSources, $this->sources); + + if (empty($diff)) { + $this->io->success('No new tle sources found'); + + return Command::SUCCESS; + } + + $this->io->writeln(""); + $this->io->writeln(\sprintf("Following new tle sources found and written to %s", $sourceFile)); + $this->io->writeln(""); + foreach ($diff as $url) { + $this->io->writeln($url); + } + + $this->io->writeln(""); + + $sources = array_merge($this->sources, $diff); + sort($sources); + + $yaml = Yaml::dump($sources); + + file_put_contents($sourceFile, $yaml); + + return Command::SUCCESS; + } + + protected function getSources(): array + { + $result = []; + + foreach (self::CATALOG as $catalog) { + $response = (new Client())->request('GET', $catalog); + + $crawler = new Crawler($response->getBody()->getContents()); + + /** @var DOMElement $anchor */ + foreach ($crawler->filter('a') as $anchor) { + $href = $anchor->getAttribute('href'); + $path = parse_url($href, PHP_URL_PATH); + $extension = pathinfo($path, PATHINFO_EXTENSION); + + if ($extension === 'txt') { + if (parse_url($href, PHP_URL_HOST) === null) { + /** @noinspection PhpArrayKeyDoesNotMatchArrayShapeInspection */ + if ($path[0] === '/') { + $scheme = parse_url($catalog, PHP_URL_SCHEME); + $host = parse_url($catalog, PHP_URL_HOST); + $href = $scheme . '://' . $host . $href; + } else { + $href = $catalog . trim($href, '/'); + } + } + + if (!$this->isIgnored($href)) { + $this->io->writeln(\sprintf('Verifying url: %s', $href)); + if ($this->isHealthy($href)) { + $result[] = $href; + } + } + } + } + } + + return $result; + } + + protected function isIgnored(string $url): bool + { + return in_array($url, self::IGNORED, false) || in_array($this->sources, self::IGNORED, false); + } + + protected function isHealthy(string $url): bool + { + try { + $response = (new Client())->request('GET', $url); + + return $response->getStatusCode() === 200; + } catch (\Exception) { + return false; + } + } +} diff --git a/src/Controller/Api/AbstractApiController.php b/src/Controller/AbstractApiController.php similarity index 58% rename from src/Controller/Api/AbstractApiController.php rename to src/Controller/AbstractApiController.php index 90e4743..eba101f 100644 --- a/src/Controller/Api/AbstractApiController.php +++ b/src/Controller/AbstractApiController.php @@ -1,42 +1,31 @@ serializer = $serializer; - } - /** * @required * @@ -47,46 +36,9 @@ public function setRouter(RouterInterface $router): void $this->router = $router; } - public function getSort(Request $request, string $default, array $available): string - { - if ($request->get(self::SORT_PARAM) && \in_array($request->get(self::SORT_PARAM), $available, true)) { - $default = strtolower($request->get('sort')); - } - - return $default; - } - - public function getSortDirection(Request $request, string $default): string - { - if ($request->get(self::SORT_DIR_PARAM) && \in_array( - $request->get(self::SORT_DIR_PARAM), - self::$sortDirection, - true - )) { - $default = strtolower($request->get(self::SORT_DIR_PARAM)); - } - - return $default; - } - - public function getPageSize(Request $request, int $default = self::PAGE_SIZE): int - { - if ($request->get(self::PAGE_SIZE_PARAM) && \is_numeric($request->get(self::PAGE_SIZE_PARAM))) { - $default = $request->get(self::PAGE_SIZE_PARAM); - } - - return $default; - } - public function getPage(Request $request): int { - $page = $request->get(self::PAGE_PARAM, 1); - - if ($page < 1) { - throw new \LogicException('Page parameter must be greater than zero.'); - } - - return $page; + return (int)$request->get(self::PAGE_PARAM, 1); } public function getPageOffset(int $page, int $pageSize): int @@ -156,15 +108,18 @@ public function getPagination(Request $request, int $total, int $pageSize): arra return $result; } - public function response($response): Response + public function response(array $data): JsonResponse { - return new Response( - $this->serializer->serialize($response, 'json'), + return new JsonResponse( + $data, Response::HTTP_OK, - [ - 'Content-type' => 'application/json', - 'Access-Control-Allow-Origin' => '*', - ] ); } + + protected function getDate(Request $request, string $name): \DateTime + { + $date = $request->get($name, DateTimeService::getCurrentUTC()->format(\DateTimeInterface::ATOM)); + + return \DateTime::createFromFormat(\DateTimeInterface::ATOM, str_replace(' ', '+', $date)); + } } diff --git a/src/Controller/Api/TleController.php b/src/Controller/Api/TleController.php deleted file mode 100644 index 516f8ad..0000000 --- a/src/Controller/Api/TleController.php +++ /dev/null @@ -1,73 +0,0 @@ -findOneBy(['id' => $id]); - - if ($tle === null) { - throw new NotFoundHttpException(\sprintf('Unable to find record with id %s', $id)); - } - - return $this->response($tle); - } - - /** - * @Route(name="tle_collection") - */ - public function collection(Request $request, TleRepository $repository): Response - { - $search = $request->get(self::SEARCH_PARAM); - $sort = $this->getSort($request, TleRepository::SORT_NAME, TleRepository::$sort); - $sortDir = $this->getSortDirection($request, self::SORT_ASC); - $pageSize = min($this->getPageSize($request, self::PAGE_SIZE), self::MAX_PAGE_SIZE); - - $collection = $repository->collection( - $search, - $sort, - $sortDir, - $pageSize, - $this->getPageOffset($this->getPage($request), $pageSize) - ); - - return $this->response( - [ - '@context' => 'http://www.w3.org/ns/hydra/context.jsonld', - '@id' => $this->router->generate('tle_collection', [], UrlGeneratorInterface::ABSOLUTE_URL), - '@type' => 'Collection', - 'totalItems' => $collection->getTotal(), - 'member' => $collection->getCollection(), - 'parameters' => [ - self::SEARCH_PARAM => $search ?? '*', - self::SORT_PARAM => $sort, - self::SORT_DIR_PARAM => $sortDir, - self::PAGE_PARAM => $this->getPage($request), - self::PAGE_SIZE_PARAM => $pageSize, - ], - 'view' => $this->getPagination($request, $collection->getTotal(), $pageSize), - ] - ); - } -} diff --git a/src/Controller/ApiController.php b/src/Controller/ApiController.php deleted file mode 100644 index af187a7..0000000 --- a/src/Controller/ApiController.php +++ /dev/null @@ -1,26 +0,0 @@ -getProjectDir() . '/config/custom/' . $name . '.json'; - - $file = json_decode(file_get_contents($path), true, 512, JSON_THROW_ON_ERROR); - - return new JsonResponse($file, Response::HTTP_OK, ['Access-Control-Allow-Origin' => '*',]); - } -} diff --git a/src/Controller/DocsController.php b/src/Controller/DocsController.php new file mode 100644 index 0000000..343af1f --- /dev/null +++ b/src/Controller/DocsController.php @@ -0,0 +1,36 @@ +getProjectDir() . '/public/index.html')); + } + + /** + * @throws \JsonException + */ + #[Route("/api/tle.json", name: "app_api_docs_json")] + public function getJson(): JsonResponse + { + $path = $this->getProjectDir() . '/etc/custom/tle.json'; + + $docs = json_decode(file_get_contents($path), true, 512, JSON_THROW_ON_ERROR); + + $docs['info']['version'] = $this->getParameter('version'); + + return new JsonResponse($docs, Response::HTTP_OK, ['Access-Control-Allow-Origin' => '*',]); + } +} diff --git a/src/Controller/FlyOverController.php b/src/Controller/FlyOverController.php new file mode 100644 index 0000000..af24873 --- /dev/null +++ b/src/Controller/FlyOverController.php @@ -0,0 +1,129 @@ + "\d+"])] + public function flyover( + int $id, + Request $request + ): JsonResponse { + $observer = $this->getObserver($request); + $onlyVisible = $request->get('only_visible', true); + $tle = $this->getTle($id); + + $this->service + ->setObserver($observer) + ->setTle($tle); + + if ($onlyVisible) { + $results = $this->service->getVisiblePasses(\Predict_Time::get_current_daynum()); + } else { + $results = $this->service->getPasses(\Predict_Time::get_current_daynum()); + } + + $parameters = [ + 'latitude' => $observer->latitude, + 'longitude' => $observer->longitude, + 'only_visible' => $onlyVisible, + ]; + + $url = $this->router->generate( + 'tle_flyover', + array_merge($request->request->all(), $parameters, ['id' => $id]), + UrlGeneratorInterface::ABSOLUTE_URL + ); + + $parameters['satelliteId'] = $id; + + $members = $this->normalizer->normalize($results, null, ['timezone' => $observer->getTimezone()]); + + foreach ($members as $index => &$member) { + $item = [ + '@id' => $this->generateUrl('tle_flyover_details', ['id' => $id, 'passId' => $index], UrlGeneratorInterface::ABSOLUTE_URL), + ]; + + $member = $item + $member; + } + + return $this->response( + [ + '@context' => self::HYDRA_CONTEXT, + '@id' => $url, + '@type' => 'SatelliteFlyOverCollection', + 'observer' => $this->normalizer->normalize($observer), + 'tle' => $this->normalizer->normalize($tle), + 'member' => $members, + 'parameters' => $parameters, + ] + ); + } + + #[Route("/api/tle/{id}/flyover/{passId}", name: "tle_flyover_details", requirements: ["id" => "\d+", "passId" => "\d+"])] + public function flyoverDetails( + int $id, + int $passId, + Request $request, + ): JsonResponse { + $observer = $this->getObserver($request); + $onlyVisible = $request->get('only_visible', true); + $tle = $this->getTle($id); + + $this->service + ->setObserver($observer) + ->setTle($tle); + + if ($onlyVisible) { + $results = $this->service->getVisiblePasses(\Predict_Time::get_current_daynum()); + } else { + $results = $this->service->getPasses(\Predict_Time::get_current_daynum()); + } + + $pass = $results[$passId] ?? null; + + if ($pass === null) { + throw new NotFoundHttpException('Unable to find requested flyover details'); + } + + $url = $this->router->generate( + 'tle_flyover_details', + array_merge($request->request->all(), ['id' => $id, 'passId' => $passId]), + UrlGeneratorInterface::ABSOLUTE_URL + ); + + $data = [ + '@context' => self::HYDRA_CONTEXT, + '@id' => $url, + 'observer' => $this->normalizer->normalize($observer), + 'tle' => $this->normalizer->normalize($tle), + ]; + + return $this->response( + array_merge( + $data, + $this->normalizer->normalize($pass, null, ['timezone' => $observer->getTimezone(), 'details' => true]) + ) + ); + } + +} diff --git a/src/Controller/PropagateController.php b/src/Controller/PropagateController.php new file mode 100644 index 0000000..d2befb8 --- /dev/null +++ b/src/Controller/PropagateController.php @@ -0,0 +1,101 @@ +propagator = new \Predict_SGPSDP(); + } + + #[Route("/api/tle/{id}/propagate", name: "tle_propagate", requirements: ["id" => "\d+"])] + public function propagate( + int $id, + Request $request, + NormalizerInterface $normalizer + ): JsonResponse { + $tle = $this->getTle($id); + + $tleModel = new TleModel($tle->getLine1(), $tle->getLine2(), $tle->getName()); + $sat = new \Predict_Sat(new \Predict_TLE($tle->getName(), $tle->getLine1(), $tle->getLine2())); + + $datetime = $this->getDate($request, 'date'); + $deltaT = ($datetime->getTimestamp() - $tleModel->epochDateTime()->getTimestamp()) / 60; // minutes + + $algorithm = ($tleModel->period() / 60) > self::DEEP_SATELLITE_PERIOD ? PropagatorAlgorithm::SDP4 : PropagatorAlgorithm::SGP4; + + $this->propagator->$algorithm($sat, $deltaT); + + \Predict_Math::Convert_Sat_State($sat->pos, $sat->vel); + + $sat_geodetic = new \Predict_Geodetic(); + \Predict_SGPObs::Calculate_LatLonAlt(\Predict_Time::unix2daynum($datetime->getTimestamp()), $sat->pos, $sat_geodetic); + + $sat_geodetic->lat = rad2deg($sat_geodetic->lat); + $sat_geodetic->lon = rad2deg($sat_geodetic->lon); + + $parameters = [ + 'date' => $datetime->format(\DateTimeInterface::ATOM), + ]; + + $url = $this->router->generate( + 'tle_propagate', + array_merge($request->request->all(), $parameters, ['id' => $id]), + UrlGeneratorInterface::ABSOLUTE_URL + ); + + $parameters['satelliteId'] = $id; + + $data = [ + '@context' => self::HYDRA_CONTEXT, + '@id' => $url, + '@type' => 'SatellitePropagationResult', + 'tle' => $tle, + 'algorithm' => $algorithm, + 'vector' => [ + 'reference_frame' => 'ECI', + 'position' => [ + 'x' => $sat->pos->x, + 'y' => $sat->pos->y, + 'z' => $sat->pos->z, + 'r' => $sat->pos->w, + 'unit' => 'km', + ], + 'velocity' => [ + 'x' => $sat->vel->x, + 'y' => $sat->vel->y, + 'z' => $sat->vel->z, + 'r' => $sat->vel->w, + 'unit' => 'km/s', + ], + ], + 'geodetic' => [ + 'latitude' => $sat_geodetic->lat, + 'longitude' => $sat_geodetic->lon, + 'altitude' => $sat_geodetic->alt, + ], + 'parameters' => $parameters, + ]; + + return $this->response( + $normalizer->normalize($data) + ); + } +} diff --git a/src/Controller/StatisticsController.php b/src/Controller/StatisticsController.php new file mode 100644 index 0000000..ba3acd7 --- /dev/null +++ b/src/Controller/StatisticsController.php @@ -0,0 +1,66 @@ +setTime(0, 0); + $newerThan->modify('-3 days'); + + $qb = $em->createQueryBuilder(); + + $qb->select( + [ + 'DATE_FORMAT(r.createdAt, \'%Y-%m-%d\') as date', + 'ROUND(CAST(DATE_FORMAT(r.createdAt, \'%H\') AS UNSIGNED) / :interval) as hour', + 'COUNT(r.id) as hits', + ] + ); + + $qb + ->from(Request::class, 'r') + ->where('r.createdAt > :newerThan') + ->setParameter('newerThan', $newerThan) + ->groupBy('date, hour') + ->setParameter('interval', self::INTERVAL); + + /** @var Request[] $result */ + $result = $qb->getQuery()->getResult(); + + $response = []; + foreach ($result as $key => &$item) { + if ($item['hour'] === "0") { + $previousKey = $key - 1; + if (isset($result[$previousKey])) { + $result[$previousKey]['hits'] = $item['hits']; + } + + unset($result[$key]); + } + + $date = new \DateTime($item['date']); + $date->setTime((int)$item['hour'] * self::INTERVAL, 0); + + $response[$date->format(\DateTimeInterface::ATOM)] = $item['hits']; + } + + return new JsonResponse( + $response, + Response::HTTP_OK, + ); + } +} diff --git a/src/Controller/TleController.php b/src/Controller/TleController.php new file mode 100644 index 0000000..68caf42 --- /dev/null +++ b/src/Controller/TleController.php @@ -0,0 +1,127 @@ + Filter::FILTER_TYPE_FLOAT, + TleCollectionSortableFieldsEnum::INCLINATION => Filter::FILTER_TYPE_FLOAT, + TleCollectionSortableFieldsEnum::PERIOD => Filter::FILTER_TYPE_FLOAT, + TleCollectionSortableFieldsEnum::SATELLITE_ID => Filter::FILTER_TYPE_ARRAY, + ]; + + public function __construct(protected TleRepository $repository) + { + } + + #[Route("/{id}", name: "tle_record", requirements: ["id" => "\d+"])] + public function record( + int $id, + NormalizerInterface $normalizer, + Request $request, + ): JsonResponse { + $this->assertParamIsBoolean($request, self::PARAM_EXTRA); + + $extra = (bool)$request->get(self::PARAM_EXTRA, false); + + $data = [ + '@context' => self::HYDRA_CONTEXT, + ]; + + return $this->response( + array_merge($data, $normalizer->normalize($this->getTle($id), null, [self::PARAM_EXTRA => $extra])), + ); + } + + #[Route("/", name: "tle_collection")] + public function collection( + Request $request, + NormalizerInterface $normalizer + ): JsonResponse { + $this + ->assertParamIsInteger($request, self::PAGE_PARAM) + ->assertParamIsGreaterThan($request, self::PAGE_PARAM, 0) + ->assertParamIsInteger($request, self::PAGE_SIZE_PARAM) + ->assertParamIsGreaterThan($request, self::PAGE_SIZE_PARAM, 0) + ->assertParamIsLessThan($request, self::PAGE_SIZE_PARAM, self::MAX_PAGE_SIZE) + ->assertParamInEnum($request, self::SORT_DIR_PARAM, SortDirectionEnum::toArray()) + ->assertParamInEnum($request, self::SORT_PARAM, TleCollectionSortableFieldsEnum::toArray()) + ->assertParamIsBoolean($request, self::PARAM_EXTRA); + + $extra = (bool)$request->get(self::PARAM_EXTRA, false); + + $satelliteIds = $request->get(TleCollectionSortableFieldsEnum::SATELLITE_ID, []); + + /** @var Filter[] $filters */ + $filters = $this->assertFilter($request, self::COLLECTION_FILTERS); + + $search = $request->get(self::SEARCH_PARAM); + $sort = $request->get(self::SORT_PARAM, TleCollectionSortableFieldsEnum::POPULARITY); + $sortDir = $request->get(self::SORT_DIR_PARAM, SortDirectionEnum::DESCENDING); + $pageSize = (int)min($request->get(self::PAGE_SIZE_PARAM, self::PAGE_SIZE), self::MAX_PAGE_SIZE); + + $collection = $this->repository->collection( + $search, + $sort, + $sortDir, + $pageSize, + $this->getPageOffset($this->getPage($request), $pageSize), + $filters, + ); + + $parameters = [ + self::SEARCH_PARAM => $search ?? '*', + self::SORT_PARAM => $sort, + self::SORT_DIR_PARAM => $sortDir, + self::PAGE_PARAM => $this->getPage($request), + self::PAGE_SIZE_PARAM => $pageSize, + ]; + + foreach ($filters as $filter) { + if ($filter->filter === TleCollectionSortableFieldsEnum::SATELLITE_ID) { + continue; + } + $parameters[\sprintf('%s[%s]', $filter->filter, $filter->operator)] = $filter->value; + } + + foreach ($satelliteIds as $index => $satelliteId) { + $name = \sprintf('%s[%d]', TleCollectionSortableFieldsEnum::SATELLITE_ID, $index); + $parameters[$name] = $satelliteId; + } + + $response = [ + '@context' => self::HYDRA_CONTEXT, + '@id' => $this->router->generate('tle_collection', [], UrlGeneratorInterface::ABSOLUTE_URL), + '@type' => 'Collection', + 'totalItems' => $collection->getTotal(), + 'member' => $collection->getCollection(), + 'parameters' => $parameters, + 'view' => $this->getPagination($request, $collection->getTotal(), $pageSize), + ]; + + return $this->response( + $normalizer->normalize($response, null, [self::PARAM_EXTRA => $extra]) + ); + } +} diff --git a/src/DataFixtures/TleFixtures.php b/src/DataFixtures/TleFixtures.php index 9ab650c..7b2ce03 100644 --- a/src/DataFixtures/TleFixtures.php +++ b/src/DataFixtures/TleFixtures.php @@ -25,10 +25,22 @@ public static function create(): Tle return $tle; } + public static function createDeep(): Tle + { + $tle = new Tle(); + $tle->setId(22049); + $tle->setName('GEOTAIL'); + $tle->setLine1('1 22049U 92044A 21119.24930644 -.00001485 00000-0 00000+0 0 9990'); + $tle->setLine2('2 22049 38.4941 42.7845 5317694 181.2241 357.6003 0.19228928 12156'); + + return $tle; + } + public function load(ObjectManager $manager): void { // create single record $manager->persist(self::create()); + $manager->persist(self::createDeep()); // create additional nine records with dummy satelliteIds for ($satelliteId = 1; $satelliteId < 10; $satelliteId++) { diff --git a/src/Entity/Attributes/TleOneToOneReference.php b/src/Entity/Attributes/TleOneToOneReference.php new file mode 100644 index 0000000..3b2dcda --- /dev/null +++ b/src/Entity/Attributes/TleOneToOneReference.php @@ -0,0 +1,26 @@ +tle; + } + + public function setTle(Tle $tle): void + { + $this->tle = $tle; + } +} diff --git a/src/Entity/Request.php b/src/Entity/Request.php new file mode 100644 index 0000000..9d75b84 --- /dev/null +++ b/src/Entity/Request.php @@ -0,0 +1,83 @@ +createdAt = DateTimeService::getCurrentUTC(); + } + + public function getTle(): Tle + { + return $this->tle; + } + + public function setTle(Tle $tle): void + { + $this->tle = $tle; + } + + public function getIp(): string + { + return $this->ip; + } + + public function setIp(string $ip): void + { + $this->ip = $ip; + } + + public function getReferer(): ?string + { + return $this->referer; + } + + public function setReferer(?string $referer): void + { + $this->referer = $referer; + } +} diff --git a/src/Entity/Tle.php b/src/Entity/Tle.php index 1fc8f78..6ddfe45 100644 --- a/src/Entity/Tle.php +++ b/src/Entity/Tle.php @@ -7,6 +7,7 @@ use App\Field\TleField; use App\Service\DateTimeService; use Doctrine\ORM\Mapping as ORM; +use Doctrine\ORM\Mapping\OneToOne; /** * @ORM\Entity(repositoryClass="App\Repository\TleRepository") @@ -18,6 +19,11 @@ class Tle use NameField; use TleField; + /** + * @OneToOne(targetEntity="TleInformation", mappedBy="tle") + */ + private ?TleInformation $info = null; + /** * @ORM\Column(name="updated_at", type="datetime") */ @@ -31,4 +37,8 @@ public function update(): void { $this->updatedAt = DateTimeService::getCurrentUTC(); } + + public function getInfo(): ?TleInformation { + return $this->info; + } } diff --git a/src/Entity/TleInformation.php b/src/Entity/TleInformation.php new file mode 100644 index 0000000..e0e55d4 --- /dev/null +++ b/src/Entity/TleInformation.php @@ -0,0 +1,53 @@ +tle = $tle; + } +} diff --git a/src/Enum/PropagatorAlgorithm.php b/src/Enum/PropagatorAlgorithm.php new file mode 100644 index 0000000..9e92b79 --- /dev/null +++ b/src/Enum/PropagatorAlgorithm.php @@ -0,0 +1,11 @@ +getRequest()->getPathInfo(), self::API_PATH)) { + return; + } + $exception = $event->getThrowable(); - $path = $event->getRequest()->getPathInfo(); + $response = ['message' => 'Unspecified error']; - if (strpos($path, self::API_PATH) === false) { - return; + if ($this->env === 'dev' || $this->env === 'test') { + $response['message'] = $exception->getMessage(); + $response['exception'] = $this->throwableToArray($exception); } - if ($exception instanceof NotFoundHttpException) { - $this->setResponse($event, $exception->getMessage()); - } + if ($exception instanceof HttpException) { + $response['message'] = $exception->getMessage(); - if ($exception instanceof AccessDeniedHttpException) { - $this->setResponse($event, 'Forbidden'); + $this->setJsonResponse($event, $response); + return; } - if ($this->env === 'dev') { - $this->setResponse($event, $exception->getMessage()); - } + $this->setJsonResponse($event, $response); } - private function setResponse(ExceptionEvent $event, string $message): void + private function setJsonResponse(ExceptionEvent $event, array $response): void { - $response = new JsonResponse( - [ - 'response' => [ - 'message' => $message, + $event->setResponse( + new JsonResponse( + [ + 'response' => $response ], - ] + Response::HTTP_OK, + ) ); + } - $event->setResponse($response); + private function throwableToArray(\Throwable $throwable): array + { + return [ + 'code' => $throwable->getCode(), + 'file' => $throwable->getFile() . ':' . $throwable->getLine(), + 'message' => $throwable->getMessage(), + 'trace' => $throwable->getTrace(), + ]; } } diff --git a/src/Event/ApiLimiterSubscriber.php b/src/Event/ApiLimiterSubscriber.php new file mode 100644 index 0000000..0159c8a --- /dev/null +++ b/src/Event/ApiLimiterSubscriber.php @@ -0,0 +1,70 @@ +limiter = $anonymousApiLimiter; + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::REQUEST => 'onRequest', + ]; + } + + public function onRequest(RequestEvent $event): void + { + $refererHost = parse_url($event->getRequest()->headers->get('referer'), PHP_URL_HOST); + + if (!FeatureFlag::API_RATE_LIMITER || $refererHost === Route::PRODUCTION_HOST || !Route::inArray($event->getRequest(), self::ROUTES)) { + return; + } + + $limit = $this->limiter->create($event->getRequest()->getClientIp())->consume(); + + if (false === $limit->isAccepted()) { + $headers = [ + 'X-RateLimit-Remaining' => $limit->getRemainingTokens(), + 'X-RateLimit-Retry-After' => $limit->getRetryAfter()->format(\DateTimeInterface::ATOM), + 'X-RateLimit-Limit' => $limit->getLimit(), + ]; + + $event->setResponse( + new JsonResponse( + [ + 'response' => [ + 'message' => \sprintf('Too many requests. Retry after %s.', $limit->getRetryAfter()->format(\DateTimeInterface::ATOM)), + 'limit' => $limit->getLimit(), + 'remaining' => $limit->getRemainingTokens(), + ], + ], + Response::HTTP_TOO_MANY_REQUESTS, + $headers + ), + ); + } + } +} diff --git a/src/Event/StatisticSubscriber.php b/src/Event/StatisticSubscriber.php new file mode 100644 index 0000000..3a04206 --- /dev/null +++ b/src/Event/StatisticSubscriber.php @@ -0,0 +1,55 @@ + 'onKernelTerminate', + ]; + } + + public function onKernelTerminate(TerminateEvent $event): void + { + if (!Route::inArray($event->getRequest(), self::ROUTES)) { + return; + } + + /** @var Tle|null $tle */ + $tle = $this->tleRepository->find($event->getRequest()->get('id')); + + if ($tle === null) { + return; + } + + $request = new Request(); + $request->setTle($tle); + $request->setIp($event->getRequest()->getClientIp()); + $request->setReferer($event->getRequest()->headers->get('referer')); + + $this->em->persist($request); + $this->em->flush(); + } +} diff --git a/src/Kernel.php b/src/Kernel.php index 5ffa385..35824d9 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -7,7 +7,7 @@ use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Kernel as BaseKernel; -use Symfony\Component\Routing\RouteCollectionBuilder; +use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; class Kernel extends BaseKernel { @@ -17,7 +17,7 @@ class Kernel extends BaseKernel public function registerBundles(): iterable { - $contents = require $this->getProjectDir().'/config/bundles.php'; + $contents = require $this->getConfigDir() . '/bundles.php'; foreach ($contents as $class => $envs) { if ($envs[$this->environment] ?? $envs['all'] ?? false) { yield new $class(); @@ -30,26 +30,35 @@ public function getProjectDir(): string return \dirname(__DIR__); } + public function getConfigDir(): string + { + return $this->getProjectDir() . '/etc'; + } + + /** + * @throws \Exception + */ protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void { - $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php')); + $confDir = $this->getConfigDir(); + + $container->addResource(new FileResource($confDir . '/bundles.php')); $container->setParameter('container.dumper.inline_class_loader', \PHP_VERSION_ID < 70400); $container->setParameter('container.dumper.inline_factories', true); - $confDir = $this->getProjectDir().'/config'; - $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/{packages}/'.$this->environment.'/*'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/{parameters}'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob'); - $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{packages}/*' . self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{packages}/' . $this->environment . '/*' . self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{parameters}' . self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{services}' . self::CONFIG_EXTS, 'glob'); + $loader->load($confDir . '/{services}_' . $this->environment . self::CONFIG_EXTS, 'glob'); } - protected function configureRoutes(RouteCollectionBuilder $routes): void + protected function configureRoutes(RoutingConfigurator $routes): void { - $confDir = $this->getProjectDir().'/config'; + $confDir = $this->getConfigDir(); - $routes->import($confDir.'/{routes}/'.$this->environment.'/*'.self::CONFIG_EXTS, '/', 'glob'); - $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob'); - $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob'); + $routes->import($confDir.'/{routes}/'.$this->environment.'/*'.self::CONFIG_EXTS); + $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS); + $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS); } } diff --git a/src/Migrations/Version20191217203053.php b/src/Migrations/Version20191217203053.php index a34cb43..60949fe 100644 --- a/src/Migrations/Version20191217203053.php +++ b/src/Migrations/Version20191217203053.php @@ -2,33 +2,41 @@ declare(strict_types=1); -namespace DoctrineMigrations; +namespace App\Migrations; use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\AbstractMigration; /** - * Auto-generated Migration: Please modify to your needs! + * @codeCoverageIgnore */ final class Version20191217203053 extends AbstractMigration { - public function getDescription() : string + public function isTransactional(): bool { - return ''; + return false; } - public function up(Schema $schema) : void + /** @throws \Exception */ + public function up(Schema $schema): void { - // this up() migration is auto-generated, please modify it to your needs - $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); - - $this->addSql('CREATE TABLE tle (id INT AUTO_INCREMENT NOT NULL, updated_at DATETIME NOT NULL, name VARCHAR(255) NOT NULL, line1 VARCHAR(255) NOT NULL, line2 VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->abortIf( + $this->connection->getDatabasePlatform()->getName() !== 'mysql', + 'Migration can only be executed safely on \'mysql\'.' + ); + + $this->addSql( + 'CREATE TABLE tle (id INT AUTO_INCREMENT NOT NULL, updated_at DATETIME NOT NULL, name VARCHAR(255) NOT NULL, line1 VARCHAR(255) NOT NULL, line2 VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB' + ); } - public function down(Schema $schema) : void + /** @throws \Exception */ + public function down(Schema $schema): void { - // this down() migration is auto-generated, please modify it to your needs - $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + $this->abortIf( + $this->connection->getDatabasePlatform()->getName() !== 'mysql', + 'Migration can only be executed safely on \'mysql\'.' + ); $this->addSql('DROP TABLE tle'); } diff --git a/src/Migrations/Version20210308195105.php b/src/Migrations/Version20210308195105.php new file mode 100644 index 0000000..4d927e0 --- /dev/null +++ b/src/Migrations/Version20210308195105.php @@ -0,0 +1,44 @@ +abortIf( + $this->connection->getDatabasePlatform()->getName() !== 'mysql', + 'Migration can only be executed safely on \'mysql\'.' + ); + + $this->addSql('DROP TABLE statistic'); + } + + public function isTransactional(): bool + { + return false; + } + + public function up(Schema $schema): void + { + // this up() migration is auto-generated, please modify it to your needs + $this->abortIf( + $this->connection->getDatabasePlatform()->getName() !== 'mysql', + 'Migration can only be executed safely on \'mysql\'.' + ); + + $this->addSql( + 'CREATE TABLE statistic (tle_id INT NOT NULL, hits BIGINT NOT NULL, PRIMARY KEY(tle_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB' + ); + $this->addSql('ALTER TABLE statistic ADD CONSTRAINT FK_649B469CE84B6F2B FOREIGN KEY (tle_id) REFERENCES tle (id)'); + } +} diff --git a/src/Migrations/Version20210322151101.php b/src/Migrations/Version20210322151101.php new file mode 100644 index 0000000..94d1f08 --- /dev/null +++ b/src/Migrations/Version20210322151101.php @@ -0,0 +1,31 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('CREATE TABLE request (id INT AUTO_INCREMENT NOT NULL, tle_id INT NOT NULL, updated_at DATETIME NOT NULL, ip VARCHAR(255) NOT NULL, INDEX IDX_3B978F9FE84B6F2B (tle_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE request ADD CONSTRAINT FK_3B978F9FE84B6F2B FOREIGN KEY (tle_id) REFERENCES tle (id)'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP TABLE request'); + } +} diff --git a/src/Migrations/Version20210331192030.php b/src/Migrations/Version20210331192030.php new file mode 100644 index 0000000..0af9a58 --- /dev/null +++ b/src/Migrations/Version20210331192030.php @@ -0,0 +1,30 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE request CHANGE updated_at created_at DATETIME NOT NULL'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE request CHANGE created_at updated_at DATETIME NOT NULL'); + } +} diff --git a/src/Migrations/Version20210402050806.php b/src/Migrations/Version20210402050806.php new file mode 100644 index 0000000..aa579bf --- /dev/null +++ b/src/Migrations/Version20210402050806.php @@ -0,0 +1,36 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('CREATE TABLE tle_information (tle_id INT NOT NULL, eccentricity DOUBLE PRECISION DEFAULT NULL, inclination DOUBLE PRECISION DEFAULT NULL, PRIMARY KEY(tle_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE tle_information ADD CONSTRAINT FK_E216A773E84B6F2B FOREIGN KEY (tle_id) REFERENCES tle (id)'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP TABLE tle_information'); + } +} diff --git a/src/Migrations/Version20210420125645.php b/src/Migrations/Version20210420125645.php new file mode 100644 index 0000000..ce2fa46 --- /dev/null +++ b/src/Migrations/Version20210420125645.php @@ -0,0 +1,30 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE tle_information ADD `period` DOUBLE PRECISION DEFAULT NULL'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE tle_information DROP `period`'); + } +} diff --git a/src/Migrations/Version20210420170012.php b/src/Migrations/Version20210420170012.php new file mode 100644 index 0000000..177a0cf --- /dev/null +++ b/src/Migrations/Version20210420170012.php @@ -0,0 +1,30 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE tle_information ADD geostationary TINYINT(1) DEFAULT \'0\' NOT NULL'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE tle_information DROP geostationary'); + } +} diff --git a/src/Migrations/Version20210426124814.php b/src/Migrations/Version20210426124814.php new file mode 100644 index 0000000..8baa678 --- /dev/null +++ b/src/Migrations/Version20210426124814.php @@ -0,0 +1,36 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP TABLE statistic'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('CREATE TABLE statistic (tle_id INT NOT NULL, hits BIGINT NOT NULL, PRIMARY KEY(tle_id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB COMMENT = \'\' '); + $this->addSql('ALTER TABLE statistic ADD CONSTRAINT FK_649B469CE84B6F2B FOREIGN KEY (tle_id) REFERENCES tle (id) ON UPDATE NO ACTION ON DELETE NO ACTION'); + } +} diff --git a/src/Migrations/Version20210524103622.php b/src/Migrations/Version20210524103622.php new file mode 100644 index 0000000..ca8913c --- /dev/null +++ b/src/Migrations/Version20210524103622.php @@ -0,0 +1,30 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE tle_information ADD raan DOUBLE PRECISION DEFAULT NULL, ADD semi_major_axis DOUBLE PRECISION DEFAULT NULL'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE tle_information DROP raan, DROP semi_major_axis'); + } +} diff --git a/src/Migrations/Version20210605124127.php b/src/Migrations/Version20210605124127.php new file mode 100644 index 0000000..4a4bae5 --- /dev/null +++ b/src/Migrations/Version20210605124127.php @@ -0,0 +1,35 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE request ADD referer VARCHAR(255) DEFAULT NULL'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE request DROP referer'); + } +} diff --git a/src/Repository/RequestRepository.php b/src/Repository/RequestRepository.php new file mode 100644 index 0000000..b7d9a6e --- /dev/null +++ b/src/Repository/RequestRepository.php @@ -0,0 +1,27 @@ +_em->createQueryBuilder(); + + $builder + ->delete(Request::class, 'r') + ->where('r.createdAt < :date') + ->setParameter('date', $dateTime); + + $builder->getQuery()->execute(); + } +} diff --git a/src/Repository/TleInformationRepository.php b/src/Repository/TleInformationRepository.php new file mode 100644 index 0000000..1cd77e7 --- /dev/null +++ b/src/Repository/TleInformationRepository.php @@ -0,0 +1,15 @@ +createQueryBuilder('tle', 'tle.id') ->getQuery() @@ -35,11 +36,14 @@ public function collection( string $sort, string $sortDir, int $pageSize, - int $offset - ): PaginationCollection - { + int $offset, + array $filters, + ): PaginationCollection { $builder = $this->createQueryBuilder('tle'); + $builder->select('tle'); + $builder->leftJoin(TleInformation::class, 'info', Expr\Join::WITH, 'info.tle = tle.id'); + // search if ($search) { $builder @@ -49,14 +53,38 @@ public function collection( $builder->expr()->like('tle.name', ':search') ) ) - ->setParameter('search', '%'.$search.'%'); + ->setParameter('search', '%' . $search . '%'); + } + + // filters + foreach ($filters as $index => $filter) { + if ($filter->type === Filter::FILTER_TYPE_ARRAY) { + $paramName = \sprintf('param_%d', $index); + + $builder + ->andWhere(\sprintf("%s IN (:%s)", $this->getSortTableColumnMapping($filter->filter), $paramName)) + ->setParameter($paramName, $filter->value); + + continue; + } + + $placeholder = \sprintf('filter_%s_%d', $filter->filter, $index); + $builder->andWhere(\sprintf('info.%s %s :%s', $filter->filter, $filter->sqlOperator, $placeholder)); + $builder->setParameter($placeholder, $filter->value); } - // get total - $total = \count($builder->getQuery()->getResult()); + $total = $this->getCount($builder); // sort - $builder->orderBy('tle.'.$sort, $sortDir); + if ($sort === TleCollectionSortableFieldsEnum::POPULARITY) { + $before = (new \DateTime())->sub(new \DateInterval('P7D')); + $builder->leftJoin(Request::class, 's', Expr\Join::WITH, 's.tle = tle.id AND s.createdAt < :date'); + $builder->setParameter('date', $before); + $builder->groupBy('tle.id'); + $builder->addOrderBy('COUNT(s.id)', $sortDir); + } else { + $builder->addOrderBy($this->getSortTableColumnMapping($sort), $sortDir); + } // limit $builder->setMaxResults($pageSize); @@ -69,4 +97,32 @@ public function collection( return $collection; } + + /** + * @throws \Doctrine\ORM\NoResultException + * @throws \Doctrine\ORM\NonUniqueResultException + */ + private function getCount(QueryBuilder $builder): int + { + $builder = clone $builder; + + $builder->select('count(tle.id)'); + + return $builder->getQuery()->getSingleScalarResult(); + } + + private function getSortTableColumnMapping(string $sort): ?string + { + return match ($sort) { + TleCollectionSortableFieldsEnum::ID => 'tle.id', + TleCollectionSortableFieldsEnum::SATELLITE_ID => 'tle.id', + TleCollectionSortableFieldsEnum::NAME => 'tle.name', + TleCollectionSortableFieldsEnum::POPULARITY => null, + TleCollectionSortableFieldsEnum::INCLINATION => 'info.inclination', + TleCollectionSortableFieldsEnum::ECCENTRICITY => 'info.eccentricity', + TleCollectionSortableFieldsEnum::PERIOD => 'info.period', + TleCollectionSortableFieldsEnum::SEMI_MAJOR_AXIS => 'info.semiMajorAxis', + TleCollectionSortableFieldsEnum::RAAN => 'info.raan', + }; + } } diff --git a/src/Serializer/ObserverNormalizer.php b/src/Serializer/ObserverNormalizer.php new file mode 100644 index 0000000..15ccde1 --- /dev/null +++ b/src/Serializer/ObserverNormalizer.php @@ -0,0 +1,37 @@ + 'Observer', + ], + $this->normalizer->normalize($object) + ); + } + + public function supportsNormalization($data, string $format = null): bool + { + return $data instanceof Observer; + } +} diff --git a/src/Serializer/SatellitePassNormalizer.php b/src/Serializer/SatellitePassNormalizer.php new file mode 100644 index 0000000..7e59c35 --- /dev/null +++ b/src/Serializer/SatellitePassNormalizer.php @@ -0,0 +1,67 @@ + $details ? 'SatelliteFlyOverDetails' : 'SatelliteFlyOver', + 'aos' => [ + 'date' => \Predict_Time::daynum2datetime($object->visible_aos ?? $object->aos, $timezone)->format( + \DateTimeInterface::ATOM + ), + 'azimuth' => round($object->visible_aos_az ?? null, 2), + 'elevation' => round($object->visible_aos_el ?? null, 2), + ], + 'max' => [ + 'date' => \Predict_Time::daynum2datetime($object->visible_tca ?? $object->tca, $timezone)->format( + \DateTimeInterface::ATOM + ), + 'azimuth' => round($object->visible_max_el_az ?? null, 2), + 'elevation' => round($object->visible_max_el ?? null, 2), + ], + 'los' => [ + 'date' => \Predict_Time::daynum2datetime($object->visible_los ?? $object->los, $timezone)->format( + \DateTimeInterface::ATOM + ), + 'azimuth' => round($object->visible_los_az ?? $object->los_az, 2), + 'elevation' => round($object->visible_los_el ?? null, 2), + ], + ]; + + if ($details) { + foreach ($object->details as $item) { + $result['details'][] = [ + 'azimuth' => $item->az, + 'elevation' => $item->el + ]; + } + } + + return $result; + } + + public function supportsNormalization($data, string $format = null): bool + { + return $data instanceof \Predict_Pass; + } +} diff --git a/src/Serializer/TleModelNormalizer.php b/src/Serializer/TleModelNormalizer.php index 0e8bedd..2e65c22 100644 --- a/src/Serializer/TleModelNormalizer.php +++ b/src/Serializer/TleModelNormalizer.php @@ -2,42 +2,59 @@ namespace App\Serializer; +use App\Controller\TleController; use App\Entity\Tle; -use App\ViewModel\Model\TleModel; +use App\ViewModel\TleCollectionSortableFieldsEnum; +use Ivanstan\Tle\Model\Tle as TleModel; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; class TleModelNormalizer implements NormalizerInterface { - private UrlGeneratorInterface $router; - - public function __construct(UrlGeneratorInterface $router) + public function __construct(private UrlGeneratorInterface $router) { - $this->router = $router; } /** - * @param TleModel $model - * @param null $format - * @param array $context + * @param Tle $object + * @param string|null $format + * @param array $context * - * @return array|bool|float|int|string + * @return array */ - public function normalize($entity, string $format = null, array $context = []) + public function normalize($object, ?string $format = null, array $context = []): array { - $id = $this->router->generate('tle_record', ['id' => $entity->getId()], UrlGeneratorInterface::ABSOLUTE_URL); + $id = $this->router->generate('tle_record', ['id' => $object->getId()], UrlGeneratorInterface::ABSOLUTE_URL); + + $model = new TleModel($object->getLine1(), $object->getLine2(), $object->getName()); - $model = new TleModel($entity->getLine1(), $entity->getLine2(), $entity->getName()); + $isExtra = ($context[TleController::PARAM_EXTRA] ?? null) === true; - return [ + $normalized = [ '@id' => $id, '@type' => 'TleModel', 'satelliteId' => $model->getId(), 'name' => $model->getName(), - 'date' => $model->getDate(), + 'date' => $model->epochDateTime()->format(\DateTimeInterface::ATOM), 'line1' => $model->getLine1(), 'line2' => $model->getLine2(), ]; + + if ($isExtra && $object->getInfo()) { + $extra = [ + 'extra' => [ + TleCollectionSortableFieldsEnum::ECCENTRICITY => $object->getInfo()->eccentricity, + TleCollectionSortableFieldsEnum::INCLINATION => $object->getInfo()->inclination, + TleCollectionSortableFieldsEnum::PERIOD => $object->getInfo()->period, + TleCollectionSortableFieldsEnum::RAAN => $object->getInfo()->raan, + TleCollectionSortableFieldsEnum::SEMI_MAJOR_AXIS => $object->getInfo()->semiMajorAxis, + ], + ]; + + $normalized = array_merge($normalized, $extra); + } + + return $normalized; } public function supportsNormalization($data, string $format = null): bool diff --git a/src/Service/FeatureFlag.php b/src/Service/FeatureFlag.php new file mode 100644 index 0000000..d061893 --- /dev/null +++ b/src/Service/FeatureFlag.php @@ -0,0 +1,8 @@ +predict = new \Predict(); + $this->qth = new \Predict_QTH(); + } + + public function setTle(Tle $tle): self + { + $this->sat = new \Predict_Sat( + new \Predict_TLE($tle->getName(), $tle->getLine1(), $tle->getLine2()) + ); + + return $this; + } + + public function setObserver(Observer $observer): self + { + $this->qth->lat = $observer->latitude; + $this->qth->lon = $observer->longitude; + $this->qth->alt = $observer->altitude; + + return $this; + } + + public function getVisiblePasses(float $time): array + { + return $this->predict->filterVisiblePasses($this->getPasses($time)); + } + + public function getPasses(float $time): array + { + $this->predict->minEle = 10; // Minimum elevation for a pass + $this->predict->timeRes = 10; // Pass details: time resolution in seconds + $this->predict->numEntries = 20; // Pass details: number of entries per pass + $this->predict->threshold = -6; // Twilight threshold (sun must be at this lat or lower) + + // Get the passes and filter visible only, takes about 4 seconds for 10 days + return $this->predict->get_passes($this->sat, $this->qth, $time, 10); + } +} diff --git a/src/Service/Route.php b/src/Service/Route.php new file mode 100644 index 0000000..d25ed5b --- /dev/null +++ b/src/Service/Route.php @@ -0,0 +1,15 @@ +get('_route'), $routes, false); + } +} diff --git a/src/Service/SentryCallbackBeforeSend.php b/src/Service/SentryCallbackBeforeSend.php new file mode 100644 index 0000000..a086de2 --- /dev/null +++ b/src/Service/SentryCallbackBeforeSend.php @@ -0,0 +1,26 @@ +getExceptions(); + + foreach ($exceptions as $exception) { + if (in_array($exception->getType(), self::SKIP)) { + return null; + } + } + + return $event; + } +} diff --git a/src/Service/TleFile.php b/src/Service/TleFile.php deleted file mode 100644 index 37c917e..0000000 --- a/src/Service/TleFile.php +++ /dev/null @@ -1,44 +0,0 @@ -content = $content; - } - - /** - * @return TleModel[] - */ - public function parse(): array - { - $data = explode("\n", $this->content); - $data = array_filter($data); - $raw = array_chunk($data, 3); - - $result = []; - foreach ($raw as $key => $item) { - if (!isset($item[0], $item[1], $item[2])) { - $result[$key] = null; - continue; - } - - $result[$key] = new TleModel($this->trim($item[1]), $this->trim($item[2]), $this->trim($item[0])); - } - - return $result; - } - - protected function trim(string $string): string - { - $string = str_replace(["/\r\n/", "/\r/", "/\n/"], '', $string); - - return trim($string); - } -} \ No newline at end of file diff --git a/src/Service/Traits/TleHttpTrait.php b/src/Service/Traits/TleHttpTrait.php new file mode 100644 index 0000000..a87d0a5 --- /dev/null +++ b/src/Service/Traits/TleHttpTrait.php @@ -0,0 +1,33 @@ +repository->findOneBy(['id' => $id]); + + if ($tle === null) { + throw new NotFoundHttpException(\sprintf('Unable to find record with id %s', $id)); + } + + return $tle; + } + + protected function getObserver(Request $request): Observer + { + try { + return new Observer((float)$request->get('latitude', 0), (float)$request->get('longitude', 0)); + } catch (\InvalidArgumentException $exception) { + throw new BadRequestHttpException($exception->getMessage()); + } + } +} diff --git a/src/Service/Validator/RequestValidator.php b/src/Service/Validator/RequestValidator.php new file mode 100644 index 0000000..8cd5969 --- /dev/null +++ b/src/Service/Validator/RequestValidator.php @@ -0,0 +1,120 @@ +get($name); + + if ($param === null) { + return $this; + } + + if (!in_array($param, Filter::BOOLEAN_VALUES, true)) { + throw new BadRequestHttpException( + \sprintf('Parameter \'%s\' must be boolean. Supported values are %s.', $name, implode(' or ', Filter::BOOLEAN_VALUES)) + ); + } + + return $this; + } + + protected function assertParamIsInteger(Request $request, string $name): self + { + $param = (int)$request->get($name); + + if ($param === null) { + return $this; + } + + if (!preg_match('/^\d+$/', $param)) { + throw new BadRequestHttpException( + \sprintf('Parameter \'%s\' must be integer.', $name) + ); + } + + return $this; + } + + protected function assertParamIsGreaterThan(Request $request, string $name, float $value): self + { + $param = $request->get($name); + + if ($param === null) { + return $this; + } + + if (!($param > $value)) { + throw new BadRequestHttpException( + \sprintf('Parameter \'%s\' must be greater than %d.', $name, $value) + ); + } + + return $this; + } + + protected function assertParamIsLessThan(Request $request, string $name, float $value): self + { + $param = $request->get($name); + + if ($param === null) { + return $this; + } + + if (!($param <= $value)) { + throw new BadRequestHttpException( + \sprintf('Parameter \'%s\' must be less than %d.', $name, $value) + ); + } + + return $this; + } + + protected function assertParamInEnum(Request $request, string $name, array $values): self + { + $param = $request->get($name); + + if ($param === null) { + return $this; + } + + if (!\in_array($param, $values, true)) { + throw new BadRequestHttpException( + \sprintf( + 'Parameter \'%s\' must be one of the following: %s', + $name, + '\'' . implode('\', \'', $values) . '\'', + ) + ); + } + + return $this; + } + + protected function assertFilter(Request $request, array $filters): array + { + $result = []; + + foreach ($filters as $filter => $type) { + $values = $request->get($filter, []); + + if ($type === Filter::FILTER_TYPE_ARRAY && !empty($values)) { + $result[] = new Filter($filter, $type, Filter::OPERATOR_EQUAL, $values); + + continue; + } + + foreach ($values as $operator => $value) { + $result[] = new Filter($filter, $type, $operator, $value); + } + } + + return $result; + } +} diff --git a/src/ViewModel/Filter.php b/src/ViewModel/Filter.php new file mode 100644 index 0000000..808751c --- /dev/null +++ b/src/ViewModel/Filter.php @@ -0,0 +1,96 @@ +'; + public const OPERATOR_GREATER_THEN_EQUAL = '>='; + public const OPERATOR_LESS_THEN = '<'; + public const OPERATOR_LESS_THEN_EQUAL = '<='; + public const REST_OPERATOR_GREATER_THEN = 'gt'; + public const REST_OPERATOR_GREATER_THEN_EQUAL = 'gte'; + public const REST_OPERATOR_LESS_THEN = 'lt'; + public const REST_OPERATOR_LESS_THEN_EQUAL = 'lte'; + + public const BOOLEAN_VALUES = [ + '1', + '0', + ]; + + public const FILTER_FLOAT_OPERATORS = [ + self::FILTER_TYPE_FLOAT => [ + self::REST_OPERATOR_GREATER_THEN => self::OPERATOR_GREATER_THEN, + self::REST_OPERATOR_GREATER_THEN_EQUAL => self::OPERATOR_GREATER_THEN_EQUAL, + self::REST_OPERATOR_LESS_THEN => self::OPERATOR_LESS_THEN, + self::REST_OPERATOR_LESS_THEN_EQUAL => self::OPERATOR_LESS_THEN_EQUAL, + ], + ]; + + public mixed $value; + public string $sqlOperator; + + public function __construct(public string $filter, public string $type, public string $operator, mixed $value) + { + $this->value = $this->validateValue($value); + $this->sqlOperator = $this->validateOperator(); + } + + protected function validateOperator(): string + { + if ($this->type === self::FILTER_TYPE_FLOAT) { + $operators = self::FILTER_FLOAT_OPERATORS[self::FILTER_TYPE_FLOAT]; + if (!array_key_exists($this->operator, $operators)) { + throw new BadRequestHttpException( + \sprintf( + 'Operator for filter \'%s\' should be one of the following %s, \'%s\' provided', + $this->filter, + implode(', ', array_keys($operators)), + $this->operator + ) + ); + } + + return $operators[$this->operator]; + } + + if ($this->type === self::FILTER_TYPE_ARRAY) { + return self::OPERATOR_EQUAL; + } + + return ''; + } + + protected function validateValue(mixed $value): mixed + { + if ($this->type === self::FILTER_TYPE_FLOAT) { + $value = (float)$value; + + if (!is_float($value)) { + throw new \InvalidArgumentException( + \sprintf('Filter %s value should be %s', $this->filter, $this->type) + ); + } + + return $value; + } + + if ($this->type === self::FILTER_TYPE_ARRAY) { + if (!is_array($value)) { + throw new \InvalidArgumentException( + \sprintf('Filter %s value should be %s', $this->filter, $this->type) + ); + } + + return $value; + } + + return null; + } +} diff --git a/src/ViewModel/LatLng.php b/src/ViewModel/LatLng.php new file mode 100644 index 0000000..f93a368 --- /dev/null +++ b/src/ViewModel/LatLng.php @@ -0,0 +1,41 @@ +latitude > 90 || $this->latitude < -90) { + throw new \InvalidArgumentException('Invalid latitude value'); + } + + if ($this->longitude > 180 || $this->longitude < -180) { + throw new \InvalidArgumentException('Invalid longitude value'); + } + } + + public function getTimezone(): ?string + { + $diffs = []; + foreach (DateTimeZone::listIdentifiers() as $timezoneID) { + $timezone = new DateTimeZone($timezoneID); + $location = $timezone->getLocation(); + $tLat = $location['latitude']; + $tLng = $location['longitude']; + $diffLat = abs($this->latitude - $tLat); + $diffLng = abs($this->longitude - $tLng); + $diff = $diffLat + $diffLng; + $diffs[$timezoneID] = $diff; + } + + $timezone = array_keys($diffs, min($diffs)); + + return $timezone[0] ?? null; + } +} diff --git a/src/ViewModel/Model/TleModel.php b/src/ViewModel/Model/TleModel.php deleted file mode 100644 index 5409119..0000000 --- a/src/ViewModel/Model/TleModel.php +++ /dev/null @@ -1,217 +0,0 @@ -line1 = $line1; - $this->line2 = $line2; - $this->name = $name; - } - - public function getId(): int - { - return (int)substr($this->line1, 2, 6); - } - - public function getClassification(): string - { - return $this->line1[7]; - } - - public function getName(): string - { - return $this->name; - } - - public function launchYear(?bool $fourDigits = null): int - { - $year = (int)trim(substr($this->line1, 9, 2)); - - if ($fourDigits ?? true) { - $this->formatYear($year); - } - - return $year; - } - - public function launchNumberOfYear(): int - { - return (int)trim(substr($this->line1, 12, 2)); - } - - public function epoch(): string - { - return trim(substr($this->line1, 18, 14)); - } - - public function launchPiece(): string - { - return trim(substr($this->line1, 14, 2)); - } - - public function bstar(): string - { - return trim(substr($this->line1, 53, 8)); - } - - public function elementNumber(): int - { - return (int)trim(substr($this->line1, 64, 4)); - } - - public function inclination(): float - { - return (float)trim(substr($this->line2, 8, 8)); - } - - public function raan(): float - { - return (float)trim(substr($this->line2, 17, 8)); - } - - public function eccentricity(): float - { - return (float)('.' . trim(substr($this->line2, 26, 7))); - } - - public function meanAnomaly(): float - { - return (float)trim(substr($this->line2, 43, 8)); - } - - public function argumentOfPerigee(): float - { - return (float)trim(substr($this->line2, 34, 8)); - } - - public function meanMotion(): float - { - return (float)trim(substr($this->line2, 52, 11)); - } - - public function getDate(): string - { - $year = (int)trim(substr($this->line1, 18, 2)); - $year = $this->formatYear($year); - - $date = new \DateTime(); - $timezone = new \DateTimeZone('UTC'); - - $epoch = (float)trim(substr($this->line1, 20, 12)); - $days = (int)$epoch; - - $date - ->setTimezone($timezone) - ->setDate($year, 1, $days); - - $faction = round($epoch - $days, 8); - - $faction *= 24; // hours - $hours = round($faction); - $faction -= $hours; - - $faction *= 60; // minutes - $minutes = round($faction); - $faction -= $minutes; - - $faction *= 60; // seconds - $seconds = round($faction); - $faction -= $seconds; - - $faction *= 1000; // milliseconds - $milliseconds = round($faction); - - $date->setTime($hours, $minutes, $seconds, $milliseconds); - - return $date->format('c'); - } - - public function getChecksum(int $lineNumber): int - { - $line = $this->getLineByNumber($lineNumber); - - return (int)trim(substr($line, 68)); - } - - public function calculateChecksum(int $lineNumber): int - { - $line = $this->getLineByNumber($lineNumber); - - return $this->checksum($line); - } - - public function verify(): bool - { - if (self::LINE1 !== (int)$this->line1[0] || self::LINE2 !== (int)$this->line2[0]) { - return false; - } - - if ($this->getChecksum(self::LINE1) !== $this->calculateChecksum(self::LINE1)) { - return false; - } - - if ($this->getChecksum(self::LINE2) !== $this->calculateChecksum(self::LINE2)) { - return false; - } - - return true; - } - - private function formatYear(int $twoDigitYear): int - { - if ($twoDigitYear < 57) { - $twoDigitYear += 2000; - } else { - $twoDigitYear += 1900; - } - - return $twoDigitYear; - } - - private function getLineByNumber(int $lineNumber): string - { - if (self::LINE1 === $lineNumber) { - return $this->line1; - } - - if (self::LINE2 === $lineNumber) { - return $this->line2; - } - - throw new \InvalidArgumentException(\sprintf('Invalid line number %d', $lineNumber)); - } - - private function checksum(string $line): int - { - $line = substr($line, 0, -1); // remove checksum - $length = \strlen($line); - $sum = 0; - for ($i = 0; $i < $length; $i++) { - if ($line[$i] === '-') { - ++$sum; - continue; - } - - if (is_numeric($line[$i])) { - $sum += $line[$i]; - } - } - return $sum % 10; - } -} diff --git a/src/ViewModel/Observer.php b/src/ViewModel/Observer.php new file mode 100644 index 0000000..9120b7a --- /dev/null +++ b/src/ViewModel/Observer.php @@ -0,0 +1,18 @@ +date = $dateTime ?? new \DateTime('now', new \DateTimeZone($this->getTimezone())); + } +} diff --git a/src/ViewModel/SortDirectionEnum.php b/src/ViewModel/SortDirectionEnum.php new file mode 100644 index 0000000..33b65d1 --- /dev/null +++ b/src/ViewModel/SortDirectionEnum.php @@ -0,0 +1,11 @@ + - - - {% block head %} - - - {% block title %}{{ app_name }}{% endblock %} - {% block stylesheets %} -{# #} - - {% endblock %} - {% endblock %} - - - {% block body %} - {% block javascripts %} - - - {% endblock %} - {% endblock %} - - diff --git a/templates/base.html.twig b/templates/base.html.twig deleted file mode 100644 index 043f42d..0000000 --- a/templates/base.html.twig +++ /dev/null @@ -1,12 +0,0 @@ - - - - - {% block title %}Welcome!{% endblock %} - {% block stylesheets %}{% endblock %} - - - {% block body %}{% endblock %} - {% block javascripts %}{% endblock %} - - diff --git a/templates/pages/api/docs.html.twig b/templates/pages/api/docs.html.twig deleted file mode 100644 index 770fac5..0000000 --- a/templates/pages/api/docs.html.twig +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'base-empty.html.twig' %} - -{% block title %} API Documentation | {{ parent() }}{% endblock %} - -{% block body %} -
- {{ parent() }} -{% endblock %} - diff --git a/tests/AbstractWebTestCase.php b/tests/AbstractWebTestCase.php index 71b7270..2ef9f49 100644 --- a/tests/AbstractWebTestCase.php +++ b/tests/AbstractWebTestCase.php @@ -23,6 +23,9 @@ protected function get(string $url, array $params = []): Response return self::$client->getResponse(); } + /** + * @throws \JsonException + */ protected function toArray(Response $response): array { return json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR); diff --git a/tests/AssertionTrait.php b/tests/AssertionTrait.php new file mode 100644 index 0000000..c82a1b0 --- /dev/null +++ b/tests/AssertionTrait.php @@ -0,0 +1,22 @@ +getLine1(), $tle->getLine2(), $tle->getName()); + + self::assertEquals('https://www.w3.org/ns/hydra/context.jsonld', $response['@context']); + self::assertEquals('http://localhost/api/tle/' . $tle->getId(), $response['@id']); + self::assertEquals('TleModel', $response['@type']); + self::assertEquals($tle->getId(), $response['satelliteId']); + self::assertEquals($tle->getName(), $response['name']); + self::assertEquals($model->epochDateTime()->format(\DateTimeInterface::ATOM), $response['date']); + self::assertEquals($tle->getLine1(), $response['line1']); + self::assertEquals($tle->getLine2(), $response['line2']); + } +} diff --git a/tests/CollectionTest.php b/tests/CollectionTest.php index 5feec34..61bf1b8 100644 --- a/tests/CollectionTest.php +++ b/tests/CollectionTest.php @@ -1,130 +1,125 @@ - 1, - 'expected' => [ - '@id' => 'http://localhost/api/tle?page=1&page-size=2', - '@type' => 'PartialCollectionView', - 'first' => 'http://localhost/api/tle?page=1&page-size=2', - 'next' => 'http://localhost/api/tle?page=2&page-size=2', - 'last' => 'http://localhost/api/tle?page=5&page-size=2' - ] - ], - [ - 'page' => 3, - 'expected' => [ - '@id' => 'http://localhost/api/tle?page=3&page-size=2', - '@type' => 'PartialCollectionView', - 'first' => 'http://localhost/api/tle?page=1&page-size=2', - 'previous' => 'http://localhost/api/tle?page=2&page-size=2', - 'next' => 'http://localhost/api/tle?page=4&page-size=2', - 'last' => 'http://localhost/api/tle?page=5&page-size=2' - ] - ], - [ - 'page' => 5, - 'expected' => [ - '@id' => 'http://localhost/api/tle?page=5&page-size=2', - '@type' => 'PartialCollectionView', - 'first' => 'http://localhost/api/tle?page=1&page-size=2', - 'previous' => 'http://localhost/api/tle?page=4&page-size=2', - 'last' => 'http://localhost/api/tle?page=5&page-size=2' - ] - ], - [ - 'page' => 7, - 'expected' => [ - '@id' => 'http://localhost/api/tle?page=7&page-size=2', - '@type' => 'PartialCollectionView', - 'first' => 'http://localhost/api/tle?page=1&page-size=2', - 'previous' => 'http://localhost/api/tle?page=6&page-size=2', - 'last' => 'http://localhost/api/tle?page=5&page-size=2' - ] - ] - ]; - - public function testPaginationWorks(): void - { - foreach (self::TEST as $test) { - $response = $this->getCollectionContent($test['page'], 2); - - self::assertArrayHasKey('view', $response); - - $this->assertViewIsCorrect( - $test['expected'], - $response['view'] - ); - } - } - - public function testPaginationError(): void - { - $this->expectException(LogicException::class); - $response = $this->getCollection(-1, 2); - self::assertEquals( - Response::HTTP_INTERNAL_SERVER_ERROR, - $response->getStatusCode(), - 'Assert HTTP 500 is returned for page -1' - ); - - $this->expectException(LogicException::class); - $response = $this->getCollection(0, 2); - self::assertEquals( - Response::HTTP_INTERNAL_SERVER_ERROR, - $response->getStatusCode(), - 'Assert HTTP 500 is returned for page 0' - ); - - $this->expectException(LogicException::class); - $response = $this->getCollection(1, -1); - self::assertEquals( - Response::HTTP_INTERNAL_SERVER_ERROR, - $response->getStatusCode(), - 'Assert HTTP 500 is returned for page size -1' - ); - - $this->expectException(LogicException::class); - $response = $this->getCollection(1, 0); - self::assertEquals( - Response::HTTP_INTERNAL_SERVER_ERROR, - $response->getStatusCode(), - 'Assert HTTP 500 is returned for page size 0' - ); - } - - private function assertViewIsCorrect($expected, $actual): void - { - foreach ($actual as $key => $value) { - self::assertArrayHasKey($key, $expected, \sprintf('Assert view has key %s', $key)); - self::assertEquals($value, $expected[$key], \sprintf('Assert value of key %s is correct', $key)); - } - } - - private function getCollectionContent(int $page, int $pageSize): array - { - return $this->toArray( - $this->getCollection($page, $pageSize) - ); - } - - private function getCollection(int $page, int $pageSize): Response - { - return $this->get( - '/api/tle', - [ - 'page' => $page, - 'page-size' => $pageSize, - ] - ); - } -} \ No newline at end of file + 1, + 'expected' => [ + '@id' => 'http://localhost/api/tle/?page=1&page-size=2', + '@type' => 'PartialCollectionView', + 'first' => 'http://localhost/api/tle/?page=1&page-size=2', + 'next' => 'http://localhost/api/tle/?page=2&page-size=2', + 'last' => 'http://localhost/api/tle/?page=6&page-size=2' + ] + ], + [ + 'page' => 3, + 'expected' => [ + '@id' => 'http://localhost/api/tle/?page=3&page-size=2', + '@type' => 'PartialCollectionView', + 'first' => 'http://localhost/api/tle/?page=1&page-size=2', + 'previous' => 'http://localhost/api/tle/?page=2&page-size=2', + 'next' => 'http://localhost/api/tle/?page=4&page-size=2', + 'last' => 'http://localhost/api/tle/?page=6&page-size=2' + ] + ], + [ + 'page' => 5, + 'expected' => [ + '@id' => 'http://localhost/api/tle/?page=5&page-size=2', + '@type' => 'PartialCollectionView', + 'first' => 'http://localhost/api/tle/?page=1&page-size=2', + 'previous' => 'http://localhost/api/tle/?page=4&page-size=2', + 'next' => 'http://localhost/api/tle/?page=6&page-size=2', + 'last' => 'http://localhost/api/tle/?page=6&page-size=2' + ] + ], + [ + 'page' => 7, + 'expected' => [ + '@id' => 'http://localhost/api/tle/?page=7&page-size=2', + '@type' => 'PartialCollectionView', + 'first' => 'http://localhost/api/tle/?page=1&page-size=2', + 'previous' => 'http://localhost/api/tle/?page=6&page-size=2', + 'last' => 'http://localhost/api/tle/?page=6&page-size=2' + ] + ] + ]; + + public function testPaginationWorks(): void + { + foreach (self::TEST as $test) { + $response = $this->getCollectionContent($test['page'], 2); + + self::assertArrayHasKey('view', $response); + + $this->assertViewIsCorrect( + $test['expected'], + $response['view'] + ); + } + } + + public function testPaginationError(): void + { + $response = $this->getCollection(-1, 2); + self::assertEquals( + Response::HTTP_BAD_REQUEST, + $response->getStatusCode(), + 'Assert HTTP 400 is returned for page -1' + ); + + $response = $this->getCollection(0, 2); + self::assertEquals( + Response::HTTP_BAD_REQUEST, + $response->getStatusCode(), + 'Assert HTTP 400 is returned for page 0' + ); + + $response = $this->getCollection(1, -1); + self::assertEquals( + Response::HTTP_BAD_REQUEST, + $response->getStatusCode(), + 'Assert HTTP 400 is returned for page size -1' + ); + + $response = $this->getCollection(1, 0); + self::assertEquals( + Response::HTTP_BAD_REQUEST, + $response->getStatusCode(), + 'Assert HTTP 400 is returned for page size 0' + ); + } + + private function assertViewIsCorrect($expected, $actual): void + { + foreach ($actual as $key => $value) { + self::assertArrayHasKey($key, $expected, \sprintf('Assert view has key %s', $key)); + self::assertEquals($expected[$key], $value , \sprintf('Assert value of key %s is correct', $key)); + } + } + + /** @noinspection PhpSameParameterValueInspection */ + private function getCollectionContent(int $page, int $pageSize): array + { + return $this->toArray( + $this->getCollection($page, $pageSize) + ); + } + + private function getCollection(int $page, int $pageSize): Response + { + return $this->get( + '/api/tle/', + [ + 'page' => $page, + 'page-size' => $pageSize, + ] + ); + } +} diff --git a/tests/DocumentationTest.php b/tests/Controller/DocsControllerTest.php similarity index 58% rename from tests/DocumentationTest.php rename to tests/Controller/DocsControllerTest.php index fc3997a..a322506 100644 --- a/tests/DocumentationTest.php +++ b/tests/Controller/DocsControllerTest.php @@ -1,29 +1,24 @@ get('/api/tle/docs'); - - self::assertEquals(200, $response->getStatusCode(), 'Assert documentation is available'); - } - - public function testDocumentationIsCorrect(): void - { - $response = $this->get('/api/tle/json'); + $response = $this->get('/api/tle.json'); - self::assertEquals(200, $response->getStatusCode(), 'Assert json documentation is available'); + self::assertEquals(Response::HTTP_OK, $response->getStatusCode(), 'Assert json documentation is available'); $response = $this->toArray($response); $collectionSchema = $response['paths']['/api/tle']['get']['responses'][200]['content']['application/json']['schema']['properties']; $paginationSchema = $response['components']['schemas']['Pagination']['properties']; - $tleSchema = $response['components']['schemas']['TLE']['allOf'][0]['properties']; + $tleSchema = $response['components']['schemas']['TleModel']['allOf'][0]['properties']; $tle = TleFixtures::create(); @@ -32,7 +27,7 @@ public function testDocumentationIsCorrect(): void self::assertCount(\count($tleSchema), $response); self::assertEquals(array_keys($tleSchema), array_keys($response)); - $response = $this->toArray($this->get('/api/tle', ['page-size' => 2, 'page' => 2])); + $response = $this->toArray($this->get('/api/tle/', ['page-size' => 2, 'page' => 2])); self::assertCount(\count($paginationSchema), $response['view']); self::assertEquals(array_keys($paginationSchema), array_keys($response['view'])); @@ -40,4 +35,10 @@ public function testDocumentationIsCorrect(): void self::assertCount(\count($response), $collectionSchema); self::assertEquals(array_keys($response), array_keys($collectionSchema)); } -} \ No newline at end of file + + public function testHomepage(): void { + $response = $this->get('/api/tle/docs'); + + self::assertEmpty($response->getContent()); + } +} diff --git a/tests/Controller/PropagateControllerTest.php b/tests/Controller/PropagateControllerTest.php new file mode 100644 index 0000000..236e04e --- /dev/null +++ b/tests/Controller/PropagateControllerTest.php @@ -0,0 +1,111 @@ +get('/api/tle/0/propagate'); + + self::assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); + + $response = $this->toArray($response); + + self::assertEquals('Unable to find record with id 0', $response['response']['message']); + } + + public function testPropagateSGP4(): void + { + $tle = TleFixtures::create(); + + $response = $this->get( + '/api/tle/' . $tle->getId() . '/propagate', + [ + 'date' => '2021-04-26T17:49:45+02:00', + ] + ); + + self::assertEquals(Response::HTTP_OK, $response->getStatusCode()); + + $response = $this->toArray($response); + + self::assertEquals('https://www.w3.org/ns/hydra/context.jsonld', $response['@context']); + self::assertEquals('http://localhost/api/tle/43550/propagate?date=2021-04-26T17:49:45%2B02:00', $response['@id']); + self::assertEquals('SatellitePropagationResult', $response['@type']); + + self::assertArrayHasKey('tle', $response); + + self::assertEquals('SGP4', $response['algorithm']); + + self::assertEquals('ECI', $response['vector']['reference_frame']); + + self::assertEquals(3731.3677738358, $response['vector']['position']['x']); + self::assertEquals(-3929.0247024138, $response['vector']['position']['y']); + self::assertEquals(-3820.6175474185, $response['vector']['position']['z']); + self::assertEquals(6630.0421581948, $response['vector']['position']['r']); + self::assertEquals('km', $response['vector']['position']['unit']); + + self::assertEquals(2.2692661551689, $response['vector']['velocity']['x']); + self::assertEquals(6.1586427245624, $response['vector']['velocity']['y']); + self::assertEquals(-4.1239106928913, $response['vector']['velocity']['z']); + self::assertEquals(7.7514571852487, $response['vector']['velocity']['r']); + self::assertEquals('km/s', $response['vector']['velocity']['unit']); + + self::assertEquals(-35.362152001955, $response['geodetic']['latitude']); + self::assertEquals(221.21616992358, $response['geodetic']['longitude']); + self::assertEquals(259.03105001661, $response['geodetic']['altitude']); + + self::assertEquals(43550, $response['parameters']['satelliteId']); + self::assertEquals('2021-04-26T17:49:45+02:00', $response['parameters']['date']); + } + + public function testPropagateSDP4(): void + { + $tle = TleFixtures::createDeep(); + + $response = $this->get( + '/api/tle/' . $tle->getId() . '/propagate', + [ + 'date' => '2021-04-26T17:49:45+02:00', + ] + ); + + self::assertEquals(Response::HTTP_OK, $response->getStatusCode()); + + $response = $this->toArray($response); + + self::assertEquals('https://www.w3.org/ns/hydra/context.jsonld', $response['@context']); + self::assertEquals('http://localhost/api/tle/22049/propagate?date=2021-04-26T17:49:45%2B02:00', $response['@id']); + self::assertEquals('SatellitePropagationResult', $response['@type']); + + self::assertArrayHasKey('tle', $response); + + self::assertEquals('SDP4', $response['algorithm']); + + self::assertEquals('ECI', $response['vector']['reference_frame']); + + self::assertEquals(142825.54086031896, $response['vector']['position']['x']); + self::assertEquals(133973.34798843606, $response['vector']['position']['y']); + self::assertEquals(1303.6185230048, $response['vector']['position']['z']); + self::assertEquals(195830.7751976863, $response['vector']['position']['r']); + self::assertEquals('km', $response['vector']['position']['unit']); + + self::assertEquals(-0.51310326492624, $response['vector']['velocity']['x']); + self::assertEquals(0.5491989174236, $response['vector']['velocity']['y']); + self::assertEquals(0.60190735910381, $response['vector']['velocity']['z']); + self::assertEquals(0.96290543685273, $response['vector']['velocity']['r']); + self::assertEquals('km/s', $response['vector']['velocity']['unit']); + + self::assertEquals(0.38149611267203, $response['geodetic']['latitude']); + self::assertEquals(310.86248495862, $response['geodetic']['longitude']); + self::assertEquals(189452.64114393186, $response['geodetic']['altitude']); + + self::assertEquals(22049, $response['parameters']['satelliteId']); + self::assertEquals('2021-04-26T17:49:45+02:00', $response['parameters']['date']); + } +} diff --git a/tests/Controller/StatisticsControllerTest.php b/tests/Controller/StatisticsControllerTest.php new file mode 100644 index 0000000..86e91a4 --- /dev/null +++ b/tests/Controller/StatisticsControllerTest.php @@ -0,0 +1,16 @@ +get('/api/tle/hits'); + + self::assertEquals(Response::HTTP_OK, $response->getStatusCode()); + } +} diff --git a/tests/Controller/TleControllerTest.php b/tests/Controller/TleControllerTest.php new file mode 100644 index 0000000..59f2470 --- /dev/null +++ b/tests/Controller/TleControllerTest.php @@ -0,0 +1,53 @@ + 'tle:calculate', + '--tle' => TleFixtures::createDeep()->getId(), + ] + ); + + $application = new Application(static::$kernel); + $application->setAutoExit(false); + $application->run($input, new BufferedOutput()); + } + + public function testTleExtraFieldsMissingData(): void + { + $tle = TleFixtures::createDeep(); + + $response = $this->get('/api/tle/' . $tle->getId(), ['extra' => 1]); + + $response = $this->toArray($response); + + $this->assertTle($tle, $response); + } + + public function testTleExtraFields(): void + { + $tle = TleFixtures::create(); + + $response = $this->get('/api/tle/' . $tle->getId(), ['extra' => 1]); + + $response = $this->toArray($response); + + $this->assertTle($tle, $response); + } +} diff --git a/tests/ErrorPageTest.php b/tests/ErrorPageTest.php index fc7d0de..86481ab 100644 --- a/tests/ErrorPageTest.php +++ b/tests/ErrorPageTest.php @@ -1,21 +1,27 @@ -get('/noop'); - - self::assertEquals($response->getStatusCode(), 404, 'Assert page not found returns HTTP 404'); - - $response = $this->toArray($response); - - self::assertEquals( - 'No route found for "GET /noop"', - $response['response']['message'], - 'Assert correct response message' - ); - } -} \ No newline at end of file +get('/noop'); + + self::assertEquals( + Response::HTTP_NOT_FOUND, + $response->getStatusCode(), + 'Assert page not found returns HTTP 404' + ); + + $response = $this->toArray($response); + + self::assertEquals( + 'No route found for "GET http://localhost/noop"', + $response['response']['message'], + 'Assert correct response message' + ); + } +} diff --git a/tests/Service/SentryCallbackTest.php b/tests/Service/SentryCallbackTest.php new file mode 100644 index 0000000..5feac85 --- /dev/null +++ b/tests/Service/SentryCallbackTest.php @@ -0,0 +1,43 @@ +setExceptions( + [ + new ExceptionDataBag(new NotFoundHttpException()), + ] + ); + + self::assertNull($callback($event)); + } + + public function testOtherExceptionsForwarded(): void + { + $callback = new SentryCallbackBeforeSend(); + + $event = Event::createTransaction(); + + $event->setExceptions( + [ + new ExceptionDataBag(new \Exception()), + ] + ); + + /** @noinspection GetClassUsageInspection */ + self::assertEquals(Event::class, get_class($callback($event))); + } +} diff --git a/tests/TleModelTest.php b/tests/TleModelTest.php deleted file mode 100644 index de2a94b..0000000 --- a/tests/TleModelTest.php +++ /dev/null @@ -1,64 +0,0 @@ -getLine1(), $entity->getLine2(), $entity->getName()); - - static::assertEquals( - TleFixtures::$date, - $tle->getDate(), - 'Failed asserting TLE returned correct date' - ); - - static::assertEquals( - 0, - $tle->getChecksum(TleModel::LINE1), - 'Failed asserting TLE checksum for line1 is correct' - ); - - static::assertEquals( - 4, - $tle->getChecksum(TleModel::LINE2), - 'Failed asserting TLE checksum for line2 is correct' - ); - - static::assertEquals( - 0, - $tle->calculateChecksum(TleModel::LINE1), - 'Failed asserting TLE calculated checksum for line1 is correct' - ); - - static::assertEquals( - 4, - $tle->calculateChecksum(TleModel::LINE2), - 'Failed asserting TLE calculated checksum for line2 is correct' - ); - - static::assertEquals( - true, - $tle->verify(), - 'Failed asserting that TLE is correct' - ); - - static::assertEquals( - 43550, - $tle->getId(), - 'Failed asserting that TLE Satellite/Catalog number is correct' - ); - - static::assertEquals( - 'U', - $tle->getClassification(), - 'Failed asserting that TLE classification is correct' - ); - } -} diff --git a/tests/TleTest.php b/tests/TleTest.php index 3829923..0630b22 100644 --- a/tests/TleTest.php +++ b/tests/TleTest.php @@ -3,6 +3,7 @@ namespace App\Tests; use App\DataFixtures\TleFixtures; +use Symfony\Component\HttpFoundation\Response; final class TleTest extends AbstractWebTestCase { @@ -10,55 +11,59 @@ public function testTleSingleRecord(): void { $tle = TleFixtures::create(); - $response = $this->get('/api/tle/'.$tle->getId()); + $response = $this->get('/api/tle/' . $tle->getId()); - self::assertEquals(200, $response->getStatusCode()); + self::assertEquals(Response::HTTP_OK, $response->getStatusCode()); $response = $this->toArray($response); self::assertArrayHasKey('@id', $response); self::assertArrayHasKey('@type', $response); - self::assertArrayHasKey('satelliteId', $response); self::assertArrayHasKey('name', $response); self::assertArrayHasKey('date', $response); self::assertArrayHasKey('line1', $response); self::assertArrayHasKey('line2', $response); - self::assertEquals('http://localhost/api/tle/'.$tle->getId(), $response['@id']); + self::assertEquals('http://localhost/api/tle/' . $tle->getId(), $response['@id']); self::assertEquals('TleModel', $response['@type']); - self::assertEquals($tle->getId(), $response['satelliteId']); self::assertEquals($tle->getName(), $response['name']); self::assertEquals(TleFixtures::$date, $response['date']); self::assertEquals($tle->getLine1(), $response['line1']); self::assertEquals($tle->getLine2(), $response['line2']); } + public function testTleRecordNotFound(): void + { + $response = $this->get('/api/tle/0'); + self::assertEquals(Response::HTTP_NOT_FOUND, $response->getStatusCode()); + } + public function testTleCollectionRecord(): void { $pageSize = 2; $response = $this->get( - '/api/tle', + '/api/tle/', [ 'page-size' => $pageSize, ] ); - self::assertEquals(200, $response->getStatusCode()); + self::assertEquals(Response::HTTP_OK, $response->getStatusCode()); $response = $this->toArray($response); self::assertArrayHasKey('@context', $response); - self::assertEquals($response['@context'], 'http://www.w3.org/ns/hydra/context.jsonld'); + self::assertEquals('https://www.w3.org/ns/hydra/context.jsonld', $response['@context']); self::assertArrayHasKey('@id', $response); - self::assertEquals($response['@id'], 'http://localhost/api/tle'); + self::assertEquals('http://localhost/api/tle/', $response['@id']); self::assertArrayHasKey('@type', $response); - self::assertEquals($response['@type'], 'Collection'); + self::assertEquals('Collection', $response['@type']); self::assertArrayHasKey('totalItems', $response); - self::assertEquals($response['totalItems'], 10); + self::assertEquals(11, $response['totalItems']); self::assertArrayHasKey('member', $response); self::assertEquals(\count($response['member']), $pageSize); @@ -67,16 +72,16 @@ public function testTleCollectionRecord(): void $parameters = $response['parameters']; self::assertArrayHasKey('search', $parameters); - self::assertEquals($parameters['search'], '*'); + self::assertEquals('*', $parameters['search']); self::assertArrayHasKey('sort', $parameters); - self::assertEquals($parameters['sort'], 'name'); + self::assertEquals('popularity', $parameters['sort']); self::assertArrayHasKey('sort-dir', $parameters); - self::assertEquals($parameters['sort-dir'], 'asc'); + self::assertEquals('desc', $parameters['sort-dir']); self::assertArrayHasKey('page', $parameters); - self::assertEquals($parameters['page'], 1); + self::assertEquals(1, $parameters['page']); self::assertArrayHasKey('page-size', $parameters); self::assertEquals($parameters['page-size'], $pageSize);