From 08757016722e7a6f63367c78371d27786a620a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Zrn=C3=ADk?= Date: Fri, 22 Oct 2021 16:05:54 +0200 Subject: [PATCH] rewritten fetcher (now dispenser) phpstan bleeding edge --- LICENSE.md | 13 +- README.md | 33 +- composer.lock | 5140 ++++++++--------- docs/install-and-config.md | 11 +- docs/usage-factory-installable.md | 48 +- docs/usage-orm.md | 45 +- docs/usage-updater.md | 37 +- examples/Accounts/Pure/AccountFactory.php | 23 +- examples/Accounts/Pure/AccountTable.sql | 7 +- examples/Accounts/Updater/AccountFactory.php | 27 +- examples/updater-usage-1.php | 2 +- examples/updater-usage-2.php | 2 +- examples/updater-usage-3-c.php | 3 +- examples/updater-usage-3-w.php | 3 +- examples/updater-usage-4.php | 3 +- examples/updater-usage-5.php | 3 +- examples/usage-factory-installable-1.php | 2 +- examples/usage-factory-orm-1.php | 2 +- phpstan.neon | 2 + src/Column.php | 4 +- ...ForeignKeysTargetingSameClassException.php | 30 + src/Queries/Makers/QueryMakerMySQL.php | 2 +- src/Repository/BaseEntity.php | 68 +- src/Repository/BaseRepository.php | 35 +- src/Repository/Fetch/CompletionBuilder.php | 67 + src/Repository/Fetch/CompletionIndication.php | 37 + src/Repository/Fetch/CompletionKeyValues.php | 45 + src/Repository/Fetch/Dispenser.php | 50 + src/Repository/Fetch/EntityStorage.php | 135 + src/Repository/Fetch/FetchQuery.php | 94 + src/Repository/Fetch/ResultService.php | 135 + src/Repository/Fetcher/FetchResult.php | 337 -- src/Repository/Fetcher/FetchSql.php | 37 - src/Repository/Fetcher/Fetcher.php | 168 - src/Repository/Saver/Saver.php | 39 +- src/Tracy/Measure.php | 84 +- src/Tracy/Panel.php | 68 +- src/Updater.php | 6 +- .../EntityReflection/EntityReflection.php | 10 +- .../EntityReflection/FetchArrayData.php | 2 +- .../EntityReflection/ForeignKeyData.php | 8 +- src/Utils.php | 18 +- tests/IntegrationTest.php | 60 +- .../ReferencedClassOne.php | 14 + .../ReferencedClassTwo.php | 14 + .../ReferencingBothIsOk.php | 23 + .../ReferencingSameMultipleTimeNotOK.php | 23 + tests/Repository/BaseEntityTest.php | 15 + .../FetcherMock/Entities/Manufacturer.php | 2 + tests/Repository/Fetcher/FetcherTest.php | 18 +- tests/TableTest.php | 3 +- tests/UtilsTest.php | 2 +- tests/createTest.md | 9 +- 53 files changed, 3630 insertions(+), 3438 deletions(-) create mode 100644 src/Exceptions/MultipleForeignKeysTargetingSameClassException.php create mode 100644 src/Repository/Fetch/CompletionBuilder.php create mode 100644 src/Repository/Fetch/CompletionIndication.php create mode 100644 src/Repository/Fetch/CompletionKeyValues.php create mode 100644 src/Repository/Fetch/Dispenser.php create mode 100644 src/Repository/Fetch/EntityStorage.php create mode 100644 src/Repository/Fetch/FetchQuery.php create mode 100644 src/Repository/Fetch/ResultService.php delete mode 100644 src/Repository/Fetcher/FetchResult.php delete mode 100644 src/Repository/Fetcher/FetchSql.php delete mode 100644 src/Repository/Fetcher/Fetcher.php create mode 100644 tests/Mock/BaseRepositoryAndBaseEntity/Entities/BadEntities/OnlyOneForeignKeyTargetingSameClass/ReferencedClassOne.php create mode 100644 tests/Mock/BaseRepositoryAndBaseEntity/Entities/BadEntities/OnlyOneForeignKeyTargetingSameClass/ReferencedClassTwo.php create mode 100644 tests/Mock/BaseRepositoryAndBaseEntity/Entities/BadEntities/OnlyOneForeignKeyTargetingSameClass/ReferencingBothIsOk.php create mode 100644 tests/Mock/BaseRepositoryAndBaseEntity/Entities/BadEntities/OnlyOneForeignKeyTargetingSameClass/ReferencingSameMultipleTimeNotOK.php diff --git a/LICENSE.md b/LICENSE.md index 1dd42c5..23960b5 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,14 @@ Copyright 2020 Štěpán Zrník -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 5a7fc1d..f2cbda0 100644 --- a/README.md +++ b/README.md @@ -6,29 +6,24 @@ ![Packagist Version](https://img.shields.io/packagist/v/zrnik/mksql) ### What is it? -*So, I just found out that the thing I created -is usually called an ORM.* -**MkSQL** is a tool for keeping your tables up to -date with PHP code. It aims for a simple use cases, -so it cannot handle very complex stuff. Explore the -docs to see what is possible. +*So, I just found out that the thing I created is usually called an ORM.* -This package simply allows you to define entities, -that represent your database tables, and automatically -creates them for you. +**MkSQL** is a tool for keeping your tables up to date with PHP code. It aims for a simple use cases, so it cannot +handle very complex stuff. Explore the docs to see what is possible. -You can also skip the `ORM` part and use `Updater` class -to create your database without any entities, instead -of creating them with Adminer *(or PHPMyAdmin)*. +This package simply allows you to define entities, that represent your database tables, and automatically creates them +for you. + +You can also skip the `ORM` part and use `Updater` class to create your database without any entities, instead of +creating them with Adminer *(or PHPMyAdmin)*. Documentation index is in [docs/index.md](docs/index.md) file. #### Requirements -This package **requires** you to run it with PHP 8+, as it uses -the new stuff this version delivers. Mainly attributes and -promoted constructor properties. +This package **requires** you to run it with PHP 8+, as it uses the new stuff this version delivers. Mainly attributes +and promoted constructor properties. ```json { @@ -49,20 +44,20 @@ promoted constructor properties. Read more at [Installation and Configuration](docs/install-and-config.md) page. -#### Supported Drivers: +#### Supported Drivers: - [✅ MySQL](https://www.mysql.com) (Compatible with MariaDB) - [✅ SQLite 3](https://www.sqlite.org/index.html) - + #### This package contains a [Tracy](https://tracy.nette.org/en/) panel Add this to your bootstrap file: + ```php Tracy\Debugger::getBar()->addPanel(new \Zrnik\MkSQL\Tracy\Panel()); ``` -Or, if you are using [Nette Framework](https://nette.org/en/), -register it in your configuration file: +Or, if you are using [Nette Framework](https://nette.org/en/), register it in your configuration file: ```neon tracy: diff --git a/composer.lock b/composer.lock index 721edd3..a47dfc5 100644 --- a/composer.lock +++ b/composer.lock @@ -1,2645 +1,2645 @@ { - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "8d7506a9cc57acd7cc11f02ddd2da64a", - "packages": [ - { - "name": "jetbrains/phpstorm-attributes", - "version": "1.0", - "source": { - "type": "git", - "url": "https://github.com/JetBrains/phpstorm-attributes.git", - "reference": "a7a83ae5df4dd3c0875484483de19de8edf60a9f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-attributes/zipball/a7a83ae5df4dd3c0875484483de19de8edf60a9f", - "reference": "a7a83ae5df4dd3c0875484483de19de8edf60a9f", - "shasum": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "JetBrains\\PhpStorm\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "JetBrains", - "homepage": "https://www.jetbrains.com" - } - ], - "description": "PhpStorm specific attributes", - "keywords": [ - "attributes", - "jetbrains", - "phpstorm" - ], - "support": { - "issues": "https://youtrack.jetbrains.com/newIssue?project=WI", - "source": "https://github.com/JetBrains/phpstorm-attributes/tree/1.0" - }, - "time": "2020-11-17T11:09:47+00:00" - }, + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "8d7506a9cc57acd7cc11f02ddd2da64a", + "packages": [ + { + "name": "jetbrains/phpstorm-attributes", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/JetBrains/phpstorm-attributes.git", + "reference": "a7a83ae5df4dd3c0875484483de19de8edf60a9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JetBrains/phpstorm-attributes/zipball/a7a83ae5df4dd3c0875484483de19de8edf60a9f", + "reference": "a7a83ae5df4dd3c0875484483de19de8edf60a9f", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "JetBrains\\PhpStorm\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ { - "name": "nette/utils", - "version": "v3.2.5", - "source": { - "type": "git", - "url": "https://github.com/nette/utils.git", - "reference": "9cd80396ca58d7969ab44fc7afcf03624dfa526e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/9cd80396ca58d7969ab44fc7afcf03624dfa526e", - "reference": "9cd80396ca58d7969ab44fc7afcf03624dfa526e", - "shasum": "" - }, - "require": { - "php": ">=7.2 <8.2" - }, - "conflict": { - "nette/di": "<3.0.6" - }, - "require-dev": { - "nette/tester": "~2.0", - "phpstan/phpstan": "^0.12", - "tracy/tracy": "^2.3" - }, - "suggest": { - "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", - "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", - "ext-json": "to use Nette\\Utils\\Json", - "ext-mbstring": "to use Strings::lower() etc...", - "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()", - "ext-xml": "to use Strings::length() etc. when mbstring is not available" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", - "homepage": "https://nette.org", - "keywords": [ - "array", - "core", - "datetime", - "images", - "json", - "nette", - "paginator", - "password", - "slugify", - "string", - "unicode", - "utf-8", - "utility", - "validation" - ], - "support": { - "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v3.2.5" - }, - "time": "2021-09-20T10:50:11+00:00" - }, + "name": "JetBrains", + "homepage": "https://www.jetbrains.com" + } + ], + "description": "PhpStorm specific attributes", + "keywords": [ + "attributes", + "jetbrains", + "phpstorm" + ], + "support": { + "issues": "https://youtrack.jetbrains.com/newIssue?project=WI", + "source": "https://github.com/JetBrains/phpstorm-attributes/tree/1.0" + }, + "time": "2020-11-17T11:09:47+00:00" + }, + { + "name": "nette/utils", + "version": "v3.2.5", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "9cd80396ca58d7969ab44fc7afcf03624dfa526e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/9cd80396ca58d7969ab44fc7afcf03624dfa526e", + "reference": "9cd80396ca58d7969ab44fc7afcf03624dfa526e", + "shasum": "" + }, + "require": { + "php": ">=7.2 <8.2" + }, + "conflict": { + "nette/di": "<3.0.6" + }, + "require-dev": { + "nette/tester": "~2.0", + "phpstan/phpstan": "^0.12", + "tracy/tracy": "^2.3" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ { - "name": "zrnik/enum", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/Zrnik/Enum.git", - "reference": "f1b9e5dd18face5273e25e9f5e8428cbb48b57fd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Zrnik/Enum/zipball/f1b9e5dd18face5273e25e9f5e8428cbb48b57fd", - "reference": "f1b9e5dd18face5273e25e9f5e8428cbb48b57fd", - "shasum": "" - }, - "require": { - "php": ">=7.4" - }, - "require-dev": { - "phpunit/phpunit": "^9", - "tracy/tracy": "^v2.7.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Zrnik\\Base\\": "src/", - "ExampleEnums\\": "tests/Examples" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Štěpán Zrník", - "email": "stepan@zrnik.eu", - "homepage": "https://stepan.zrnik.eu/" - } - ], - "description": "Solution for almost 12 years old Stack Overflow question I returned many times to, is finally packed and ready to require!", - "support": { - "issues": "https://github.com/Zrnik/Enum/issues", - "source": "https://github.com/Zrnik/Enum/tree/v1.0.0" - }, - "time": "2020-09-17T20:18:35+00:00" - } - ], - "packages-dev": [ - { - "name": "brick/date-time", - "version": "0.3.2", - "source": { - "type": "git", - "url": "https://github.com/brick/date-time.git", - "reference": "b4e45bf9dc37f03a12c41b5446474a07c5fc7f39" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/brick/date-time/zipball/b4e45bf9dc37f03a12c41b5446474a07c5fc7f39", - "reference": "b4e45bf9dc37f03a12c41b5446474a07c5fc7f39", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^7.5.15 || ^8.0 || ^9.0", - "vimeo/psalm": "4.4.1" - }, - "suggest": { - "ext-timezonedb": "This PECL extension provides up-to-date timezone information" - }, - "type": "library", - "autoload": { - "psr-4": { - "Brick\\DateTime\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Date and time library", - "keywords": [ - "brick", - "date", - "datetime", - "time" - ], - "support": { - "issues": "https://github.com/brick/date-time/issues", - "source": "https://github.com/brick/date-time/tree/0.3.2" - }, - "funding": [ - { - "url": "https://github.com/BenMorel", - "type": "github" - } - ], - "time": "2021-06-30T17:11:38+00:00" + "name": "David Grudl", + "homepage": "https://davidgrudl.com" }, { - "name": "doctrine/instantiator", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^8.0", - "ext-pdo": "*", - "ext-phar": "*", - "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", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "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": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v3.2.5" + }, + "time": "2021-09-20T10:50:11+00:00" + }, + { + "name": "zrnik/enum", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/Zrnik/Enum.git", + "reference": "f1b9e5dd18face5273e25e9f5e8428cbb48b57fd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Zrnik/Enum/zipball/f1b9e5dd18face5273e25e9f5e8428cbb48b57fd", + "reference": "f1b9e5dd18face5273e25e9f5e8428cbb48b57fd", + "shasum": "" + }, + "require": { + "php": ">=7.4" + }, + "require-dev": { + "phpunit/phpunit": "^9", + "tracy/tracy": "^v2.7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Zrnik\\Base\\": "src/", + "ExampleEnums\\": "tests/Examples" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ { - "name": "myclabs/deep-copy", - "version": "1.10.2", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "replace": { - "myclabs/deep-copy": "self.version" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2020-11-13T09:40:50+00:00" - }, + "name": "Štěpán Zrník", + "email": "stepan@zrnik.eu", + "homepage": "https://stepan.zrnik.eu/" + } + ], + "description": "Solution for almost 12 years old Stack Overflow question I returned many times to, is finally packed and ready to require!", + "support": { + "issues": "https://github.com/Zrnik/Enum/issues", + "source": "https://github.com/Zrnik/Enum/tree/v1.0.0" + }, + "time": "2020-09-17T20:18:35+00:00" + } + ], + "packages-dev": [ + { + "name": "brick/date-time", + "version": "0.3.2", + "source": { + "type": "git", + "url": "https://github.com/brick/date-time.git", + "reference": "b4e45bf9dc37f03a12c41b5446474a07c5fc7f39" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/date-time/zipball/b4e45bf9dc37f03a12c41b5446474a07c5fc7f39", + "reference": "b4e45bf9dc37f03a12c41b5446474a07c5fc7f39", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^7.5.15 || ^8.0 || ^9.0", + "vimeo/psalm": "4.4.1" + }, + "suggest": { + "ext-timezonedb": "This PECL extension provides up-to-date timezone information" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\DateTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Date and time library", + "keywords": [ + "brick", + "date", + "datetime", + "time" + ], + "support": { + "issues": "https://github.com/brick/date-time/issues", + "source": "https://github.com/brick/date-time/tree/0.3.2" + }, + "funding": [ { - "name": "nette/neon", - "version": "v3.2.2", - "source": { - "type": "git", - "url": "https://github.com/nette/neon.git", - "reference": "e4ca6f4669121ca6876b1d048c612480e39a28d5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/neon/zipball/e4ca6f4669121ca6876b1d048c612480e39a28d5", - "reference": "e4ca6f4669121ca6876b1d048c612480e39a28d5", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": ">=7.1" - }, - "require-dev": { - "nette/tester": "^2.0", - "phpstan/phpstan": "^0.12", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🍸 Nette NEON: encodes and decodes NEON file format.", - "homepage": "https://ne-on.org", - "keywords": [ - "export", - "import", - "neon", - "nette", - "yaml" - ], - "support": { - "issues": "https://github.com/nette/neon/issues", - "source": "https://github.com/nette/neon/tree/v3.2.2" - }, - "time": "2021-02-28T12:30:32+00:00" - }, + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2021-06-30T17:11:38+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^8.0", + "ext-pdo": "*", + "ext-phar": "*", + "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", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ { - "name": "nikic/php-parser", - "version": "v4.13.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0" - }, - "time": "2021-09-20T12:20:58+00:00" - }, + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + }, + "funding": [ { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" }, { - "name": "phar-io/version", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "bae7c545bef187884426f042434e561ab1ddb182" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", - "reference": "bae7c545bef187884426f042434e561ab1ddb182", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.1.0" - }, - "time": "2021-02-23T14:00:09+00:00" + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" }, { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-11-10T18:47:58+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.10.2", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + }, + "funding": [ { - "name": "phpdocumentor/reflection-docblock", - "version": "5.2.2", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" - }, - "time": "2020-09-03T19:13:55+00:00" - }, + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2020-11-13T09:40:50+00:00" + }, + { + "name": "nette/neon", + "version": "v3.2.2", + "source": { + "type": "git", + "url": "https://github.com/nette/neon.git", + "reference": "e4ca6f4669121ca6876b1d048c612480e39a28d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/neon/zipball/e4ca6f4669121ca6876b1d048c612480e39a28d5", + "reference": "e4ca6f4669121ca6876b1d048c612480e39a28d5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.0", + "phpstan/phpstan": "^0.12", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ { - "name": "phpdocumentor/type-resolver", - "version": "1.5.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/a12f7e301eb7258bb68acd89d4aefa05c2906cae", - "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.5.1" - }, - "time": "2021-10-02T14:08:47+00:00" + "name": "David Grudl", + "homepage": "https://davidgrudl.com" }, { - "name": "phpspec/prophecy", - "version": "1.14.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", - "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.2", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/1.14.0" - }, - "time": "2021-09-10T09:02:12+00:00" - }, + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🍸 Nette NEON: encodes and decodes NEON file format.", + "homepage": "https://ne-on.org", + "keywords": [ + "export", + "import", + "neon", + "nette", + "yaml" + ], + "support": { + "issues": "https://github.com/nette/neon/issues", + "source": "https://github.com/nette/neon/tree/v3.2.2" + }, + "time": "2021-02-28T12:30:32+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.13.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "50953a2691a922aa1769461637869a0a2faa3f53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53", + "reference": "50953a2691a922aa1769461637869a0a2faa3f53", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ { - "name": "phpstan/phpstan", - "version": "0.12.99", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "b4d40f1d759942f523be267a1bab6884f46ca3f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b4d40f1d759942f523be267a1bab6884f46ca3f7", - "reference": "b4d40f1d759942f523be267a1bab6884f46ca3f7", - "shasum": "" - }, - "require": { - "php": "^7.1|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.12-dev" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "support": { - "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/0.12.99" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - }, - { - "url": "https://www.patreon.com/phpstan", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" - } - ], - "time": "2021-09-12T20:09:55+00:00" - }, + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0" + }, + "time": "2021-09-20T12:20:58+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ { - "name": "phpstan/phpstan-phpunit", - "version": "0.12.22", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "7c01ef93bf128b4ac8bdad38c54b2a4fd6b0b3cc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/7c01ef93bf128b4ac8bdad38c54b2a4fd6b0b3cc", - "reference": "7c01ef93bf128b4ac8bdad38c54b2a4fd6b0b3cc", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0", - "phpstan/phpstan": "^0.12.92" - }, - "conflict": { - "phpunit/phpunit": "<7.0" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-strict-rules": "^0.12.6", - "phpunit/phpunit": "^9.5" - }, - "type": "phpstan-extension", - "extra": { - "branch-alias": { - "dev-master": "0.12-dev" - }, - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPUnit extensions and rules for PHPStan", - "support": { - "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/0.12.22" - }, - "time": "2021-08-12T10:53:43+00:00" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "name": "phpunit/php-code-coverage", - "version": "9.2.7", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d4c798ed8d51506800b441f7a13ecb0f76f12218", - "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.12.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.7" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-09-17T05:39:03+00:00" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" }, { - "name": "phpunit/php-file-iterator", - "version": "3.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:57:25+00:00" - }, + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "bae7c545bef187884426f042434e561ab1ddb182" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", + "reference": "bae7c545bef187884426f042434e561ab1ddb182", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" }, { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.1.0" + }, + "time": "2021-02-23T14:00:09+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.2.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" }, { - "name": "phpunit/phpunit", - "version": "9.5.10", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c814a05837f2edb0d1471d6e3f4ab3501ca3899a", - "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.7", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3.4", - "sebastian/version": "^3.0.2" - }, - "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.5-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ], - "files": [ - "src/Framework/Assert/Functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.10" - }, - "funding": [ - { - "url": "https://phpunit.de/donate.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-09-25T07:38:51+00:00" + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + }, + "time": "2020-09-03T19:13:55+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/a12f7e301eb7258bb68acd89d4aefa05c2906cae", + "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.5.1" + }, + "time": "2021-10-02T14:08:47+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.14.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", + "reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.2", + "php": "^7.2 || ~8.0, <8.2", + "phpdocumentor/reflection-docblock": "^5.2", + "sebastian/comparator": "^3.0 || ^4.0", + "sebastian/recursion-context": "^3.0 || ^4.0" + }, + "require-dev": { + "phpspec/phpspec": "^6.0 || ^7.0", + "phpunit/phpunit": "^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" }, { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/1.14.0" + }, + "time": "2021-09-10T09:02:12+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "0.12.99", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "b4d40f1d759942f523be267a1bab6884f46ca3f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b4d40f1d759942f523be267a1bab6884f46ca3f7", + "reference": "b4d40f1d759942f523be267a1bab6884f46ca3f7", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.12-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/0.12.99" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" }, { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" + "url": "https://github.com/phpstan", + "type": "github" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" + "url": "https://www.patreon.com/phpstan", + "type": "patreon" }, { - "name": "sebastian/comparator", - "version": "4.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:49:45+00:00" + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2021-09-12T20:09:55+00:00" + }, + { + "name": "phpstan/phpstan-phpunit", + "version": "0.12.22", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-phpunit.git", + "reference": "7c01ef93bf128b4ac8bdad38c54b2a4fd6b0b3cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/7c01ef93bf128b4ac8bdad38c54b2a4fd6b0b3cc", + "reference": "7c01ef93bf128b4ac8bdad38c54b2a4fd6b0b3cc", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "phpstan/phpstan": "^0.12.92" + }, + "conflict": { + "phpunit/phpunit": "<7.0" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-strict-rules": "^0.12.6", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "branch-alias": { + "dev-master": "0.12-dev" }, + "phpstan": { + "includes": [ + "extension.neon", + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPUnit extensions and rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-phpunit/issues", + "source": "https://github.com/phpstan/phpstan-phpunit/tree/0.12.22" + }, + "time": "2021-08-12T10:53:43+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d4c798ed8d51506800b441f7a13ecb0f76f12218", + "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.12.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "*", + "ext-xdebug": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.7" + }, + "funding": [ { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-09-17T05:39:03+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", + "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:57:25+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.5.10", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c814a05837f2edb0d1471d6e3f4ab3501ca3899a", + "reference": "c814a05837f2edb0d1471d6e3f4ab3501ca3899a", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpspec/prophecy": "^1.12.1", + "phpunit/php-code-coverage": "^9.2.7", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.5", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.3", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^2.3.4", + "sebastian/version": "^3.0.2" + }, + "require-dev": { + "ext-pdo": "*", + "phpspec/prophecy-phpunit": "^2.0.1" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ], + "files": [ + "src/Framework/Assert/Functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.10" + }, + "funding": [ + { + "url": "https://phpunit.de/donate.html", + "type": "custom" }, { - "name": "sebastian/diff", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:10:38+00:00" + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-09-25T07:38:51+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:08:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", + "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "sebastian/environment", - "version": "5.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:52:38+00:00" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "sebastian/exporter", - "version": "4.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:24:23+00:00" + "name": "Volker Dusch", + "email": "github@wallbash.com" }, { - "name": "sebastian/global-state", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-06-11T13:31:12+00:00" + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:49:45+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:10:38+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "388b6ced16caa751030f6a69e588299fa09200ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", + "reference": "388b6ced16caa751030f6a69e588299fa09200ac", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:52:38+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", + "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" + "name": "Volker Dusch", + "email": "github@wallbash.com" }, { - "name": "sebastian/recursion-context", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:17:30+00:00" + "name": "Adam Harvey", + "email": "aharvey@php.net" }, { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:24:23+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49", + "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-06-11T13:31:12+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.6", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-28T06:42:11+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "sebastian/type", - "version": "2.3.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/2.3.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-06-15T12:49:02+00:00" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:17:30+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" + }, + { + "name": "sebastian/type", + "version": "2.3.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914", + "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/2.3.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-06-15T12:49:02+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.23.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", + "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-ctype": "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\\Ctype\\": "" }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ { - "name": "symfony/polyfill-ctype", - "version": "v1.23.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-ctype": "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\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/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": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { - "name": "theseer/tokenizer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2021-07-28T10:34:58+00:00" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "name": "tracy/tracy", - "version": "v2.8.7", - "source": { - "type": "git", - "url": "https://github.com/nette/tracy.git", - "reference": "8e708de7c611f626c8792d43f1c78812ea24e6f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/tracy/zipball/8e708de7c611f626c8792d43f1c78812ea24e6f6", - "reference": "8e708de7c611f626c8792d43f1c78812ea24e6f6", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-session": "*", - "php": ">=7.2 <8.2" - }, - "conflict": { - "nette/di": "<3.0" - }, - "require-dev": { - "latte/latte": "^2.5", - "nette/di": "^3.0", - "nette/mail": "^3.0", - "nette/tester": "^2.2", - "nette/utils": "^3.0", - "phpstan/phpstan": "^0.12", - "psr/log": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "classmap": [ - "src" - ], - "files": [ - "src/Tracy/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.", - "homepage": "https://tracy.nette.org", - "keywords": [ - "Xdebug", - "debug", - "debugger", - "nette", - "profiler" - ], - "support": { - "issues": "https://github.com/nette/tracy/issues", - "source": "https://github.com/nette/tracy/tree/v2.8.7" - }, - "time": "2021-08-24T16:26:27+00:00" + "url": "https://github.com/fabpot", + "type": "github" }, { - "name": "webmozart/assert", - "version": "1.10.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.10.0" - }, - "time": "2021-03-09T10:59:23+00:00" + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-02-19T12:13:01+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + }, + { + "name": "tracy/tracy", + "version": "v2.8.7", + "source": { + "type": "git", + "url": "https://github.com/nette/tracy.git", + "reference": "8e708de7c611f626c8792d43f1c78812ea24e6f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/tracy/zipball/8e708de7c611f626c8792d43f1c78812ea24e6f6", + "reference": "8e708de7c611f626c8792d43f1c78812ea24e6f6", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-session": "*", + "php": ">=7.2 <8.2" + }, + "conflict": { + "nette/di": "<3.0" + }, + "require-dev": { + "latte/latte": "^2.5", + "nette/di": "^3.0", + "nette/mail": "^3.0", + "nette/tester": "^2.2", + "nette/utils": "^3.0", + "phpstan/phpstan": "^0.12", + "psr/log": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "classmap": [ + "src" + ], + "files": [ + "src/Tracy/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" }, { - "name": "zrnik/phpunit-exceptions", - "version": "v0.0.3", - "source": { - "type": "git", - "url": "https://github.com/Zrnik/PHPUnit-Exceptions.git", - "reference": "9549d2b473c75ce345b581bc0aff37b34d22f08f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Zrnik/PHPUnit-Exceptions/zipball/9549d2b473c75ce345b581bc0aff37b34d22f08f", - "reference": "9549d2b473c75ce345b581bc0aff37b34d22f08f", - "shasum": "" - }, - "require": { - "php": ">=7.4|>=8.0", - "phpunit/phpunit": "^9" - }, - "require-dev": { - "phpstan/phpstan": "^0.12", - "roave/security-advisories": "dev-latest" - }, - "type": "library", - "autoload": { - "psr-4": { - "Zrnik\\PHPUnit\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Štěpán Zrník", - "email": "stepan.zrnik@gmail.com" - } - ], - "description": "Trait for easier exception testing in PHPUnit.", - "support": { - "issues": "https://github.com/Zrnik/PHPUnit-Exceptions/issues", - "source": "https://github.com/Zrnik/PHPUnit-Exceptions/tree/v0.0.3" - }, - "time": "2021-10-13T10:42:23+00:00" - } - ], - "aliases": [], - "minimum-stability": "dev", - "stability-flags": [], - "prefer-stable": true, - "prefer-lowest": false, - "platform": { - "php": ">=8.0", - "ext-pdo": "*" + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.", + "homepage": "https://tracy.nette.org", + "keywords": [ + "Xdebug", + "debug", + "debugger", + "nette", + "profiler" + ], + "support": { + "issues": "https://github.com/nette/tracy/issues", + "source": "https://github.com/nette/tracy/tree/v2.8.7" + }, + "time": "2021-08-24T16:26:27+00:00" }, - "platform-dev": [], - "plugin-api-version": "2.1.0" + { + "name": "webmozart/assert", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.10.0" + }, + "time": "2021-03-09T10:59:23+00:00" + }, + { + "name": "zrnik/phpunit-exceptions", + "version": "v0.0.3", + "source": { + "type": "git", + "url": "https://github.com/Zrnik/PHPUnit-Exceptions.git", + "reference": "9549d2b473c75ce345b581bc0aff37b34d22f08f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Zrnik/PHPUnit-Exceptions/zipball/9549d2b473c75ce345b581bc0aff37b34d22f08f", + "reference": "9549d2b473c75ce345b581bc0aff37b34d22f08f", + "shasum": "" + }, + "require": { + "php": ">=7.4|>=8.0", + "phpunit/phpunit": "^9" + }, + "require-dev": { + "phpstan/phpstan": "^0.12", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "autoload": { + "psr-4": { + "Zrnik\\PHPUnit\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Štěpán Zrník", + "email": "stepan.zrnik@gmail.com" + } + ], + "description": "Trait for easier exception testing in PHPUnit.", + "support": { + "issues": "https://github.com/Zrnik/PHPUnit-Exceptions/issues", + "source": "https://github.com/Zrnik/PHPUnit-Exceptions/tree/v0.0.3" + }, + "time": "2021-10-13T10:42:23+00:00" + } + ], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": ">=8.0", + "ext-pdo": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.1.0" } diff --git a/docs/install-and-config.md b/docs/install-and-config.md index 6d58c96..857abe8 100644 --- a/docs/install-and-config.md +++ b/docs/install-and-config.md @@ -1,13 +1,12 @@ # Installation -As it's written in [README.md](../README.md), you should install this -package with composer command `composer require zrnik/mksql`. Other -installation methods are **not supported**. + +As it's written in [README.md](../README.md), you should install this package with composer +command `composer require zrnik/mksql`. Other installation methods are **not supported**. # Configuration -There is not much to configure, the only thing you need, is `Updater` -instance with `PDO` as a parameter. Annotating entities (`ORM`) is -on [ORM Usage](usage-orm.md) page. +There is not much to configure, the only thing you need, is `Updater` +instance with `PDO` as a parameter. Annotating entities (`ORM`) is on [ORM Usage](usage-orm.md) page. Continue: [Updater Usage](usage-updater.md) diff --git a/docs/usage-factory-installable.md b/docs/usage-factory-installable.md index 669fb2e..582cdc2 100644 --- a/docs/usage-factory-installable.md +++ b/docs/usage-factory-installable.md @@ -1,11 +1,11 @@ # Factory usage & Installable class -There is definitely a class structure, that has a factory, which is -creating for example account objects, then you have the account class, -and probably some SQL file we must execute to install the table -and make everything working. For a "little" example, it might look like this: +There is definitely a class structure, that has a factory, which is creating for example account objects, then you have +the account class, and probably some SQL file we must execute to install the table and make everything working. For a " +little" example, it might look like this: *File: AccountFactory.php* + ```php class AccountFactory { @@ -64,7 +64,9 @@ class AccountFactory { } } ``` + *File: Account.php* + ```php class Account { @@ -102,7 +104,9 @@ class Account } } ``` + *File: AccountTable.sql* (your database installation file) + ```sql CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT, @@ -114,20 +118,16 @@ CREATE TABLE `account` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ``` -That must be a pain to write so much stuff for each class -we would like to create. And I am not even talking about a -case when you want to add new column to the account table, -writing an alter query to the sql file and editing all the +That must be a pain to write so much stuff for each class we would like to create. And I am not even talking about a +case when you want to add new column to the account table, writing an alter query to the sql file and editing all the queries in save/fetch methods... Damn... So what can **MkSQL** help you with? ## Use updater instead of the `.sql` file! -We can omit the `AccountTable.sql` entirely by using the updater. -File `Account.php` will stay the same for now -(more in the [ORM Usage](usage-orm.md) section), -but we will change `AccountFactory.php` like this: +We can omit the `AccountTable.sql` entirely by using the updater. File `Account.php` will stay the same for now +(more in the [ORM Usage](usage-orm.md) section), but we will change `AccountFactory.php` like this: ```php private static bool $installed = false; @@ -180,15 +180,12 @@ but we will change `AccountFactory.php` like this: } ``` -This helped two things, the table `account` is created automatically and -is also automatically updated when you change it. It means we don't need -to update database manually when we are updating our website. How about -adding new column to the `account` table now? Much better on the database -side, but still pain. +This helped two things, the table `account` is created automatically and is also automatically updated when you change +it. It means we don't need to update database manually when we are updating our website. How about adding new column to +the `account` table now? Much better on the database side, but still pain. Also, the code is still ugly and who would like to have additional property -(`$installed`) in the factory? That's where `Installable` class is coming -to make our life little nicer... +(`$installed`) in the factory? That's where `Installable` class is coming to make our life little nicer... New `AccountFactory` extending `Installable` class: @@ -230,14 +227,11 @@ class AccountFactory extends Installable { } ``` -I mean, yeah, the installation of the database looks better, but still, when -we want to add another column to `account` table, we still must create the -property, modify `fromArray` and `toArray` methods, update `updateAccount` -and `createAccount` method and create the column in `install` method. That's -still so much work, where you can make a mistake and spend even more time to -find bugs. That's where ORM comes in, how about we could throw away -`getAccountById`, `saveAccount`, `createAccount`, `updateAccount` methods -and reduce our `install` method to this: +I mean, yeah, the installation of the database looks better, but still, when we want to add another column to `account` +table, we still must create the property, modify `fromArray` and `toArray` methods, update `updateAccount` +and `createAccount` method and create the column in `install` method. That's still so much work, where you can make a +mistake and spend even more time to find bugs. That's where ORM comes in, how about we could throw away +`getAccountById`, `saveAccount`, `createAccount`, `updateAccount` methods and reduce our `install` method to this: ```php protected function install(Updater $updater): void diff --git a/docs/usage-orm.md b/docs/usage-orm.md index 028853f..f824846 100644 --- a/docs/usage-orm.md +++ b/docs/usage-orm.md @@ -1,23 +1,21 @@ # ORM Usage -This functionality is in MkSQL since v0.8. and I actually didn't know -what ORM meant before, as I never used any and didn't know I would -need it to stop writing a ton of `toArray` and `fromArray`/`fromRow` methods -in entities. If I knew what it is and how to use for example `Doctrine` -I might actually never write this package. (But I have no idea if Doctrine -can automatically create tables, maybe I could just write adapter for creating -tables for it?) - -Anyway I would not use Doctrine in PHP lower than 8, because I believe -that comments (annotations) should not be part of the working code. That changed -with introduction of `Attributes`, so I think Doctrine is the way now. - -So, let's look at the factory and entity from previous page introducing the -`Updater` class for us in +This functionality is in MkSQL since v0.8. and I actually didn't know what ORM meant before, as I never used any and +didn't know I would need it to stop writing a ton of `toArray` and `fromArray`/`fromRow` methods in entities. If I knew +what it is and how to use for example `Doctrine` +I might actually never write this package. (But I have no idea if Doctrine can automatically create tables, maybe I +could just write adapter for creating tables for it?) + +Anyway I would not use Doctrine in PHP lower than 8, because I believe that comments (annotations) should not be part of +the working code. That changed with introduction of `Attributes`, so I think Doctrine is the way now. + +So, let's look at the factory and entity from previous page introducing the +`Updater` class for us in [Factory Usage & Installable Class](usage-factory-installable.md) page. *You should probably read it, if you didn't yet.* *AccountFactory.php file:* + ```php class AccountFactory extends Installable { @@ -93,6 +91,7 @@ class AccountFactory extends Installable ``` *Account.php file:* + ```php class Account { @@ -132,11 +131,9 @@ class Account } ``` -I promised you, that you can get rid of all those -methods, and I deliver! +I promised you, that you can get rid of all those methods, and I deliver! -Extend your entity with `BaseEntity` class! You can then safely -remove `fromArray` and `toArray` methods! Look at this: +Extend your entity with `BaseEntity` class! You can then safely remove `fromArray` and `toArray` methods! Look at this: ```php #[TableName('account')] @@ -169,9 +166,9 @@ can you see that it has everything from this below? ->setNotNull()->setComment('sha256'); ``` -That means, we don't need to write our updater anymore! -As mentioned before, in the [Factory Usage & Installable Class](usage-factory-installable.md), -this allows us to change our `install` method to this: +That means, we don't need to write our updater anymore! +As mentioned before, in the [Factory Usage & Installable Class](usage-factory-installable.md), this allows us to change +our `install` method to this: ```php protected function install(Updater $updater): void @@ -180,8 +177,7 @@ protected function install(Updater $updater): void } ``` -Installable class is also extending `BaseRepository` class! More -about it on [Base Repository Usage](usage-orm.md) page. +Installable class is also extending `BaseRepository` class! More about it on [Base Repository Usage](usage-orm.md) page. To tease you a little and get ahead my self again, this is how the new `AccountFactory.php` file looks: @@ -209,8 +205,7 @@ class AccountFactory extends Installable } ``` -We are getting closer to the end of it all, -the last page awaiting your attention is +We are getting closer to the end of it all, the last page awaiting your attention is [Base Repository Usage](usage-orm.md)! diff --git a/docs/usage-updater.md b/docs/usage-updater.md index 5408fe6..d1cfa18 100644 --- a/docs/usage-updater.md +++ b/docs/usage-updater.md @@ -22,18 +22,18 @@ $a->setPrimaryKeyType("char(36)"); $updater->install(); ``` -And it's done! You now have an accounts table. -It will look like this: +And it's done! You now have an accounts table. It will look like this: ![updater-usage-1.php](./img/updater-usage-1.png) ***Wow*, where did the `id` column came from?** -Table primary key is automatically generated for you. You can -modify its type and name with `$table->setPrimaryKeyName("newPkColumnName");` -and `$a->setPrimaryKeyType("char(36)"); // uuid?` methods. +Table primary key is automatically generated for you. You can modify its type and name +with `$table->setPrimaryKeyName("newPkColumnName");` +and `$a->setPrimaryKeyType("char(36)"); // uuid?` methods. Example: + ```php // File: /examples/updater-usage-2.php use Zrnik\MkSQL\Updater; @@ -56,14 +56,12 @@ Result: ![updater-usage-2.php](./img/updater-usage-2.png) -**Composite primary keys** are not, and will not be supported. First, -I have no idea what is the use for them and second, I don't have a -slight idea how it could be implemented. +**Composite primary keys** are not, and will not be supported. First, I have no idea what is the use for them and +second, I don't have a slight idea how it could be implemented. ## Column cloning -What if you want to have more tables with the same column definition? -It might tempt you to write it like this: +What if you want to have more tables with the same column definition? It might tempt you to write it like this: ```php // File: /examples/updater-usage-3-w.php @@ -88,6 +86,7 @@ $updater->install(); ``` Result: + ``` LogicException: Column 'createDate' already has a parent 'shop_order', consider cloning! ``` @@ -116,13 +115,14 @@ $i->columnAdd(clone $multipleTableColumn); // and REMOVES the parent from it. $updater->install(); ``` -Result: +Result: ![updater-usage-3-c.png](./img/updater-usage-3-c.png) ## Column properties You can define more stuff to the column. For example: + - NOT NULL - Unique Index - Default Value @@ -159,17 +159,15 @@ $a->columnCreate('administrator', 'tinyint(1)') $updater->install(); ``` -Result: +Result: ![updater-usage-4.png](./img/updater-usage-4.png) ## Foreign Key -Foreign key support is limited, you should aim the foreign key at -another table's primary key, and it will constrain in from actions -that would break the link. You cannot (yet?) change -`ON DELETE` and `ON UPDATE` behavior, so the default -is used. +Foreign key support is limited, you should aim the foreign key at another table's primary key, and it will constrain in +from actions that would break the link. You cannot (yet?) change +`ON DELETE` and `ON UPDATE` behavior, so the default is used. For example, can link authentication token to the account like this: @@ -203,11 +201,12 @@ $t->columnCreate('token', 'varchar') $updater->install(); ``` -Result: +Result: ![updater-usage-5.png](./img/updater-usage-5.png) -I guess that's everything that relates to the updater itself, you can continue to [Factory Usage & Installable Class](usage-factory-installable.md) page. +I guess that's everything that relates to the updater itself, you can continue +to [Factory Usage & Installable Class](usage-factory-installable.md) page. diff --git a/examples/Accounts/Pure/AccountFactory.php b/examples/Accounts/Pure/AccountFactory.php index 1cb37cf..2e2398e 100644 --- a/examples/Accounts/Pure/AccountFactory.php +++ b/examples/Accounts/Pure/AccountFactory.php @@ -1,30 +1,33 @@ pdo->prepare('SELECT * FROM account WHERE id = :id'); $statement->execute(['id' => $id]); $result = $statement->fetch(PDO::FETCH_ASSOC); - if($result === false) { + if ($result === false) { return null; } return Account::fromArray(iterator_to_array($result)); } - public function saveAccount(Account $account): void { - if($account->id === null) { + public function saveAccount(Account $account): void + { + if ($account->id === null) { $this->createAccount($account); - } - else { + } else { $this->updateAccount($account); } } @@ -37,12 +40,12 @@ private function createAccount(Account $account): void unset($accountData['id']); $queryData = []; - foreach($accountData as $key => $value) { + foreach ($accountData as $key => $value) { $queryData[sprintf(':%s', $key)] = $value; } $statement->execute($queryData); - $account->id = (int) $this->pdo->lastInsertId(); + $account->id = (int)$this->pdo->lastInsertId(); } private function updateAccount(Account $account): void @@ -52,7 +55,7 @@ private function updateAccount(Account $account): void $accountData = $account->toArray(); $queryData = []; - foreach($accountData as $key => $value) { + foreach ($accountData as $key => $value) { $queryData[sprintf(':%s', $key)] = $value; } diff --git a/examples/Accounts/Pure/AccountTable.sql b/examples/Accounts/Pure/AccountTable.sql index 1202baa..0ce4adb 100644 --- a/examples/Accounts/Pure/AccountTable.sql +++ b/examples/Accounts/Pure/AccountTable.sql @@ -1,7 +1,8 @@ -CREATE TABLE `account` ( - `id` int(11) NOT NULL AUTO_INCREMENT, +CREATE TABLE `account` +( + `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(60) NOT NULL, - `password` char(64) NOT NULL COMMENT 'sha256', + `password` char(64) NOT NULL COMMENT 'sha256', PRIMARY KEY (`id`), UNIQUE KEY `account_username_unique_index` (`username`), UNIQUE KEY `account_id_unique_index` (`id`) diff --git a/examples/Accounts/Updater/AccountFactory.php b/examples/Accounts/Updater/AccountFactory.php index 2f30a60..87063fd 100644 --- a/examples/Accounts/Updater/AccountFactory.php +++ b/examples/Accounts/Updater/AccountFactory.php @@ -1,11 +1,13 @@ pdo); @@ -38,21 +40,22 @@ private function install(): void $updater->install(); } - public function getAccountById(int $id): ?Account { + public function getAccountById(int $id): ?Account + { $statement = $this->pdo->prepare('SELECT * FROM account WHERE id = :id'); $statement->execute(['id' => $id]); $result = $statement->fetch(PDO::FETCH_ASSOC); - if($result === false) { + if ($result === false) { return null; } return Account::fromArray(iterator_to_array($result)); } - public function saveAccount(Account $account): void { - if($account->id === null) { + public function saveAccount(Account $account): void + { + if ($account->id === null) { $this->createAccount($account); - } - else { + } else { $this->updateAccount($account); } } @@ -65,12 +68,12 @@ private function createAccount(Account $account): void unset($accountData['id']); $queryData = []; - foreach($accountData as $key => $value) { + foreach ($accountData as $key => $value) { $queryData[sprintf(':%s', $key)] = $value; } $statement->execute($queryData); - $account->id = (int) $this->pdo->lastInsertId(); + $account->id = (int)$this->pdo->lastInsertId(); } private function updateAccount(Account $account): void @@ -80,7 +83,7 @@ private function updateAccount(Account $account): void $accountData = $account->toArray(); $queryData = []; - foreach($accountData as $key => $value) { + foreach ($accountData as $key => $value) { $queryData[sprintf(':%s', $key)] = $value; } diff --git a/examples/updater-usage-1.php b/examples/updater-usage-1.php index f5c2f7e..bcec4cc 100644 --- a/examples/updater-usage-1.php +++ b/examples/updater-usage-1.php @@ -4,7 +4,7 @@ include __DIR__ . '/../vendor/autoload.php'; -$pdo = new PDO('sqlite:' . __FILE__ . '.sqlite'); +$pdo = new PDO('sqlite:' . __FILE__ . '.sqlite'); $updater = new Updater($pdo); $a = $updater->tableCreate('accounts'); diff --git a/examples/updater-usage-2.php b/examples/updater-usage-2.php index 7a4182f..1627330 100644 --- a/examples/updater-usage-2.php +++ b/examples/updater-usage-2.php @@ -4,7 +4,7 @@ include __DIR__ . '/../vendor/autoload.php'; -$pdo = new PDO('sqlite:' . __FILE__ . '.sqlite'); +$pdo = new PDO('sqlite:' . __FILE__ . '.sqlite'); $updater = new Updater($pdo); $a = $updater->tableCreate('accounts'); diff --git a/examples/updater-usage-3-c.php b/examples/updater-usage-3-c.php index 2fe801b..976f47f 100644 --- a/examples/updater-usage-3-c.php +++ b/examples/updater-usage-3-c.php @@ -1,9 +1,10 @@ tableCreate('accounts'); diff --git a/examples/updater-usage-5.php b/examples/updater-usage-5.php index 9341270..19ad5c0 100644 --- a/examples/updater-usage-5.php +++ b/examples/updater-usage-5.php @@ -1,9 +1,10 @@ tableCreate('accounts'); diff --git a/examples/usage-factory-installable-1.php b/examples/usage-factory-installable-1.php index 65ca926..6016d95 100644 --- a/examples/usage-factory-installable-1.php +++ b/examples/usage-factory-installable-1.php @@ -6,7 +6,7 @@ include __DIR__ . '/../vendor/autoload.php'; -$pdo = new PDO('sqlite:' . __FILE__ . '.sqlite'); +$pdo = new PDO('sqlite:' . __FILE__ . '.sqlite'); $installableAccountFactory = new \Examples\Accounts\Installable\AccountFactory($pdo); diff --git a/examples/usage-factory-orm-1.php b/examples/usage-factory-orm-1.php index 9e6d9be..f8320a2 100644 --- a/examples/usage-factory-orm-1.php +++ b/examples/usage-factory-orm-1.php @@ -6,7 +6,7 @@ include __DIR__ . '/../vendor/autoload.php'; -$pdo = new PDO('sqlite:' . __FILE__ . '.sqlite'); +$pdo = new PDO('sqlite:' . __FILE__ . '.sqlite'); $installableAccountFactory = new \Examples\Accounts\Orm\AccountFactory($pdo); diff --git a/phpstan.neon b/phpstan.neon index 81fb1f2..bc123ee 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,6 @@ parameters: level: max +# checkExplicitmixed: true paths: - src - tests @@ -8,3 +9,4 @@ parameters: includes: - vendor/phpstan/phpstan-phpunit/extension.neon - vendor/phpstan/phpstan-phpunit/rules.neon + - vendor/phpstan/phpstan/conf/bleedingEdge.neon diff --git a/src/Column.php b/src/Column.php index af3923e..c1783e1 100644 --- a/src/Column.php +++ b/src/Column.php @@ -188,11 +188,11 @@ public function setDefault(mixed $defaultValue = null): Column { $type = gettype($defaultValue); - if (!in_array($type, static::$_AllowedDefaultValues)) { + if (!in_array($type, self::$_AllowedDefaultValues)) { throw new InvalidArgumentException( sprintf( "Comment must be one of '%s'. Got '%s' instead!", - implode(', ', static::$_AllowedDefaultValues), + implode(', ', self::$_AllowedDefaultValues), $type ) ); diff --git a/src/Exceptions/MultipleForeignKeysTargetingSameClassException.php b/src/Exceptions/MultipleForeignKeysTargetingSameClassException.php new file mode 100644 index 0000000..8342c29 --- /dev/null +++ b/src/Exceptions/MultipleForeignKeysTargetingSameClassException.php @@ -0,0 +1,30 @@ + + * @copyright Copyright (c) 2021, Štěpán Zrník + * @project MkSQL + */ + +namespace Zrnik\MkSQL\Exceptions; + +use JetBrains\PhpStorm\Pure; +use Zrnik\MkSQL\Repository\BaseEntity; + +class MultipleForeignKeysTargetingSameClassException extends MkSQLException +{ + /** + * @param class-string $targetingClass + * @param class-string $targetClass + * @param string $propertyName + */ + #[Pure] + public function __construct(string $targetingClass, string $targetClass, string $propertyName) + { + parent::__construct( + sprintf( + "Class '%s' have foreign key target '%s' already defined on property '%s'", + $targetingClass, $targetClass, $propertyName + ) + ); + } +} diff --git a/src/Queries/Makers/QueryMakerMySQL.php b/src/Queries/Makers/QueryMakerMySQL.php index f1ef94c..3fc99c1 100644 --- a/src/Queries/Makers/QueryMakerMySQL.php +++ b/src/Queries/Makers/QueryMakerMySQL.php @@ -356,7 +356,7 @@ public static function removeUniqueIndexQuery(Table $table, Column $column, stri $CreateQuery->setReason("Invoked by 'removeUniqueIndexQuery[" . $uniqueIndex . "]'" . PHP_EOL . $CreateQuery->getReason()); } - foreach ($CreateQueries ?? [] as $query) { + foreach ($CreateQueries as $query) { $Queries[] = $query; } diff --git a/src/Repository/BaseEntity.php b/src/Repository/BaseEntity.php index 468ff23..4d11bb5 100644 --- a/src/Repository/BaseEntity.php +++ b/src/Repository/BaseEntity.php @@ -9,7 +9,6 @@ use Attribute; use JetBrains\PhpStorm\Pure; -use JsonException; use JsonSerializable; use ReflectionClass; use ReflectionException; @@ -21,6 +20,7 @@ use Zrnik\MkSQL\Exceptions\InvalidPropertyTypeException; use Zrnik\MkSQL\Exceptions\MissingAttributeArgumentException; use Zrnik\MkSQL\Exceptions\MissingForeignKeyDefinitionInEntityException; +use Zrnik\MkSQL\Exceptions\MultipleForeignKeysTargetingSameClassException; use Zrnik\MkSQL\Exceptions\PrimaryKeyDefinitionException; use Zrnik\MkSQL\Exceptions\ReflectionFailedException; use Zrnik\MkSQL\Exceptions\RequiredClassAttributeMissingException; @@ -63,14 +63,15 @@ public static function getReflectionClass(BaseEntity|string $obj): ReflectionCla { /** @var class-string $objKey */ $objKey = is_string($obj) ? $obj : get_debug_type($obj); - if (!array_key_exists($objKey, static::$reflectionClasses)) { + if (!array_key_exists($objKey, self::$reflectionClasses)) { try { /** * @var ReflectionClass $reflectionInstance * @noinspection PhpRedundantVariableDocTypeInspection + * @throws ReflectionException */ $reflectionInstance = new ReflectionClass($objKey); - static::$reflectionClasses[$objKey] = $reflectionInstance; + self::$reflectionClasses[$objKey] = $reflectionInstance; } catch (ReflectionException $e) { throw new ReflectionFailedException( sprintf( @@ -81,7 +82,7 @@ public static function getReflectionClass(BaseEntity|string $obj): ReflectionCla ); } } - return static::$reflectionClasses[$objKey]; + return self::$reflectionClasses[$objKey]; } /** @@ -172,7 +173,7 @@ public function toArray(): array $result[$propertyName] = $propertyValue; } - foreach (static::getColumnNames() as $columnName) { + foreach (self::getColumnNames() as $columnName) { $this->rawData[$columnName] = $result[$columnName] ?? null; } @@ -187,7 +188,7 @@ public function toArray(): array public function updateRawData(): void { $data = $this->toArray(); - foreach (static::getColumnNames() as $columnName) { + foreach (self::getColumnNames() as $columnName) { $this->rawData[$columnName] = $data[$columnName] ?? null; } } @@ -201,7 +202,7 @@ public static function create(): static $entity = new static(); // We MUST initialize `FetchArray` properties as array! - foreach(EntityReflection::getFetchArrayProperties($entity) as $fetchArrayData) { + foreach (EntityReflection::getFetchArrayProperties($entity) as $fetchArrayData) { $propertyName = $fetchArrayData->getPropertyName(); $entity->$propertyName = []; } @@ -246,7 +247,7 @@ public static function fromIterable(iterable $iterable): static //$obj->rawData = $data; - foreach (static::getColumnNames() as $columnName) { + foreach (self::getColumnNames() as $columnName) { $obj->rawData[$columnName] = $data[$columnName] ?? null; } @@ -450,6 +451,17 @@ public static function getPrimaryKeyName(?ReflectionClass $reflection = null): s { return self::columnName(self::getPrimaryKeyReflectionProperty($reflection)); } + + /** + * @param ReflectionClass|null $reflection + * @return string + */ + public static function getPrimaryKeyPropertyName(?ReflectionClass $reflection = null): string + { + return self::getPrimaryKeyReflectionProperty($reflection)->getName(); + } + + //endregion //region Primary Key Type @@ -738,6 +750,8 @@ public static function hydrateUpdater(Updater $updater, array $baseEntitiesWeHav /** @var array> $fetchArrayEntities */ $fetchArrayEntities = []; + $referencedForeignKeys = []; + // Columns: foreach ($properties as $property) { @@ -803,12 +817,19 @@ public static function hydrateUpdater(Updater $updater, array $baseEntitiesWeHav $referencedEntityName = Reflection::attributeGetArgument($foreignKeyAttribute); + if (array_key_exists($referencedEntityName, $referencedForeignKeys)) { + throw new MultipleForeignKeysTargetingSameClassException( + $reflection->getName(), $referencedEntityName, $referencedForeignKeys[$referencedEntityName] + ); + } + if (!$isFetchArray && in_array($referencedEntityName, $baseEntitiesWeHaveAlreadySeen, true)) { throw new CircularReferenceDetectedException( static::class, $property->getName() ); } + $referencedForeignKeys[$referencedEntityName] = $property->getName(); $hydrateAfter[] = $referencedEntityName; } @@ -867,9 +888,8 @@ public static function hydrateUpdater(Updater $updater, array $baseEntitiesWeHav */ public function getPrimaryKeyValue(): mixed { - $primaryKeyColumnName = static::getPrimaryKeyName(); - $data = $this->toArray(); - return $data[$primaryKeyColumnName]; + $primaryKeyPropertyName = static::getPrimaryKeyPropertyName(); + return $this->$primaryKeyPropertyName; } /** @@ -886,12 +906,12 @@ public function setPrimaryKeyValue(mixed $newPrimaryKeyValue): void } $this->$primaryKeyPropertyName = $newPrimaryKeyValue; - foreach(EntityReflection::getFetchArrayProperties($this) as $fetchArrayData) { - foreach(EntityReflection::getForeignKeys($fetchArrayData->getTargetClassName()) as $targetForeignKeyPropertyData) { - if(static::class === $targetForeignKeyPropertyData->getTargetClassName()) { + foreach (EntityReflection::getFetchArrayProperties($this) as $fetchArrayData) { + foreach (EntityReflection::getForeignKeys($fetchArrayData->getTargetClassName()) as $targetForeignKeyPropertyData) { + if (static::class === $targetForeignKeyPropertyData->getTargetClassName()) { $thisPropertyName = $fetchArrayData->getPropertyName(); $targetPropertyName = $targetForeignKeyPropertyData->getPropertyName(); - foreach($this->$thisPropertyName as $value) { + foreach ($this->$thisPropertyName as $value) { $value->$targetPropertyName = $this; } } @@ -922,22 +942,22 @@ public function jsonSerialize(): array // Add 'FetchArray' values: $reflection = self::getReflectionClass($this); - foreach($reflection->getProperties() as $property) { + foreach ($reflection->getProperties() as $property) { $fetchArrayAttribute = Reflection::propertyGetAttribute( $property, FetchArray::class ); - if($fetchArrayAttribute !== null) { + if ($fetchArrayAttribute !== null) { $propertyName = $property->getName(); $result[$propertyName] = $this->$propertyName; } else { $dataKey = $property->getName(); $reflectionProperty = self::propertyReflection($dataKey); - if($reflectionProperty !== null) { + if ($reflectionProperty !== null) { $columnNameAttribute = Reflection::propertyGetAttribute($reflectionProperty, ColumnName::class); - if($columnNameAttribute !== null) { + if ($columnNameAttribute !== null) { $dataKey = Reflection::attributeGetArgument($columnNameAttribute) ?? $dataKey; } } @@ -952,13 +972,15 @@ public function jsonSerialize(): array public function fixSubEntityForeignKeys(): void { - foreach(EntityReflection::getFetchArrayProperties($this) as $fetchArrayProperty) { + foreach (EntityReflection::getFetchArrayProperties($this) as $fetchArrayProperty) { $propertyName = $fetchArrayProperty->getPropertyName(); /** @var BaseEntity $childEntity */ - foreach($this->$propertyName as $childEntity) { - foreach(EntityReflection::getForeignKeys($childEntity) as $foreignKeyData) { + foreach ($this->$propertyName as $childEntity) { + foreach (EntityReflection::getForeignKeys($childEntity) as $foreignKeyData) { $childEntityForeignKeyPropertyName = $foreignKeyData->getPropertyName(); - if($foreignKeyData->getTargetClassName() === self::class) { + if ( + $foreignKeyData->getTargetClassName() === self::class + ) { $childEntity->$childEntityForeignKeyPropertyName = $this; } } diff --git a/src/Repository/BaseRepository.php b/src/Repository/BaseRepository.php index c82cf25..3a389ed 100644 --- a/src/Repository/BaseRepository.php +++ b/src/Repository/BaseRepository.php @@ -9,7 +9,7 @@ use PDO; use Zrnik\MkSQL\Exceptions\InvalidArgumentException; -use Zrnik\MkSQL\Repository\Fetcher\Fetcher; +use Zrnik\MkSQL\Repository\Fetch\Dispenser; use Zrnik\MkSQL\Repository\Saver\Saver; use Zrnik\MkSQL\Utilities\Reflection; use function count; @@ -56,26 +56,13 @@ public function getResultByPrimaryKey(string $baseEntityClassString, mixed $prim /** * @param class-string $baseEntityClassString - * @param mixed $primaryKeyValue - * @return BaseEntity[] - */ - public function getResultsByPrimaryKey(string $baseEntityClassString, mixed $primaryKeyValue): array - { - /** @var BaseEntity $baseEntity */ - $baseEntity = $baseEntityClassString; - $primaryKey = $baseEntity::getPrimaryKeyName(); - return $this->getResultsByKey($baseEntityClassString, $primaryKey, $primaryKeyValue); - } - - /** - * @param class-string $baseEntityClassString - * @param string $key + * @param string $propertyName * @param mixed $value * @return ?BaseEntity */ - public function getResultByKey(string $baseEntityClassString, string $key, mixed $value): ?BaseEntity + public function getResultByKey(string $baseEntityClassString, string $propertyName, mixed $value): ?BaseEntity { - $result = $this->getResultsByKeys($baseEntityClassString, $key, [$value]); + $result = $this->getResultsByKeys($baseEntityClassString, $propertyName, [$value]); if (count($result) > 0) { return $result[0]; } @@ -94,11 +81,11 @@ public function getAll(string $baseEntityClassString): array /** * @param class-string $baseEntityClassString - * @param string|null $key + * @param string|null $propertyName * @param mixed|null $value * @return BaseEntity[] */ - public function getResultsByKey(string $baseEntityClassString, ?string $key = null, mixed $value = null): array + public function getResultsByKey(string $baseEntityClassString, ?string $propertyName = null, mixed $value = null): array { if (is_array($value)) { throw new InvalidArgumentException("For array value, please use 'getResultsByKeys' method!"); @@ -106,13 +93,13 @@ public function getResultsByKey(string $baseEntityClassString, ?string $key = nu return $this->getResultsByKeys( - $baseEntityClassString, $key, $value === null ? [] : [$value] + $baseEntityClassString, $propertyName, $value === null ? [] : [$value] ); } /** * @param class-string $baseEntityClassString - * @param string|null $key + * @param string|null $propertyName * @param array $values * @return BaseEntity[] * @noinspection PhpFunctionCyclomaticComplexityInspection @@ -120,12 +107,12 @@ public function getResultsByKey(string $baseEntityClassString, ?string $key = nu */ public function getResultsByKeys( string $baseEntityClassString, - ?string $key = null, + ?string $propertyName = null, array $values = [], ): array { - return (new Fetcher($this->getPdo())) - ->getResultsByKeys($baseEntityClassString, $key, $values); + return (new Dispenser($this->getPdo())) + ->getResultsByKeys($baseEntityClassString, $propertyName, $values); } /** diff --git a/src/Repository/Fetch/CompletionBuilder.php b/src/Repository/Fetch/CompletionBuilder.php new file mode 100644 index 0000000..903b3af --- /dev/null +++ b/src/Repository/Fetch/CompletionBuilder.php @@ -0,0 +1,67 @@ +storage as $completionKeyValues) { + if ($completionKeyValues->hasAnyValues()) { + $result[] = $completionKeyValues; + } + } + + return $result; + } + + /** + * @param class-string $className + * @param string $columnName + * @param mixed $value + */ + public function add(string $className, string $columnName, mixed $value): void + { + $completionClass = $this->classOf($className, $columnName); + if ($value !== null && !in_array($value, $completionClass->values, true)) { + $completionClass->values[] = $value; + } + } + + /** + * @param class-string $className + * @param string $columnName + * @return CompletionKeyValues + */ + private function classOf(string $className, string $columnName): CompletionKeyValues + { + foreach ($this->storage as $existingCompletionKeyValues) { + if ( + $existingCompletionKeyValues->baseEntityClassName === $className + && $existingCompletionKeyValues->columnName === $columnName + ) { + return $existingCompletionKeyValues; + } + } + + $newCompletionKeyValues = CompletionKeyValues::create($className, $columnName, []); + $this->storage[] = $newCompletionKeyValues; + return $newCompletionKeyValues; + } +} \ No newline at end of file diff --git a/src/Repository/Fetch/CompletionIndication.php b/src/Repository/Fetch/CompletionIndication.php new file mode 100644 index 0000000..613771f --- /dev/null +++ b/src/Repository/Fetch/CompletionIndication.php @@ -0,0 +1,37 @@ +keyOf($entity), $this->storage, true); + } + + public function setCompleted(BaseEntity $entity): void + { + if (!$this->isCompleted($entity)) { + $this->storage[] = $this->keyOf($entity); + } + } + + private function keyOf(BaseEntity $entity): string + { + $rawData = $entity->getRawData(); + $primaryKeyName = $entity::getPrimaryKeyName(); + return sprintf('%s::primaryKey(%s)', $entity::class, $rawData[$primaryKeyName]); + } +} \ No newline at end of file diff --git a/src/Repository/Fetch/CompletionKeyValues.php b/src/Repository/Fetch/CompletionKeyValues.php new file mode 100644 index 0000000..1372338 --- /dev/null +++ b/src/Repository/Fetch/CompletionKeyValues.php @@ -0,0 +1,45 @@ + $baseEntityClassName + * @param string $columnName + * @param mixed[] $values + */ + final private function __construct( + public string $baseEntityClassName, + public string $columnName, + public array $values, + ) + { + + } + + /** + * @param class-string $baseEntityClassName + * @param string $columnName + * @param mixed[] $values + * @return CompletionKeyValues + */ + #[Pure] public static function create( + string $baseEntityClassName, + string $columnName, + array $values, + ): CompletionKeyValues + { + return new CompletionKeyValues($baseEntityClassName, $columnName, $values); + } + + public function hasAnyValues(): bool + { + return count($this->values) > 0; + } + +} \ No newline at end of file diff --git a/src/Repository/Fetch/Dispenser.php b/src/Repository/Fetch/Dispenser.php new file mode 100644 index 0000000..51e2299 --- /dev/null +++ b/src/Repository/Fetch/Dispenser.php @@ -0,0 +1,50 @@ + $baseEntityClassString + * @param ?string $propertyName + * @param array $values + * @return BaseEntity[] + */ + public function getResultsByKeys( + string $baseEntityClassString, + ?string $propertyName = null, array $values = [] + ): array + { + $resultCompiler = new ResultService(); + + $sql = FetchQuery::create($baseEntityClassString, $propertyName, $values); + $resultCompiler->addRows($baseEntityClassString, $sql->fetchAll($this->pdo)); + + $killSwitch = 150; + while (!$resultCompiler->complete()) { + $completionData = $resultCompiler->completionData(); + foreach ($completionData as $completionQuery) { + $sql = FetchQuery::create($completionQuery->baseEntityClassName, $completionQuery->columnName, $completionQuery->values); + $resultCompiler->addRows($completionQuery->baseEntityClassName, $sql->fetchAll($this->pdo)); + } + + if ($killSwitch <= 0) { + throw new MkSQLException('Stack Overflow!'); + } else { + $killSwitch--; + } + } + + $resultCompiler->linkEntities(); + + return $resultCompiler->getEntities($baseEntityClassString, $propertyName, $values); + } +} diff --git a/src/Repository/Fetch/EntityStorage.php b/src/Repository/Fetch/EntityStorage.php new file mode 100644 index 0000000..7c23457 --- /dev/null +++ b/src/Repository/Fetch/EntityStorage.php @@ -0,0 +1,135 @@ +entities[] = $entity; + } + + /** + * @param class-string $baseEntityClassString + * @return BaseEntity[] + */ + public function getEntitiesByClassName(string $baseEntityClassString): array + { + $result = []; + foreach ($this->entities as $entity) { + if ($entity::class === $baseEntityClassString) { + $result[] = $entity; + } + } + return $result; + } + + /** + * @return BaseEntity[] + */ + public function getEntities(): array + { + return $this->entities; + } + + /** + * @param class-string $className + * @param mixed $primaryKeyValue + * @return bool + */ + public function has(string $className, mixed $primaryKeyValue): bool + { + return $this->getEntityByPrimaryKey($className, $primaryKeyValue) !== null; + } + + /** + * @param class-string $className + * @param mixed $primaryKeyValue + * @return BaseEntity|null + */ + private function getEntityByPrimaryKey( + string $className, mixed $primaryKeyValue + ): ?BaseEntity + { + foreach ($this->getEntitiesByClassName($className) as $entity) { + if ((string)$entity->getPrimaryKeyValue() === (string)$primaryKeyValue) { + return $entity; + } + } + + return null; + } + + /** + * @param class-string $className + * @param string $columnName + * @param mixed $columnValue + * @return BaseEntity[] + */ + private function getEntitiesByColumn(string $className, string $columnName, mixed $columnValue): array + { + $result = []; + foreach ($this->getEntitiesByClassName($className) as $entity) { + if ((string)$entity->getRawData()[$columnName] === (string)$columnValue) { + $result[] = $entity; + } + } + + return $result; + } + + public function linkEntities(): void + { + foreach ($this->entities as $entity) { + + foreach (EntityReflection::getForeignKeys($entity) as $foreignKeyData) { + + $requiredPrimaryKey = $entity->getRawData()[$foreignKeyData->foreignKeyColumnName()]; + + $foreignEntity = $this->getEntityByPrimaryKey( + $foreignKeyData->getTargetClassName(), $requiredPrimaryKey + ); + + $propertyName = $foreignKeyData->getPropertyName(); + $entity->$propertyName = $foreignEntity; + } + + + foreach (EntityReflection::getFetchArrayProperties($entity) as $fetchArrayData) { + + + $neededClass = $fetchArrayData->getTargetClassName(); + + $propertyName = $fetchArrayData->getPropertyName(); + + foreach (EntityReflection::getForeignKeys($neededClass) as $aimingBackForeignKeyData) { + + $fetchEntities = $this->getEntitiesByColumn( + $neededClass, + BaseEntity::columnName($aimingBackForeignKeyData->getProperty()), + $entity->getPrimaryKeyValue() + ); + + /** @var BaseEntity[] $data */ + $data = $entity->$propertyName; + foreach ($fetchEntities as $fetchEntity) { + $data[] = $fetchEntity; + } + $entity->$propertyName = $data; + } + } + } + } + + +} diff --git a/src/Repository/Fetch/FetchQuery.php b/src/Repository/Fetch/FetchQuery.php new file mode 100644 index 0000000..3613456 --- /dev/null +++ b/src/Repository/Fetch/FetchQuery.php @@ -0,0 +1,94 @@ +values); + + $statement = $pdo->prepare($this->query); + + $statement->execute($values); + + /** + * Since PHP 8.0 it never returns false, and MkSQL needs PHP 8+ so..... + * @see https://www.php.net/manual/en/pdostatement.fetchall.php#refsect1-pdostatement.fetchall-changelog + * @noinspection PhpUnnecessaryLocalVariableInspection + * + * @var mixed[] $fetch + */ + $fetch = $statement->fetchAll(); + + return $fetch; + } + + /** + * @param class-string $baseEntityClassString + * @param string|null $propertyName // It can take columnName too... + * @param array $values + * @return FetchQuery + */ + public static function create( + string $baseEntityClassString, + ?string $propertyName = null, + array $values = [] + ): FetchQuery + { + + /** @var BaseEntity $baseEntityForStaticUse */ + $baseEntityForStaticUse = $baseEntityClassString; + + $tableName = $baseEntityForStaticUse::getTableName(); + + if ($propertyName === null) { + return new FetchQuery(sprintf('SELECT * FROM %s', $tableName)); + } + + if (count($values) === 0) { + // This is actually handled in `getResultsByKey` but it's here for peace of mind... + return new FetchQuery(sprintf('SELECT * FROM %s WHERE 0 = 1', $tableName)); + } + + $columnName = $propertyName; + + $property = $baseEntityForStaticUse::propertyReflection($propertyName); + if ($property !== null) { + $columnNameAttribute = Reflection::propertyGetAttribute($property, ColumnName::class); + if ($columnNameAttribute !== null) { + $columnName = Reflection::attributeGetArgument($columnNameAttribute); + } + } + + $fetchSql = new FetchQuery( + sprintf( + 'SELECT * FROM %s WHERE %s IN (%s)', $tableName, $columnName, + str_repeat('?,', count($values) - 1) . '?' + ) + ); + + $fetchSql->values = $values; + + return $fetchSql; + } +} diff --git a/src/Repository/Fetch/ResultService.php b/src/Repository/Fetch/ResultService.php new file mode 100644 index 0000000..40540ab --- /dev/null +++ b/src/Repository/Fetch/ResultService.php @@ -0,0 +1,135 @@ +entityStorage = new EntityStorage(); + $this->completion = new CompletionIndication(); + } + + /** + * @param bool $dryRun + * @return CompletionKeyValues[] + */ + public function completionData(bool $dryRun = false): array + { + $completionResult = new CompletionBuilder(); + + foreach ($this->entityStorage->getEntities() as $entity) { + + if ($this->completion->isCompleted($entity)) { + continue; + } + + //region ForeignKey + foreach (EntityReflection::getForeignKeys($entity) as $foreignKeyData) { + + /** @var BaseEntity $targetClassStaticUsage */ + $targetClassStaticUsage = $foreignKeyData->getTargetClassName(); + + $keyToLoad = $entity->getRawData()[$foreignKeyData->foreignKeyColumnName()]; + + $completionResult->add( + $foreignKeyData->getTargetClassName(), + $targetClassStaticUsage::getPrimaryKeyName(), + $keyToLoad + ); + + } + //endregion + + + //region FetchArray + foreach (EntityReflection::getFetchArrayProperties($entity) as $fetchArrayData) { + $entityPrimaryKeyValue = $entity->getRawData()[$entity::getPrimaryKeyName()]; + foreach (EntityReflection::getForeignKeys($fetchArrayData->getTargetClassName()) as $foreignKeyAimingBack) { + if ($foreignKeyAimingBack->getTargetClassName() === $entity::class) { + $completionResult->add( + $fetchArrayData->getTargetClassName(), + $foreignKeyAimingBack->getPropertyName(), + $entityPrimaryKeyValue + ); + } + } + } + //endregion + + + if (!$dryRun) { + $this->completion->setCompleted($entity); + } + } + + return $completionResult->getCompletionData(); + } + + public function complete(): bool + { + return count($this->completionData(true)) === 0; + } + + /** + * @param class-string $baseEntityClassString + * @param array $rows + */ + public function addRows(string $baseEntityClassString, array $rows): void + { + /** @var BaseEntity $baseEntityForStaticUsage */ + $baseEntityForStaticUsage = $baseEntityClassString; + $primaryKeyColumnName = $baseEntityForStaticUsage::getPrimaryKeyName(); + foreach ($rows as $row) { + $newPrimaryValue = $row[$primaryKeyColumnName]; + if (!$this->entityStorage->has($baseEntityClassString, $newPrimaryValue)) { + $this->entityStorage->addEntity($baseEntityForStaticUsage::fromIterable($row)); + } + } + } + + /** + * @param class-string $baseEntityClassString + * @param string|null $propertyName + * @param mixed[] $values + * @return BaseEntity[] + */ + public function getEntities(string $baseEntityClassString, ?string $propertyName, array $values): array + { + /** @var BaseEntity $baseEntityForStaticUsage */ + $baseEntityForStaticUsage = $baseEntityClassString; + $result = []; + + if ($propertyName === null) { + return $this->entityStorage->getEntitiesByClassName($baseEntityClassString); + } + + $propertyReflection = $baseEntityForStaticUsage::propertyReflection($propertyName); + + if ($propertyReflection !== null) { + $columnName = $baseEntityForStaticUsage::columnName($propertyReflection); + foreach ($this->entityStorage->getEntitiesByClassName($baseEntityClassString) as $entity) { + $entityValue = $entity->getRawData()[$columnName]; + if (in_array($entityValue, $values, false)) { + $result[] = $entity; + } + } + } + + + return $result; + } + + public function linkEntities(): void + { + $this->entityStorage->linkEntities(); + } +} \ No newline at end of file diff --git a/src/Repository/Fetcher/FetchResult.php b/src/Repository/Fetcher/FetchResult.php deleted file mode 100644 index 5776367..0000000 --- a/src/Repository/Fetcher/FetchResult.php +++ /dev/null @@ -1,337 +0,0 @@ -> */ - /** @var array>> $rowData */ - private array $rowData = []; - - /** - * @param string $selectedBaseEntityClassString - */ - public function __construct( - private string $selectedBaseEntityClassString - ) - { - } - - /** - * @return BaseEntity[] - */ - public function getEntities(): array - { - $entities = []; - - foreach ($this->rowData as $className => $rows) { - - /** @var BaseEntity $classNameForStaticUse */ - $classNameForStaticUse = $className; - - $entities[$className] = []; - - foreach ($rows as $row) { - $entities[$className][$row[$classNameForStaticUse::getPrimaryKeyName()]] = $classNameForStaticUse::fromIterable($row); - } - - } - - - // 'Inject' foreign keys: - /** @var BaseEntity[] $keyEntities */ - foreach ($entities as $keyEntities) { - /** - * @var BaseEntity $entity - */ - foreach ($keyEntities as $entity) { - foreach (EntityReflection::getForeignKeys($entity) as $foreignKeyData) { - $propertyName = $foreignKeyData->getPropertyName(); - $requiredClassName = $foreignKeyData->getTargetClassName(); - $requiredPrimaryKeyValue = $entity->getRawData()[$foreignKeyData->foreignKeyColumnName()]; - - $entity->$propertyName = $entities[$requiredClassName][$requiredPrimaryKeyValue]; - } - } - } - - // 'Inject' fetch array - /** - * @var BaseEntity[] $keyEntities - */ - foreach ($entities as $keyEntities) { - /** - * @var BaseEntity $entity - */ - foreach ($keyEntities as $entity) { - foreach (EntityReflection::getFetchArrayProperties($entity) as $fetchArrayProperty) { - $propertyName = $fetchArrayProperty->getPropertyName(); - $requiredClassName = $fetchArrayProperty->getTargetClassName(); - - $pointerReflectionProperties = $this->findPropertyPointingTo($requiredClassName, $entity::class); - $values = []; - - foreach ($pointerReflectionProperties as $pointerRp) { - $pointerName = BaseEntity::columnName($pointerRp); - - if (array_key_exists($requiredClassName, $entities)) { - foreach ($entities[$requiredClassName] as $row) { - if ((string)$row->getRawData()[$pointerName] === (string)$entity->getPrimaryKeyValue()) { - - $values[$row->getPrimaryKeyValue()] = $row; - } - } - } - } - $entity->$propertyName = array_values($values); - } - } - } - - - if (!array_key_exists($this->selectedBaseEntityClassString, $entities)) { - $entities[$this->selectedBaseEntityClassString] = []; - } - - return $entities[$this->selectedBaseEntityClassString]; - } - - /** - * @param class-string $baseEntityClassString - * @param mixed[] $rows - */ - public function addRows(string $baseEntityClassString, array $rows): void - { - - /** @var BaseEntity $baseEntityForStaticUse */ - $baseEntityForStaticUse = $baseEntityClassString; - - if (!array_key_exists($baseEntityClassString, $this->rowData)) { - $this->rowData[$baseEntityClassString] = []; - } - - foreach ($rows as $row) { - $primaryKeyColumnName = $baseEntityForStaticUse::getPrimaryKeyName(); - $this->rowData[$baseEntityClassString][$row[$primaryKeyColumnName]] = $row; - } - - } - - /** - * Returns array, with missing primary key values - * - * Shape: > - * - * @return array>> - */ - public function getCompletionKeys(): array - { - $completionKeys = []; - - /** - * @var class-string $classString - * @var mixed[] $rowsByPrimaryKey - */ - foreach ($this->rowData as $classString => $rowsByPrimaryKey) { - - //region Foreign Key - - $foreignKeyProperties = $this->foreignKeyProperties($classString); - - /** @var BaseEntity $currentEntityStatic */ - $currentEntityStatic = $classString; - - /** - * @var string $propertyName - * @var class-string $foreignEntityClassName - */ - foreach ($foreignKeyProperties as $propertyName => $foreignEntityClassName) { - /** @var BaseEntity $foreignEntityStatic */ - $foreignEntityStatic = $foreignEntityClassName; - - if (!array_key_exists($foreignEntityClassName, $completionKeys)) { - $completionKeys[$foreignEntityClassName] = []; - } - - $values = []; - foreach ($rowsByPrimaryKey as $row) { - $propertyReflection = $currentEntityStatic::propertyReflection($propertyName); - if ($propertyReflection !== null) { - $values[] = $row[BaseEntity::columnName($propertyReflection)]; - } - } - - $completionKeys - [$foreignEntityClassName] - [$foreignEntityStatic::getPrimaryKeyName()] = array_unique($values); - - } - - //endregion - - //region FetchArray - - $fetchArrayData = $this->fetchArrayData($classString); - - foreach ($fetchArrayData as $foreignKeyProperty) { - - /** @var class-string $declaringClass */ - $declaringClass = $foreignKeyProperty->getDeclaringClass()->getName(); - - if (!array_key_exists($declaringClass, $completionKeys)) { - $completionKeys[$declaringClass] = []; - } - - $columnName = BaseEntity::columnName($foreignKeyProperty); - - if (!array_key_exists($columnName, $completionKeys[$declaringClass])) { - $completionKeys[$declaringClass][$columnName] = []; - } - - foreach ($this->rowData as $className => $rows) { - - /** @var BaseEntity $classNameStaticUse */ - $classNameStaticUse = $className; - - $primaryKeyName = $classNameStaticUse::getPrimaryKeyName(); - - foreach ($rows as $row) { - $completionKeys[$declaringClass][$columnName][] = $row[$primaryKeyName]; - } - - } - } - - //endregion - - } - - return $this->removeExistingRowsFromCompletionKeys($completionKeys); - } - - public function needsCompletion(): bool - { - return count($this->getCompletionKeys()) > 0; - } - - /** - * @param class-string $classString - * @return array - */ - private function foreignKeyProperties(string $classString): array - { - $result = []; - - foreach (EntityReflection::getForeignKeys($classString) as $foreignKeyData) { - $result[$foreignKeyData->getPropertyName()] = $foreignKeyData->getTargetClassName(); - } - - return $result; - } - - /** - * @param class-string $classString - * @return ReflectionProperty[] - */ - private function fetchArrayData(string $classString): array - { - $result = []; - - foreach (EntityReflection::getFetchArrayProperties($classString) as $fetchArrayData) { - $fetchClassName = $fetchArrayData->getTargetClassName(); - $pointerReflectionProperties = $this->findPropertyPointingTo($fetchClassName, $classString); - foreach ($pointerReflectionProperties as $pointerReflectionProperty) { - $result[] = $pointerReflectionProperty; - } - } - - return $result; - } - - /** - * @param array, array> $completionKeys - * @return array, array> - */ - private function removeExistingRowsFromCompletionKeys(array $completionKeys): array - { - $newCompletionKeys = []; - /** - * @var class-string $className - */ - foreach ($completionKeys as $className => $keyValues) { - $newKeyValues = []; - foreach ($keyValues as $key => $values) { - - $key = (string)$key; - - if (!array_key_exists($key, $newKeyValues)) { - $newKeyValues[$key] = []; - } - - foreach ($values as $value) { - - $found = false; - - if (array_key_exists($className, $this->rowData)) { - foreach ($this->rowData[$className] as $pkeyRow) { - - $primaryKeyColumnName = BaseEntity::getPrimaryKeyName( - BaseEntity::getReflectionClass($className) - ); - - if ((string)$pkeyRow[$primaryKeyColumnName] === (string)$value) { - $found = true; - } - } - } - - if (!$found) { - $newKeyValues[$key][] = $value; - } - - } - - if (count($newKeyValues[$key]) === 0) { - unset($newKeyValues[$key]); - } - } - - if (count($newKeyValues) > 0) { - $newCompletionKeys[$className] = $newKeyValues; - } - } - - return $newCompletionKeys; - } - - /** - * @param class-string $referencingClass - * @param class-string $searchClass - * @return ReflectionProperty[] - */ - private function findPropertyPointingTo(string $referencingClass, string $searchClass): array - { - $result = []; - $reflection = BaseEntity::getReflectionClass($referencingClass); - foreach ($reflection->getProperties() as $reflectionProperty) { - $foreignKeyAttribute = Reflection::propertyGetAttribute($reflectionProperty, ForeignKey::class); - if ($foreignKeyAttribute !== null) { - $arg = Reflection::attributeGetArgument($foreignKeyAttribute); - if ($arg === $searchClass) { - $result[] = $reflectionProperty; - } - } - } - return $result; - } - - -} diff --git a/src/Repository/Fetcher/FetchSql.php b/src/Repository/Fetcher/FetchSql.php deleted file mode 100644 index a727592..0000000 --- a/src/Repository/Fetcher/FetchSql.php +++ /dev/null @@ -1,37 +0,0 @@ -prepare($this->query); - $statement->execute($this->values); - /** - * Since PHP 8.0 it never returns false - * @see https://www.php.net/manual/en/pdostatement.fetchall.php#refsect1-pdostatement.fetchall-changelog - * @noinspection PhpUnnecessaryLocalVariableInspection - * - * @var mixed[] $fetch - */ - $fetch = $statement->fetchAll(); - - return $fetch; - } -} \ No newline at end of file diff --git a/src/Repository/Fetcher/Fetcher.php b/src/Repository/Fetcher/Fetcher.php deleted file mode 100644 index 5b2ff11..0000000 --- a/src/Repository/Fetcher/Fetcher.php +++ /dev/null @@ -1,168 +0,0 @@ - $baseEntityClassString - * @param ?string $key - * @param array $values - * @return BaseEntity[] - */ - public function getResultsByKeys( - string $baseEntityClassString, - ?string $key = null, array $values = [] - ): array - { - //This is quicker :) - if ($key !== null && count($values) === 0) { - return []; - } - - $fetchResult = new FetchResult($baseEntityClassString); - - $fetchSql = $this->createFetchSql($baseEntityClassString, $key, $values); - $fetchResult->addRows($baseEntityClassString, $fetchSql->fetchAll($this->pdo)); - - $tries = 20; - while ($fetchResult->needsCompletion()) { - $completionKeys = $fetchResult->getCompletionKeys(); - - /** - * @var class-string $entityClass - * @var array $keyValues - */ - foreach ($completionKeys as $entityClass => $keyValues) { - /** - * @var int|string $subKey - * @var mixed[] $subValues - */ - foreach ($keyValues as $subKey => $subValues) { - $fetchSql = $this->createFetchSql($entityClass, (string)$subKey, $subValues); - $fetchResult->addRows($entityClass, $fetchSql->fetchAll($this->pdo)); - } - } - - - //Kill Switch - $tries--; - if ($tries <= 0) { - break; - } - } - - return $this->filterEntities($fetchResult->getEntities(), $key, $values); - } - - /** - * @param class-string $baseEntityClassString - * @param string|null $key - * @param array $values - * @return FetchSql - */ - private function createFetchSql( - string $baseEntityClassString, - ?string $key = null, - array $values = [] - ): FetchSql - { - /** @var BaseEntity $baseEntityForStaticUse */ - $baseEntityForStaticUse = $baseEntityClassString; - - $tableName = $baseEntityForStaticUse::getTableName(); - - if ($key === null) { - return new FetchSql(sprintf('SELECT * FROM %s', $tableName)); - } - - if (count($values) === 0) { - // This is actually handled in `getResultsByKey` but it's here for peace of mind... - return new FetchSql(sprintf('SELECT * FROM %s WHERE 0 = 1', $tableName)); - } - - $property = $baseEntityForStaticUse::propertyReflection($key); - if ($property !== null) { - $columnNameAttribute = Reflection::propertyGetAttribute($property, ColumnName::class); - if ($columnNameAttribute !== null) { - $columnName = Reflection::attributeGetArgument($columnNameAttribute); - $key = $columnName; - } - } - - $fetchSql = new FetchSql( - sprintf( - 'SELECT * FROM %s WHERE %s IN (%s)', $tableName, $key, - str_repeat('?,', count($values) - 1) . '?' - ) - ); - - $fetchSql->values = $values; - - return $fetchSql; - } - - /** - * @param BaseEntity[] $entities - * @param ?string $key //PROPERTY NAME, NOT COLUMN NAME! - * @param mixed $values - * @return BaseEntity[] - */ - private function filterEntities(array $entities, ?string $key = null, mixed $values = []): array - { - - if ($key !== null) { - - $result = []; - - foreach ($entities as $entity) { - $reflection = BaseEntity::getReflectionClass($entity); - foreach ($reflection->getProperties() as $property) { - - $propertyName = $property->getName(); - $propertyReflection = $entity::propertyReflection($propertyName); - if ($propertyReflection !== null) { - $columnName = $entity::columnName($propertyReflection); - - if ($propertyName === $key) { - $value = $entity->getRawData()[$columnName]; - - if (in_array($value, $values, false)) { - $result[$entity->getPrimaryKeyValue()] = $entity; - } - } - } - } - } - - return array_values($result); - - } - - return array_values($entities); - } - - -} \ No newline at end of file diff --git a/src/Repository/Saver/Saver.php b/src/Repository/Saver/Saver.php index ff94cd3..66c4d92 100644 --- a/src/Repository/Saver/Saver.php +++ b/src/Repository/Saver/Saver.php @@ -5,11 +5,8 @@ use JetBrains\PhpStorm\Pure; use PDO; use Zrnik\MkSQL\Exceptions\MkSQLException; -use Zrnik\MkSQL\Repository\Attributes\FetchArray; -use Zrnik\MkSQL\Repository\Attributes\ForeignKey; use Zrnik\MkSQL\Repository\BaseEntity; use Zrnik\MkSQL\Utilities\EntityReflection\EntityReflection; -use Zrnik\MkSQL\Utilities\Reflection; use function array_key_exists; use function count; use function in_array; @@ -47,8 +44,8 @@ public function saveEntities(array $entities): void $chunkByTables = self::chunkByTables($orderedInserts); - foreach($chunkByTables as $insertChunk) { - foreach(array_chunk($insertChunk, self::DEFAULT_INSERT_CHUNK_SIZE) as $chunk) { + foreach ($chunkByTables as $insertChunk) { + foreach (array_chunk($insertChunk, self::DEFAULT_INSERT_CHUNK_SIZE) as $chunk) { $this->insert($chunk); } } @@ -113,7 +110,7 @@ private function subEntitiesOf(BaseEntity $entity): array { $subEntities = []; - foreach(EntityReflection::getFetchArrayProperties($entity) as $fetchArrayData) { + foreach (EntityReflection::getFetchArrayProperties($entity) as $fetchArrayData) { $propertyName = $fetchArrayData->getPropertyName(); foreach ($entity->$propertyName as $subEntity) { $subEntities[] = $subEntity; @@ -132,13 +129,13 @@ private function supEntitiesOf(BaseEntity $entity): array { $superiorEntities = []; - foreach(EntityReflection::getForeignKeys($entity) as $foreignKeyData) { + foreach (EntityReflection::getForeignKeys($entity) as $foreignKeyData) { $initialized = $foreignKeyData->getProperty()->isInitialized($entity); if (!$initialized) { continue; } $propertyName = $foreignKeyData->getPropertyName(); - // $superiorEntities[] = $entity->$propertyName; + $superiorEntities[] = $entity->$propertyName; } return $superiorEntities; } @@ -187,7 +184,7 @@ private function insert(array $entities): void } // We need at least one entity - if(count($entities) <= 0) { + if (count($entities) <= 0) { return; } @@ -195,15 +192,15 @@ private function insert(array $entities): void //region Remove primary key from data $primaryKeyName = $entities[0]::getPrimaryKeyName(); - $primaryKeyKey = array_search($primaryKeyName,$dataKeys,true); - if($primaryKeyKey !== false) { + $primaryKeyKey = array_search($primaryKeyName, $dataKeys, true); + if ($primaryKeyKey !== false) { unset($dataKeys[$primaryKeyKey]); } //endregion $tableName = $entities[0]::getTableName(); - $sql = sprintf( + $sql = sprintf( 'INSERT INTO %s (%s) VALUES %s;', $tableName, implode(',', $dataKeys), @@ -213,7 +210,7 @@ private function insert(array $entities): void $values = []; foreach ($entities as $entity) { $data = $entity->toArray(); - foreach($dataKeys as $dataKey) { + foreach ($dataKeys as $dataKey) { $values[] = $data[$dataKey]; } } @@ -224,12 +221,12 @@ private function insert(array $entities): void $stmt->execute($values); //region Update `PRIMARY KEY`s - $lastPk = (int) $this->pdo->lastInsertId(); + $lastPk = (int)$this->pdo->lastInsertId(); //region Fix for MySQL/MariaDB /** @see https://www.php.net/manual/en/pdo.lastinsertid.php#122009 */ $driver = $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME); - if(strtolower($driver) === 'mysql') { + if (strtolower($driver) === 'mysql') { $lastPk += count($entities) - 1; } //endregion @@ -257,8 +254,8 @@ private static function createPlaceholderRows(int $count, int $placeholderAmount { $result = ''; - for($i = 0; $i < $count; $i++) { - $result .= sprintf('%s(%s)',$i === 0 ? ' ' : ', ', self::createPlaceholders($placeholderAmount)); + for ($i = 0; $i < $count; $i++) { + $result .= sprintf('%s(%s)', $i === 0 ? ' ' : ', ', self::createPlaceholders($placeholderAmount)); } return trim($result); @@ -272,8 +269,8 @@ private static function createPlaceholders(int $count): string { $result = ''; - for($i = 0; $i < $count; $i++) { - $result .= sprintf('%s?',$i === 0 ? ' ' : ', '); + for ($i = 0; $i < $count; $i++) { + $result .= sprintf('%s?', $i === 0 ? ' ' : ', '); } return trim($result); @@ -287,8 +284,8 @@ private static function chunkByTables(array $entities): array { $orderByTable = []; - foreach($entities as $entity) { - if(!array_key_exists($entity::class, $orderByTable)) { + foreach ($entities as $entity) { + if (!array_key_exists($entity::class, $orderByTable)) { $orderByTable[$entity::class] = []; } $orderByTable[$entity::class][] = $entity; diff --git a/src/Tracy/Measure.php b/src/Tracy/Measure.php index 2df39c4..c1908d1 100644 --- a/src/Tracy/Measure.php +++ b/src/Tracy/Measure.php @@ -29,12 +29,12 @@ class Measure public static function reportTotalSpeed(float $microTime): void { - static::$_totalSpeed += $microTime; + self::$_totalSpeed += $microTime; } public static function getTotalSpeed(): float { - return static::$_totalSpeed; + return self::$_totalSpeed; } //endregion @@ -46,7 +46,7 @@ public static function getTotalSpeed(): float $errorQueries = []; - foreach (static::getQueryModification() as $query) { + foreach (self::getQueryModification() as $query) { if ($query->errorText !== null) { $errorQueries[] = $query; } @@ -83,42 +83,42 @@ public static function logTableSpeed(string $tableName, int $type, float $speed) throw new InvalidArgumentException("Invalid type '" . $type . "' for measurement!"); } - if (!isset(static::$_tableSpeeds[$tableName])) { - static::$_tableSpeeds[$tableName] = []; + if (!isset(self::$_tableSpeeds[$tableName])) { + self::$_tableSpeeds[$tableName] = []; } - if (!isset(static::$_tableSpeeds[$tableName][$type])) { - static::$_tableSpeeds[$tableName][$type] = 0; + if (!isset(self::$_tableSpeeds[$tableName][$type])) { + self::$_tableSpeeds[$tableName][$type] = 0; } - static::$_tableSpeeds[$tableName][$type] += $speed; + self::$_tableSpeeds[$tableName][$type] += $speed; } public static function getTableSpeed(string $tableName, int $type): float { - if (!isset(static::$_tableSpeeds[$tableName])) { - static::$_tableSpeeds[$tableName] = []; + if (!isset(self::$_tableSpeeds[$tableName])) { + self::$_tableSpeeds[$tableName] = []; } - if (!isset(static::$_tableSpeeds[$tableName][$type])) { - static::$_tableSpeeds[$tableName][$type] = 0; + if (!isset(self::$_tableSpeeds[$tableName][$type])) { + self::$_tableSpeeds[$tableName][$type] = 0; } - return static::$_tableSpeeds[$tableName][$type]; + return self::$_tableSpeeds[$tableName][$type]; } public static function getTableTotalSpeed(?string $checkedTable = null): float { $speed = 0; - foreach (static::$_tableSpeeds as $tableName => $measurements) { + foreach (self::$_tableSpeeds as $tableName => $measurements) { if ($checkedTable !== null && $checkedTable !== $tableName) { continue; } - $speed += static::getTableSpeed($tableName, self::TABLE_SPEED_DESCRIBE); - $speed += static::getTableSpeed($tableName, self::TABLE_SPEED_GENERATE); - $speed += static::getTableSpeed($tableName, self::TABLE_SPEED_EXECUTE); + $speed += self::getTableSpeed($tableName, self::TABLE_SPEED_DESCRIBE); + $speed += self::getTableSpeed($tableName, self::TABLE_SPEED_GENERATE); + $speed += self::getTableSpeed($tableName, self::TABLE_SPEED_EXECUTE); } return $speed; @@ -144,7 +144,7 @@ public static function getTableTotalSpeed(?string $checkedTable = null): float */ public static function getQueryDescription(): array { - return static::$_DescriptionQueries; + return self::$_DescriptionQueries; } /** @@ -152,24 +152,24 @@ public static function getQueryDescription(): array */ public static function getQueryModification(): array { - return static::$_ModificationQueries; + return self::$_ModificationQueries; } public static function reportQueryDescription(QueryInfo $query): void { - static::$_DescriptionQueries[] = $query; + self::$_DescriptionQueries[] = $query; } public static function reportQueryModification(Query $query): void { - static::$_ModificationQueries[] = $query; + self::$_ModificationQueries[] = $query; } public static function querySpeedDescription(): float { $speed = 0; - foreach (static::$_DescriptionQueries as $descQuery) { + foreach (self::$_DescriptionQueries as $descQuery) { $speed += $descQuery->executionSpeed; } @@ -180,7 +180,7 @@ public static function querySpeedModification(): float { $speed = 0; - foreach (static::$_ModificationQueries as $modQuery) { + foreach (self::$_ModificationQueries as $modQuery) { $speed += $modQuery->speed; } @@ -190,12 +190,12 @@ public static function querySpeedModification(): float public static function queryCountDescription(): float { - return count(static::$_DescriptionQueries); + return count(self::$_DescriptionQueries); } public static function queryCountModification(): float { - return count(static::$_ModificationQueries); + return count(self::$_ModificationQueries); } //endregion @@ -203,31 +203,31 @@ public static function queryCountModification(): float //region Structure /** - * @var array + * @var array> */ private static array $_Tables = []; /** - * @var array + * @var array> */ private static array $_Columns = []; /** - * @return array + * @return array> */ public static function structureTableList(): array { - return static::$_Tables; + return self::$_Tables; } /** * @param string $tableName - * @return array + * @return array> */ public static function structureColumnList(string $tableName): array { - return static::$_Columns[$tableName] ?? []; + return self::$_Columns[$tableName] ?? []; } /** @@ -235,15 +235,15 @@ public static function structureColumnList(string $tableName): array */ public static function reportStructureTable(Table $table): void { - if (!isset(static::$_Tables[$table->getName()])) { - static::$_Tables[$table->getName()] = [ + if (!isset(self::$_Tables[$table->getName()])) { + self::$_Tables[$table->getName()] = [ 'calls' => 0, 'objects' => [] ]; } - static::$_Tables[$table->getName()]['calls']++; - static::$_Tables[$table->getName()]['objects'][] = $table; + self::$_Tables[$table->getName()]['calls']++; + self::$_Tables[$table->getName()]['objects'][] = $table; } /** @@ -252,21 +252,21 @@ public static function reportStructureTable(Table $table): void */ public static function reportStructureColumn(Table $table, Column $column): void { - if (!isset(static::$_Columns[$table->getName()])) { - static::$_Columns[$table->getName()] = []; + if (!isset(self::$_Columns[$table->getName()])) { + self::$_Columns[$table->getName()] = []; } - if (!isset(static::$_Columns[$table->getName()][$column->getName()])) { - static::$_Columns[$table->getName()][$column->getName()] = []; + if (!isset(self::$_Columns[$table->getName()][$column->getName()])) { + self::$_Columns[$table->getName()][$column->getName()] = []; } - static::$_Columns[$table->getName()][$column->getName()] = $column; + self::$_Columns[$table->getName()][$column->getName()] = $column; } #[Pure] public static function structureTableCount(): int { - return count(static::$_Tables); + return count(self::$_Tables); } /** @@ -278,7 +278,7 @@ public static function structureColumnCount(?string $filterTable = null): int { $result = 0; - foreach (static::$_Columns as $tableName => $columnList) { + foreach (self::$_Columns as $tableName => $columnList) { if ($filterTable !== null && $filterTable !== $tableName) { continue; } diff --git a/src/Tracy/Panel.php b/src/Tracy/Panel.php index 5966462..3ef1740 100644 --- a/src/Tracy/Panel.php +++ b/src/Tracy/Panel.php @@ -84,8 +84,8 @@ private function getIconStyle(int $style): array */ private function loadSvg(string $svgName): string { - if (isset(static::$_svgCache[$svgName])) { - return static::$_svgCache[$svgName]; + if (isset(self::$_svgCache[$svgName])) { + return self::$_svgCache[$svgName]; } $assetsFolder = __DIR__ . '/assets/'; @@ -102,9 +102,9 @@ private function loadSvg(string $svgName): string ); } - static::$_svgCache[$svgName] = $imageContent; + self::$_svgCache[$svgName] = $imageContent; - return static::$_svgCache[$svgName]; + return self::$_svgCache[$svgName]; } //endregion @@ -173,7 +173,7 @@ public function getTab(): ?string ); if (Measure::$Driver !== null) { - $ContentElement->addText(static::convertToMs(Measure::getTotalSpeed())); + $ContentElement->addText(self::convertToMs(Measure::getTotalSpeed())); $ContentElement->addText(' ms'); $ContentElement->addText(' / '); $ContentElement->addText(Measure::queryCountModification()); @@ -199,7 +199,7 @@ private function headerElement(bool $success = true): Html if ($success) { $topRight - ->addText(static::convertToMs(Measure::getTotalSpeed())) + ->addText(self::convertToMs(Measure::getTotalSpeed())) ->addText(' ms') ->addText(' / ') ->addText(Measure::queryCountModification()); @@ -252,7 +252,7 @@ private function subPanelSpeed(): Html Html::el('td') ->style('font-weight', 'bold') ->setText( - static::convertToMs(Measure::getTotalSpeed(), 3) . ' ms' + self::convertToMs(Measure::getTotalSpeed(), 3) . ' ms' ) ) ) @@ -325,7 +325,7 @@ private function subPanelStructure(): Html $tableObject = $_tableDefinition['objects'][0]; $totalCalls = $_tableDefinition['calls']; - $totalColumns = count(Measure::structureColumnList($tableObject->getName() ?? 'unknown table')); + $totalColumns = count(Measure::structureColumnList($tableObject->getName())); $table->addHtml(Html::el('tr') ->addHtml( @@ -338,7 +338,7 @@ private function subPanelStructure(): Html '​_', Html::el() ->setText( - $tableObject->getName() ?? 'unknown table' + $tableObject->getName() ) ->render() ) @@ -363,7 +363,7 @@ private function subPanelStructure(): Html Html::el('td') ->style('font-weight', 'bold') ->setText( - static::convertToMs( + self::convertToMs( Measure::getTableTotalSpeed($tableObject->getName()), 3 ) @@ -396,9 +396,9 @@ private function subPanelStructure(): Html ->addHtml( Html::el('td') ->setText( - static::convertToMs( + self::convertToMs( Measure::getTableSpeed( - $tableObject->getName() ?? 'unknown table', + $tableObject->getName(), Measure::TABLE_SPEED_DESCRIBE ), 3 @@ -416,9 +416,9 @@ private function subPanelStructure(): Html ->addHtml( Html::el('td') ->setText( - static::convertToMs( + self::convertToMs( Measure::getTableSpeed( - $tableObject->getName() ?? 'unknown table', + $tableObject->getName(), Measure::TABLE_SPEED_GENERATE ), 3 @@ -436,9 +436,9 @@ private function subPanelStructure(): Html ->addHtml( Html::el('td') ->setText( - static::convertToMs( + self::convertToMs( Measure::getTableSpeed( - $tableObject->getName() ?? 'unknown table', + $tableObject->getName(), Measure::TABLE_SPEED_EXECUTE ), 3 @@ -456,7 +456,7 @@ private function subPanelStructure(): Html ->addHtml( Html::el('td') ->setText( - static::convertToMs( + self::convertToMs( Measure::getTableTotalSpeed( $tableObject->getName() ), @@ -490,7 +490,7 @@ private function subPanelStructure(): Html /** @var Column $columnObject */ - foreach (Measure::structureColumnList($tableObject->getName() ?? 'unknown table') as $columnObject) { + foreach (Measure::structureColumnList($tableObject->getName()) as $columnObject) { $detailDataTable->addHtml( Html::el('tr', ['style' => ['background-color' => 'rgba(0,200,255,0.1);']]) ->addHtml( @@ -514,7 +514,7 @@ private function subPanelStructure(): Html ->addHtml( Html::el('td', ['style' => 'width: 70%;']) ->addHtml( - static::yesNo($columnObject->getNotNull()) + self::yesNo($columnObject->getNotNull()) ) ) @@ -528,7 +528,7 @@ private function subPanelStructure(): Html ->addHtml( Html::el('td') ->addHtml( - static::yesNo($columnObject->getUnique()) + self::yesNo($columnObject->getUnique()) ) ) @@ -614,7 +614,7 @@ private function subPanelStructure(): Html ->addHtml( Html::el('th') ->setText( - static::convertToMs( + self::convertToMs( Measure::getTableTotalSpeed(), 3 ) @@ -635,11 +635,11 @@ private function subPanelStructure(): Html ->addText('(') ->addText($tables) ->addText(' ') - ->addText('table' . static::s($tables)) + ->addText('table' . self::s($tables)) ->addText(', ') ->addText($columns) ->addText(' ') - ->addText('column' . static::s($columns)) + ->addText('column' . self::s($columns)) ->addText(')') , $table @@ -689,7 +689,7 @@ private function subPanelDescription(): Html ) ->addHtml( Html::el('td') - ->setText(static::convertToMs($queryInfo->executionSpeed, 3)) + ->setText(self::convertToMs($queryInfo->executionSpeed, 3)) ->addText(' ms') ) ); @@ -724,7 +724,7 @@ private function subPanelDescription(): Html ) ->addHtml( Html::el('th') - ->setText(static::convertToMs($execSpeedTotal, 3)) + ->setText(self::convertToMs($execSpeedTotal, 3)) ->addText(' ms') ) ); @@ -736,7 +736,7 @@ private function subPanelDescription(): Html ->addText(' ') ->addText('(') ->addText( - static::convertToMs( + self::convertToMs( Measure::querySpeedDescription() ) ) @@ -815,7 +815,7 @@ private function subPanelModification(): Html ]) ->addHtml( Html::el('td') - ->setText($query->getTable()->getName() ?? 'unknown table') + ->setText($query->getTable()->getName()) ) ->addHtml( Html::el('td') @@ -824,18 +824,18 @@ private function subPanelModification(): Html ->addHtml( Html::el('td') ->setHtml( - static::yesNo($query->executed, $query->executed) + self::yesNo($query->executed, $query->executed) ) ) ->addHtml( Html::el('td') ->setHtml( - static::yesNoInverted($query->errorText !== null, $query->executed) + self::yesNoInverted($query->errorText !== null, $query->executed) ) ) ->addHtml( Html::el('td') - ->setText(static::convertToMs($query->speed, 3)) + ->setText(self::convertToMs($query->speed, 3)) ->addText(' ms') ) ); @@ -923,7 +923,7 @@ private function subPanelModification(): Html ) ->addHtml( Html::el('th') - ->setText(static::convertToMs($execSpeedTotal, 3)) + ->setText(self::convertToMs($execSpeedTotal, 3)) ->addText(' ms') ) ); @@ -935,7 +935,7 @@ private function subPanelModification(): Html ->addText(' ') ->addText('(') ->addText( - static::convertToMs( + self::convertToMs( Measure::querySpeedModification() ) ) @@ -1009,7 +1009,7 @@ public function getPanel(): ?string */ private function createToggleHandle(string $id, Html $header, bool $defaultHidden = true): Html { - $id = static::createRealId($id); + $id = self::createRealId($id); return Html::el('a') ->href('#' . $id) @@ -1027,7 +1027,7 @@ private function createToggleHandle(string $id, Html $header, bool $defaultHidde */ private function createToggleContainer(string $id, string $elem, Html $content, bool $defaultHidden = true): Html { - $id = static::createRealId($id); + $id = self::createRealId($id); return Html::el($elem, ['id' => $id]) ->class('tracy-collapsed', $defaultHidden) diff --git a/src/Updater.php b/src/Updater.php index 044be3f..38874ed 100644 --- a/src/Updater.php +++ b/src/Updater.php @@ -225,7 +225,7 @@ public function install(): bool $TableDescription = $QueryMakerClass::describeTable($this->pdo, $table); Measure::logTableSpeed( - $table->getName() ?? 'unknown table', + $table->getName(), Measure::TABLE_SPEED_DESCRIBE, microtime(true) - $table_speed_prepare ); @@ -240,7 +240,7 @@ public function install(): bool } Measure::logTableSpeed( - $table->getName() ?? 'unknown table', + $table->getName(), Measure::TABLE_SPEED_GENERATE, microtime(true) - $table_speed_generate ); @@ -282,7 +282,7 @@ public function install(): bool $QueryCommand->speed = $queryExecuteSpeed; Measure::logTableSpeed( - $QueryCommand->getTable()->getName() ?? 'unknown table', + $QueryCommand->getTable()->getName(), Measure::TABLE_SPEED_EXECUTE, $queryExecuteSpeed ); diff --git a/src/Utilities/EntityReflection/EntityReflection.php b/src/Utilities/EntityReflection/EntityReflection.php index 94c9fe6..a5a4550 100644 --- a/src/Utilities/EntityReflection/EntityReflection.php +++ b/src/Utilities/EntityReflection/EntityReflection.php @@ -19,10 +19,10 @@ public static function getForeignKeys(BaseEntity|string $entity): array { $reflection = BaseEntity::getReflectionClass($entity); $result = []; - foreach($reflection->getProperties() as $reflectionProperty) { + foreach ($reflection->getProperties() as $reflectionProperty) { /** @var ?ReflectionAttribute $reflectionAttribute */ $reflectionAttribute = Reflection::propertyGetAttribute($reflectionProperty, ForeignKey::class); - if($reflectionAttribute !== null) { + if ($reflectionAttribute !== null) { $result[] = new ForeignKeyData( $reflectionProperty, $reflectionAttribute, @@ -38,12 +38,12 @@ public static function getForeignKeys(BaseEntity|string $entity): array */ public static function getFetchArrayProperties(BaseEntity|string $entity): array { - $reflection = BaseEntity::getReflectionClass($entity); + $reflection = BaseEntity::getReflectionClass($entity); $result = []; - foreach($reflection->getProperties() as $reflectionProperty) { + foreach ($reflection->getProperties() as $reflectionProperty) { /** @var ?ReflectionAttribute $reflectionAttribute */ $reflectionAttribute = Reflection::propertyGetAttribute($reflectionProperty, FetchArray::class); - if($reflectionAttribute !== null) { + if ($reflectionAttribute !== null) { $result[] = new FetchArrayData( $reflectionProperty, $reflectionAttribute, diff --git a/src/Utilities/EntityReflection/FetchArrayData.php b/src/Utilities/EntityReflection/FetchArrayData.php index 4ecaaaa..6df5912 100644 --- a/src/Utilities/EntityReflection/FetchArrayData.php +++ b/src/Utilities/EntityReflection/FetchArrayData.php @@ -16,7 +16,7 @@ class FetchArrayData * @param ReflectionAttribute $reflectionAttribute */ public function __construct( - private ReflectionProperty $reflectionProperty, + private ReflectionProperty $reflectionProperty, private ReflectionAttribute $reflectionAttribute ) { diff --git a/src/Utilities/EntityReflection/ForeignKeyData.php b/src/Utilities/EntityReflection/ForeignKeyData.php index 9356d7b..d39cca5 100644 --- a/src/Utilities/EntityReflection/ForeignKeyData.php +++ b/src/Utilities/EntityReflection/ForeignKeyData.php @@ -16,10 +16,11 @@ class ForeignKeyData * @param ReflectionAttribute $foreignKeyAttribute */ public function __construct( - private ReflectionProperty $reflectionProperty, + private ReflectionProperty $reflectionProperty, private ReflectionAttribute $foreignKeyAttribute, ) - { } + { + } public function getProperty(): ReflectionProperty { @@ -32,6 +33,9 @@ public function getPropertyName(): string return $this->getProperty()->getName(); } + /** + * @return class-string + */ public function getTargetClassName(): string { return Reflection::attributeGetArgument($this->foreignKeyAttribute); diff --git a/src/Utils.php b/src/Utils.php index 7b7db8b..94710f0 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -43,7 +43,7 @@ class Utils */ public static function internalTestCommentsError(string $name): string { - return static::confirmName($name, ['/', '*', '-']); + return self::confirmName($name, ['/', '*', '-']); } /** @@ -65,7 +65,7 @@ private static function confirmName(string $name, array $AdditionalAllowed = []) } // Remove allowed characters, if the string isn't empty, it contains invalid characters! - $Allowed = array_merge(static::$_defaultAllowedCharacters, $AdditionalAllowed); + $Allowed = array_merge(self::$_defaultAllowedCharacters, $AdditionalAllowed); if (str_replace($Allowed, '', $name) !== '') { { @@ -86,7 +86,7 @@ private static function confirmName(string $name, array $AdditionalAllowed = []) */ public static function confirmTableName(string $name): string { - return static::confirmName($name); + return self::confirmName($name); } /** @@ -98,7 +98,7 @@ public static function confirmTableName(string $name): string */ public static function confirmColumnName(string $name): string { - return static::confirmName($name); + return self::confirmName($name); } /** @@ -110,7 +110,7 @@ public static function confirmColumnName(string $name): string */ public static function confirmType(string $type): string { - return static::confirmName(str_replace(' ', '', $type), ['(', ')', ',']); + return self::confirmName(str_replace(' ', '', $type), ['(', ')', ',']); } /** @@ -128,7 +128,7 @@ public static function confirmKeyName(string $keyName, int $maxLen = 64): string return substr(md5($keyName), 0, min(32, $maxLen)); } } - return static::confirmName($keyName); + return self::confirmName($keyName); } /** @@ -140,7 +140,7 @@ public static function confirmKeyName(string $keyName, int $maxLen = 64): string */ public static function confirmForeignKeyTarget(string $keyTarget): string { - $keyTarget = static::confirmName($keyTarget, ['.']); + $keyTarget = self::confirmName($keyTarget, ['.']); if (!Strings::contains($keyTarget, '.')) { throw new InvalidArgumentException("Invalid foreign key target '" . $keyTarget . "'. Dot is missing."); @@ -169,7 +169,7 @@ public static function confirmComment(?string $name): ?string return null; } - return static::checkForbiddenWords(static::confirmName($name, [',', '.', ' '])); + return self::checkForbiddenWords(self::confirmName($name, [',', '.', ' '])); } /** @@ -182,7 +182,7 @@ public static function confirmComment(?string $name): ?string */ public static function checkForbiddenWords(string $text): string { - foreach (static::$_Forbidden as $ForbiddenWord) { + foreach (self::$_Forbidden as $ForbiddenWord) { if (Strings::contains( strtolower($text), strtolower($ForbiddenWord) diff --git a/tests/IntegrationTest.php b/tests/IntegrationTest.php index 4d41d2d..a265d18 100644 --- a/tests/IntegrationTest.php +++ b/tests/IntegrationTest.php @@ -11,7 +11,6 @@ use Brick\DateTime\LocalDateTime; use JsonException; use Nette\Neon\Neon; -use Nette\Utils\Strings; use PDO; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\TestCase; @@ -20,7 +19,11 @@ use Tests\Mock\BaseRepositoryAndBaseEntity\Entities\AuctionItem; use Tests\Mock\BaseRepositoryAndBaseEntity\Entities\AutoHydrateAndCircularReference\ReferencingEntityOne; use Tests\Mock\BaseRepositoryAndBaseEntity\HydrateTestEntities\FetchedEntity; +use Tests\Mock\BaseRepositoryAndBaseEntity\HydrateTestEntities\FetchedEntityFromSubEntity; use Tests\Mock\BaseRepositoryAndBaseEntity\HydrateTestEntities\MainEntity; +use Tests\Mock\BaseRepositoryAndBaseEntity\HydrateTestEntities\SubEntityFetchedEntity; +use Tests\Mock\BaseRepositoryAndBaseEntity\HydrateTestEntities\SubEntityOne; +use Tests\Mock\BaseRepositoryAndBaseEntity\HydrateTestEntities\SubEntityTwo; use Tests\Mock\Bugs\DoubleRetrieve\AccountEntry; use Tests\Mock\Bugs\DoubleRetrieve\DoubleRetrieveRepository; use Tests\Mock\Bugs\DoubleRetrieve\Person; @@ -72,7 +75,7 @@ public function testIntegration(): void $MySQL_VersionStatement = $MySQL_PDO->query('select version();'); $MySQL_Version = $MySQL_VersionStatement === false ? '?' : $MySQL_VersionStatement->fetch()[0]; - $this->processTest($MySQL_PDO, $MySQL_Version); + $this->runIntegrationTest($MySQL_PDO, $MySQL_Version); // SQLite Integration: //$SQLite_PDO = new PDO("sqlite::memory:"); @@ -86,7 +89,8 @@ public function testIntegration(): void $SQLite_PDO = new PDO(sprintf('sqlite:%s', $SQLiteFile)); $SQLite_VersionStatement = $SQLite_PDO->query('select sqlite_version();'); $SQLite_Version = $SQLite_VersionStatement === false ? '?' : $SQLite_VersionStatement->fetch()[0]; - $this->processTest($SQLite_PDO, $SQLite_Version); + + $this->runIntegrationTest($SQLite_PDO, $SQLite_Version); } /** @@ -169,6 +173,43 @@ private function processTest(PDO $pdo, string $version = ''): void } + + private function runIntegrationTest(PDO $pdo, string $version): void + { + $this->cleanup($pdo); + + //Yes, every test is run 2 times! + $this->processTest($pdo, $version); + $this->processTest($pdo, $version); + + $this->cleanup($pdo); + } + + private function cleanup(PDO $pdo): void + { + $clearDatabase = [ + 'last_action', 'sessions', 'accounts', 'hello', + + AuctionItem::getTableName(), + Auction::getTableName(), + + SubEntityFetchedEntity::getTableName(), + FetchedEntity::getTableName(), + FetchedEntityFromSubEntity::getTableName(), + MainEntity::getTableName(), + SubEntityOne::getTableName(), + SubEntityTwo::getTableName(), + + Reward::getTableName(), + AccountEntry::getTableName(), + Person::getTableName(), + ]; + + foreach ($clearDatabase as $tableName) { + $pdo->exec(sprintf('DROP TABLE IF EXISTS %s', $tableName)); + } + } + private function dropAll(PDO $pdo): void { //Must be in reverse order because of foreign key constraints @@ -503,18 +544,11 @@ private function subTestBaseRepoAndEntity(PDO $pdo): void static::assertCount(2, $auctionList1); $this->dot(); + $auctionRepository->save($auction1); + /** @var Auction $fetchedAuction1 */ $fetchedAuction1 = $auctionRepository->getResultByPrimaryKey(Auction::class, $auction1->id); - - /*dump("------------------------------"); - dump( - $pdo->getAttribute(PDO::ATTR_DRIVER_NAME), - false - ); - dump($auction1); - dump($fetchedAuction1);*/ - static::assertEquals($auction1, $fetchedAuction1); static::assertNotSame($auction1, $fetchedAuction1); $this->dot(); @@ -564,6 +598,7 @@ private function subTestBaseRepoAndEntity(PDO $pdo): void static::assertEquals($auction1->auctionItems[0], $fetchedAuctionItem); static::assertNotSame($auction1->auctionItems[0], $fetchedAuctionItem); + /** @var AuctionItem[] $allAuctionItems */ $allAuctionItems = $auctionRepository->getAll(AuctionItem::class); @@ -571,7 +606,6 @@ private function subTestBaseRepoAndEntity(PDO $pdo): void $allAuctionItems[0]->auction?->auctionItems[0]->whenSold ); - $allAuctionItems[0]->whenSold = LocalDateTime::of( 2020, 9, 1, 12 ); diff --git a/tests/Mock/BaseRepositoryAndBaseEntity/Entities/BadEntities/OnlyOneForeignKeyTargetingSameClass/ReferencedClassOne.php b/tests/Mock/BaseRepositoryAndBaseEntity/Entities/BadEntities/OnlyOneForeignKeyTargetingSameClass/ReferencedClassOne.php new file mode 100644 index 0000000..001e5cf --- /dev/null +++ b/tests/Mock/BaseRepositoryAndBaseEntity/Entities/BadEntities/OnlyOneForeignKeyTargetingSameClass/ReferencedClassOne.php @@ -0,0 +1,14 @@ +assertNoExceptionThrown( + function () use ($updater) { + $updater->use(ReferencingBothIsOk::class); + } + ); + + $this->assertExceptionThrown( + MultipleForeignKeysTargetingSameClassException::class, + function () use ($updater) { + $updater->use(ReferencingSameMultipleTimeNotOK::class); + } + ); } } diff --git a/tests/Repository/Fetcher/FetcherMock/Entities/Manufacturer.php b/tests/Repository/Fetcher/FetcherMock/Entities/Manufacturer.php index e737dfe..719ac71 100644 --- a/tests/Repository/Fetcher/FetcherMock/Entities/Manufacturer.php +++ b/tests/Repository/Fetcher/FetcherMock/Entities/Manufacturer.php @@ -2,6 +2,7 @@ namespace Tests\Repository\Fetcher\FetcherMock\Entities; +use Zrnik\MkSQL\Repository\Attributes\ColumnName; use Zrnik\MkSQL\Repository\Attributes\ColumnType; use Zrnik\MkSQL\Repository\Attributes\FetchArray; use Zrnik\MkSQL\Repository\Attributes\PrimaryKey; @@ -12,6 +13,7 @@ class Manufacturer extends BaseEntity { #[PrimaryKey] + #[ColumnName('mn')] public ?int $id = null; /** @var Car[] $cars */ diff --git a/tests/Repository/Fetcher/FetcherTest.php b/tests/Repository/Fetcher/FetcherTest.php index 4f5d0e4..98e3228 100644 --- a/tests/Repository/Fetcher/FetcherTest.php +++ b/tests/Repository/Fetcher/FetcherTest.php @@ -19,7 +19,7 @@ class FetcherTest extends TestCase public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); - static::$repository = new FetcherTestRepository( + self::$repository = new FetcherTestRepository( new PDO('sqlite::memory:') ); } @@ -35,12 +35,15 @@ public static function setUpBeforeClass(): void */ public function testFetcher(): void { - static::assertNotNull(static::$repository); + static::assertNotNull(self::$repository); $tesla = Manufacturer::create(); $tesla->name = 'Tesla'; - static::$repository->save($tesla); + $c = Car::create(); + $c->name = 'Model G'; + $tesla->cars[] = $c; + self::$repository->save($tesla); $manufacturer = Manufacturer::create(); $manufacturer->name = 'Cheng Car'; @@ -59,24 +62,25 @@ public function testFetcher(): void $this->addPart($car2, 'wheels'); $manufacturer->cars[] = $car2; - static::$repository->save($manufacturer); + self::$repository->save($manufacturer); - $car1Fetched = static::$repository->getCarById($car1->id ?? -1); + $car1Fetched = self::$repository->getCarById($car1->id ?? -1); static::assertNotNull($car1Fetched); static::assertSame($car1->id, $car1Fetched->id); - $car2Fetched = static::$repository->getCarById($car2->id ?? -1); + $car2Fetched = self::$repository->getCarById($car2->id ?? -1); static::assertNotNull($car2Fetched); static::assertSame($car2->id, $car2Fetched->id); } - private function addPart(Car $car, string $partName): void + private function addPart(Car $car, string $partName): Part { $newPart = Part::create(); $newPart->car = $car; $newPart->name = $partName; $car->parts[] = $newPart; + return $newPart; } } diff --git a/tests/TableTest.php b/tests/TableTest.php index 7178134..8558290 100644 --- a/tests/TableTest.php +++ b/tests/TableTest.php @@ -256,7 +256,8 @@ public function testColumnCreateForeign(): void ); } - public function testGetParent():void { + public function testGetParent(): void + { $updater = new Updater(new PDO()); $tableNoParent = new Table('noParent'); $tableYesParent = $updater->tableCreate('yesParent'); diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index ac01daa..156bf26 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -23,7 +23,7 @@ public function testForbiddenWords(): void { $this->assertExceptionThrown( InvalidArgumentException::class, - function() { + function () { Utils::checkForbiddenWords('CONSTRAINT'); } ); diff --git a/tests/createTest.md b/tests/createTest.md index fd149b0..e8185d3 100644 --- a/tests/createTest.md +++ b/tests/createTest.md @@ -1,8 +1,7 @@ Udelat test: -Pokud Ukazuju s FetchArray na nejakou entitu, a ona ukazuje zpátky s -více než jednou 'foreignKey' property, vyhodit vyjimku! +Pokud Ukazuju s FetchArray na nejakou entitu, a ona ukazuje zpátky s více než jednou 'foreignKey' property, vyhodit +vyjimku! -Otestovat ze pokud ma entita pres FetchArray nejake childy, ale -child entita má foreignKey ukazujici na neco jinneho nez na me/nebo unset -tak tu forignKey propertky zmenime na sebe! \ No newline at end of file +Otestovat ze pokud ma entita pres FetchArray nejake childy, ale child entita má foreignKey ukazujici na neco jinneho nez +na me/nebo unset tak tu forignKey propertky zmenime na sebe! \ No newline at end of file