diff --git a/.github/workflows/code-checks.yml b/.github/workflows/code-checks.yml index 5ecb947..4d7578e 100644 --- a/.github/workflows/code-checks.yml +++ b/.github/workflows/code-checks.yml @@ -11,8 +11,6 @@ jobs: strategy: matrix: php: - - '7.4' - - '8.0' - '8.1' - '8.2' - '8.3' diff --git a/.gitignore b/.gitignore index 4901aab..a3ee6db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -/vendor +/.phpunit.cache/ +/vendor/ /composer.lock -/.phpunit.result.cache diff --git a/.runConfigurations/All tests.run.xml b/.runConfigurations/All tests.run.xml index 8050fe4..cff37e4 100644 --- a/.runConfigurations/All tests.run.xml +++ b/.runConfigurations/All tests.run.xml @@ -6,7 +6,7 @@ - + \ No newline at end of file diff --git a/.runConfigurations/All unit tests.run.xml b/.runConfigurations/All unit tests.run.xml index 0a179b1..1c5c127 100644 --- a/.runConfigurations/All unit tests.run.xml +++ b/.runConfigurations/All unit tests.run.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.runConfigurations/Integration tests.run.xml b/.runConfigurations/Integration tests.run.xml index ce1486d..050b950 100644 --- a/.runConfigurations/Integration tests.run.xml +++ b/.runConfigurations/Integration tests.run.xml @@ -6,7 +6,7 @@ - + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d65742..183a0b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added +- Add PHP v8 type declarations. +### Removed +- **BC break**: Removed support for PHP versions <= v8.0 as they are no longer + [actively supported](https://php.net/supported-versions.php) by the PHP project. ## [2.2.0] - 2024-10-22 ### Added diff --git a/composer.json b/composer.json index 072db41..25c0305 100644 --- a/composer.json +++ b/composer.json @@ -17,11 +17,11 @@ } ], "require": { - "php": "^7.4 || ^8.0", + "php": "^8.1", "ext-pdo": "*" }, "require-dev": { - "phpunit/phpunit": "^9", + "phpunit/phpunit": "^10", "symplify/easy-coding-standard": "^12" }, "autoload": { diff --git a/ecs.php b/ecs.php index d9deafc..4832784 100644 --- a/ecs.php +++ b/ecs.php @@ -52,4 +52,19 @@ [ 'closure_fn_spacing' => 'none', ], + ) + + /* + * Rule from PER Coding Style 2.6: + * "If the list is split across multiple lines, then the last item MUST have a trailing comma." + */ + ->withConfiguredRule( + \PhpCsFixer\Fixer\ControlStructure\TrailingCommaInMultilineFixer::class, + [ + 'elements' => [ + \PhpCsFixer\Fixer\ControlStructure\TrailingCommaInMultilineFixer::ELEMENTS_ARGUMENTS, + \PhpCsFixer\Fixer\ControlStructure\TrailingCommaInMultilineFixer::ELEMENTS_ARRAYS, + \PhpCsFixer\Fixer\ControlStructure\TrailingCommaInMultilineFixer::ELEMENTS_PARAMETERS, + ], + ], ); diff --git a/phpunit.xml.dist b/phpunit.xml.dist index e35ee00..42bb03e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,10 @@ @@ -20,9 +20,9 @@ tests - + src - + diff --git a/src/Adapter.php b/src/Adapter.php index d7e185f..689e4bd 100644 --- a/src/Adapter.php +++ b/src/Adapter.php @@ -168,7 +168,7 @@ public function ping(): bool { try { return $this->query('SELECT "1"')->fetchColumn() === '1'; - } catch (\Exception $e) { + } catch (\Exception) { return false; } } @@ -177,7 +177,7 @@ public function ping(): bool * Get the last inserted id. If the tablename is provided the id returned is * the last insert id will be for that table. */ - public function lastInsertId(string $tablename = null): string + public function lastInsertId(?string $tablename = null): string { // the lastInsertId is cached from the last insert, so no point in detected disconnection return $this->getConnection()->lastInsertId($tablename); diff --git a/src/Adapter/ConnectionFactory.php b/src/Adapter/ConnectionFactory.php index a6c830c..5a5a13e 100644 --- a/src/Adapter/ConnectionFactory.php +++ b/src/Adapter/ConnectionFactory.php @@ -47,7 +47,7 @@ public function create(Config $config): \PDO $config->getDsn(), $config->getUsername(), $config->getPassword(), - $config->getOptions() + $config->getOptions(), ); } } diff --git a/src/Adapter/QuoteHandler.php b/src/Adapter/QuoteHandler.php index 4e4b071..c34d9c0 100644 --- a/src/Adapter/QuoteHandler.php +++ b/src/Adapter/QuoteHandler.php @@ -8,27 +8,21 @@ class QuoteHandler { - private bool $autoQuoteIdentifiers; - - private \Closure $quoteFn; - /** * @param \Closure{ * value: mixed, * }:string $quoteFn */ - public function __construct(\Closure $quoteFn, bool $autoQuoteIdentifiers = true) - { - $this->quoteFn = $quoteFn; - $this->autoQuoteIdentifiers = $autoQuoteIdentifiers; + public function __construct( + private readonly \Closure $quoteFn, + private readonly bool $autoQuoteIdentifiers = true, + ) { } /** - * Quote a database value. - * - * @param mixed $value + * Quote a value for the database */ - public function value($value): string + public function value(mixed $value): string { switch (true) { case is_object($value): @@ -43,7 +37,7 @@ public function value($value): string case $value === null: return 'NULL'; case is_array($value): - $value = array_map(function ($value) { + $value = array_map(function ($value): string { if (is_array($value)) { $value = 'Array'; } @@ -56,52 +50,51 @@ public function value($value): string } /** - * Quote into the value for the database. - * - * @param mixed $value + * Quote a value to replace the `?` placeholder */ - public function into(string $text, $value): string + public function into(string $text, mixed $value): string { return str_replace('?', $this->value($value), $text); } /** - * Quote a column identifier and alias. - * - * @param string|string[] $ident + * Quote a column identifier and alias */ - public function columnAs($ident, string $alias, bool $auto = false): string - { + public function columnAs( + string|array|object $ident, + string $alias, + bool $auto = false, + ): string { return $this->quoteIdentifierAs($ident, $alias, $auto); } /** - * Quote a table identifier and alias. - * - * @param string|string[] $ident + * Quote a table identifier and alias */ - public function tableAs($ident, string $alias, bool $auto = false): string - { + public function tableAs( + string|array|object $ident, + string $alias, + bool $auto = false, + ): string { return $this->quoteIdentifierAs($ident, $alias, $auto); } /** - * Quotes an identifier - * - * @param string|string[] $ident + * Quote an identifier */ - public function identifier($ident, bool $auto = false): string - { + public function identifier( + string|array|object $ident, + bool $auto = false, + ): string { return $this->quoteIdentifierAs($ident, null, $auto); } - /** - * Quote an identifier and an optional alias. - * - * @param string|array|object $ident - */ - private function quoteIdentifierAs($ident, string $alias = null, bool $auto = false, string $as = ' AS '): string - { + private function quoteIdentifierAs( + string|array|object $ident, + ?string $alias = null, + bool $auto = false, + string $as = ' AS ', + ): string { if (is_object($ident) && method_exists($ident, 'assemble')) { $quoted = '(' . $ident->assemble() . ')'; } elseif (is_object($ident)) { diff --git a/src/AdapterInterface.php b/src/AdapterInterface.php index 8e8cee0..3aa2c08 100644 --- a/src/AdapterInterface.php +++ b/src/AdapterInterface.php @@ -40,7 +40,7 @@ public function ping(): bool; * Get the last inserted id. If the tablename is provided the id returned is * the last insert id will be for that table. */ - public function lastInsertId(string $tablename = null): string; + public function lastInsertId(?string $tablename = null): string; public function prepare(string $statement): \PDOStatement; diff --git a/src/Exception/InvalidQueryException.php b/src/Exception/InvalidQueryException.php index 5956ddd..8742d49 100644 --- a/src/Exception/InvalidQueryException.php +++ b/src/Exception/InvalidQueryException.php @@ -6,27 +6,23 @@ class InvalidQueryException extends RuntimeException implements Exception { - private string $query; - - private array $bind; - public static function isInvalidSyntax(\PDOException $exception): bool { return stripos($exception->getMessage(), 'You have an error in your SQL syntax') !== false; } - public function __construct(string $query, array $bind = [], \PDOException $previous = null) - { - $this->query = $query; - $this->bind = $bind; - + public function __construct( + private readonly string $query, + private readonly array $bind = [], + ?\PDOException $previous = null, + ) { $message = 'You have an error in your SQL syntax.'; $code = 0; if ($previous !== null) { $message = $previous->getMessage(); $code = (int)$previous->getCode(); } - $message .= ' SQL: ' . $query . ' Bind: ' . var_export($bind, true); + $message .= ' SQL: ' . $this->query . ' Bind: ' . var_export($this->bind, true); parent::__construct($message, $code, $previous); } diff --git a/src/Exception/UnknownDatabaseException.php b/src/Exception/UnknownDatabaseException.php index 4d97418..a8fa1a7 100644 --- a/src/Exception/UnknownDatabaseException.php +++ b/src/Exception/UnknownDatabaseException.php @@ -24,8 +24,6 @@ class UnknownDatabaseException extends RuntimeException implements Exception */ public const ER_BAD_DB_ERROR_2 = 42000; - private string $name; - public static function createFromUnknownDatabase(string $database, \PDOException $exception): self { return new static($database, "Unknown database '{$database}'.", self::ER_BAD_DB_ERROR_1, $exception); @@ -40,9 +38,12 @@ public static function isUnknownDatabase(\PDOException $exception): bool ); } - public function __construct(string $database, string $message, int $code = 0, \PDOException $previous = null) - { - $this->name = $database; + public function __construct( + private readonly string $name, + string $message, + int $code = 0, + ?\PDOException $previous = null, + ) { parent::__construct($message, $code, $previous); } diff --git a/src/SqlFragment.php b/src/SqlFragment.php index e42ab5a..1f52fcd 100644 --- a/src/SqlFragment.php +++ b/src/SqlFragment.php @@ -10,11 +10,9 @@ */ class SqlFragment { - private string $value; - - public function __construct(string $value) - { - $this->value = $value; + public function __construct( + private readonly string $value, + ) { } public function __toString(): string diff --git a/tests/Adapter/ConfigTest.php b/tests/Adapter/ConfigTest.php index dcba81c..a2d5986 100644 --- a/tests/Adapter/ConfigTest.php +++ b/tests/Adapter/ConfigTest.php @@ -6,20 +6,19 @@ use Phlib\Db\Adapter\Config; use Phlib\Db\Exception\InvalidArgumentException; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class ConfigTest extends TestCase { - /** - * @dataProvider getDsnDataProvider - */ + #[DataProvider('getDsnDataProvider')] public function testGetDsn(array $dsnConfig, string $expectedElement): void { $config = new Config($dsnConfig); static::assertStringContainsString($dsnConfig[$expectedElement], $config->getDsn()); } - public function getDsnDataProvider(): array + public static function getDsnDataProvider(): array { return [ [['host' => '127.0.0.1'], 'host'], @@ -36,11 +35,8 @@ public function testGetDsnWithoutHost(): void $config->getDsn(); } - /** - * @param mixed $value - * @dataProvider getMethodsDataProvider - */ - public function testGetMethods(string $method, string $element, $value): void + #[DataProvider('getMethodsDataProvider')] + public function testGetMethods(string $method, string $element, string $value): void { $config = new Config([ $element => $value, @@ -48,7 +44,7 @@ public function testGetMethods(string $method, string $element, $value): void static::assertSame($value, $config->{$method}()); } - public function getMethodsDataProvider(): array + public static function getMethodsDataProvider(): array { return [ ['getUsername', 'username', 'foo'], @@ -59,18 +55,15 @@ public function getMethodsDataProvider(): array ]; } - /** - * @param mixed $expected - * @dataProvider getOptionsDataProvider - */ - public function testGetOptions(array $data, int $element, $expected): void + #[DataProvider('getOptionsDataProvider')] + public function testGetOptions(array $data, int $element, int $expected): void { $options = (new Config($data))->getOptions(); static::assertArrayHasKey($element, $options); static::assertSame($expected, $options[$element]); } - public function getOptionsDataProvider(): array + public static function getOptionsDataProvider(): array { return [ 'timeout-default' => [ @@ -164,9 +157,7 @@ public function getOptionsDataProvider(): array ]; } - /** - * @dataProvider getMaximumAttemptsDataProvider - */ + #[DataProvider('getMaximumAttemptsDataProvider')] public function testGetMaximumAttempts(int $value, int $expected): void { $config = new Config([ @@ -175,7 +166,7 @@ public function testGetMaximumAttempts(int $value, int $expected): void static::assertSame($expected, $config->getMaximumAttempts()); } - public function getMaximumAttemptsDataProvider(): array + public static function getMaximumAttemptsDataProvider(): array { return [ [-1, 1], diff --git a/tests/Adapter/ConnectionFactoryTest.php b/tests/Adapter/ConnectionFactoryTest.php index 4071e11..b7ee101 100644 --- a/tests/Adapter/ConnectionFactoryTest.php +++ b/tests/Adapter/ConnectionFactoryTest.php @@ -9,6 +9,7 @@ use Phlib\Db\Exception\RuntimeException; use Phlib\Db\Exception\UnknownDatabaseException; use Phlib\Db\Tests\Exception\PDOExceptionStub; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -60,7 +61,7 @@ public function testConnectionSetsCharsetTimezone(): void $this->factory->method('create') ->willReturn($this->pdo); - $testSet = function (string $sql) use ($charset, $timezone) { + $testSet = function (string $sql) use ($charset, $timezone): bool { static::assertStringStartsWith('SET ', $sql); static::assertStringContainsString('NAMES ' . $charset, $sql); static::assertStringContainsString('time_zone = "' . $timezone . '"', $sql); @@ -90,16 +91,14 @@ public function testSettingUnknownDatabase(): void $this->factory->method('create') ->willThrowException(new PDOExceptionStub( "SQLSTATE[HY000] [1049] Unknown database ''", - 1049 + 1049, )); $this->config->method('getMaximumAttempts') ->willReturn(5); $this->factory->__invoke($this->config); } - /** - * @dataProvider exceedingNumberOfAttemptsDataProvider - */ + #[DataProvider('exceedingNumberOfAttemptsDataProvider')] public function testExceedingNumberOfAttempts(int $attempts): void { $this->expectException(RuntimeException::class); @@ -107,14 +106,14 @@ public function testExceedingNumberOfAttempts(int $attempts): void $this->factory->method('create') ->willThrowException(new PDOExceptionStub( "SQLSTATE[HY000] [1049] Unknown database ''", - 1049 + 1049, )); $this->config->method('getMaximumAttempts') ->willReturn($attempts); $this->factory->__invoke($this->config); } - public function exceedingNumberOfAttemptsDataProvider(): array + public static function exceedingNumberOfAttemptsDataProvider(): array { return [ [1], @@ -133,7 +132,7 @@ public function testFailedAttemptThenSucceeds(): void ->method('exec') ->will(static::onConsecutiveCalls( static::throwException(new \PDOException()), - static::returnValue(0) + static::returnValue(0), )); $this->config->method('getMaximumAttempts') diff --git a/tests/Adapter/CrudTraitTest.php b/tests/Adapter/CrudTraitTest.php index 773a29c..3645b46 100644 --- a/tests/Adapter/CrudTraitTest.php +++ b/tests/Adapter/CrudTraitTest.php @@ -7,6 +7,7 @@ use Phlib\Db\Adapter\CrudTrait; use Phlib\Db\Adapter\QuoteHandler; use Phlib\Db\SqlFragment; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -22,19 +23,17 @@ protected function setUp(): void parent::setUp(); $this->crud = $this->getMockBuilder(CrudTrait::class) - ->setMethods(['query', 'quote']) + ->onlyMethods(['query', 'quote']) ->getMockForTrait(); - $quoteHandler = new QuoteHandler(function ($value) { + $quoteHandler = new QuoteHandler(function ($value): string { return "'{$value}'"; }); $this->crud->method('quote') ->willReturn($quoteHandler); } - /** - * @dataProvider selectDataProvider - */ + #[DataProvider('selectDataProvider')] public function testSelect(string $expectedSql, string $table, array $where): void { $pdoStatement = $this->createMock(\PDOStatement::class); @@ -49,7 +48,7 @@ public function testSelect(string $expectedSql, string $table, array $where): vo $this->crud->select($table); } - public function selectDataProvider(): array + public static function selectDataProvider(): array { return [ [ @@ -87,9 +86,7 @@ public function testSelectReturnsStatement(): void static::assertSame($pdoStatement, $this->crud->select('my_table')); } - /** - * @dataProvider insertDataProvider - */ + #[DataProvider('insertDataProvider')] public function testInsert(string $expectedSql, string $table, array $data): void { // Returned stmt will have rowCount called @@ -109,7 +106,7 @@ public function testInsert(string $expectedSql, string $table, array $data): voi static::assertSame($rowCount, $actual); } - public function insertDataProvider(): array + public static function insertDataProvider(): array { return [ [ @@ -144,9 +141,7 @@ public function insertDataProvider(): array ]; } - /** - * @dataProvider replaceDataProvider - */ + #[DataProvider('replaceDataProvider')] public function testReplace(string $expectedSql, string $table, array $data): void { // Returned stmt will have rowCount called @@ -166,7 +161,7 @@ public function testReplace(string $expectedSql, string $table, array $data): vo static::assertSame($rowCount, $actual); } - public function replaceDataProvider(): array + public static function replaceDataProvider(): array { return [ [ @@ -201,9 +196,7 @@ public function replaceDataProvider(): array ]; } - /** - * @dataProvider updateDataProvider - */ + #[DataProvider('updateDataProvider')] public function testUpdate(string $expectedSql, string $table, array $data, array $where): void { // Returned stmt will have rowCount called @@ -226,7 +219,7 @@ public function testUpdate(string $expectedSql, string $table, array $data, arra static::assertSame($rowCount, $actual); } - public function updateDataProvider(): array + public static function updateDataProvider(): array { return [ [ @@ -273,9 +266,7 @@ public function updateDataProvider(): array ]; } - /** - * @dataProvider deleteDataProvider - */ + #[DataProvider('deleteDataProvider')] public function testDelete(string $expectedSql, string $table, array $where): void { // Returned stmt will have rowCount called @@ -298,7 +289,7 @@ public function testDelete(string $expectedSql, string $table, array $where): vo static::assertSame($rowCount, $actual); } - public function deleteDataProvider(): array + public static function deleteDataProvider(): array { return [ [ @@ -327,9 +318,7 @@ public function deleteDataProvider(): array ]; } - /** - * @dataProvider upsertDataProvider - */ + #[DataProvider('upsertDataProvider')] public function testUpsert(string $expectedSql, string $table, array $data, array $updateFields): void { // Returned stmt will have rowCount called @@ -348,7 +337,7 @@ public function testUpsert(string $expectedSql, string $table, array $data, arra static::assertSame(1, $this->crud->upsert($table, $data, $updateFields)); } - public function upsertDataProvider(): array + public static function upsertDataProvider(): array { return [ [ diff --git a/tests/Adapter/QuoteHandlerTest.php b/tests/Adapter/QuoteHandlerTest.php index 8db536d..3d19aec 100644 --- a/tests/Adapter/QuoteHandlerTest.php +++ b/tests/Adapter/QuoteHandlerTest.php @@ -6,6 +6,7 @@ use Phlib\Db\Adapter\QuoteHandler; use Phlib\Db\SqlFragment; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; class QuoteHandlerTest extends TestCase @@ -14,23 +15,19 @@ class QuoteHandlerTest extends TestCase protected function setUp(): void { - $this->handler = new QuoteHandler(function ($value) { + $this->handler = new QuoteHandler(function ($value): string { return "`{$value}`"; }); parent::setUp(); } - /** - * @param mixed $value - * @param mixed $expected - * @dataProvider valueDataProvider - */ - public function testValue($value, $expected): void + #[DataProvider('valueDataProvider')] + public function testValue(mixed $value, string $expected): void { static::assertSame($expected, $this->handler->value($value)); } - public function valueDataProvider(): array + public static function valueDataProvider(): array { $toStringVal = 'foo'; $object = new SqlFragment($toStringVal); @@ -54,16 +51,13 @@ public function valueDataProvider(): array ]; } - /** - * @param mixed $value - * @dataProvider intoDataProvider - */ - public function testInto(string $expected, string $text, $value): void + #[DataProvider('intoDataProvider')] + public function testInto(string $expected, string $text, mixed $value): void { static::assertSame($expected, $this->handler->into($text, $value)); } - public function intoDataProvider(): array + public static function intoDataProvider(): array { return [ ['field = `value`', 'field = ?', 'value'], @@ -76,11 +70,8 @@ public function intoDataProvider(): array ]; } - /** - * @param string|string[] $ident - * @dataProvider columnAsData - */ - public function testColumnAs(string $expected, $ident, string $alias, ?bool $auto): void + #[DataProvider('columnAsData')] + public function testColumnAs(string $expected, string|array $ident, string $alias, ?bool $auto): void { $result = ($auto !== null) ? $this->handler->columnAs($ident, $alias, $auto) : @@ -88,7 +79,7 @@ public function testColumnAs(string $expected, $ident, string $alias, ?bool $aut static::assertSame($expected, $result); } - public function columnAsData(): array + public static function columnAsData(): array { return [ ['`col1` AS `alias`', 'col1', 'alias', null], @@ -98,11 +89,8 @@ public function columnAsData(): array ]; } - /** - * @param string|string[] $ident - * @dataProvider tableAsData - */ - public function testTableAs(string $expected, $ident, string $alias, ?bool $auto): void + #[DataProvider('tableAsData')] + public function testTableAs(string $expected, string|array $ident, string $alias, ?bool $auto): void { $result = ($auto !== null) ? $this->handler->tableAs($ident, $alias, $auto) : @@ -110,7 +98,7 @@ public function testTableAs(string $expected, $ident, string $alias, ?bool $auto static::assertSame($expected, $result); } - public function tableAsData(): array + public static function tableAsData(): array { return [ ['`table1` AS `alias`', 'table1', 'alias', null], @@ -119,11 +107,8 @@ public function tableAsData(): array ]; } - /** - * @param string|string[] $ident - * @dataProvider identifierData - */ - public function testIdentifier(string $expected, $ident, ?bool $auto): void + #[DataProvider('identifierData')] + public function testIdentifier(string $expected, string|array|SqlFragment $ident, ?bool $auto): void { $result = ($auto !== null) ? $this->handler->identifier($ident, $auto) : @@ -131,7 +116,7 @@ public function testIdentifier(string $expected, $ident, ?bool $auto): void static::assertSame($expected, $result); } - public function identifierData(): array + public static function identifierData(): array { return [ ['`col1`', 'col1', null], diff --git a/tests/AdapterTest.php b/tests/AdapterTest.php index 0b91ee3..54ce99b 100644 --- a/tests/AdapterTest.php +++ b/tests/AdapterTest.php @@ -9,6 +9,7 @@ use Phlib\Db\Exception\RuntimeException; use Phlib\Db\Exception\UnknownDatabaseException; use Phlib\Db\Tests\Exception\PDOExceptionStub; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -46,9 +47,6 @@ public function testGetQuoteHandler(): void static::assertInstanceOf(Adapter\QuoteHandler::class, $adapter->quote()); } - /** - * @covers \Phlib\Db\Adapter::setConnection - */ public function testSetConnection(): void { $adapter = new Adapter(); @@ -57,16 +55,13 @@ public function testSetConnection(): void static::assertSame($this->pdo, $adapter->getConnection()); } - /** - * @covers \Phlib\Db\Adapter::setDatabase - */ public function testSetDatabaseMakesDbCall(): void { $dbname = 'MyDbName'; /** @var Adapter|MockObject $adapter */ $adapter = $this->getMockBuilder(Adapter::class) - ->setMethods(['query']) + ->onlyMethods(['query']) ->getMock(); $adapter->expects(static::once()) ->method('query') @@ -76,15 +71,12 @@ public function testSetDatabaseMakesDbCall(): void $adapter->setDatabase($dbname); } - /** - * @covers \Phlib\Db\Adapter::setDatabase - */ public function testSetDatabaseSetsConfig(): void { $dbname = 'MyDbName'; /** @var Adapter|MockObject $adapter */ $adapter = $this->getMockBuilder(Adapter::class) - ->setMethods(['query']) + ->onlyMethods(['query']) ->getMock(); $adapter->setConnection($this->pdo); $adapter->setDatabase($dbname); @@ -102,7 +94,7 @@ public function testSetDatabaseWhenItsUnknown(): void $database = 'foobar'; $exception = new PDOExceptionStub( "SQLSTATE[42000]: Syntax error or access violation: 1049 Unknown database '{$database}'.", - '42000' + '42000', ); $statement = $this->createMock(\PDOStatement::class); $statement->method('execute') @@ -148,9 +140,6 @@ public function testGetConfigMixed(): void static::assertSame($expected, $adapter->getConfig()); } - /** - * @covers \Phlib\Db\Adapter::getConfig - */ public function testGetConfigOverrides(): void { $config = [ @@ -166,11 +155,8 @@ public function testGetConfigOverrides(): void static::assertSame($config, $adapter->getConfig()); } - /** - * @param mixed $value - * @dataProvider settingAdapterOptionsDataProvider - */ - public function testSettingAdapterOptionsWithConnection(string $option, $value): void + #[DataProvider('settingAdapterOptionsDataProvider')] + public function testSettingAdapterOptionsWithConnection(string $option, string $value): void { $statement = $this->createMock(\PDOStatement::class); $statement->expects(static::once()) @@ -185,7 +171,7 @@ public function testSettingAdapterOptionsWithConnection(string $option, $value): $adapter->{$method}($value); } - public function settingAdapterOptionsDataProvider(): array + public static function settingAdapterOptionsDataProvider(): array { return [ ['charset', 'iso-8859-1'], @@ -195,9 +181,6 @@ public function settingAdapterOptionsDataProvider(): array ]; } - /** - * @covers \Phlib\Db\Adapter::ping - */ public function testSuccessfulPing(): void { $pdoStatement = $this->createMock(\PDOStatement::class); @@ -211,9 +194,6 @@ public function testSuccessfulPing(): void static::assertTrue($adapter->ping()); } - /** - * @covers \Phlib\Db\Adapter::ping - */ public function testFailedPing(): void { $this->pdo->method('prepare') @@ -283,7 +263,7 @@ public function testExecute(): void // Exec should call query with the SQL /** @var Adapter|MockObject $adapter */ $adapter = $this->getMockBuilder(Adapter::class) - ->setMethods(['query']) + ->onlyMethods(['query']) ->getMock(); $adapter->expects(static::once()) ->method('query') @@ -310,7 +290,7 @@ public function testExecuteBind(): void // Exec should call query with the SQL /** @var Adapter|MockObject $adapter */ $adapter = $this->getMockBuilder(Adapter::class) - ->setMethods(['query']) + ->onlyMethods(['query']) ->getMock(); $adapter->expects(static::once()) ->method('query') @@ -384,7 +364,7 @@ public function testQueryReconnectsWhenMysqlHasGoneAway(): void $adapter = new Adapter(); $adapter->setConnection($this->pdo); - $adapter->setConnectionFactory(function () { + $adapter->setConnectionFactory(function (): \PDO { $statement = $this->createMock(\PDOStatement::class); $statement->expects(static::once()) ->method('execute'); @@ -409,7 +389,7 @@ public function testQueryFailsAfterSuccessfulReconnect(): void $adapter = new Adapter(); $adapter->setConnection($this->pdo); - $adapter->setConnectionFactory(function () { + $adapter->setConnectionFactory(function (): \PDO { $exception = new PDOExceptionStub('failed for some random reason', 1234); $statement = $this->createMock(\PDOStatement::class); $statement->method('execute') @@ -462,7 +442,7 @@ public function testCloning(): void { $adapter = new Adapter(); $adapter->setConnection($this->pdo); - $adapter->setConnectionFactory(function () { + $adapter->setConnectionFactory(function (): \PDO { return $this->createMock(\PDO::class); }); @@ -491,7 +471,7 @@ public function testBeginTransactionWhenServerHasGoneAway(): void $adapter = new Adapter(); $adapter->setConnection($this->pdo); - $adapter->setConnectionFactory(function () { + $adapter->setConnectionFactory(function (): \PDO { $pdo = $this->createMock(\PDO::class); $pdo->expects(static::once()) ->method('beginTransaction') @@ -513,7 +493,7 @@ public function testBeginTransactionWhenServerHasGoneAwayAndThenFails(): void $adapter = new Adapter(); $adapter->setConnection($this->pdo); - $adapter->setConnectionFactory(function () { + $adapter->setConnectionFactory(function (): \PDO { $exception = new \PDOException('something else bad happened'); $pdo = $this->createMock(\PDO::class); $pdo->method('beginTransaction') diff --git a/tests/Exception/PDOExceptionStub.php b/tests/Exception/PDOExceptionStub.php index 98ab375..6a2b05f 100644 --- a/tests/Exception/PDOExceptionStub.php +++ b/tests/Exception/PDOExceptionStub.php @@ -9,7 +9,7 @@ class PDOExceptionStub extends \PDOException /** * @param int|string $code */ - public function __construct(string $message, $code, \Exception $previous = null) + public function __construct(string $message, $code, ?\Exception $previous = null) { parent::__construct($message, 0, $previous); diff --git a/tests/IntegrationTest.php b/tests/IntegrationTest.php index 9d1b5dd..4db7023 100644 --- a/tests/IntegrationTest.php +++ b/tests/IntegrationTest.php @@ -8,11 +8,11 @@ use Phlib\Db\Exception\InvalidQueryException; use Phlib\Db\Exception\RuntimeException; use Phlib\Db\Exception\UnknownDatabaseException; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; -/** - * @group integration - */ +#[Group('integration')] class IntegrationTest extends TestCase { private array $dbConfig; @@ -99,9 +99,7 @@ public function testInvalidQueryException(): void $this->adapter->query('SELECT foo FROM bar WHERE'); } - /** - * @dataProvider dataSetCharset - */ + #[DataProvider('dataSetCharset')] public function testSetCharset(string $charset): void { $config = $this->dbConfig + [ @@ -117,7 +115,7 @@ public function testSetCharset(string $charset): void self::assertSame($charset, $variables['character_set_results']); } - public function dataSetCharset(): array + public static function dataSetCharset(): array { return [ 'utf8mb4' => ['utf8mb4'], @@ -126,9 +124,7 @@ public function dataSetCharset(): array ]; } - /** - * @dataProvider dataSetTimezone - */ + #[DataProvider('dataSetTimezone')] public function testSetTimezone(string $timezone): void { $config = $this->dbConfig + [ @@ -142,7 +138,7 @@ public function testSetTimezone(string $timezone): void self::assertSame($timezone, $variables['time_zone']); } - public function dataSetTimezone(): array + public static function dataSetTimezone(): array { return [ 'default' => ['+00:00'],