diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index 2f2fe2a..7d97fac 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -5,10 +5,102 @@ on:
pull_request:
workflow_dispatch:
+env:
+ COMPOSER_FLAGS: "--ansi --no-interaction --no-progress --prefer-dist --no-plugins"
+ COMPOSER_UPDATE_FLAGS: ""
+
jobs:
- ci:
- uses: ray-di/.github/.github/workflows/continuous-integration.yml@v1
- with:
- old_stable: '["7.3", "7.4", "8.0", "8.1", "8.2", , "8.31"]'
- current_stable: 8.4
- script: demo/run.php
+ phpunit:
+ name: PHPUnit - PHP ${{ matrix.php-version }} (${{ matrix.os }}, ${{ matrix.dependencies }})
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ # PHP 8.2
+ - {php-version: "8.2", os: ubuntu-latest, dependencies: highest}
+ - {php-version: "8.2", os: ubuntu-latest, dependencies: lowest}
+ # PHP 8.3
+ - {php-version: "8.3", os: ubuntu-latest, dependencies: highest}
+ - {php-version: "8.3", os: ubuntu-latest, dependencies: lowest}
+ # PHP 8.4 (current stable)
+ # aura/sql 5.x (lowest) is skipped on PHP 8.4: PDO::connect() static/non-static conflict (upstream bug)
+ - {php-version: "8.4", os: windows-latest, dependencies: highest}
+ - {php-version: "8.4", os: ubuntu-latest, dependencies: highest}
+
+ steps:
+ - name: Disable autocrlf on Windows
+ if: contains(matrix.os, 'windows')
+ run: git config --global core.autocrlf false
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Setup PHP ${{ matrix.php-version }}
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-version }}
+ coverage: pcov
+ ini-values: |
+ zend.assertions=1
+ memory_limit=512M
+ opcache.jit=0
+ opcache.jit_buffer_size=0
+ opcache.enable=0
+ opcache.enable_cli=0
+ extensions: fileinfo,pdo,pdo_mysql,pdo_sqlite
+
+ - name: Check fileinfo extension
+ run: php --ri fileinfo
+
+ - name: Get composer cache directory
+ id: composer-cache
+ shell: bash
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+
+ - name: Cache dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-php${{ matrix.php-version }}-composer-${{ hashFiles('**/composer.json', '**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-php${{ matrix.php-version }}-composer-
+ ${{ runner.os }}-composer-
+
+ - name: Set platform requirements
+ shell: bash
+ run: composer config platform.php ${{ matrix.php-version }}
+
+ - name: Handle lowest dependencies
+ if: matrix.dependencies == 'lowest'
+ shell: bash
+ run: echo COMPOSER_UPDATE_FLAGS="$COMPOSER_UPDATE_FLAGS --prefer-lowest" >> $GITHUB_ENV
+
+ - name: Remove platform config for highest resolution
+ if: matrix.dependencies == 'highest'
+ shell: bash
+ run: composer config platform --unset
+
+ - name: Update dependencies
+ shell: bash
+ run: |
+ composer validate --no-check-all --strict
+ composer update ${{ env.COMPOSER_UPDATE_FLAGS }} ${{ env.COMPOSER_FLAGS }}
+
+ - name: Run test suite
+ shell: bash
+ run: vendor/bin/phpunit --coverage-clover=coverage.xml
+ env:
+ XDEBUG_MODE: coverage
+
+ - name: Upload coverage report
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ fail_ci_if_error: false
+
+ - name: Run additional script
+ shell: bash
+ run: php demo/run.php
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
index 1e5f6bf..ed34a12 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -9,4 +9,4 @@ jobs:
sa:
uses: ray-di/.github/.github/workflows/static-analysis.yml@v1
with:
- php_version: 8.3
+ php_version: 8.4
diff --git a/composer.json b/composer.json
index c049470..7653354 100644
--- a/composer.json
+++ b/composer.json
@@ -10,19 +10,18 @@
}
],
"require": {
- "php": "^7.3 || ^8.0",
+ "php": "^8.2",
"ext-json": "*",
"ext-pdo": "*",
- "aura/sql": "^3.0 | ^4.0 | ^5.0",
+ "aura/sql": "^5.0.3 | ^6.0",
"bear/resource": "^1.15",
- "doctrine/annotations": "^1.12",
"guzzlehttp/guzzle": "^6.3 || ^7.0",
"koriym/param-reader": "^1.0",
"koriym/query-locator": "^1.4",
"nikic/php-parser": "^v4.13",
"ray/aop": "^2.10.3",
"ray/aura-sql-module": "^1.10.0",
- "ray/di": "^2.11"
+ "ray/di": "^2.20"
},
"require-dev": {
"phpunit/phpunit": "^9.6.19",
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
deleted file mode 100644
index 4d94b24..0000000
--- a/phpstan-baseline.neon
+++ /dev/null
@@ -1,37 +0,0 @@
-parameters:
- ignoreErrors:
- -
- message: "#^Method Ray\\\\Query\\\\QueryInterface\\:\\:__invoke\\(\\) has parameter \\$query with no value type specified in iterable type array\\.$#"
- count: 1
- path: src/QueryInterface.php
-
- -
- message: "#^Method Ray\\\\Query\\\\RowInterface\\:\\:__invoke\\(\\) has parameter \\$query with no value type specified in iterable type array\\.$#"
- count: 1
- path: src/RowInterface.php
-
- -
- message: "#^Method Ray\\\\Query\\\\RowListInterface\\:\\:__invoke\\(\\) has parameter \\$query with no value type specified in iterable type array\\.$#"
- count: 1
- path: src/RowListInterface.php
-
- -
- message: "#^Method Ray\\\\Query\\\\SqlQueryRow\\:\\:__invoke\\(\\) has parameter \\$queries with no value type specified in iterable type array\\.$#"
- count: 1
- path: src/SqlQueryRow.php
-
- -
- message: "#^Method Ray\\\\Query\\\\SqlQueryRowList\\:\\:__invoke\\(\\) has parameter \\$queries with no value type specified in iterable type array\\.$#"
- count: 1
- path: src/SqlQueryRowList.php
-
- -
- message: "#^Method Ray\\\\Query\\\\WebQuery\\:\\:__invoke\\(\\) has parameter \\$queries with no value type specified in iterable type array\\.$#"
- count: 1
- path: src/WebQuery.php
-
- -
- message: "#^Method class@anonymous/tests/Iso8601InterceptorTest\\.php\\:33\\:\\:__invoke\\(\\) has parameter \\$query with no value type specified in iterable type array\\.$#"
- count: 1
- path: tests/Iso8601InterceptorTest.php
-
diff --git a/phpstan.neon b/phpstan.neon
index 8978572..6e01048 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -3,6 +3,6 @@ parameters:
paths:
- src
- tests
- excludes_analyse:
+ excludePaths:
- %currentWorkingDirectory%/tests/tmp/*
- %currentWorkingDirectory%/tests/Fake/*
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
deleted file mode 100644
index 057768d..0000000
--- a/psalm-baseline.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
- FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::SKIP_DOTS
-
-
-
-
- FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::SKIP_DOTS
-
-
-
diff --git a/psalm.xml b/psalm.xml
index 31406d6..c21120f 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -5,7 +5,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
- errorBaseline="psalm-baseline.xml"
>
@@ -15,4 +14,7 @@
+
+
+
diff --git a/src-deprecated/Annotation/AliasQuery.php b/src-deprecated/Annotation/AliasQuery.php
index 34520bb..9cde94a 100644
--- a/src-deprecated/Annotation/AliasQuery.php
+++ b/src-deprecated/Annotation/AliasQuery.php
@@ -4,34 +4,27 @@
namespace Ray\Query\Annotation;
+use Attribute;
+
/**
- * Annotates your class methods into which the Injector should inject values
- *
- * @Annotation
- * @Target("METHOD")
- *
- * @deprecated use MapQuery instead
+ * @deprecated use Query instead
*/
+#[Attribute(Attribute::TARGET_METHOD)]
final class AliasQuery
{
- /**
- * Query ID
- *
- * @var string
- */
+ /** @var string */
public $id;
- /**
- * Is ID templated ?
- *
- * @var bool
- */
+ /** @var bool */
public $templated = false;
- /**
- * @Enum({"row", "row_list"})
- *
- * @var string
- */
+ /** @var 'row'|'row_list' */
public $type = 'row_list';
+
+ public function __construct(string $id = '', string $type = 'row_list', bool $templated = false)
+ {
+ $this->id = $id;
+ $this->type = $type;
+ $this->templated = $templated;
+ }
}
diff --git a/src/Annotation/Query.php b/src/Annotation/Query.php
index cd0f956..8da8fcc 100644
--- a/src/Annotation/Query.php
+++ b/src/Annotation/Query.php
@@ -5,17 +5,8 @@
namespace Ray\Query\Annotation;
use Attribute;
-use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
use Ray\Query\Exception\QueryTypeException;
-/**
- * Annotates your class methods into which the Injector should inject values
- *
- * @Annotation
- * @Target("METHOD")
- * @psalm-suppress MissingConstructor
- * @NamedArgumentConstructor
- */
#[Attribute(Attribute::TARGET_METHOD)]
final class Query
{
@@ -33,13 +24,13 @@ final class Query
*/
public $templated;
- /**
- * @Enum({"row", "row_list"})
- * @var 'row'|'row_list'
- */
+ /** @var 'row'|'row_list' */
public $type = 'row_list';
- /** @SuppressWarnings(PHPMD.BooleanArgumentFlag) */
+ /**
+ * @psalm-api
+ * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
+ */
public function __construct(string $id, string $type = 'row_list', bool $templated = false)
{
$this->id = $id;
diff --git a/src/Annotation/Sql.php b/src/Annotation/Sql.php
index ab09930..8a2006b 100644
--- a/src/Annotation/Sql.php
+++ b/src/Annotation/Sql.php
@@ -5,19 +5,14 @@
namespace Ray\Query\Annotation;
use Attribute;
-use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
-/**
- * @Annotation
- * @Target("PROPERTY")
- * @NamedArgumentConstructor()
- */
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_PARAMETER)]
final class Sql
{
/** @var string */
public $sql;
+ /** @psalm-api */
public function __construct(string $sql)
{
$this->sql = $sql;
diff --git a/src/Exception/QueryNumException.php b/src/Exception/QueryNumException.php
index 441bcbf..5a96022 100644
--- a/src/Exception/QueryNumException.php
+++ b/src/Exception/QueryNumException.php
@@ -6,6 +6,6 @@
use InvalidArgumentException;
-class QueryNumException extends InvalidArgumentException
+final class QueryNumException extends InvalidArgumentException
{
}
diff --git a/src/Exception/QueryTypeException.php b/src/Exception/QueryTypeException.php
index b0a6ea9..22f6d85 100644
--- a/src/Exception/QueryTypeException.php
+++ b/src/Exception/QueryTypeException.php
@@ -6,6 +6,6 @@
use InvalidArgumentException;
-class QueryTypeException extends InvalidArgumentException
+final class QueryTypeException extends InvalidArgumentException
{
}
diff --git a/src/Exception/SqlFileNotFoundException.php b/src/Exception/SqlFileNotFoundException.php
index 57dbac7..4ddc528 100644
--- a/src/Exception/SqlFileNotFoundException.php
+++ b/src/Exception/SqlFileNotFoundException.php
@@ -6,6 +6,6 @@
use LogicException;
-class SqlFileNotFoundException extends LogicException
+final class SqlFileNotFoundException extends LogicException
{
}
diff --git a/src/Exception/SqlNotAnnotatedException.php b/src/Exception/SqlNotAnnotatedException.php
index 2859047..b98cb4f 100644
--- a/src/Exception/SqlNotAnnotatedException.php
+++ b/src/Exception/SqlNotAnnotatedException.php
@@ -6,6 +6,6 @@
use LogicException;
-class SqlNotAnnotatedException extends LogicException
+final class SqlNotAnnotatedException extends LogicException
{
}
diff --git a/src/Exception/WebQueryException.php b/src/Exception/WebQueryException.php
index 50300e8..272d9fb 100644
--- a/src/Exception/WebQueryException.php
+++ b/src/Exception/WebQueryException.php
@@ -6,6 +6,6 @@
use RuntimeException;
-class WebQueryException extends RuntimeException
+final class WebQueryException extends RuntimeException
{
}
diff --git a/src/Iso8601FormatModule.php b/src/Iso8601FormatModule.php
index 0491cc3..d64c1c0 100644
--- a/src/Iso8601FormatModule.php
+++ b/src/Iso8601FormatModule.php
@@ -6,7 +6,8 @@
use Ray\Di\AbstractModule;
-class Iso8601FormatModule extends AbstractModule
+/** @psalm-api */
+final class Iso8601FormatModule extends AbstractModule
{
/** @var array */
private $datetimeColumns;
diff --git a/src/Iso8601Interceptor.php b/src/Iso8601Interceptor.php
index 154f598..c458963 100644
--- a/src/Iso8601Interceptor.php
+++ b/src/Iso8601Interceptor.php
@@ -21,10 +21,10 @@ final class Iso8601Interceptor implements MethodInterceptor
/**
* @param string[] $datetimeColumns
*
- * @Named("datetimeColumns=iso8601_date_time_columns")
+ * @psalm-api
*/
- #[Named('datetimeColumns=iso8601_date_time_columns')]
- public function __construct(array $datetimeColumns)
+ public function __construct(#[Named('iso8601_date_time_columns')]
+ array $datetimeColumns)
{
$this->datetimeColumns = $datetimeColumns;
}
diff --git a/src/PhpQueryModule.php b/src/PhpQueryModule.php
index 685b9d4..2cecad5 100644
--- a/src/PhpQueryModule.php
+++ b/src/PhpQueryModule.php
@@ -10,12 +10,13 @@
use function class_exists;
use function is_string;
+/** @psalm-api */
class PhpQueryModule extends AbstractModule
{
- /** @var iterable */
+ /** @var iterable */
private $configs;
- /** @param iterable $configs */
+ /** @param iterable $configs */
public function __construct(iterable $configs, ?AbstractModule $module = null)
{
$this->configs = $configs;
@@ -32,7 +33,10 @@ protected function configure(): void
}
}
- /** @param mixed $binding */
+ /**
+ * @param non-empty-string $name
+ * @param mixed $binding
+ */
private function bindQuery(string $name, $binding): void
{
if (is_string($binding) && class_exists($binding) && (new ReflectionClass($binding))->implementsInterface(QueryInterface::class)) {
diff --git a/src/QueryInterceptor.php b/src/QueryInterceptor.php
index 8911e4a..6ac0678 100644
--- a/src/QueryInterceptor.php
+++ b/src/QueryInterceptor.php
@@ -16,7 +16,8 @@
use function parse_str;
use function parse_url;
-class QueryInterceptor implements MethodInterceptor
+/** @psalm-api */
+final class QueryInterceptor implements MethodInterceptor
{
/** @var InjectorInterface */
private $injector;
diff --git a/src/RowInterfaceProvider.php b/src/RowInterfaceProvider.php
index e707e62..22be6f7 100644
--- a/src/RowInterfaceProvider.php
+++ b/src/RowInterfaceProvider.php
@@ -8,7 +8,10 @@
use Ray\Di\InjectionPointInterface;
use Ray\Di\ProviderInterface;
-/** @implements ProviderInterface */
+/**
+ * @psalm-api
+ * @implements ProviderInterface
+ */
final class RowInterfaceProvider implements ProviderInterface
{
/** @var InjectionPointInterface */
diff --git a/src/RowListInterfaceProvider.php b/src/RowListInterfaceProvider.php
index 284f32e..f984236 100644
--- a/src/RowListInterfaceProvider.php
+++ b/src/RowListInterfaceProvider.php
@@ -8,7 +8,10 @@
use Ray\Di\InjectionPointInterface;
use Ray\Di\ProviderInterface;
-/** @implements ProviderInterface */
+/**
+ * @psalm-api
+ * @implements ProviderInterface
+ */
final class RowListInterfaceProvider implements ProviderInterface
{
/** @var InjectionPointInterface */
diff --git a/src/SqlFileName.php b/src/SqlFileName.php
index 8f2c4e3..0185102 100644
--- a/src/SqlFileName.php
+++ b/src/SqlFileName.php
@@ -9,6 +9,7 @@
use function file_get_contents;
use function sprintf;
+/** @psalm-api */
final class SqlFileName
{
/**
diff --git a/src/SqlFinder.php b/src/SqlFinder.php
index 30d511c..f8fceff 100644
--- a/src/SqlFinder.php
+++ b/src/SqlFinder.php
@@ -14,6 +14,7 @@
use function file_get_contents;
use function sprintf;
+/** @psalm-api */
final class SqlFinder
{
/** @var ParamReaderInterface