From aebe9cdddc1bf71079ca45864d5fcc69f70d72ef Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Mon, 24 Aug 2026 16:11:10 +1000 Subject: [PATCH 1/7] Bump to PHP 8.3 minimum, migrate to Mago QA toolchain, add Pdo\Result coverage php-db/phpdb 0.6.x added getQueryResult() to Driver\ResultInterface, which Sqlite already satisfies for free via the shared core Pdo\Result class (no sqlite-owned Result class exists). Ports the core's exhaustive Pdo\Result unit test suite to cover it, matching the coverage mysql/pgsql carry for their own Result classes. Also replaces laminas-coding-standard/phpstan with the shared php-db/phpdb-qa-tools Mago toolchain, mirroring phpdb-qa-analysis-sql: mago.toml extending the shared base, the qa-tools phpunit.xml.dist template, mago-based composer scripts, and the reusable CI workflow. Pre-existing lint/analyzer findings in untouched code are captured in lint-baseline.toml/analyzer-baseline.toml rather than fixed here. --- .github/workflows/continuous-integration.yml | 32 +- .laminas-ci.json | 12 - analyzer-baseline.toml | 751 ++++++++++++ composer.json | 24 +- composer.lock | 546 +-------- lint-baseline.toml | 1021 +++++++++++++++++ mago.toml | 12 + phpcs.xml.dist | 23 - phpstan-baseline.neon | 2 - phpstan.neon.dist | 17 - phpunit.xml.dist | 33 +- test/unit/Pdo/ResultTest.php | 453 ++++++++ .../unit/Pdo/TestAsset/TemporaryResultSet.php | 9 + 13 files changed, 2332 insertions(+), 603 deletions(-) delete mode 100644 .laminas-ci.json create mode 100644 analyzer-baseline.toml create mode 100644 lint-baseline.toml create mode 100644 mago.toml delete mode 100644 phpcs.xml.dist delete mode 100644 phpstan-baseline.neon delete mode 100644 phpstan.neon.dist create mode 100644 test/unit/Pdo/ResultTest.php create mode 100644 test/unit/Pdo/TestAsset/TemporaryResultSet.php diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 25bc29b..9c67ec6 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -1,31 +1,15 @@ name: "Continuous Integration" on: - pull_request: push: - branches: - tags: + pull_request: jobs: - matrix: - name: Generate job matrix - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.matrix.outputs.matrix }} - steps: - - name: Gather CI configuration - id: matrix - uses: laminas/laminas-ci-matrix-action@v1 - qa: - name: QA Checks - needs: [matrix] - runs-on: ${{ matrix.operatingSystem }} - strategy: - fail-fast: false - matrix: ${{ fromJSON(needs.matrix.outputs.matrix) }} - steps: - - name: ${{ matrix.name }} - uses: laminas/laminas-continuous-integration-action@v1 - with: - job: ${{ matrix.job }} \ No newline at end of file + uses: php-db/phpdb-qa-tools/.github/workflows/continuous-integration.yml@0.1.x + secrets: inherit + with: + php-versions: '["8.3", "8.4", "8.5"]' + run-integration: true + enable-codecov: false + enable-infection: false diff --git a/.laminas-ci.json b/.laminas-ci.json deleted file mode 100644 index 10c530b..0000000 --- a/.laminas-ci.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "additional_checks": [ - { - "name": "PhpStan", - "job": { - "php": "8.2", - "dependencies": "latest", - "command": "composer require --dev phpstan/phpstan && vendor/bin/phpstan analyse" - } - } - ] -} \ No newline at end of file diff --git a/analyzer-baseline.toml b/analyzer-baseline.toml new file mode 100644 index 0000000..1914077 --- /dev/null +++ b/analyzer-baseline.toml @@ -0,0 +1,751 @@ +variant = "loose" + +[[issues]] +file = "src/AdapterPlatform.php" +code = "class-must-be-final" +message = 'Class `PhpDb\Sqlite\AdapterPlatform` should be declared `final`.' +count = 1 + +[[issues]] +file = "src/AdapterPlatform.php" +code = "falsable-return-statement" +message = '''Function `PhpDb\Sqlite\AdapterPlatform::quoteTrustedValue` is declared to return `null|string` but possibly returns 'false' (inferred as `false|string`).''' +count = 1 + +[[issues]] +file = "src/AdapterPlatform.php" +code = "falsable-return-statement" +message = '''Function `PhpDb\Sqlite\AdapterPlatform::quoteValue` is declared to return `string` but possibly returns 'false' (inferred as `false|string`).''' +count = 1 + +[[issues]] +file = "src/AdapterPlatform.php" +code = "invalid-return-statement" +message = 'Invalid return type for function `PhpDb\Sqlite\AdapterPlatform::quoteTrustedValue`: expected `null|string`, but found `false|string`.' +count = 1 + +[[issues]] +file = "src/AdapterPlatform.php" +code = "invalid-return-statement" +message = 'Invalid return type for function `PhpDb\Sqlite\AdapterPlatform::quoteValue`: expected `string`, but found `false|string`.' +count = 1 + +[[issues]] +file = "src/AdapterPlatform.php" +code = "missing-constant-type" +message = "Class constant `PLATFORM_NAME` is missing a type hint." +count = 1 + +[[issues]] +file = "src/AdapterPlatform.php" +code = "possibly-invalid-argument" +message = "Possible argument type mismatch for argument #1 of `PDO::quote`: expected `string`, but possibly received `bool|float|int|string`." +count = 1 + +[[issues]] +file = "src/ConfigProvider.php" +code = "imprecise-type" +message = "Type `array` in return type of `__invoke` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/ConfigProvider.php" +code = "imprecise-type" +message = "Type `array` in return type of `getConfig` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/ConfigProvider.php" +code = "imprecise-type" +message = "Type `array` in return type of `getDependencies` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Container/MetadataInterfaceFactory.php" +code = "imprecise-type" +message = "Type `array` in parameter `$options` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Container/MetadataInterfaceFactory.php" +code = "missing-constant-type" +message = "Class constant `ADAPTER_SERVICE_NAME` is missing a type hint." +count = 1 + +[[issues]] +file = "src/Container/MetadataInterfaceFactory.php" +code = "mixed-argument" +message = 'Invalid argument type for argument #1 of `PhpDb\Metadata\Source\AbstractSource::__construct`: expected `PhpDb\Adapter\AdapterInterface&PhpDb\Adapter\SchemaAwareInterface`, but found `mixed`.' +count = 1 + +[[issues]] +file = "src/Container/MetadataInterfaceFactory.php" +code = "mixed-argument" +message = 'Invalid argument type for argument #1 of `Psr\Container\ContainerInterface::get`: expected `string`, but found `nonnull`.' +count = 1 + +[[issues]] +file = "src/Container/MetadataInterfaceFactory.php" +code = "mixed-assignment" +message = "Assigning `nonnull` type to a variable may lead to unexpected behavior." +count = 1 + +[[issues]] +file = "src/Container/MetadataInterfaceFactory.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `Psr\Container\ContainerExceptionInterface` in `PhpDb\Sqlite\Container\MetadataInterfaceFactory::__invoke`.' +count = 1 + +[[issues]] +file = "src/Container/MetadataInterfaceFactory.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `Psr\Container\NotFoundExceptionInterface` in `PhpDb\Sqlite\Container\MetadataInterfaceFactory::__invoke`.' +count = 1 + +[[issues]] +file = "src/Container/MetadataInterfaceFactory.php" +code = "unused-parameter" +message = "Parameter `$requestedName` is never used." +count = 1 + +[[issues]] +file = "src/Container/PdoConnectionFactory.php" +code = "imprecise-type" +message = "Type `array` in parameter `$options` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Container/PdoConnectionFactory.php" +code = "mixed-argument" +message = 'Invalid argument type for argument #2 of `PhpDb\Adapter\Exception\InvalidConnectionParametersException::__construct`: expected `array`, but found `nonnull`.' +count = 1 + +[[issues]] +file = "src/Container/PdoConnectionFactory.php" +code = "mixed-assignment" +message = "Assigning `nonnull` type to a variable may lead to unexpected behavior." +count = 1 + +[[issues]] +file = "src/Container/PdoConnectionFactory.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `PhpDb\Adapter\Exception\InvalidConnectionParametersException` in `PhpDb\Sqlite\Container\PdoConnectionFactory::__invoke`.' +count = 1 + +[[issues]] +file = "src/Container/PdoConnectionFactory.php" +code = "unused-parameter" +message = "Parameter `$container` is never used." +count = 1 + +[[issues]] +file = "src/Container/PdoConnectionFactory.php" +code = "unused-parameter" +message = "Parameter `$requestedName` is never used." +count = 1 + +[[issues]] +file = "src/Container/PdoDriverInterfaceFactory.php" +code = "imprecise-type" +message = "Type `array` in parameter `$options` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Container/PdoDriverInterfaceFactory.php" +code = "mixed-argument" +message = 'Invalid argument type for argument #2 of `Laminas\ServiceManager\ServiceManager::build`: expected `array|null`, but found `nonnull`.' +count = 1 + +[[issues]] +file = "src/Container/PdoDriverInterfaceFactory.php" +code = "redundant-docblock-type" +message = "Redundant docblock type for variable `$connectionInstance`." +count = 1 + +[[issues]] +file = "src/Container/PdoDriverInterfaceFactory.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `Laminas\ServiceManager\Exception\ServiceNotCreatedException` in `PhpDb\Sqlite\Container\PdoDriverInterfaceFactory::__invoke`.' +count = 1 + +[[issues]] +file = "src/Container/PdoDriverInterfaceFactory.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `Psr\Container\ContainerExceptionInterface` in `PhpDb\Sqlite\Container\PdoDriverInterfaceFactory::__invoke`.' +count = 1 + +[[issues]] +file = "src/Container/PdoDriverInterfaceFactory.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `Psr\Container\NotFoundExceptionInterface` in `PhpDb\Sqlite\Container\PdoDriverInterfaceFactory::__invoke`.' +count = 1 + +[[issues]] +file = "src/Container/PdoDriverInterfaceFactory.php" +code = "unused-parameter" +message = "Parameter `$requestedName` is never used." +count = 1 + +[[issues]] +file = "src/Container/PdoResultFactory.php" +code = "unused-parameter" +message = "Parameter `$container` is never used." +count = 1 + +[[issues]] +file = "src/Container/PdoStatementFactory.php" +code = "imprecise-type" +message = "Type `array` in parameter `$options` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Container/PdoStatementFactory.php" +code = "possibly-null-argument" +message = 'Argument #1 of method `PhpDb\Adapter\Driver\Pdo\Statement::__construct` is possibly `null`, but parameter type `array` does not accept it.' +count = 1 + +[[issues]] +file = "src/Container/PdoStatementFactory.php" +code = "unused-parameter" +message = "Parameter `$container` is never used." +count = 1 + +[[issues]] +file = "src/Container/PdoStatementFactory.php" +code = "unused-parameter" +message = "Parameter `$requestedName` is never used." +count = 1 + +[[issues]] +file = "src/Container/PlatformInterfaceFactory.php" +code = "imprecise-type" +message = "Type `array` in parameter `$options` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Container/PlatformInterfaceFactory.php" +code = "mixed-assignment" +message = "Assigning `mixed` type to a variable may lead to unexpected behavior." +count = 1 + +[[issues]] +file = "src/Container/PlatformInterfaceFactory.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `PhpDb\Exception\ContainerException` in `PhpDb\Sqlite\Container\PlatformInterfaceFactory::__invoke`.' +count = 1 + +[[issues]] +file = "src/Container/PlatformInterfaceFactory.php" +code = "unused-parameter" +message = "Parameter `$container` is never used." +count = 1 + +[[issues]] +file = "src/Container/PlatformInterfaceFactory.php" +code = "unused-parameter" +message = "Parameter `$requestedName` is never used." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "imprecise-type" +message = "Type `array` in parameter `$re` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "imprecise-type" +message = "Type `array` in return type of `fetchPragma` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "invalid-return-statement" +message = 'Invalid return type for function `PhpDb\Sqlite\Metadata\Source::getIdentifierChainRegularExpression`: expected `string`, but found `null|truthy-string`.' +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "invalid-return-statement" +message = 'Invalid return type for function `PhpDb\Sqlite\Metadata\Source::getIdentifierListRegularExpression`: expected `string`, but found `null|truthy-string`.' +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "invalid-return-statement" +message = 'Invalid return type for function `PhpDb\Sqlite\Metadata\Source::getIdentifierRegularExpression`: expected `string`, but found `null|truthy-literal-string`.' +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "less-specific-nested-argument-type" +message = "Argument type mismatch for argument #2 of `implode`: expected `array|null`, but provided type `array` is less specific." +count = 2 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-argument" +message = 'Invalid argument type for argument #1 of `PhpDb\Sqlite\Metadata\Source::parseTrigger`: expected `string`, but found `mixed`.' +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-argument" +message = 'Invalid argument type for argument #1 of `PhpDb\Sqlite\Metadata\Source::parseView`: expected `string`, but found `mixed`.' +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-argument" +message = "Invalid argument type for argument #1 of `strtoupper`: expected `string`, but found `mixed`." +count = 3 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-argument" +message = 'Invalid argument type for argument #2 of `PhpDb\Sqlite\Metadata\Source::fetchPragma`: expected `null|string`, but found `mixed`.' +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-array-access" +message = "Unsafe array access on type `mixed`." +count = 25 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-array-assignment" +message = "Unsafe array assignment on type `mixed`." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-assignment" +message = "Assigning `mixed` type to a variable may lead to unexpected behavior." +count = 10 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-operand" +message = "Casting `mixed` to `bool`." +count = 3 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-operand" +message = "Invalid left operand: type `mixed` cannot be reliably used in string concatenation." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-operand" +message = "Invalid right operand: type `mixed` cannot be reliably used in string concatenation." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-operand" +message = "Left operand in binary operation has type `mixed`." +count = 2 + +[[issues]] +file = "src/Metadata/Source.php" +code = "mixed-property-type-coercion" +message = "A value with a less specific type `array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas': array{}|non-empty-list|null, 'table_names'?: array>, 'triggers'?: array>}` is being assigned to property `$data` (array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names'?: array>, 'triggers'?: array>})." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "null-array-access" +message = "Cannot perform array access on `null`." +count = 2 + +[[issues]] +file = "src/Metadata/Source.php" +code = "null-iterator" +message = "Iterating over `null` in `foreach`." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "nullable-return-statement" +message = 'Function `PhpDb\Sqlite\Metadata\Source::getIdentifierChainRegularExpression` is declared to return `string` but possibly returns a nullable value (inferred as `null|truthy-string`).' +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "nullable-return-statement" +message = 'Function `PhpDb\Sqlite\Metadata\Source::getIdentifierListRegularExpression` is declared to return `string` but possibly returns a nullable value (inferred as `null|truthy-string`).' +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "nullable-return-statement" +message = 'Function `PhpDb\Sqlite\Metadata\Source::getIdentifierRegularExpression` is declared to return `string` but possibly returns a nullable value (inferred as `null|truthy-literal-string`).' +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "possibly-null-argument" +message = "Argument #1 of function `preg_match` is possibly `null`, but parameter type `string` does not accept it." +count = 2 + +[[issues]] +file = "src/Metadata/Source.php" +code = "possibly-null-argument" +message = "Argument #1 of function `strtoupper` is possibly `null`, but parameter type `string` does not accept it." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "possibly-null-array-index" +message = "Possibly using `null` as an array index to access element." +count = 2 + +[[issues]] +file = "src/Metadata/Source.php" +code = "possibly-null-operand" +message = "Possibly null middle operand used in string concatenation (type `null|string`)." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "possibly-undefined-string-array-index" +message = "Possibly undefined array key `string('event_manipulation')` accessed on `array`." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "possibly-undefined-string-array-index" +message = "Possibly undefined array key `string('view_definition')` accessed on `array`." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "property-type-coercion" +message = "A value of a less specific type `array{'columns': non-empty-array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': mixed}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'sqlite_columns': non-empty-list, 'table_names'?: array>, 'triggers'?: array>}` is being assigned to property `$data` (array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names'?: array>, 'triggers'?: array>})." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "property-type-coercion" +message = "A value of a less specific type `array{'columns': non-empty-array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': mixed}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names'?: array>, 'triggers'?: array>}` is being assigned to property `$data` (array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names'?: array>, 'triggers'?: array>})." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "property-type-coercion" +message = "A value of a less specific type `array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints': non-empty-array, 'constraint_name'?: mixed, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: mixed, 'referenced_table_schema'?: string, 'table_name'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names'?: array>, 'triggers'?: array>}` is being assigned to property `$data` (array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names'?: array>, 'triggers'?: array>})." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "property-type-coercion" +message = "A value of a less specific type `array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names': non-empty-array}|array{'check_option'?: null|string, 'is_updatable'?: bool|null, 'table_type': string, 'view_definition'?: null|string}>>, 'triggers'?: array>}` is being assigned to property `$data` (array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names'?: array>, 'triggers'?: array>})." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "property-type-coercion" +message = "A value of a less specific type `array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names'?: array>, 'triggers': non-empty-array}|array{'action_condition': null, 'action_order': int(0), 'action_orientation': string('ROW'), 'action_reference_new_row': string('NEW'), 'action_reference_new_table': null, 'action_reference_old_row': string('OLD'), 'action_reference_old_table': null, 'action_statement': null, 'action_timing': null, 'created': null, 'event_manipulation': null, 'event_object_catalog': null, 'event_object_schema': string, 'event_object_table': mixed, 'trigger_name': mixed}|array{'action_condition': null|string, 'action_order': string, 'action_orientation': string, 'action_reference_new_row': string, 'action_reference_new_table': null|string, 'action_reference_old_row': string, 'action_reference_old_table': null|string, 'action_statement': string, 'action_timing': string, 'created': DateTime|null, 'event_manipulation': string, 'event_object_catalog': string, 'event_object_schema': string, 'event_object_table': string}>>}` is being assigned to property `$data` (array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names'?: array>, 'triggers'?: array>})." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "redundant-condition" +message = "This condition (type `true`) will always evaluate to true." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "reference-to-undefined-variable" +message = "Reference created from a previously undefined variable `$matches`." +count = 2 + +[[issues]] +file = "src/Metadata/Source.php" +code = "undefined-string-array-index" +message = "Undefined array key 'sqlite_columns' accessed on `array{'columns'?: array, 'is_nullable': bool|null, 'numeric_precision': int|null|string, 'numeric_scale': int|null|string, 'numeric_unsigned': bool|null, 'ordinal_position': int|null|string}>>>, 'constraint_keys'?: array>, 'constraint_references'?: array>, 'constraints'?: array, 'constraint_type'?: string, 'delete_rule'?: string, 'match_option'?: string, 'referenced_columns'?: list, 'referenced_table_name'?: string, 'referenced_table_schema'?: string, 'update_rule'?: string}>>>, 'schemas'?: list, 'table_names'?: array>, 'triggers'?: array>}`." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "class-must-be-final" +message = 'Class `PhpDb\Sqlite\Pdo\Connection` should be declared `final`.' +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "imprecise-type" +message = "Type `array` in parameter `$connectionParameters` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "incompatible-parameter-type" +message = 'Parameter `$name` of `PhpDb\Sqlite\Pdo\Connection::getlastgeneratedvalue()` expects type `string` but parent `PhpDb\Adapter\Driver\ConnectionInterface::getlastgeneratedvalue()` expects type `null|string`' +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "invalid-type-cast" +message = "Casting `mixed` to `array`." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "less-specific-argument" +message = "Argument type mismatch for argument #1 of `strtolower`: expected `string`, but provided type `array-key` is less specific." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "missing-constant-type" +message = "Class constant `CURRENT_SCHEMA` is missing a type hint." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "mixed-assignment" +message = "Assigning `mixed` type to a variable may lead to unexpected behavior." +count = 3 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "mixed-return-statement" +message = 'Could not infer a precise return type for function `PhpDb\Sqlite\Pdo\Connection::getLastGeneratedValue`. Saw type `mixed`.' +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "possible-method-access-on-null" +message = "Attempting to call a method on `null`." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "redundant-condition" +message = "This condition (type `true`) will always evaluate to true." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `PhpDb\Adapter\Exception\InvalidConnectionParametersException` in `PhpDb\Sqlite\Pdo\Connection::getCurrentSchema`.' +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `PhpDb\Adapter\Exception\RuntimeException` in `PhpDb\Sqlite\Pdo\Connection::getCurrentSchema`.' +count = 1 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "class-must-be-final" +message = 'Class `PhpDb\Sqlite\Pdo\Driver` should be declared `final`.' +count = 1 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "imprecise-type" +message = "Type `array` in parameter `$features` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "invalid-method-access" +message = "Attempting to access a method on a non-object type (`resource`)." +count = 1 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "invalid-operand" +message = "Left operand in `&&` operation is an `object`." +count = 1 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "invalid-property-assignment-value" +message = 'Invalid type for property `$connection`: expected `(PhpDb\Adapter\Driver\PdoConnectionInterface&PhpDb\Adapter\Driver\AbstractConnection&PhpDb\Adapter\Driver\PdoDriverAwareInterface)|PDO`, but got `(PhpDb\Adapter\Driver\PdoConnectionInterface&PhpDb\Adapter\Driver\PdoDriverAwareInterface)|PDO`.' +count = 1 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "mixed-argument" +message = 'Invalid argument type for argument #2 of `PhpDb\Adapter\Driver\Pdo\Result::initialize`: expected `false|int|null|string`, but found `mixed`.' +count = 1 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "mixed-operand" +message = "Left operand in `>` comparison has `mixed` type." +count = 1 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "non-existent-method" +message = "Method `getlastgeneratedvalue` does not exist on type `PDO`." +count = 1 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "possibly-invalid-argument" +message = 'Possible argument type mismatch for argument #1 of `PhpDb\Adapter\Driver\Pdo\Result::initialize`: expected `PDOStatement`, but possibly received `PDOStatement|resource`.' +count = 1 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "redundant-logical-operation" +message = "Redundant `&&` operation: left operand is always truthy and right operand is evaluated." +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "class-must-be-final" +message = 'Class `PhpDb\Sqlite\Pdo\Feature\SqliteRowCounter` should be declared `final`.' +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "docblock-type-mismatch" +message = "Docblock type mismatch for variable `$pdo`." +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "invalid-method-access" +message = "Attempting to access a method on a non-object type (`false`)." +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "missing-constructor" +message = 'Class `PhpDb\Sqlite\Pdo\Feature\SqliteRowCounter` has typed properties without default values but no constructor to initialize them.' +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "mixed-array-access" +message = "Unsafe array access on type `mixed`." +count = 2 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "mixed-assignment" +message = "Assigning `mixed` type to a variable may lead to unexpected behavior." +count = 2 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "mixed-method-access" +message = "Attempting to access a method on a non-object type (`mixed`)." +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "possible-method-access-on-null" +message = "Attempting to call a method on `null`." +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "possibly-null-argument" +message = 'Argument #1 of method `PhpDb\Sqlite\Pdo\Feature\SqliteRowCounter::getCountForSql` is possibly `null`, but parameter type `string` does not accept it.' +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `PDOException` in `PhpDb\Sqlite\Pdo\Feature\SqliteRowCounter::getCountForSql`.' +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `PhpDb\Adapter\Exception\InvalidQueryException` in `PhpDb\Sqlite\Pdo\Feature\SqliteRowCounter::getCountForStatement`.' +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "unhandled-thrown-type" +message = 'Potentially unhandled exception `PhpDb\Adapter\Exception\RuntimeException` in `PhpDb\Sqlite\Pdo\Feature\SqliteRowCounter::getCountForStatement`.' +count = 1 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "imprecise-type" +message = "Type `array` in return type of `processOffset` is imprecise, equivalent to `array`." +count = 1 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "incompatible-parameter-type" +message = 'Parameter `$subject` of `PhpDb\Sqlite\Sql\SelectDecorator::setsubject()` expects type `PhpDb\Sql\Select` but parent `PhpDb\Sql\Platform\PlatformDecoratorInterface::setsubject()` expects type `PhpDb\Sql\PreparableSqlInterface|PhpDb\Sql\SqlInterface|null`' +count = 1 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "invalid-property-assignment-value" +message = "Invalid type for property `$specifications`: expected `array>|array`, but got `array{'limit': string('LIMIT 18446744073709551615'), ...|string>}`." +count = 1 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "invalid-return-statement" +message = 'Invalid return type for function `PhpDb\Sqlite\Sql\SelectDecorator::processLimit`: expected `array|array|null`, but found `list{int|string}`.' +count = 1 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "missing-override-attribute" +message = 'Missing `#[Override]` attribute on overriding method `PhpDb\Sqlite\Sql\SelectDecorator::localizeVariables`.' +count = 1 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "missing-override-attribute" +message = 'Missing `#[Override]` attribute on overriding method `PhpDb\Sqlite\Sql\SelectDecorator::processLimit`.' +count = 1 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "missing-override-attribute" +message = 'Missing `#[Override]` attribute on overriding method `PhpDb\Sqlite\Sql\SelectDecorator::processOffset`.' +count = 1 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "missing-override-attribute" +message = 'Missing `#[Override]` attribute on overriding method `PhpDb\Sqlite\Sql\SelectDecorator::setSubject`.' +count = 1 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "redundant-cast" +message = "Redundant cast to `(string)`: the expression already has this type." +count = 2 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "uninitialized-property" +message = 'Property `$subject` is not initialized in the constructor of class `PhpDb\Sqlite\Sql\SelectDecorator`.' +count = 1 + +[[issues]] +file = "vendor/php-db/phpdb/src/Adapter/Driver/AbstractConnection.php" +code = "uninitialized-property" +message = 'Property `$driverName` is not initialized in the constructor of class `PhpDb\Sqlite\Pdo\Connection`.' +count = 1 + +[[issues]] +file = "vendor/php-db/phpdb/src/Adapter/Driver/Pdo/AbstractPdo.php" +code = "uninitialized-property" +message = 'Property `$profiler` is not initialized in the constructor of class `PhpDb\Sqlite\Pdo\Driver`.' +count = 1 + +[[issues]] +file = "vendor/php-db/phpdb/src/Adapter/Driver/Pdo/AbstractPdoConnection.php" +code = "uninitialized-property" +message = 'Property `$dsn` is not initialized in the constructor of class `PhpDb\Sqlite\Pdo\Connection`.' +count = 1 diff --git a/composer.json b/composer.json index f2e6ea1..d1bc897 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "config": { "sort-packages": true, "platform": { - "php": "8.2.99" + "php": "8.3.99" }, "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true @@ -30,16 +30,14 @@ } }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "php": "~8.3.0 || ~8.4.0 || ~8.5.0", "php-db/phpdb": "^0.6.0", "webmozart/assert": "^2.0" }, "require-dev": { "ext-pdo": "*", "ext-pdo_sqlite": "*", - "laminas/laminas-coding-standard": "^3.0.1", - "phpstan/phpstan": "^2.1", - "phpstan/phpstan-phpunit": "^2.0", + "php-db/phpdb-qa-tools": "0.1.x-dev", "phpunit/phpunit": "^11.5.42" }, "suggest": { @@ -59,18 +57,22 @@ "scripts": { "check": [ "@cs-check", - "@sa", + "@static-analysis", "@test", "@test-integration" ], - "cs-check": "phpcs", - "cs-fix": "phpcbf", + "cs-check": [ + "mago format --check", + "mago lint" + ], + "cs-fix": [ + "mago format", + "mago lint --fix" + ], + "static-analysis": "mago analyze", "test": "phpunit --colors=always --testsuite \"unit test\"", "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", "test-integration": "phpunit --colors=always --testsuite \"integration test\"", - "sa": "vendor/bin/phpstan analyse --memory-limit=256M", - "sa-gen-baseline": "vendor/bin/phpstan analyse --memory-limit=256M --generate-baseline", - "sa-verbose": "vendor/bin/phpstan analyse --memory-limit=256M -vv", "upload-coverage": "coveralls -v" } } diff --git a/composer.lock b/composer.lock index dd6fdc6..1a22b7b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dd8725e19686a7f5dd3dcaa1544efee1", + "content-hash": "eac5fb5580421cacc7e6da527a62a4cc", "packages": [ { "name": "brick/varexporter", @@ -201,20 +201,19 @@ }, { "name": "nikic/php-parser", - "version": "v5.7.0", + "version": "v5.8.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/044a6a392ff8ad0d61f14370a5fbbd0a0107152f", + "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f", "shasum": "" }, "require": { - "ext-ctype": "*", "ext-json": "*", "ext-tokenizer": "*", "php": ">=7.4" @@ -253,9 +252,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.8.0" }, - "time": "2025-12-06T11:56:16+00:00" + "time": "2026-07-04T14:30:18+00:00" }, { "name": "php-db/phpdb", @@ -263,30 +262,29 @@ "source": { "type": "git", "url": "https://github.com/php-db/phpdb.git", - "reference": "81844a5699bf397bf044bbe36ea90be361b4a021" + "reference": "b57f549b411d0b4fe46de8a469983816395be850" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-db/phpdb/zipball/81844a5699bf397bf044bbe36ea90be361b4a021", - "reference": "81844a5699bf397bf044bbe36ea90be361b4a021", + "url": "https://api.github.com/repos/php-db/phpdb/zipball/b57f549b411d0b4fe46de8a469983816395be850", + "reference": "b57f549b411d0b4fe46de8a469983816395be850", "shasum": "" }, "require": { "laminas/laminas-servicemanager": "^3.0.0 || ^4.0.0", "laminas/laminas-stdlib": "^3.20.0", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, "conflict": { "laminas/laminas-db": "*", "zendframework/zend-db": "*" }, "require-dev": { - "laminas/laminas-coding-standard": "^3.0.1", + "infection/infection": "^0.34.1", "laminas/laminas-eventmanager": "^3.14.0", "laminas/laminas-hydrator": "^4.6.0", + "php-db/phpdb-qa-tools": "0.1.x-dev", "phpbench/phpbench": "^1.4", - "phpstan/phpstan": "^2.1", - "phpstan/phpstan-phpunit": "^2.0", "phpunit/phpunit": "^11.5.42", "rector/rector": "^2.0" }, @@ -324,7 +322,7 @@ "issues": "https://github.com/php-db/phpdb/issues", "source": "https://github.com/php-db/phpdb" }, - "time": "2026-04-13T01:24:01+00:00" + "time": "2026-08-24T01:49:39+00:00" }, { "name": "psr/container", @@ -443,155 +441,6 @@ } ], "packages-dev": [ - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.2.1", - "source": { - "type": "git", - "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/963f0c67bffde0eac41b56be71ac0e8ba132f0bd", - "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.2", - "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" - }, - "require-dev": { - "composer/composer": "^2.2", - "ext-json": "*", - "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.4.0", - "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", - "yoast/phpunit-polyfills": "^1.0" - }, - "type": "composer-plugin", - "extra": { - "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "opensource@frenck.dev", - "homepage": "https://frenck.dev", - "role": "Open source developer" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcbf", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/composer-installer/issues", - "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", - "source": "https://github.com/PHPCSStandards/composer-installer" - }, - "funding": [ - { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcsstandards", - "type": "thanks_dev" - } - ], - "time": "2026-05-06T08:26:05+00:00" - }, - { - "name": "laminas/laminas-coding-standard", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-coding-standard.git", - "reference": "d4412caba9ed16c93cdcf301759f5ee71f9d9aea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/d4412caba9ed16c93cdcf301759f5ee71f9d9aea", - "reference": "d4412caba9ed16c93cdcf301759f5ee71f9d9aea", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.0", - "php": "^7.4 || ^8.0", - "slevomat/coding-standard": "^8.15.0", - "squizlabs/php_codesniffer": "^3.10", - "webimpress/coding-standard": "^1.3" - }, - "type": "phpcodesniffer-standard", - "autoload": { - "psr-4": { - "LaminasCodingStandard\\": "src/LaminasCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Laminas Coding Standard", - "homepage": "https://laminas.dev", - "keywords": [ - "Coding Standard", - "laminas" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-coding-standard/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-coding-standard/issues", - "rss": "https://github.com/laminas/laminas-coding-standard/releases.atom", - "source": "https://github.com/laminas/laminas-coding-standard" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2025-05-13T08:37:04+00:00" - }, { "name": "myclabs/deep-copy", "version": "1.13.4", @@ -771,160 +620,48 @@ "time": "2022-02-21T01:04:05+00:00" }, { - "name": "phpstan/phpdoc-parser", - "version": "2.3.2", + "name": "php-db/phpdb-qa-tools", + "version": "0.1.x-dev", "source": { "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", - "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", - "shasum": "" + "url": "https://github.com/php-db/phpdb-qa-tools.git", + "reference": "f2323423deac77dd719f3f2ca7a9b2a7e21c93f6" }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^5.3.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" - }, - "time": "2026-01-25T14:56:51+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "2.1.55", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9eaac3826ed5e9b8427350a43cac825eeca3f566", - "reference": "9eaac3826ed5e9b8427350a43cac825eeca3f566", + "url": "https://api.github.com/repos/php-db/phpdb-qa-tools/zipball/f2323423deac77dd719f3f2ca7a9b2a7e21c93f6", + "reference": "f2323423deac77dd719f3f2ca7a9b2a7e21c93f6", "shasum": "" }, "require": { - "php": "^7.4|^8.0" + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, - "conflict": { - "phpstan/phpstan-shim": "*" + "suggest": { + "phpunit/phpunit": "To run the shared test configuration (^11.5 || ^12.0)" }, - "bin": [ - "phpstan", - "phpstan.phar" - ], + "default-branch": true, "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" - ], - "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-05-18T11:57:34+00:00" - }, - { - "name": "phpstan/phpstan-phpunit", - "version": "2.0.16", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "6ab598e1bc106e6827fd346ae4a12b4a5d634c32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6ab598e1bc106e6827fd346ae4a12b4a5d634c32", - "reference": "6ab598e1bc106e6827fd346ae4a12b4a5d634c32", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.32" - }, - "conflict": { - "phpunit/phpunit": "<7.0" - }, - "require-dev": { - "nikic/php-parser": "^5", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-deprecation-rules": "^2.0", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" + "BSD-3-Clause" ], - "description": "PHPUnit extensions and rules for PHPStan", + "description": "Shared QA toolchain for php-db components: Mago formatting, linting and static analysis, plus the PHPUnit baseline and CI workflow.", + "homepage": "https://github.com/php-db/phpdb-qa-tools", "keywords": [ - "static analysis" + "coding-standards", + "formatter", + "linter", + "mago", + "phpdb", + "qa", + "static-analysis" ], "support": { - "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.16" + "forum": "https://github.com/php-db/phpdb-qa-tools/discussions", + "issues": "https://github.com/php-db/phpdb-qa-tools/issues", + "source": "https://github.com/php-db/phpdb-qa-tools" }, - "time": "2026-02-14T09:05:21+00:00" + "time": "2026-08-10T01:10:13+00:00" }, { "name": "phpunit/php-code-coverage", @@ -2369,150 +2106,6 @@ ], "time": "2024-10-09T05:16:32+00:00" }, - { - "name": "slevomat/coding-standard", - "version": "8.22.1", - "source": { - "type": "git", - "url": "https://github.com/slevomat/coding-standard.git", - "reference": "1dd80bf3b93692bedb21a6623c496887fad05fec" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/1dd80bf3b93692bedb21a6623c496887fad05fec", - "reference": "1dd80bf3b93692bedb21a6623c496887fad05fec", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.1.2", - "php": "^7.4 || ^8.0", - "phpstan/phpdoc-parser": "^2.3.0", - "squizlabs/php_codesniffer": "^3.13.4" - }, - "require-dev": { - "phing/phing": "3.0.1|3.1.0", - "php-parallel-lint/php-parallel-lint": "1.4.0", - "phpstan/phpstan": "2.1.24", - "phpstan/phpstan-deprecation-rules": "2.0.3", - "phpstan/phpstan-phpunit": "2.0.7", - "phpstan/phpstan-strict-rules": "2.0.6", - "phpunit/phpunit": "9.6.8|10.5.48|11.4.4|11.5.36|12.3.10" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-master": "8.x-dev" - } - }, - "autoload": { - "psr-4": { - "SlevomatCodingStandard\\": "SlevomatCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", - "keywords": [ - "dev", - "phpcs" - ], - "support": { - "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.22.1" - }, - "funding": [ - { - "url": "https://github.com/kukulich", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", - "type": "tidelift" - } - ], - "time": "2025-09-13T08:53:30+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.13.5", - "source": { - "type": "git", - "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4", - "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" - }, - "bin": [ - "bin/phpcbf", - "bin/phpcs" - ], - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "Former lead" - }, - { - "name": "Juliette Reinders Folmer", - "role": "Current lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", - "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", - "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" - }, - "funding": [ - { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcsstandards", - "type": "thanks_dev" - } - ], - "time": "2025-11-04T16:30:35+00:00" - }, { "name": "staabm/side-effects-detector", "version": "1.0.5", @@ -2614,77 +2207,24 @@ } ], "time": "2025-11-17T20:03:58+00:00" - }, - { - "name": "webimpress/coding-standard", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/webimpress/coding-standard.git", - "reference": "6f6a1a90bd9e18fc8bee0660dd1d1ce68cf9fc53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/6f6a1a90bd9e18fc8bee0660dd1d1ce68cf9fc53", - "reference": "6f6a1a90bd9e18fc8bee0660dd1d1ce68cf9fc53", - "shasum": "" - }, - "require": { - "php": "^7.3 || ^8.0", - "squizlabs/php_codesniffer": "^3.10.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.6.15" - }, - "type": "phpcodesniffer-standard", - "extra": { - "dev-master": "1.2.x-dev", - "dev-develop": "1.3.x-dev" - }, - "autoload": { - "psr-4": { - "WebimpressCodingStandard\\": "src/WebimpressCodingStandard/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "description": "Webimpress Coding Standard", - "keywords": [ - "Coding Standard", - "PSR-2", - "phpcs", - "psr-12", - "webimpress" - ], - "support": { - "issues": "https://github.com/webimpress/coding-standard/issues", - "source": "https://github.com/webimpress/coding-standard/tree/1.4.0" - }, - "funding": [ - { - "url": "https://github.com/michalbundyra", - "type": "github" - } - ], - "time": "2024-10-16T06:55:17+00:00" } ], "aliases": [], "minimum-stability": "dev", - "stability-flags": {}, + "stability-flags": { + "php-db/phpdb-qa-tools": 20 + }, "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, "platform-dev": { "ext-pdo": "*", "ext-pdo_sqlite": "*" }, "platform-overrides": { - "php": "8.2.99" + "php": "8.3.99" }, "plugin-api-version": "2.9.0" } diff --git a/lint-baseline.toml b/lint-baseline.toml new file mode 100644 index 0000000..ab917dd --- /dev/null +++ b/lint-baseline.toml @@ -0,0 +1,1021 @@ +variant = "loose" + +[[issues]] +file = "src/Container/PdoConnectionFactory.php" +code = "yoda-conditions" +message = "Use Yoda condition style for safer comparisons" +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "cyclomatic-complexity" +message = "Class has high complexity." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "halstead" +message = "Method has a high halstead volume and effort" +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "inline-variable-return" +message = "Variable assignment can be inlined into the return statement." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "kan-defect" +message = "Class has a high kan defect score." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "no-array-accumulation-in-loop" +message = "`array_merge()` called inside a loop causes O(n²) array copying." +count = 2 + +[[issues]] +file = "src/Metadata/Source.php" +code = "no-else-clause" +message = "Avoid `else` clauses." +count = 3 + +[[issues]] +file = "src/Metadata/Source.php" +code = "no-empty" +message = "Use of the `empty` construct." +count = 3 + +[[issues]] +file = "src/Metadata/Source.php" +code = "no-isset" +message = "Use of the `isset` construct." +count = 5 + +[[issues]] +file = "src/Metadata/Source.php" +code = "no-multi-assignments" +message = "Avoid multiple assignments in a single statement." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "no-negated-ternary" +message = "Negated ternary condition." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "prefer-array-spread" +message = "Use the array spread operator instead of `array_merge()`." +count = 2 + +[[issues]] +file = "src/Metadata/Source.php" +code = "prefer-early-continue" +message = "Consider using early continue pattern to reduce nesting." +count = 2 + +[[issues]] +file = "src/Metadata/Source.php" +code = "string-style" +message = "String concatenation can be replaced with interpolation." +count = 9 + +[[issues]] +file = "src/Metadata/Source.php" +code = "tagged-todo" +message = "TODO should be tagged with (@username) or (#issue)." +count = 3 + +[[issues]] +file = "src/Metadata/Source.php" +code = "too-many-methods" +message = "Class has too many methods." +count = 1 + +[[issues]] +file = "src/Metadata/Source.php" +code = "yoda-conditions" +message = "Use Yoda condition style for safer comparisons" +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "assert-description" +message = "Missing description in assert function." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "no-else-clause" +message = "Avoid `elseif` clauses." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "no-empty-catch-clause" +message = "Do not use empty `catch` blocks." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "no-fully-qualified-global-class-like" +message = "Fully-qualified class-like reference detected." +count = 1 + +[[issues]] +file = "src/Pdo/Connection.php" +code = "string-style" +message = "String concatenation can be replaced with interpolation." +count = 2 + +[[issues]] +file = "src/Pdo/Driver.php" +code = "yoda-conditions" +message = "Use Yoda condition style for safer comparisons" +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "no-empty" +message = "Use of the `empty` construct." +count = 2 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "no-fully-qualified-global-class-like" +message = "Fully-qualified class-like reference detected." +count = 2 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "prefer-arrow-function" +message = "This closure can be simplified to a more concise arrow function." +count = 1 + +[[issues]] +file = "src/Pdo/Feature/SqliteRowCounter.php" +code = "string-style" +message = "String concatenation can be replaced with interpolation." +count = 2 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "no-negated-ternary" +message = "Negated ternary condition." +count = 1 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "string-style" +message = "String concatenation can be replaced with interpolation." +count = 4 + +[[issues]] +file = "src/Sql/SelectDecorator.php" +code = "yoda-conditions" +message = "Use Yoda condition style for safer comparisons" +count = 7 + +[[issues]] +file = "test/integration/AdapterPlatformTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 1 + +[[issues]] +file = "test/integration/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testQuoteValueWithPdoSqlite`." +count = 1 + +[[issues]] +file = "test/integration/AdapterPlatformTest.php" +code = "strict-assertions" +message = "Use strict assertions in PHPUnit tests." +count = 1 + +[[issues]] +file = "test/integration/Container/PdoConnectionFactoryTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 3 + +[[issues]] +file = "test/integration/Container/PdoConnectionFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsPdoConnection`." +count = 1 + +[[issues]] +file = "test/integration/Container/PdoDriverInterfaceFactoryTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 2 + +[[issues]] +file = "test/integration/Container/PdoDriverInterfaceFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsPdoDriver`." +count = 1 + +[[issues]] +file = "test/integration/Container/PdoResultFactoryTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 2 + +[[issues]] +file = "test/integration/Container/PdoResultFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsPdoResult`." +count = 1 + +[[issues]] +file = "test/integration/Container/PdoStatementFactoryTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 2 + +[[issues]] +file = "test/integration/Container/PdoStatementFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsPdoStatement`." +count = 1 + +[[issues]] +file = "test/integration/Container/SqliteMetadataFactoryTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 2 + +[[issues]] +file = "test/integration/Container/SqliteMetadataFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testFactoryReturnsMysqlMetadata`." +count = 1 + +[[issues]] +file = "test/integration/Container/TestAsset/SetupTrait.php" +code = "yoda-conditions" +message = "Use Yoda condition style for safer comparisons" +count = 1 + +[[issues]] +file = "test/integration/Pdo/AbstractAdapterTestCase.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 9 + +[[issues]] +file = "test/integration/Pdo/AbstractAdapterTestCase.php" +code = "braced-string-interpolation" +message = "Unbraced variable in string interpolation." +count = 1 + +[[issues]] +file = "test/integration/Pdo/AbstractAdapterTestCase.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testConnection`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/AbstractAdapterTestCase.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testDriverDisconnectAfterQuoteWithPlatform`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/AbstractAdapterTestCase.php" +code = "yoda-conditions" +message = "Use Yoda condition style for safer comparisons" +count = 1 + +[[issues]] +file = "test/integration/Pdo/ConnectionIntegrationTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 11 + +[[issues]] +file = "test/integration/Pdo/ConnectionIntegrationTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testConnectReturnsConnectionWhenResourceSet`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/ConnectionIntegrationTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testConnect`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/ConnectionIntegrationTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testDisconnect`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/ConnectionIntegrationTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetCurrentSchema`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/ConnectionIntegrationTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetResource`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/ConnectionIntegrationTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testIsConnected`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/StatementTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 7 + +[[issues]] +file = "test/integration/Pdo/StatementTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testExecute`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/StatementTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetResource`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/StatementTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetSql`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/StatementTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testIsPrepared`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/StatementTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testPrepare`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/StatementTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testSetSql`." +count = 1 + +[[issues]] +file = "test/integration/Pdo/StatementTest.php" +code = "strict-assertions" +message = "Use strict assertions in PHPUnit tests." +count = 2 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 27 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "no-error-control-operator" +message = "Unsafe use of error control operator `@`." +count = 4 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testConstructWithPdoDriver`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testConstructWithPdo`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetIdentifierSeparator`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetNameReturnsSqlite`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetName`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetQuoteIdentifierSymbol`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetQuoteValueSymbol`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetSqlPlatformDecorator`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testPlatformNameConstant`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testQuoteIdentifierChain`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testQuoteIdentifierInFragment`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testQuoteIdentifier`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testQuoteTrustedValue`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testQuoteValueList`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testQuoteValueThrowsExeceptionWithoutDriverSupport`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testQuoteValue`." +count = 1 + +[[issues]] +file = "test/unit/AdapterPlatformTest.php" +code = "strict-assertions" +message = "Use strict assertions in PHPUnit tests." +count = 21 + +[[issues]] +file = "test/unit/ConfigProviderTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 13 + +[[issues]] +file = "test/unit/ConfigProviderTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetDependenciesContainsExpectedAliases`." +count = 1 + +[[issues]] +file = "test/unit/ConfigProviderTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetDependenciesContainsMetadataAlias`." +count = 1 + +[[issues]] +file = "test/unit/ConfigProviderTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetDependenciesContainsMetadataFactory`." +count = 1 + +[[issues]] +file = "test/unit/ConfigProviderTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetDependenciesReturnsCorrectStructure`." +count = 1 + +[[issues]] +file = "test/unit/ConfigProviderTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsCorrectStructure`." +count = 1 + +[[issues]] +file = "test/unit/ConfigProviderTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsExpectedStructure`." +count = 1 + +[[issues]] +file = "test/unit/Container/MetadataInterfaceFactoryTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 1 + +[[issues]] +file = "test/unit/Container/MetadataInterfaceFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsMetadata`." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoConnectionFactoryTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoConnectionFactoryTest.php" +code = "literal-named-argument" +message = "Literal argument `null` should be passed as a named argument for clarity." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoConnectionFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsConnection`." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoConnectionFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeWithNullOptionsThrows`." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoConnectionFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeWithoutConnectionConfigThrows`." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoDriverInterfaceFactoryTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoDriverInterfaceFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testFactoryExists`." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoResultFactoryTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoResultFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsResult`." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoStatementFactoryTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 2 + +[[issues]] +file = "test/unit/Container/PdoStatementFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsStatementWithEmptyOptions`." +count = 1 + +[[issues]] +file = "test/unit/Container/PdoStatementFactoryTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsStatementWithOptions`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ConnectionTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 3 + +[[issues]] +file = "test/unit/Pdo/ConnectionTest.php" +code = "no-empty-catch-clause" +message = "Do not use empty `catch` blocks." +count = 2 + +[[issues]] +file = "test/unit/Pdo/ConnectionTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testArrayOfConnectionParametersCreatesCorrectDsn`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ConnectionTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetDsn`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ConnectionTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testResource`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/DriverTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 1 + +[[issues]] +file = "test/unit/Pdo/DriverTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testFormatParameterNameWithInvalidCharacters`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/DriverTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testFormatParameterName`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/Feature/SqliteRowCounterTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 1 + +[[issues]] +file = "test/unit/Pdo/Feature/SqliteRowCounterTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testRowCounterExists`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "assert-description" +message = "Missing description in assert function." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 39 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-first-class-callable" +message = "Use first-class callable syntax `...` instead of a arrow function." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testBufferIsCallableWithNoEffect`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testCountCachesResultFromClosure`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testCountCachesResultFromStatementRowCount`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testCountWithClosureInvokesClosureAndReturnsValue`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testCountWithIntReturnsProvidedValue`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testCountWithNoRowCountFallsBackToStatementRowCount`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testCurrentReturnsSameDataOnConsecutiveCalls`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testFetchModeAcceptsNamedMode`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testFetchModeObjReturnsStdClass`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetAffectedRowsDelegatesToRowCount`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetFetchModeDefaultIsAssoc`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetFieldCountDelegatesToColumnCount`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetGeneratedValueReturnsInitializedValue`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetGeneratedValueReturnsNullByDefault`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetQueryResultClonesGivenPrototypeRatherThanMutatingIt`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetQueryResultInitializesReturnedResultSetWithThisResult`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetQueryResultReturnsDefaultResultSetPrototypeWhenNoneGiven`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetQueryResultThrowsWhenResultIsNotAQueryResult`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetResourceReturnsPdoStatement`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testInitializeStoresResourceAndValues`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testIsBufferedReturnsFalse`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testIsQueryResultReturnsFalseWhenNoColumns`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testIsQueryResultReturnsTrueWhenColumnsExist`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testNextAdvancesPositionAndFetchesData`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testRewindResetsIterationToStart`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testRewindThrowsExceptionOnForwardOnlyAfterAdvancing`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testSetFetchModeStoresValidMode`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testSetFetchModeThrowsOnInvalidFetchMode`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testSetFetchModeThrowsOnInvalidMode`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testSetStatementModeThrowsOnInvalidMode`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testSetStatementModeToForward`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testSetStatementModeToScrollable`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testValidReturnsFalseWhenCurrentDataIsFalse`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testValidReturnsTrueWhenCurrentDataExists`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/ResultTest.php" +code = "strict-assertions" +message = "Use strict assertions in PHPUnit tests." +count = 6 + +[[issues]] +file = "test/unit/Pdo/StatementIntegrationTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 12 + +[[issues]] +file = "test/unit/Pdo/StatementIntegrationTest.php" +code = "no-assign-in-argument" +message = "Avoid assignments in function call arguments." +count = 1 + +[[issues]] +file = "test/unit/Pdo/StatementIntegrationTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testStatementExecuteWillConvertPhpBoolToPdoBoolWhenBinding`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/StatementIntegrationTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testStatementExecuteWillUsePdoIntForIntWhenBinding`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/StatementIntegrationTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testStatementExecuteWillUsePdoStrByDefaultWhenBinding`." +count = 1 + +[[issues]] +file = "test/unit/Pdo/StatementIntegrationTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testStatementExecuteWillUsePdoStrForStringIntegerWhenBinding`." +count = 1 + +[[issues]] +file = "test/unit/Sql/PlatformTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 3 + +[[issues]] +file = "test/unit/Sql/PlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testConstructorSetsTypeDecorators`." +count = 1 + +[[issues]] +file = "test/unit/Sql/PlatformTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testSelectDecoratorIsRegistered`." +count = 1 + +[[issues]] +file = "test/unit/Sql/SelectDecoratorTest.php" +code = "assertion-style" +message = "Inconsistent assertions style." +count = 13 + +[[issues]] +file = "test/unit/Sql/SelectDecoratorTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testProcessLimitWithLimitAndParameterContainer`." +count = 1 + +[[issues]] +file = "test/unit/Sql/SelectDecoratorTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testProcessLimitWithLimit`." +count = 1 + +[[issues]] +file = "test/unit/Sql/SelectDecoratorTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testProcessLimitWithoutLimitAndWithoutOffset`." +count = 1 + +[[issues]] +file = "test/unit/Sql/SelectDecoratorTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testProcessLimitWithoutLimitButWithOffset`." +count = 1 + +[[issues]] +file = "test/unit/Sql/SelectDecoratorTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testProcessOffsetWithOffsetAndParameterContainer`." +count = 1 + +[[issues]] +file = "test/unit/Sql/SelectDecoratorTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testProcessOffsetWithOffset`." +count = 1 + +[[issues]] +file = "test/unit/Sql/SelectDecoratorTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testProcessOffsetWithoutOffset`." +count = 1 + +[[issues]] +file = "test/unit/Sql/SelectDecoratorTest.php" +code = "prefer-test-attribute" +message = "Use `#[Test]` attribute instead of `test` prefix on method `testSetSubject`." +count = 1 diff --git a/mago.toml b/mago.toml new file mode 100644 index 0000000..ad23c4d --- /dev/null +++ b/mago.toml @@ -0,0 +1,12 @@ +extends = "vendor/php-db/phpdb-qa-tools/mago.toml" +php-version = "8.3.0" + +[source] +paths = ["src", "test"] +includes = ["vendor"] + +[linter] +baseline = "lint-baseline.toml" + +[analyzer] +baseline = "analyzer-baseline.toml" diff --git a/phpcs.xml.dist b/phpcs.xml.dist deleted file mode 100644 index 57d45ca..0000000 --- a/phpcs.xml.dist +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - src - test - - - - - - diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon deleted file mode 100644 index 364905f..0000000 --- a/phpstan-baseline.neon +++ /dev/null @@ -1,2 +0,0 @@ -parameters: - ignoreErrors: diff --git a/phpstan.neon.dist b/phpstan.neon.dist deleted file mode 100644 index 4b4e3f6..0000000 --- a/phpstan.neon.dist +++ /dev/null @@ -1,17 +0,0 @@ -includes: - - phpstan-baseline.neon -parameters: - level: 5 - paths: - - src - - test - universalObjectCratesClasses: - - Laminas\Stdlib\ArrayObject - stubFiles: - - stubs/Laminas/ServiceManager/Factory/AbstractFactoryInterface.stub - - stubs/Laminas/ServiceManager/Factory/DelegatorFactoryInterface.stub - - stubs/Laminas/ServiceManager/Factory/FactoryInterface.stub - - stubs/Laminas/ServiceManager/Factory/InvokableFactory.stub - - stubs/Laminas/ServiceManager/Initializer/InitializerInterface.stub - - stubs/Psr/Container/ContainerInterface.stub - treatPhpDocTypesAsCertain: false \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1d24c33..0e7051d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,15 +1,22 @@ - +> ./test/unit @@ -18,9 +25,13 @@ ./test/integration - + + + + + - ./src + ./src - \ No newline at end of file + diff --git a/test/unit/Pdo/ResultTest.php b/test/unit/Pdo/ResultTest.php new file mode 100644 index 0000000..84ffd89 --- /dev/null +++ b/test/unit/Pdo/ResultTest.php @@ -0,0 +1,453 @@ +buffer(); + + self::assertFalse($result->isBuffered()); + } + + public function testCountCachesResultFromClosure(): void + { + $callCount = 0; + $rowCount = static function () use (&$callCount): int { + $callCount++; + return 7; + }; + + $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); + + $result = new Result(); + $result->initialize($stub, null, $rowCount); + + $result->count(); + $result->count(); + + self::assertSame(1, $callCount); + } + + public function testCountCachesResultFromStatementRowCount(): void + { + $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); + $stub->expects($this->once())->method('rowCount')->willReturn(3); + + $result = new Result(); + $result->initialize($stub, null); + + $result->count(); + $result->count(); + + self::assertSame(3, $result->count()); + } + + public function testCountWithClosureInvokesClosureAndReturnsValue(): void + { + $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); + $stub->expects($this->never())->method('rowCount'); + + $rowCount = static fn(): int => 42; + + $result = new Result(); + $result->initialize($stub, null, $rowCount); + + self::assertSame(42, $result->count()); + } + + public function testCountWithIntReturnsProvidedValue(): void + { + $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); + $stub->expects($this->never())->method('rowCount'); + + $result = new Result(); + $result->initialize($stub, null, 10); + + self::assertSame(10, $result->count()); + } + + public function testCountWithNoRowCountFallsBackToStatementRowCount(): void + { + $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); + $stub->expects($this->once()) + ->method('rowCount') + ->willReturn(5); + + $result = new Result(); + $result->initialize($stub, null); + + self::assertSame(5, $result->count()); + } + + /** + * Tests current method returns same data on consecutive calls. + */ + public function testCurrentReturnsSameDataOnConsecutiveCalls(): void + { + $stub = $this->getMockBuilder('PDOStatement')->getMock(); + $stub->expects($this->any()) + ->method('fetch') + ->willReturnCallback(static fn() => uniqid()); + + $result = new Result(); + $result->initialize($stub, null); + + self::assertEquals($result->current(), $result->current()); + } + + /** + * Tests whether the fetch mode has a broader range + */ + public function testFetchModeAcceptsNamedMode(): void + { + $stub = $this->getMockBuilder('PDOStatement')->getMock(); + $stub->expects($this->any()) + ->method('fetch') + ->willReturnCallback(static fn() => new stdClass()); + $result = new Result(); + $result->initialize($stub, null); + $result->setFetchMode(PDO::FETCH_NAMED); + self::assertEquals(11, $result->getFetchMode()); + self::assertInstanceOf('stdClass', $result->current()); + } + + /** + * Tests whether the fetch mode was set properly and + */ + public function testFetchModeObjReturnsStdClass(): void + { + $stub = $this->getMockBuilder('PDOStatement')->getMock(); + $stub->expects($this->any()) + ->method('fetch') + ->willReturnCallback(static fn() => new stdClass()); + + $result = new Result(); + $result->initialize($stub, null); + $result->setFetchMode(PDO::FETCH_OBJ); + + self::assertEquals(5, $result->getFetchMode()); + self::assertInstanceOf('stdClass', $result->current()); + } + + public function testGetAffectedRowsDelegatesToRowCount(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('rowCount')->willReturn(5); + + $result = new Result(); + $result->initialize($stub, null); + + self::assertSame(5, $result->getAffectedRows()); + } + + public function testGetFetchModeDefaultIsAssoc(): void + { + $result = new Result(); + + self::assertSame(PDO::FETCH_ASSOC, $result->getFetchMode()); + } + + public function testGetFieldCountDelegatesToColumnCount(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('columnCount')->willReturn(3); + + $result = new Result(); + $result->initialize($stub, null); + + self::assertSame(3, $result->getFieldCount()); + } + + public function testGetGeneratedValueReturnsInitializedValue(): void + { + $stub = $this->createMock(PDOStatement::class); + $result = new Result(); + $result->initialize($stub, 42); + + self::assertSame(42, $result->getGeneratedValue()); + } + + public function testGetGeneratedValueReturnsNullByDefault(): void + { + $result = new Result(); + + self::assertNull($result->getGeneratedValue()); + } + + public function testGetQueryResultClonesGivenPrototypeRatherThanMutatingIt(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('columnCount')->willReturn(3); + + $result = new Result(); + $result->initialize($stub, null); + $prototype = new TemporaryResultSet(); + + $returned = $result->getQueryResult($prototype); + + self::assertInstanceOf(TemporaryResultSet::class, $returned); + self::assertNotSame($prototype, $returned); + } + + public function testGetQueryResultInitializesReturnedResultSetWithThisResult(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('columnCount')->willReturn(3); + + $result = new Result(); + $result->initialize($stub, null); + + self::assertSame($result->getFieldCount(), $result->getQueryResult()->getFieldCount()); + } + + public function testGetQueryResultReturnsDefaultResultSetPrototypeWhenNoneGiven(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('columnCount')->willReturn(3); + + $result = new Result(); + $result->initialize($stub, null); + + self::assertInstanceOf(ResultSet::class, $result->getQueryResult()); + } + + public function testGetQueryResultThrowsWhenResultIsNotAQueryResult(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('columnCount')->willReturn(0); + + $result = new Result(); + $result->initialize($stub, null); + + $this->expectException(RuntimeException::class); + $result->getQueryResult(); + } + + public function testGetResourceReturnsPdoStatement(): void + { + $stub = $this->createMock(PDOStatement::class); + $result = new Result(); + $result->initialize($stub, null); + + self::assertSame($stub, $result->getResource()); + } + + public function testInitializeStoresResourceAndValues(): void + { + $stub = $this->createMock(PDOStatement::class); + $result = new Result(); + + $result->initialize($stub, 42, 5); + + self::assertSame(42, $result->getGeneratedValue()); + self::assertSame(5, $result->count()); + } + + public function testIsBufferedReturnsFalse(): void + { + $result = new Result(); + + self::assertFalse($result->isBuffered()); + } + + public function testIsQueryResultReturnsFalseWhenNoColumns(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('columnCount')->willReturn(0); + + $result = new Result(); + $result->initialize($stub, null); + + self::assertFalse($result->isQueryResult()); + } + + public function testIsQueryResultReturnsTrueWhenColumnsExist(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('columnCount')->willReturn(3); + + $result = new Result(); + $result->initialize($stub, null); + + self::assertTrue($result->isQueryResult()); + } + + public function testNextAdvancesPositionAndFetchesData(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('fetch')->willReturn(['name' => 'test']); + + $result = new Result(); + $result->initialize($stub, null); + + $result->rewind(); + self::assertSame(0, $result->key()); + + $result->next(); + self::assertSame(1, $result->key()); + } + + public function testRewindResetsIterationToStart(): void + { + $data = [ + ['test' => 1], + ['test' => 2], + ]; + $position = 0; + + $stub = $this->getMockBuilder('PDOStatement')->getMock(); + assert($stub instanceof PDOStatement); // to suppress IDE type warnings + $stub->expects($this->any()) + ->method('fetch') + ->willReturnCallback(static function () use ($data, &$position) { + return $data[$position++]; + }); + $result = new Result(); + $result->initialize($stub, null); + + $result->rewind(); + $result->rewind(); + + $this->assertEquals(0, $result->key()); + $this->assertEquals(1, $position); + $this->assertEquals($data[0], $result->current()); + + $result->next(); + $this->assertEquals(1, $result->key()); + $this->assertEquals(2, $position); + $this->assertEquals($data[1], $result->current()); + } + + public function testRewindThrowsExceptionOnForwardOnlyAfterAdvancing(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('fetch')->willReturn(['id' => 1]); + + $result = new Result(); + $result->initialize($stub, null); + $result->setStatementMode(Result::STATEMENT_MODE_FORWARD); + + $result->rewind(); + $result->next(); + + $this->expectException(RuntimeException::class); + $result->rewind(); + } + + public function testSetFetchModeStoresValidMode(): void + { + $result = new Result(); + $result->setFetchMode(PDO::FETCH_NUM); + + self::assertSame(PDO::FETCH_NUM, $result->getFetchMode()); + } + + public function testSetFetchModeThrowsOnInvalidFetchMode(): void + { + $result = new Result(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('The fetch mode must be one of the PDO::FETCH_* constants.'); + + $result->setFetchMode(9999); + } + + public function testSetFetchModeThrowsOnInvalidMode(): void + { + $result = new Result(); + + $this->expectException(InvalidArgumentException::class); + $result->setFetchMode(13); + } + + public function testSetStatementModeThrowsOnInvalidMode(): void + { + $result = new Result(); + + $this->expectException(InvalidArgumentException::class); + $result->setStatementMode('invalid'); + } + + public function testSetStatementModeToForward(): void + { + $result = new Result(); + + $result->setStatementMode(Result::STATEMENT_MODE_FORWARD); + + self::assertSame(Result::STATEMENT_MODE_FORWARD, $result->getStatementMode()); + } + + public function testSetStatementModeToScrollable(): void + { + $result = new Result(); + + $result->setStatementMode(Result::STATEMENT_MODE_SCROLLABLE); + + self::assertSame(Result::STATEMENT_MODE_SCROLLABLE, $result->getStatementMode()); + } + + public function testValidReturnsFalseWhenCurrentDataIsFalse(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('fetch')->willReturn(false); + + $result = new Result(); + $result->initialize($stub, null); + $result->rewind(); + + self::assertFalse($result->valid()); + } + + public function testValidReturnsTrueWhenCurrentDataExists(): void + { + $stub = $this->createMock(PDOStatement::class); + $stub->method('fetch')->willReturn(['id' => 1]); + + $result = new Result(); + $result->initialize($stub, null); + $result->rewind(); + + self::assertTrue($result->valid()); + } +} diff --git a/test/unit/Pdo/TestAsset/TemporaryResultSet.php b/test/unit/Pdo/TestAsset/TemporaryResultSet.php new file mode 100644 index 0000000..e25ca57 --- /dev/null +++ b/test/unit/Pdo/TestAsset/TemporaryResultSet.php @@ -0,0 +1,9 @@ + Date: Mon, 24 Aug 2026 16:11:19 +1000 Subject: [PATCH 2/7] Apply mago formatting --- src/AdapterPlatform.php | 50 +-- src/ConfigProvider.php | 16 +- src/Container/MetadataInterfaceFactory.php | 3 +- src/Container/PdoConnectionFactory.php | 4 +- src/Container/PdoDriverInterfaceFactory.php | 6 +- src/Container/PdoStatementFactory.php | 2 +- src/Container/PlatformInterfaceFactory.php | 4 +- src/Metadata/Source.php | 305 +++++++++--------- src/Pdo/Connection.php | 43 +-- src/Pdo/Feature/SqliteRowCounter.php | 28 +- src/Sql/SelectDecorator.php | 16 +- .../PdoDriverInterfaceFactoryTest.php | 2 +- .../Container/TestAsset/SetupTrait.php | 20 +- .../Pdo/ConnectionIntegrationTest.php | 58 ++-- test/integration/Pdo/StatementTest.php | 38 +-- test/unit/AdapterPlatformTest.php | 156 ++++----- test/unit/ConfigProviderTest.php | 59 ++-- .../Container/PdoConnectionFactoryTest.php | 8 +- .../Container/PdoStatementFactoryTest.php | 8 +- test/unit/Pdo/ConnectionTest.php | 56 ++-- test/unit/Pdo/DriverTest.php | 80 ++--- .../unit/Pdo/Feature/SqliteRowCounterTest.php | 8 +- test/unit/Pdo/StatementIntegrationTest.php | 72 +++-- test/unit/Pdo/TestAsset/CtorlessPdo.php | 6 +- test/unit/Sql/PlatformTest.php | 10 +- test/unit/Sql/SelectDecoratorTest.php | 76 ++--- 26 files changed, 579 insertions(+), 555 deletions(-) diff --git a/src/AdapterPlatform.php b/src/AdapterPlatform.php index 220c020..fc64afd 100644 --- a/src/AdapterPlatform.php +++ b/src/AdapterPlatform.php @@ -13,7 +13,8 @@ class AdapterPlatform extends AbstractPlatform { - public final const PLATFORM_NAME = 'SQLite'; + final public const PLATFORM_NAME = 'SQLite'; + /** @var string[] */ protected array $quoteIdentifier = ['"', '"']; @@ -27,27 +28,25 @@ class AdapterPlatform extends AbstractPlatform protected string $quoteIdentifierTo = '\''; public function __construct( - protected readonly PdoDriverInterface|PDO|null $driver = null - ) { - } + protected readonly PdoDriverInterface|PDO|null $driver = null, + ) {} /** * {@inheritDoc} */ #[Override] - public function quoteValue(string $value): string + public function getName(): string { - $resource = $this->resource; - - if ($resource instanceof PdoDriverInterface) { - $resource = $resource->getConnection()->getResource(); - } - - if ($resource instanceof PDO) { - return $resource->quote($value); - } + return self::PLATFORM_NAME; + } - return parent::quoteValue($value); + /** + * {@inheritDoc} + */ + #[Override] + public function getSqlPlatformDecorator(): PlatformDecoratorInterface + { + return new Platform(); } /** @@ -73,17 +72,18 @@ public function quoteTrustedValue(int|float|string|bool $value): ?string * {@inheritDoc} */ #[Override] - public function getName(): string + public function quoteValue(string $value): string { - return self::PLATFORM_NAME; - } + $resource = $this->resource; - /** - * {@inheritDoc} - */ - #[Override] - public function getSqlPlatformDecorator(): PlatformDecoratorInterface - { - return new Platform(); + if ($resource instanceof PdoDriverInterface) { + $resource = $resource->getConnection()->getResource(); + } + + if ($resource instanceof PDO) { + return $resource->quote($value); + } + + return parent::quoteValue($value); } } diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index 2101a4d..b240998 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -15,14 +15,6 @@ final class ConfigProvider { - public function __invoke(): array - { - return [ - 'dependencies' => $this->getDependencies(), - //AdapterInterface::class => $this->getConfig(), - ]; - } - public function getConfig(): array { return [ @@ -61,4 +53,12 @@ public function getDependencies(): array ], ]; } + + public function __invoke(): array + { + return [ + 'dependencies' => $this->getDependencies(), + //AdapterInterface::class => $this->getConfig(), + ]; + } } diff --git a/src/Container/MetadataInterfaceFactory.php b/src/Container/MetadataInterfaceFactory.php index bd4f615..4557a03 100644 --- a/src/Container/MetadataInterfaceFactory.php +++ b/src/Container/MetadataInterfaceFactory.php @@ -12,10 +12,11 @@ final class MetadataInterfaceFactory { public const ADAPTER_SERVICE_NAME = 'adapter_service_name'; + public function __invoke( ContainerInterface $container, string $requestedName, - ?array $options = null + ?array $options = null, ): MetadataInterface&Metadata\Source { $adapterServiceName = $options[self::ADAPTER_SERVICE_NAME] ?? AdapterInterface::class; diff --git a/src/Container/PdoConnectionFactory.php b/src/Container/PdoConnectionFactory.php index 7957e26..6fc6972 100644 --- a/src/Container/PdoConnectionFactory.php +++ b/src/Container/PdoConnectionFactory.php @@ -16,13 +16,13 @@ final class PdoConnectionFactory public function __invoke( ContainerInterface $container, string $requestedName, - ?array $options = null + ?array $options = null, ): PdoConnectionInterface&Connection { $conn = $options['connection'] ?? []; if (! is_array($conn) || $conn === []) { throw new InvalidConnectionParametersException( 'Connection configuration must be an array of parameters passed via $options["connection"]', - $conn + $conn, ); } diff --git a/src/Container/PdoDriverInterfaceFactory.php b/src/Container/PdoDriverInterfaceFactory.php index f32715b..bfd5366 100644 --- a/src/Container/PdoDriverInterfaceFactory.php +++ b/src/Container/PdoDriverInterfaceFactory.php @@ -17,12 +17,12 @@ final class PdoDriverInterfaceFactory public function __invoke( ContainerInterface&ServiceManager $container, string $requestedName, - ?array $options = null + ?array $options = null, ): PdoDriverInterface&Pdo\Driver { /** @var Pdo\Connection $connectionInstance */ $connectionInstance = $container->build( Pdo\Connection::class, - $options + $options, ); /** @var ResultInterface&Result $resultInstance */ @@ -31,7 +31,7 @@ public function __invoke( : new Result(); return new Pdo\Driver( - connection:$connectionInstance, + connection: $connectionInstance, statementPrototype: $container->build(Statement::class, $options['options'] ?? []), resultPrototype: $resultInstance, features: [new Pdo\Feature\SqliteRowCounter()], diff --git a/src/Container/PdoStatementFactory.php b/src/Container/PdoStatementFactory.php index 270fea3..690cd7a 100644 --- a/src/Container/PdoStatementFactory.php +++ b/src/Container/PdoStatementFactory.php @@ -13,7 +13,7 @@ final class PdoStatementFactory public function __invoke( ContainerInterface $container, string $requestedName, - ?array $options = null + ?array $options = null, ): StatementInterface&Statement { return new Statement(options: $options); } diff --git a/src/Container/PlatformInterfaceFactory.php b/src/Container/PlatformInterfaceFactory.php index 9407dc0..593735e 100644 --- a/src/Container/PlatformInterfaceFactory.php +++ b/src/Container/PlatformInterfaceFactory.php @@ -15,14 +15,14 @@ final class PlatformInterfaceFactory public function __invoke( ContainerInterface $container, string $requestedName, - ?array $options = null + ?array $options = null, ): PlatformInterface&AdapterPlatform { $driverInstance = $options['driver'] ?? null; if (! $driverInstance instanceof Driver) { throw ContainerException::forService( AdapterPlatform::class, self::class, - 'Invalid or missing driver provided recieved: ' + 'Invalid or missing driver provided recieved: ', ); } return new AdapterPlatform($driverInstance); diff --git a/src/Metadata/Source.php b/src/Metadata/Source.php index 0f905b2..9f1cbd5 100644 --- a/src/Metadata/Source.php +++ b/src/Metadata/Source.php @@ -19,65 +19,78 @@ final class Source extends AbstractSource { - #[Override] - protected function loadSchemaData(): void + protected function buildRegularExpression(array $re): string { - if (isset($this->data['schemas'])) { - return; - } - $this->prepareDataHierarchy('schemas'); - - $results = $this->fetchPragma('database_list'); - // proposed phpstan fix - $schemas = $results !== [] ? [] : null; - // end proposed fix - foreach ($results as $row) { - $schemas[] = $row['name']; + foreach ($re as &$value) { + if (is_array($value)) { + $value = '(?:' . implode('\\s*+', $value) . '\\s*+)?'; + } else { + $value .= '\\s*+'; + } } - $this->data['schemas'] = $schemas; + unset($value); + $re = '/^' . implode('\\s*+', $re) . '$/'; + return $re; } - #[Override] - protected function loadTableNameData(string $schema): void + protected function fetchPragma(string $name, ?string $value = null, ?string $schema = null): array { - if (isset($this->data['table_names'][$schema])) { - return; - } - $this->prepareDataHierarchy('table_names', $schema); + $p = $this->adapter->getPlatform(); - // FEATURE: Filename? + $sql = 'PRAGMA '; - $p = $this->adapter->getPlatform(); + if (null !== $schema) { + $sql .= $p->quoteIdentifier($schema) . '.'; + } + $sql .= $name; - $sql = 'SELECT "name", "type", "sql" FROM ' . $p->quoteIdentifierChain([$schema, 'sqlite_master']) - . ' WHERE "type" IN (\'table\',\'view\') AND "name" NOT LIKE \'sqlite_%\''; + if (null !== $value) { + $sql .= '(' . $p->quoteTrustedValue($value) . ')'; + } /** @var ResultSet $results */ $results = $this->adapter->query($sql, AdapterInterface::QUERY_MODE_EXECUTE); - $tables = []; - foreach ($results->toArray() as $row) { - if ('table' === $row['type']) { - $table = [ - 'table_type' => 'BASE TABLE', - 'view_definition' => null, // VIEW only - 'check_option' => null, // VIEW only - 'is_updatable' => null, // VIEW only - ]; - } else { - $table = [ - 'table_type' => 'VIEW', - 'view_definition' => null, - 'check_option' => 'NONE', - 'is_updatable' => false, - ]; + if ($results instanceof ResultSetInterface) { + return $results->toArray(); + } + return []; + } - // Parse out extra data - if (null !== ($data = $this->parseView($row['sql']))) { - $table = array_merge($table, $data); - } - } - $tables[$row['name']] = $table; + protected function getIdentifierChainRegularExpression(): string + { + static $re = null; + if (null === $re) { + $identifier = $this->getIdentifierRegularExpression(); + $re = $identifier . '(?:\\s*\\.\\s*' . $identifier . ')*+'; } - $this->data['table_names'][$schema] = $tables; + return $re; + } + + protected function getIdentifierListRegularExpression(): string + { + static $re = null; + if (null === $re) { + $identifier = $this->getIdentifierRegularExpression(); + $re = $identifier . '(?:\\s*,\\s*' . $identifier . ')*+'; + } + return $re; + } + + protected function getIdentifierRegularExpression(): string + { + static $re = null; + if (null === $re) { + $re = + '(?:' + . implode('|', [ + '"(?:[^"\\\\]++|\\\\.)*+"', + '`(?:[^`]++|``)*+`', + '\\[[^\\]]+\\]', + '[^\\s\\.]+', + ]) + . ')'; + } + + return $re; } #[Override] @@ -107,6 +120,7 @@ protected function loadColumnData(string $table, string $schema): void 'numeric_unsigned' => null, 'erratas' => [], ]; + // TODO: populate character_ and numeric_values with correct info } @@ -199,6 +213,69 @@ protected function loadConstraintData(string $table, string $schema): void $this->data['constraints'][$schema][$table] = $constraints; } + #[Override] + protected function loadSchemaData(): void + { + if (isset($this->data['schemas'])) { + return; + } + $this->prepareDataHierarchy('schemas'); + + $results = $this->fetchPragma('database_list'); + // proposed phpstan fix + $schemas = $results !== [] ? [] : null; + // end proposed fix + foreach ($results as $row) { + $schemas[] = $row['name']; + } + $this->data['schemas'] = $schemas; + } + + #[Override] + protected function loadTableNameData(string $schema): void + { + if (isset($this->data['table_names'][$schema])) { + return; + } + $this->prepareDataHierarchy('table_names', $schema); + + // FEATURE: Filename? + + $p = $this->adapter->getPlatform(); + + $sql = + 'SELECT "name", "type", "sql" FROM ' + . $p->quoteIdentifierChain([$schema, 'sqlite_master']) + . ' WHERE "type" IN (\'table\',\'view\') AND "name" NOT LIKE \'sqlite_%\''; + /** @var ResultSet $results */ + $results = $this->adapter->query($sql, AdapterInterface::QUERY_MODE_EXECUTE); + $tables = []; + foreach ($results->toArray() as $row) { + if ('table' === $row['type']) { + $table = [ + 'table_type' => 'BASE TABLE', + 'view_definition' => null, // VIEW only + 'check_option' => null, // VIEW only + 'is_updatable' => null, // VIEW only + ]; + } else { + $table = [ + 'table_type' => 'VIEW', + 'view_definition' => null, + 'check_option' => 'NONE', + 'is_updatable' => false, + ]; + + // Parse out extra data + if (null !== ($data = $this->parseView($row['sql']))) { + $table = array_merge($table, $data); + } + } + $tables[$row['name']] = $table; + } + $this->data['table_names'][$schema] = $tables; + } + #[Override] protected function loadTriggerData(string $schema): void { @@ -210,24 +287,25 @@ protected function loadTriggerData(string $schema): void $p = $this->adapter->getPlatform(); - $sql = 'SELECT "name", "tbl_name", "sql" FROM ' - . $p->quoteIdentifierChain([$schema, 'sqlite_master']) - . ' WHERE "type" = \'trigger\''; + $sql = + 'SELECT "name", "tbl_name", "sql" FROM ' + . $p->quoteIdentifierChain([$schema, 'sqlite_master']) + . ' WHERE "type" = \'trigger\''; /** @var ResultSet $results */ $results = $this->adapter->query($sql, AdapterInterface::QUERY_MODE_EXECUTE); $triggers = []; foreach ($results->toArray() as $row) { $trigger = [ - 'trigger_name' => $row['name'], - 'event_manipulation' => null, // in $row['sql'] - 'event_object_catalog' => null, - 'event_object_schema' => $schema, - 'event_object_table' => $row['tbl_name'], - 'action_order' => 0, - 'action_condition' => null, // in $row['sql'] - 'action_statement' => null, // in $row['sql'] - 'action_orientation' => 'ROW', - 'action_timing' => null, // in $row['sql'] + 'trigger_name' => $row['name'], + 'event_manipulation' => null, // in $row['sql'] + 'event_object_catalog' => null, + 'event_object_schema' => $schema, + 'event_object_table' => $row['tbl_name'], + 'action_order' => 0, + 'action_condition' => null, // in $row['sql'] + 'action_statement' => null, // in $row['sql'] + 'action_orientation' => 'ROW', + 'action_timing' => null, // in $row['sql'] 'action_reference_old_table' => null, 'action_reference_new_table' => null, 'action_reference_old_row' => 'OLD', @@ -245,55 +323,6 @@ protected function loadTriggerData(string $schema): void $this->data['triggers'][$schema] = $triggers; } - protected function fetchPragma(string $name, ?string $value = null, ?string $schema = null): array - { - $p = $this->adapter->getPlatform(); - - $sql = 'PRAGMA '; - - if (null !== $schema) { - $sql .= $p->quoteIdentifier($schema) . '.'; - } - $sql .= $name; - - if (null !== $value) { - $sql .= '(' . $p->quoteTrustedValue($value) . ')'; - } - /** @var ResultSet $results */ - $results = $this->adapter->query($sql, AdapterInterface::QUERY_MODE_EXECUTE); - if ($results instanceof ResultSetInterface) { - return $results->toArray(); - } - return []; - } - - /** @return null|array */ - protected function parseView(string $sql): ?array - { - static $re = null; - if (null === $re) { - $identifierChain = $this->getIdentifierChainRegularExpression(); - $re = $this->buildRegularExpression([ - 'CREATE', - ['TEMP|TEMPORARY'], - 'VIEW', - ['IF', 'NOT', 'EXISTS'], - $identifierChain, - 'AS', - '(?.+)', - [';'], - ]); - } - - if (! preg_match($re, $sql, $matches)) { - return null; - } - - return [ - 'view_definition' => $matches['view_definition'], - ]; - } - /** @return null|array */ protected function parseTrigger(string $sql): ?array { @@ -353,52 +382,30 @@ protected function parseTrigger(string $sql): ?array return $data; } - protected function buildRegularExpression(array $re): string - { - foreach ($re as &$value) { - if (is_array($value)) { - $value = '(?:' . implode('\\s*+', $value) . '\\s*+)?'; - } else { - $value .= '\\s*+'; - } - } - unset($value); - $re = '/^' . implode('\\s*+', $re) . '$/'; - return $re; - } - - protected function getIdentifierRegularExpression(): string + /** @return null|array */ + protected function parseView(string $sql): ?array { static $re = null; if (null === $re) { - $re = '(?:' . implode('|', [ - '"(?:[^"\\\\]++|\\\\.)*+"', - '`(?:[^`]++|``)*+`', - '\\[[^\\]]+\\]', - '[^\\s\\.]+', - ]) . ')'; + $identifierChain = $this->getIdentifierChainRegularExpression(); + $re = $this->buildRegularExpression([ + 'CREATE', + ['TEMP|TEMPORARY'], + 'VIEW', + ['IF', 'NOT', 'EXISTS'], + $identifierChain, + 'AS', + '(?.+)', + [';'], + ]); } - return $re; - } - - protected function getIdentifierChainRegularExpression(): string - { - static $re = null; - if (null === $re) { - $identifier = $this->getIdentifierRegularExpression(); - $re = $identifier . '(?:\\s*\\.\\s*' . $identifier . ')*+'; + if (! preg_match($re, $sql, $matches)) { + return null; } - return $re; - } - protected function getIdentifierListRegularExpression(): string - { - static $re = null; - if (null === $re) { - $identifier = $this->getIdentifierRegularExpression(); - $re = $identifier . '(?:\\s*,\\s*' . $identifier . ')*+'; - } - return $re; + return [ + 'view_definition' => $matches['view_definition'], + ]; } } diff --git a/src/Pdo/Connection.php b/src/Pdo/Connection.php index 1442d47..f63ac1c 100644 --- a/src/Pdo/Connection.php +++ b/src/Pdo/Connection.php @@ -22,10 +22,10 @@ class Connection extends AbstractPdoConnection { - public final const CURRENT_SCHEMA = 'main'; + final public const CURRENT_SCHEMA = 'main'; public function __construct( - PDO|array $connectionParameters + PDO|array $connectionParameters, ) { if (is_array($connectionParameters)) { $this->setConnectionParameters($connectionParameters); @@ -34,19 +34,6 @@ public function __construct( } } - /** - * {@inheritDoc} - */ - #[Override] - public function getCurrentSchema(): string|false - { - if (! $this->isConnected()) { - $this->connect(); - } - - return self::CURRENT_SCHEMA; - } - /** * {@inheritDoc} * @@ -85,22 +72,22 @@ public function connect(): ConnectionInterface if (! is_string($dsn)) { throw new Exception\InvalidConnectionParametersException( 'A dsn was not provided', - $this->connectionParameters + $this->connectionParameters, ); } if (! str_starts_with($dsn, 'sqlite:')) { Assert::fileExists( $dsn, - 'The provided DSN does not point to a valid file.' + 'The provided DSN does not point to a valid file.', ); Assert::readable( $dsn, - 'The provided DSN does not point to a readable file.' + 'The provided DSN does not point to a readable file.', ); Assert::writable( $dsn, - 'The provided DSN does not point to a writable file.' + 'The provided DSN does not point to a writable file.', ); $dsn = 'sqlite:' . $dsn; } @@ -108,7 +95,10 @@ public function connect(): ConnectionInterface $this->dsn = $dsn; try { - $this->resource = new PDO(dsn: $dsn, options: $options); + $this->resource = new PDO( + dsn: $dsn, + options: $options, + ); $this->resource->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $driverName = $this->resource->getAttribute(PDO::ATTR_DRIVER_NAME); assert(is_string($driverName)); @@ -124,6 +114,19 @@ public function connect(): ConnectionInterface return $this; } + /** + * {@inheritDoc} + */ + #[Override] + public function getCurrentSchema(): string|false + { + if (! $this->isConnected()) { + $this->connect(); + } + + return self::CURRENT_SCHEMA; + } + /** * {@inheritDoc} * diff --git a/src/Pdo/Feature/SqliteRowCounter.php b/src/Pdo/Feature/SqliteRowCounter.php index 9b9238f..ce2ee98 100644 --- a/src/Pdo/Feature/SqliteRowCounter.php +++ b/src/Pdo/Feature/SqliteRowCounter.php @@ -17,32 +17,32 @@ */ class SqliteRowCounter extends AbstractFeature { - public function getCountForStatement(Pdo\Statement $statement): int + public function getCountForSql(string $sql): int { - $countStmt = clone $statement; - $sql = $statement->getSql(); if (empty($sql) || ! str_contains(strtolower($sql), 'select')) { return 0; } - $countSql = 'SELECT COUNT(*) as "count" FROM (' . $sql . ')'; - $countStmt->prepare($countSql); - $result = $countStmt->execute(); - $countRow = $result->getResource()->fetch(\PDO::FETCH_ASSOC); - unset($statement, $result); + $countSql = 'SELECT COUNT(*) as count FROM (' . $sql . ')'; + /** @var \PDO $pdo */ + $pdo = $this->driver->getConnection()->getResource(); + $result = $pdo->query($countSql); + $countRow = $result->fetch(\PDO::FETCH_ASSOC); return (int) $countRow['count']; } - public function getCountForSql(string $sql): int + public function getCountForStatement(Pdo\Statement $statement): int { + $countStmt = clone $statement; + $sql = $statement->getSql(); if (empty($sql) || ! str_contains(strtolower($sql), 'select')) { return 0; } - $countSql = 'SELECT COUNT(*) as count FROM (' . $sql . ')'; - /** @var \PDO $pdo */ - $pdo = $this->driver->getConnection()->getResource(); - $result = $pdo->query($countSql); - $countRow = $result->fetch(\PDO::FETCH_ASSOC); + $countSql = 'SELECT COUNT(*) as "count" FROM (' . $sql . ')'; + $countStmt->prepare($countSql); + $result = $countStmt->execute(); + $countRow = $result->getResource()->fetch(\PDO::FETCH_ASSOC); + unset($statement, $result); return (int) $countRow['count']; } diff --git a/src/Sql/SelectDecorator.php b/src/Sql/SelectDecorator.php index 6013cd0..5c9e21d 100644 --- a/src/Sql/SelectDecorator.php +++ b/src/Sql/SelectDecorator.php @@ -37,8 +37,8 @@ protected function localizeVariables(): void /** @return null|string[]|int[] */ protected function processLimit( PlatformInterface $platform, - DriverInterface|null $driver = null, - ParameterContainer|null $parameterContainer = null + ?DriverInterface $driver = null, + ?ParameterContainer $parameterContainer = null, ): ?array { if ($this->limit === null && $this->offset !== null) { return ['']; @@ -49,9 +49,11 @@ protected function processLimit( if ($parameterContainer) { $paramPrefix = (string) $this->processInfo['paramPrefix']; $parameterContainer->offsetSet($paramPrefix . 'limit', $this->limit, ParameterContainer::TYPE_INTEGER); - return $driver !== null - ? [$driver->formatParameterName($paramPrefix . 'limit')] - : null; + return ( + $driver !== null + ? [$driver->formatParameterName($paramPrefix . 'limit')] + : null + ); } return [$this->limit]; @@ -59,8 +61,8 @@ protected function processLimit( protected function processOffset( PlatformInterface $platform, - DriverInterface|null $driver = null, - ParameterContainer|null $parameterContainer = null + ?DriverInterface $driver = null, + ?ParameterContainer $parameterContainer = null, ): ?array { if ($this->offset === null) { return null; diff --git a/test/integration/Container/PdoDriverInterfaceFactoryTest.php b/test/integration/Container/PdoDriverInterfaceFactoryTest.php index bbdea71..cddf092 100644 --- a/test/integration/Container/PdoDriverInterfaceFactoryTest.php +++ b/test/integration/Container/PdoDriverInterfaceFactoryTest.php @@ -27,7 +27,7 @@ public function testInvokeReturnsPdoDriver(): void $instance = $factory( $this->container, Driver::class, - $this->container->get('config')[AdapterInterface::class] + $this->container->get('config')[AdapterInterface::class], ); self::assertInstanceOf(PdoDriverInterface::class, $instance); diff --git a/test/integration/Container/TestAsset/SetupTrait.php b/test/integration/Container/TestAsset/SetupTrait.php index 7c1fe68..ddc9b89 100644 --- a/test/integration/Container/TestAsset/SetupTrait.php +++ b/test/integration/Container/TestAsset/SetupTrait.php @@ -34,13 +34,6 @@ trait SetupTrait protected DriverInterface|string|null $driver; - #[Override] - protected function setUp(): void - { - $this->getAdapter(); - parent::setUp(); - } - protected function getAdapter(array $config = []): AdapterInterface { $connectionConfig = [ @@ -60,12 +53,12 @@ protected function getAdapter(array $config = []): AdapterInterface // merge service config from both PhpDb and PhpDb\Sqlite $serviceManagerConfig = ArrayUtils::merge( (new LaminasDbConfigProvider())()['dependencies'], - (new ConfigProvider())()['dependencies'] + (new ConfigProvider())()['dependencies'], ); $serviceManagerConfig = ArrayUtils::merge( $serviceManagerConfig, - $connectionConfig + $connectionConfig, ); // prefer passed config over environment variables @@ -79,7 +72,7 @@ protected function getAdapter(array $config = []): AdapterInterface 'services' => [ 'config' => $serviceManagerConfig, ], - ] + ], ); $this->config = $serviceManagerConfig; @@ -98,4 +91,11 @@ protected function getHostname(): string { return $this->getConfig()['db']['connection']['hostname']; } + + #[Override] + protected function setUp(): void + { + $this->getAdapter(); + parent::setUp(); + } } diff --git a/test/integration/Pdo/ConnectionIntegrationTest.php b/test/integration/Pdo/ConnectionIntegrationTest.php index 7b08555..5815f15 100644 --- a/test/integration/Pdo/ConnectionIntegrationTest.php +++ b/test/integration/Pdo/ConnectionIntegrationTest.php @@ -30,64 +30,65 @@ final class ConnectionIntegrationTest extends TestCase { use SetupTrait; - public function testGetCurrentSchema(): void + public function testConnect(): void { $connection = $this->getAdapter()->getDriver()->getConnection(); - self::assertIsString($connection->getCurrentSchema()); + self::assertSame($connection, $connection->connect()); + self::assertTrue($connection->isConnected()); + + $connection->disconnect(); } - public function testGetResource(): void + public function testConnectReturnsConnectionWhenResourceSet(): void { + /** @var PDO $resource */ + $resource = $this->getAdapter()->getDriver()->getConnection()->getResource(); + /** @var PdoConnectionInterface&Connection $connection */ $connection = $this->getAdapter()->getDriver()->getConnection(); - $connection->connect(); - - self::assertInstanceOf(PDO::class, $connection->getResource()); + self::assertInstanceOf(PdoConnectionInterface::class, $connection); + $connection->setResource($resource); + self::assertSame($connection, $connection->connect()); $connection->disconnect(); + unset($connection); + unset($resource); } - public function testConnect(): void + public function testDisconnect(): void { $connection = $this->getAdapter()->getDriver()->getConnection(); - self::assertSame($connection, $connection->connect()); + $connection->connect(); self::assertTrue($connection->isConnected()); - $connection->disconnect(); + self::assertFalse($connection->isConnected()); } - public function testIsConnected(): void + public function testGetCurrentSchema(): void { $connection = $this->getAdapter()->getDriver()->getConnection(); - self::assertFalse($connection->isConnected()); - self::assertSame($connection, $connection->connect()); - self::assertTrue($connection->isConnected()); - - $connection->disconnect(); - //unset($connection); + self::assertIsString($connection->getCurrentSchema()); } - public function testDisconnect(): void + public function testGetResource(): void { $connection = $this->getAdapter()->getDriver()->getConnection(); $connection->connect(); - self::assertTrue($connection->isConnected()); + + self::assertInstanceOf(PDO::class, $connection->getResource()); + $connection->disconnect(); - self::assertFalse($connection->isConnected()); } - public function testConnectReturnsConnectionWhenResourceSet(): void + public function testIsConnected(): void { - /** @var PDO $resource */ - $resource = $this->getAdapter()->getDriver()->getConnection()->getResource(); - /** @var PdoConnectionInterface&Connection $connection */ $connection = $this->getAdapter()->getDriver()->getConnection(); - self::assertInstanceOf(PdoConnectionInterface::class, $connection); - $connection->setResource($resource); + self::assertFalse($connection->isConnected()); self::assertSame($connection, $connection->connect()); + self::assertTrue($connection->isConnected()); $connection->disconnect(); - unset($connection); - unset($resource); + + //unset($connection); } // public function testBeginTransaction(): never @@ -97,7 +98,6 @@ public function testConnectReturnsConnectionWhenResourceSet(): void // 'This test has not been implemented yet.' // ); // } - // public function testCommit(): never // { // // Remove the following lines when you implement this test. @@ -105,7 +105,6 @@ public function testConnectReturnsConnectionWhenResourceSet(): void // 'This test has not been implemented yet.' // ); // } - // public function testRollback(): never // { // // Remove the following lines when you implement this test. @@ -113,7 +112,6 @@ public function testConnectReturnsConnectionWhenResourceSet(): void // 'This test has not been implemented yet.' // ); // } - // public function testGetLastGeneratedValue(): never // { // $this->markTestIncomplete('Need to create a temporary sequence.'); diff --git a/test/integration/Pdo/StatementTest.php b/test/integration/Pdo/StatementTest.php index db86498..74bf89a 100644 --- a/test/integration/Pdo/StatementTest.php +++ b/test/integration/Pdo/StatementTest.php @@ -26,6 +26,15 @@ final class StatementTest extends TestCase { use SetupTrait; + public function testExecute(): void + { + /** @var StatementInterface&Statement $statement */ + $statement = $this->getAdapter()->getDriver()->createStatement(); + //$statement->initialize($pdo); + $statement->prepare('SELECT 1'); + self::assertInstanceOf(Result::class, $statement->execute()); + } + public function testGetResource(): void { /** @var PDO $pdo */ @@ -39,19 +48,21 @@ public function testGetResource(): void self::assertSame($stmt, $statement->getResource()); } - public function testSetSql(): void + public function testGetSql(): void { - /** @var StatementInterface&Statement $statement */ $statement = $this->getAdapter()->getDriver()->createStatement(); $statement->setSql('SELECT 1'); self::assertEquals('SELECT 1', $statement->getSql()); } - public function testGetSql(): void + public function testIsPrepared(): void { + /** @var StatementInterface&Statement $statement */ $statement = $this->getAdapter()->getDriver()->createStatement(); - $statement->setSql('SELECT 1'); - self::assertEquals('SELECT 1', $statement->getSql()); + self::assertFalse($statement->isPrepared()); + //$statement->initialize($resource); + $statement->prepare('SELECT 1'); + self::assertTrue($statement->isPrepared()); } /** @@ -64,22 +75,11 @@ public function testPrepare(): void self::assertInstanceOf(StatementInterface::class, $statement->prepare('SELECT 1')); } - public function testIsPrepared(): void - { - /** @var StatementInterface&Statement $statement */ - $statement = $this->getAdapter()->getDriver()->createStatement(); - self::assertFalse($statement->isPrepared()); - //$statement->initialize($resource); - $statement->prepare('SELECT 1'); - self::assertTrue($statement->isPrepared()); - } - - public function testExecute(): void + public function testSetSql(): void { /** @var StatementInterface&Statement $statement */ $statement = $this->getAdapter()->getDriver()->createStatement(); - //$statement->initialize($pdo); - $statement->prepare('SELECT 1'); - self::assertInstanceOf(Result::class, $statement->execute()); + $statement->setSql('SELECT 1'); + self::assertEquals('SELECT 1', $statement->getSql()); } } diff --git a/test/unit/AdapterPlatformTest.php b/test/unit/AdapterPlatformTest.php index 6d0c2d0..d23469d 100644 --- a/test/unit/AdapterPlatformTest.php +++ b/test/unit/AdapterPlatformTest.php @@ -17,39 +17,48 @@ final class AdapterPlatformTest extends TestCase { private AdapterPlatform $platform; - protected function setUp(): void + public function testConstructWithPdo(): void { - $pdoMock = $this->createMock(PDO::class); - $this->platform = new AdapterPlatform($pdoMock); + $pdoMock = $this->createMock(PDO::class); + $platform = new AdapterPlatform($pdoMock); + + self::assertInstanceOf(AdapterPlatform::class, $platform); } - public function testGetNameReturnsSqlite(): void + public function testConstructWithPdoDriver(): void { - $pdoMock = $this->createMock(PDO::class); - $platform = new AdapterPlatform($pdoMock); + $driverMock = $this->createMock(PdoDriverInterface::class); + $platform = new AdapterPlatform($driverMock); - self::assertSame('SQLite', $platform->getName()); + self::assertInstanceOf(AdapterPlatform::class, $platform); } - public function testPlatformNameConstant(): void + public function testGetIdentifierSeparator(): void { - self::assertSame('SQLite', AdapterPlatform::PLATFORM_NAME); + self::assertEquals('.', $this->platform->getIdentifierSeparator()); } - public function testConstructWithPdo(): void + public function testGetName(): void + { + self::assertEquals('SQLite', $this->platform->getName()); + } + + public function testGetNameReturnsSqlite(): void { $pdoMock = $this->createMock(PDO::class); $platform = new AdapterPlatform($pdoMock); - self::assertInstanceOf(AdapterPlatform::class, $platform); + self::assertSame('SQLite', $platform->getName()); } - public function testConstructWithPdoDriver(): void + public function testGetQuoteIdentifierSymbol(): void { - $driverMock = $this->createMock(PdoDriverInterface::class); - $platform = new AdapterPlatform($driverMock); + self::assertEquals('"', $this->platform->getQuoteIdentifierSymbol()); + } - self::assertInstanceOf(AdapterPlatform::class, $platform); + public function testGetQuoteValueSymbol(): void + { + self::assertEquals("'", $this->platform->getQuoteValueSymbol()); } public function testGetSqlPlatformDecorator(): void @@ -62,14 +71,9 @@ public function testGetSqlPlatformDecorator(): void self::assertInstanceOf(SqlPlatformDecorator::class, $decorator); } - public function testGetName(): void - { - self::assertEquals('SQLite', $this->platform->getName()); - } - - public function testGetQuoteIdentifierSymbol(): void + public function testPlatformNameConstant(): void { - self::assertEquals('"', $this->platform->getQuoteIdentifierSymbol()); + self::assertSame('SQLite', AdapterPlatform::PLATFORM_NAME); } public function testQuoteIdentifier(): void @@ -84,39 +88,33 @@ public function testQuoteIdentifierChain(): void self::assertEquals('"schema"."identifier"', $this->platform->quoteIdentifierChain(['schema', 'identifier'])); } - public function testGetQuoteValueSymbol(): void - { - self::assertEquals("'", $this->platform->getQuoteValueSymbol()); - } - - public function testQuoteValueThrowsExeceptionWithoutDriverSupport(): void + public function testQuoteIdentifierInFragment(): void { - $platform = new AdapterPlatform(); - //$this->expectNotToPerformAssertions(); - $this->expectException(VunerablePlatformQuoteException::class); - $platform->quoteValue('value'); - } + self::assertEquals('"foo"."bar"', $this->platform->quoteIdentifierInFragment('foo.bar')); + self::assertEquals('"foo" as "bar"', $this->platform->quoteIdentifierInFragment('foo as bar')); - public function testQuoteValueList(): void - { - $expected = "'Foo O\\'Bar'"; - $platform = new AdapterPlatform(); - $this->expectException(VunerablePlatformQuoteException::class); - $actual = $platform->quoteValueList("Foo O'Bar"); - self::assertEquals($expected, $actual); - } + // single char words + self::assertEquals( + '("foo"."bar" = "boo"."baz")', + $this->platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', ['(', ')', '=']), + ); - public function testQuoteValue(): void - { - self::assertEquals("'value'", @$this->platform->quoteValue('value')); - self::assertEquals("'Foo O\\'Bar'", @$this->platform->quoteValue("Foo O'Bar")); + // case insensitive safe words self::assertEquals( - '\'\\\'; DELETE FROM some_table; -- \'', - @$this->platform->quoteValue('\'; DELETE FROM some_table; -- ') + '("foo"."bar" = "boo"."baz") AND ("foo"."baz" = "boo"."baz")', + $this->platform->quoteIdentifierInFragment( + '(foo.bar = boo.baz) AND (foo.baz = boo.baz)', + ['(', ')', '=', 'and'], + ), ); + + // case insensitive safe words in field self::assertEquals( - "'\\\\\\'; DELETE FROM some_table; -- '", - @$this->platform->quoteValue('\\\'; DELETE FROM some_table; -- ') + '("foo"."bar" = "boo".baz) AND ("foo".baz = "boo".baz)', + $this->platform->quoteIdentifierInFragment( + '(foo.bar = boo.baz) AND (foo.baz = boo.baz)', + ['(', ')', '=', 'and', 'bAz'], + ), ); } @@ -126,48 +124,50 @@ public function testQuoteTrustedValue(): void self::assertEquals("'Foo O\\'Bar'", $this->platform->quoteTrustedValue("Foo O'Bar")); self::assertEquals( '\'\\\'; DELETE FROM some_table; -- \'', - $this->platform->quoteTrustedValue('\'; DELETE FROM some_table; -- ') + $this->platform->quoteTrustedValue('\'; DELETE FROM some_table; -- '), ); // '\\\'; DELETE FROM some_table; -- ' <- actual below self::assertEquals( "'\\\\\\'; DELETE FROM some_table; -- '", - $this->platform->quoteTrustedValue('\\\'; DELETE FROM some_table; -- ') + $this->platform->quoteTrustedValue('\\\'; DELETE FROM some_table; -- '), ); } - public function testGetIdentifierSeparator(): void - { - self::assertEquals('.', $this->platform->getIdentifierSeparator()); - } - - public function testQuoteIdentifierInFragment(): void + public function testQuoteValue(): void { - self::assertEquals('"foo"."bar"', $this->platform->quoteIdentifierInFragment('foo.bar')); - self::assertEquals('"foo" as "bar"', $this->platform->quoteIdentifierInFragment('foo as bar')); - - // single char words + self::assertEquals("'value'", @$this->platform->quoteValue('value')); + self::assertEquals("'Foo O\\'Bar'", @$this->platform->quoteValue("Foo O'Bar")); self::assertEquals( - '("foo"."bar" = "boo"."baz")', - $this->platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', ['(', ')', '=']) + '\'\\\'; DELETE FROM some_table; -- \'', + @$this->platform->quoteValue('\'; DELETE FROM some_table; -- '), ); - - // case insensitive safe words self::assertEquals( - '("foo"."bar" = "boo"."baz") AND ("foo"."baz" = "boo"."baz")', - $this->platform->quoteIdentifierInFragment( - '(foo.bar = boo.baz) AND (foo.baz = boo.baz)', - ['(', ')', '=', 'and'] - ) + "'\\\\\\'; DELETE FROM some_table; -- '", + @$this->platform->quoteValue('\\\'; DELETE FROM some_table; -- '), ); + } - // case insensitive safe words in field - self::assertEquals( - '("foo"."bar" = "boo".baz) AND ("foo".baz = "boo".baz)', - $this->platform->quoteIdentifierInFragment( - '(foo.bar = boo.baz) AND (foo.baz = boo.baz)', - ['(', ')', '=', 'and', 'bAz'] - ) - ); + public function testQuoteValueList(): void + { + $expected = "'Foo O\\'Bar'"; + $platform = new AdapterPlatform(); + $this->expectException(VunerablePlatformQuoteException::class); + $actual = $platform->quoteValueList("Foo O'Bar"); + self::assertEquals($expected, $actual); + } + + public function testQuoteValueThrowsExeceptionWithoutDriverSupport(): void + { + $platform = new AdapterPlatform(); + //$this->expectNotToPerformAssertions(); + $this->expectException(VunerablePlatformQuoteException::class); + $platform->quoteValue('value'); + } + + protected function setUp(): void + { + $pdoMock = $this->createMock(PDO::class); + $this->platform = new AdapterPlatform($pdoMock); } } diff --git a/test/unit/ConfigProviderTest.php b/test/unit/ConfigProviderTest.php index 993ddae..268c969 100644 --- a/test/unit/ConfigProviderTest.php +++ b/test/unit/ConfigProviderTest.php @@ -38,27 +38,35 @@ final class ConfigProviderTest extends TestCase StatementInterface::class => Statement::class, MetadataInterface::class => Metadata\Source::class, ]; + private ConfigProvider $configProvider; - protected function setUp(): void + public function testGetDependenciesContainsExpectedAliases(): void { - $this->configProvider = new ConfigProvider(); + $config = $this->configProvider->getDependencies(); + self::assertEquals(self::EXPECTED_ALIASES, $config['aliases']); } - public function testInvokeReturnsExpectedStructure(): void + public function testGetDependenciesContainsMetadataAlias(): void { - $config = ($this->configProvider)(); + $dependencies = $this->configProvider->getDependencies(); - self::assertNotEmpty($config); - self::assertArrayHasKey('dependencies', $config); + self::assertArrayHasKey(MetadataInterface::class, $dependencies['aliases']); + self::assertSame( + Metadata\Source::class, + $dependencies['aliases'][MetadataInterface::class], + ); } - public function testInvokeReturnsCorrectStructure(): void + public function testGetDependenciesContainsMetadataFactory(): void { - $config = (new ConfigProvider())(); - self::assertArrayHasKey('dependencies', $config); - self::assertArrayHasKey('aliases', $config['dependencies']); - self::assertArrayHasKey('factories', $config['dependencies']); + $dependencies = $this->configProvider->getDependencies(); + + self::assertArrayHasKey(Metadata\Source::class, $dependencies['factories']); + self::assertSame( + Container\MetadataInterfaceFactory::class, + $dependencies['factories'][Metadata\Source::class], + ); } public function testGetDependenciesReturnsCorrectStructure(): void @@ -70,31 +78,24 @@ public function testGetDependenciesReturnsCorrectStructure(): void self::assertArrayHasKey('factories', $dependencies); } - public function testGetDependenciesContainsMetadataAlias(): void + public function testInvokeReturnsCorrectStructure(): void { - $dependencies = $this->configProvider->getDependencies(); - - self::assertArrayHasKey(MetadataInterface::class, $dependencies['aliases']); - self::assertSame( - Metadata\Source::class, - $dependencies['aliases'][MetadataInterface::class] - ); + $config = (new ConfigProvider())(); + self::assertArrayHasKey('dependencies', $config); + self::assertArrayHasKey('aliases', $config['dependencies']); + self::assertArrayHasKey('factories', $config['dependencies']); } - public function testGetDependenciesContainsMetadataFactory(): void + public function testInvokeReturnsExpectedStructure(): void { - $dependencies = $this->configProvider->getDependencies(); + $config = ($this->configProvider)(); - self::assertArrayHasKey(Metadata\Source::class, $dependencies['factories']); - self::assertSame( - Container\MetadataInterfaceFactory::class, - $dependencies['factories'][Metadata\Source::class] - ); + self::assertNotEmpty($config); + self::assertArrayHasKey('dependencies', $config); } - public function testGetDependenciesContainsExpectedAliases(): void + protected function setUp(): void { - $config = $this->configProvider->getDependencies(); - self::assertEquals(self::EXPECTED_ALIASES, $config['aliases']); + $this->configProvider = new ConfigProvider(); } } diff --git a/test/unit/Container/PdoConnectionFactoryTest.php b/test/unit/Container/PdoConnectionFactoryTest.php index 7da08cb..d04f047 100644 --- a/test/unit/Container/PdoConnectionFactoryTest.php +++ b/test/unit/Container/PdoConnectionFactoryTest.php @@ -24,23 +24,23 @@ public function testInvokeReturnsConnection(): void self::assertInstanceOf(Connection::class, $connection); } - public function testInvokeWithoutConnectionConfigThrows(): void + public function testInvokeWithNullOptionsThrows(): void { $containerMock = $this->createMock(ContainerInterface::class); $this->expectException(InvalidConnectionParametersException::class); $factory = new PdoConnectionFactory(); - $factory($containerMock, Connection::class, []); + $factory($containerMock, Connection::class, null); } - public function testInvokeWithNullOptionsThrows(): void + public function testInvokeWithoutConnectionConfigThrows(): void { $containerMock = $this->createMock(ContainerInterface::class); $this->expectException(InvalidConnectionParametersException::class); $factory = new PdoConnectionFactory(); - $factory($containerMock, Connection::class, null); + $factory($containerMock, Connection::class, []); } } diff --git a/test/unit/Container/PdoStatementFactoryTest.php b/test/unit/Container/PdoStatementFactoryTest.php index 4c11e5e..2b148c4 100644 --- a/test/unit/Container/PdoStatementFactoryTest.php +++ b/test/unit/Container/PdoStatementFactoryTest.php @@ -13,22 +13,22 @@ #[CoversClass(PdoStatementFactory::class)] final class PdoStatementFactoryTest extends TestCase { - public function testInvokeReturnsStatementWithOptions(): void + public function testInvokeReturnsStatementWithEmptyOptions(): void { $containerMock = $this->createMock(ContainerInterface::class); $factory = new PdoStatementFactory(); - $statement = $factory($containerMock, Statement::class, ['key' => 'value']); + $statement = $factory($containerMock, Statement::class, []); self::assertInstanceOf(Statement::class, $statement); } - public function testInvokeReturnsStatementWithEmptyOptions(): void + public function testInvokeReturnsStatementWithOptions(): void { $containerMock = $this->createMock(ContainerInterface::class); $factory = new PdoStatementFactory(); - $statement = $factory($containerMock, Statement::class, []); + $statement = $factory($containerMock, Statement::class, ['key' => 'value']); self::assertInstanceOf(Statement::class, $statement); } diff --git a/test/unit/Pdo/ConnectionTest.php b/test/unit/Pdo/ConnectionTest.php index 9ee377c..29f8278 100644 --- a/test/unit/Pdo/ConnectionTest.php +++ b/test/unit/Pdo/ConnectionTest.php @@ -19,25 +19,20 @@ final class ConnectionTest extends TestCase //protected string $dsn = 'sqlite::memory:'; protected string $dsn = 'sqlite::memory:'; - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - #[Override] - protected function setUp(): void + #[Group('2622')] + public function testArrayOfConnectionParametersCreatesCorrectDsn(): void { - $this->connection = new Connection([ - 'dsn' => $this->dsn, + $this->connection->setConnectionParameters([ + 'dsn' => 'sqlite::memory:', ]); - } + try { + $this->connection->connect(); + } catch (Exception) { + } + $responseString = $this->connection->getDsn(); - /** - * Test getResource method tries to connect to the database, it should never return null - */ - public function testResource(): void - { - $this->expectNotToPerformAssertions(); - $this->connection->getResource(); + self::assertStringStartsWith('sqlite:', $responseString); + self::assertStringContainsString('memory', $responseString); } /** @@ -55,19 +50,24 @@ public function testGetDsn(): void self::assertEquals($this->dsn, $responseString); } - #[Group('2622')] - public function testArrayOfConnectionParametersCreatesCorrectDsn(): void + /** + * Test getResource method tries to connect to the database, it should never return null + */ + public function testResource(): void { - $this->connection->setConnectionParameters([ - 'dsn' => 'sqlite::memory:', - ]); - try { - $this->connection->connect(); - } catch (Exception) { - } - $responseString = $this->connection->getDsn(); + $this->expectNotToPerformAssertions(); + $this->connection->getResource(); + } - self::assertStringStartsWith('sqlite:', $responseString); - self::assertStringContainsString('memory', $responseString); + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + #[Override] + protected function setUp(): void + { + $this->connection = new Connection([ + 'dsn' => $this->dsn, + ]); } } diff --git a/test/unit/Pdo/DriverTest.php b/test/unit/Pdo/DriverTest.php index fb0fcc9..4776dc3 100644 --- a/test/unit/Pdo/DriverTest.php +++ b/test/unit/Pdo/DriverTest.php @@ -22,43 +22,32 @@ final class DriverTest extends TestCase { protected Driver $pdo; - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - #[Override] - protected function setUp(): void + /** @psalm-return array */ + public static function getInvalidParamName(): array { - $connection = new Connection(['dsn' => ':memory:']); - - /** @var StatementInterface&PdoDriverAwareInterface&MockObject $statementPrototype */ - $statementPrototype = $this->createMockForIntersectionOfInterfaces([ - StatementInterface::class, - PdoDriverAwareInterface::class, - ]); - - $this->pdo = new Driver( - $connection, - $statementPrototype, - $this->createMock(ResultInterface::class), - ); + return [ + ['foo%'], + ['foo-'], + ['foo$'], + ['foo0!'], + ]; } /** @psalm-return array */ public static function getParamsAndType(): array { return [ - ['foo', null, ':foo'], - ['foo_bar', null, ':foo_bar'], - ['123foo', null, ':123foo'], - [1, null, '?'], - ['1', null, '?'], - ['foo', PdoDriverInterface::PARAMETERIZATION_NAMED, ':foo'], + ['foo', null, ':foo'], + ['foo_bar', null, ':foo_bar'], + ['123foo', null, ':123foo'], + [1, null, '?'], + ['1', null, '?'], + ['foo', PdoDriverInterface::PARAMETERIZATION_NAMED, ':foo'], ['foo_bar', PdoDriverInterface::PARAMETERIZATION_NAMED, ':foo_bar'], - ['123foo', PdoDriverInterface::PARAMETERIZATION_NAMED, ':123foo'], - [1, PdoDriverInterface::PARAMETERIZATION_NAMED, ':1'], - ['1', PdoDriverInterface::PARAMETERIZATION_NAMED, ':1'], - [':foo', null, ':foo'], + ['123foo', PdoDriverInterface::PARAMETERIZATION_NAMED, ':123foo'], + [1, PdoDriverInterface::PARAMETERIZATION_NAMED, ':1'], + ['1', PdoDriverInterface::PARAMETERIZATION_NAMED, ':1'], + [':foo', null, ':foo'], ]; } @@ -69,21 +58,32 @@ public function testFormatParameterName(int|string $name, ?string $type, string $this->assertEquals($expected, $result); } - /** @psalm-return array */ - public static function getInvalidParamName(): array - { - return [ - ['foo%'], - ['foo-'], - ['foo$'], - ['foo0!'], - ]; - } - #[DataProvider('getInvalidParamName')] public function testFormatParameterNameWithInvalidCharacters(string $name): void { $this->expectException(RuntimeException::class); $this->pdo->formatParameterName($name); } + + /** + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. + */ + #[Override] + protected function setUp(): void + { + $connection = new Connection(['dsn' => ':memory:']); + + /** @var StatementInterface&PdoDriverAwareInterface&MockObject $statementPrototype */ + $statementPrototype = $this->createMockForIntersectionOfInterfaces([ + StatementInterface::class, + PdoDriverAwareInterface::class, + ]); + + $this->pdo = new Driver( + $connection, + $statementPrototype, + $this->createMock(ResultInterface::class), + ); + } } diff --git a/test/unit/Pdo/Feature/SqliteRowCounterTest.php b/test/unit/Pdo/Feature/SqliteRowCounterTest.php index 4377b87..ac332d8 100644 --- a/test/unit/Pdo/Feature/SqliteRowCounterTest.php +++ b/test/unit/Pdo/Feature/SqliteRowCounterTest.php @@ -13,13 +13,13 @@ final class SqliteRowCounterTest extends TestCase { private SqliteRowCounter $rowCounter; - protected function setUp(): void + public function testRowCounterExists(): void { - $this->rowCounter = new SqliteRowCounter(); + self::assertInstanceOf(SqliteRowCounter::class, $this->rowCounter); } - public function testRowCounterExists(): void + protected function setUp(): void { - self::assertInstanceOf(SqliteRowCounter::class, $this->rowCounter); + $this->rowCounter = new SqliteRowCounter(); } } diff --git a/test/unit/Pdo/StatementIntegrationTest.php b/test/unit/Pdo/StatementIntegrationTest.php index 5c8fc56..4c56f70 100644 --- a/test/unit/Pdo/StatementIntegrationTest.php +++ b/test/unit/Pdo/StatementIntegrationTest.php @@ -23,44 +23,56 @@ final class StatementIntegrationTest extends TestCase public function testStatementExecuteWillConvertPhpBoolToPdoBoolWhenBinding(): void { - $this->pdoStatementMock->expects($this->any())->method('bindParam')->with( - $this->equalTo(':foo'), - $this->equalTo(false), - $this->equalTo(PDO::PARAM_BOOL) - ); + $this->pdoStatementMock + ->expects($this->any()) + ->method('bindParam') + ->with( + $this->equalTo(':foo'), + $this->equalTo(false), + $this->equalTo(PDO::PARAM_BOOL), + ); $this->statement->execute(['foo' => false]); } + public function testStatementExecuteWillUsePdoIntForIntWhenBinding(): void + { + $this->pdoStatementMock + ->expects($this->any()) + ->method('bindParam') + ->with( + $this->equalTo(':foo'), + $this->equalTo(123), + $this->equalTo(PDO::PARAM_INT), + ); + $this->statement->execute(['foo' => 123]); + } + public function testStatementExecuteWillUsePdoStrByDefaultWhenBinding(): void { - $this->pdoStatementMock->expects($this->any())->method('bindParam')->with( - $this->equalTo(':foo'), - $this->equalTo('bar'), - $this->equalTo(PDO::PARAM_STR) - ); + $this->pdoStatementMock + ->expects($this->any()) + ->method('bindParam') + ->with( + $this->equalTo(':foo'), + $this->equalTo('bar'), + $this->equalTo(PDO::PARAM_STR), + ); $this->statement->execute(['foo' => 'bar']); } public function testStatementExecuteWillUsePdoStrForStringIntegerWhenBinding(): void { - $this->pdoStatementMock->expects($this->any())->method('bindParam')->with( - $this->equalTo(':foo'), - $this->equalTo('123'), - $this->equalTo(PDO::PARAM_STR) - ); + $this->pdoStatementMock + ->expects($this->any()) + ->method('bindParam') + ->with( + $this->equalTo(':foo'), + $this->equalTo('123'), + $this->equalTo(PDO::PARAM_STR), + ); $this->statement->execute(['foo' => '123']); } - public function testStatementExecuteWillUsePdoIntForIntWhenBinding(): void - { - $this->pdoStatementMock->expects($this->any())->method('bindParam')->with( - $this->equalTo(':foo'), - $this->equalTo(123), - $this->equalTo(PDO::PARAM_INT) - ); - $this->statement->execute(['foo' => 123]); - } - /** * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. @@ -69,16 +81,16 @@ public function testStatementExecuteWillUsePdoIntForIntWhenBinding(): void protected function setUp(): void { $driver = $this->getMockBuilder(Driver::class) - ->onlyMethods(['createResult']) - ->disableOriginalConstructor() - ->getMock(); + ->onlyMethods(['createResult']) + ->disableOriginalConstructor() + ->getMock(); $this->statement = new Statement(); $this->statement->setDriver($driver); $this->statement->initialize(new CtorlessPdo( $this->pdoStatementMock = $this->getMockBuilder(PDOStatement::class) - ->onlyMethods(['execute', 'bindParam']) - ->getMock() + ->onlyMethods(['execute', 'bindParam']) + ->getMock(), )); } } diff --git a/test/unit/Pdo/TestAsset/CtorlessPdo.php b/test/unit/Pdo/TestAsset/CtorlessPdo.php index 8c16ad1..b4ce191 100644 --- a/test/unit/Pdo/TestAsset/CtorlessPdo.php +++ b/test/unit/Pdo/TestAsset/CtorlessPdo.php @@ -11,9 +11,9 @@ final class CtorlessPdo extends PDO { - public function __construct(protected PDOStatement&MockObject $mockStatement) - { - } + public function __construct( + protected PDOStatement&MockObject $mockStatement, + ) {} /** * @param array $options diff --git a/test/unit/Sql/PlatformTest.php b/test/unit/Sql/PlatformTest.php index 2e1a2f0..b53f00d 100644 --- a/test/unit/Sql/PlatformTest.php +++ b/test/unit/Sql/PlatformTest.php @@ -16,11 +16,6 @@ final class PlatformTest extends TestCase { private Platform $platform; - protected function setUp(): void - { - $this->platform = new Platform(); - } - public function testConstructorSetsTypeDecorators(): void { self::assertInstanceOf(Platform::class, $this->platform); @@ -35,4 +30,9 @@ public function testSelectDecoratorIsRegistered(): void self::assertArrayHasKey(Select::class, $decorators); self::assertInstanceOf(SelectDecorator::class, $decorators[Select::class]); } + + protected function setUp(): void + { + $this->platform = new Platform(); + } } diff --git a/test/unit/Sql/SelectDecoratorTest.php b/test/unit/Sql/SelectDecoratorTest.php index 118eeef..950fbc8 100644 --- a/test/unit/Sql/SelectDecoratorTest.php +++ b/test/unit/Sql/SelectDecoratorTest.php @@ -18,37 +18,6 @@ final class SelectDecoratorTest extends TestCase { private SelectDecorator $decorator; - protected function setUp(): void - { - $this->decorator = new SelectDecorator(); - } - - public function testSetSubject(): void - { - $select = new Select(); - $result = $this->decorator->setSubject($select); - - self::assertSame($this->decorator, $result); - - $reflection = new ReflectionClass($this->decorator); - $subjectProperty = $reflection->getProperty('subject'); - $subject = $subjectProperty->getValue($this->decorator); - - self::assertSame($select, $subject); - } - - public function testProcessLimitWithoutLimitAndWithoutOffset(): void - { - $platformMock = $this->createMock(PlatformInterface::class); - - $reflection = new ReflectionClass($this->decorator); - $method = $reflection->getMethod('processLimit'); - - $result = $method->invoke($this->decorator, $platformMock); - - self::assertNull($result); - } - public function testProcessLimitWithLimit(): void { $this->decorator->limit(10); @@ -88,10 +57,8 @@ public function testProcessLimitWithLimitAndParameterContainer(): void self::assertSame(15, $parameterContainer->offsetGet('limit')); } - public function testProcessLimitWithoutLimitButWithOffset(): void + public function testProcessLimitWithoutLimitAndWithoutOffset(): void { - $this->decorator->offset(5); - $platformMock = $this->createMock(PlatformInterface::class); $reflection = new ReflectionClass($this->decorator); @@ -99,19 +66,21 @@ public function testProcessLimitWithoutLimitButWithOffset(): void $result = $method->invoke($this->decorator, $platformMock); - self::assertSame([''], $result); + self::assertNull($result); } - public function testProcessOffsetWithoutOffset(): void + public function testProcessLimitWithoutLimitButWithOffset(): void { + $this->decorator->offset(5); + $platformMock = $this->createMock(PlatformInterface::class); $reflection = new ReflectionClass($this->decorator); - $method = $reflection->getMethod('processOffset'); + $method = $reflection->getMethod('processLimit'); $result = $method->invoke($this->decorator, $platformMock); - self::assertNull($result); + self::assertSame([''], $result); } public function testProcessOffsetWithOffset(): void @@ -152,4 +121,35 @@ public function testProcessOffsetWithOffsetAndParameterContainer(): void self::assertTrue($parameterContainer->offsetExists('offset')); self::assertSame(25, $parameterContainer->offsetGet('offset')); } + + public function testProcessOffsetWithoutOffset(): void + { + $platformMock = $this->createMock(PlatformInterface::class); + + $reflection = new ReflectionClass($this->decorator); + $method = $reflection->getMethod('processOffset'); + + $result = $method->invoke($this->decorator, $platformMock); + + self::assertNull($result); + } + + public function testSetSubject(): void + { + $select = new Select(); + $result = $this->decorator->setSubject($select); + + self::assertSame($this->decorator, $result); + + $reflection = new ReflectionClass($this->decorator); + $subjectProperty = $reflection->getProperty('subject'); + $subject = $subjectProperty->getValue($this->decorator); + + self::assertSame($select, $subject); + } + + protected function setUp(): void + { + $this->decorator = new SelectDecorator(); + } } From af8d723c69587d4378d14ab7e00354b318d43510 Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Mon, 24 Aug 2026 16:11:28 +1000 Subject: [PATCH 3/7] Ignore mago reformat in git blame --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..2c34e73 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1 @@ +c20d173529037a293036b1c8dd51fd0b757ccb62 From bcc6602d9040b6550c33d43261dd2af21a1e3f0a Mon Sep 17 00:00:00 2001 From: Simon Mundy <46739456+simon-mundy@users.noreply.github.com> Date: Wed, 9 Sep 2026 13:34:40 +1000 Subject: [PATCH 4/7] Update AdapterPlatform.php Signed-off-by: Simon Mundy <46739456+simon-mundy@users.noreply.github.com> --- src/AdapterPlatform.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AdapterPlatform.php b/src/AdapterPlatform.php index fc64afd..d813042 100644 --- a/src/AdapterPlatform.php +++ b/src/AdapterPlatform.php @@ -19,7 +19,7 @@ class AdapterPlatform extends AbstractPlatform protected array $quoteIdentifier = ['"', '"']; - /** @var PDO */ + /** @var PDO $resource */ protected $resource; /** From 7c3859e53df8e891842a73491539996d4b7ca438 Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Wed, 9 Sep 2026 13:49:47 +1000 Subject: [PATCH 5/7] Fix mago 1.47.6 analyzer errors - Use setSpecification() in SelectDecorator instead of direct array write - Ensure Source::loadSchemaData always assigns list to schemas - Add native type to AdapterPlatform::$resource --- src/AdapterPlatform.php | 3 +-- src/Metadata/Source.php | 9 +++------ src/Sql/SelectDecorator.php | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/AdapterPlatform.php b/src/AdapterPlatform.php index d813042..10eaf9d 100644 --- a/src/AdapterPlatform.php +++ b/src/AdapterPlatform.php @@ -19,8 +19,7 @@ class AdapterPlatform extends AbstractPlatform protected array $quoteIdentifier = ['"', '"']; - /** @var PDO $resource */ - protected $resource; + protected PdoDriverInterface|PDO|null $resource = null; /** * {@inheritDoc} diff --git a/src/Metadata/Source.php b/src/Metadata/Source.php index 9f1cbd5..2f16c1a 100644 --- a/src/Metadata/Source.php +++ b/src/Metadata/Source.php @@ -221,12 +221,9 @@ protected function loadSchemaData(): void } $this->prepareDataHierarchy('schemas'); - $results = $this->fetchPragma('database_list'); - // proposed phpstan fix - $schemas = $results !== [] ? [] : null; - // end proposed fix - foreach ($results as $row) { - $schemas[] = $row['name']; + $schemas = []; + foreach ($this->fetchPragma('database_list') as $row) { + $schemas[] = (string) $row['name']; } $this->data['schemas'] = $schemas; } diff --git a/src/Sql/SelectDecorator.php b/src/Sql/SelectDecorator.php index 5c9e21d..ae8fa39 100644 --- a/src/Sql/SelectDecorator.php +++ b/src/Sql/SelectDecorator.php @@ -30,7 +30,7 @@ protected function localizeVariables(): void { parent::localizeVariables(); if ($this->limit === null && $this->offset !== null) { - $this->specifications[self::LIMIT] = 'LIMIT 18446744073709551615'; + $this->setSpecification(self::LIMIT, 'LIMIT 18446744073709551615'); } } From 5c82e81b4867c6234b948f299087bb54ae74c052 Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Wed, 9 Sep 2026 13:55:43 +1000 Subject: [PATCH 6/7] Add Infection mutation testing - Require infection/infection ^0.34.1 and allow its composer plugin - Add infection.json5.dist mirroring php-db/phpdb, using mago as static analysis tool - Add mutation-test composer script and enable the CI mutation job at 80% MSI - Fix invalid CoversMethod target in DriverTest that failed the coverage run - Assert the full factories map in ConfigProviderTest to kill an escaped mutant --- .github/workflows/continuous-integration.yml | 5 +- .gitignore | 3 + composer.json | 5 +- composer.lock | 3894 ++++++++++++++---- infection.json5.dist | 22 + test/unit/ConfigProviderTest.php | 15 + test/unit/Pdo/DriverTest.php | 4 +- 7 files changed, 3176 insertions(+), 772 deletions(-) create mode 100644 infection.json5.dist diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 9c67ec6..21c3009 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -11,5 +11,8 @@ jobs: with: php-versions: '["8.3", "8.4", "8.5"]' run-integration: true + coverage-php-version: "8.4" enable-codecov: false - enable-infection: false + enable-infection: true + min-msi: "80" + min-covered-msi: "80" diff --git a/.gitignore b/.gitignore index e07730c..42d06d6 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ /xdebug_filter.php /clover.xml /test/coverage/ +/infection.json5 +/infection.log +/summary.log diff --git a/composer.json b/composer.json index d1bc897..9dcdfe9 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,8 @@ "php": "8.3.99" }, "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true + "dealerdirect/phpcodesniffer-composer-installer": true, + "infection/extension-installer": true } }, "extra": { @@ -37,6 +38,7 @@ "require-dev": { "ext-pdo": "*", "ext-pdo_sqlite": "*", + "infection/infection": "^0.34.1", "php-db/phpdb-qa-tools": "0.1.x-dev", "phpunit/phpunit": "^11.5.42" }, @@ -70,6 +72,7 @@ "mago lint --fix" ], "static-analysis": "mago analyze", + "mutation-test": "infection", "test": "phpunit --colors=always --testsuite \"unit test\"", "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", "test-integration": "phpunit --colors=always --testsuite \"integration test\"", diff --git a/composer.lock b/composer.lock index 1a22b7b..3adea5c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "eac5fb5580421cacc7e6da527a62a4cc", + "content-hash": "e514e909e3d57be2e3f0accaa5a7721e", "packages": [ { "name": "brick/varexporter", @@ -442,267 +442,2423 @@ ], "packages-dev": [ { - "name": "myclabs/deep-copy", - "version": "1.13.4", + "name": "colinodell/json5", + "version": "v3.0.0", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + "url": "https://github.com/colinodell/json5.git", + "reference": "5724d21bc5c910c2560af1b8915f0cc0163579c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", - "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "url": "https://api.github.com/repos/colinodell/json5/zipball/5724d21bc5c910c2560af1b8915f0cc0163579c8", + "reference": "5724d21bc5c910c2560af1b8915f0cc0163579c8", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.0" }, "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" + "mikehaertl/php-shellcommand": "^1.7.0", + "phpstan/phpstan": "^1.10.57", + "scrutinizer/ocular": "^1.9", + "squizlabs/php_codesniffer": "^3.8.1", + "symfony/finder": "^6.0|^7.0", + "symfony/phpunit-bridge": "^7.0.3" }, + "bin": [ + "bin/json5" + ], "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, "autoload": { "files": [ - "src/DeepCopy/deep_copy.php" + "src/global.php" ], "psr-4": { - "DeepCopy\\": "src/DeepCopy/" + "ColinODell\\Json5\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Create deep copies (clones) of your objects", + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Developer" + } + ], + "description": "UTF-8 compatible JSON5 parser for PHP", + "homepage": "https://github.com/colinodell/json5", "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" + "JSON5", + "json", + "json5_decode", + "json_decode" ], "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + "issues": "https://github.com/colinodell/json5/issues", + "source": "https://github.com/colinodell/json5/tree/v3.0.0" }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://www.patreon.com/colinodell", + "type": "patreon" } ], - "time": "2025-08-01T08:46:24+00:00" + "time": "2024-02-09T13:06:12+00:00" }, { - "name": "phar-io/manifest", - "version": "2.0.4", + "name": "composer/pcre", + "version": "3.4.0", "source": { "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" + "url": "https://github.com/composer/pcre.git", + "reference": "d5a341b3fb61f3001970940afb1d332968a183ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", + "url": "https://api.github.com/repos/composer/pcre/zipball/d5a341b3fb61f3001970940afb1d332968a183ed", + "reference": "d5a341b3fb61f3001970940afb1d332968a183ed", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<2.2.2" + }, + "require-dev": { + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^9" }, "type": "library", "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Composer\\Pcre\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.4.0" + }, + "funding": [ { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" + "url": "https://packagist.com", + "type": "custom" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "url": "https://github.com/composer", + "type": "github" } ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2026-06-07T11:47:49+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" }, "funding": [ { - "url": "https://github.com/theseer", + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" } ], - "time": "2024-03-03T12:33:53+00:00" + "time": "2024-05-06T16:37:16+00:00" }, { - "name": "phar-io/version", - "version": "3.2.1", + "name": "fidry/cpu-core-counter", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + }, + "funding": [ { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2025-08-14T07:29:31+00:00" + }, + { + "name": "infection/abstract-testframework-adapter", + "version": "0.5.1", + "source": { + "type": "git", + "url": "https://github.com/infection/abstract-testframework-adapter.git", + "reference": "b24bf3e850f70cd20a10621f08c3cef66f147ac8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/infection/abstract-testframework-adapter/zipball/b24bf3e850f70cd20a10621f08c3cef66f147ac8", + "reference": "b24bf3e850f70cd20a10621f08c3cef66f147ac8", + "shasum": "" + }, + "require": { + "php": "^8.3" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.18", + "fidry/makefile": "^1.0", + "friendsofphp/php-cs-fixer": "^3.95.2", + "phpunit/phpunit": "^12.0 || ^13.0", + "rector/rector": "^2.4.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Infection\\AbstractTestFramework\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "name": "Maks Rafalko", + "email": "maks.rafalko@gmail.com" } ], - "description": "Library for handling version information and constraints", + "description": "Abstract Test Framework Adapter for Infection", "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" + "issues": "https://github.com/infection/abstract-testframework-adapter/issues", + "source": "https://github.com/infection/abstract-testframework-adapter/tree/0.5.1" }, - "time": "2022-02-21T01:04:05+00:00" + "funding": [ + { + "url": "https://github.com/infection", + "type": "github" + }, + { + "url": "https://opencollective.com/infection", + "type": "open_collective" + } + ], + "time": "2026-05-28T19:10:29+00:00" }, { - "name": "php-db/phpdb-qa-tools", - "version": "0.1.x-dev", + "name": "infection/extension-installer", + "version": "0.1.2", "source": { "type": "git", - "url": "https://github.com/php-db/phpdb-qa-tools.git", - "reference": "f2323423deac77dd719f3f2ca7a9b2a7e21c93f6" + "url": "https://github.com/infection/extension-installer.git", + "reference": "9b351d2910b9a23ab4815542e93d541e0ca0cdcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-db/phpdb-qa-tools/zipball/f2323423deac77dd719f3f2ca7a9b2a7e21c93f6", - "reference": "f2323423deac77dd719f3f2ca7a9b2a7e21c93f6", + "url": "https://api.github.com/repos/infection/extension-installer/zipball/9b351d2910b9a23ab4815542e93d541e0ca0cdcf", + "reference": "9b351d2910b9a23ab4815542e93d541e0ca0cdcf", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "composer-plugin-api": "^1.1 || ^2.0" }, - "suggest": { - "phpunit/phpunit": "To run the shared test configuration (^11.5 || ^12.0)" + "require-dev": { + "composer/composer": "^1.9 || ^2.0", + "friendsofphp/php-cs-fixer": "^2.18, <2.19", + "infection/infection": "^0.15.2", + "php-coveralls/php-coveralls": "^2.4", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.10", + "phpstan/phpstan-phpunit": "^0.12.6", + "phpstan/phpstan-strict-rules": "^0.12.2", + "phpstan/phpstan-webmozart-assert": "^0.12.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.8" + }, + "type": "composer-plugin", + "extra": { + "class": "Infection\\ExtensionInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "Infection\\ExtensionInstaller\\": "src/" + } }, - "default-branch": true, - "type": "library", "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "description": "Shared QA toolchain for php-db components: Mago formatting, linting and static analysis, plus the PHPUnit baseline and CI workflow.", - "homepage": "https://github.com/php-db/phpdb-qa-tools", - "keywords": [ - "coding-standards", - "formatter", - "linter", - "mago", - "phpdb", - "qa", - "static-analysis" + "authors": [ + { + "name": "Maks Rafalko", + "email": "maks.rafalko@gmail.com" + } ], + "description": "Infection Extension Installer", "support": { - "forum": "https://github.com/php-db/phpdb-qa-tools/discussions", - "issues": "https://github.com/php-db/phpdb-qa-tools/issues", - "source": "https://github.com/php-db/phpdb-qa-tools" + "issues": "https://github.com/infection/extension-installer/issues", + "source": "https://github.com/infection/extension-installer/tree/0.1.2" }, - "time": "2026-08-10T01:10:13+00:00" + "funding": [ + { + "url": "https://github.com/infection", + "type": "github" + }, + { + "url": "https://opencollective.com/infection", + "type": "open_collective" + } + ], + "time": "2021-10-20T22:08:34+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "11.0.12", + "name": "infection/include-interceptor", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56" + "url": "https://github.com/infection/include-interceptor.git", + "reference": "c083331bc0cd1cd319ac1b7a08e3ad4a34aa7992" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56", - "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56", + "url": "https://api.github.com/repos/infection/include-interceptor/zipball/c083331bc0cd1cd319ac1b7a08e3ad4a34aa7992", + "reference": "c083331bc0cd1cd319ac1b7a08e3ad4a34aa7992", + "shasum": "" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.16", + "infection/infection": "^0.19.0", + "phan/phan": "^2.4 || ^3", + "php-coveralls/php-coveralls": "^2.2", + "phpstan/phpstan": "^0.12.8", + "phpunit/phpunit": "^8.5", + "vimeo/psalm": "^3.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Infection\\StreamWrapper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Maks Rafalko", + "email": "maks.rafalko@gmail.com" + } + ], + "description": "Stream Wrapper: Include Interceptor. Allows to replace included (autoloaded) file with another one.", + "support": { + "issues": "https://github.com/infection/include-interceptor/issues", + "source": "https://github.com/infection/include-interceptor/tree/1.0.0" + }, + "funding": [ + { + "url": "https://github.com/infection", + "type": "github" + }, + { + "url": "https://opencollective.com/infection", + "type": "open_collective" + } + ], + "time": "2024-05-03T21:48:06+00:00" + }, + { + "name": "infection/infection", + "version": "0.34.2", + "source": { + "type": "git", + "url": "https://github.com/infection/infection.git", + "reference": "18d9bef39fae250f202920d1453ab96e793e6637" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/infection/infection/zipball/18d9bef39fae250f202920d1453ab96e793e6637", + "reference": "18d9bef39fae250f202920d1453ab96e793e6637", + "shasum": "" + }, + "require": { + "colinodell/json5": "^3.0", + "composer-runtime-api": "^2.0", + "composer/xdebug-handler": "^3.0", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "fidry/cpu-core-counter": "^1.0", + "infection/abstract-testframework-adapter": "^0.5.0", + "infection/extension-installer": "^0.1.0", + "infection/include-interceptor": "^0.2.5 || ^1.0.0", + "infection/mutator": "^0.4", + "justinrainbow/json-schema": "^6.0", + "nikic/php-parser": "^5.6.2", + "ondram/ci-detector": "^4.1.0", + "php": "^8.3", + "psr/log": "^2.0 || ^3.0", + "sanmai/di-container": "^0.1.16", + "sanmai/duoclock": "^0.1.0", + "sanmai/later": "^0.1.7", + "sanmai/pipeline": "^7.2", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0", + "symfony/console": "^6.4 || ^7.4 || ^8.0", + "symfony/filesystem": "^6.4 || ^7.4 || ^8.0", + "symfony/finder": "^6.4 || ^7.4 || ^8.0", + "symfony/polyfill-php85": "^1.33", + "symfony/process": "^6.4 || ^7.4 || ^8.0", + "thecodingmachine/safe": "^v3.0", + "webmozart/assert": "^1.11 || ^2.0" + }, + "conflict": { + "antecedent/patchwork": "<2.1.25", + "dg/bypass-finals": "<1.4.1" + }, + "require-dev": { + "carthage-software/mago": "^1.20", + "ext-simplexml": "*", + "fidry/makefile": "^1.0", + "fig/log-test": "^1.2", + "phpat/phpat": "^0.12.4", + "phpbench/phpbench": "^1.4", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpstan/phpstan-webmozart-assert": "^2.0", + "phpunit/phpunit": "^12.5.29", + "rector/rector": "^2.2.4", + "shipmonk/dead-code-detector": "^1.3", + "shipmonk/name-collision-detector": "^2.1", + "sidz/phpstan-rules": "^0.5.1", + "symfony/yaml": "^6.4 || ^7.4 || ^8.0", + "thecodingmachine/phpstan-safe-rule": "^1.4", + "webmozarts/strict-phpunit": "^7.15" + }, + "bin": [ + "bin/infection" + ], + "type": "library", + "autoload": { + "psr-4": { + "Infection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Maks Rafalko", + "email": "maks.rafalko@gmail.com", + "homepage": "https://twitter.com/maks_rafalko" + }, + { + "name": "Oleg Zhulnev", + "homepage": "https://github.com/sidz" + }, + { + "name": "Gert de Pagter", + "homepage": "https://github.com/BackEndTea" + }, + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com", + "homepage": "https://twitter.com/tfidry" + }, + { + "name": "Alexey Kopytko", + "email": "alexey@kopytko.com", + "homepage": "https://www.alexeykopytko.com" + }, + { + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" + } + ], + "description": "Infection is a Mutation Testing framework for PHP. The mutation adequacy score can be used to measure the effectiveness of a test set in terms of its ability to detect faults.", + "keywords": [ + "coverage", + "mutant", + "mutation framework", + "mutation testing", + "testing", + "unit testing" + ], + "support": { + "issues": "https://github.com/infection/infection/issues", + "source": "https://github.com/infection/infection/tree/0.34.2" + }, + "funding": [ + { + "url": "https://github.com/infection", + "type": "github" + }, + { + "url": "https://opencollective.com/infection", + "type": "open_collective" + } + ], + "time": "2026-08-07T12:59:47+00:00" + }, + { + "name": "infection/mutator", + "version": "0.4.1", + "source": { + "type": "git", + "url": "https://github.com/infection/mutator.git", + "reference": "3c976d721b02b32f851ee4e15d553ef1e9186d1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/infection/mutator/zipball/3c976d721b02b32f851ee4e15d553ef1e9186d1d", + "reference": "3c976d721b02b32f851ee4e15d553ef1e9186d1d", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^10" + }, + "type": "library", + "autoload": { + "psr-4": { + "Infection\\Mutator\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Maks Rafalko", + "email": "maks.rafalko@gmail.com" + } + ], + "description": "Mutator interface to implement custom mutators (mutation operators) for Infection", + "support": { + "issues": "https://github.com/infection/mutator/issues", + "source": "https://github.com/infection/mutator/tree/0.4.1" + }, + "funding": [ + { + "url": "https://github.com/infection", + "type": "github" + }, + { + "url": "https://opencollective.com/infection", + "type": "open_collective" + } + ], + "time": "2025-04-29T08:19:52+00:00" + }, + { + "name": "justinrainbow/json-schema", + "version": "6.12.0", + "source": { + "type": "git", + "url": "https://github.com/jsonrainbow/json-schema.git", + "reference": "8ef236a1a37df364b518b7411a4b5bb95b040d79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/8ef236a1a37df364b518b7411a4b5bb95b040d79", + "reference": "8ef236a1a37df364b518b7411a4b5bb95b040d79", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "ext-json": "*", + "marc-mabe/php-enum": "^4.4", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "3.3.0", + "json-schema/json-schema-test-suite": "dev-main", + "marc-mabe/php-enum-phpstan": "^2.0", + "phpspec/prophecy": "^1.19", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^8.5" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.x-dev" + } + }, + "autoload": { + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Danny van der Sluijs", + "email": "danny.vandersluijs@icloud.com", + "role": "Maintainer" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/jsonrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "support": { + "issues": "https://github.com/jsonrainbow/json-schema/issues", + "source": "https://github.com/jsonrainbow/json-schema/tree/6.12.0" + }, + "time": "2026-09-04T12:54:20+00:00" + }, + { + "name": "marc-mabe/php-enum", + "version": "v4.7.2", + "source": { + "type": "git", + "url": "https://github.com/marc-mabe/php-enum.git", + "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/bb426fcdd65c60fb3638ef741e8782508fda7eef", + "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef", + "shasum": "" + }, + "require": { + "ext-reflection": "*", + "php": "^7.1 | ^8.0" + }, + "require-dev": { + "phpbench/phpbench": "^0.16.10 || ^1.0.4", + "phpstan/phpstan": "^1.3.1", + "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11", + "vimeo/psalm": "^4.17.0 | ^5.26.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.2-dev", + "dev-master": "4.7-dev" + } + }, + "autoload": { + "psr-4": { + "MabeEnum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Marc Bennewitz", + "email": "dev@mabe.berlin", + "homepage": "https://mabe.berlin/", + "role": "Lead" + } + ], + "description": "Simple and fast implementation of enumerations with native PHP", + "homepage": "https://github.com/marc-mabe/php-enum", + "keywords": [ + "enum", + "enum-map", + "enum-set", + "enumeration", + "enumerator", + "enummap", + "enumset", + "map", + "set", + "type", + "type-hint", + "typehint" + ], + "support": { + "issues": "https://github.com/marc-mabe/php-enum/issues", + "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.2" + }, + "time": "2025-09-14T11:18:39+00:00" + }, + { + "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": "ondram/ci-detector", + "version": "4.2.0", + "source": { + "type": "git", + "url": "https://github.com/OndraM/ci-detector.git", + "reference": "8b0223b5ed235fd377c75fdd1bfcad05c0f168b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/OndraM/ci-detector/zipball/8b0223b5ed235fd377c75fdd1bfcad05c0f168b8", + "reference": "8b0223b5ed235fd377c75fdd1bfcad05c0f168b8", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.13.2", + "lmc/coding-standard": "^3.0.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.1.0", + "phpstan/phpstan": "^1.2.0", + "phpstan/phpstan-phpunit": "^1.0.0", + "phpunit/phpunit": "^9.6.13" + }, + "type": "library", + "autoload": { + "psr-4": { + "OndraM\\CiDetector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ondřej Machulda", + "email": "ondrej.machulda@gmail.com" + } + ], + "description": "Detect continuous integration environment and provide unified access to properties of current build", + "keywords": [ + "CircleCI", + "Codeship", + "Wercker", + "adapter", + "appveyor", + "aws", + "aws codebuild", + "azure", + "azure devops", + "azure pipelines", + "bamboo", + "bitbucket", + "buddy", + "ci-info", + "codebuild", + "continuous integration", + "continuousphp", + "devops", + "drone", + "github", + "gitlab", + "interface", + "jenkins", + "pipelines", + "sourcehut", + "teamcity", + "travis" + ], + "support": { + "issues": "https://github.com/OndraM/ci-detector/issues", + "source": "https://github.com/OndraM/ci-detector/tree/4.2.0" + }, + "time": "2024-03-12T13:22:30+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": "php-db/phpdb-qa-tools", + "version": "0.1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/php-db/phpdb-qa-tools.git", + "reference": "f2323423deac77dd719f3f2ca7a9b2a7e21c93f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-db/phpdb-qa-tools/zipball/f2323423deac77dd719f3f2ca7a9b2a7e21c93f6", + "reference": "f2323423deac77dd719f3f2ca7a9b2a7e21c93f6", + "shasum": "" + }, + "require": { + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + }, + "suggest": { + "phpunit/phpunit": "To run the shared test configuration (^11.5 || ^12.0)" + }, + "default-branch": true, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Shared QA toolchain for php-db components: Mago formatting, linting and static analysis, plus the PHPUnit baseline and CI workflow.", + "homepage": "https://github.com/php-db/phpdb-qa-tools", + "keywords": [ + "coding-standards", + "formatter", + "linter", + "mago", + "phpdb", + "qa", + "static-analysis" + ], + "support": { + "forum": "https://github.com/php-db/phpdb-qa-tools/discussions", + "issues": "https://github.com/php-db/phpdb-qa-tools/issues", + "source": "https://github.com/php-db/phpdb-qa-tools" + }, + "time": "2026-08-10T01:10:13+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": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "sanmai/di-container", + "version": "0.1.23", + "source": { + "type": "git", + "url": "https://github.com/sanmai/di-container.git", + "reference": "8cf59c091f33297389d0a5a27ea0d688df15c376" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sanmai/di-container/zipball/8cf59c091f33297389d0a5a27ea0d688df15c376", + "reference": "8cf59c091f33297389d0a5a27ea0d688df15c376", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/container": "^1.1.2 || ^2.0", + "sanmai/pipeline": "^7.10" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.8", + "friendsofphp/php-cs-fixer": "^3.17", + "infection/infection": ">=0.31", + "php-coveralls/php-coveralls": "^2.4.1", + "phpbench/phpbench": "^1.4", + "phpstan/extension-installer": "^1.4", + "phpunit/phpunit": "^11.5.25", + "sanmai/phpstan-rules": "^0.3.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.1.x-dev" + }, + "preferred-install": "dist" + }, + "autoload": { + "psr-4": { + "DIContainer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Alexey Kopytko", + "email": "alexey@kopytko.com", + "homepage": "https://github.com/sanmai" + }, + { + "name": "Maks Rafalko", + "homepage": "https://twitter.com/maks_rafalko" + }, + { + "name": "Théo FIDRY", + "homepage": "https://twitter.com/tfidry" + } + ], + "description": "dependency injection container with automatic constructor dependency resolution", + "keywords": [ + "Autowiring", + "constructor di", + "di container", + "psr 11" + ], + "support": { + "issues": "https://github.com/sanmai/di-container/issues", + "source": "https://github.com/sanmai/di-container/tree/0.1.23" + }, + "funding": [ + { + "url": "https://github.com/sanmai", + "type": "github" + } + ], + "time": "2026-08-11T00:58:41+00:00" + }, + { + "name": "sanmai/duoclock", + "version": "0.1.3", + "source": { + "type": "git", + "url": "https://github.com/sanmai/DuoClock.git", + "reference": "47461e3ff65b7308635047831a55615652e7be1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sanmai/DuoClock/zipball/47461e3ff65b7308635047831a55615652e7be1a", + "reference": "47461e3ff65b7308635047831a55615652e7be1a", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.8", + "friendsofphp/php-cs-fixer": "^3.17", + "infection/infection": ">=0.29", + "php-coveralls/php-coveralls": "^2.4.1", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2", + "phpunit/phpunit": "^11.5.25", + "sanmai/phpstan-rules": "^0.3.1" + }, + "type": "library", + "extra": { + "preferred-install": "dist" + }, + "autoload": { + "psr-4": { + "DuoClock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Alexey Kopytko", + "email": "alexey@kopytko.com" + } + ], + "description": "PHP time mocking for tests - PSR-20 clock with mockable sleep(), time(), and TimeSpy for PHPUnit testing", + "support": { + "issues": "https://github.com/sanmai/DuoClock/issues", + "source": "https://github.com/sanmai/DuoClock/tree/0.1.3" + }, + "funding": [ + { + "url": "https://github.com/sanmai", + "type": "github" + } + ], + "time": "2025-12-26T06:12:34+00:00" + }, + { + "name": "sanmai/later", + "version": "0.1.8", + "source": { + "type": "git", + "url": "https://github.com/sanmai/later.git", + "reference": "c56aeb8fa7fdf81eda2640a68b51884685963d13" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sanmai/later/zipball/c56aeb8fa7fdf81eda2640a68b51884685963d13", + "reference": "c56aeb8fa7fdf81eda2640a68b51884685963d13", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.8", + "friendsofphp/php-cs-fixer": "^3.35.1", + "infection/infection": ">=0.27.6", + "phan/phan": ">=2", + "php-coveralls/php-coveralls": "^2.0", + "phpstan/phpstan": ">=1.4.5", + "phpunit/phpunit": ">=9.5 <10", + "vimeo/psalm": ">=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.1.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Later\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Alexey Kopytko", + "email": "alexey@kopytko.com" + } + ], + "description": "Later: deferred wrapper object", + "support": { + "issues": "https://github.com/sanmai/later/issues", + "source": "https://github.com/sanmai/later/tree/0.1.8" + }, + "funding": [ + { + "url": "https://github.com/sanmai", + "type": "github" + } + ], + "time": "2026-06-29T07:24:33+00:00" + }, + { + "name": "sanmai/pipeline", + "version": "7.10", + "source": { + "type": "git", + "url": "https://github.com/sanmai/pipeline.git", + "reference": "a8e4e57a6031efc7a92defd13fed9c1c4c73fc71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sanmai/pipeline/zipball/a8e4e57a6031efc7a92defd13fed9c1c4c73fc71", + "reference": "a8e4e57a6031efc7a92defd13fed9c1c4c73fc71", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.8", + "esi/phpunit-coverage-check": ">2", + "friendsofphp/php-cs-fixer": "^3.17", + "infection/infection": ">=0.32.3", + "league/pipeline": "^0.3 || ^1.0", + "php-coveralls/php-coveralls": "^2.4.1", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2", + "phpunit/phpunit": "^11 || ^12", + "sanmai/phpstan-rules": "^0.3.11", + "sanmai/phpunit-double-colon-syntax": "^0.1.1", + "vimeo/psalm": ">=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Pipeline\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Alexey Kopytko", + "email": "alexey@kopytko.com" + } + ], + "description": "General-purpose collections pipeline", + "support": { + "issues": "https://github.com/sanmai/pipeline/issues", + "source": "https://github.com/sanmai/pipeline/tree/7.10" + }, + "funding": [ + { + "url": "https://github.com/sanmai", + "type": "github" + } + ], + "time": "2026-08-03T04:56:22+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-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^5.7.0", + "ext-mbstring": "*", "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" + "sebastian/recursion-context": "^6.0" }, "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" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "11.0.x-dev" + "dev-main": "6.3-dev" } }, "autoload": { @@ -717,21 +2873,35 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "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": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ - "coverage", - "testing", - "xunit" + "export", + "exporter" ], "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" + "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": [ { @@ -747,36 +2917,39 @@ "type": "thanks_dev" }, { - "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", "type": "tidelift" } ], - "time": "2025-12-24T07:01:01+00:00" + "time": "2025-09-24T06:12:51+00:00" }, { - "name": "phpunit/php-file-iterator", - "version": "5.1.1", + "name": "sebastian/global-state", + "version": "7.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903", - "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^11.3" + "ext-dom": "*", + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -791,69 +2964,52 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ - "filesystem", - "iterator" + "global state" ], "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" + "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" - }, - { - "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" + "time": "2024-07-03T04:57:36+00:00" }, { - "name": "phpunit/php-invoker", - "version": "5.0.1", + "name": "sebastian/lines-of-code", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", - "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "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": { - "ext-pcntl": "*", "phpunit/phpunit": "^11.0" }, - "suggest": { - "ext-pcntl": "*" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -872,15 +3028,12 @@ "role": "lead" } ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], + "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/php-invoker/issues", - "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + "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": [ { @@ -888,24 +3041,26 @@ "type": "github" } ], - "time": "2024-07-03T05:07:44+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { - "name": "phpunit/php-text-template", - "version": "4.0.1", + "name": "sebastian/object-enumerator", + "version": "6.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", - "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { "phpunit/phpunit": "^11.0" @@ -913,7 +3068,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -928,19 +3083,15 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], + "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/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" + "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": [ { @@ -948,20 +3099,20 @@ "type": "github" } ], - "time": "2024-07-03T05:08:43+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { - "name": "phpunit/php-timer", - "version": "7.0.1", + "name": "sebastian/object-reflector", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", - "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { @@ -973,7 +3124,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -988,19 +3139,15 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], + "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/php-timer/issues", - "security": "https://github.com/sebastianbergmann/php-timer/security/policy", - "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + "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": [ { @@ -1008,67 +3155,35 @@ "type": "github" } ], - "time": "2024-07-03T05:09:35+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { - "name": "phpunit/phpunit", - "version": "11.5.55", + "name": "sebastian/recursion-context", + "version": "6.0.3", "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" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" + "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" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-main": "11.5-dev" + "dev-main": "6.0-dev" } }, "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], "classmap": [ "src/" ] @@ -1080,27 +3195,25 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "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" + "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://phpunit.de/sponsors.html", - "type": "custom" - }, { "url": "https://github.com/sebastianbergmann", "type": "github" @@ -1114,36 +3227,36 @@ "type": "thanks_dev" }, { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", "type": "tidelift" } ], - "time": "2026-02-18T12:37:06+00:00" + "time": "2025-08-13T04:42:22+00:00" }, { - "name": "sebastian/cli-parser", - "version": "3.0.2", + "name": "sebastian/type", + "version": "5.1.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", - "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -1162,45 +3275,54 @@ "role": "lead" } ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", + "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/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + "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": "2024-07-03T04:41:36+00:00" + "time": "2025-08-09T06:55:48+00:00" }, { - "name": "sebastian/code-unit", - "version": "3.0.3", + "name": "sebastian/version", + "version": "5.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", - "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { "php": ">=8.2" }, - "require-dev": { - "phpunit/phpunit": "^11.5" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1219,12 +3341,12 @@ "role": "lead" } ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", + "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/code-unit/issues", - "security": "https://github.com/sebastianbergmann/code-unit/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" + "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": [ { @@ -1232,931 +3354,1167 @@ "type": "github" } ], - "time": "2025-03-19T07:56:08+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "4.0.1", + "name": "staabm/side-effects-detector", + "version": "1.0.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", - "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", "shasum": "" }, "require": { - "php": ">=8.2" + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "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", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, "autoload": { "classmap": [ - "src/" + "lib/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" ], - "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" + "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/sebastianbergmann", + "url": "https://github.com/staabm", "type": "github" } ], - "time": "2024-07-03T04:45:54+00:00" + "time": "2024-10-20T05:08:20+00:00" }, { - "name": "sebastian/comparator", - "version": "6.3.3", + "name": "symfony/console", + "version": "v7.4.18", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9" + "url": "https://github.com/symfony/console.git", + "reference": "23d6f88a29f6d0eac45bd77d70307adf83ba7ab0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", - "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9", + "url": "https://api.github.com/repos/symfony/console/zipball/23d6f88a29f6d0eac45bd77d70307adf83ba7ab0", + "reference": "23d6f88a29f6d0eac45bd77d70307adf83ba7ab0", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-mbstring": "*", "php": ">=8.2", - "sebastian/diff": "^6.0", - "sebastian/exporter": "^6.0" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^7.2|^8.0" }, - "require-dev": { - "phpunit/phpunit": "^11.4" + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" }, - "suggest": { - "ext-bcmath": "For comparing BcMath\\Number objects" + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.3-dev" - } + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, + "type": "library", "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", "keywords": [ - "comparator", - "compare", - "equality" + "cli", + "command-line", + "console", + "terminal" ], "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" + "source": "https://github.com/symfony/console/tree/v7.4.18" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" + "url": "https://github.com/fabpot", + "type": "github" }, { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" + "url": "https://github.com/nicolas-grekas", + "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2026-01-24T09:26:40+00:00" + "time": "2026-08-25T14:18:37+00:00" }, { - "name": "sebastian/complexity", - "version": "4.0.1", + "name": "symfony/deprecation-contracts", + "version": "v3.7.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", - "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d", "shasum": "" }, "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" + "php": ">=8.1" }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "3.7-dev" } }, "autoload": { - "classmap": [ - "src/" + "files": [ + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", "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" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-07-03T04:49:50+00:00" + "time": "2026-06-05T06:23:12+00:00" }, { - "name": "sebastian/diff", - "version": "6.0.2", + "name": "symfony/filesystem", + "version": "v7.4.18", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + "url": "https://github.com/symfony/filesystem.git", + "reference": "90d412aa5277c6819db39e7605aa46b1019e3232" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", - "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/90d412aa5277c6819db39e7605aa46b1019e3232", + "reference": "90d412aa5277c6819db39e7605aa46b1019e3232", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "phpunit/phpunit": "^11.0", - "symfony/process": "^4.2 || ^5" + "symfony/process": "^6.4|^7.0|^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", "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" + "source": "https://github.com/symfony/filesystem/tree/v7.4.18" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-07-03T04:53:05+00:00" + "time": "2026-08-23T10:03:40+00:00" }, { - "name": "sebastian/environment", - "version": "7.2.1", + "name": "symfony/finder", + "version": "v7.4.17", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" + "url": "https://github.com/symfony/finder.git", + "reference": "5ce28827081f6d1f0c32eaf3882750f19cb5bbe6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", - "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", + "url": "https://api.github.com/repos/symfony/finder/zipball/5ce28827081f6d1f0c32eaf3882750f19cb5bbe6", + "reference": "5ce28827081f6d1f0c32eaf3882750f19cb5bbe6", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.3" - }, - "suggest": { - "ext-posix": "*" + "symfony/filesystem": "^6.4|^7.0|^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "7.2-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", "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" + "source": "https://github.com/symfony/finder/tree/v7.4.17" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" + "url": "https://github.com/fabpot", + "type": "github" }, { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" + "url": "https://github.com/nicolas-grekas", + "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-05-21T11:55:47+00:00" + "time": "2026-08-21T12:09:28+00:00" }, { - "name": "sebastian/exporter", - "version": "6.3.2", + "name": "symfony/polyfill-ctype", + "version": "v1.37.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "70a298763b40b213ec087c51c739efcaa90bcd74" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74", - "reference": "70a298763b40b213ec087c51c739efcaa90bcd74", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": ">=8.2", - "sebastian/recursion-context": "^6.0" + "php": ">=7.2" }, - "require-dev": { - "phpunit/phpunit": "^11.3" + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "6.3-dev" + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "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": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", "keywords": [ - "export", - "exporter" + "compatibility", + "ctype", + "polyfill", + "portable" ], "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" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" + "url": "https://github.com/fabpot", + "type": "github" }, { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" + "url": "https://github.com/nicolas-grekas", + "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-09-24T06:12:51+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { - "name": "sebastian/global-state", - "version": "7.0.2", + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.41.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", - "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", "shasum": "" }, "require": { - "php": ">=8.2", - "sebastian/object-reflector": "^4.0", - "sebastian/recursion-context": "^6.0" + "php": ">=7.2" }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^11.0" + "suggest": { + "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "7.0-dev" + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", "keywords": [ - "global state" + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" ], "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" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-07-03T04:57:36+00:00" + "time": "2026-07-28T08:25:59+00:00" }, { - "name": "sebastian/lines-of-code", - "version": "3.0.1", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.42.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", - "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502", + "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502", "shasum": "" }, "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.2" + "php": ">=7.2" }, - "require-dev": { - "phpunit/phpunit": "^11.0" + "suggest": { + "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.0-dev" + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, "classmap": [ - "src/" + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], "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" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-07-03T04:58:38+00:00" + "time": "2026-08-07T06:33:24+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "6.0.1", + "name": "symfony/polyfill-mbstring", + "version": "v1.38.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", - "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", "shasum": "" }, "require": { - "php": ">=8.2", - "sebastian/object-reflector": "^4.0", - "sebastian/recursion-context": "^6.0" + "ext-iconv": "*", + "php": ">=7.2" }, - "require-dev": { - "phpunit/phpunit": "^11.0" + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "6.0-dev" + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], "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" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-07-03T05:00:13+00:00" + "time": "2026-05-27T06:59:30+00:00" }, { - "name": "sebastian/object-reflector", - "version": "4.0.1", + "name": "symfony/polyfill-php85", + "version": "v1.41.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + "url": "https://github.com/symfony/polyfill-php85.git", + "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", - "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/255fab485aaa1006ed411040c42aecd7b5302d7a", + "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a", "shasum": "" }, "require": { - "php": ">=8.2" - }, - "require-dev": { - "phpunit/phpunit": "^11.0" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "4.0-dev" + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php85\\": "" + }, "classmap": [ - "src/" + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], "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" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.41.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-07-03T05:01:32+00:00" + "time": "2026-07-01T12:47:55+00:00" }, { - "name": "sebastian/recursion-context", - "version": "6.0.3", + "name": "symfony/process", + "version": "v7.4.18", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" + "url": "https://github.com/symfony/process.git", + "reference": "058d17fc284cce14efb2385783b55014a461b176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc", - "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc", + "url": "https://api.github.com/repos/symfony/process/zipball/058d17fc284cce14efb2385783b55014a461b176", + "reference": "058d17fc284cce14efb2385783b55014a461b176", "shasum": "" }, "require": { "php": ">=8.2" }, - "require-dev": { - "phpunit/phpunit": "^11.3" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", "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" + "source": "https://github.com/symfony/process/tree/v7.4.18" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" + "url": "https://github.com/fabpot", + "type": "github" }, { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" + "url": "https://github.com/nicolas-grekas", + "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-08-13T04:42:22+00:00" + "time": "2026-08-21T17:40:08+00:00" }, { - "name": "sebastian/type", - "version": "5.1.3", + "name": "symfony/service-contracts", + "version": "v3.7.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", - "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/15e6a07ec2a2c75ceb1b21dd98105ee8456d2257", + "reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, - "require-dev": { - "phpunit/phpunit": "^11.3" + "conflict": { + "ext-psr": "<1.1|>=2" }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "3.7-dev" } }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], "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" + "source": "https://github.com/symfony/service-contracts/tree/v3.7.3" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" + "url": "https://github.com/fabpot", + "type": "github" }, { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" + "url": "https://github.com/nicolas-grekas", + "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-08-09T06:55:48+00:00" + "time": "2026-07-27T15:39:01+00:00" }, { - "name": "sebastian/version", - "version": "5.0.2", + "name": "symfony/string", + "version": "v7.4.15", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" + "url": "https://github.com/symfony/string.git", + "reference": "e394af32256bf9e7bf80849d95e589167c10097b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", - "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", + "url": "https://api.github.com/repos/symfony/string/zipball/e394af32256bf9e7bf80849d95e589167c10097b", + "reference": "e394af32256bf9e7bf80849d95e589167c10097b", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.33", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } + "conflict": { + "symfony/translation-contracts": "<2.5" }, + "require-dev": { + "symfony/emoji": "^7.1|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0" + }, + "type": "library", "autoload": { - "classmap": [ - "src/" + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], "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" + "source": "https://github.com/symfony/string/tree/v7.4.15" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-10-09T05:16:32+00:00" + "time": "2026-07-28T07:33:02+00:00" }, { - "name": "staabm/side-effects-detector", - "version": "1.0.5", + "name": "thecodingmachine/safe", + "version": "v3.4.0", "source": { "type": "git", - "url": "https://github.com/staabm/side-effects-detector.git", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/705683a25bacf0d4860c7dea4d7947bfd09eea19", + "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0" + "php": "^8.1" }, "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" + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpstan/phpstan": "^2", + "phpunit/phpunit": "^10", + "squizlabs/php_codesniffer": "^3.2" }, "type": "library", "autoload": { + "files": [ + "lib/special_cases.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gettext.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/mysql.php", + "generated/mysqli.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rnp.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ], "classmap": [ - "lib/" + "lib/DateTime.php", + "lib/DateTimeImmutable.php", + "lib/Exceptions/", + "generated/Exceptions/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "A static analysis tool to detect side effects in PHP code", - "keywords": [ - "static analysis" - ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", "support": { - "issues": "https://github.com/staabm/side-effects-detector/issues", - "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + "issues": "https://github.com/thecodingmachine/safe/issues", + "source": "https://github.com/thecodingmachine/safe/tree/v3.4.0" }, "funding": [ + { + "url": "https://github.com/OskarStark", + "type": "github" + }, + { + "url": "https://github.com/shish", + "type": "github" + }, + { + "url": "https://github.com/silasjoisten", + "type": "github" + }, { "url": "https://github.com/staabm", "type": "github" } ], - "time": "2024-10-20T05:08:20+00:00" + "time": "2026-02-04T18:08:13+00:00" }, { "name": "theseer/tokenizer", diff --git a/infection.json5.dist b/infection.json5.dist new file mode 100644 index 0000000..c5f2789 --- /dev/null +++ b/infection.json5.dist @@ -0,0 +1,22 @@ +{ + "$schema": "vendor/infection/infection/resources/schema.json", + "source": { + "directories": [ + "src" + ] + }, + "timeout": 10, + "threads": "max", + "logs": { + "text": "infection.log", + "summary": "summary.log", + "stryker": { + // matches versioned release branches, e.g. "0.2.x", "0.3.x" + "badge": "/^\\d+\\.\\d+\\.x$/" + } + }, + "mutators": { + "@default": true + }, + "staticAnalysisTool": "mago" +} diff --git a/test/unit/ConfigProviderTest.php b/test/unit/ConfigProviderTest.php index 268c969..e173353 100644 --- a/test/unit/ConfigProviderTest.php +++ b/test/unit/ConfigProviderTest.php @@ -39,6 +39,15 @@ final class ConfigProviderTest extends TestCase MetadataInterface::class => Metadata\Source::class, ]; + public const EXPECTED_FACTORIES = [ + Pdo\Connection::class => Container\PdoConnectionFactory::class, + Pdo\Driver::class => Container\PdoDriverInterfaceFactory::class, + Result::class => Container\PdoResultFactory::class, + Statement::class => Container\PdoStatementFactory::class, + AdapterPlatform::class => Container\PlatformInterfaceFactory::class, + Metadata\Source::class => Container\MetadataInterfaceFactory::class, + ]; + private ConfigProvider $configProvider; public function testGetDependenciesContainsExpectedAliases(): void @@ -47,6 +56,12 @@ public function testGetDependenciesContainsExpectedAliases(): void self::assertEquals(self::EXPECTED_ALIASES, $config['aliases']); } + public function testGetDependenciesContainsExpectedFactories(): void + { + $config = $this->configProvider->getDependencies(); + self::assertSame(self::EXPECTED_FACTORIES, $config['factories']); + } + public function testGetDependenciesContainsMetadataAlias(): void { $dependencies = $this->configProvider->getDependencies(); diff --git a/test/unit/Pdo/DriverTest.php b/test/unit/Pdo/DriverTest.php index 4776dc3..f953583 100644 --- a/test/unit/Pdo/DriverTest.php +++ b/test/unit/Pdo/DriverTest.php @@ -12,12 +12,12 @@ use PhpDb\Exception\RuntimeException; use PhpDb\Sqlite\Pdo\Connection; use PhpDb\Sqlite\Pdo\Driver; -use PHPUnit\Framework\Attributes\CoversMethod; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -#[CoversMethod(Driver::class, 'getDatabasePlatformName')] +#[CoversClass(Driver::class)] final class DriverTest extends TestCase { protected Driver $pdo; From 930325ec16e6998947f8c413505aa88464d7cae9 Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Wed, 9 Sep 2026 14:07:33 +1000 Subject: [PATCH 7/7] Bring ConfigProviderTest into lint compliance and prune stale baseline entries - Use #[Test] attributes and static:: assertions so the new factories test does not surface lint warnings beyond the baseline count - Regenerate lint-baseline.toml to drop entries no longer present --- lint-baseline.toml | 54 -------------------------------- test/unit/ConfigProviderTest.php | 50 ++++++++++++++++------------- 2 files changed, 29 insertions(+), 75 deletions(-) diff --git a/lint-baseline.toml b/lint-baseline.toml index ab917dd..1c6dc88 100644 --- a/lint-baseline.toml +++ b/lint-baseline.toml @@ -60,12 +60,6 @@ code = "no-multi-assignments" message = "Avoid multiple assignments in a single statement." count = 1 -[[issues]] -file = "src/Metadata/Source.php" -code = "no-negated-ternary" -message = "Negated ternary condition." -count = 1 - [[issues]] file = "src/Metadata/Source.php" code = "prefer-array-spread" @@ -96,12 +90,6 @@ code = "too-many-methods" message = "Class has too many methods." count = 1 -[[issues]] -file = "src/Metadata/Source.php" -code = "yoda-conditions" -message = "Use Yoda condition style for safer comparisons" -count = 1 - [[issues]] file = "src/Pdo/Connection.php" code = "assert-description" @@ -498,48 +486,6 @@ code = "strict-assertions" message = "Use strict assertions in PHPUnit tests." count = 21 -[[issues]] -file = "test/unit/ConfigProviderTest.php" -code = "assertion-style" -message = "Inconsistent assertions style." -count = 13 - -[[issues]] -file = "test/unit/ConfigProviderTest.php" -code = "prefer-test-attribute" -message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetDependenciesContainsExpectedAliases`." -count = 1 - -[[issues]] -file = "test/unit/ConfigProviderTest.php" -code = "prefer-test-attribute" -message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetDependenciesContainsMetadataAlias`." -count = 1 - -[[issues]] -file = "test/unit/ConfigProviderTest.php" -code = "prefer-test-attribute" -message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetDependenciesContainsMetadataFactory`." -count = 1 - -[[issues]] -file = "test/unit/ConfigProviderTest.php" -code = "prefer-test-attribute" -message = "Use `#[Test]` attribute instead of `test` prefix on method `testGetDependenciesReturnsCorrectStructure`." -count = 1 - -[[issues]] -file = "test/unit/ConfigProviderTest.php" -code = "prefer-test-attribute" -message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsCorrectStructure`." -count = 1 - -[[issues]] -file = "test/unit/ConfigProviderTest.php" -code = "prefer-test-attribute" -message = "Use `#[Test]` attribute instead of `test` prefix on method `testInvokeReturnsExpectedStructure`." -count = 1 - [[issues]] file = "test/unit/Container/MetadataInterfaceFactoryTest.php" code = "assertion-style" diff --git a/test/unit/ConfigProviderTest.php b/test/unit/ConfigProviderTest.php index e173353..d4042a2 100644 --- a/test/unit/ConfigProviderTest.php +++ b/test/unit/ConfigProviderTest.php @@ -18,6 +18,7 @@ use PhpDb\Sqlite\Metadata; use PhpDb\Sqlite\Pdo; use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; #[CoversClass(ConfigProvider::class)] @@ -50,63 +51,70 @@ final class ConfigProviderTest extends TestCase private ConfigProvider $configProvider; - public function testGetDependenciesContainsExpectedAliases(): void + #[Test] + public function getDependenciesContainsExpectedAliases(): void { $config = $this->configProvider->getDependencies(); - self::assertEquals(self::EXPECTED_ALIASES, $config['aliases']); + static::assertEquals(self::EXPECTED_ALIASES, $config['aliases']); } - public function testGetDependenciesContainsExpectedFactories(): void + #[Test] + public function getDependenciesContainsExpectedFactories(): void { $config = $this->configProvider->getDependencies(); - self::assertSame(self::EXPECTED_FACTORIES, $config['factories']); + static::assertSame(self::EXPECTED_FACTORIES, $config['factories']); } - public function testGetDependenciesContainsMetadataAlias(): void + #[Test] + public function getDependenciesContainsMetadataAlias(): void { $dependencies = $this->configProvider->getDependencies(); - self::assertArrayHasKey(MetadataInterface::class, $dependencies['aliases']); - self::assertSame( + static::assertArrayHasKey(MetadataInterface::class, $dependencies['aliases']); + static::assertSame( Metadata\Source::class, $dependencies['aliases'][MetadataInterface::class], ); } - public function testGetDependenciesContainsMetadataFactory(): void + #[Test] + public function getDependenciesContainsMetadataFactory(): void { $dependencies = $this->configProvider->getDependencies(); - self::assertArrayHasKey(Metadata\Source::class, $dependencies['factories']); - self::assertSame( + static::assertArrayHasKey(Metadata\Source::class, $dependencies['factories']); + static::assertSame( Container\MetadataInterfaceFactory::class, $dependencies['factories'][Metadata\Source::class], ); } - public function testGetDependenciesReturnsCorrectStructure(): void + #[Test] + public function getDependenciesReturnsCorrectStructure(): void { $dependencies = $this->configProvider->getDependencies(); - self::assertNotEmpty($dependencies); - self::assertArrayHasKey('aliases', $dependencies); - self::assertArrayHasKey('factories', $dependencies); + static::assertNotEmpty($dependencies); + static::assertArrayHasKey('aliases', $dependencies); + static::assertArrayHasKey('factories', $dependencies); } - public function testInvokeReturnsCorrectStructure(): void + #[Test] + public function invokeReturnsCorrectStructure(): void { $config = (new ConfigProvider())(); - self::assertArrayHasKey('dependencies', $config); - self::assertArrayHasKey('aliases', $config['dependencies']); - self::assertArrayHasKey('factories', $config['dependencies']); + static::assertArrayHasKey('dependencies', $config); + static::assertArrayHasKey('aliases', $config['dependencies']); + static::assertArrayHasKey('factories', $config['dependencies']); } - public function testInvokeReturnsExpectedStructure(): void + #[Test] + public function invokeReturnsExpectedStructure(): void { $config = ($this->configProvider)(); - self::assertNotEmpty($config); - self::assertArrayHasKey('dependencies', $config); + static::assertNotEmpty($config); + static::assertArrayHasKey('dependencies', $config); } protected function setUp(): void