From c901091b1eb6fa6c549d66a292e361bb975d3ffd Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 9 Jun 2026 12:33:43 +0000 Subject: [PATCH 1/2] Add PHPStan rule verifying #[DbQuery] contracts (MVP) Introduce a self-contained PHPStan extension under tools/phpstan/ that statically checks the cross-artifact invariants of Ray.MediaQuery #[DbQuery] interface methods that PHPStan core cannot see: - rayMediaQuery.sqlFileNotFound / emptySqlFile: the {id}.sql backing a #[DbQuery('id')] exists in a configured directory and is non-empty. - rayMediaQuery.pagerReturnMismatch / missingPagerAttribute: #[Pager] is present iff the return type is a PagesInterface. - rayMediaQuery.invalidFactory: a declared factory: class exists and exposes the configured factory method (static or instance). Invalid type: literals are intentionally left to PHPStan core, which already reports them via the 'row'|'row_list' constructor type. The extension ships its own phpstan + phpunit so RuleTestCase can run (the repo's vendor-bin/tools has phpstan but no phpunit, the root has phpunit but no phpstan). It is wired into the repo phpstan.neon against the tutorial SQL set, and rule code self-analyses at level max. https://claude.ai/code/session_01HWD3hygK9SGrLvZvehW28x --- .gitignore | 3 + composer.json | 1 + phpstan.neon | 7 + tools/phpstan/README.md | 98 +++++++++++ tools/phpstan/bootstrap.php | 18 ++ tools/phpstan/composer.json | 33 ++++ tools/phpstan/extension.neon | 26 +++ tools/phpstan/phpstan.neon.dist | 6 + tools/phpstan/phpunit.xml.dist | 11 ++ .../phpstan/src/Rules/DbQueryContractRule.php | 166 ++++++++++++++++++ tools/phpstan/src/Support/AttributeFinder.php | 38 ++++ .../phpstan/src/Support/DbQueryAttribute.php | 60 +++++++ tools/phpstan/src/Support/SqlFileResolver.php | 50 ++++++ .../tests/Fixture/Data/FactoryInterface.php | 19 ++ .../Data/FactoryWithoutFactoryMethod.php | 9 + .../tests/Fixture/Data/PagerInterface.php | 24 +++ .../tests/Fixture/Data/SqlFilesInterface.php | 19 ++ .../tests/Fixture/Data/ValidFactory.php | 15 ++ .../phpstan/tests/Fixture/sql/empty_query.sql | 2 + .../tests/Fixture/sql/existing_query.sql | 1 + .../tests/Rules/DbQueryContractRuleTest.php | 67 +++++++ 21 files changed, 673 insertions(+) create mode 100644 tools/phpstan/README.md create mode 100644 tools/phpstan/bootstrap.php create mode 100644 tools/phpstan/composer.json create mode 100644 tools/phpstan/extension.neon create mode 100644 tools/phpstan/phpstan.neon.dist create mode 100644 tools/phpstan/phpunit.xml.dist create mode 100644 tools/phpstan/src/Rules/DbQueryContractRule.php create mode 100644 tools/phpstan/src/Support/AttributeFinder.php create mode 100644 tools/phpstan/src/Support/DbQueryAttribute.php create mode 100644 tools/phpstan/src/Support/SqlFileResolver.php create mode 100644 tools/phpstan/tests/Fixture/Data/FactoryInterface.php create mode 100644 tools/phpstan/tests/Fixture/Data/FactoryWithoutFactoryMethod.php create mode 100644 tools/phpstan/tests/Fixture/Data/PagerInterface.php create mode 100644 tools/phpstan/tests/Fixture/Data/SqlFilesInterface.php create mode 100644 tools/phpstan/tests/Fixture/Data/ValidFactory.php create mode 100644 tools/phpstan/tests/Fixture/sql/empty_query.sql create mode 100644 tools/phpstan/tests/Fixture/sql/existing_query.sql create mode 100644 tools/phpstan/tests/Rules/DbQueryContractRuleTest.php diff --git a/.gitignore b/.gitignore index 8eeb092..db0cc62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ /vendor/ /vendor-bin/*/vendor/ +/tools/phpstan/vendor/ +/tools/phpstan/composer.lock +/tools/phpstan/.phpunit.cache/ /build/ /composer.lock /phpunit.xml diff --git a/composer.json b/composer.json index d1863b5..7e94c6d 100644 --- a/composer.json +++ b/composer.json @@ -42,6 +42,7 @@ "tests/", "tests/Fake" ], + "Ray\\MediaQuery\\PHPStan\\": "tools/phpstan/src/", "Tutorial\\Blog\\": "docs/tutorial/src/Blog/" } }, diff --git a/phpstan.neon b/phpstan.neon index 59a88a0..1752f2c 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,3 +1,6 @@ +includes: + - tools/phpstan/extension.neon + parameters: level: max paths: @@ -8,3 +11,7 @@ parameters: - tests/Fake/* - tests/tmp/* - src/MediaQueryModule.php + rayMediaQuery: + sqlDirectories: + - %currentWorkingDirectory%/docs/tutorial/src/sql + factoryMethod: factory diff --git a/tools/phpstan/README.md b/tools/phpstan/README.md new file mode 100644 index 0000000..228b46c --- /dev/null +++ b/tools/phpstan/README.md @@ -0,0 +1,98 @@ +# ray/media-query-phpstan + +PHPStan rules that statically verify the `#[DbQuery]` contract of +Ray.MediaQuery interfaces — the cross-artifact invariants that PHPStan core +cannot see on its own (SQL files, `#[Pager]` coherence, factory existence). + +This currently lives in-repo as a development tool under `tools/phpstan/`. It is +structured as a self-contained Composer package so it can later be extracted to +a standalone `ray/media-query-phpstan` distribution unchanged. + +## What it checks (MVP) + +The MVP is intentionally scoped to checks with near-zero false positives: + +| Identifier | Meaning | +| --- | --- | +| `rayMediaQuery.sqlFileNotFound` | `#[DbQuery('id')]` has no `{sqlDir}/id.sql` in any configured directory. | +| `rayMediaQuery.emptySqlFile` | The resolved `id.sql` exists but is empty. | +| `rayMediaQuery.pagerReturnMismatch` | `#[Pager]` is present but the return type is not a `PagesInterface`. | +| `rayMediaQuery.missingPagerAttribute` | The return type is a `PagesInterface` but `#[Pager]` is missing. | +| `rayMediaQuery.invalidFactory` | `factory:` names a class/method that does not exist. | + +Not implemented on purpose: + +- **Invalid `type:` value** — PHPStan core already reports this via the + `'row'|'row_list'` constructor type of `DbQuery` (`argument.type`). +- **Placeholder ↔ parameter matching** — deferred until the SQL lexer lands; it + needs `#[Input]` flattening and `#[SqlTemplate]` handling to avoid false + positives. + +## Usage + +Add the extension to your `phpstan.neon` and point it at your SQL directories: + +```neon +includes: + - tools/phpstan/extension.neon + +parameters: + rayMediaQuery: + sqlDirectories: + - %currentWorkingDirectory%/path/to/sql + factoryMethod: factory # default: 'factory' + strict: false # reserved for later phases + strictPlaceholderCheck: false # reserved for later phases +``` + +When `sqlDirectories` is empty the SQL existence/empty checks are skipped; the +Pager and factory checks still run. SQL ids are a flat, globally-unique +namespace, so each id is searched across every configured directory. + +## Caveat: SQL changes and PHPStan's result cache + +PHPStan's result cache is keyed on PHP files and their PHP dependencies. A change +to a `.sql` file alone does **not** invalidate the cache, so a stale +`sqlFileNotFound` / `emptySqlFile` result can persist locally. CI runs are +unaffected because they start from a clean cache. Locally, after changing SQL +files, run: + +```bash +composer clean # clears PHPStan + Psalm caches +``` + +## Developing / testing the rules + +The package carries its own `phpstan` + `phpunit` so `PHPStan\Testing\RuleTestCase` +has both available (the repo's `vendor-bin/tools` has phpstan but no phpunit, and +the root has phpunit but no phpstan — neither can run rule tests alone). + +```bash +cd tools/phpstan +composer install +composer test # or: ./vendor/bin/phpunit +``` + +Self-analyse the rule code at level max: + +```bash +cd tools/phpstan +./vendor/bin/phpstan analyse -c phpstan.neon.dist +``` + +## Layout + +``` +tools/phpstan/ + extension.neon # parameters schema + service registration + phpstan.neon.dist # self-analysis of the rule code + src/ + Rules/DbQueryContractRule.php + Support/AttributeFinder.php + Support/DbQueryAttribute.php + Support/SqlFileResolver.php + tests/ + Rules/DbQueryContractRuleTest.php + Fixture/Data/*.php # interfaces/classes analysed by the rule tests + Fixture/sql/*.sql # SQL fixtures +``` diff --git a/tools/phpstan/bootstrap.php b/tools/phpstan/bootstrap.php new file mode 100644 index 0000000..d2913f7 --- /dev/null +++ b/tools/phpstan/bootstrap.php @@ -0,0 +1,18 @@ + + + + + tests/Rules + + + + + + diff --git a/tools/phpstan/src/Rules/DbQueryContractRule.php b/tools/phpstan/src/Rules/DbQueryContractRule.php new file mode 100644 index 0000000..ce1ddf1 --- /dev/null +++ b/tools/phpstan/src/Rules/DbQueryContractRule.php @@ -0,0 +1,166 @@ + + */ +final class DbQueryContractRule implements Rule +{ + public function __construct( + private SqlFileResolver $sqlFileResolver, + private ReflectionProvider $reflectionProvider, + private string $factoryMethod, + ) { + } + + public function getNodeType(): string + { + return InClassMethodNode::class; + } + + /** @return list */ + public function processNode(Node $node, Scope $scope): array + { + $classMethod = $node->getOriginalNode(); + $dbQueryNode = AttributeFinder::find($classMethod, DbQuery::class); + if ($dbQueryNode === null) { + return []; + } + + $dbQuery = DbQueryAttribute::fromNode($dbQueryNode, $scope); + $returnType = $node->getMethodReflection()->getReturnType(); + $hasPager = AttributeFinder::has($classMethod, Pager::class); + + return array_merge( + $this->checkSqlFile($dbQuery), + $this->checkPager($hasPager, $returnType), + $this->checkFactory($dbQuery), + ); + } + + /** @return list */ + private function checkSqlFile(DbQueryAttribute $dbQuery): array + { + if ($dbQuery->id === null || ! $this->sqlFileResolver->isConfigured()) { + return []; + } + + $path = $this->sqlFileResolver->resolve($dbQuery->id); + if ($path === null) { + return [ + RuleErrorBuilder::message(sprintf( + 'SQL file "%s.sql" for #[DbQuery(\'%s\')] was not found in configured sqlDirectories (%s).', + $dbQuery->id, + $dbQuery->id, + $this->sqlFileResolver->describeDirectories(), + ))->identifier('rayMediaQuery.sqlFileNotFound')->build(), + ]; + } + + if (trim((string) file_get_contents($path)) === '') { + return [ + RuleErrorBuilder::message(sprintf( + 'SQL file "%s" for #[DbQuery(\'%s\')] is empty.', + $path, + $dbQuery->id, + ))->identifier('rayMediaQuery.emptySqlFile')->build(), + ]; + } + + return []; + } + + /** @return list */ + private function checkPager(bool $hasPager, Type $returnType): array + { + $pagesType = new ObjectType(PagesInterface::class); + $isPages = $pagesType->isSuperTypeOf($returnType); + + if ($hasPager && $isPages->no()) { + return [ + RuleErrorBuilder::message(sprintf( + '#[Pager] requires the return type to be %s, but %s is declared.', + PagesInterface::class, + $returnType->describe(VerbosityLevel::typeOnly()), + ))->identifier('rayMediaQuery.pagerReturnMismatch')->build(), + ]; + } + + if (! $hasPager && $isPages->yes()) { + return [ + RuleErrorBuilder::message(sprintf( + 'Return type %s requires a #[Pager] attribute.', + $returnType->describe(VerbosityLevel::typeOnly()), + ))->identifier('rayMediaQuery.missingPagerAttribute')->build(), + ]; + } + + return []; + } + + /** @return list */ + private function checkFactory(DbQueryAttribute $dbQuery): array + { + $factory = $dbQuery->factory; + if ($factory === null || $factory === '') { + return []; + } + + if (! $this->reflectionProvider->hasClass($factory)) { + return [ + RuleErrorBuilder::message(sprintf( + 'Factory class %s declared in #[DbQuery] does not exist.', + $factory, + ))->identifier('rayMediaQuery.invalidFactory')->build(), + ]; + } + + if (! $this->reflectionProvider->getClass($factory)->hasMethod($this->factoryMethod)) { + return [ + RuleErrorBuilder::message(sprintf( + 'Factory method %s::%s() declared in #[DbQuery] does not exist.', + $factory, + $this->factoryMethod, + ))->identifier('rayMediaQuery.invalidFactory')->build(), + ]; + } + + return []; + } +} diff --git a/tools/phpstan/src/Support/AttributeFinder.php b/tools/phpstan/src/Support/AttributeFinder.php new file mode 100644 index 0000000..c02e1e5 --- /dev/null +++ b/tools/phpstan/src/Support/AttributeFinder.php @@ -0,0 +1,38 @@ +attrGroups as $group) { + foreach ($group->attrs as $attr) { + if (ltrim($attr->name->toString(), '\\') === $needle) { + return $attr; + } + } + } + + return null; + } + + public static function has(ClassMethod $method, string $fqcn): bool + { + return self::find($method, $fqcn) !== null; + } +} diff --git a/tools/phpstan/src/Support/DbQueryAttribute.php b/tools/phpstan/src/Support/DbQueryAttribute.php new file mode 100644 index 0000000..f9b98ba --- /dev/null +++ b/tools/phpstan/src/Support/DbQueryAttribute.php @@ -0,0 +1,60 @@ + Constructor parameter order of Ray\MediaQuery\Annotation\DbQuery. */ + private const PARAMETER_ORDER = ['id', 'type', 'factory']; + + public function __construct( + public readonly string|null $id, + public readonly string|null $type, + public readonly string|null $factory, + ) { + } + + public static function fromNode(Attribute $attr, Scope $scope): self + { + $values = []; + $position = 0; + foreach ($attr->args as $arg) { + if ($arg->name !== null) { + $name = $arg->name->toString(); + } else { + $name = self::PARAMETER_ORDER[$position] ?? null; + $position++; + } + + if ($name === null) { + continue; + } + + $constantStrings = $scope->getType($arg->value)->getConstantStrings(); + if (count($constantStrings) === 1) { + $values[$name] = $constantStrings[0]->getValue(); + } + } + + return new self( + $values['id'] ?? null, + $values['type'] ?? null, + $values['factory'] ?? null, + ); + } +} diff --git a/tools/phpstan/src/Support/SqlFileResolver.php b/tools/phpstan/src/Support/SqlFileResolver.php new file mode 100644 index 0000000..9ac0182 --- /dev/null +++ b/tools/phpstan/src/Support/SqlFileResolver.php @@ -0,0 +1,50 @@ + */ + private array $directories; + + /** @param list $directories */ + public function __construct(array $directories) + { + $this->directories = $directories; + } + + public function isConfigured(): bool + { + return $this->directories !== []; + } + + public function resolve(string $id): string|null + { + foreach ($this->directories as $dir) { + $path = rtrim($dir, '/') . '/' . $id . '.sql'; + if (is_file($path)) { + return $path; + } + } + + return null; + } + + public function describeDirectories(): string + { + return implode(', ', $this->directories); + } +} diff --git a/tools/phpstan/tests/Fixture/Data/FactoryInterface.php b/tools/phpstan/tests/Fixture/Data/FactoryInterface.php new file mode 100644 index 0000000..a93d282 --- /dev/null +++ b/tools/phpstan/tests/Fixture/Data/FactoryInterface.php @@ -0,0 +1,19 @@ + */ +final class DbQueryContractRuleTest extends RuleTestCase +{ + private const SQL_DIR = __DIR__ . '/../Fixture/sql'; + + protected function getRule(): Rule + { + return new DbQueryContractRule( + new SqlFileResolver([self::SQL_DIR]), + $this->createReflectionProvider(), + 'factory', + ); + } + + public function testSqlFileExistence(): void + { + $this->analyse([__DIR__ . '/../Fixture/Data/SqlFilesInterface.php'], [ + [ + 'SQL file "missing_query.sql" for #[DbQuery(\'missing_query\')] was not found in configured sqlDirectories (' . self::SQL_DIR . ').', + 14, + ], + [ + 'SQL file "' . self::SQL_DIR . '/empty_query.sql" for #[DbQuery(\'empty_query\')] is empty.', + 17, + ], + ]); + } + + public function testPagerCoherence(): void + { + $this->analyse([__DIR__ . '/../Fixture/Data/PagerInterface.php'], [ + [ + '#[Pager] requires the return type to be Ray\MediaQuery\PagesInterface, but array is declared.', + 13, + ], + [ + 'Return type Ray\MediaQuery\Pages requires a #[Pager] attribute.', + 16, + ], + ]); + } + + public function testFactoryExistence(): void + { + $this->analyse([__DIR__ . '/../Fixture/Data/FactoryInterface.php'], [ + [ + 'Factory class Ray\MediaQuery\PHPStan\Tests\Fixture\Data\MissingFactory declared in #[DbQuery] does not exist.', + 14, + ], + [ + 'Factory method Ray\MediaQuery\PHPStan\Tests\Fixture\Data\FactoryWithoutFactoryMethod::factory() declared in #[DbQuery] does not exist.', + 17, + ], + ]); + } +} From e0da9b1dafae91ee0aad270182836b3637acfcfb Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 12 Jun 2026 18:04:13 +0000 Subject: [PATCH 2/2] Move PHPStan extension into vendor-bin/ bamarni bin Address review feedback: the extension's isolated dependency set conflicted with the repo convention (tool deps live under vendor-bin/ via bamarni/composer-bin-plugin). Relocate the whole package from tools/phpstan/ to vendor-bin/media-query-phpstan/ so it is installed as its own bamarni bin, matching vendor-bin/tools/. - Relocate package; root autoload-dev and phpstan.neon include now point at vendor-bin/media-query-phpstan/. - .gitignore: drop the bespoke tools/phpstan/* entries; the existing /vendor-bin/*/vendor/ rule covers the vendor dir, and composer.lock is committed to match vendor-bin/tools/. Ignore /vendor-bin/*/.phpunit.cache/. - bootstrap.php still resolves the parent autoloader (two levels up), so the root binaries can drive the extension's phpunit/phpstan configs: ./vendor/bin/phpunit -c vendor-bin/media-query-phpstan ./vendor/bin/phpstan analyse -c vendor-bin/media-query-phpstan/phpstan.neon.dist - README: update paths/commands and add the missing fenced-block language tag (markdownlint MD040). composer sa, composer test (109), the extension rule tests (3) and the rule self-analysis all pass after the move. https://claude.ai/code/session_01HWD3hygK9SGrLvZvehW28x --- .gitignore | 4 +- composer.json | 2 +- phpstan.neon | 2 +- .../media-query-phpstan}/README.md | 31 +- .../media-query-phpstan}/bootstrap.php | 0 .../media-query-phpstan}/composer.json | 0 vendor-bin/media-query-phpstan/composer.lock | 1867 +++++++++++++++++ .../media-query-phpstan}/extension.neon | 0 .../media-query-phpstan}/phpstan.neon.dist | 0 .../media-query-phpstan}/phpunit.xml.dist | 0 .../src/Rules/DbQueryContractRule.php | 0 .../src/Support/AttributeFinder.php | 0 .../src/Support/DbQueryAttribute.php | 0 .../src/Support/SqlFileResolver.php | 0 .../tests/Fixture/Data/FactoryInterface.php | 0 .../Data/FactoryWithoutFactoryMethod.php | 0 .../tests/Fixture/Data/PagerInterface.php | 0 .../tests/Fixture/Data/SqlFilesInterface.php | 0 .../tests/Fixture/Data/ValidFactory.php | 0 .../tests/Fixture/sql/empty_query.sql | 0 .../tests/Fixture/sql/existing_query.sql | 0 .../tests/Rules/DbQueryContractRuleTest.php | 0 22 files changed, 1887 insertions(+), 19 deletions(-) rename {tools/phpstan => vendor-bin/media-query-phpstan}/README.md (72%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/bootstrap.php (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/composer.json (100%) create mode 100644 vendor-bin/media-query-phpstan/composer.lock rename {tools/phpstan => vendor-bin/media-query-phpstan}/extension.neon (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/phpstan.neon.dist (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/phpunit.xml.dist (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/src/Rules/DbQueryContractRule.php (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/src/Support/AttributeFinder.php (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/src/Support/DbQueryAttribute.php (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/src/Support/SqlFileResolver.php (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/tests/Fixture/Data/FactoryInterface.php (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/tests/Fixture/Data/FactoryWithoutFactoryMethod.php (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/tests/Fixture/Data/PagerInterface.php (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/tests/Fixture/Data/SqlFilesInterface.php (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/tests/Fixture/Data/ValidFactory.php (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/tests/Fixture/sql/empty_query.sql (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/tests/Fixture/sql/existing_query.sql (100%) rename {tools/phpstan => vendor-bin/media-query-phpstan}/tests/Rules/DbQueryContractRuleTest.php (100%) diff --git a/.gitignore b/.gitignore index db0cc62..9bbad46 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,6 @@ /vendor/ /vendor-bin/*/vendor/ -/tools/phpstan/vendor/ -/tools/phpstan/composer.lock -/tools/phpstan/.phpunit.cache/ +/vendor-bin/*/.phpunit.cache/ /build/ /composer.lock /phpunit.xml diff --git a/composer.json b/composer.json index 7e94c6d..fed5c21 100644 --- a/composer.json +++ b/composer.json @@ -42,7 +42,7 @@ "tests/", "tests/Fake" ], - "Ray\\MediaQuery\\PHPStan\\": "tools/phpstan/src/", + "Ray\\MediaQuery\\PHPStan\\": "vendor-bin/media-query-phpstan/src/", "Tutorial\\Blog\\": "docs/tutorial/src/Blog/" } }, diff --git a/phpstan.neon b/phpstan.neon index 1752f2c..58a7bbe 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ includes: - - tools/phpstan/extension.neon + - vendor-bin/media-query-phpstan/extension.neon parameters: level: max diff --git a/tools/phpstan/README.md b/vendor-bin/media-query-phpstan/README.md similarity index 72% rename from tools/phpstan/README.md rename to vendor-bin/media-query-phpstan/README.md index 228b46c..c05acfe 100644 --- a/tools/phpstan/README.md +++ b/vendor-bin/media-query-phpstan/README.md @@ -4,9 +4,11 @@ PHPStan rules that statically verify the `#[DbQuery]` contract of Ray.MediaQuery interfaces — the cross-artifact invariants that PHPStan core cannot see on its own (SQL files, `#[Pager]` coherence, factory existence). -This currently lives in-repo as a development tool under `tools/phpstan/`. It is -structured as a self-contained Composer package so it can later be extracted to -a standalone `ray/media-query-phpstan` distribution unchanged. +This currently lives in-repo under `vendor-bin/media-query-phpstan/`, installed as +its own isolated dependency set via `bamarni/composer-bin-plugin` (the same +convention the repo uses for `vendor-bin/tools/`). It is structured as a +self-contained Composer package so it can later be extracted to a standalone +`ray/media-query-phpstan` distribution unchanged. ## What it checks (MVP) @@ -34,7 +36,7 @@ Add the extension to your `phpstan.neon` and point it at your SQL directories: ```neon includes: - - tools/phpstan/extension.neon + - vendor-bin/media-query-phpstan/extension.neon parameters: rayMediaQuery: @@ -63,27 +65,28 @@ composer clean # clears PHPStan + Psalm caches ## Developing / testing the rules -The package carries its own `phpstan` + `phpunit` so `PHPStan\Testing\RuleTestCase` -has both available (the repo's `vendor-bin/tools` has phpstan but no phpunit, and -the root has phpunit but no phpstan — neither can run rule tests alone). +This bin carries its own `phpstan` + `phpunit` so `PHPStan\Testing\RuleTestCase` +has both available in one vendor (the repo's `vendor-bin/tools` has phpstan but no +phpunit, and the root has phpunit but no phpstan — neither can run rule tests +alone). Install it with the bamarni forward command, then run the tests; the +package `bootstrap.php` makes both the rule code and the parent project types +available, so the root binaries can drive the extension's configs: ```bash -cd tools/phpstan -composer install -composer test # or: ./vendor/bin/phpunit +composer bin media-query-phpstan install +./vendor/bin/phpunit -c vendor-bin/media-query-phpstan ``` Self-analyse the rule code at level max: ```bash -cd tools/phpstan -./vendor/bin/phpstan analyse -c phpstan.neon.dist +./vendor/bin/phpstan analyse -c vendor-bin/media-query-phpstan/phpstan.neon.dist ``` ## Layout -``` -tools/phpstan/ +```text +vendor-bin/media-query-phpstan/ extension.neon # parameters schema + service registration phpstan.neon.dist # self-analysis of the rule code src/ diff --git a/tools/phpstan/bootstrap.php b/vendor-bin/media-query-phpstan/bootstrap.php similarity index 100% rename from tools/phpstan/bootstrap.php rename to vendor-bin/media-query-phpstan/bootstrap.php diff --git a/tools/phpstan/composer.json b/vendor-bin/media-query-phpstan/composer.json similarity index 100% rename from tools/phpstan/composer.json rename to vendor-bin/media-query-phpstan/composer.json diff --git a/vendor-bin/media-query-phpstan/composer.lock b/vendor-bin/media-query-phpstan/composer.lock new file mode 100644 index 0000000..21c6332 --- /dev/null +++ b/vendor-bin/media-query-phpstan/composer.lock @@ -0,0 +1,1867 @@ +{ + "_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": "5fb12363f0dbe7030ebe98f6dbac8e3e", + "packages": [ + { + "name": "phpstan/phpstan", + "version": "2.2.2", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e5cc34d491a90e79c216d824f60fe21fd4d93bd6", + "reference": "e5cc34d491a90e79c216d824f60fe21fd4d93bd6", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ondřej Mirtes" + }, + { + "name": "Markus Staab" + }, + { + "name": "Vincent Langlet" + } + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2026-06-05T09:00:01+00:00" + } + ], + "packages-dev": [ + { + "name": "myclabs/deep-copy", + "version": "1.13.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "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.13.4" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-08-01T08:46:24+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.7.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-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/v5.7.0" + }, + "time": "2025-12-06T11:56:16+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "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.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "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.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "11.0.12", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56", + "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.7.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.1", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.3.1" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.46" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.0.x-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", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" + } + ], + "time": "2025-12-24T07:01:01+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "5.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903", + "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.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": "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", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator", + "type": "tidelift" + } + ], + "time": "2026-02-02T13:52:54+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.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", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:08:43+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.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", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:09:35+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "11.5.55", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/adc7262fccc12de2b30f12a8aa0b33775d814f00", + "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.12", + "phpunit/php-file-iterator": "^5.1.1", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.3", + "sebastian/comparator": "^6.3.3", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.1", + "sebastian/exporter": "^6.3.2", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/recursion-context": "^6.0.3", + "sebastian/type": "^5.1.3", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "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", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.55" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2026-02-18T12:37:06+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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 for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:41:36+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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": "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", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-19T07:56:08+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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": "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", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.3.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", + "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.3-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", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2026-01-24T09:26:40+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.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", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:49:50+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.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", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "sebastian/environment", + "version": "7.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.2-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": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" + } + ], + "time": "2025-05-21T11:55:47+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.3.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74", + "reference": "70a298763b40b213ec087c51c739efcaa90bcd74", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.3-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": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" + } + ], + "time": "2025-09-24T06:12:51+00:00" + }, + { + "name": "sebastian/global-state", + "version": "7.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.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": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:57:36+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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 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", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:58:38+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.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", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:00:13+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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": "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", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:01:32+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "6.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.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": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" + } + ], + "time": "2025-08-13T04:42:22+00:00" + }, + { + "name": "sebastian/type", + "version": "5.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.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": "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", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" + } + ], + "time": "2025-08-09T06:55:48+00:00" + }, + { + "name": "sebastian/version", + "version": "5.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "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": "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", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-09T05:16:32+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", + "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.3.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2025-11-17T20:03:58+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.2" + }, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/tools/phpstan/extension.neon b/vendor-bin/media-query-phpstan/extension.neon similarity index 100% rename from tools/phpstan/extension.neon rename to vendor-bin/media-query-phpstan/extension.neon diff --git a/tools/phpstan/phpstan.neon.dist b/vendor-bin/media-query-phpstan/phpstan.neon.dist similarity index 100% rename from tools/phpstan/phpstan.neon.dist rename to vendor-bin/media-query-phpstan/phpstan.neon.dist diff --git a/tools/phpstan/phpunit.xml.dist b/vendor-bin/media-query-phpstan/phpunit.xml.dist similarity index 100% rename from tools/phpstan/phpunit.xml.dist rename to vendor-bin/media-query-phpstan/phpunit.xml.dist diff --git a/tools/phpstan/src/Rules/DbQueryContractRule.php b/vendor-bin/media-query-phpstan/src/Rules/DbQueryContractRule.php similarity index 100% rename from tools/phpstan/src/Rules/DbQueryContractRule.php rename to vendor-bin/media-query-phpstan/src/Rules/DbQueryContractRule.php diff --git a/tools/phpstan/src/Support/AttributeFinder.php b/vendor-bin/media-query-phpstan/src/Support/AttributeFinder.php similarity index 100% rename from tools/phpstan/src/Support/AttributeFinder.php rename to vendor-bin/media-query-phpstan/src/Support/AttributeFinder.php diff --git a/tools/phpstan/src/Support/DbQueryAttribute.php b/vendor-bin/media-query-phpstan/src/Support/DbQueryAttribute.php similarity index 100% rename from tools/phpstan/src/Support/DbQueryAttribute.php rename to vendor-bin/media-query-phpstan/src/Support/DbQueryAttribute.php diff --git a/tools/phpstan/src/Support/SqlFileResolver.php b/vendor-bin/media-query-phpstan/src/Support/SqlFileResolver.php similarity index 100% rename from tools/phpstan/src/Support/SqlFileResolver.php rename to vendor-bin/media-query-phpstan/src/Support/SqlFileResolver.php diff --git a/tools/phpstan/tests/Fixture/Data/FactoryInterface.php b/vendor-bin/media-query-phpstan/tests/Fixture/Data/FactoryInterface.php similarity index 100% rename from tools/phpstan/tests/Fixture/Data/FactoryInterface.php rename to vendor-bin/media-query-phpstan/tests/Fixture/Data/FactoryInterface.php diff --git a/tools/phpstan/tests/Fixture/Data/FactoryWithoutFactoryMethod.php b/vendor-bin/media-query-phpstan/tests/Fixture/Data/FactoryWithoutFactoryMethod.php similarity index 100% rename from tools/phpstan/tests/Fixture/Data/FactoryWithoutFactoryMethod.php rename to vendor-bin/media-query-phpstan/tests/Fixture/Data/FactoryWithoutFactoryMethod.php diff --git a/tools/phpstan/tests/Fixture/Data/PagerInterface.php b/vendor-bin/media-query-phpstan/tests/Fixture/Data/PagerInterface.php similarity index 100% rename from tools/phpstan/tests/Fixture/Data/PagerInterface.php rename to vendor-bin/media-query-phpstan/tests/Fixture/Data/PagerInterface.php diff --git a/tools/phpstan/tests/Fixture/Data/SqlFilesInterface.php b/vendor-bin/media-query-phpstan/tests/Fixture/Data/SqlFilesInterface.php similarity index 100% rename from tools/phpstan/tests/Fixture/Data/SqlFilesInterface.php rename to vendor-bin/media-query-phpstan/tests/Fixture/Data/SqlFilesInterface.php diff --git a/tools/phpstan/tests/Fixture/Data/ValidFactory.php b/vendor-bin/media-query-phpstan/tests/Fixture/Data/ValidFactory.php similarity index 100% rename from tools/phpstan/tests/Fixture/Data/ValidFactory.php rename to vendor-bin/media-query-phpstan/tests/Fixture/Data/ValidFactory.php diff --git a/tools/phpstan/tests/Fixture/sql/empty_query.sql b/vendor-bin/media-query-phpstan/tests/Fixture/sql/empty_query.sql similarity index 100% rename from tools/phpstan/tests/Fixture/sql/empty_query.sql rename to vendor-bin/media-query-phpstan/tests/Fixture/sql/empty_query.sql diff --git a/tools/phpstan/tests/Fixture/sql/existing_query.sql b/vendor-bin/media-query-phpstan/tests/Fixture/sql/existing_query.sql similarity index 100% rename from tools/phpstan/tests/Fixture/sql/existing_query.sql rename to vendor-bin/media-query-phpstan/tests/Fixture/sql/existing_query.sql diff --git a/tools/phpstan/tests/Rules/DbQueryContractRuleTest.php b/vendor-bin/media-query-phpstan/tests/Rules/DbQueryContractRuleTest.php similarity index 100% rename from tools/phpstan/tests/Rules/DbQueryContractRuleTest.php rename to vendor-bin/media-query-phpstan/tests/Rules/DbQueryContractRuleTest.php