diff --git a/composer.json b/composer.json index 47ceed0..871d732 100644 --- a/composer.json +++ b/composer.json @@ -20,12 +20,14 @@ "require": { "php": "~7.4||~8.0", "ext-curl": "*", + "ext-json": "*", "guzzlehttp/guzzle": "~6.1|~7.0", "composer/ca-bundle": "^1.5" }, "require-dev": { "phpunit/phpunit": "9.5.10", - "squizlabs/php_codesniffer": "3.6.1" + "squizlabs/php_codesniffer": "3.6.1", + "phpstan/phpstan": "^1.11" }, "autoload": { "psr-4": { @@ -34,10 +36,12 @@ }, "scripts": { "ci": [ + "@phpstan", "@phpcs", "@test" ], "test": "phpunit", - "phpcs": "phpcs --standard=PSR2 src && phpcs --standard=PSR2 tests" + "phpcs": "phpcs --standard=PSR2 src && phpcs --standard=PSR2 tests", + "phpstan": "phpstan analyse -l 8 src tests" } } diff --git a/src/FioApi/Downloader.php b/src/FioApi/Downloader.php index e96221f..9964ec9 100644 --- a/src/FioApi/Downloader.php +++ b/src/FioApi/Downloader.php @@ -8,6 +8,8 @@ use FioApi\Exceptions\TooGreedyException; use GuzzleHttp\Client; use GuzzleHttp\ClientInterface; +use GuzzleHttp\Exception\BadResponseException; +use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\RequestOptions; use Psr\Http\Message\ResponseInterface; @@ -16,7 +18,7 @@ class Downloader /** @var UrlBuilder */ protected $urlBuilder; - /** @var Client */ + /** @var ?ClientInterface */ protected $client; public function __construct(string $token, ClientInterface $client = null) @@ -27,7 +29,7 @@ public function __construct(string $token, ClientInterface $client = null) public function getClient(): ClientInterface { - if (!$this->client) { + if ($this->client === null) { $this->client = new Client([ RequestOptions::VERIFY => CaBundle::getSystemCaRootBundlePath() ]); @@ -59,26 +61,34 @@ public function setLastId(string $id): void try { $client->request('get', $url); - } catch (\GuzzleHttp\Exception\BadResponseException $e) { + } catch (BadResponseException $e) { $this->handleException($e); } } + /** + * @param string $url + * @return TransactionList + */ private function downloadTransactionsList(string $url): TransactionList { $client = $this->getClient(); + $transactions = null; try { - /** @var ResponseInterface $response */ + /** @var ?ResponseInterface $response */ $response = $client->request('get', $url); - } catch (\GuzzleHttp\Exception\BadResponseException $e) { + if ($response) { + $transactions = json_decode($response->getBody()->getContents())->accountStatement; + } + } catch (BadResponseException $e) { $this->handleException($e); } - return TransactionList::create(json_decode($response->getBody()->getContents())->accountStatement); + return TransactionList::create($transactions); } - private function handleException(\GuzzleHttp\Exception\BadResponseException $e): void + private function handleException(BadResponseException $e): void { if ($e->getCode() == 409) { throw new TooGreedyException('You can use one token for API call every 30 seconds', $e->getCode(), $e); diff --git a/src/FioApi/TransactionList.php b/src/FioApi/TransactionList.php index 5ed1e94..1ad827d 100644 --- a/src/FioApi/TransactionList.php +++ b/src/FioApi/TransactionList.php @@ -17,13 +17,13 @@ class TransactionList /** @var \DateTimeImmutable */ protected $dateEnd; - /** @var float */ + /** @var float|null */ protected $idFrom; - /** @var float */ + /** @var float|null */ protected $idTo; - /** @var int */ + /** @var int|null */ protected $idLastDownload; /** @var Account */ @@ -55,7 +55,7 @@ protected function __construct( /** * @param Transaction $transaction */ - protected function addTransaction(Transaction $transaction) + protected function addTransaction(Transaction $transaction): void { $this->transactions[] = $transaction; } diff --git a/src/FioApi/UrlBuilder.php b/src/FioApi/UrlBuilder.php index 3e4d9cc..666a7eb 100644 --- a/src/FioApi/UrlBuilder.php +++ b/src/FioApi/UrlBuilder.php @@ -22,7 +22,7 @@ public function getToken(): string return $this->token; } - public function setToken(string $token) + public function setToken(string $token): void { if (!$token) { throw new MissingTokenException( diff --git a/tests/FioApi/AccountTest.php b/tests/FioApi/AccountTest.php index d9a257a..2dc810c 100644 --- a/tests/FioApi/AccountTest.php +++ b/tests/FioApi/AccountTest.php @@ -5,7 +5,7 @@ class AccountTest extends \PHPUnit\Framework\TestCase { - public function testAccountValuesAreProperlySet() + public function testAccountValuesAreProperlySet(): void { $account = new Account( '214498596', diff --git a/tests/FioApi/DownloaderTest.php b/tests/FioApi/DownloaderTest.php index 33949c7..6879019 100644 --- a/tests/FioApi/DownloaderTest.php +++ b/tests/FioApi/DownloaderTest.php @@ -11,7 +11,7 @@ class DownloaderTest extends \PHPUnit\Framework\TestCase { - public function testNotRespectingTheTimeoutResultsInTooGreedyException() + public function testNotRespectingTheTimeoutResultsInTooGreedyException(): void { $handler = HandlerStack::create(new MockHandler([ new Response(409), @@ -23,7 +23,7 @@ public function testNotRespectingTheTimeoutResultsInTooGreedyException() $downloader->downloadSince(new \DateTimeImmutable('-1 week')); } - public function testInvalidTokenResultsInInternalErrorException() + public function testInvalidTokenResultsInInternalErrorException(): void { $handler = HandlerStack::create(new MockHandler([ new Response(500), @@ -35,7 +35,7 @@ public function testInvalidTokenResultsInInternalErrorException() $downloader->downloadSince(new \DateTimeImmutable('-1 week')); } - public function testUnknownResponseCodePassesOriginalException() + public function testUnknownResponseCodePassesOriginalException(): void { $handler = HandlerStack::create(new MockHandler([ new Response(418), @@ -48,10 +48,10 @@ public function testUnknownResponseCodePassesOriginalException() $downloader->downloadSince(new \DateTimeImmutable('-1 week')); } - public function testDownloaderDownloadsData() + public function testDownloaderDownloadsData(): void { $handler = HandlerStack::create(new MockHandler([ - new Response(200, [], file_get_contents(__DIR__ . '/data/example-response.json')), + new Response(200, [], (string) file_get_contents(__DIR__ . '/data/example-response.json')), ])); $downloader = new Downloader('validToken', new Client(['handler' => $handler])); @@ -60,10 +60,10 @@ public function testDownloaderDownloadsData() $this->assertInstanceOf(TransactionList::class, $transactionList); } - public function testDownloaderDownloadsLast() + public function testDownloaderDownloadsLast(): void { $handler = HandlerStack::create(new MockHandler([ - new Response(200, [], file_get_contents(__DIR__ . '/data/example-response.json')), + new Response(200, [], (string) file_get_contents(__DIR__ . '/data/example-response.json')), ])); $downloader = new Downloader('validToken', new Client(['handler' => $handler])); @@ -72,7 +72,7 @@ public function testDownloaderDownloadsLast() $this->assertInstanceOf(TransactionList::class, $transactionList); } - public function testDownloaderSetsLastId() + public function testDownloaderSetsLastId(): void { $container = []; $history = Middleware::history($container); diff --git a/tests/FioApi/TransactionListTest.php b/tests/FioApi/TransactionListTest.php index 39b817b..8a3786a 100644 --- a/tests/FioApi/TransactionListTest.php +++ b/tests/FioApi/TransactionListTest.php @@ -5,9 +5,9 @@ class TransactionListTest extends \PHPUnit\Framework\TestCase { - public function testTransactionListValuesAreProperlySet() + public function testTransactionListValuesAreProperlySet(): void { - $transactionList = json_decode(file_get_contents(__DIR__ . '/data/example-response.json')); + $transactionList = json_decode((string) file_get_contents(__DIR__ . '/data/example-response.json')); $transactionList = TransactionList::create($transactionList->accountStatement); @@ -22,9 +22,9 @@ public function testTransactionListValuesAreProperlySet() $this->assertInstanceOf(Transaction::class, $transactionList->getTransactions()[0]); } - public function testEmptyTransactionList() + public function testEmptyTransactionList(): void { - $transactionList = json_decode(file_get_contents(__DIR__ . '/data/example-empty-response.json')); + $transactionList = json_decode((string) file_get_contents(__DIR__ . '/data/example-empty-response.json')); $transactionList = TransactionList::create($transactionList->accountStatement); diff --git a/tests/FioApi/TransactionTest.php b/tests/FioApi/TransactionTest.php index f32605a..8533c63 100644 --- a/tests/FioApi/TransactionTest.php +++ b/tests/FioApi/TransactionTest.php @@ -5,9 +5,9 @@ class TransactionTest extends \PHPUnit\Framework\TestCase { - public function testAccountValuesAreProperlySet() + public function testAccountValuesAreProperlySet(): void { - $transaction = json_decode(file_get_contents(__DIR__ . '/data/example-transaction.json')); + $transaction = json_decode((string) file_get_contents(__DIR__ . '/data/example-transaction.json')); $transaction = Transaction::create($transaction); diff --git a/tests/FioApi/UrlBuilderTest.php b/tests/FioApi/UrlBuilderTest.php index bc5c788..ba33c96 100644 --- a/tests/FioApi/UrlBuilderTest.php +++ b/tests/FioApi/UrlBuilderTest.php @@ -5,27 +5,27 @@ class UrlBuilderTest extends \PHPUnit\Framework\TestCase { - public function testMissingTokenExceptionIsThrownForEmptyToken() + public function testMissingTokenExceptionIsThrownForEmptyToken(): void { $this->expectException(\FioApi\Exceptions\MissingTokenException::class); new UrlBuilder(''); } - public function testTokenCanBeSetThroughConstructor() + public function testTokenCanBeSetThroughConstructor(): void { $urlBuilder = new UrlBuilder('token1'); $this->assertSame('token1', $urlBuilder->getToken()); } - public function testTokenCanBeChangedThroughSetter() + public function testTokenCanBeChangedThroughSetter(): void { $urlBuilder = new UrlBuilder('token1'); $urlBuilder->setToken('token2'); $this->assertSame('token2', $urlBuilder->getToken()); } - public function testBuildPeriodsUrlReturnValidUrl() + public function testBuildPeriodsUrlReturnValidUrl(): void { $urlBuilder = new UrlBuilder('token1'); $this->assertSame(