diff --git a/.ci/php-cs-fixer/composer.lock b/.ci/php-cs-fixer/composer.lock index 753cec5164..070f1496b1 100644 --- a/.ci/php-cs-fixer/composer.lock +++ b/.ci/php-cs-fixer/composer.lock @@ -1331,16 +1331,16 @@ }, { "name": "symfony/console", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "29afb89f4e941f68a6e90f28e3f52ff1f6793a7d" + "reference": "4b81146e3ee248ea969186f85499b54fbc78db08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/29afb89f4e941f68a6e90f28e3f52ff1f6793a7d", - "reference": "29afb89f4e941f68a6e90f28e3f52ff1f6793a7d", + "url": "https://api.github.com/repos/symfony/console/zipball/4b81146e3ee248ea969186f85499b54fbc78db08", + "reference": "4b81146e3ee248ea969186f85499b54fbc78db08", "shasum": "" }, "require": { @@ -1407,7 +1407,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v8.1.7" + "source": "https://github.com/symfony/console/tree/v8.1.8" }, "funding": [ { @@ -1427,7 +1427,7 @@ "type": "tidelift" } ], - "time": "2026-09-13T10:55:57+00:00" + "time": "2026-09-18T16:00:27+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1739,16 +1739,16 @@ }, { "name": "symfony/finder", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "4fbe46a3eb64abf8a57f0364075b91f4a233e062" + "reference": "bd4fed193a3132c91c5c93595cbfc78988915822" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/4fbe46a3eb64abf8a57f0364075b91f4a233e062", - "reference": "4fbe46a3eb64abf8a57f0364075b91f4a233e062", + "url": "https://api.github.com/repos/symfony/finder/zipball/bd4fed193a3132c91c5c93595cbfc78988915822", + "reference": "bd4fed193a3132c91c5c93595cbfc78988915822", "shasum": "" }, "require": { @@ -1783,7 +1783,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v8.1.7" + "source": "https://github.com/symfony/finder/tree/v8.1.8" }, "funding": [ { @@ -1803,7 +1803,7 @@ "type": "tidelift" } ], - "time": "2026-09-10T19:14:39+00:00" + "time": "2026-09-26T06:33:49+00:00" }, { "name": "symfony/options-resolver", diff --git a/app/Api/V1/Controllers/Insight/Income/TagController.php b/app/Api/V1/Controllers/Insight/Income/TagController.php index 94be2ae461..df99eef909 100644 --- a/app/Api/V1/Controllers/Insight/Income/TagController.php +++ b/app/Api/V1/Controllers/Insight/Income/TagController.php @@ -158,10 +158,7 @@ final class TagController extends Controller 'currency_id' => (string) $foreignCurrencyId, 'currency_code' => $journal['foreign_currency_code'], ]; - $response[$foreignKey]['difference'] = bcadd( - (string) $response[$foreignKey]['difference'], - Steam::positive($journal['foreign_amount']) - ); + $response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount'])); $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; } } diff --git a/app/Api/V1/Controllers/Insight/Transfer/TagController.php b/app/Api/V1/Controllers/Insight/Transfer/TagController.php index b7b85fd376..f92a7aa9f0 100644 --- a/app/Api/V1/Controllers/Insight/Transfer/TagController.php +++ b/app/Api/V1/Controllers/Insight/Transfer/TagController.php @@ -155,10 +155,7 @@ final class TagController extends Controller 'currency_id' => (string) $foreignCurrencyId, 'currency_code' => $journal['foreign_currency_code'], ]; - $response[$foreignKey]['difference'] = bcadd( - (string) $response[$foreignKey]['difference'], - Steam::positive($journal['foreign_amount']) - ); + $response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount'])); $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float } } diff --git a/app/Api/V1/Requests/AggregateFormRequest.php b/app/Api/V1/Requests/AggregateFormRequest.php index 10eeb5a1ba..daec7ff249 100644 --- a/app/Api/V1/Requests/AggregateFormRequest.php +++ b/app/Api/V1/Requests/AggregateFormRequest.php @@ -53,7 +53,7 @@ abstract class AggregateFormRequest extends ApiRequest parent::initialize($query, $request, $attributes, $cookies, $files, $server, $content); // instantiate all subrequests and share current requests' bags with them - Log::debug('Initializing AggregateFormRequest.'); + Log::debug('Initializing AggregateFormRequest.'); /** @var array|string $config */ foreach ($this->getRequests() as $config) { @@ -62,7 +62,7 @@ abstract class AggregateFormRequest extends ApiRequest if (!is_a($requestClass, Request::class, true)) { throw new RuntimeException('getRequests() must return class-strings of subclasses of Request'); } - Log::debug(sprintf('Initializing subrequest %s', $requestClass)); + Log::debug(sprintf('Initializing subrequest %s', $requestClass)); $instance = new $requestClass(); $this->requests[] = $instance; @@ -97,7 +97,7 @@ abstract class AggregateFormRequest extends ApiRequest // register all subrequests' validators foreach ($this->requests as $request) { if (method_exists($request, 'withValidator')) { - Log::debug(sprintf('Process withValidator from class %s', $request::class)); + Log::debug(sprintf('Process withValidator from class %s', $request::class)); $request->withValidator($validator); } } diff --git a/app/Api/V1/Requests/Generic/FilterRequest.php b/app/Api/V1/Requests/Generic/FilterRequest.php index acb6d997ef..d539a6ed12 100644 --- a/app/Api/V1/Requests/Generic/FilterRequest.php +++ b/app/Api/V1/Requests/Generic/FilterRequest.php @@ -26,7 +26,6 @@ namespace FireflyIII\Api\V1\Requests\Generic; use FireflyIII\Api\V1\Requests\ApiRequest; use FireflyIII\Rules\IsValidFilterInstruction; -use FireflyIII\Rules\IsValidSortInstruction; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Contracts\Validation\Validator; @@ -36,6 +35,7 @@ class FilterRequest extends ApiRequest { use ChecksLogin; use ConvertsDataTypes; + private ?string $filterClass = null; public function handleConfig(array $config): void @@ -45,7 +45,7 @@ class FilterRequest extends ApiRequest $this->filterClass = $config['filter_class'] ?? null; if (null === $this->filterClass) { - //throw new RuntimeException('FilterRequest requires a filter_class config'); + // throw new RuntimeException('FilterRequest requires a filter_class config'); $this->filterClass = 'Account'; } } @@ -53,7 +53,7 @@ class FilterRequest extends ApiRequest public function rules(): array { return [ - 'filter' => ['min:0','max:255', $this->required, new IsValidFilterInstruction((string) $this->filterClass)], + 'filter' => ['min:0', 'max:255', $this->required, new IsValidFilterInstruction((string) $this->filterClass)], ]; } @@ -65,7 +65,8 @@ class FilterRequest extends ApiRequest } }); } -// private function convertToFilter(string $value): array { -// return []; -// } + + // private function convertToFilter(string $value): array { + // return []; + // } } diff --git a/app/Api/V1/Requests/Models/Account/ShowRequest.php b/app/Api/V1/Requests/Models/Account/ShowRequest.php index ac5c632efd..f303c645de 100644 --- a/app/Api/V1/Requests/Models/Account/ShowRequest.php +++ b/app/Api/V1/Requests/Models/Account/ShowRequest.php @@ -28,7 +28,6 @@ use FireflyIII\Api\V1\Requests\AggregateFormRequest; use FireflyIII\Api\V1\Requests\DateRangeRequest; use FireflyIII\Api\V1\Requests\DateRequest; use FireflyIII\Api\V1\Requests\Generic\ActiveObjectRequest; -use FireflyIII\Api\V1\Requests\Generic\FilterRequest; use FireflyIII\Api\V1\Requests\PaginationRequest; use FireflyIII\Models\Account; diff --git a/app/Api/V1/Requests/PaginationRequest.php b/app/Api/V1/Requests/PaginationRequest.php index 3f42d11c63..1574172bc1 100644 --- a/app/Api/V1/Requests/PaginationRequest.php +++ b/app/Api/V1/Requests/PaginationRequest.php @@ -50,21 +50,20 @@ class PaginationRequest extends ApiRequest public function rules(): array { return [ - 'sort' => ['nullable', new IsValidSortInstruction((string) $this->sortClass)], - 'filter' => ['nullable', new IsValidFilterInstruction((string)$this->sortClass)], - 'limit' => ['numeric', 'min:1', 'max:131337'], - 'page' => ['numeric', 'min:1', 'max:131337'], + 'sort' => ['nullable', new IsValidSortInstruction((string) $this->sortClass)], + 'filter' => ['nullable', new IsValidFilterInstruction((string) $this->sortClass)], + 'limit' => ['numeric', 'min:1', 'max:131337'], + 'page' => ['numeric', 'min:1', 'max:131337'], ]; } public function withValidator(Validator $validator): void { - $validator->after(function (Validator $validator): void { if (count($validator->failed()) > 0) { return; } - $data = $validator->getData(); + $data = $validator->getData(); $limit = $this->integerFromValue($data['limit'] ?? null); if (0 === $limit || null === $limit) { // get default for user: @@ -77,7 +76,7 @@ class PaginationRequest extends ApiRequest $page = clamp(value: $page, min: 1, max: 2 ** 16); $offset = ($page - 1) * $limit; $sort = null !== $this->sortClass ? $this->convertSortParameters('sort', $this->sortClass) : ''; - $filter = null !== $this->sortClass ? $this->convertFilterParameters('filter', $this->sortClass) : []; + $filter = null !== $this->sortClass ? $this->convertFilterParameters('filter', $this->sortClass) : []; $this->attributes->set('limit', $limit); $this->attributes->set('sort', $sort); $this->attributes->set('filter', $filter); diff --git a/app/Helpers/Attachments/AttachmentHelper.php b/app/Helpers/Attachments/AttachmentHelper.php index b386a90184..45dcec4b2e 100644 --- a/app/Helpers/Attachments/AttachmentHelper.php +++ b/app/Helpers/Attachments/AttachmentHelper.php @@ -175,9 +175,10 @@ class AttachmentHelper implements AttachmentHelperInterface $parts = explode('/', $attachment->fileName()); $file = $parts[count($parts) - 1]; Log::debug(sprintf('Write file to disk in file named "%s"', $file)); - $res = $this->uploadDisk->put($file, $content); - if(false === $res) { + $res = $this->uploadDisk->put($file, $content); + if (false === $res) { Log::error('Could not write to disk.'); + return false; } diff --git a/app/Http/Controllers/Budget/BudgetLimitController.php b/app/Http/Controllers/Budget/BudgetLimitController.php index d461374baa..2edb4f5531 100644 --- a/app/Http/Controllers/Budget/BudgetLimitController.php +++ b/app/Http/Controllers/Budget/BudgetLimitController.php @@ -198,13 +198,7 @@ final class BudgetLimitController extends Controller if ($request->expectsJson()) { $array = $limit->toArray(); // add some extra metadata: - $spentArr = $this->opsRepository->sumExpenses( - $limit->start_date, - $limit->end_date, - null, - new Collection()->push($budget), - $currency - ); + $spentArr = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency); $array['spent'] = $spentArr[$currency->id]['sum'] ?? '0'; $array['left_formatted'] = Amount::formatAnything($limit->transactionCurrency, bcadd($array['spent'], (string) $array['amount'])); $array['amount_formatted'] = Amount::formatAnything($limit->transactionCurrency, $limit['amount']); diff --git a/app/Http/Controllers/Budget/IndexController.php b/app/Http/Controllers/Budget/IndexController.php index 52c6f900e3..65429e59c1 100644 --- a/app/Http/Controllers/Budget/IndexController.php +++ b/app/Http/Controllers/Budget/IndexController.php @@ -272,10 +272,7 @@ final class IndexController extends Controller if (array_key_exists($currency->id, $spentArr) && array_key_exists('sum', $spentArr[$currency->id])) { $array['spent'][$currency->id]['spent'] = $spentArr[$currency->id]['sum']; - $array['spent'][$currency->id]['spent_outside'] = Steam::negative(bcsub( - $spentInLimits[$currency->id], - $spentArr[$currency->id]['sum'] - )); + $array['spent'][$currency->id]['spent_outside'] = Steam::negative(bcsub($spentInLimits[$currency->id], $spentArr[$currency->id]['sum'])); $array['spent'][$currency->id]['currency_id'] = $currency->id; $array['spent'][$currency->id]['currency_symbol'] = $currency->symbol; $array['spent'][$currency->id]['currency_decimal_places'] = $currency->decimal_places; diff --git a/app/Http/Controllers/Chart/BudgetController.php b/app/Http/Controllers/Chart/BudgetController.php index f4b32fe5c5..ad724137dc 100644 --- a/app/Http/Controllers/Chart/BudgetController.php +++ b/app/Http/Controllers/Chart/BudgetController.php @@ -539,13 +539,7 @@ final class BudgetController extends Controller } // get spent amount in this period for this currency. - $sum = $this->opsRepository->sumExpenses( - $currentStart, - $currentEnd, - $accounts, - new Collection()->push($budget), - $currency - ); + $sum = $this->opsRepository->sumExpenses($currentStart, $currentEnd, $accounts, new Collection()->push($budget), $currency); $amount = Steam::positive($sum[$currency->id]['sum'] ?? '0'); $chartData[0]['entries'][$title] = Steam::bcround($amount, $currency->decimal_places); diff --git a/app/Http/Controllers/Report/BudgetController.php b/app/Http/Controllers/Report/BudgetController.php index 7b9511f876..64e40cde01 100644 --- a/app/Http/Controllers/Report/BudgetController.php +++ b/app/Http/Controllers/Report/BudgetController.php @@ -139,8 +139,8 @@ final class BudgetController extends Controller */ public function avgExpenses(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end) { - $spent = $this->opsRepository->listExpenses($start, $end, $accounts, $budgets); - $result = []; + $spent = $this->opsRepository->listExpenses($start, $end, $accounts, $budgets); + $result = []; foreach ($spent as $currency) { foreach ($currency['budgets'] as $budget) { foreach ($budget['transaction_journals'] as $journal) { @@ -167,7 +167,7 @@ final class BudgetController extends Controller } // sort by amount_float // sort temp array by amount. - $amounts = array_column($result, 'avg_float'); + $amounts = array_column($result, 'avg_float'); array_multisort($amounts, SORT_ASC, $result); $incomeTopLength = count(array_keys($result)); diff --git a/app/Http/Controllers/Report/CategoryController.php b/app/Http/Controllers/Report/CategoryController.php index d804a717dd..f66c7c009f 100644 --- a/app/Http/Controllers/Report/CategoryController.php +++ b/app/Http/Controllers/Report/CategoryController.php @@ -250,8 +250,8 @@ final class CategoryController extends Controller */ public function avgExpenses(Collection $accounts, Collection $categories, Carbon $start, Carbon $end) { - $spent = $this->opsRepository->listExpenses($start, $end, $accounts, $categories); - $result = []; + $spent = $this->opsRepository->listExpenses($start, $end, $accounts, $categories); + $result = []; foreach ($spent as $currency) { foreach ($currency['categories'] as $category) { foreach ($category['transaction_journals'] as $journal) { @@ -278,7 +278,7 @@ final class CategoryController extends Controller } // sort by amount_float // sort temp array by amount. - $amounts = array_column($result, 'avg_float'); + $amounts = array_column($result, 'avg_float'); array_multisort($amounts, SORT_ASC, $result); $incomeTopLength = count(array_keys($result)); diff --git a/app/Http/Controllers/Report/DoubleController.php b/app/Http/Controllers/Report/DoubleController.php index 08de552dad..674943ad2b 100644 --- a/app/Http/Controllers/Report/DoubleController.php +++ b/app/Http/Controllers/Report/DoubleController.php @@ -69,10 +69,10 @@ final class DoubleController extends Controller */ public function avgExpenses(Collection $accounts, Collection $doubles, Carbon $start, Carbon $end) { - $expanded = $this->accountRepository->expandWithDoubles($doubles); - $accounts = $accounts->merge($expanded); - $spent = $this->opsRepository->listExpenses($start, $end, $accounts); - $result = []; + $expanded = $this->accountRepository->expandWithDoubles($doubles); + $accounts = $accounts->merge($expanded); + $spent = $this->opsRepository->listExpenses($start, $end, $accounts); + $result = []; foreach ($spent as $currency) { foreach ($currency['transaction_journals'] as $journal) { $sourceId = $journal['source_account_id']; @@ -98,7 +98,7 @@ final class DoubleController extends Controller $incomeTopLength = count(array_keys($result)); // sort by amount_float // sort temp array by amount. - $amounts = array_column($result, 'avg_float'); + $amounts = array_column($result, 'avg_float'); array_multisort($amounts, SORT_ASC, $result); try { diff --git a/app/Jobs/CreateAutoBudgetLimits.php b/app/Jobs/CreateAutoBudgetLimits.php index affea656a0..476da65ac3 100644 --- a/app/Jobs/CreateAutoBudgetLimits.php +++ b/app/Jobs/CreateAutoBudgetLimits.php @@ -132,13 +132,7 @@ class CreateAutoBudgetLimits implements ShouldQueue // if has one, calculate expenses and use that as a base. $repository = app(OperationsRepositoryInterface::class); $repository->setUser($autoBudget->budget->user); - $spent = $repository->sumExpenses( - $previousStart, - $previousEnd, - null, - new Collection()->push($autoBudget->budget), - $autoBudget->transactionCurrency - ); + $spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency); $currencyId = $autoBudget->transaction_currency_id; $spentAmount = $spent[$currencyId]['sum'] ?? '0'; Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount)); @@ -228,13 +222,7 @@ class CreateAutoBudgetLimits implements ShouldQueue // if has one, calculate expenses and use that as a base. $repository = app(OperationsRepositoryInterface::class); $repository->setUser($autoBudget->budget->user); - $spent = $repository->sumExpenses( - $previousStart, - $previousEnd, - null, - new Collection()->push($autoBudget->budget), - $autoBudget->transactionCurrency - ); + $spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency); $currencyId = $autoBudget->transaction_currency_id; $spentAmount = $spent[$currencyId]['sum'] ?? '0'; Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount)); diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 1e5e45981e..c2cec98bce 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -244,8 +244,8 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac // add sort parameters $allowed = config('firefly.allowed_db_sort_parameters.Account', []); $sorted = 0; - $sort = $sort ?? []; - $filter = $filter ?? []; + $sort ??= []; + $filter ??= []; if (0 !== count($sort)) { foreach ($sort as $param) { if (in_array($param[0], $allowed, true)) { @@ -259,7 +259,7 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac if (0 !== count($filter)) { foreach ($filter as $field => $search) { if (in_array($field, $allowed, true)) { - if('' !== (string) $search) { + if ('' !== (string) $search) { $query->whereLike($field, sprintf('%%%s%%', $search)); } } diff --git a/app/Rules/IsValidFilterInstruction.php b/app/Rules/IsValidFilterInstruction.php index 316b2287e3..97eaa77602 100644 --- a/app/Rules/IsValidFilterInstruction.php +++ b/app/Rules/IsValidFilterInstruction.php @@ -1,6 +1,7 @@ class); @@ -48,16 +50,18 @@ class IsValidFilterInstruction implements ValidationRule return; } - foreach($value as $key => $search) { - if(!in_array($key, $validParameters, true)) { + foreach ($value as $key => $search) { + if (!in_array($key, $validParameters, true)) { $fail('validation.no_filter_instructions')->translate(['object' => $shortClass]); + return; } - if(strlen($search) > 50) { + if (strlen($search) > 50) { $fail('validation.no_filter_instructions')->translate(['object' => $shortClass]); + return; } } - return; + } } diff --git a/app/Support/Http/Controllers/AugumentData.php b/app/Support/Http/Controllers/AugumentData.php index a507156873..a3a940b1ba 100644 --- a/app/Support/Http/Controllers/AugumentData.php +++ b/app/Support/Http/Controllers/AugumentData.php @@ -222,14 +222,7 @@ trait AugumentData $currentEnd->addMonth(); } // primary currency amount. - $expenses = $opsRepository->sumExpenses( - $currentStart, - $currentEnd, - null, - $budgetCollection, - $entry->transactionCurrency, - $this->convertToPrimary - ); + $expenses = $opsRepository->sumExpenses($currentStart, $currentEnd, null, $budgetCollection, $entry->transactionCurrency, $this->convertToPrimary); $spent = $expenses[$currency->id]['sum'] ?? '0'; $entry->pc_spent = $spent; diff --git a/app/Support/JsonApi/Enrichments/RecurringEnrichment.php b/app/Support/JsonApi/Enrichments/RecurringEnrichment.php index 2428353cb0..d0c09bf027 100644 --- a/app/Support/JsonApi/Enrichments/RecurringEnrichment.php +++ b/app/Support/JsonApi/Enrichments/RecurringEnrichment.php @@ -354,11 +354,7 @@ class RecurringEnrichment implements EnrichmentInterface /** @var RecurrenceRepetition $repetition */ foreach ($set as $repetition) { - $recurrence = $this->collection->filter( - static fn (Recurrence $item): bool => (int) $item->id === (int) $repetition->recurrence_id - ) - ->first() - ; + $recurrence = $this->collection->filter(static fn (Recurrence $item): bool => (int) $item->id === (int) $repetition->recurrence_id)->first(); $fromDate = clone ($recurrence->latest_date ?? $recurrence->first_date); $recurrenceId = (int) $repetition->recurrence_id; $repId = (int) $repetition->id; diff --git a/app/Support/Request/ConvertsDataTypes.php b/app/Support/Request/ConvertsDataTypes.php index 7ba34a360b..ed07e3d584 100644 --- a/app/Support/Request/ConvertsDataTypes.php +++ b/app/Support/Request/ConvertsDataTypes.php @@ -151,6 +151,25 @@ trait ConvertsDataTypes return trim($string); } + public function convertFilterParameters(string $field, string $class): array + { + $parameter = request()->query->all($field); + + if (0 === count($parameter)) { + return []; + } + $shortClass = str_replace('FireflyIII\Models\\', '', $class); + $validParameters = config(sprintf('firefly.allowed_filter_parameters.%s', $shortClass)); + $return = []; + foreach ($parameter as $key => $search) { + if (in_array($key, $validParameters, true) && strlen((string) $search) <= 50) { + $return[$key] = trim((string) $search); + } + } + + return $return; + } + public function convertIban(string $field): string { return Steam::filterSpaces($this->convertString($field)); @@ -186,24 +205,6 @@ trait ConvertsDataTypes return $sortParameters; } - public function convertFilterParameters(string $field, string $class): array - { - $parameter = request()->query->all($field); - - if(0 === count($parameter)) { - return []; - } - $shortClass = str_replace('FireflyIII\Models\\', '', $class); - $validParameters = config(sprintf('firefly.allowed_filter_parameters.%s', $shortClass)); - $return = []; - foreach($parameter as $key => $search) { - if(in_array($key, $validParameters, true) && strlen((string)$search) <= 50) { - $return[$key] = trim((string)$search); - } - } - return $return; - } - /** * Return string value. */ diff --git a/changelog.md b/changelog.md index a665085326..264547d0fc 100644 --- a/changelog.md +++ b/changelog.md @@ -9,9 +9,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed -- #12928 -- #12922 -- #12929 +- [Issue 12928](https://github.com/firefly-iii/firefly-iii/issues/12928) (Webhook creation fails) reported by @Xav-v +- [Issue 12922](https://github.com/firefly-iii/firefly-iii/issues/12922) (Undefined variable $incomeTopLength in category graphs) reported by @GunoH +- [Issue 12929](https://github.com/firefly-iii/firefly-iii/issues/12929) (v6.7.6 Alpine.js requires 'unsafe-eval' in CSP – breaks behind strict proxies) reported by @37-b-j ## v6.7.6 - 2026-09-28 diff --git a/composer.lock b/composer.lock index 6995d5a086..fb291823f6 100644 --- a/composer.lock +++ b/composer.lock @@ -1012,16 +1012,16 @@ }, { "name": "firebase/php-jwt", - "version": "v7.2.0", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/googleapis/php-jwt.git", - "reference": "f502cdbf279cd7532060b041f7c22a05208c0b93" + "reference": "0501f5729b9e2448516674aff07c7d1727869b8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/f502cdbf279cd7532060b041f7c22a05208c0b93", - "reference": "f502cdbf279cd7532060b041f7c22a05208c0b93", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/0501f5729b9e2448516674aff07c7d1727869b8e", + "reference": "0501f5729b9e2448516674aff07c7d1727869b8e", "shasum": "" }, "require": { @@ -1080,9 +1080,9 @@ ], "support": { "issues": "https://github.com/googleapis/php-jwt/issues", - "source": "https://github.com/googleapis/php-jwt/tree/v7.2.0" + "source": "https://github.com/googleapis/php-jwt/tree/v7.2.1" }, - "time": "2026-09-21T19:29:58+00:00" + "time": "2026-09-28T17:51:46+00:00" }, { "name": "fruitcake/php-cors", @@ -1897,16 +1897,16 @@ }, { "name": "laravel/framework", - "version": "v13.33.0", + "version": "v13.34.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "91188a17ceaa3dbace6e8a5f7abd0d042e466359" + "reference": "c829b4982d29344cbcf1d7ad78eb5d2bb8ae66c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/91188a17ceaa3dbace6e8a5f7abd0d042e466359", - "reference": "91188a17ceaa3dbace6e8a5f7abd0d042e466359", + "url": "https://api.github.com/repos/laravel/framework/zipball/c829b4982d29344cbcf1d7ad78eb5d2bb8ae66c4", + "reference": "c829b4982d29344cbcf1d7ad78eb5d2bb8ae66c4", "shasum": "" }, "require": { @@ -2022,10 +2022,10 @@ "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", "opis/json-schema": "^2.4.1", - "orchestra/testbench-core": "^11.0.0", + "orchestra/testbench-core": "^11.5.0", "pda/pheanstalk": "^7.0.0 || ^8.0.0", "php-http/discovery": "^1.15", - "phpstan/phpstan": "^2.2.14", + "phpstan/phpstan": "2.2.15", "phpunit/phpunit": "^11.5.50 || ^12.5.8 || ^13.0.3", "predis/predis": "^2.3 || ^3.0", "rector/rector": "2.6.3", @@ -2124,7 +2124,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2026-09-22T14:12:33+00:00" + "time": "2026-09-29T12:46:21+00:00" }, { "name": "laravel/passport", @@ -3535,16 +3535,16 @@ }, { "name": "monolog/monolog", - "version": "3.12.0", + "version": "3.12.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "72c534fc0ab181ef52d92a68382318631e301608" + "reference": "d7059e4c691d05ea1222b5124bed0f961be46e15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/72c534fc0ab181ef52d92a68382318631e301608", - "reference": "72c534fc0ab181ef52d92a68382318631e301608", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/d7059e4c691d05ea1222b5124bed0f961be46e15", + "reference": "d7059e4c691d05ea1222b5124bed0f961be46e15", "shasum": "" }, "require": { @@ -3624,7 +3624,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.12.0" + "source": "https://github.com/Seldaek/monolog/tree/3.12.1" }, "funding": [ { @@ -3636,7 +3636,7 @@ "type": "tidelift" } ], - "time": "2026-09-09T08:34:20+00:00" + "time": "2026-09-29T19:21:12+00:00" }, { "name": "nesbot/carbon", @@ -6412,16 +6412,16 @@ }, { "name": "symfony/cache", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "47616ab077b5aff4d0f718b96680a48599fc1a3f" + "reference": "8888daf06a2fc8440346215d3b52f3c611cc486d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/47616ab077b5aff4d0f718b96680a48599fc1a3f", - "reference": "47616ab077b5aff4d0f718b96680a48599fc1a3f", + "url": "https://api.github.com/repos/symfony/cache/zipball/8888daf06a2fc8440346215d3b52f3c611cc486d", + "reference": "8888daf06a2fc8440346215d3b52f3c611cc486d", "shasum": "" }, "require": { @@ -6487,7 +6487,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v8.1.7" + "source": "https://github.com/symfony/cache/tree/v8.1.8" }, "funding": [ { @@ -6507,7 +6507,7 @@ "type": "tidelift" } ], - "time": "2026-09-08T13:39:13+00:00" + "time": "2026-09-29T12:38:40+00:00" }, { "name": "symfony/cache-contracts", @@ -6668,16 +6668,16 @@ }, { "name": "symfony/console", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "29afb89f4e941f68a6e90f28e3f52ff1f6793a7d" + "reference": "4b81146e3ee248ea969186f85499b54fbc78db08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/29afb89f4e941f68a6e90f28e3f52ff1f6793a7d", - "reference": "29afb89f4e941f68a6e90f28e3f52ff1f6793a7d", + "url": "https://api.github.com/repos/symfony/console/zipball/4b81146e3ee248ea969186f85499b54fbc78db08", + "reference": "4b81146e3ee248ea969186f85499b54fbc78db08", "shasum": "" }, "require": { @@ -6744,7 +6744,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v8.1.7" + "source": "https://github.com/symfony/console/tree/v8.1.8" }, "funding": [ { @@ -6764,7 +6764,7 @@ "type": "tidelift" } ], - "time": "2026-09-13T10:55:57+00:00" + "time": "2026-09-18T16:00:27+00:00" }, { "name": "symfony/css-selector", @@ -6908,16 +6908,16 @@ }, { "name": "symfony/error-handler", - "version": "v8.1.5", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8b2a4289ffe5e2dc8fcf645b8e7870e1fa0325ce" + "reference": "c146daceccd5d4f864c051b233c276641cec527b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8b2a4289ffe5e2dc8fcf645b8e7870e1fa0325ce", - "reference": "8b2a4289ffe5e2dc8fcf645b8e7870e1fa0325ce", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/c146daceccd5d4f864c051b233c276641cec527b", + "reference": "c146daceccd5d4f864c051b233c276641cec527b", "shasum": "" }, "require": { @@ -6965,7 +6965,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v8.1.5" + "source": "https://github.com/symfony/error-handler/tree/v8.1.8" }, "funding": [ { @@ -6985,7 +6985,7 @@ "type": "tidelift" } ], - "time": "2026-08-21T17:47:34+00:00" + "time": "2026-09-22T18:58:53+00:00" }, { "name": "symfony/event-dispatcher", @@ -7222,16 +7222,16 @@ }, { "name": "symfony/finder", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "4fbe46a3eb64abf8a57f0364075b91f4a233e062" + "reference": "bd4fed193a3132c91c5c93595cbfc78988915822" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/4fbe46a3eb64abf8a57f0364075b91f4a233e062", - "reference": "4fbe46a3eb64abf8a57f0364075b91f4a233e062", + "url": "https://api.github.com/repos/symfony/finder/zipball/bd4fed193a3132c91c5c93595cbfc78988915822", + "reference": "bd4fed193a3132c91c5c93595cbfc78988915822", "shasum": "" }, "require": { @@ -7266,7 +7266,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v8.1.7" + "source": "https://github.com/symfony/finder/tree/v8.1.8" }, "funding": [ { @@ -7286,20 +7286,20 @@ "type": "tidelift" } ], - "time": "2026-09-10T19:14:39+00:00" + "time": "2026-09-26T06:33:49+00:00" }, { "name": "symfony/http-client", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "099aae7d3619bffb5e68b33dbbadf6649c6d49c5" + "reference": "e20aca4ceaa888197de5c792ffc551d99e43d98a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/099aae7d3619bffb5e68b33dbbadf6649c6d49c5", - "reference": "099aae7d3619bffb5e68b33dbbadf6649c6d49c5", + "url": "https://api.github.com/repos/symfony/http-client/zipball/e20aca4ceaa888197de5c792ffc551d99e43d98a", + "reference": "e20aca4ceaa888197de5c792ffc551d99e43d98a", "shasum": "" }, "require": { @@ -7363,7 +7363,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v8.1.7" + "source": "https://github.com/symfony/http-client/tree/v8.1.8" }, "funding": [ { @@ -7383,7 +7383,7 @@ "type": "tidelift" } ], - "time": "2026-09-08T13:39:13+00:00" + "time": "2026-09-24T11:09:32+00:00" }, { "name": "symfony/http-client-contracts", @@ -7469,16 +7469,16 @@ }, { "name": "symfony/http-foundation", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "d8fdc670ed510a69e3a9eb4f5eac89f5ed627e17" + "reference": "662f5257658d4f60deff1bc790e9f2c68cb391bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d8fdc670ed510a69e3a9eb4f5eac89f5ed627e17", - "reference": "d8fdc670ed510a69e3a9eb4f5eac89f5ed627e17", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/662f5257658d4f60deff1bc790e9f2c68cb391bf", + "reference": "662f5257658d4f60deff1bc790e9f2c68cb391bf", "shasum": "" }, "require": { @@ -7526,7 +7526,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v8.1.7" + "source": "https://github.com/symfony/http-foundation/tree/v8.1.8" }, "funding": [ { @@ -7546,20 +7546,20 @@ "type": "tidelift" } ], - "time": "2026-09-14T17:47:24+00:00" + "time": "2026-09-24T07:13:53+00:00" }, { "name": "symfony/http-kernel", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "ec7a3a5832c22cf880cf27d2fdc7ad2e94838e85" + "reference": "51c014e881d8b4ce61e56c0d4105f65b50df786a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ec7a3a5832c22cf880cf27d2fdc7ad2e94838e85", - "reference": "ec7a3a5832c22cf880cf27d2fdc7ad2e94838e85", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/51c014e881d8b4ce61e56c0d4105f65b50df786a", + "reference": "51c014e881d8b4ce61e56c0d4105f65b50df786a", "shasum": "" }, "require": { @@ -7636,7 +7636,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v8.1.7" + "source": "https://github.com/symfony/http-kernel/tree/v8.1.8" }, "funding": [ { @@ -7656,7 +7656,7 @@ "type": "tidelift" } ], - "time": "2026-09-15T07:12:52+00:00" + "time": "2026-09-29T14:08:01+00:00" }, { "name": "symfony/mailer", @@ -9030,16 +9030,16 @@ }, { "name": "symfony/routing", - "version": "v8.1.6", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "3c188091b6b4fa2e4bc83a135caede12deb8576c" + "reference": "e46d741c56485441f37104a3e7eace4e17ed91f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/3c188091b6b4fa2e4bc83a135caede12deb8576c", - "reference": "3c188091b6b4fa2e4bc83a135caede12deb8576c", + "url": "https://api.github.com/repos/symfony/routing/zipball/e46d741c56485441f37104a3e7eace4e17ed91f9", + "reference": "e46d741c56485441f37104a3e7eace4e17ed91f9", "shasum": "" }, "require": { @@ -9086,7 +9086,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v8.1.6" + "source": "https://github.com/symfony/routing/tree/v8.1.8" }, "funding": [ { @@ -9106,7 +9106,7 @@ "type": "tidelift" } ], - "time": "2026-08-17T13:18:34+00:00" + "time": "2026-09-28T19:13:15+00:00" }, { "name": "symfony/service-contracts", @@ -9462,16 +9462,16 @@ }, { "name": "symfony/uid", - "version": "v8.1.5", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "a08aef47989093f32fe50fd11859be1b427df389" + "reference": "f412a0b5edd75eb3104a93bd0d11fd2ea3da34e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/a08aef47989093f32fe50fd11859be1b427df389", - "reference": "a08aef47989093f32fe50fd11859be1b427df389", + "url": "https://api.github.com/repos/symfony/uid/zipball/f412a0b5edd75eb3104a93bd0d11fd2ea3da34e4", + "reference": "f412a0b5edd75eb3104a93bd0d11fd2ea3da34e4", "shasum": "" }, "require": { @@ -9516,7 +9516,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v8.1.5" + "source": "https://github.com/symfony/uid/tree/v8.1.8" }, "funding": [ { @@ -9536,7 +9536,7 @@ "type": "tidelift" } ], - "time": "2026-08-11T13:39:01+00:00" + "time": "2026-09-23T17:45:45+00:00" }, { "name": "symfony/var-dumper", @@ -12188,16 +12188,16 @@ }, { "name": "phpunit/phpunit", - "version": "13.3.5", + "version": "13.3.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1b482b9a77774705a5c4a47ab7d60819d2589e90" + "reference": "b7d0ee4ea89121cb963302b8708b1c09d9ebc7d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1b482b9a77774705a5c4a47ab7d60819d2589e90", - "reference": "1b482b9a77774705a5c4a47ab7d60819d2589e90", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7d0ee4ea89121cb963302b8708b1c09d9ebc7d6", + "reference": "b7d0ee4ea89121cb963302b8708b1c09d9ebc7d6", "shasum": "" }, "require": { @@ -12268,7 +12268,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/13.3.5" + "source": "https://github.com/sebastianbergmann/phpunit/tree/13.3.6" }, "funding": [ { @@ -12276,7 +12276,7 @@ "type": "other" } ], - "time": "2026-09-25T08:41:20+00:00" + "time": "2026-09-29T12:12:05+00:00" }, { "name": "rector/rector", @@ -13622,6 +13622,7 @@ "type": "github" } ], + "abandoned": true, "time": "2024-03-18T22:02:54+00:00" }, { diff --git a/config/firefly.php b/config/firefly.php index cb9fb617e8..179a74f5b4 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -78,8 +78,8 @@ return [ 'running_balance_column' => (bool)env_default_when_empty(env('USE_RUNNING_BALANCE'), true), // this is only the default value, is not used. // see cer.php for exchange rates feature flag. ], -'version' => '6.7.6', -'build_time' => 1790572120, +'version' => 'develop/2026-09-29', +'build_time' => 1790710740, 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 28, // field is no longer used. @@ -848,9 +848,9 @@ return [ // dynamic date ranges are as follows: 'dynamic_date_ranges' => ['last7', 'last30', 'last90', 'last365', 'MTD', 'QTD', 'YTD'], - 'allowed_filter_parameters' => [ + 'allowed_filter_parameters' => [ 'Account' => [ - 'name' + 'name', ], ], 'allowed_sort_parameters' => [ diff --git a/package-lock.json b/package-lock.json index 7349b999f3..f52da85a42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -474,9 +474,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -498,9 +495,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -522,9 +516,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -546,9 +537,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -570,9 +558,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -594,9 +579,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -786,9 +768,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -806,9 +785,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -826,9 +802,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -846,9 +819,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -866,9 +836,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -886,9 +853,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2566,9 +2530,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -2590,9 +2551,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -2614,9 +2572,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -2638,9 +2593,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ diff --git a/resources/assets/v3/js/pages/accounts/index.js b/resources/assets/v3/js/pages/accounts/index.js index fad4c0a893..07a40760eb 100644 --- a/resources/assets/v3/js/pages/accounts/index.js +++ b/resources/assets/v3/js/pages/accounts/index.js @@ -22,13 +22,13 @@ import "../../boot/bootstrap.js"; import sidebar from "../shared/sidebar.js"; import dates from "../shared/dates.js"; import Alpine from "@alpinejs/csp"; -import {getVariable} from "../../store/get-variable.js"; +import { getVariable } from "../../store/get-variable.js"; import Put from "../../api/model/account/put.js"; import Get from "../../api/model/account/get.js"; -import format from '../../util/format.js'; +import format from "../../util/format.js"; import formatMoney from "../../util/format-money.js"; import i18next from "i18next"; -import {addDrag} from "../shared/drag-and-droppable-rows.js"; +import { addDrag } from "../shared/drag-and-droppable-rows.js"; window.enableDates = false; @@ -40,7 +40,7 @@ let index = function () { accounts: [], sortDirection: "asc", page: 1, - i18next:null, + i18next: null, anonymous: false, totalPages: 1, loadingPage: true, @@ -53,22 +53,24 @@ let index = function () { debts: {}, differences: {}, filter: { - name: '', + name: "", }, formatMoney: formatMoney, objectToQueryString(obj, prefix) { - return Object.keys(obj).map(objKey => { - if (Object.hasOwn(obj, objKey)) { - const key = prefix ? `${prefix}[${objKey}]` : objKey; - const value = obj[objKey]; + return Object.keys(obj) + .map((objKey) => { + if (Object.hasOwn(obj, objKey)) { + const key = prefix ? `${prefix}[${objKey}]` : objKey; + const value = obj[objKey]; - return typeof value === "object" ? - this.objectToQueryString(value, key) : - `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; - } + return typeof value === "object" + ? this.objectToQueryString(value, key) + : `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } - return null; - }).join("&"); + return null; + }) + .join("&"); }, updateHistory() { @@ -78,27 +80,23 @@ let index = function () { page: this.page, column: this.sortColumn, direction: this.sortDirection, - filter: this.filter + filter: this.filter, }; let string = this.objectToQueryString(obj); let newUrl = - window.location.protocol + - "//" + - window.location.host + - window.location.pathname + - "?" + string; - window.history.pushState({path: newUrl}, "", newUrl); - window.store.set(this.storageKey, {column: this.sortColumn, direction: this.sortDirection}); + window.location.protocol + "//" + window.location.host + window.location.pathname + "?" + string; + window.history.pushState({ path: newUrl }, "", newUrl); + window.store.set(this.storageKey, { column: this.sortColumn, direction: this.sortDirection }); } }, updateFilterValue(field, newValue) { - console.log('Update', field, newValue); + console.log("Update", field, newValue); this.filter[field] = newValue; this.updateHistory(); this.downloadAccounts(); }, init() { - this.$watch('filter.name', (value) => this.updateFilterValue('name', value)); + this.$watch("filter.name", (value) => this.updateFilterValue("name", value)); this.i18next = i18next; this.anonymous = window.store.get("anonymous"); @@ -156,17 +154,18 @@ let index = function () { el.addEventListener("click", () => { let column = el.dataset.column; // show search input again - document.querySelector(`span.title[data-column="${column}"]`).classList.remove('d-none'); - document.querySelector(`span.search-spacer[data-column="${column}"]`).classList.remove('d-none'); - document.querySelector(`em.search-button[data-column="${column}"]`).classList.remove('d-none'); - document.querySelector(`div.search-filter[data-column="${column}"] input`).value = ''; + document.querySelector(`span.title[data-column="${column}"]`).classList.remove("d-none"); + document + .querySelector(`span.search-spacer[data-column="${column}"]`) + .classList.remove("d-none"); + document.querySelector(`em.search-button[data-column="${column}"]`).classList.remove("d-none"); + document.querySelector(`div.search-filter[data-column="${column}"] input`).value = ""; let input = document.querySelector(`div.search-filter[data-column="${column}"]`); - input.classList.add('d-none'); + input.classList.add("d-none"); // TODO hardcoded!! - this.filter.name = ''; - + this.filter.name = ""; }); }); @@ -175,20 +174,18 @@ let index = function () { el.addEventListener("click", () => { let column = el.dataset.column; // hide search buttons etc. - el.classList.add('d-none'); - document.querySelector(`span.title[data-column="${column}"]`).classList.add('d-none'); - document.querySelector(`span.search-spacer[data-column="${column}"]`).classList.add('d-none'); + el.classList.add("d-none"); + document.querySelector(`span.title[data-column="${column}"]`).classList.add("d-none"); + document.querySelector(`span.search-spacer[data-column="${column}"]`).classList.add("d-none"); // show search input let input = document.querySelector(`div.search-filter[data-column="${column}"]`); - input.classList.remove('d-none'); - input.querySelector('input').focus(); + input.classList.remove("d-none"); + input.querySelector("input").focus(); }); }); - }); - getVariable("listPageSize").then((listPageSize) => { this.listPageSize = listPageSize; addDrag(); @@ -198,7 +195,7 @@ let index = function () { let item = e.detail[i]; if (item.order !== item.currentOrder) { // PUT new order to system. - new Put().put({order: item.order}, {id: item.id}); + new Put().put({ order: item.order }, { id: item.id }); // save new order as current order in the row. document .querySelector(`tr[data-id="${item.id}"]`) @@ -362,7 +359,11 @@ let index = function () { if (null === date) { return ""; } - return format(new Date(date), i18next.t("config.date_time_fns_short", {lng: window.store.get("locale")}), window.store.get("locale")); + return format( + new Date(date), + i18next.t("config.date_time_fns_short", { lng: window.store.get("locale") }), + window.store.get("locale"), + ); }, handlePageClick(e) { let link = e.currentTarget; diff --git a/resources/assets/v3/js/pages/dashboard/dashboard.js b/resources/assets/v3/js/pages/dashboard/dashboard.js index 201cb71b84..6649fcbba2 100644 --- a/resources/assets/v3/js/pages/dashboard/dashboard.js +++ b/resources/assets/v3/js/pages/dashboard/dashboard.js @@ -36,8 +36,7 @@ let index = function () { anonymous: false, loadingPiggyBanks: true, init() { - - console.log('I am translation'); + console.log("I am translation"); console.log(i18next.t(format(new Date(), "d MMMM yyyy 'o' HH:mm"))); getVariable("anonymous").then((value) => { diff --git a/resources/assets/v3/js/pages/transactions/create.js b/resources/assets/v3/js/pages/transactions/create.js index f7152269da..4d6802793e 100644 --- a/resources/assets/v3/js/pages/transactions/create.js +++ b/resources/assets/v3/js/pages/transactions/create.js @@ -342,7 +342,6 @@ let create = function () { }, save() { - this.notifications.error.show = false; this.notifications.success.show = false; this.notifications.wait.show = true; diff --git a/resources/assets/v3/js/pages/transactions/shared/autocomplete-functions.js b/resources/assets/v3/js/pages/transactions/shared/autocomplete-functions.js index 910a21c772..79539de6d7 100644 --- a/resources/assets/v3/js/pages/transactions/shared/autocomplete-functions.js +++ b/resources/assets/v3/js/pages/transactions/shared/autocomplete-functions.js @@ -37,11 +37,11 @@ export function changeDescription(item, ac) { } export function changeDestinationAccount(item, ac) { - console.log('changeDestinationAccount', item, ac); + console.log("changeDestinationAccount", item, ac); if (typeof item === "object") { // changed account but did not select. const index = parseInt(ac._searchInput.dataset.index); - console.log('changeDestinationAccount X', document.querySelector("#form")); + console.log("changeDestinationAccount X", document.querySelector("#form")); document.querySelector("#form")._x_dataStack[0].$data.entries[index].destination_account = { id: item.id, name: item.name, @@ -69,7 +69,7 @@ export function changeDestinationAccount(item, ac) { export function selectDestinationAccount(item, ac) { const index = parseInt(ac._searchInput.attributes["data-index"].value); - console.log('selectDestinationAccount', index); + console.log("selectDestinationAccount", index); document.querySelector("#form")._x_dataStack[0].$data.entries[index].destination_account = { id: item.id, name: item.name, diff --git a/resources/assets/v3/js/pages/transactions/shared/keyup-from-category.js b/resources/assets/v3/js/pages/transactions/shared/keyup-from-category.js index 9fdbe5902b..f26db167dc 100644 --- a/resources/assets/v3/js/pages/transactions/shared/keyup-from-category.js +++ b/resources/assets/v3/js/pages/transactions/shared/keyup-from-category.js @@ -20,7 +20,7 @@ export function keyUpFromCategory(e) { let target = null === e.currentTarget ? null : e.currentTarget.nextSibling; - if ("Enter" === e.key && 'UL' === target.nodeName && !target.classList.contains("show")) { + if ("Enter" === e.key && "UL" === target.nodeName && !target.classList.contains("show")) { this.save(); } } diff --git a/resources/assets/v3/js/pages/transactions/shared/keyup-from-description.js b/resources/assets/v3/js/pages/transactions/shared/keyup-from-description.js index 34f9db986b..c19a5d90df 100644 --- a/resources/assets/v3/js/pages/transactions/shared/keyup-from-description.js +++ b/resources/assets/v3/js/pages/transactions/shared/keyup-from-description.js @@ -18,10 +18,9 @@ * along with this program. If not, see . */ - export function keyUpFromDescription(e) { let target = null === e.currentTarget ? null : e.currentTarget.nextSibling; - if ("Enter" === e.key && 'UL' === target.nodeName && !target.classList.contains("show")) { + if ("Enter" === e.key && "UL" === target.nodeName && !target.classList.contains("show")) { this.save(); } } diff --git a/resources/assets/v3/js/pages/transactions/shared/keyup-from-destination.js b/resources/assets/v3/js/pages/transactions/shared/keyup-from-destination.js index c9ac806610..be3b8f4baa 100644 --- a/resources/assets/v3/js/pages/transactions/shared/keyup-from-destination.js +++ b/resources/assets/v3/js/pages/transactions/shared/keyup-from-destination.js @@ -20,8 +20,7 @@ export function keyUpFromDestination(e) { let target = null === e.currentTarget ? null : e.currentTarget.nextSibling; - if ("Enter" === e.key && 'UL' === target.nodeName && !target.classList.contains("show")) { + if ("Enter" === e.key && "UL" === target.nodeName && !target.classList.contains("show")) { this.save(); } - } diff --git a/resources/assets/v3/js/pages/transactions/shared/keyup-from-source.js b/resources/assets/v3/js/pages/transactions/shared/keyup-from-source.js index 594f637716..a3628dcda8 100644 --- a/resources/assets/v3/js/pages/transactions/shared/keyup-from-source.js +++ b/resources/assets/v3/js/pages/transactions/shared/keyup-from-source.js @@ -20,7 +20,7 @@ export function keyUpFromSource(e) { let target = null === e.currentTarget ? null : e.currentTarget.nextSibling; - if ("Enter" === e.key && 'UL' === target.nodeName && !target.classList.contains("show")) { + if ("Enter" === e.key && "UL" === target.nodeName && !target.classList.contains("show")) { this.save(); } } diff --git a/resources/assets/v3/js/util/format-money.js b/resources/assets/v3/js/util/format-money.js index 6299040170..ff77a533b3 100644 --- a/resources/assets/v3/js/util/format-money.js +++ b/resources/assets/v3/js/util/format-money.js @@ -20,7 +20,7 @@ export default function (amount, currencyCode) { if ((typeof amount !== "number" && typeof amount !== "string") || isNaN(amount)) { - if(null !== amount) { + if (null !== amount) { console.warn("format-money: amount is not a number:", amount); } return ""; diff --git a/resources/assets/v3/js/util/format.js b/resources/assets/v3/js/util/format.js index 8da335d829..f022f10e6c 100644 --- a/resources/assets/v3/js/util/format.js +++ b/resources/assets/v3/js/util/format.js @@ -95,11 +95,11 @@ export default function (date, formatStr = "PP", locale) { if (typeof locale === "undefined") { locale = window.__localeId__.replace("_", ""); } - let res = '(DATE ERROR)'; + let res = "(DATE ERROR)"; try { - res = format(date, formatStr, {locale: locales[locale] ?? locales[locale.slice(0, 2)] ?? locales["enUS"],}); - } catch(error) { - console.warn('Could not format date: ', error); + res = format(date, formatStr, { locale: locales[locale] ?? locales[locale.slice(0, 2)] ?? locales["enUS"] }); + } catch (error) { + console.warn("Could not format date: ", error); } // console.log("Locale is " + locale); return res; diff --git a/resources/assets/v3/js/util/serialize.js b/resources/assets/v3/js/util/serialize.js index 04ccef3f04..abcff4646d 100644 --- a/resources/assets/v3/js/util/serialize.js +++ b/resources/assets/v3/js/util/serialize.js @@ -1,11 +1,15 @@ - - -export default function serialize (obj, prefix) { - let str = [], p; +export default function serialize(obj, prefix) { + let str = [], + p; for (p in obj) { if (Object.hasOwn(obj, p)) { - let k = prefix ? prefix + "[" + p + "]" : p, v = obj[p]; - str.push((v !== null && typeof v === "object") ? serialize(v, k) : encodeURIComponent(k) + "=" + encodeURIComponent(v)); + let k = prefix ? prefix + "[" + p + "]" : p, + v = obj[p]; + str.push( + v !== null && typeof v === "object" + ? serialize(v, k) + : encodeURIComponent(k) + "=" + encodeURIComponent(v), + ); } } return str.join("&"); diff --git a/resources/lang/en_US/validation.php b/resources/lang/en_US/validation.php index 8cab50b1f7..a4f642ad69 100644 --- a/resources/lang/en_US/validation.php +++ b/resources/lang/en_US/validation.php @@ -31,7 +31,7 @@ return [ 'invalid_transaction_type_list' => 'Invalid transaction type list', 'limit_exists' => 'There is already a budget limit (amount) for this budget and currency in the given period.', 'invalid_sort_instruction' => 'The sort instruction is invalid for an object of type ":object".', - 'no_filter_instructions' => 'The filter instruction is invalid for an object of type ":object".', + 'no_filter_instructions' => 'The filter instruction is invalid for an object of type ":object".', 'invalid_sort_instruction_index' => 'The sort instruction at index #:index is invalid for an object of type ":object".', 'no_sort_instructions' => 'There are no sort instructions defined for an object of type ":object".', 'webhook_budget_info' => 'Cannot deliver budget information for transaction related webhooks.',