From 507c74d26396b1c7cc13829d88310bbf195bd468 Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Thu, 11 Jun 2020 16:33:46 +0200 Subject: [PATCH 1/8] Removed temporary storage support --- src/Contract/ResultInterface.php | 8 +- src/Model/Adapter/Mysqli/Result.php | 158 ++++------------- src/Model/Adapter/PDO/Result.php | 180 ++++---------------- tests/src/Adapter/Mysqli/ReadResultTest.php | 77 +++------ tests/src/Adapter/PDO/PDOStatementTest.php | 4 +- tests/src/Adapter/PDO/ReadResultTest.php | 75 +++----- 6 files changed, 117 insertions(+), 385 deletions(-) diff --git a/src/Contract/ResultInterface.php b/src/Contract/ResultInterface.php index 88d8628..565e99d 100644 --- a/src/Contract/ResultInterface.php +++ b/src/Contract/ResultInterface.php @@ -37,6 +37,7 @@ public function asValue(); /** * Return the ID of the last inserted row or sequence value. + * * @return mixed|null */ public function getLastInsertId(); @@ -46,10 +47,5 @@ public function getLastInsertId(); * * @return int */ - public function count(); - - /** - * @return ResultInterface - */ - public function withoutStorage(): ResultInterface; + public function count(): int; } diff --git a/src/Model/Adapter/Mysqli/Result.php b/src/Model/Adapter/Mysqli/Result.php index c855362..4a83939 100644 --- a/src/Model/Adapter/Mysqli/Result.php +++ b/src/Model/Adapter/Mysqli/Result.php @@ -26,17 +26,12 @@ class Result implements IteratorAggregate, ResultInterface */ private $result; - private $storage = []; - - /** - * @var bool - */ - private $storageEnabled = true; + private $frozen = false; /** * Result constructor. - * @param mysqli $mysqli - * @param mysqli_stmt $stmt + * @param mysqli $mysqli + * @param mysqli_stmt $stmt * @param mysqli_result $result */ public function __construct(mysqli $mysqli, mysqli_result $result = null, mysqli_stmt $stmt = null) @@ -57,7 +52,7 @@ public function getLastInsertId() /** * @inheritDoc */ - public function count() + public function count(): int { return null === $this->result ? $this->mysqli->affected_rows : $this->result->num_rows; } @@ -70,20 +65,10 @@ public function asArray(): array if (null === $this->result) { throw new DBALException("No mysqli_result object provided."); } - if (empty($this->storage['array'])) { - if ($this->shouldResetResultset()) { - $this->resetResultset(); - } - $result = $this->result->fetch_all(MYSQLI_ASSOC); + $this->freeze(); - if (true === $this->storageEnabled) { - $this->storage['array'] = $result; - } - - return $result; - } - return $this->storage['array']; + return $this->result->fetch_all(MYSQLI_ASSOC); } /** @@ -94,24 +79,10 @@ public function asRow(): ?array if (null === $this->result) { throw new DBALException("No mysqli_result object provided."); } - if (empty($this->storage['row'])) { - if (isset($this->storage['array'][0])) { - $this->storage['row'] = &$this->storage['array'][0]; - } else { - if ($this->shouldResetResultset()) { - $this->resetResultset(); - } - $result = $this->result->fetch_array(MYSQLI_ASSOC) ?: null; + $this->freeze(); - if (true === $this->storageEnabled) { - $this->storage['row'] = $result; - } - - return $result; - } - } - return $this->storage['row']; + return $this->result->fetch_array(MYSQLI_ASSOC) ?: null; } /** @@ -122,29 +93,16 @@ public function asList(): array if (null === $this->result) { throw new DBALException("No mysqli_result object provided."); } - if (empty($this->storage['list'])) { - if (!empty($this->storage['array'])) { - $this->storage['list'] = array_column($this->storage['array'], array_keys($this->storage['array'][0])[0]); - } else { - if ($this->shouldResetResultset()) { - $this->resetResultset(); - } - - $generator = function (\mysqli_result $result) { - while ($row = $result->fetch_array(MYSQLI_NUM)) { - yield $row[0]; - } - }; - $result = iterator_to_array($generator($this->result)); - - if (true === $this->storageEnabled) { - $this->storage['list'] = $result; - } - - return $result; + + $this->freeze(); + + $generator = function (mysqli_result $result) { + while ($row = $result->fetch_array(MYSQLI_NUM)) { + yield $row[0]; } - } - return $this->storage['list']; + }; + + return iterator_to_array($generator($this->result)); } /** @@ -155,29 +113,12 @@ public function asValue() if (null === $this->result) { throw new DBALException("No mysqli_result object provided."); } - if (empty($this->storage['value'])) { - if (!empty($this->storage['list'][0])) { - $this->storage['value'] = $this->storage['list'][0]; - } elseif (!empty($this->storage['row'])) { - $this->storage['value'] = array_values($this->storage['row'])[0]; - } elseif (!empty($this->storage['array'])) { - $this->storage['value'] = array_values($this->storage['array'][0])[0]; - } else { - if ($this->shouldResetResultset()) { - $this->resetResultset(); - } - - $row = $this->result->fetch_array(MYSQLI_NUM); - $result = $row ? $row[0] : null; - - if (true === $this->storageEnabled) { - $this->storage['value'] = $result; - } - - return $result; - } - } - return $this->storage['value']; + + $this->freeze(); + + $row = $this->result->fetch_array(MYSQLI_NUM); + + return $row ? $row[0] : null; } /** @@ -188,57 +129,20 @@ public function getIterator() if (null === $this->result) { throw new DBALException("No mysqli_result object provided."); } - if (!empty($this->storage['array'])) { - foreach ($this->storage['array'] as $key => $value) { - yield $key => $value; - } - } else { - if ($this->shouldResetResultset()) { - $this->resetResultset(); - } - - while ($row = $this->result->fetch_array(MYSQLI_ASSOC)) { - if (empty($this->storage['yield'])) { - $this->storage['yield'] = true; - } - yield $row; - } - } - } + $this->freeze(); - /** - * If asRow(), asList() or asValue() was called earlier, the iterator may be incomplete. - * In such case we need to rewind the iterator by executing the statement a second time. - * You should avoid to call getIterator() and asRow(), etc. with the same resultset. - * - * @return bool - */ - private function shouldResetResultset(): bool - { - return !empty($this->storage['row']) || !empty($this->storage['value']) || !empty($this->storage['list']) || !empty($this->storage['yield']); + while ($row = $this->result->fetch_array(MYSQLI_ASSOC)) { + yield $row; + } } - - /** - * Reset the resultset. - */ - private function resetResultset() + private function freeze(): void { - if (null !== $this->stmt) { - $this->stmt->execute(); - $this->result = $this->stmt->get_result(); + if (true === $this->frozen) { + throw new DBALException("This result is frozen. You have to re-execute this statement."); } - } - /** - * @return ResultInterface - */ - public function withoutStorage(): ResultInterface - { - $clone = clone $this; - $clone->storage = []; - $clone->storageEnabled = false; - return $clone; + $this->frozen = true; } } diff --git a/src/Model/Adapter/PDO/Result.php b/src/Model/Adapter/PDO/Result.php index 9b76f22..6b86f44 100644 --- a/src/Model/Adapter/PDO/Result.php +++ b/src/Model/Adapter/PDO/Result.php @@ -10,32 +10,11 @@ class Result implements IteratorAggregate, ResultInterface { - /** - * @var PDO - */ private $pdo; - - /** - * @var Statement - */ private $stmt; + private $frozen = false; - /** - * @var array - */ - private $storage = []; - - /** - * @var bool - */ - private $storageEnabled = true; - - /** - * Result constructor. - * @param PDO $pdo - * @param Statement $stmt - */ - public function __construct(PDO $pdo, PDOStatement $stmt = null) + public function __construct(PDO $pdo = null, PDOStatement $stmt = null) { $this->pdo = $pdo; $this->stmt = $stmt; @@ -52,8 +31,12 @@ public function getLastInsertId() /** * @inheritDoc */ - public function count() + public function count(): int { + if (null === $this->stmt) { + throw new DBALException("No \PDOStatement object provided."); + } + return $this->stmt->rowCount(); } @@ -65,23 +48,10 @@ public function asArray(): array if (null === $this->stmt) { throw new DBALException("No \PDOStatement object provided."); } - if (!empty($this->storage['row']) || !empty($this->storage['value']) || !empty($this->storage['list']) || !empty($this->storage['yield'])) { - $this->stmt->execute(); - } - if (empty($this->storage['array'])) { - if ($this->shouldResetResultset()) { - $this->resetResultset(); - } - $result = $this->stmt->fetchAll(PDO::FETCH_ASSOC); + $this->freeze(); - if (true === $this->storageEnabled) { - $this->storage['array'] = $result; - } - - return $result; - } - return $this->storage['array']; + return $this->stmt->fetchAll(PDO::FETCH_ASSOC); } /** @@ -92,23 +62,10 @@ public function asRow(): ?array if (null === $this->stmt) { throw new DBALException("No \PDOStatement object provided."); } - if (empty($this->storage['row'])) { - if (isset($this->storage['array'][0])) { - $this->storage['row'] = &$this->storage['array'][0]; - } else { - if ($this->shouldResetResultset()) { - $this->resetResultset(); - } - - $result = $this->stmt->fetch(PDO::FETCH_ASSOC) ?: null; - - if (true === $this->storageEnabled) { - $this->storage['row'] = $result; - } - return $result; - } - } - return $this->storage['row']; + + $this->freeze(); + + return $this->stmt->fetch(PDO::FETCH_ASSOC) ?: null; } /** @@ -119,30 +76,16 @@ public function asList(): array if (null === $this->stmt) { throw new DBALException("No \PDOStatement object provided."); } - if (empty($this->storage['list'])) { - if (!empty($this->storage['array'])) { - $this->storage['list'] = array_column($this->storage['array'], array_keys($this->storage['array'][0])[0]); - } else { - if ($this->shouldResetResultset()) { - $this->resetResultset(); - } - - $generator = function (\PDOStatement $stmt) { - while ($value = $stmt->fetchColumn(0)) { - yield $value; - } - }; - - $result = iterator_to_array($generator($this->stmt)); - - if (true === $this->storageEnabled) { - $this->storage['list'] = $result; - } - - return $result; + + $this->freeze(); + + $generator = static function (PDOStatement $stmt) { + while ($value = $stmt->fetchColumn(0)) { + yield $value; } - } - return $this->storage['list']; + }; + + return iterator_to_array($generator($this->stmt)); } /** @@ -153,30 +96,11 @@ public function asValue() if (null === $this->stmt) { throw new DBALException("No \PDOStatement object provided."); } - if (empty($this->storage['value'])) { - if (!empty($this->storage['list'][0])) { - $this->storage['value'] = $this->storage['list'][0]; - } elseif (!empty($this->storage['row'])) { - $this->storage['value'] = array_values($this->storage['row'])[0]; - } elseif (!empty($this->storage['array'])) { - $this->storage['value'] = array_values($this->storage['array'][0])[0]; - } else { - if ($this->shouldResetResultset()) { - $this->resetResultset(); - } - - $result = $this->stmt->fetchColumn(0) ?: null; - - if (true === $this->storageEnabled) { - $this->storage['value'] = $result; - } - - return $result; - } - } - return $this->storage['value']; - } + $this->freeze(); + + return $this->stmt->fetchColumn(0) ?: null; + } /** * @inheritDoc @@ -187,55 +111,19 @@ public function getIterator() throw new DBALException("No \PDOStatement object provided."); } - // If asArray() was called earlier, iterate over the stored resultset. - if (!empty($this->storage['array'])) { - foreach ($this->storage['array'] as $key => $value) { - yield $key => $value; - } - } else { - $wrappedStmt = $this->stmt; - - if ($this->shouldResetResultset()) { - $this->resetResultset(); - } + $this->freeze(); - while ($row = $wrappedStmt->fetch(PDO::FETCH_ASSOC)) { - if (empty($this->storage['yield'])) { - $this->storage['yield'] = true; - } - yield $row; - } + while ($row = $this->stmt->fetch(PDO::FETCH_ASSOC)) { + yield $row; } } - /** - * If asRow(), asList() or asValue() was called earlier, the iterator may be incomplete. - * In such case we need to rewind the iterator by executing the statement a second time. - * You should avoid to call getIterator() and asRow(), etc. with the same resultset. - * - * @return bool - */ - private function shouldResetResultset(): bool - { - return !empty($this->storage['row']) || !empty($this->storage['value']) || !empty($this->storage['list']) || !empty($this->storage['yield']); - } - - /** - * Reset the resultset. - */ - private function resetResultset() + private function freeze(): void { - $this->stmt->execute(); - } + if (true === $this->frozen) { + throw new DBALException("This result is frozen. You have to re-execute this statement."); + } - /** - * @return ResultInterface - */ - public function withoutStorage(): ResultInterface - { - $clone = clone $this; - $clone->storage = []; - $clone->storageEnabled = false; - return $clone; + $this->frozen = true; } } diff --git a/tests/src/Adapter/Mysqli/ReadResultTest.php b/tests/src/Adapter/Mysqli/ReadResultTest.php index 9f2bf67..68f1138 100644 --- a/tests/src/Adapter/Mysqli/ReadResultTest.php +++ b/tests/src/Adapter/Mysqli/ReadResultTest.php @@ -3,10 +3,10 @@ namespace BenTools\SimpleDBAL\Tests\Adapter\Mysqli; use BenTools\SimpleDBAL\Model\Adapter\Mysqli\Result; +use BenTools\SimpleDBAL\Model\Exception\DBALException; class ReadResultTest extends MysqliTestCase { - protected $sampleData = [ [ 'id' => null, @@ -48,27 +48,16 @@ public function testIterator() $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); $this->assertEquals($this->expectedResult, iterator_to_array($result)); - $this->assertEquals($this->expectedResult, iterator_to_array($result)); } - public function testArrayAfterIterator() + public function testIteratorYellsWhenCalledTwice() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); + $this->expectException(DBALException::class); + $this->expectExceptionMessage('This result is frozen. You have to re-execute this statement.'); + iterator_to_array($result); iterator_to_array($result); - $this->assertEquals($this->expectedResult, $result->asArray()); - $this->assertEquals($this->expectedResult, $result->asArray()); - } - - public function testArrayAfterIncompleteIterator() - { - $this->insertSampleData($this->sampleData); - $result = $this->fetchResult(); - foreach ($result as $item) { - break; - } - $this->assertEquals($this->expectedResult, $result->asArray()); - $this->assertEquals($this->expectedResult, $result->asArray()); } public function testArray() @@ -76,16 +65,16 @@ public function testArray() $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); $this->assertEquals($this->expectedResult, $result->asArray()); - $this->assertEquals($this->expectedResult, $result->asArray()); } - public function testIteratorAfterArray() + public function testArrayYellsWhenCalledTwice() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); + $this->expectException(DBALException::class); + $this->expectExceptionMessage('This result is frozen. You have to re-execute this statement.'); + $result->asArray(); $result->asArray(); - $this->assertEquals($this->expectedResult, iterator_to_array($result)); - $this->assertEquals($this->expectedResult, iterator_to_array($result)); } public function testRow() @@ -93,16 +82,16 @@ public function testRow() $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); $this->assertEquals($this->expectedResult[0], $result->asRow()); - $this->assertEquals($this->expectedResult[0], $result->asRow()); } - public function testRowAfterArray() + public function testRowYellsWhenCalledTwice() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); - $result->asArray(); - $this->assertEquals($this->expectedResult[0], $result->asRow()); - $this->assertEquals($this->expectedResult[0], $result->asRow()); + $this->expectException(DBALException::class); + $this->expectExceptionMessage('This result is frozen. You have to re-execute this statement.'); + $result->asRow(); + $result->asRow(); } public function testList() @@ -110,50 +99,32 @@ public function testList() $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); $this->assertEquals(array_column($this->expectedResult, 'id'), $result->asList()); - $this->assertEquals(array_column($this->expectedResult, 'id'), $result->asList()); - } - - public function testListAfterArray() - { - $this->insertSampleData($this->sampleData); - $result = $this->fetchResult(); - $result->asArray(); - $this->assertEquals(array_column($this->expectedResult, 'id'), $result->asList()); - $this->assertEquals(array_column($this->expectedResult, 'id'), $result->asList()); - } - - public function testValue() - { - $this->insertSampleData($this->sampleData); - $result = $this->fetchResult(); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); } - public function testValueAfterList() + public function testListYellsWhenCalledTwice() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); + $this->expectException(DBALException::class); + $this->expectExceptionMessage('This result is frozen. You have to re-execute this statement.'); + $result->asList(); $result->asList(); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); } - public function testValueAfterRow() + public function testValue() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); - $result->asRow(); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); } - public function testValueAfterArray() + public function testValueYellsWhenCalledTwice() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); - $result->asArray(); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); + $this->expectException(DBALException::class); + $this->expectExceptionMessage('This result is frozen. You have to re-execute this statement.'); + $result->asValue(); + $result->asValue(); } } diff --git a/tests/src/Adapter/PDO/PDOStatementTest.php b/tests/src/Adapter/PDO/PDOStatementTest.php index 3c92992..5b854de 100644 --- a/tests/src/Adapter/PDO/PDOStatementTest.php +++ b/tests/src/Adapter/PDO/PDOStatementTest.php @@ -66,7 +66,7 @@ public function testPreparedStmtWithNamedParameters() } /** - * @expectedException \BenTools\SimpleDBAL\Model\Exception\ParamBindingException + * @expectedException \BenTools\SimpleDBAL\Model\Exception\DBALException */ public function testPreparedStmtWithNamedParametersNotProvided() { @@ -106,7 +106,7 @@ public function testPreparedStmtWithIncrementalParameters() } /** - * @expectedException \BenTools\SimpleDBAL\Model\Exception\ParamBindingException + * @expectedException \BenTools\SimpleDBAL\Model\Exception\DBALException */ public function testPreparedStmtWithIncrementalParametersNotProvided() { diff --git a/tests/src/Adapter/PDO/ReadResultTest.php b/tests/src/Adapter/PDO/ReadResultTest.php index b73a4f6..aee6c36 100644 --- a/tests/src/Adapter/PDO/ReadResultTest.php +++ b/tests/src/Adapter/PDO/ReadResultTest.php @@ -3,6 +3,7 @@ namespace BenTools\SimpleDBAL\Tests\Adapter\PDO; use BenTools\SimpleDBAL\Model\Adapter\PDO\Result; +use BenTools\SimpleDBAL\Model\Exception\DBALException; use PHPUnit\Framework\TestCase; class ReadResultTest extends PDOTestCase @@ -49,27 +50,16 @@ public function testIterator() $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); $this->assertEquals($this->expectedResult, iterator_to_array($result)); - $this->assertEquals($this->expectedResult, iterator_to_array($result)); } - public function testArrayAfterIterator() + public function testIteratorYellsWhenCalledTwice() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); + $this->expectException(DBALException::class); + $this->expectExceptionMessage('This result is frozen. You have to re-execute this statement.'); + iterator_to_array($result); iterator_to_array($result); - $this->assertEquals($this->expectedResult, $result->asArray()); - $this->assertEquals($this->expectedResult, $result->asArray()); - } - - public function testArrayAfterIncompleteIterator() - { - $this->insertSampleData($this->sampleData); - $result = $this->fetchResult(); - foreach ($result as $item) { - break; - } - $this->assertEquals($this->expectedResult, $result->asArray()); - $this->assertEquals($this->expectedResult, $result->asArray()); } public function testArray() @@ -77,16 +67,16 @@ public function testArray() $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); $this->assertEquals($this->expectedResult, $result->asArray()); - $this->assertEquals($this->expectedResult, $result->asArray()); } - public function testIteratorAfterArray() + public function testArrayYellsWhenCalledTwice() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); + $this->expectException(DBALException::class); + $this->expectExceptionMessage('This result is frozen. You have to re-execute this statement.'); + $result->asArray(); $result->asArray(); - $this->assertEquals($this->expectedResult, iterator_to_array($result)); - $this->assertEquals($this->expectedResult, iterator_to_array($result)); } public function testRow() @@ -94,16 +84,16 @@ public function testRow() $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); $this->assertEquals($this->expectedResult[0], $result->asRow()); - $this->assertEquals($this->expectedResult[0], $result->asRow()); } - public function testRowAfterArray() + public function testRowYellsWhenCalledTwice() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); - $result->asArray(); - $this->assertEquals($this->expectedResult[0], $result->asRow()); - $this->assertEquals($this->expectedResult[0], $result->asRow()); + $this->expectException(DBALException::class); + $this->expectExceptionMessage('This result is frozen. You have to re-execute this statement.'); + $result->asRow(); + $result->asRow(); } public function testList() @@ -111,16 +101,16 @@ public function testList() $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); $this->assertEquals(array_column($this->expectedResult, 'id'), $result->asList()); - $this->assertEquals(array_column($this->expectedResult, 'id'), $result->asList()); } - public function testListAfterArray() + public function testListYellsWhenCalledTwice() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); - $result->asArray(); - $this->assertEquals(array_column($this->expectedResult, 'id'), $result->asList()); - $this->assertEquals(array_column($this->expectedResult, 'id'), $result->asList()); + $this->expectException(DBALException::class); + $this->expectExceptionMessage('This result is frozen. You have to re-execute this statement.'); + $result->asList(); + $result->asList(); } public function testValue() @@ -128,33 +118,16 @@ public function testValue() $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); } - public function testValueAfterList() + public function testValueYellsWhenCalledTwice() { $this->insertSampleData($this->sampleData); $result = $this->fetchResult(); - $result->asList(); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); + $this->expectException(DBALException::class); + $this->expectExceptionMessage('This result is frozen. You have to re-execute this statement.'); + $result->asValue(); + $result->asValue(); } - public function testValueAfterRow() - { - $this->insertSampleData($this->sampleData); - $result = $this->fetchResult(); - $result->asRow(); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); - } - - public function testValueAfterArray() - { - $this->insertSampleData($this->sampleData); - $result = $this->fetchResult(); - $result->asArray(); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); - $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); - } } From 18d29a8c8449f3b67865cd089e48b3cf45ea3d03 Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Fri, 12 Jun 2020 15:52:42 +0200 Subject: [PATCH 2/8] Add factories --- src/Model/Adapter/Mysqli/Result.php | 29 +++++++++++++------- src/Model/Adapter/Mysqli/Statement.php | 2 +- src/Model/Adapter/PDO/Result.php | 17 +++++++++++- tests/src/Adapter/Mysqli/ReadResultTest.php | 10 +++++++ tests/src/Adapter/Mysqli/WriteResultTest.php | 11 ++++++++ tests/src/Adapter/PDO/ReadResultTest.php | 10 +++++++ tests/src/Adapter/PDO/WriteResultTest.php | 11 ++++++++ 7 files changed, 78 insertions(+), 12 deletions(-) diff --git a/src/Model/Adapter/Mysqli/Result.php b/src/Model/Adapter/Mysqli/Result.php index 4a83939..5a465ec 100644 --- a/src/Model/Adapter/Mysqli/Result.php +++ b/src/Model/Adapter/Mysqli/Result.php @@ -9,20 +9,15 @@ use mysqli_result; use mysqli_stmt; -class Result implements IteratorAggregate, ResultInterface +final class Result implements IteratorAggregate, ResultInterface { /** - * @var mysqli + * @var mysqli|null */ private $mysqli; /** - * @var mysqli_stmt - */ - private $stmt; - - /** - * @var mysqli_result + * @var mysqli_result|null */ private $result; @@ -34,10 +29,9 @@ class Result implements IteratorAggregate, ResultInterface * @param mysqli_stmt $stmt * @param mysqli_result $result */ - public function __construct(mysqli $mysqli, mysqli_result $result = null, mysqli_stmt $stmt = null) + public function __construct(mysqli $mysqli = null, mysqli_result $result = null) { $this->mysqli = $mysqli; - $this->stmt = $stmt; $this->result = $result; } @@ -145,4 +139,19 @@ private function freeze(): void $this->frozen = true; } + + public static function from(...$arguments): self + { + $instance = new self; + foreach ($arguments as $argument) { + if ($argument instanceof mysqli) { + $instance->mysqli = $argument; + } + if ($argument instanceof mysqli_result) { + $instance->result = $argument; + } + } + + return $instance; + } } diff --git a/src/Model/Adapter/Mysqli/Statement.php b/src/Model/Adapter/Mysqli/Statement.php index d5c9ce5..35e34f8 100644 --- a/src/Model/Adapter/Mysqli/Statement.php +++ b/src/Model/Adapter/Mysqli/Statement.php @@ -242,7 +242,7 @@ public function createResult(): ResultInterface $this->getWrappedStatement()->execute(); $result = $this->getWrappedStatement()->get_result(); $mysqli = $this->getConnection()->getWrappedConnection(); - return !$result instanceof mysqli_result ? new Result($mysqli) : new Result($mysqli, $result, $this->getWrappedStatement()); + return !$result instanceof mysqli_result ? new Result($mysqli) : new Result($mysqli, $result); } /** diff --git a/src/Model/Adapter/PDO/Result.php b/src/Model/Adapter/PDO/Result.php index 6b86f44..304af53 100644 --- a/src/Model/Adapter/PDO/Result.php +++ b/src/Model/Adapter/PDO/Result.php @@ -8,7 +8,7 @@ use PDO; use PDOStatement; -class Result implements IteratorAggregate, ResultInterface +final class Result implements IteratorAggregate, ResultInterface { private $pdo; private $stmt; @@ -126,4 +126,19 @@ private function freeze(): void $this->frozen = true; } + + public static function from(...$arguments): self + { + $instance = new self; + foreach ($arguments as $argument) { + if ($argument instanceof PDO) { + $instance->pdo = $argument; + } + if ($argument instanceof PDOStatement) { + $instance->stmt = $argument; + } + } + + return $instance; + } } diff --git a/tests/src/Adapter/Mysqli/ReadResultTest.php b/tests/src/Adapter/Mysqli/ReadResultTest.php index 68f1138..6d898ce 100644 --- a/tests/src/Adapter/Mysqli/ReadResultTest.php +++ b/tests/src/Adapter/Mysqli/ReadResultTest.php @@ -127,4 +127,14 @@ public function testValueYellsWhenCalledTwice() $result->asValue(); $result->asValue(); } + + public function testInstanciateFromExistingResultset() + { + $this->insertSampleData($this->sampleData); + /** @var \mysqli $link */ + $link = self::$cnx->getWrappedConnection(); + $rows = \mysqli_query($link, sprintf("SELECT * FROM `%s` ORDER BY id", self::$tableName)); + $result = Result::from($rows); + $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); + } } diff --git a/tests/src/Adapter/Mysqli/WriteResultTest.php b/tests/src/Adapter/Mysqli/WriteResultTest.php index 901b0b8..c37e775 100644 --- a/tests/src/Adapter/Mysqli/WriteResultTest.php +++ b/tests/src/Adapter/Mysqli/WriteResultTest.php @@ -2,6 +2,8 @@ namespace BenTools\SimpleDBAL\Tests\Adapter\Mysqli; +use BenTools\SimpleDBAL\Model\Adapter\Mysqli\Result; + class WriteResultTest extends ReadResultTest { @@ -34,4 +36,13 @@ public function testLastInsertId() ]); $this->assertEquals(2, $result->getLastInsertId()); } + + public function testInstanciateFromExistingLink() + { + $this->insertSampleData($this->sampleData); + /** @var \mysqli $link */ + $link = self::$cnx->getWrappedConnection(); + $result = Result::from($link); + $this->assertGreaterThan(0, $result->getLastInsertId()); + } } diff --git a/tests/src/Adapter/PDO/ReadResultTest.php b/tests/src/Adapter/PDO/ReadResultTest.php index aee6c36..f154b2f 100644 --- a/tests/src/Adapter/PDO/ReadResultTest.php +++ b/tests/src/Adapter/PDO/ReadResultTest.php @@ -130,4 +130,14 @@ public function testValueYellsWhenCalledTwice() $result->asValue(); } + public function testInstanciateFromExistingResultset() + { + $this->insertSampleData($this->sampleData); + /** @var \PDO $link */ + $link = self::$cnx->getWrappedConnection(); + $rows = $link->query(sprintf("SELECT * FROM `%s` ORDER BY id", self::$tableName)); + $result = Result::from($rows); + $this->assertEquals($this->expectedResult[0]['id'], $result->asValue()); + } + } diff --git a/tests/src/Adapter/PDO/WriteResultTest.php b/tests/src/Adapter/PDO/WriteResultTest.php index 5da08b4..d7b10ee 100644 --- a/tests/src/Adapter/PDO/WriteResultTest.php +++ b/tests/src/Adapter/PDO/WriteResultTest.php @@ -2,6 +2,8 @@ namespace BenTools\SimpleDBAL\Tests\Adapter\PDO; +use BenTools\SimpleDBAL\Model\Adapter\PDO\Result; + class WriteResultTest extends ReadResultTest { @@ -36,4 +38,13 @@ public function testLastInsertId() ]); $this->assertEquals(2, $result->getLastInsertId()); } + + public function testInstanciateFromExistingLink() + { + $this->insertSampleData($this->sampleData); + /** @var \PDO $link */ + $link = self::$cnx->getWrappedConnection(); + $result = Result::from($link); + $this->assertGreaterThan(0, $result->getLastInsertId()); + } } From 4d008556141706e6cd04c9ef47cd37cc2a8dabde Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Fri, 12 Jun 2020 15:55:58 +0200 Subject: [PATCH 3/8] Cleanup --- src/Model/Adapter/Mysqli/Result.php | 40 ++++++++++++++++++++--------- src/Model/Adapter/PDO/Result.php | 4 +++ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/Model/Adapter/Mysqli/Result.php b/src/Model/Adapter/Mysqli/Result.php index 5a465ec..5e56fd5 100644 --- a/src/Model/Adapter/Mysqli/Result.php +++ b/src/Model/Adapter/Mysqli/Result.php @@ -23,12 +23,6 @@ final class Result implements IteratorAggregate, ResultInterface private $frozen = false; - /** - * Result constructor. - * @param mysqli $mysqli - * @param mysqli_stmt $stmt - * @param mysqli_result $result - */ public function __construct(mysqli $mysqli = null, mysqli_result $result = null) { $this->mysqli = $mysqli; @@ -40,6 +34,10 @@ public function __construct(mysqli $mysqli = null, mysqli_result $result = null) */ public function getLastInsertId() { + if (null === $this->mysqli) { + throw new DBALException("No \mysqli object provided."); + } + return $this->mysqli->insert_id; } @@ -48,7 +46,7 @@ public function getLastInsertId() */ public function count(): int { - return null === $this->result ? $this->mysqli->affected_rows : $this->result->num_rows; + return null === $this->result ? $this->getAffectedRows() : $this->getNumRows(); } /** @@ -57,7 +55,7 @@ public function count(): int public function asArray(): array { if (null === $this->result) { - throw new DBALException("No mysqli_result object provided."); + throw new DBALException("No \mysqli_result object provided."); } $this->freeze(); @@ -71,7 +69,7 @@ public function asArray(): array public function asRow(): ?array { if (null === $this->result) { - throw new DBALException("No mysqli_result object provided."); + throw new DBALException("No \mysqli_result object provided."); } $this->freeze(); @@ -85,7 +83,7 @@ public function asRow(): ?array public function asList(): array { if (null === $this->result) { - throw new DBALException("No mysqli_result object provided."); + throw new DBALException("No \mysqli_result object provided."); } $this->freeze(); @@ -105,7 +103,7 @@ public function asList(): array public function asValue() { if (null === $this->result) { - throw new DBALException("No mysqli_result object provided."); + throw new DBALException("No \mysqli_result object provided."); } $this->freeze(); @@ -121,7 +119,7 @@ public function asValue() public function getIterator() { if (null === $this->result) { - throw new DBALException("No mysqli_result object provided."); + throw new DBALException("No \mysqli_result object provided."); } $this->freeze(); @@ -140,6 +138,24 @@ private function freeze(): void $this->frozen = true; } + private function getAffectedRows() + { + if (null === $this->mysqli) { + throw new DBALException("No \mysqli object provided."); + } + + return $this->mysqli->affected_rows; + } + + private function getNumRows() + { + if (null === $this->result) { + throw new DBALException("No \mysqli_result object provided."); + } + + return $this->result->num_rows; + } + public static function from(...$arguments): self { $instance = new self; diff --git a/src/Model/Adapter/PDO/Result.php b/src/Model/Adapter/PDO/Result.php index 304af53..6aee90e 100644 --- a/src/Model/Adapter/PDO/Result.php +++ b/src/Model/Adapter/PDO/Result.php @@ -25,6 +25,10 @@ public function __construct(PDO $pdo = null, PDOStatement $stmt = null) */ public function getLastInsertId() { + if (null === $this->pdo) { + throw new DBALException("No \PDO object provided."); + } + return $this->pdo->lastInsertId(); } From 34f04d0955d19bcec51925989f10fd43c702fa8f Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Sun, 19 Jul 2020 09:27:17 +0200 Subject: [PATCH 4/8] fix: enforce strict comparisons --- src/Model/Adapter/Mysqli/Result.php | 8 ++++---- src/Model/Adapter/PDO/Result.php | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Model/Adapter/Mysqli/Result.php b/src/Model/Adapter/Mysqli/Result.php index 5e56fd5..f062032 100644 --- a/src/Model/Adapter/Mysqli/Result.php +++ b/src/Model/Adapter/Mysqli/Result.php @@ -89,7 +89,7 @@ public function asList(): array $this->freeze(); $generator = function (mysqli_result $result) { - while ($row = $result->fetch_array(MYSQLI_NUM)) { + while (null !== ($row = $result->fetch_array(MYSQLI_NUM))) { yield $row[0]; } }; @@ -110,7 +110,7 @@ public function asValue() $row = $this->result->fetch_array(MYSQLI_NUM); - return $row ? $row[0] : null; + return $row[0] ?? null; } /** @@ -138,7 +138,7 @@ private function freeze(): void $this->frozen = true; } - private function getAffectedRows() + private function getAffectedRows(): ?int { if (null === $this->mysqli) { throw new DBALException("No \mysqli object provided."); @@ -147,7 +147,7 @@ private function getAffectedRows() return $this->mysqli->affected_rows; } - private function getNumRows() + private function getNumRows(): ?int { if (null === $this->result) { throw new DBALException("No \mysqli_result object provided."); diff --git a/src/Model/Adapter/PDO/Result.php b/src/Model/Adapter/PDO/Result.php index 6aee90e..70d8ebd 100644 --- a/src/Model/Adapter/PDO/Result.php +++ b/src/Model/Adapter/PDO/Result.php @@ -84,7 +84,7 @@ public function asList(): array $this->freeze(); $generator = static function (PDOStatement $stmt) { - while ($value = $stmt->fetchColumn(0)) { + while (false !== ($value = $stmt->fetchColumn(0))) { yield $value; } }; @@ -103,7 +103,9 @@ public function asValue() $this->freeze(); - return $this->stmt->fetchColumn(0) ?: null; + $value = $this->stmt->fetchColumn(0); + + return false !== $value ? $value : null; } /** From 2a1f132087c3aeb323ffcb7afa2dd159aa6661bd Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Sun, 19 Jul 2020 10:00:20 +0200 Subject: [PATCH 5/8] style: fix static analysis --- composer.json | 8 +- phpcs.xml.dist | 15 +++ src/Contract/ConnectionInterface.php | 2 +- src/Model/Adapter/Mysqli/MysqliAdapter.php | 119 +++++++++++++-------- src/Model/Adapter/Mysqli/Result.php | 4 +- src/Model/Adapter/Mysqli/Statement.php | 6 +- src/Model/Adapter/PDO/PDOAdapter.php | 17 ++- src/Model/Adapter/PDO/Statement.php | 8 +- src/Model/ConfigurableTrait.php | 21 +--- src/Model/Credentials.php | 2 +- src/Model/SimpleDBAL.php | 5 +- 11 files changed, 118 insertions(+), 89 deletions(-) create mode 100644 phpcs.xml.dist diff --git a/composer.json b/composer.json index 0ec76ad..965a548 100644 --- a/composer.json +++ b/composer.json @@ -12,13 +12,15 @@ "guzzlehttp/promises": "^1.3" }, "require-dev": { - "phpunit/phpunit": "^6.0", "squizlabs/php_codesniffer": "~2.0", - "satooshi/php-coveralls": "^1.0", "symfony/var-dumper": "^3.2", "bentools/iterable-functions": "^1.1", "incenteev/composer-parameter-handler": "^2.1", - "symfony/yaml": "^3.2" + "symfony/yaml": "^3.2", + "phpstan/phpstan": "^0.12.32", + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^7.0", + "friendsofphp/php-cs-fixer": "^2.16" }, "autoload-dev": { "psr-4": { diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..c69b39d --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,15 @@ + + + + + + + + + + + + src/ + + diff --git a/src/Contract/ConnectionInterface.php b/src/Contract/ConnectionInterface.php index 816cde7..61cba4f 100644 --- a/src/Contract/ConnectionInterface.php +++ b/src/Contract/ConnectionInterface.php @@ -27,7 +27,7 @@ public function execute($stmt, array $values = null): ResultInterface; * Executes a read statement asynchronously. * The promise MUST return a Result object. * - * @param $stmt + * @param mixed $stmt * @param array|null $values * @return PromiseInterface */ diff --git a/src/Model/Adapter/Mysqli/MysqliAdapter.php b/src/Model/Adapter/Mysqli/MysqliAdapter.php index 9c620e8..b5fea81 100644 --- a/src/Model/Adapter/Mysqli/MysqliAdapter.php +++ b/src/Model/Adapter/Mysqli/MysqliAdapter.php @@ -20,14 +20,14 @@ use mysqli_sql_exception; use Throwable; -class MysqliAdapter implements AdapterInterface, TransactionAdapterInterface, ReconnectableAdapterInterface +final class MysqliAdapter implements AdapterInterface, TransactionAdapterInterface, ReconnectableAdapterInterface { use ConfigurableTrait; - const OPT_RESOLVE_NAMED_PARAMS = 'resolve_named_params'; - const OPT_ENABLE_PARALLEL_QUERIES = 'enable_parallel_queries'; - const OPT_EMULATE_PREPARED_STATEMENTS = 'emulate_prepared_statements'; + public const OPT_RESOLVE_NAMED_PARAMS = 'resolve_named_params'; + public const OPT_ENABLE_PARALLEL_QUERIES = 'enable_parallel_queries'; + public const OPT_EMULATE_PREPARED_STATEMENTS = 'emulate_prepared_statements'; /** * @var mysqli @@ -35,7 +35,7 @@ class MysqliAdapter implements AdapterInterface, TransactionAdapterInterface, Re private $cnx; /** - * @var CredentialsInterface + * @var CredentialsInterface|null */ private $credentials; @@ -50,13 +50,13 @@ class MysqliAdapter implements AdapterInterface, TransactionAdapterInterface, Re * @param CredentialsInterface|null $credentials * @param array|null $options */ - protected function __construct(mysqli $cnx, CredentialsInterface $credentials = null, array $options = null) + protected function __construct(mysqli $cnx, ?CredentialsInterface $credentials = null, array $options = null) { mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); - $this->cnx = $cnx; + $this->cnx = $cnx; $this->credentials = $credentials; if (null !== $options) { - $this->options = array_replace($this->getDefaultOptions(), $options); + $this->options = array_replace($this->getDefaultOptions(), $options); if ($this->hasOption('charset')) { $this->cnx->set_charset($this->getOption('charset')); } @@ -148,16 +148,20 @@ public function prepare(string $queryString, array $values = null): StatementInt } try { - $wrappedStmt = self::wrapWithErrorHandler(function () use ($runnableQueryString) { - return $this->cnx->prepare($runnableQueryString); - }); + $wrappedStmt = self::wrapWithErrorHandler( + function () use ($runnableQueryString) { + return $this->cnx->prepare($runnableQueryString); + } + ); } catch (mysqli_sql_exception $e) { if (!$this->isConnected()) { $this->reconnect(); + return $this->prepare($queryString, $values); } throw new DBALException($e->getMessage(), (int) $e->getCode(), $e); } + return new Statement($this, $wrappedStmt, $values, $queryString, $runnableQueryString); } @@ -182,7 +186,9 @@ public function execute($stmt, array $values = null): ResultInterface $stmt = $this->prepare($stmt, $values); } else { if (!$stmt instanceof Statement) { - throw new \InvalidArgumentException(sprintf('Expected %s object, got %s', Statement::class, get_class($stmt))); + throw new \InvalidArgumentException( + sprintf('Expected %s object, got %s', Statement::class, get_class($stmt)) + ); } if (null !== $values) { $stmt = $stmt->withValues($values); @@ -190,11 +196,11 @@ public function execute($stmt, array $values = null): ResultInterface } try { - $result = $this->runStmt($stmt); - return $result; + return $this->runStmt($stmt); } catch (Throwable $e) { if (!$this->isConnected()) { $this->reconnect(); + return $this->execute($this->prepare((string) $stmt, $stmt->getValues())); } throw $e; @@ -211,21 +217,24 @@ public function executeAsync($stmt, array $values = null): PromiseInterface return $this->executeParallel($stmt, $values); } - $promise = new Promise(function () use (&$promise, $stmt, $values) { - try { - $promise->resolve($this->execute($stmt, $values)); - } catch (Throwable $e) { - $promise->reject($e); + $promise = new Promise( + function () use (&$promise, $stmt, $values) { + try { + $promise->resolve($this->execute($stmt, $values)); + } catch (Throwable $e) { + $promise->reject($e); + } } - }); + ); + return $promise; } /** - * EXPERIMENTAL ! Executes a statement asynchronously. + * Executes a statement asynchronously. * The promise will return a Result object. * - * @param $stmt + * @param mixed $stmt * @param array|null $values * @return PromiseInterface */ @@ -235,7 +244,9 @@ private function executeParallel($stmt, array $values = null): PromiseInterface $stmt = $this->emulatePrepare((string) $stmt, $values); } else { if (!$stmt instanceof Statement) { - throw new \InvalidArgumentException(sprintf('Expected %s object, got %s', Statement::class, get_class($stmt))); + throw new \InvalidArgumentException( + sprintf('Expected %s object, got %s', Statement::class, get_class($stmt)) + ); } if (!$stmt instanceof EmulatedStatement) { $stmt = $this->emulatePrepare((string) $stmt, $values ?? $stmt->getValues()); @@ -246,7 +257,7 @@ private function executeParallel($stmt, array $values = null): PromiseInterface try { // Clone connection (Mysqli Asynchronous queries require a different connection to work properly) $credentials = $this->getCredentials(); - $cnx = self::createLink($credentials); + $cnx = self::createLink($credentials); if ($this->hasOption('charset')) { $cnx->set_charset($this->getOption('charset')); } @@ -255,26 +266,35 @@ private function executeParallel($stmt, array $values = null): PromiseInterface } $stmt->bind(); - $promise = MysqliAsync::query($stmt->getRunnableQuery(), $cnx)->then(function ($result) use ($cnx, $stmt) { - if (!$result instanceof mysqli_result) { - $result = null; - } - return new Result($cnx, $result); - }); - return $promise; + $query = $stmt instanceof EmulatedStatement ? $stmt->getRunnableQuery() : $stmt; + + return MysqliAsync::query($query, $cnx)->then( + static function ($result) use ($cnx) { + if (!$result instanceof mysqli_result) { + $result = null; + } + + return new Result($cnx, $result); + } + ); } - private function runStmt(Statement $stmt) + private function runStmt(StatementInterface $stmt) { try { - return self::wrapWithErrorHandler(function () use ($stmt) { - return $stmt->createResult(); - }); + return self::wrapWithErrorHandler( + static function () use ($stmt) { + return $stmt->createResult(); + } + ); } catch (mysqli_sql_exception $e) { if (false !== strpos($e->getMessage(), 'No data supplied for parameters in prepared statement')) { throw new ParamBindingException($e->getMessage(), (int) $e->getCode(), $e, $stmt); - } elseif (false !== strpos($e->getMessage(), "Number of variables doesn't match number of parameters in prepared statement")) { + } elseif (false !== strpos( + $e->getMessage(), + "Number of variables doesn't match number of parameters in prepared statement" + )) { throw new ParamBindingException($e->getMessage(), (int) $e->getCode(), $e, $stmt); } else { throw new DBALException($e->getMessage(), (int) $e->getCode(), $e); @@ -325,32 +345,32 @@ private function convertToRunnableQuery(string $queryString): string public function getDefaultOptions(): array { return [ - self::OPT_MAX_RECONNECT_ATTEMPTS => self::DEFAULT_MAX_RECONNECT_ATTEMPTS, - self::OPT_USLEEP_AFTER_FIRST_ATTEMPT => self::DEFAULT_USLEEP_AFTER_FIRST_ATTEMPT, - self::OPT_RESOLVE_NAMED_PARAMS => false, + self::OPT_MAX_RECONNECT_ATTEMPTS => self::DEFAULT_MAX_RECONNECT_ATTEMPTS, + self::OPT_USLEEP_AFTER_FIRST_ATTEMPT => self::DEFAULT_USLEEP_AFTER_FIRST_ATTEMPT, + self::OPT_RESOLVE_NAMED_PARAMS => false, self::OPT_EMULATE_PREPARED_STATEMENTS => false, - self::OPT_ENABLE_PARALLEL_QUERIES => false, + self::OPT_ENABLE_PARALLEL_QUERIES => false, ]; } /** * @param CredentialsInterface $credentials - * @param bool $resolveNamedParameters + * @param array|null $options * @return MysqliAdapter */ public static function factory(CredentialsInterface $credentials, array $options = null): self { - return new static(self::createLink($credentials), $credentials, $options); + return new self(self::createLink($credentials), $credentials, $options); } /** - * @param mysqli $link + * @param mysqli $link * @param CredentialsInterface|null $credentials * @return MysqliAdapter */ public static function createFromLink(mysqli $link, CredentialsInterface $credentials = null): self { - return new static($link, $credentials); + return new self($link, $credentials); } /** @@ -361,7 +381,13 @@ private static function createLink(CredentialsInterface $credentials): mysqli { mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); try { - return new mysqli($credentials->getHostname(), $credentials->getUser(), $credentials->getPassword(), $credentials->getDatabase(), $credentials->getPort()); + return new mysqli( + $credentials->getHostname(), + $credentials->getUser(), + $credentials->getPassword(), + $credentials->getDatabase(), + $credentials->getPort() + ); } catch (mysqli_sql_exception $e) { throw new AccessDeniedException($e->getMessage(), (int) $e->getCode(), $e); } @@ -373,12 +399,13 @@ private static function createLink(CredentialsInterface $credentials): mysqli */ private static function wrapWithErrorHandler(callable $run) { - $errorHandler = function ($errno, $errstr) { + $errorHandler = static function ($errno, $errstr) { throw new mysqli_sql_exception($errstr, $errno); }; set_error_handler($errorHandler, E_WARNING); $result = $run(); restore_error_handler(); + return $result; } } diff --git a/src/Model/Adapter/Mysqli/Result.php b/src/Model/Adapter/Mysqli/Result.php index f062032..5420c9f 100644 --- a/src/Model/Adapter/Mysqli/Result.php +++ b/src/Model/Adapter/Mysqli/Result.php @@ -138,7 +138,7 @@ private function freeze(): void $this->frozen = true; } - private function getAffectedRows(): ?int + private function getAffectedRows(): int { if (null === $this->mysqli) { throw new DBALException("No \mysqli object provided."); @@ -147,7 +147,7 @@ private function getAffectedRows(): ?int return $this->mysqli->affected_rows; } - private function getNumRows(): ?int + private function getNumRows(): int { if (null === $this->result) { throw new DBALException("No \mysqli_result object provided."); diff --git a/src/Model/Adapter/Mysqli/Statement.php b/src/Model/Adapter/Mysqli/Statement.php index 35e34f8..6915911 100644 --- a/src/Model/Adapter/Mysqli/Statement.php +++ b/src/Model/Adapter/Mysqli/Statement.php @@ -130,7 +130,7 @@ private function resolveValues(): array /** * Attempt to convert non-scalar values. * - * @param $value + * @param mixed $value * @return string */ protected function toScalar($value) @@ -215,10 +215,10 @@ public function preview(): string } /** - * @param $value + * @param mixed $value * @return string */ - protected function getMysqliType($value) + protected function getMysqliType($value): ?string { if (!is_scalar($value)) { throw new \InvalidArgumentException(sprintf("Can only cast scalar variables, %s given.", gettype($value))); diff --git a/src/Model/Adapter/PDO/PDOAdapter.php b/src/Model/Adapter/PDO/PDOAdapter.php index 3070be6..d240014 100644 --- a/src/Model/Adapter/PDO/PDOAdapter.php +++ b/src/Model/Adapter/PDO/PDOAdapter.php @@ -19,7 +19,7 @@ use PDOException; use Throwable; -class PDOAdapter implements AdapterInterface, TransactionAdapterInterface, ReconnectableAdapterInterface +final class PDOAdapter implements AdapterInterface, TransactionAdapterInterface, ReconnectableAdapterInterface { use ConfigurableTrait; @@ -29,7 +29,7 @@ class PDOAdapter implements AdapterInterface, TransactionAdapterInterface, Recon private $cnx; /** - * @var CredentialsInterface + * @var CredentialsInterface|null */ private $credentials; @@ -44,7 +44,7 @@ class PDOAdapter implements AdapterInterface, TransactionAdapterInterface, Recon * @param CredentialsInterface|null $credentials * @param array|null $options */ - protected function __construct(PDO $cnx, CredentialsInterface $credentials = null, array $options = null) + protected function __construct(PDO $cnx, ?CredentialsInterface $credentials = null, array $options = null) { $this->cnx = $cnx; if (PDO::ERRMODE_EXCEPTION !== $this->cnx->getAttribute(PDO::ATTR_ERRMODE)) { @@ -98,7 +98,7 @@ public function shouldReconnect(): bool /** * Tries to reconnect to database. */ - private function reconnect() + private function reconnect(): void { if (0 === (int) $this->getOption(self::OPT_MAX_RECONNECT_ATTEMPTS)) { throw new MaxConnectAttempsException("Connection lost."); @@ -184,10 +184,7 @@ public function executeAsync($stmt, array $values = null): PromiseInterface return $promise; } - /** - * @param \PDOStatement $wrappedStmt - */ - private function runStmt(Statement $stmt) + private function runStmt(StatementInterface $stmt): void { $wrappedStmt = $stmt->getWrappedStatement(); try { @@ -257,7 +254,7 @@ public static function factory(CredentialsInterface $credentials, array $options */ public static function createFromLink(PDO $link, CredentialsInterface $credentials = null): self { - return new static($link, $credentials); + return new self($link, $credentials); } /** @@ -292,7 +289,7 @@ private static function createLink(CredentialsInterface $credentials, array $opt */ private static function wrapWithErrorHandler(callable $run) { - $errorHandler = function ($errno, $errstr) { + $errorHandler = static function ($errno, $errstr) { throw new PDOException($errstr, $errno); }; set_error_handler($errorHandler, E_WARNING); diff --git a/src/Model/Adapter/PDO/Statement.php b/src/Model/Adapter/PDO/Statement.php index bd78621..ed9176b 100644 --- a/src/Model/Adapter/PDO/Statement.php +++ b/src/Model/Adapter/PDO/Statement.php @@ -56,7 +56,7 @@ public function getQueryString(): string * @inheritDoc * @return PDOStatement */ - public function getWrappedStatement() + public function getWrappedStatement(): PDOStatement { return $this->stmt; } @@ -102,7 +102,7 @@ protected function bindNumericParameters(): void /** * Attempt to convert non-scalar values. * - * @param $value + * @param mixed $value * @return string */ protected function toScalar($value) @@ -125,10 +125,10 @@ protected function toScalar($value) } /** - * @param $var + * @param mixed $value * @return int */ - protected function getPdoType($value) + protected function getPdoType($value): ?int { if (!is_scalar($value) && null !== $value) { throw new \InvalidArgumentException("Can only cast scalar variables."); diff --git a/src/Model/ConfigurableTrait.php b/src/Model/ConfigurableTrait.php index fadddee..da3f87a 100644 --- a/src/Model/ConfigurableTrait.php +++ b/src/Model/ConfigurableTrait.php @@ -8,7 +8,7 @@ trait ConfigurableTrait protected $options; /** - * @param $key + * @param string $key * @return mixed */ public function getOption($key) @@ -20,7 +20,7 @@ public function getOption($key) } /** - * @param $key + * @param string $key * @return bool */ public function hasOption($key): bool @@ -43,10 +43,10 @@ public function getOptions(): array } /** - * @param $key - * @param $value + * @param string $key + * @param mixed $value */ - public function setOption($key, $value) + public function setOption($key, $value): void { if (null === $this->options) { $this->options = $this->getDefaultOptions(); @@ -54,17 +54,6 @@ public function setOption($key, $value) $this->options[$key] = $value; } - /** - * @param $key - */ - public function unsetOption($key) - { - if (null === $this->options) { - $this->options = $this->getDefaultOptions(); - } - unset($this->options[$key]); - } - /** * @return array */ diff --git a/src/Model/Credentials.php b/src/Model/Credentials.php index 5baf78c..4f2ae88 100644 --- a/src/Model/Credentials.php +++ b/src/Model/Credentials.php @@ -32,7 +32,7 @@ class Credentials implements CredentialsInterface private $platform; /** - * @var string + * @var int */ private $port; diff --git a/src/Model/SimpleDBAL.php b/src/Model/SimpleDBAL.php index 81e22a0..38ac95a 100644 --- a/src/Model/SimpleDBAL.php +++ b/src/Model/SimpleDBAL.php @@ -9,9 +9,8 @@ class SimpleDBAL { - - const PDO = 'pdo'; - const MYSQLI = 'mysqli'; + public const PDO = 'pdo'; + public const MYSQLI = 'mysqli'; /** * @param CredentialsInterface $credentials From e9bde753cbed03ec1fa35059536983f6ac0d3f65 Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Sun, 19 Jul 2020 10:03:20 +0200 Subject: [PATCH 6/8] style: fix CS + add CI --- .github/workflows/ci.yml | 53 +++++++++++++++++++ .gitignore | 6 ++- README.md | 3 +- composer.json | 18 ++++--- phpstan.neon.dist | 4 ++ phpunit.xml.dist | 8 +++ .../ReconnectableAdapterInterface.php | 8 +-- src/Model/Adapter/Mysqli/MysqliAdapter.php | 9 ++-- src/Model/Adapter/Mysqli/MysqliAsync.php | 2 +- src/Model/Adapter/Mysqli/Result.php | 2 +- src/Model/Adapter/Mysqli/Statement.php | 4 +- src/Model/Adapter/PDO/Result.php | 2 +- src/Model/Adapter/PDO/Statement.php | 7 ++- src/Model/ConfigurableTrait.php | 1 - src/Model/Exception/AccessDeniedException.php | 1 - src/Model/Exception/DBALException.php | 1 - .../Exception/MaxConnectAttempsException.php | 1 - src/Model/Exception/ParamBindingException.php | 2 - src/Model/SimpleDBALPool.php | 11 ++-- tests/bootstrap.php | 12 ----- tests/config/settings.yml.dist | 9 ---- tests/src/TestSuite.php | 32 +++++------ 22 files changed, 115 insertions(+), 81 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 phpstan.neon.dist delete mode 100644 tests/config/settings.yml.dist diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a4a8696 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,53 @@ +name: CI Workflow + +on: [push, pull_request] + +jobs: + code-style: + + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Enable Composer parallel downloads + run: composer global require symfony/flex + + - name: Install dependencies + if: steps.composer-cache.outputs.cache-hit != 'true' + run: composer install --prefer-dist --no-progress --no-suggest + + - name: Check code style + run: composer phpcs:check + + - name: Track avoidable bugs + run: composer phpstan:analyze + + tests: + + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + + - name: Shutdown Ubuntu MySQL (SUDO) + run: sudo service mysql stop + + - uses: mirromutth/mysql-action@v1.1 + with: + mysql user: test + mysql password: test + mysql database: test + + - name: Enable Composer parallel downloads + run: composer global require symfony/flex + + - name: Install dependencies + if: steps.composer-cache.outputs.cache-hit != 'true' + run: composer install --prefer-dist --no-progress --no-suggest + + - name: Run tests + run: composer tests:run diff --git a/.gitignore b/.gitignore index b8f3d63..6593e51 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ -tests/config/settings.yml \ No newline at end of file +tests/config/settings.yml +.php_cs.cache +.phpcs-cache +composer.lock +phpunit.xml diff --git a/README.md b/README.md index b4272b0..6dfa9e7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +![CI Workflow](https://github.com/bpolaszek/simple-dbal/workflows/CI%20Workflow/badge.svg) [![Latest Stable Version](https://poser.pugx.org/bentools/simple-dbal/v/stable)](https://packagist.org/packages/bentools/simple-dbal) [![License](https://poser.pugx.org/bentools/simple-dbal/license)](https://packagist.org/packages/bentools/simple-dbal) [![Quality Score](https://img.shields.io/scrutinizer/g/bpolaszek/simple-dbal.svg?style=flat-square)](https://scrutinizer-ci.com/g/bpolaszek/simple-dbal) @@ -63,7 +64,7 @@ For _INSERT_ / _UPDATE_ / _DELETE_ queries, use the following methods: Installation ------------ ``` -composer require bentools/simple-dbal +composer require bentools/simple-dbal:0.7.* ``` Tests diff --git a/composer.json b/composer.json index 965a548..6264445 100644 --- a/composer.json +++ b/composer.json @@ -12,10 +12,9 @@ "guzzlehttp/promises": "^1.3" }, "require-dev": { - "squizlabs/php_codesniffer": "~2.0", + "squizlabs/php_codesniffer": "^3.5", "symfony/var-dumper": "^3.2", "bentools/iterable-functions": "^1.1", - "incenteev/composer-parameter-handler": "^2.1", "symfony/yaml": "^3.2", "phpstan/phpstan": "^0.12.32", "php-coveralls/php-coveralls": "^2.2", @@ -36,14 +35,17 @@ } }, "scripts": { - "set-parameters": [ - "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters" - ] + "tests:run": "vendor/bin/phpunit", + "phpcs:check": "vendor/bin/phpcs --standard=PSR12 -n src", + "php-cs-fixer:run": "vendor/bin/php-cs-fixer fix src --allow-risky=yes", + "phpcbf:run": "vendor/bin/phpcbf --standard=PSR12 -n bin migrations src tests || true", + "phpcs:fix": [ + "@php-cs-fixer:run", + "@phpcbf:run" + ], + "phpstan:analyze": "vendor/bin/phpstan analyze" }, "extra": { - "incenteev-parameters": { - "file": "tests/config/settings.yml" - }, "branch-alias": { "dev-master": "1.0.x-dev" } diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..077ee5a --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,4 @@ +parameters: + level: 5 + paths: + - src diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 36470ed..29abc82 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -15,6 +15,14 @@ stopOnFailure="false" verbose="true" > + + + + + + + + ./tests/src diff --git a/src/Contract/ReconnectableAdapterInterface.php b/src/Contract/ReconnectableAdapterInterface.php index 8f11800..8bccad6 100644 --- a/src/Contract/ReconnectableAdapterInterface.php +++ b/src/Contract/ReconnectableAdapterInterface.php @@ -4,10 +4,10 @@ interface ReconnectableAdapterInterface { - const OPT_MAX_RECONNECT_ATTEMPTS = 'max_reconnect_attempts'; - const OPT_USLEEP_AFTER_FIRST_ATTEMPT = 'usleep_after_first_attempt'; - const DEFAULT_USLEEP_AFTER_FIRST_ATTEMPT = 50000; - const DEFAULT_MAX_RECONNECT_ATTEMPTS = 0; + public const OPT_MAX_RECONNECT_ATTEMPTS = 'max_reconnect_attempts'; + public const OPT_USLEEP_AFTER_FIRST_ATTEMPT = 'usleep_after_first_attempt'; + public const DEFAULT_USLEEP_AFTER_FIRST_ATTEMPT = 50000; + public const DEFAULT_MAX_RECONNECT_ATTEMPTS = 0; /** * @return bool diff --git a/src/Model/Adapter/Mysqli/MysqliAdapter.php b/src/Model/Adapter/Mysqli/MysqliAdapter.php index b5fea81..5a75509 100644 --- a/src/Model/Adapter/Mysqli/MysqliAdapter.php +++ b/src/Model/Adapter/Mysqli/MysqliAdapter.php @@ -22,7 +22,6 @@ final class MysqliAdapter implements AdapterInterface, TransactionAdapterInterface, ReconnectableAdapterInterface { - use ConfigurableTrait; public const OPT_RESOLVE_NAMED_PARAMS = 'resolve_named_params'; @@ -136,7 +135,6 @@ protected function hasNamedParameters(string $queryString): bool */ public function prepare(string $queryString, array $values = null): StatementInterface { - if (true === $this->getOption(self::OPT_EMULATE_PREPARED_STATEMENTS)) { return $this->emulatePrepare($queryString, $values); } @@ -212,7 +210,6 @@ public function execute($stmt, array $values = null): ResultInterface */ public function executeAsync($stmt, array $values = null): PromiseInterface { - if (true === $this->getOption(self::OPT_ENABLE_PARALLEL_QUERIES)) { return $this->executeParallel($stmt, $values); } @@ -291,10 +288,12 @@ static function () use ($stmt) { } catch (mysqli_sql_exception $e) { if (false !== strpos($e->getMessage(), 'No data supplied for parameters in prepared statement')) { throw new ParamBindingException($e->getMessage(), (int) $e->getCode(), $e, $stmt); - } elseif (false !== strpos( + } elseif ( + false !== strpos( $e->getMessage(), "Number of variables doesn't match number of parameters in prepared statement" - )) { + ) + ) { throw new ParamBindingException($e->getMessage(), (int) $e->getCode(), $e, $stmt); } else { throw new DBALException($e->getMessage(), (int) $e->getCode(), $e); diff --git a/src/Model/Adapter/Mysqli/MysqliAsync.php b/src/Model/Adapter/Mysqli/MysqliAsync.php index 1b001cf..b6d5093 100644 --- a/src/Model/Adapter/Mysqli/MysqliAsync.php +++ b/src/Model/Adapter/Mysqli/MysqliAsync.php @@ -49,7 +49,7 @@ public static function query(string $query, mysqli $cnx) public static function getInstance() { if (null === self::$instance) { - self::$instance = new self; + self::$instance = new self(); } return self::$instance; diff --git a/src/Model/Adapter/Mysqli/Result.php b/src/Model/Adapter/Mysqli/Result.php index 5420c9f..2d8fa8b 100644 --- a/src/Model/Adapter/Mysqli/Result.php +++ b/src/Model/Adapter/Mysqli/Result.php @@ -158,7 +158,7 @@ private function getNumRows(): int public static function from(...$arguments): self { - $instance = new self; + $instance = new self(); foreach ($arguments as $argument) { if ($argument instanceof mysqli) { $instance->mysqli = $argument; diff --git a/src/Model/Adapter/Mysqli/Statement.php b/src/Model/Adapter/Mysqli/Statement.php index 6915911..e248fb2 100644 --- a/src/Model/Adapter/Mysqli/Statement.php +++ b/src/Model/Adapter/Mysqli/Statement.php @@ -12,7 +12,6 @@ class Statement implements StatementInterface { - use StatementTrait; /** @@ -192,8 +191,7 @@ public function preview(): string foreach ($this->values as $value) { $preview = preg_replace("/([\?])/", $escape($value), $preview, 1); } - } # Case of named placeholders - else { + } else { # Case of named placeholders foreach ($this->values as $key => $value) { if (!in_array($key, $keywords, true)) { $keywords[] = $key; diff --git a/src/Model/Adapter/PDO/Result.php b/src/Model/Adapter/PDO/Result.php index 70d8ebd..abf70d3 100644 --- a/src/Model/Adapter/PDO/Result.php +++ b/src/Model/Adapter/PDO/Result.php @@ -135,7 +135,7 @@ private function freeze(): void public static function from(...$arguments): self { - $instance = new self; + $instance = new self(); foreach ($arguments as $argument) { if ($argument instanceof PDO) { $instance->pdo = $argument; diff --git a/src/Model/Adapter/PDO/Statement.php b/src/Model/Adapter/PDO/Statement.php index ed9176b..8388ed4 100644 --- a/src/Model/Adapter/PDO/Statement.php +++ b/src/Model/Adapter/PDO/Statement.php @@ -133,7 +133,7 @@ protected function getPdoType($value): ?int if (!is_scalar($value) && null !== $value) { throw new \InvalidArgumentException("Can only cast scalar variables."); } - switch (strtolower(gettype($value))) : + switch (strtolower(gettype($value))) { case 'integer': return PDO::PARAM_INT; case 'boolean': @@ -144,7 +144,7 @@ protected function getPdoType($value): ?int case 'string': default: return PDO::PARAM_STR; - endswitch; + } } /** @@ -181,8 +181,7 @@ public function preview(): string foreach ($this->values as $value) { $preview = preg_replace("/([\?])/", $escape($value), $preview, 1); } - } # Case of named placeholders - else { + } else { # Case of named placeholders foreach ($this->values as $key => $value) { if (!in_array($key, $keywords, true)) { $keywords[] = $key; diff --git a/src/Model/ConfigurableTrait.php b/src/Model/ConfigurableTrait.php index da3f87a..bb7c5e3 100644 --- a/src/Model/ConfigurableTrait.php +++ b/src/Model/ConfigurableTrait.php @@ -4,7 +4,6 @@ trait ConfigurableTrait { - protected $options; /** diff --git a/src/Model/Exception/AccessDeniedException.php b/src/Model/Exception/AccessDeniedException.php index 131ebf6..d8f2170 100644 --- a/src/Model/Exception/AccessDeniedException.php +++ b/src/Model/Exception/AccessDeniedException.php @@ -4,5 +4,4 @@ class AccessDeniedException extends DBALException { - } diff --git a/src/Model/Exception/DBALException.php b/src/Model/Exception/DBALException.php index 450d604..1a83c93 100644 --- a/src/Model/Exception/DBALException.php +++ b/src/Model/Exception/DBALException.php @@ -4,5 +4,4 @@ class DBALException extends \RuntimeException { - } diff --git a/src/Model/Exception/MaxConnectAttempsException.php b/src/Model/Exception/MaxConnectAttempsException.php index c704294..c424a52 100644 --- a/src/Model/Exception/MaxConnectAttempsException.php +++ b/src/Model/Exception/MaxConnectAttempsException.php @@ -4,5 +4,4 @@ class MaxConnectAttempsException extends DBALException { - } diff --git a/src/Model/Exception/ParamBindingException.php b/src/Model/Exception/ParamBindingException.php index 5225664..68cffc5 100644 --- a/src/Model/Exception/ParamBindingException.php +++ b/src/Model/Exception/ParamBindingException.php @@ -4,6 +4,4 @@ class ParamBindingException extends StatementException { - - } diff --git a/src/Model/SimpleDBALPool.php b/src/Model/SimpleDBALPool.php index b6087aa..3293104 100644 --- a/src/Model/SimpleDBALPool.php +++ b/src/Model/SimpleDBALPool.php @@ -8,10 +8,9 @@ class SimpleDBALPool { - - const READ_WRITE = 1; - const READ_ONLY = 2; - const WRITE_ONLY = 3; + public const READ_WRITE = 1; + public const READ_ONLY = 2; + public const WRITE_ONLY = 3; protected $rConnections = []; protected $wConnections = []; @@ -21,7 +20,7 @@ class SimpleDBALPool * @param int $access * @param int $weight */ - public function attach(ConnectionInterface $connection, int $access = self::READ_WRITE, int $weight = 1) + public function attach(ConnectionInterface $connection, int $access = self::READ_WRITE, int $weight = 1): void { if ($weight >= 1) { switch ($access) { @@ -44,7 +43,7 @@ public function attach(ConnectionInterface $connection, int $access = self::READ /** * @param ConnectionInterface $connection */ - public function detach(ConnectionInterface $connection) + public function detach(ConnectionInterface $connection): void { $reorderReadConnections = false; $reorderWriteConnections = false; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b2ea073..b378e3a 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -4,18 +4,6 @@ require_once __DIR__ . '/../vendor/autoload.php'; -$configFile = __DIR__ . '/config/settings.yml'; -if (!is_readable($configFile)) { - print PHP_EOL . PHP_EOL; - printf('The config file %s is not readable.' . PHP_EOL, $configFile); - printf('Create this file and put your databse settings in it (see %s.dist)' . PHP_EOL, $configFile); - printf('You can also run the following command to do this interactively:'); - print PHP_EOL . PHP_EOL; - print 'composer run-script set-parameters'; - print PHP_EOL . PHP_EOL; - exit; -} - $settings = TestSuite::getSettings(); $credentials = TestSuite::getCredentialsFromSettings($settings); diff --git a/tests/config/settings.yml.dist b/tests/config/settings.yml.dist deleted file mode 100644 index aa244de..0000000 --- a/tests/config/settings.yml.dist +++ /dev/null @@ -1,9 +0,0 @@ -parameters: - - database_platform: mysql - database_host: localhost - database_port: 3306 - database_name: test - database_user: root - database_password: ~ - test_table_name: simpledbal_test \ No newline at end of file diff --git a/tests/src/TestSuite.php b/tests/src/TestSuite.php index e098385..4594550 100644 --- a/tests/src/TestSuite.php +++ b/tests/src/TestSuite.php @@ -8,29 +8,18 @@ class TestSuite { - - const CONFIG_DIR = __DIR__ . '/../config'; - - /** - * @param $fileName - * @return string - */ - public static function getConfigFile($fileName) - { - return sprintf('%s/%s', self::CONFIG_DIR, $fileName); - } - /** * @return array */ public static function getSettings(): array { - $settingsFile = TestSuite::getConfigFile('settings.yml'); - if (!is_readable($settingsFile)) { - throw new \RuntimeException("settings.yml is not readable."); - } - $settings = Yaml::parse(file_get_contents($settingsFile))['parameters']; - return $settings; + return [ + 'database_host' => $_SERVER['DATABASE_HOST'], + 'database_user' => $_SERVER['DATABASE_USER'], + 'database_password' => $_SERVER['DATABASE_PASSWORD'], + 'database_name' => $_SERVER['DATABASE_NAME'], + 'test_table_name' => 'simpledbal_test', + ]; } /** @@ -38,6 +27,11 @@ public static function getSettings(): array */ public static function getCredentialsFromSettings(array $settings): CredentialsInterface { - return new Credentials($settings['database_host'], $settings['database_user'], $settings['database_password'], $settings['database_name'], $settings['database_platform'], $settings['database_port']); + return new Credentials( + $settings['database_host'], + $settings['database_user'], + $settings['database_password'], + $settings['database_name'] + ); } } From 2f49947ace39952e7e67ed22541babf06d36276d Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Sun, 19 Jul 2020 11:17:10 +0200 Subject: [PATCH 7/8] docs: add link to bentools/where --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6dfa9e7..c4ca7f1 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Tests ``` Documentation ------ +------------- [Getting started](doc/01-GettingStarted.md) @@ -85,3 +85,9 @@ Documentation [Connection pools](doc/04-ConnectionPools.md) [Known Issues](doc/05-KnownIssues.md) + + +See also +-------- + +[bentools/where](https://github.com/bpolaszek/where) - A fluent, immutable SQL expressions builder. From a9f0e92872ed36892f7afb3782ee1edabac7e9bc Mon Sep 17 00:00:00 2001 From: Beno!t POLASZEK Date: Fri, 23 Oct 2020 11:54:28 +0200 Subject: [PATCH 8/8] build: add PHP matrix --- .github/workflows/ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4a8696..0457a5b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,19 @@ jobs: tests: runs-on: ubuntu-20.04 + continue-on-error: ${{ matrix.experimental }} + strategy: + max-parallel: 10 + matrix: + php: + - '7.1' + - '7.2' + - '7.3' + - '7.4' + experimental: [ false ] + include: + - php: 8.0 + experimental: true steps: - uses: actions/checkout@v2