From cce5a73dd2c8e8f1bf4c37677ffc832895b39825 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 7 Sep 2025 14:28:58 +0200 Subject: [PATCH] Clean up and fix phpstan issues. --- .ci/phpstan.neon | 18 ++- .../V1/Controllers/Chart/BudgetController.php | 4 +- .../StoreByDateRequest.php | 4 + app/Helpers/Collector/GroupCollector.php | 132 ++++++++---------- 4 files changed, 77 insertions(+), 81 deletions(-) diff --git a/.ci/phpstan.neon b/.ci/phpstan.neon index c85e03774f..3da6d3fa52 100644 --- a/.ci/phpstan.neon +++ b/.ci/phpstan.neon @@ -7,21 +7,19 @@ parameters: - ../bootstrap/app.php universalObjectCratesClasses: - Illuminate\Database\Eloquent\Model - # TODO: slowly remove these parameters and fix the issues found. reportUnmatchedIgnoredErrors: true ignoreErrors: - # TODO: slowly remove these exceptions and fix the issues found. - - identifier: varTag.type + # all errors below I will never fix. + - '#expects view-string\|null, string given#' + - '#expects view-string, string given#' + - "#Parameter \\#[1-2] \\$num[1-2] of function bc[a-z]+ expects numeric-string, [a-z\\-|&]+ given#" + - identifier: missingType.generics # not interesting enough to fix. - identifier: larastan.noEnvCallsOutsideOfConfig path: ../app/Console/Commands/System/CreatesDatabase.php - identifier: missingType.iterableValue # not interesting enough to fix. - - identifier: missingType.generics # not interesting enough to fix. - - "#Parameter \\#[1-2] \\$num[1-2] of function bc[a-z]+ expects numeric-string, [a-z\\-|&]+ given#" - - '#expects view-string, string given#' - - '#expects view-string\|null, string given#' - - # phpstan can't handle this so we ignore them. + - identifier: varTag.type # needs a custom extension for every repository, not gonna happen. + - '#Dynamic call to static method Illuminate#' - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::before#' # is custom scope - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::after#' # is custom scope - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::withTrashed#' # is to allow soft delete @@ -30,5 +28,5 @@ parameters: # The level 8 is the highest level. original was 5 # 7 is more than enough, higher just leaves NULL things. - level: 7 + level: 8 diff --git a/app/Api/V1/Controllers/Chart/BudgetController.php b/app/Api/V1/Controllers/Chart/BudgetController.php index f4a76d258c..4bebbce464 100644 --- a/app/Api/V1/Controllers/Chart/BudgetController.php +++ b/app/Api/V1/Controllers/Chart/BudgetController.php @@ -250,7 +250,9 @@ class BudgetController extends Controller // var_dump($return); /** @var array $journal */ foreach ($currentBudgetArray['transaction_journals'] as $journal) { - $return[$currencyId]['spent'] = bcadd($return[$currencyId]['spent'], (string)$journal['amount']); + /** @var numeric-string $amount */ + $amount= (string)$journal['amount']; + $return[$currencyId]['spent'] = bcadd($return[$currencyId]['spent'], $amount); } } diff --git a/app/Api/V1/Requests/Models/CurrencyExchangeRate/StoreByDateRequest.php b/app/Api/V1/Requests/Models/CurrencyExchangeRate/StoreByDateRequest.php index 48f43d108f..4afb664063 100644 --- a/app/Api/V1/Requests/Models/CurrencyExchangeRate/StoreByDateRequest.php +++ b/app/Api/V1/Requests/Models/CurrencyExchangeRate/StoreByDateRequest.php @@ -35,6 +35,9 @@ class StoreByDateRequest extends FormRequest use ChecksLogin; use ConvertsDataTypes; + /** + * @return array + */ public function getAll(): array { return [ @@ -50,6 +53,7 @@ class StoreByDateRequest extends FormRequest /** * The rules that the incoming request must be matched against. + * @return array */ public function rules(): array { diff --git a/app/Helpers/Collector/GroupCollector.php b/app/Helpers/Collector/GroupCollector.php index 94c8d32076..6bff06a3e3 100644 --- a/app/Helpers/Collector/GroupCollector.php +++ b/app/Helpers/Collector/GroupCollector.php @@ -26,6 +26,7 @@ namespace FireflyIII\Helpers\Collector; use Carbon\Carbon; use Carbon\Exceptions\InvalidFormatException; +use Closure; use Exception; use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Exceptions\FireflyException; @@ -45,9 +46,7 @@ use Illuminate\Database\Query\JoinClause; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; -use Closure; use Override; - use function Safe\json_decode; /** @@ -67,15 +66,15 @@ class GroupCollector implements GroupCollectorInterface */ public function __construct() { - $this->sorting = []; - $this->postFilters = []; - $this->tags = []; - $this->user = null; - $this->userGroup = null; - $this->limit = null; - $this->page = null; - $this->startRow = null; - $this->endRow = null; + $this->sorting = []; + $this->postFilters = []; + $this->tags = []; + $this->user = null; + $this->userGroup = null; + $this->limit = null; + $this->page = null; + $this->startRow = null; + $this->endRow = null; $this->hasAccountInfo = false; $this->hasCatInformation = false; @@ -303,9 +302,9 @@ class GroupCollector implements GroupCollectorInterface foreach ($params as $param) { $replace = sprintf('"%s"', $param); if (is_int($param)) { - $replace = (string) $param; + $replace = (string)$param; } - $pos = strpos($query, '?'); + $pos = strpos($query, '?'); if (false !== $pos) { $query = substr_replace($query, $replace, $pos, 1); } @@ -477,15 +476,15 @@ class GroupCollector implements GroupCollectorInterface // add to query: $this->query->orWhereIn('transaction_journals.transaction_group_id', $groupIds); } - $result = $this->query->get($this->fields); + $result = $this->query->get($this->fields); // now to parse this into an array. - $collection = $this->parseArray($result); + $collection = $this->parseArray($result); // filter the array using all available post filters: - $collection = $this->postFilterCollection($collection); + $collection = $this->postFilterCollection($collection); // sort the collection, if sort instructions are present. - $collection = $this->sortCollection($collection); + $collection = $this->sortCollection($collection); // count it and continue: $this->total = $collection->count(); @@ -518,13 +517,13 @@ class GroupCollector implements GroupCollectorInterface /** @var TransactionJournal $augumentedJournal */ foreach ($collection as $augumentedJournal) { - $groupId = (int) $augumentedJournal->transaction_group_id; + $groupId = (int)$augumentedJournal->transaction_group_id; if (!array_key_exists($groupId, $groups)) { // make new array - $parsedGroup = $this->parseAugmentedJournal($augumentedJournal); - $groupArray = [ - 'id' => (int) $augumentedJournal->transaction_group_id, + $parsedGroup = $this->parseAugmentedJournal($augumentedJournal); + $groupArray = [ + 'id' => (int)$augumentedJournal->transaction_group_id, 'user_id' => $augumentedJournal->user_id, 'user_group_id' => $augumentedJournal->user_group_id, // Field transaction_group_title was added by the query. @@ -537,7 +536,7 @@ class GroupCollector implements GroupCollectorInterface 'transactions' => [], ]; // Field transaction_journal_id was added by the query. - $journalId = (int) $augumentedJournal->transaction_journal_id; + $journalId = (int)$augumentedJournal->transaction_journal_id; $groupArray['transactions'][$journalId] = $parsedGroup; $groups[$groupId] = $groupArray; @@ -545,7 +544,7 @@ class GroupCollector implements GroupCollectorInterface } // or parse the rest. // Field transaction_journal_id was added by the query. - $journalId = (int) $augumentedJournal->transaction_journal_id; + $journalId = (int)$augumentedJournal->transaction_journal_id; if (array_key_exists($journalId, $groups[$groupId]['transactions'])) { // append data to existing group + journal (for multiple tags or multiple attachments) $groups[$groupId]['transactions'][$journalId] = $this->mergeTags($groups[$groupId]['transactions'][$journalId], $augumentedJournal); @@ -594,27 +593,27 @@ class GroupCollector implements GroupCollectorInterface } // try to process meta date value (if present) - $dates = ['interest_date', 'payment_date', 'invoice_date', 'book_date', 'due_date', 'process_date']; + $dates = ['interest_date', 'payment_date', 'invoice_date', 'book_date', 'due_date', 'process_date']; if (array_key_exists('meta_name', $result) && in_array($result['meta_name'], $dates, true)) { $name = $result['meta_name']; - if (array_key_exists('meta_data', $result) && '' !== (string) $result['meta_data']) { - $result[$name] = Carbon::createFromFormat('!Y-m-d', substr((string) json_decode((string) $result['meta_data']), 0, 10)); + if (array_key_exists('meta_data', $result) && '' !== (string)$result['meta_data']) { + $result[$name] = Carbon::createFromFormat('!Y-m-d', substr((string)json_decode((string)$result['meta_data']), 0, 10)); } } // convert values to integers: - $result = $this->convertToInteger($result); + $result = $this->convertToInteger($result); // convert to boolean - $result = $this->convertToBoolean($result); + $result = $this->convertToBoolean($result); // convert back to strings because SQLite is dumb like that. - $result = $this->convertToStrings($result); + $result = $this->convertToStrings($result); - $result['reconciled'] = 1 === (int) $result['reconciled']; + $result['reconciled'] = 1 === (int)$result['reconciled']; if (array_key_exists('tag_id', $result) && null !== $result['tag_id']) { // assume the other fields are present as well. - $tagId = (int) $augumentedJournal['tag_id']; - $tagDate = null; + $tagId = (int)$augumentedJournal['tag_id']; + $tagDate = null; try { $tagDate = Carbon::parse($augumentedJournal['tag_date']); @@ -623,7 +622,7 @@ class GroupCollector implements GroupCollectorInterface } $result['tags'][$tagId] = [ - 'id' => (int) $result['tag_id'], + 'id' => (int)$result['tag_id'], 'name' => $result['tag_name'], 'date' => $tagDate, 'description' => $result['tag_description'], @@ -632,8 +631,8 @@ class GroupCollector implements GroupCollectorInterface // also merge attachments: if (array_key_exists('attachment_id', $result)) { - $uploaded = 1 === (int) $result['attachment_uploaded']; - $attachmentId = (int) $augumentedJournal['attachment_id']; + $uploaded = 1 === (int)$result['attachment_uploaded']; + $attachmentId = (int)$augumentedJournal['attachment_id']; if (0 !== $attachmentId && $uploaded) { $result['attachments'][$attachmentId] = [ 'id' => $attachmentId, @@ -659,7 +658,7 @@ class GroupCollector implements GroupCollectorInterface private function convertToInteger(array $array): array { foreach ($this->integerFields as $field) { - $array[$field] = array_key_exists($field, $array) ? (int) $array[$field] : null; + $array[$field] = array_key_exists($field, $array) ? (int)$array[$field] : null; } return $array; @@ -668,7 +667,7 @@ class GroupCollector implements GroupCollectorInterface private function convertToBoolean(array $array): array { foreach ($this->booleanFields as $field) { - $array[$field] = array_key_exists($field, $array) ? (bool) $array[$field] : null; + $array[$field] = array_key_exists($field, $array) ? (bool)$array[$field] : null; } return $array; @@ -677,7 +676,7 @@ class GroupCollector implements GroupCollectorInterface private function convertToStrings(array $array): array { foreach ($this->stringFields as $field) { - $array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (string) $array[$field] : null; + $array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (string)$array[$field] : null; } return $array; @@ -687,9 +686,9 @@ class GroupCollector implements GroupCollectorInterface { $newArray = $newJournal->toArray(); if (array_key_exists('tag_id', $newArray)) { // assume the other fields are present as well. - $tagId = (int) $newJournal['tag_id']; + $tagId = (int)$newJournal['tag_id']; - $tagDate = null; + $tagDate = null; try { $tagDate = Carbon::parse($newArray['tag_date']); @@ -698,7 +697,7 @@ class GroupCollector implements GroupCollectorInterface } $existingJournal['tags'][$tagId] = [ - 'id' => (int) $newArray['tag_id'], + 'id' => (int)$newArray['tag_id'], 'name' => $newArray['tag_name'], 'date' => $tagDate, 'description' => $newArray['tag_description'], @@ -712,7 +711,7 @@ class GroupCollector implements GroupCollectorInterface { $newArray = $newJournal->toArray(); if (array_key_exists('attachment_id', $newArray)) { - $attachmentId = (int) $newJournal['attachment_id']; + $attachmentId = (int)$newJournal['attachment_id']; $existingJournal['attachments'][$attachmentId] = [ 'id' => $attachmentId, @@ -725,19 +724,19 @@ class GroupCollector implements GroupCollectorInterface private function parseSums(array $groups): array { /** - * @var int $groudId + * @var int $groudId * @var array $group */ foreach ($groups as $groudId => $group) { /** @var array $transaction */ foreach ($group['transactions'] as $transaction) { - $currencyId = (int) $transaction['currency_id']; + $currencyId = (int)$transaction['currency_id']; if (null === $transaction['amount']) { throw new FireflyException(sprintf('Amount is NULL for a transaction in group #%d, please investigate.', $groudId)); } - $pcAmount = (string) ('' === $transaction['pc_amount'] ? '0' : $transaction['pc_amount']); - $pcForeignAmount = (string) ('' === $transaction['pc_foreign_amount'] ? '0' : $transaction['pc_foreign_amount']); - $foreignAmount = (string) ('' === $transaction['foreign_amount'] ? '0' : $transaction['foreign_amount']); + $pcAmount = (string)('' === $transaction['pc_amount'] ? '0' : $transaction['pc_amount']); + $pcForeignAmount = (string)('' === $transaction['pc_foreign_amount'] ? '0' : $transaction['pc_foreign_amount']); + $foreignAmount = (string)('' === $transaction['foreign_amount'] ? '0' : $transaction['foreign_amount']); // set default: if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) { @@ -748,11 +747,11 @@ class GroupCollector implements GroupCollectorInterface $groups[$groudId]['sums'][$currencyId]['amount'] = '0'; $groups[$groudId]['sums'][$currencyId]['pc_amount'] = '0'; } - $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd((string) $groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']); - $groups[$groudId]['sums'][$currencyId]['pc_amount'] = bcadd((string) $groups[$groudId]['sums'][$currencyId]['pc_amount'], $pcAmount); + $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd((string)$groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']); + $groups[$groudId]['sums'][$currencyId]['pc_amount'] = bcadd((string)$groups[$groudId]['sums'][$currencyId]['pc_amount'], $pcAmount); if (null !== $transaction['foreign_amount'] && null !== $transaction['foreign_currency_id']) { - $currencyId = (int) $transaction['foreign_currency_id']; + $currencyId = (int)$transaction['foreign_currency_id']; // set default: if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) { @@ -763,7 +762,7 @@ class GroupCollector implements GroupCollectorInterface $groups[$groudId]['sums'][$currencyId]['amount'] = '0'; $groups[$groudId]['sums'][$currencyId]['pc_amount'] = '0'; } - $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd((string) $groups[$groudId]['sums'][$currencyId]['amount'], $foreignAmount); + $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd((string)$groups[$groudId]['sums'][$currencyId]['amount'], $foreignAmount); $groups[$groudId]['sums'][$currencyId]['pc_amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $pcForeignAmount); } } @@ -787,7 +786,7 @@ class GroupCollector implements GroupCollectorInterface */ foreach ($this->postFilters as $function) { app('log')->debug('Applying filter...'); - $nextCollection = new Collection(); + $nextCollection = new Collection(); // loop everything in the current collection // and save it (or not) in the new collection. @@ -851,7 +850,7 @@ class GroupCollector implements GroupCollectorInterface */ public function getPaginatedGroups(): LengthAwarePaginator { - $set = $this->getGroups(); + $set = $this->getGroups(); if (0 === $this->limit) { $this->setLimit(50); } @@ -1075,8 +1074,7 @@ class GroupCollector implements GroupCollectorInterface 'transactions as source', static function (JoinClause $join): void { $join->on('source.transaction_journal_id', '=', 'transaction_journals.id') - ->where('source.amount', '<', 0) - ; + ->where('source.amount', '<', 0); } ) // join destination transaction @@ -1084,8 +1082,7 @@ class GroupCollector implements GroupCollectorInterface 'transactions as destination', static function (JoinClause $join): void { $join->on('destination.transaction_journal_id', '=', 'transaction_journals.id') - ->where('destination.amount', '>', 0) - ; + ->where('destination.amount', '>', 0); } ) // left join transaction type. @@ -1098,15 +1095,13 @@ class GroupCollector implements GroupCollectorInterface // #10507 ignore opening balance. ->where('transaction_types.type', '!=', TransactionTypeEnum::OPENING_BALANCE->value) - ->whereNotNull('transaction_groups.id') ->whereNull('destination.deleted_at') ->orderBy('transaction_journals.date', 'DESC') ->orderBy('transaction_journals.order', 'ASC') ->orderBy('transaction_journals.id', 'DESC') ->orderBy('transaction_journals.description', 'DESC') - ->orderBy('source.amount', 'DESC') - ; + ->orderBy('source.amount', 'DESC'); } /** @@ -1137,8 +1132,7 @@ class GroupCollector implements GroupCollectorInterface 'transactions as source', static function (JoinClause $join): void { $join->on('source.transaction_journal_id', '=', 'transaction_journals.id') - ->where('source.amount', '<', 0) - ; + ->where('source.amount', '<', 0); } ) // join destination transaction @@ -1146,8 +1140,7 @@ class GroupCollector implements GroupCollectorInterface 'transactions as destination', static function (JoinClause $join): void { $join->on('destination.transaction_journal_id', '=', 'transaction_journals.id') - ->where('destination.amount', '>', 0) - ; + ->where('destination.amount', '>', 0); } ) // left join transaction type. @@ -1162,8 +1155,7 @@ class GroupCollector implements GroupCollectorInterface ->orderBy('transaction_journals.order', 'ASC') ->orderBy('transaction_journals.id', 'DESC') ->orderBy('transaction_journals.description', 'DESC') - ->orderBy('source.amount', 'DESC') - ; + ->orderBy('source.amount', 'DESC'); } /** @@ -1174,13 +1166,13 @@ class GroupCollector implements GroupCollectorInterface // include source + destination account name and type. $this->withAccountInformation() // include category ID + name (if any) - ->withCategoryInformation() + ->withCategoryInformation() // include budget ID + name (if any) - ->withBudgetInformation() + ->withBudgetInformation() // include bill ID + name (if any) - ->withBillInformation() - ; + ->withBillInformation(); return $this; } + }