From 8fd6aa89406b7497e177dc345a644fd87a5d0c5e Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 03:47:43 +0100 Subject: [PATCH 01/36] add phpstan, update phpunit, workflow --- .github/workflows/ci.yml | 11 +++++++++-- README.md | 6 ++++++ composer.json | 6 ++++-- ecs.php | 4 ++++ phpstan.neon | 4 ++++ phpunit.xml | 33 ++++++++++++--------------------- 6 files changed, 39 insertions(+), 25 deletions(-) create mode 100644 phpstan.neon diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aac0da5..668647e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ name: CI -on: [ push ] +on: [ push, pull_request ] jobs: check: @@ -19,8 +19,15 @@ jobs: - name: Check formatting run: ./vendor/bin/ecs check + - name: Analyse code + run: ./vendor/bin/phpstan + - name: Run tests uses: php-actions/phpunit@v3 + env: + XDEBUG_MODE: coverage with: - version: 8.5 + version: 10.5 php_version: 8.1 + php_extensions: "xdebug" + coverage_text: true diff --git a/README.md b/README.md index c77c1ca..05e10e4 100644 --- a/README.md +++ b/README.md @@ -42,3 +42,9 @@ Run the fixer before push. ```shell ./vendor/bin/ecs --fix ``` + +Run phpstan before push + +```shell +./vendor/bin/phpstan analyse +``` diff --git a/composer.json b/composer.json index 2545366..eefcf37 100644 --- a/composer.json +++ b/composer.json @@ -23,13 +23,15 @@ "require": { "php": "^8.1", "ext-dom": "*", + "ext-simplexml": "*", "moneyphp/money": "^4.3" }, "require-dev": { - "phpunit/phpunit": "^8.5", + "phpunit/phpunit": "^10.5", "mockery/mockery": "*", "mikey179/vfsstream": "^1.6", - "symplify/easy-coding-standard": "^12.0" + "symplify/easy-coding-standard": "^12.0", + "phpstan/phpstan": "^1.10" }, "autoload": { "psr-4": { diff --git a/ecs.php b/ecs.php index c31a2fe..36f8b7c 100644 --- a/ecs.php +++ b/ecs.php @@ -6,6 +6,8 @@ use PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer; use PhpCsFixer\Fixer\FunctionNotation\NativeFunctionInvocationFixer; use PhpCsFixer\Fixer\Import\NoUnusedImportsFixer; +use PhpCsFixer\Fixer\Phpdoc\PhpdocOrderFixer; +use PhpCsFixer\Fixer\Phpdoc\PhpdocTypesOrderFixer; use PhpCsFixer\Fixer\Strict\StrictComparisonFixer; use Symplify\EasyCodingStandard\Config\ECSConfig; use Symplify\EasyCodingStandard\ValueObject\Set\SetList; @@ -23,6 +25,8 @@ YodaStyleFixer::class, OrderedClassElementsFixer::class, NativeFunctionInvocationFixer::class, + PhpdocTypesOrderFixer::class, + PhpdocOrderFixer::class, ]); $ecsConfig->sets([ diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..6e451fa --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + level: 6 + paths: + - src diff --git a/phpunit.xml b/phpunit.xml index 87d71ae..ac43922 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,23 +1,14 @@ - - - - tests - - - - - - src - - + + + + + tests + + + + + src + + From 4f2d4ee1e5cc32fb100d8aa86e3679c46dbd17ea Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 01:08:12 +0100 Subject: [PATCH 02/36] cleanup Account.php --- src/Account.php | 54 +++++++++++----------------------------- src/AccountInterface.php | 17 ++++--------- tests/AccountTest.php | 38 ++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 51 deletions(-) create mode 100644 tests/AccountTest.php diff --git a/src/Account.php b/src/Account.php index 15fbd86..c591094 100644 --- a/src/Account.php +++ b/src/Account.php @@ -1,66 +1,42 @@ bankCode = $bankCode; - $this->accountNumber = $accountNumber; - $this->accountHolderName = $accountHolderName; + public function __construct( + private readonly BankCode $bankCode, + private readonly string $accountNumber, + private readonly string $accountHolderName = '', + ) { } - /** - * @return BankCode - */ - public function getBankCode() + public function getBankCode(): BankCode { return $this->bankCode; } - /** - * @return string - */ - public function getAccountNumber() + public function getAccountNumber(): string { return $this->accountNumber; } - /** - * @return string - */ - public function getAccountHolderName() + public function getAccountHolderName(): string { return $this->accountHolderName; } - public function toArray() + /** + * @return array + */ + public function toArray(): array { return [ 'bankCode' => $this->getBankCode()->getString(), - 'accountHolderName' => $this->getAccountHolderName(), 'accountNumber' => $this->getAccountNumber(), + 'accountHolderName' => $this->getAccountHolderName(), ]; } } diff --git a/src/AccountInterface.php b/src/AccountInterface.php index 6b46195..031ca7d 100644 --- a/src/AccountInterface.php +++ b/src/AccountInterface.php @@ -1,21 +1,14 @@ assertInstanceOf(BankCode::class, $sut->getBankCode()); + $this->assertSame($accountNumber, $sut->getAccountNumber()); + $this->assertSame($accountHolderName, $sut->getAccountHolderName()); + $this->assertSame([ + 'bankCode' => $bankCode, + 'accountNumber' => $accountNumber, + 'accountHolderName' => $accountHolderName, + ], $sut->toArray()); + } +} From e517c964ba254ca2ee84b307db1833ee9e900a4d Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 04:04:10 +0100 Subject: [PATCH 03/36] cleanup ExistingAccount --- src/ExistingAccount.php | 27 +++++++++++--------------- tests/ExistingAccountTest.php | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 tests/ExistingAccountTest.php diff --git a/src/ExistingAccount.php b/src/ExistingAccount.php index a042728..7e63a06 100644 --- a/src/ExistingAccount.php +++ b/src/ExistingAccount.php @@ -1,31 +1,26 @@ user = $account; - $this->uniqueAccountId = $uniqueAccountId; + return $this->account; } - public function getUniqueAccountId() + public function getUniqueAccountId(): int { return $this->uniqueAccountId; } diff --git a/tests/ExistingAccountTest.php b/tests/ExistingAccountTest.php new file mode 100644 index 0000000..7d8bad2 --- /dev/null +++ b/tests/ExistingAccountTest.php @@ -0,0 +1,36 @@ +assertSame($account, $sut->getAccount()); + $this->assertSame($uniqueAccountId, $sut->getUniqueAccountId()); + } +} From 3d87a6fedbb15850a89a38b3c2a2f7f036ae4e10 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 01:08:21 +0100 Subject: [PATCH 04/36] cleanup Balance.php --- src/Balance.php | 45 +++++++++++-------------------------------- tests/BalanceTest.php | 8 +++++++- 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/src/Balance.php b/src/Balance.php index 822a10d..fb15c3f 100644 --- a/src/Balance.php +++ b/src/Balance.php @@ -2,60 +2,37 @@ namespace AqBanking; +use DateTime; use Money\Money; class Balance implements Arrayable { - /** - * @var string - */ - private $type; - - /** - * @var \DateTime - */ - private $date; - - /** - * @var Money - */ - private $value; - public function __construct( - \DateTime $date, - Money $value, - string $type + private readonly DateTime $date, + private readonly Money $value, + private readonly string $type ) { - $this->date = $date; - $this->value = $value; - $this->type = $type; } - /** - * @return \DateTime - */ - public function getDate() + public function getDate(): DateTime { return $this->date; } - /** - * @return string - */ - public function getType() + public function getType(): string { return $this->type; } - /** - * @return \Money\Money - */ - public function getValue() + public function getValue(): Money { return $this->value; } - public function toArray() + /** + * @return array|string> + */ + public function toArray(): array { return [ 'type' => $this->getType(), diff --git a/tests/BalanceTest.php b/tests/BalanceTest.php index 95bc107..6cc3f0f 100644 --- a/tests/BalanceTest.php +++ b/tests/BalanceTest.php @@ -1,11 +1,17 @@ Date: Wed, 6 Dec 2023 01:00:29 +0100 Subject: [PATCH 05/36] cleanup Bank.php --- src/Bank.php | 45 ++++++++++----------------------------------- tests/BankTest.php | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 35 deletions(-) create mode 100644 tests/BankTest.php diff --git a/src/Bank.php b/src/Bank.php index 2d02fd7..9de7992 100644 --- a/src/Bank.php +++ b/src/Bank.php @@ -1,54 +1,29 @@ bankCode = $bankCode; - $this->hbciUrl = $hbciUrl; - $this->hbciVersion = $hbciVersion; + public function __construct( + private readonly BankCode $bankCode, + private readonly string $hbciUrl, + private readonly ?HbciVersion $hbciVersion = null + ) { } - /** - * @return BankCode - */ - public function getBankCode() + public function getBankCode(): BankCode { return $this->bankCode; } - /** - * @return string - */ - public function getHbciUrl() + public function getHbciUrl(): string { return $this->hbciUrl; } - /** - * @return HbciVersion|null - */ - public function getHbciVersion() + public function getHbciVersion(): ?HbciVersion { return $this->hbciVersion; } diff --git a/tests/BankTest.php b/tests/BankTest.php new file mode 100644 index 0000000..ab6bb2c --- /dev/null +++ b/tests/BankTest.php @@ -0,0 +1,35 @@ +assertSame($bankCode, $sut->getBankCode()); + $this->assertSame($hbciVersion, $sut->getHbciVersion()); + $this->assertSame($hbciUrl, $sut->getHbciUrl()); + } +} From 7c7110da580e1d8852f683269ab2d9f3463ef10d Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 01:08:27 +0100 Subject: [PATCH 06/36] cleanup BankCode.php --- src/BankCode.php | 21 ++++++--------------- tests/BankCodeTest.php | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 tests/BankCodeTest.php diff --git a/src/BankCode.php b/src/BankCode.php index 846d6ca..3a54307 100644 --- a/src/BankCode.php +++ b/src/BankCode.php @@ -1,26 +1,17 @@ bankCode = $bankCode; + public function __construct( + private readonly string $bankCode + ) { } - /** - * @return string - */ - public function getString() + public function getString(): string { return $this->bankCode; } diff --git a/tests/BankCodeTest.php b/tests/BankCodeTest.php new file mode 100644 index 0000000..3e4a611 --- /dev/null +++ b/tests/BankCodeTest.php @@ -0,0 +1,22 @@ +assertSame($bankCode, $sut->getString()); + } +} From 205c2d5a4246b7a5fb236ef69aef8de12e33119a Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 01:08:35 +0100 Subject: [PATCH 07/36] cleanup ContextFile.php --- src/ContextFile.php | 21 ++++++--------------- tests/ContextFileTest.php | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 tests/ContextFileTest.php diff --git a/src/ContextFile.php b/src/ContextFile.php index a6ebee8..e4c5e80 100644 --- a/src/ContextFile.php +++ b/src/ContextFile.php @@ -1,26 +1,17 @@ path = $path; + public function __construct( + private readonly string $path + ) { } - /** - * @return string - */ - public function getPath() + public function getPath(): string { return $this->path; } diff --git a/tests/ContextFileTest.php b/tests/ContextFileTest.php new file mode 100644 index 0000000..e3f3e78 --- /dev/null +++ b/tests/ContextFileTest.php @@ -0,0 +1,21 @@ +assertSame($path, $sut->getPath()); + } +} From 72a3d08d650230c4e2447a6a71897f4931885566 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 01:02:11 +0100 Subject: [PATCH 08/36] cleanup ContextXmlRenderer.php --- src/ContextXmlRenderer.php | 74 ++++++++++++++------------------ tests/ContextXmlRendererTest.php | 23 ++++++---- 2 files changed, 48 insertions(+), 49 deletions(-) diff --git a/src/ContextXmlRenderer.php b/src/ContextXmlRenderer.php index a38ac7d..fea5b89 100644 --- a/src/ContextXmlRenderer.php +++ b/src/ContextXmlRenderer.php @@ -1,38 +1,40 @@ domDocument = $domDocument; - $this->xPath = new \DOMXPath($domDocument); + $this->xPath = new DOMXPath($domDocument); $this->moneyElementRenderer = new MoneyElementRenderer(); } /** - * @return Transaction[] + * @throws Exception + * + * @return array */ - public function getTransactions() + public function getTransactions(): array { $transactionNodes = $this->domDocument->getElementsByTagName('transaction'); $transactions = []; @@ -90,38 +92,34 @@ public function getTransactions() } /** - * @return Balance + * @throws Exception + * + * @return array */ - public function getBalances() + public function getBalances(): array { $balanceNodes = $this->domDocument->getElementsByTagName('balance'); $balances = []; - /** - * @var DOMElement $balanceNode - */ foreach ($balanceNodes as $balanceNode) { + /** @var DOMElement $balanceNode */ $date = $this->renderDateElement($this->xPath->query('date', $balanceNode)->item(0)); $value = $this->renderMoneyElement($this->xPath->query('value', $balanceNode)->item(0)); $type = $this->renderSimpleTextElement($this->xPath->query('type', $balanceNode)); - $balances[] = new Balance($date, $value, $type); + $balances[] = new Balance(date: $date, value: $value, type: $type); } return $balances; } - /** - * @throws \RuntimeException - * @return string - */ - private function renderMultiLineElement(\DOMNodeList $nodes) + private function renderMultiLineElement(DOMNodeList $nodes): string { $lines = []; foreach ($nodes as $node) { $line = trim($node->nodeValue); if (false !== strpos($line, '|')) { - throw new \RuntimeException('Unexpected character'); + throw new RuntimeException('Unexpected character'); } $lines[] = $line; } @@ -129,43 +127,37 @@ private function renderMultiLineElement(\DOMNodeList $nodes) return implode('|', $lines); } - /** - * @throws \RuntimeException - * @return \DateTime - */ - private function renderDateElement(\DOMNode $node = null) + private function renderDateElement(DOMNode $node = null): ?DateTime { if (! $node) { return null; } $dateElement = $this->xPath->query('value', $node)->item(0); - $date = \DateTime::createFromFormat( + $date = DateTime::createFromFormat( 'Ymd', $dateElement->nodeValue, new \DateTimeZone('UTC') ); $date->setTime(0, 0, 0); + return $date; } /** - * @return Money - * @throws \Exception + * @throws RuntimeException */ - private function renderMoneyElement(\DOMNode $node) + private function renderMoneyElement(DOMNode $node): Money { $value = $this->renderSimpleTextElement($this->xPath->query('value', $node)); $pair = explode(':', $value); $valueString = $pair[0]; $currencyString = empty($pair[1]) ? 'EUR' : $pair[1]; + return $this->moneyElementRenderer->render($valueString, $currencyString); } - /** - * @return string - */ - private function renderSimpleTextElement(\DOMNodeList $valueNodes) + private function renderSimpleTextElement(DOMNodeList $valueNodes): string { return trim($valueNodes->item(0)->nodeValue); } diff --git a/tests/ContextXmlRendererTest.php b/tests/ContextXmlRendererTest.php index 4ff171f..d967a37 100644 --- a/tests/ContextXmlRendererTest.php +++ b/tests/ContextXmlRendererTest.php @@ -1,20 +1,27 @@ markTestSkipped('temporarily skipped due the unclear behaviour of Account<>getTransaction'); @@ -42,9 +49,9 @@ public function can_render_transfers() } /** - * @test + * @throws Exception */ - public function can_render_transactions() + public function testCanRenderTransactions() { $this->markTestSkipped('temporarily skipped due the unclear behaviour of Account<>getTransaction'); @@ -72,9 +79,9 @@ public function can_render_transactions() } /** - * @test + * @throws Exception */ - public function throws_exception_if_data_contains_reserved_char() + public function testThrowsExceptionIfDataContainsReservedChar() { $fixture = file_get_contents(__DIR__ . '/fixtures/test_context_file_transactions_with_reserved_char.xml'); $domDocument = new \DOMDocument(); @@ -87,9 +94,9 @@ public function throws_exception_if_data_contains_reserved_char() } /** - * @test + * @throws Exception */ - public function throws_exception_if_amount_is_malformed() + public function testThrowsExceptionIfAmountIsMalformed() { $fixture = file_get_contents(__DIR__ . '/fixtures/test_context_file_transactions_with_malformed_amount.xml'); $domDocument = new \DOMDocument(); From a9f44a281bce2b0c026653b7da72a01b83bca00e Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 02:31:49 +0100 Subject: [PATCH 09/36] cleanup User.php --- src/User.php | 46 ++++++++++------------------------------------ tests/UserTest.php | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 36 deletions(-) create mode 100644 tests/UserTest.php diff --git a/src/User.php b/src/User.php index c664683..6815252 100644 --- a/src/User.php +++ b/src/User.php @@ -1,55 +1,29 @@ userId = $userId; - $this->userName = $userName; - $this->bank = $bank; + public function __construct( + private readonly string $userId, + private readonly string $userName, + private readonly Bank $bank + ) { } - /** - * @return string - */ - public function getUserId() + public function getUserId(): string { return $this->userId; } - /** - * @return string - */ - public function getUserName() + public function getUserName(): string { return $this->userName; } - /** - * @return Bank - */ - public function getBank() + public function getBank(): Bank { return $this->bank; } diff --git a/tests/UserTest.php b/tests/UserTest.php new file mode 100644 index 0000000..1223644 --- /dev/null +++ b/tests/UserTest.php @@ -0,0 +1,41 @@ +assertSame($userId, $sut->getUserId()); + $this->assertSame($userName, $sut->getUserName()); + $this->assertSame($bank, $sut->getBank()); + } +} From e6a8d6de7f3e827af2cc5970abe15f1856205c28 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 01:03:34 +0100 Subject: [PATCH 10/36] cleanup ExistingUser.php --- src/ExistingUser.php | 41 +++++++++---------------------- tests/ExistingUserTest.php | 49 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 tests/ExistingUserTest.php diff --git a/src/ExistingUser.php b/src/ExistingUser.php index 39ded3a..ec8d15e 100644 --- a/src/ExistingUser.php +++ b/src/ExistingUser.php @@ -1,55 +1,36 @@ user = $user; - $this->uniqueUserId = $uniqueUserId; + public function __construct( + private readonly User $user, + private readonly int $uniqueUserId + ) { } - public function getUniqueUserId() + public function getUniqueUserId(): int { return $this->uniqueUserId; } - /** - * @return string - */ - public function getUserId() + public function getUserId(): string { return $this->user->getUserId(); } - /** - * @return string - */ - public function getUserName() + public function getUserName(): string { return $this->user->getUserName(); } - /** - * @return Bank - */ - public function getBank() + public function getBank(): Bank { return $this->user->getBank(); } diff --git a/tests/ExistingUserTest.php b/tests/ExistingUserTest.php new file mode 100644 index 0000000..01c7e8f --- /dev/null +++ b/tests/ExistingUserTest.php @@ -0,0 +1,49 @@ +assertSame($bank, $sut->getBank()); + $this->assertSame($userName, $sut->getUserName()); + $this->assertSame($userId, $sut->getUserId()); + $this->assertSame($uniqueUserId, $sut->getUniqueUserId()); + } +} From bb8cb7645b077eb5381d8109ecd611a5ceb6e8da Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 00:06:00 +0100 Subject: [PATCH 11/36] cleanup Arrayable.php --- src/Arrayable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Arrayable.php b/src/Arrayable.php index 60d1ddb..8ce5049 100644 --- a/src/Arrayable.php +++ b/src/Arrayable.php @@ -4,5 +4,5 @@ interface Arrayable { - public function toArray(); + public function toArray(): array; } From 70e742d1d68a8a0ee87bc5dc06f6f197c33b9071 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 01:08:46 +0100 Subject: [PATCH 12/36] cleanup HbciVersion.php --- src/HbciVersion.php | 39 ++++++++------------------------ tests/HbciVersionTest.php | 47 ++++++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 51 deletions(-) diff --git a/src/HbciVersion.php b/src/HbciVersion.php index 73b614a..2465014 100644 --- a/src/HbciVersion.php +++ b/src/HbciVersion.php @@ -1,33 +1,18 @@ versionNumber = $versionNumber; - $this->methodCode = $methodCode; + public function __construct( + private readonly string $versionNumber, + private readonly ?string $methodCode = null + ) { } - /** - * @return bool - */ - public function isHigherThan(HbciVersion $hbciVersion = null) + public function isHigherThan(?HbciVersion $hbciVersion = null): bool { if (null === $hbciVersion) { return true; @@ -36,18 +21,12 @@ public function isHigherThan(HbciVersion $hbciVersion = null) return (version_compare($this->versionNumber, $hbciVersion->versionNumber) > 0); } - /** - * @return string|null - */ - public function getMethodCode() + public function getMethodCode(): ?string { return $this->methodCode; } - /** - * @return string - */ - public function getVersionNumber() + public function getVersionNumber(): string { return $this->versionNumber; } diff --git a/tests/HbciVersionTest.php b/tests/HbciVersionTest.php index 998f2e5..a53d42e 100644 --- a/tests/HbciVersionTest.php +++ b/tests/HbciVersionTest.php @@ -1,16 +1,36 @@ assertSame($versionNumber, $sut->getVersionNumber()); + $this->assertNull($sut->getMethodCode()); + } + + public function testHbciVersionMethodeCode(): void + { + $methodCode = '1234'; + + $sut = new HbciVersion('1.2.3', $methodCode); + + $this->assertSame($methodCode, $sut->getMethodCode()); + } + + public function testCanTellIfHigherVersionThanOtherInstance(): void { $sut = new HbciVersion('1.2.3'); @@ -24,25 +44,10 @@ public function can_tell_if_higher_version_than_other_instance() $this->assertFalse($sut->isHigherThan($higherVersion)); } - /** - * @test - */ - public function is_higher_than_null() + public function testIsHigherThanNull(): void { $sut = new HbciVersion('1.2.3'); - $this->assertTrue($sut->isHigherThan(null)); - } - - /** - * @test - */ - public function can_have_method_code() - { - $methodCode = '1234'; - - $sut = new HbciVersion('1.2.3', $methodCode); - - $this->assertEquals($methodCode, $sut->getMethodCode()); + $this->assertTrue($sut->isHigherThan()); } } From e5688f360efef9af384d5e546aeff652c3088bf9 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 01:29:11 +0100 Subject: [PATCH 13/36] cleanup Transaction.php --- src/Transaction.php | 135 +++++++++----------------------------- tests/TransactionTest.php | 12 ++-- 2 files changed, 38 insertions(+), 109 deletions(-) diff --git a/src/Transaction.php b/src/Transaction.php index bfb5ec3..7e36f16 100644 --- a/src/Transaction.php +++ b/src/Transaction.php @@ -1,151 +1,76 @@ date = $date; - $this->localAccount = $localAccount; - $this->purpose = $purpose; - $this->remoteAccount = $remoteAccount; - $this->type = $type; - $this->value = $value; - $this->valutaDate = $valutaDate; - $this->primaNota = $primaNota; - $this->customerReference = $customerReference; } - /** - * @return \DateTime - */ - public function getDate() + public function getLocalAccount(): Account { - return $this->date; + return $this->localAccount; } - /** - * @return \AqBanking\Account - */ - public function getLocalAccount() + public function getRemoteAccount(): Account { - return $this->localAccount; + return $this->remoteAccount; } - /** - * @return string - */ - public function getPurpose() + public function getDate(): DateTime { - return $this->purpose; + return $this->date; } - /** - * @return \AqBanking\Account - */ - public function getRemoteAccount() + public function getPurpose(): string { - return $this->remoteAccount; + return $this->purpose; } - /** - * @return \Money\Money - */ - public function getValue() + public function getValue(): Money { return $this->value; } - /** - * @return \DateTime - */ - public function getValutaDate() + public function getValutaDate(): ?DateTime { return $this->valutaDate; } - /** - * @return string - */ - public function getPrimaNota() + public function getPrimaNota(): string { return $this->primaNota; } - /** - * @return string - */ - public function getCustomerReference() + public function getCustomerReference(): string { return $this->customerReference; } - /** - * @return string - */ - public function getType() + public function getType(): string { return $this->type; } - public function toArray() + /** + * @return array + */ + public function toArray(): array { return [ 'date' => $this->getDate()->format('Y-m-d'), @@ -155,7 +80,7 @@ public function toArray() 'type' => $this->getType(), 'value' => [ 'amount' => $this->getValue()->getAmount(), - 'currency' => $this->getValue()->getCurrency()->getName(), + 'currency' => $this->getValue()->getCurrency()->getCode(), 'priceUnit' => 100, ], 'valutaDate' => $this->getValutaDate() ? $this->getValutaDate()->format('Y-m-d') : null, diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php index 491ae0b..336915a 100644 --- a/tests/TransactionTest.php +++ b/tests/TransactionTest.php @@ -1,5 +1,7 @@ Date: Wed, 6 Dec 2023 01:50:27 +0100 Subject: [PATCH 14/36] cleanup MoneyElementRender.php --- .../MoneyElementRenderer.php | 28 +++++++--------- .../MoneyElementRendererTest.php | 33 +++++++++++-------- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/ContentXmlRenderer/MoneyElementRenderer.php b/src/ContentXmlRenderer/MoneyElementRenderer.php index cb92939..c0774a6 100644 --- a/src/ContentXmlRenderer/MoneyElementRenderer.php +++ b/src/ContentXmlRenderer/MoneyElementRenderer.php @@ -1,5 +1,7 @@ extractAmountAndDivisorAsString($value); @@ -57,10 +54,11 @@ private function normalizeAmount($value) } /** - * @return array - * @throws \AqBanking\RuntimeException + * @throws RuntimeException + * + * @return string[] */ - private function extractAmountAndDivisorAsString($amountString) + private function extractAmountAndDivisorAsString(string $amountString): array { $matches = []; if (preg_match('/^(?P(-){0,1}\d+)\/(?P1(0)*)$/', $amountString, $matches)) { @@ -80,11 +78,7 @@ private function extractAmountAndDivisorAsString($amountString) throw new RuntimeException("Unexpected amount input '$amountString'"); } - /** - * @param mixed $normalizedAmount - * @return bool - */ - private function isNormalizedValueBiassed($normalizedAmount) + private function isNormalizedValueBiassed(float|int $normalizedAmount): bool { return 0.00 !== fmod($normalizedAmount, 1); } diff --git a/tests/ContentXmlRenderer/MoneyElementRendererTest.php b/tests/ContentXmlRenderer/MoneyElementRendererTest.php index 6564d9c..659071c 100644 --- a/tests/ContentXmlRenderer/MoneyElementRendererTest.php +++ b/tests/ContentXmlRenderer/MoneyElementRendererTest.php @@ -1,17 +1,22 @@ Date: Wed, 6 Dec 2023 02:47:50 +0100 Subject: [PATCH 15/36] cleanup PinFile --- src/PinFile/PinFile.php | 24 ++++------- src/PinFile/PinFileCreator.php | 36 ++++++---------- src/PinFile/PinFileInterface.php | 12 ++---- tests/{ => PinFile}/PinFileCreatorTest.php | 27 ++++++------ tests/PinFile/PinFileTest.php | 49 ++++++++++++++++++++++ 5 files changed, 88 insertions(+), 60 deletions(-) rename tests/{ => PinFile}/PinFileCreatorTest.php (81%) create mode 100644 tests/PinFile/PinFileTest.php diff --git a/src/PinFile/PinFile.php b/src/PinFile/PinFile.php index 8ed57aa..d1c6e6a 100644 --- a/src/PinFile/PinFile.php +++ b/src/PinFile/PinFile.php @@ -1,28 +1,20 @@ user = $user; - $this->dir = $dir; + public function __construct( + private readonly string $dir, + private readonly User $user + ) { } - public function getFileName() + public function getFileName(): string { return sprintf( 'pinfile_%s_%s', @@ -31,7 +23,7 @@ public function getFileName() ); } - public function getPath() + public function getPath(): string { return $this->dir . '/' . $this->getFileName(); } diff --git a/src/PinFile/PinFileCreator.php b/src/PinFile/PinFileCreator.php index c86a731..4b562be 100644 --- a/src/PinFile/PinFileCreator.php +++ b/src/PinFile/PinFileCreator.php @@ -1,26 +1,23 @@ pinFileDir = $pinFileDir; + public function __construct( + private readonly string $pinFileDir + ) { } /** - * @param string $pin - * @return PinFileInterface + * @throws InvalidArgumentException */ - public function createFile($pin, User $user) + public function createFile(string $pin, User $user): PinFileInterface { $pinFileDir = $this->pinFileDir; @@ -40,26 +37,19 @@ public function createFile($pin, User $user) } /** - * @param string $pinFileDir - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ - private function assertIsWritableDir($pinFileDir) + private function assertIsWritableDir(string $pinFileDir): void { if (! is_dir($pinFileDir)) { - throw new \InvalidArgumentException("PIN file dir '$pinFileDir' is not a directory"); + throw new InvalidArgumentException("PIN file dir '$pinFileDir' is not a directory"); } if (! is_writable($pinFileDir)) { - throw new \InvalidArgumentException("PIN file dir '$pinFileDir' is not writable"); + throw new InvalidArgumentException("PIN file dir '$pinFileDir' is not writable"); } } - /** - * @param string $pin - * @param string $userId - * @param string $bankCodeString - * @return string - */ - private function createFileContent($pin, $userId, $bankCodeString) + private function createFileContent(string $pin, string $userId, string $bankCodeString): string { // The comments and line breaks seem to be mandatory for AqBanking to parse the file return '# This is a PIN file to be used with AqBanking' . PHP_EOL diff --git a/src/PinFile/PinFileInterface.php b/src/PinFile/PinFileInterface.php index 0a777ba..1c02cb2 100644 --- a/src/PinFile/PinFileInterface.php +++ b/src/PinFile/PinFileInterface.php @@ -1,16 +1,12 @@ expectException('\InvalidArgumentException'); - $this->expectErrorMessage('is not a directory'); + $this->expectExceptionMessage('is not a directory'); $sut->createFile('12345', $this->createDummyUser()); } /** * @test */ - public function throws_exception_if_given_pin_file_dir_is_not_writable() + public function testDirIsNotWritable(): void { $pinFileDir = 'someDir'; vfsStream::setup($pinFileDir, 0555); @@ -70,14 +74,11 @@ public function throws_exception_if_given_pin_file_dir_is_not_writable() $sut = new PinFileCreator($pinFileDirMock); $this->expectException('\InvalidArgumentException'); - $this->expectErrorMessage('is not writable'); + $this->expectExceptionMessage('is not writable'); $sut->createFile('12345', $this->createDummyUser()); } - /** - * @return User - */ - private function createDummyUser() + private function createDummyUser(): User { return new User('mustermann', 'Max Mustermann', new Bank(new BankCode('12345678'), 'https://hbci.example.com')); } diff --git a/tests/PinFile/PinFileTest.php b/tests/PinFile/PinFileTest.php new file mode 100644 index 0000000..e510b61 --- /dev/null +++ b/tests/PinFile/PinFileTest.php @@ -0,0 +1,49 @@ +assertSame($expectedFileName, $sut->getFileName()); + $this->assertSame(implode('/', [$dir, $expectedFileName]), $sut->getPath()); + } +} From 4c92e367240808d11eddf5a3bc2dcf29720c66cd Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 11:20:14 +0100 Subject: [PATCH 16/36] cleanup AddUserCommand --- src/Command/AddUserCommand.php | 4 +++- tests/Command/AddUserCommandTest.php | 30 +++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/Command/AddUserCommand.php b/src/Command/AddUserCommand.php index 12b04eb..f4a5f6c 100644 --- a/src/Command/AddUserCommand.php +++ b/src/Command/AddUserCommand.php @@ -1,5 +1,7 @@ pathToAqHBCIToolBinary diff --git a/tests/Command/AddUserCommandTest.php b/tests/Command/AddUserCommandTest.php index 8f908c6..cae517e 100644 --- a/tests/Command/AddUserCommandTest.php +++ b/tests/Command/AddUserCommandTest.php @@ -1,16 +1,34 @@ assertTrue(true); } - public function testThrowsExceptionIfUserAlreadyExists() + /** + * @throws DefectiveResultException + */ + public function testThrowsExceptionIfUserAlreadyExists(): void { $userId = 'mustermann'; $userName = 'Max Mustermann'; @@ -78,7 +99,10 @@ public function testThrowsExceptionIfUserAlreadyExists() $sut->execute(new User($userId, $userName, new Bank(new BankCode($bankCodeString), $hbciUrl))); } - public function testThrowsExceptionOnUnexpectedResult() + /** + * @throws UserAlreadyExistsException + */ + public function testThrowsExceptionOnUnexpectedResult(): void { $userId = 'mustermann'; $userName = 'Max Mustermann'; From 7d6aeb2cf4ef5957c765d7783cd17c6b1119cf11 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 11:21:12 +0100 Subject: [PATCH 17/36] cleanup AbstractCommand --- src/Command/AbstractCommand.php | 44 +++++++++------------------------ 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/src/Command/AbstractCommand.php b/src/Command/AbstractCommand.php index 916facc..3c1a6c2 100644 --- a/src/Command/AbstractCommand.php +++ b/src/Command/AbstractCommand.php @@ -1,62 +1,40 @@ shellCommandExecutor = $shellCommandExecutor; } - /** - * @param string $binaryPath - */ - public function setPathToAqBankingCLIBinary($binaryPath) + public function setPathToAqBankingCLIBinary(string $binaryPath): void { $this->pathToAqBankingCLIBinary = $binaryPath; } - /** - * @param string $pathToAqBankingConfigBinary - */ - public function setPathToAqBankingConfigBinary($pathToAqBankingConfigBinary) + public function setPathToAqBankingConfigBinary(string $pathToAqBankingConfigBinary): void { $this->pathToAqBankingConfigBinary = $pathToAqBankingConfigBinary; } - /** - * @param string $pathToAqHBCIToolBinary - */ - public function setPathToAqHBCIToolBinary($pathToAqHBCIToolBinary) + public function setPathToAqHBCIToolBinary(string $pathToAqHBCIToolBinary): void { $this->pathToAqHBCIToolBinary = $pathToAqHBCIToolBinary; } - /** - * @return ShellCommandExecutor - */ - protected function getShellCommandExecutor() + protected function getShellCommandExecutor(): ShellCommandExecutor { if (null === $this->shellCommandExecutor) { $this->shellCommandExecutor = new ShellCommandExecutor(); From 7809cd82fddb0a9661e8f816cbd43a3670b5d291 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 23:45:37 +0100 Subject: [PATCH 18/36] cleanup Result --- .../DefectiveResultException.php | 28 +++++------- src/Command/ShellCommandExecutor/Result.php | 43 ++++++------------ .../ShellCommandExecutor/ResultAnalyzer.php | 18 ++++---- .../DefectiveResultExceptionTest.php | 44 +++++++++++++++++++ .../ResultAnalyzerTest.php | 23 ++++++++-- .../ShellCommandExecutor/ResultTest.php | 24 ++++++++++ 6 files changed, 121 insertions(+), 59 deletions(-) create mode 100644 tests/Command/ShellCommandExecutor/DefectiveResultExceptionTest.php create mode 100644 tests/Command/ShellCommandExecutor/ResultTest.php diff --git a/src/Command/ShellCommandExecutor/DefectiveResultException.php b/src/Command/ShellCommandExecutor/DefectiveResultException.php index f89b846..5beae26 100644 --- a/src/Command/ShellCommandExecutor/DefectiveResultException.php +++ b/src/Command/ShellCommandExecutor/DefectiveResultException.php @@ -1,20 +1,18 @@ shellCommand = $shellCommand; } - /** - * @return \AqBanking\Command\ShellCommandExecutor\Result - */ - public function getResult() + public function getResult(): ?Result { return $this->result; } - /** - * @return string - */ - public function getShellCommand() + public function getShellCommand(): string { return $this->shellCommand; } diff --git a/src/Command/ShellCommandExecutor/Result.php b/src/Command/ShellCommandExecutor/Result.php index c76b741..ee9aafa 100644 --- a/src/Command/ShellCommandExecutor/Result.php +++ b/src/Command/ShellCommandExecutor/Result.php @@ -1,54 +1,39 @@ $output + * @param array $errors */ - private $returnVar; - - /** - * @param int $returnVar - */ - public function __construct(array $output, array $errors, $returnVar) - { - $this->output = $output; - $this->errors = $errors; - $this->returnVar = $returnVar; + public function __construct( + private readonly array $output, + private readonly array $errors, + private readonly int $returnVar + ) { } /** - * @return array + * @return array */ - public function getOutput() + public function getOutput(): array { return $this->output; } /** - * @return array + * @return array */ - public function getErrors() + public function getErrors(): array { return $this->errors; } - /** - * @return int - */ - public function getReturnVar() + public function getReturnVar(): int { return $this->returnVar; } diff --git a/src/Command/ShellCommandExecutor/ResultAnalyzer.php b/src/Command/ShellCommandExecutor/ResultAnalyzer.php index 9ace097..fdefa8e 100644 --- a/src/Command/ShellCommandExecutor/ResultAnalyzer.php +++ b/src/Command/ShellCommandExecutor/ResultAnalyzer.php @@ -1,10 +1,15 @@ + */ + private array $expectedOutputRegexes = [ '/Automatically accepting valid new certificate/', '/Automatically accepting certificate/', '/The TLS connection was non-properly terminated./', // it usually automatically restarts, so no error @@ -41,21 +46,18 @@ class ResultAnalyzer '/Selecting PAIN format.*$/', ]; - /** - * @return bool - */ - public function isDefectiveResult(Result $result) + public function isDefectiveResult(Result $result): bool { if (0 !== $result->getReturnVar()) { return true; } - if ($error = $this->resultHasErrors($result)) { + if ($this->resultHasErrors($result)) { return true; } return false; } - private function resultHasErrors(Result $result) + private function resultHasErrors(Result $result): bool { if (1 === \count($result->getErrors()) && preg_match('/accepting valid new certificate/', $result->getErrors()[0])) { // When calling getsysid with wrong PIN, we don't get any error message. @@ -71,7 +73,7 @@ private function resultHasErrors(Result $result) return false; } - private function isErrorMessage($line) + private function isErrorMessage(string $line): bool { foreach ($this->expectedOutputRegexes as $regex) { if (preg_match($regex, $line)) { diff --git a/tests/Command/ShellCommandExecutor/DefectiveResultExceptionTest.php b/tests/Command/ShellCommandExecutor/DefectiveResultExceptionTest.php new file mode 100644 index 0000000..48c5a29 --- /dev/null +++ b/tests/Command/ShellCommandExecutor/DefectiveResultExceptionTest.php @@ -0,0 +1,44 @@ +assertInstanceOf(Exception::class, $sut); + $this->assertSame($message . + ' - Command: ' . $shellCommand . + ' - Errors: ' . implode(PHP_EOL, $result->getErrors()), $sut->getMessage()); + $this->assertSame($result, $sut->getResult()); + $this->assertSame($shellCommand, $sut->getShellCommand()); + } +} diff --git a/tests/Command/ShellCommandExecutor/ResultAnalyzerTest.php b/tests/Command/ShellCommandExecutor/ResultAnalyzerTest.php index c1c0ab4..9b77c10 100644 --- a/tests/Command/ShellCommandExecutor/ResultAnalyzerTest.php +++ b/tests/Command/ShellCommandExecutor/ResultAnalyzerTest.php @@ -1,14 +1,20 @@ assertFalse($sut->isDefectiveResult($result)); } - public function testRecognizesErrorByResultVar() + public function testRecognizesErrorByResultVar(): void { $result = new Result([], [], 1); @@ -26,7 +32,7 @@ public function testRecognizesErrorByResultVar() $this->assertTrue($sut->isDefectiveResult($result)); } - public function testCanTellCorrectPollResult() + public function testCanTellCorrectPollResult(): void { $errors = [ '5:2013/07/22 11-32-32:aqbanking(39873):abgui.c: 182: Automatically accepting valid new certificate [40:BD:81:8B:76:27:1A:58:5C:B7:68:46:1E:CB:F2:FD]', @@ -43,7 +49,7 @@ public function testCanTellCorrectPollResult() $this->assertFalse($sut->isDefectiveResult($result)); } - public function testCanTellDefectivePollResult() + public function testCanTellDefectivePollResult(): void { $errors = [ '5:2013/07/22 11-31-44:aqbanking(39859):abgui.c: 182: Automatically accepting valid new certificate [40:BD:81:8B:76:27:1A:58:5C:B7:68:46:1E:CB:F2:FD]', @@ -57,4 +63,13 @@ public function testCanTellDefectivePollResult() $this->assertTrue($sut->isDefectiveResult($result)); } + + public function testGetsysidError(): void + { + $result = new Result([], ['accepting valid new certificate'], 0); + + $sut = new ResultAnalyzer(); + + $this->assertTrue($sut->isDefectiveResult($result)); + } } diff --git a/tests/Command/ShellCommandExecutor/ResultTest.php b/tests/Command/ShellCommandExecutor/ResultTest.php new file mode 100644 index 0000000..1596284 --- /dev/null +++ b/tests/Command/ShellCommandExecutor/ResultTest.php @@ -0,0 +1,24 @@ +assertCount(2, $sut->getOutput()); + $this->assertCount(1, $sut->getErrors()); + + $this->assertSame(0, $sut->getReturnVar()); + } +} From b6019711338f98de7b0d8a8946c4a0fff6d2698c Mon Sep 17 00:00:00 2001 From: grummbeer Date: Wed, 6 Dec 2023 23:55:56 +0100 Subject: [PATCH 19/36] cleanup ShellCommandExecuter --- src/Command/ShellCommandExecutor.php | 6 ++++-- tests/Command/ShellCommandExecutorTest.php | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Command/ShellCommandExecutor.php b/src/Command/ShellCommandExecutor.php index 01a528e..b0d6636 100644 --- a/src/Command/ShellCommandExecutor.php +++ b/src/Command/ShellCommandExecutor.php @@ -1,5 +1,7 @@ assertEquals(0, $result->getReturnVar()); } - public function testCanTellAboutErrors() + public function testCanTellAboutErrors(): void { $sut = new ShellCommandExecutor(); From a03f78b8680d6adbb3e05ea84cd08384441ab8a3 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 00:24:28 +0100 Subject: [PATCH 20/36] cleanup CheckAqBankingCommand --- src/Command/CheckAqBankingCommand.php | 18 ++++++++++--- tests/Command/CheckAqBankingCommandTest.php | 30 ++++++++++++++++++--- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/Command/CheckAqBankingCommand.php b/src/Command/CheckAqBankingCommand.php index b66bbea..49d0644 100644 --- a/src/Command/CheckAqBankingCommand.php +++ b/src/Command/CheckAqBankingCommand.php @@ -1,5 +1,7 @@ assertAqBankingResponds(); $this->assertAqBankingIsAppropriateVersion(); } - private function assertAqBankingResponds() + /** + * @throws AqBankingNotRespondingException + */ + private function assertAqBankingResponds(): void { $shellCommand = $this->pathToAqBankingCLIBinary . ' --help'; $result = $this->getShellCommandExecutor()->execute($shellCommand); @@ -23,7 +32,10 @@ private function assertAqBankingResponds() } } - private function assertAqBankingIsAppropriateVersion() + /** + * @throws AqBankingVersionTooOldException + */ + private function assertAqBankingIsAppropriateVersion(): void { $minVersion = '5.0.24'; $shellCommand = $this->pathToAqBankingConfigBinary . ' --vstring'; diff --git a/tests/Command/CheckAqBankingCommandTest.php b/tests/Command/CheckAqBankingCommandTest.php index f43b4f7..02a8c63 100644 --- a/tests/Command/CheckAqBankingCommandTest.php +++ b/tests/Command/CheckAqBankingCommandTest.php @@ -1,14 +1,27 @@ assertTrue(true); } - public function testCanTellIfAqBankingIsNotInstalled() + /** + * @throws AqBankingVersionTooOldException + */ + public function testCanTellIfAqBankingIsNotInstalled(): void { $shellCommandExecutorMock = \Mockery::mock('AqBanking\Command\ShellCommandExecutor'); $shellCommandExecutorMock @@ -42,7 +58,10 @@ public function testCanTellIfAqBankingIsNotInstalled() $sut->execute(); } - public function testCanHandleVeryOldAqBankingVersionWithoutAqBankingConfig() + /** + * @throws AqBankingNotRespondingException + */ + public function testCanHandleVeryOldAqBankingVersionWithoutAqBankingConfig(): void { $shellCommandExecutorMock = \Mockery::mock('AqBanking\Command\ShellCommandExecutor'); $shellCommandExecutorMock @@ -60,7 +79,10 @@ public function testCanHandleVeryOldAqBankingVersionWithoutAqBankingConfig() $sut->execute(); } - public function testCanTellIfAqBankingVersionIsTooOld() + /** + * @throws AqBankingNotRespondingException + */ + public function testCanTellIfAqBankingVersionIsTooOld(): void { $shellCommandExecutorMock = \Mockery::mock('AqBanking\Command\ShellCommandExecutor'); $shellCommandExecutorMock From 98be58d2ef6113ef333f7b73e4aa37061270a3fd Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 00:29:58 +0100 Subject: [PATCH 21/36] cleanup AddUserFlagsCommand --- src/Command/AddUserFlagsCommand.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Command/AddUserFlagsCommand.php b/src/Command/AddUserFlagsCommand.php index c9d799a..d2347b2 100644 --- a/src/Command/AddUserFlagsCommand.php +++ b/src/Command/AddUserFlagsCommand.php @@ -1,11 +1,12 @@ pathToAqHBCIToolBinary From fd9c6a86da10b25ff40702966ab0e5141f2af89c Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 01:29:58 +0100 Subject: [PATCH 22/36] cleanup AddAccountFlagsCommandTest --- src/Command/AddAccountFlagsCommand.php | 7 +- tests/Command/AddAccountFlagsCommandTest.php | 69 ++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 tests/Command/AddAccountFlagsCommandTest.php diff --git a/src/Command/AddAccountFlagsCommand.php b/src/Command/AddAccountFlagsCommand.php index 3fc4ec3..c40b5c1 100644 --- a/src/Command/AddAccountFlagsCommand.php +++ b/src/Command/AddAccountFlagsCommand.php @@ -1,5 +1,7 @@ pathToAqHBCIToolBinary diff --git a/tests/Command/AddAccountFlagsCommandTest.php b/tests/Command/AddAccountFlagsCommandTest.php new file mode 100644 index 0000000..747d2ec --- /dev/null +++ b/tests/Command/AddAccountFlagsCommandTest.php @@ -0,0 +1,69 @@ +shouldReceive('execute') + ->with(sprintf('aqhbci-tool4 addaccountflags --account=%s --flags=%s', $uniqueAccountId, $flags)) + ->andReturn($result); + + $sut = new AddAccountFlagsCommand(); + $sut->setShellCommandExecutor($shellCommandExecutorMock); + + if (! $pass) { + $this->expectException(DefectiveResultException::class); + } + + $sut->execute($account, $flags); + + if ($pass) { + $this->assertTrue(true); + } + } + + public static function samples(): array + { + return [ + 'pass' => [new Result([], [], 0), true], + 'error' => [new Result([], ['Error'], 1), false], + ]; + } +} From f9fe1c091751ce31217b3541d922adbba4598e67 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 02:10:59 +0100 Subject: [PATCH 23/36] cleanup ListAccountsCommand --- src/Command/ListAccountsCommand.php | 11 ++-- tests/Command/ListAccountsCommandTest.php | 67 +++++++++++++++++++++++ 2 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 tests/Command/ListAccountsCommandTest.php diff --git a/src/Command/ListAccountsCommand.php b/src/Command/ListAccountsCommand.php index dad448e..c84375e 100644 --- a/src/Command/ListAccountsCommand.php +++ b/src/Command/ListAccountsCommand.php @@ -1,7 +1,11 @@ pathToAqHBCIToolBinary @@ -25,7 +26,7 @@ public function execute() $result = $this->getShellCommandExecutor()->execute($shellCommand); if (0 !== $result->getReturnVar()) { - throw new \RuntimeException( + throw new RuntimeException( 'AqBanking exited with errors: ' . PHP_EOL . implode(PHP_EOL, $result->getErrors()) ); diff --git a/tests/Command/ListAccountsCommandTest.php b/tests/Command/ListAccountsCommandTest.php new file mode 100644 index 0000000..b646dfb --- /dev/null +++ b/tests/Command/ListAccountsCommandTest.php @@ -0,0 +1,67 @@ +shouldReceive('execute') + ->with('aqhbci-tool4 listaccounts -v') + ->andReturn($result); + + $sut = new ListAccountsCommand(); + $sut->setShellCommandExecutor($shellCommandExecutorMock); + + if (! $pass) { + $this->expectException(RuntimeException::class); + } + + $accounts = $sut->execute(); + + if ($pass) { + $this->assertIsArray($accounts); + $this->assertCount(2, $accounts); + $this->assertSame([ + ListAccountsCommand::BANK => '10010010', + ListAccountsCommand::NUMBER => '10000000', + ListAccountsCommand::UNIQUE_ID => 1, + ], $accounts[0]); + $this->assertSame([ + ListAccountsCommand::BANK => '20020020', + ListAccountsCommand::NUMBER => '200000', + ListAccountsCommand::UNIQUE_ID => 2, + ], $accounts[1]); + } + } + + public static function samples(): array + { + return [ + 'pass' => [new Result(static::$output, [], 0), true], + 'error' => [new Result([], ['Error'], 1), false], + ]; + } +} From 5abe70342d10bd699d96503fe9cd2f3ebd738811 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 02:27:45 +0100 Subject: [PATCH 24/36] cleanup, fix Test RenderContextFileToXMLCommand --- src/Command/RenderContextFileToXMLCommand.php | 17 ++++++++++------ .../RenderContextFileToXMLCommandTest.php | 20 ++++++++++++++++--- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/Command/RenderContextFileToXMLCommand.php b/src/Command/RenderContextFileToXMLCommand.php index 8765e24..0396537 100644 --- a/src/Command/RenderContextFileToXMLCommand.php +++ b/src/Command/RenderContextFileToXMLCommand.php @@ -1,16 +1,21 @@ pathToAqBankingCLIBinary @@ -22,17 +27,17 @@ public function execute(ContextFile $contextFile, bool $returnSimpleXml = false) $result = $this->getShellCommandExecutor()->execute($shellCommand); if (0 !== $result->getReturnVar()) { - throw new \RuntimeException( + throw new RuntimeException( 'AqBanking exited with errors: ' . PHP_EOL . implode(PHP_EOL, $result->getErrors()) ); } if ($returnSimpleXml) { - return new \SimpleXMLElement(implode(PHP_EOL, $result->getOutput())); + return new SimpleXMLElement(implode(PHP_EOL, $result->getOutput())); } - $domDocument = new \DOMDocument(); + $domDocument = new DOMDocument(); $domDocument->loadXML(implode(PHP_EOL, $result->getOutput())); return $domDocument; diff --git a/tests/Command/RenderContextFileToXMLCommandTest.php b/tests/Command/RenderContextFileToXMLCommandTest.php index 2dc16f8..36fce2b 100644 --- a/tests/Command/RenderContextFileToXMLCommandTest.php +++ b/tests/Command/RenderContextFileToXMLCommandTest.php @@ -1,25 +1,36 @@ markTestSkipped('FIXME'); - $contextFile = new ContextFile('/path/to/some/context/file.ctx'); $shellCommandExecutorMock = \Mockery::mock('AqBanking\Command\ShellCommandExecutor'); $expectedCommand = 'aqbanking-cli' . ' export' - . ' --ctxfile=' . $contextFile->getPath() + . ' --ctxfile=' . escapeshellcmd($contextFile->getPath()) + . ' --transactiontype=statement' // we are only interested in statements, not notedStatement and so on . ' --exporter=xmldb'; $output = [ '', @@ -42,6 +53,9 @@ public function testCanIssueCorrectRenderCommand() $this->assertXmlStringEqualsXmlString($expectedXmlString, $result->saveXML()); } + /** + * @throws Exception + */ public function testCanHandleUnexpectedOutput() { $shellCommandExecutorMock = \Mockery::mock('AqBanking\Command\ShellCommandExecutor'); From 429ce1b72832ddc01567ea46c5a48ff13d870d60 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 02:47:52 +0100 Subject: [PATCH 25/36] cleanup GetAccountsCommand --- src/Command/GetAccountsCommand.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Command/GetAccountsCommand.php b/src/Command/GetAccountsCommand.php index aa9383d..42f9e26 100644 --- a/src/Command/GetAccountsCommand.php +++ b/src/Command/GetAccountsCommand.php @@ -1,5 +1,7 @@ pathToAqHBCIToolBinary From 7a3e0db03185dd75c48ef56df17f9b10983558e3 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 02:48:18 +0100 Subject: [PATCH 26/36] cleanup GetAccSepaCommand --- src/Command/GetAccSepaCommand.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Command/GetAccSepaCommand.php b/src/Command/GetAccSepaCommand.php index df2ac26..7498b6d 100644 --- a/src/Command/GetAccSepaCommand.php +++ b/src/Command/GetAccSepaCommand.php @@ -1,5 +1,7 @@ pathToAqHBCIToolBinary @@ -23,7 +28,13 @@ public function execute(ExistingAccount $account, PinFile $pinFile) $resultAnalyzer = new ResultAnalyzer(); if ($resultAnalyzer->isDefectiveResult($result)) { - throw new DefectiveResultException('Unexpected output on getting account sepa', 0, null, $result, $shellCommand); + throw new DefectiveResultException( + 'Unexpected output on getting account sepa', + 0, + null, + $result, + $shellCommand + ); } } } From 8a44306e8c1b8ef592c330de1a6ecaf30050ce63 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 03:03:12 +0100 Subject: [PATCH 27/36] cleanup GetSysIDCommand --- src/Command/GetSysIDCommand.php | 5 +++-- tests/Command/GetSysIDCommandTest.php | 22 ++++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/Command/GetSysIDCommand.php b/src/Command/GetSysIDCommand.php index 67c7658..634d603 100644 --- a/src/Command/GetSysIDCommand.php +++ b/src/Command/GetSysIDCommand.php @@ -1,5 +1,7 @@ pathToAqHBCIToolBinary diff --git a/tests/Command/GetSysIDCommandTest.php b/tests/Command/GetSysIDCommandTest.php index b6967a2..2ac0d39 100644 --- a/tests/Command/GetSysIDCommandTest.php +++ b/tests/Command/GetSysIDCommandTest.php @@ -1,18 +1,36 @@ assertTrue(true); } - public function testThrowsExceptionOnUnexpectedResult() + public function testThrowsExceptionOnUnexpectedResult(): void { $userId = 'mustermann'; $uniqueUserId = 123; From 0537c23a0d3c7259b8909aedf382074a0546dc07 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 03:10:00 +0100 Subject: [PATCH 28/36] cleanup ListUsersCommand --- src/Command/ListUsersCommand.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Command/ListUsersCommand.php b/src/Command/ListUsersCommand.php index e86e83b..1b1957d 100644 --- a/src/Command/ListUsersCommand.php +++ b/src/Command/ListUsersCommand.php @@ -1,15 +1,17 @@ pathToAqHBCIToolBinary @@ -23,13 +25,13 @@ public function execute() } if (0 !== $result->getReturnVar()) { - throw new \RuntimeException( + throw new RuntimeException( 'AqBanking exited with errors: ' . PHP_EOL . implode(PHP_EOL, $result->getErrors()) ); } - $domDocument = new \DOMDocument(); + $domDocument = new DOMDocument(); $domDocument->loadXML(implode(PHP_EOL, $result->getOutput())); return $domDocument; From a9cc6e480a975a55d86586c457f96288f9d12c44 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 03:15:09 +0100 Subject: [PATCH 29/36] cleanup RequestCommand --- src/Command/RequestCommand.php | 35 ++++++++------------------ tests/Command/RequestCommandTest.php | 37 ++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/Command/RequestCommand.php b/src/Command/RequestCommand.php index cbd948c..391ee4f 100644 --- a/src/Command/RequestCommand.php +++ b/src/Command/RequestCommand.php @@ -1,5 +1,7 @@ account = $account; - $this->contextFile = $contextFile; - $this->pinFile = $pinFile; + public function __construct( + private readonly Account $account, + private readonly ContextFile $contextFile, + private readonly PinFile $pinFile + ) { } /** * @throws ShellCommandExecutor\DefectiveResultException */ - public function execute(\DateTime $fromDate = null) + public function execute(DateTime $fromDate = null): void { $shellCommand = $this->getShellCommand($fromDate); $result = $this->getShellCommandExecutor()->execute($shellCommand); @@ -52,10 +40,7 @@ public function execute(\DateTime $fromDate = null) } } - /** - * @return string - */ - private function getShellCommand(\DateTime $fromDate = null) + private function getShellCommand(DateTime $fromDate = null): string { $shellCommand = $this->pathToAqBankingCLIBinary diff --git a/tests/Command/RequestCommandTest.php b/tests/Command/RequestCommandTest.php index 8e0b38f..6a18722 100644 --- a/tests/Command/RequestCommandTest.php +++ b/tests/Command/RequestCommandTest.php @@ -1,16 +1,34 @@ assertTrue(true); } - public function testCanExecuteWithFromDate() + /** + * @throws DefectiveResultException + */ + public function testCanExecuteWithFromDate(): void { $accountNumber = '12345678'; $bankCodeString = '23456789'; @@ -91,7 +112,7 @@ public function testCanExecuteWithFromDate() $this->assertTrue(true); } - public function testThrowsExceptionOnUnexpectedResult() + public function testThrowsExceptionOnUnexpectedResult(): void { $accountNumber = '12345678'; $bankCodeString = '23456789'; @@ -115,13 +136,9 @@ public function testThrowsExceptionOnUnexpectedResult() $sut->execute(); } - /** - * @param string $pathToPinFile - * @return \Mockery\MockInterface - */ - private function getPinFileMock($pathToPinFile) + private function getPinFileMock(string $pathToPinFile): MockInterface { - $pinFileMock = \Mockery::mock('AqBanking\PinFile\PinFile'); + $pinFileMock = Mockery::mock('AqBanking\PinFile\PinFile'); $pinFileMock ->shouldReceive('getPath') ->andReturn($pathToPinFile); From ff32b4ffdaaedf2edf30f5e7b283dd82e4e35a4f Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 03:24:27 +0100 Subject: [PATCH 30/36] cleanup SepaTransferCommand --- src/Command/SepaTransferCommand.php | 36 +++++++---------------- tests/Command/SepaTransferCommandTest.php | 28 ++++++++++++++---- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/Command/SepaTransferCommand.php b/src/Command/SepaTransferCommand.php index f93e5df..a503bb3 100644 --- a/src/Command/SepaTransferCommand.php +++ b/src/Command/SepaTransferCommand.php @@ -1,5 +1,7 @@ account = $account; - $this->contextFile = $contextFile; - $this->pinFile = $pinFile; + public function __construct( + private readonly Account $account, + private readonly ContextFile $contextFile, + private readonly PinFile $pinFile + ) { } /** - * @param string $rname remote name - * @param string $riban remote iban * @param string $value value to transfer "1/100:EUR" - * @param string $purpose purpose of the transfer + * * @throws ShellCommandExecutor\DefectiveResultException */ - public function execute(string $rname, string $riban, string $value, string $purpose, \DateTime $executionDate = null) + public function execute(string $rname, string $riban, string $value, string $purpose, \DateTime $executionDate = null): void { $shellCommand = $this->getShellCommand($rname, $riban, $value, $purpose, $executionDate); $result = $this->getShellCommandExecutor()->execute($shellCommand); @@ -60,9 +45,8 @@ public function execute(string $rname, string $riban, string $value, string $pur * @param string $riban remote iban * @param string $value value to transfer "1/100:EUR" * @param string $purpose purpose of the transfer - * @return string */ - private function getShellCommand(string $rname, string $riban, string $value, string $purpose, \DateTime $executionDate = null) + private function getShellCommand(string $rname, string $riban, string $value, string $purpose, \DateTime $executionDate = null): string { $shellCommand = $this->pathToAqBankingCLIBinary diff --git a/tests/Command/SepaTransferCommandTest.php b/tests/Command/SepaTransferCommandTest.php index f15ca84..1264e0e 100644 --- a/tests/Command/SepaTransferCommandTest.php +++ b/tests/Command/SepaTransferCommandTest.php @@ -1,16 +1,33 @@ assertTrue(true); } - public function testAcceptsValidOutput() + public function testAcceptsValidOutput(): void { $accountNumber = '12345678'; $bankCodeString = '23456789'; @@ -87,11 +104,10 @@ public function testAcceptsValidOutput() /** * @param string $pathToPinFile - * @return \Mockery\MockInterface */ - private function getPinFileMock($pathToPinFile) + private function getPinFileMock($pathToPinFile): MockInterface { - $pinFileMock = \Mockery::mock('AqBanking\PinFile\PinFile'); + $pinFileMock = Mockery::mock('AqBanking\PinFile\PinFile'); $pinFileMock ->shouldReceive('getPath') ->andReturn($pathToPinFile); From e7a5d7ff68dbaa491d6b9054fc5be78ce4b2a668 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 03:27:30 +0100 Subject: [PATCH 31/36] cleanup SetAppropriateITanModeCommand --- src/Command/SetAppropriateITanModeCommand.php | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/Command/SetAppropriateITanModeCommand.php b/src/Command/SetAppropriateITanModeCommand.php index abb523e..2db1aab 100644 --- a/src/Command/SetAppropriateITanModeCommand.php +++ b/src/Command/SetAppropriateITanModeCommand.php @@ -1,5 +1,7 @@ user = $user; + public function __construct( + private readonly User $user + ) { } - public function execute() + /** + * @throws DefectiveResultException + */ + public function execute(): void { $this->setHbciVersion($this->determineHbciVersionToSet()); } /** - * @return HbciVersion * @throws DefectiveResultException */ - private function determineHbciVersionToSet() + private function determineHbciVersionToSet(): HbciVersion { $shellCommand = $this->pathToAqHBCIToolBinary . @@ -62,10 +61,7 @@ private function determineHbciVersionToSet() return $highestVersionAvailable; } - /** - * @return null|HbciVersion - */ - private function findHighestAvailableHbciVersion(Result $result) + private function findHighestAvailableHbciVersion(Result $result): ?HbciVersion { $highestVersionAvailable = null; @@ -87,7 +83,7 @@ private function findHighestAvailableHbciVersion(Result $result) /** * @throws DefectiveResultException */ - private function setHbciVersion(HbciVersion $highestVersionAvailable) + private function setHbciVersion(HbciVersion $highestVersionAvailable): void { $shellCommand = $this->pathToAqHBCIToolBinary . From dded38afabd001c4574b269283eac00d34befe2b Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 03:27:53 +0100 Subject: [PATCH 32/36] cleanup SetITanModeCommand --- src/Command/SetITanModeCommand.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Command/SetITanModeCommand.php b/src/Command/SetITanModeCommand.php index b5e60ad..4394fe4 100644 --- a/src/Command/SetITanModeCommand.php +++ b/src/Command/SetITanModeCommand.php @@ -1,20 +1,19 @@ pathToAqHBCIToolBinary From dc5abf3e63e82191395fad21d8abf9654d161806 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Thu, 7 Dec 2023 04:04:26 +0100 Subject: [PATCH 33/36] phpstan generate baseline --- phpstan-baseline.neon | 46 +++++++++++++++++++++++++++++++++++++++++++ phpstan.neon | 2 ++ 2 files changed, 48 insertions(+) create mode 100644 phpstan-baseline.neon diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..601994e --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,46 @@ +parameters: + ignoreErrors: + - + message: "#^Argument of an invalid type DOMDocument supplied for foreach, only iterables are supported\\.$#" + count: 1 + path: src/AccountMatcher.php + + - + message: "#^Method AqBanking\\\\AccountMatcher\\:\\:__construct\\(\\) has parameter \\$array with no type specified\\.$#" + count: 1 + path: src/AccountMatcher.php + + - + message: "#^Method AqBanking\\\\AccountMatcher\\:\\:getExistingAccount\\(\\) has no return type specified\\.$#" + count: 1 + path: src/AccountMatcher.php + + - + message: "#^Method AqBanking\\\\Arrayable\\:\\:toArray\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Arrayable.php + + - + message: "#^Method AqBanking\\\\Command\\\\ListAccountsCommand\\:\\:execute\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: src/Command/ListAccountsCommand.php + + - + message: "#^Method AqBanking\\\\ContextXmlRenderer\\:\\:renderMultiLineElement\\(\\) has parameter \\$nodes with generic class DOMNodeList but does not specify its types\\: TNode$#" + count: 1 + path: src/ContextXmlRenderer.php + + - + message: "#^Method AqBanking\\\\ContextXmlRenderer\\:\\:renderSimpleTextElement\\(\\) has parameter \\$valueNodes with generic class DOMNodeList but does not specify its types\\: TNode$#" + count: 1 + path: src/ContextXmlRenderer.php + + - + message: "#^Access to an undefined property AqBanking\\\\UserMatcher\\:\\:\\$xPath\\.$#" + count: 2 + path: src/UserMatcher.php + + - + message: "#^Method AqBanking\\\\UserMatcher\\:\\:getExistingUser\\(\\) has no return type specified\\.$#" + count: 1 + path: src/UserMatcher.php diff --git a/phpstan.neon b/phpstan.neon index 6e451fa..a79233e 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,3 +1,5 @@ +includes: + - phpstan-baseline.neon parameters: level: 6 paths: From 5bfcade47c040d22037d6ad99baaa178ed9ac371 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Sat, 9 Dec 2023 14:49:26 +0100 Subject: [PATCH 34/36] cleanup UserMatcher --- phpstan-baseline.neon | 10 ---- src/UserMatcher.php | 41 ++++++--------- tests/UserMatcherTest.php | 105 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 36 deletions(-) create mode 100644 tests/UserMatcherTest.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 601994e..cc2e689 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -34,13 +34,3 @@ parameters: message: "#^Method AqBanking\\\\ContextXmlRenderer\\:\\:renderSimpleTextElement\\(\\) has parameter \\$valueNodes with generic class DOMNodeList but does not specify its types\\: TNode$#" count: 1 path: src/ContextXmlRenderer.php - - - - message: "#^Access to an undefined property AqBanking\\\\UserMatcher\\:\\:\\$xPath\\.$#" - count: 2 - path: src/UserMatcher.php - - - - message: "#^Method AqBanking\\\\UserMatcher\\:\\:getExistingUser\\(\\) has no return type specified\\.$#" - count: 1 - path: src/UserMatcher.php diff --git a/src/UserMatcher.php b/src/UserMatcher.php index d4d0d65..b76134b 100644 --- a/src/UserMatcher.php +++ b/src/UserMatcher.php @@ -1,47 +1,36 @@ domDocument = $domDocument; - if (null !== $domDocument) { - $this->xPath = new \DOMXPath($domDocument); - } + public function __construct( + private readonly ?DOMDocument $domDocument = null + ) { } - public function getExistingUser(User $user) + public function getExistingUser(User $user): ?ExistingUser { if (null === $this->domDocument) { return null; } - $userNodes = $this->xPath->query('/users/user', $this->domDocument); - - foreach ($userNodes as $userNode) { - $userName = $userNode->getElementsByTagName('UserName')[0]->nodeValue; - $userId = $userNode->getElementsByTagName('UserId')[0]->nodeValue; - $customerId = $userNode->getElementsByTagName('CustomerId')[0]->nodeValue; - $bankCode = $userNode->getElementsByTagName('BankCode')[0]->nodeValue; - $uniqueId = $userNode->getElementsByTagName('userUniqueId')[0]->nodeValue; - + foreach ($this->domDocument->getElementsByTagName('user') as $node) { + /** @var DOMElement $node */ if ( - $user->getUserName() === $userName && - $user->getUserId() === $userId && - $user->getBank()->getBankCode()->getString() === $bankCode + $user->getUserName() === $node->getElementsByTagName('UserName')->item(0)?->nodeValue && + $user->getUserId() === $node->getElementsByTagName('UserId')->item(0)?->nodeValue && + $user->getBank()->getBankCode()->getString() === $node->getElementsByTagName('BankCode')->item(0)?->nodeValue ) { - return new ExistingUser($user, $uniqueId); + return new ExistingUser($user, (int) $node->getElementsByTagName('userUniqueId')->item(0)->nodeValue); } } diff --git a/tests/UserMatcherTest.php b/tests/UserMatcherTest.php new file mode 100644 index 0000000..23a9cc5 --- /dev/null +++ b/tests/UserMatcherTest.php @@ -0,0 +1,105 @@ +getDomDocument()); + if (! $pass) { + $this->assertNull($matcher->getExistingUser($user)); + } else { + $this->assertInstanceOf(ExistingUser::class, $matcher->getExistingUser($user)); + } + } + + public function testUserMatcherNoDom(): void + { + $user = new User( + userId: '123', + userName: 'Name', + bank: new Bank( + bankCode: new BankCode('1235690'), + hbciUrl: 'https://fints.bank.de/fints', + hbciVersion: new HbciVersion('1.2.3'), + ), + ); + + $matcher = new UserMatcher(); + $this->assertNull($matcher->getExistingUser($user)); + } + + public static function samples(): array + { + return [ + 'match' => [self::$matchingUserName, self::$matchingUserId, self::$matchingBankCode, true], + 'no match' => ['User', 'ID', '123', false], + ]; + } + + private function getDomDocument(): \DOMDocument + { + $domDocument = new \DOMDocument(); + $domDocument->loadXML(' + + + 1 + + 23 + CutomerID + 12345678 + de + 0 + + + 3 + + ' . self::$matchingUserId . ' + 123456 + ' . self::$matchingBankCode . ' + de + 0 + + '); + + return $domDocument; + } +} From 9805bedf4f2e67b2899732c1544cfb0492151f9b Mon Sep 17 00:00:00 2001 From: grummbeer Date: Sat, 9 Dec 2023 15:37:32 +0100 Subject: [PATCH 35/36] cleanup AccountMatcher --- phpstan-baseline.neon | 12 +------ src/AccountMatcher.php | 20 +++++------ tests/AccountMatcherTest.php | 64 ++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 tests/AccountMatcherTest.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index cc2e689..d7b10e8 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,17 +1,7 @@ parameters: ignoreErrors: - - message: "#^Argument of an invalid type DOMDocument supplied for foreach, only iterables are supported\\.$#" - count: 1 - path: src/AccountMatcher.php - - - - message: "#^Method AqBanking\\\\AccountMatcher\\:\\:__construct\\(\\) has parameter \\$array with no type specified\\.$#" - count: 1 - path: src/AccountMatcher.php - - - - message: "#^Method AqBanking\\\\AccountMatcher\\:\\:getExistingAccount\\(\\) has no return type specified\\.$#" + message: "#^Method AqBanking\\\\AccountMatcher\\:\\:__construct\\(\\) has parameter \\$existingAccounts with no value type specified in iterable type array\\.$#" count: 1 path: src/AccountMatcher.php diff --git a/src/AccountMatcher.php b/src/AccountMatcher.php index b55e2fc..d78d0c0 100644 --- a/src/AccountMatcher.php +++ b/src/AccountMatcher.php @@ -1,33 +1,29 @@ array = $array; + public function __construct( + private readonly array $existingAccounts + ) { } - public function getExistingAccount(Account $account) + public function getExistingAccount(Account $account): ?ExistingAccount { - foreach ($this->array as $record) { + foreach ($this->existingAccounts as $record) { if ( $account->getBankCode()->getString() === $record[ListAccountsCommand::BANK] && $account->getAccountNumber() === $record[ListAccountsCommand::NUMBER] ) { - return new ExistingAccount($account, $record[ListAccountsCommand::UNIQUE_ID]); + return new ExistingAccount($account, (int) $record[ListAccountsCommand::UNIQUE_ID]); } } diff --git a/tests/AccountMatcherTest.php b/tests/AccountMatcherTest.php new file mode 100644 index 0000000..41de9ee --- /dev/null +++ b/tests/AccountMatcherTest.php @@ -0,0 +1,64 @@ + '50050010', + ListAccountsCommand::NUMBER => '987654123', + ListAccountsCommand::UNIQUE_ID => '1', + ], + [ + ListAccountsCommand::BANK => self::$matchingBankCode, + ListAccountsCommand::NUMBER => self::$matchingAccountNumber, + ListAccountsCommand::UNIQUE_ID => '2', + ], + ]); + + if (! $pass) { + $this->assertNull($matcher->getExistingAccount($account)); + } else { + $this->assertInstanceOf(ExistingAccount::class, $matcher->getExistingAccount($account)); + } + } + + public static function samples(): array + { + return [ + 'match' => [self::$matchingBankCode, self::$matchingAccountNumber, true], + 'no match' => ['12345678', '123569', false], + ]; + } +} From 4e7cf7724de31a850baab3b7b1d840369f981d52 Mon Sep 17 00:00:00 2001 From: grummbeer Date: Sat, 9 Dec 2023 16:23:42 +0100 Subject: [PATCH 36/36] add parameter types ContextXMLRenderer --- phpstan-baseline.neon | 10 ---------- src/ContextXmlRenderer.php | 6 ++++++ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index d7b10e8..a7f0268 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -14,13 +14,3 @@ parameters: message: "#^Method AqBanking\\\\Command\\\\ListAccountsCommand\\:\\:execute\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: src/Command/ListAccountsCommand.php - - - - message: "#^Method AqBanking\\\\ContextXmlRenderer\\:\\:renderMultiLineElement\\(\\) has parameter \\$nodes with generic class DOMNodeList but does not specify its types\\: TNode$#" - count: 1 - path: src/ContextXmlRenderer.php - - - - message: "#^Method AqBanking\\\\ContextXmlRenderer\\:\\:renderSimpleTextElement\\(\\) has parameter \\$valueNodes with generic class DOMNodeList but does not specify its types\\: TNode$#" - count: 1 - path: src/ContextXmlRenderer.php diff --git a/src/ContextXmlRenderer.php b/src/ContextXmlRenderer.php index fea5b89..ff8ee42 100644 --- a/src/ContextXmlRenderer.php +++ b/src/ContextXmlRenderer.php @@ -113,6 +113,9 @@ public function getBalances(): array return $balances; } + /** + * @param DOMNodeList $nodes + */ private function renderMultiLineElement(DOMNodeList $nodes): string { $lines = []; @@ -157,6 +160,9 @@ private function renderMoneyElement(DOMNode $node): Money return $this->moneyElementRenderer->render($valueString, $currencyString); } + /** + * @param DOMNodeList $valueNodes + */ private function renderSimpleTextElement(DOMNodeList $valueNodes): string { return trim($valueNodes->item(0)->nodeValue);