Compare commits

..

90 Commits

Author SHA1 Message Date
github-actions[bot]
08c9703900 Merge pull request #11137 from firefly-iii/release-1761889447
🤖 Automatically merge the PR into the develop branch.
2025-10-31 06:44:16 +01:00
JC5
101f56d1b1 🤖 Auto commit for release 'develop' on 2025-10-31 2025-10-31 06:44:07 +01:00
James Cole
83bdaff033 Update changelog. 2025-10-31 06:39:28 +01:00
James Cole
e25fbcfb19 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-10-31 06:31:02 +01:00
James Cole
40c4c9f109 Fix #11132 2025-10-31 06:30:56 +01:00
github-actions[bot]
d178956541 Merge pull request #11135 from firefly-iii/release-1761853876
🤖 Automatically merge the PR into the develop branch.
2025-10-30 20:51:23 +01:00
JC5
c29f997733 🤖 Auto commit for release 'develop' on 2025-10-30 2025-10-30 20:51:16 +01:00
James Cole
2aabb56d2d Fix https://github.com/firefly-iii/firefly-iii/issues/11134 2025-10-30 20:46:43 +01:00
github-actions[bot]
e1e18a2a0c Merge pull request #11130 from firefly-iii/release-1761763997
🤖 Automatically merge the PR into the develop branch.
2025-10-29 19:53:25 +01:00
JC5
2c41694f41 🤖 Auto commit for release 'develop' on 2025-10-29 2025-10-29 19:53:18 +01:00
James Cole
48a641286c Fix account type list. 2025-10-29 19:47:35 +01:00
James Cole
5eec91f439 Merge branch 'main' into develop
# Conflicts:
#	package-lock.json
2025-10-29 19:22:19 +01:00
James Cole
782f0c7d54 Update readme. 2025-10-29 17:41:56 +01:00
James Cole
a4dff6d39f Fix #11122 2025-10-27 10:00:16 +01:00
James Cole
9312ddbb7b Reset the anonimity. 2025-10-27 08:51:50 +01:00
github-actions[bot]
14a9bede11 Merge pull request #11121 from firefly-iii/release-1761535923
🤖 Automatically merge the PR into the develop branch.
2025-10-27 04:32:13 +01:00
JC5
58d798df86 🤖 Auto commit for release 'develop' on 2025-10-27 2025-10-27 04:32:03 +01:00
James Cole
e740fc57a6 Replace a few request class calls. 2025-10-26 17:15:54 +01:00
James Cole
ecd7750030 Replace a few request instances. 2025-10-26 16:04:03 +01:00
James Cole
19c4a82194 Use new API request. 2025-10-26 15:37:27 +01:00
James Cole
ffc91d5ead Migrate one of the API endpoints to the new unified API thing. 2025-10-26 12:28:42 +01:00
James Cole
4898c29b85 Replace reference to facade. 2025-10-26 12:12:30 +01:00
github-actions[bot]
84b4ab0cc2 Merge pull request #11112 from firefly-iii/release-1761470095
🤖 Automatically merge the PR into the develop branch.
2025-10-26 10:15:03 +01:00
JC5
eb808a0fbc 🤖 Auto commit for release 'develop' on 2025-10-26 2025-10-26 10:14:55 +01:00
James Cole
d25ae50d30 Fix routes. 2025-10-26 10:09:59 +01:00
github-actions[bot]
c43821e29c Merge pull request #11111 from firefly-iii/release-1761469189
🤖 Automatically merge the PR into the develop branch.
2025-10-26 09:59:56 +01:00
JC5
b7570b2651 🤖 Auto commit for release 'develop' on 2025-10-26 2025-10-26 09:59:49 +01:00
James Cole
cb77609f27 Add disclaimer. 2025-10-26 09:55:51 +01:00
James Cole
99651bb61e Catch some exceptions. 2025-10-26 09:53:19 +01:00
James Cole
bf1e14f66d Explain about user agents. 2025-10-26 09:45:00 +01:00
github-actions[bot]
d0e55804f8 Merge pull request #11110 from firefly-iii/release-1761467960
🤖 Automatically merge the PR into the develop branch.
2025-10-26 09:39:29 +01:00
JC5
0a9715b8c1 🤖 Auto commit for release 'develop' on 2025-10-26 2025-10-26 09:39:20 +01:00
James Cole
61390e67f6 Add debug info. 2025-10-26 09:34:40 +01:00
James Cole
536d25980f Fix issues related to #11109 2025-10-26 09:31:07 +01:00
github-actions[bot]
3253b2e569 Merge pull request #11107 from firefly-iii/release-1761395685
🤖 Automatically merge the PR into the develop branch.
2025-10-25 14:34:54 +02:00
JC5
11ac955303 🤖 Auto commit for release 'develop' on 2025-10-25 2025-10-25 14:34:46 +02:00
James Cole
caf9a31bc4 Replace version with build time. 2025-10-25 14:30:22 +02:00
github-actions[bot]
8c84ab5855 Merge pull request #11106 from firefly-iii/release-1761394994
🤖 Automatically merge the PR into the develop branch.
2025-10-25 14:23:23 +02:00
JC5
91a56a7396 🤖 Auto commit for release 'develop' on 2025-10-25 2025-10-25 14:23:14 +02:00
James Cole
f5806ea6de Fix #11102 2025-10-25 14:09:44 +02:00
James Cole
60b3692ac9 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-10-25 11:50:43 +02:00
James Cole
0bdb4f2e69 Fix https://github.com/orgs/firefly-iii/discussions/11104 2025-10-25 11:50:34 +02:00
github-actions[bot]
f89f50c2db Merge pull request #11101 from firefly-iii/release-1761383546
🤖 Automatically merge the PR into the develop branch.
2025-10-25 11:12:35 +02:00
JC5
394df46961 🤖 Auto commit for release 'develop' on 2025-10-25 2025-10-25 11:12:26 +02:00
James Cole
535e5e4f50 Catch null pointer. 2025-10-25 11:08:07 +02:00
James Cole
00ba2a46d2 Fix #11063 2025-10-25 09:20:21 +02:00
James Cole
a3ff26e3e4 Fix https://github.com/firefly-iii/firefly-iii/issues/11096 2025-10-23 16:54:13 +02:00
James Cole
3388cb6f66 Merge pull request #11085 from firefly-iii/dependabot/npm_and_yarn/npm_and_yarn-fd296dbd23
Bump vite from 7.1.9 to 7.1.11 in the npm_and_yarn group across 1 directory
2025-10-21 07:13:37 +02:00
dependabot[bot]
1c3c9377ca Bump vite in the npm_and_yarn group across 1 directory
Bumps the npm_and_yarn group with 1 update in the / directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 7.1.9 to 7.1.11
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.11/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.11
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-20 22:58:03 +00:00
github-actions[bot]
54aeb4b4ef Merge pull request #11084 from firefly-iii/release-1760930902
🤖 Automatically merge the PR into the develop branch.
2025-10-20 05:28:30 +02:00
JC5
9eb3ad62dd 🤖 Auto commit for release 'develop' on 2025-10-20 2025-10-20 05:28:22 +02:00
github-actions[bot]
4f0e978687 Merge pull request #11060 from firefly-iii/release-1760325917
🤖 Automatically merge the PR into the develop branch.
2025-10-13 05:25:26 +02:00
JC5
e1cf9f7a79 🤖 Auto commit for release 'develop' on 2025-10-13 2025-10-13 05:25:17 +02:00
James Cole
7ce055a22c Merge pull request #11056 from ctrl-f5/feat/account-attachment-list-request
account/attachments endpoint use request object for pagination, add test
2025-10-12 20:15:00 +02:00
Nicky De Maeyer
7bd915930c account/attachments endpoint use request object for pagination, add test 2025-10-12 19:54:47 +02:00
github-actions[bot]
75aa2d99fd Merge pull request #11055 from firefly-iii/release-1760278017
🤖 Automatically merge the PR into the develop branch.
2025-10-12 16:07:07 +02:00
JC5
f52bc0e242 🤖 Auto commit for release 'develop' on 2025-10-12 2025-10-12 16:06:57 +02:00
James Cole
55cf924794 Another fix for #11054 2025-10-12 16:02:14 +02:00
James Cole
df3e4a6554 Fix #11054 2025-10-12 12:25:21 +02:00
James Cole
7c4ada458e Merge pull request #11052 from ctrl-f5/fix/incorrect-validator-function
correct validator function to check for errors + `Account\ShowControllerTest`
2025-10-12 06:47:19 +02:00
Nicky De Maeyer
2a4a98dd10 use the correct validator function to check for errors, add a test for ShowController 2025-10-11 23:02:54 +02:00
github-actions[bot]
a3bf845851 Merge pull request #11051 from firefly-iii/release-1760189013
🤖 Automatically merge the PR into the develop branch.
2025-10-11 15:23:39 +02:00
JC5
78e832cdba 🤖 Auto commit for release 'develop' on 2025-10-11 2025-10-11 15:23:33 +02:00
James Cole
d47e4c4f24 Fix #11050 2025-10-11 15:17:51 +02:00
github-actions[bot]
056329291f Merge pull request #11049 from firefly-iii/release-1760159506
🤖 Automatically merge the PR into the develop branch.
2025-10-11 07:11:57 +02:00
JC5
977946064d 🤖 Auto commit for release 'develop' on 2025-10-11 2025-10-11 07:11:46 +02:00
James Cole
1870345ddf Add new request in style of aggregated requests, fix issue with missing field. 2025-10-11 07:05:32 +02:00
James Cole
6980717075 Set version in more places. 2025-10-11 06:47:55 +02:00
James Cole
1fe0aebacb Validate version using build_time. 2025-10-11 06:45:16 +02:00
github-actions[bot]
cbf7aef0c1 Merge pull request #11048 from firefly-iii/release-1760157167
🤖 Automatically merge the PR into the develop branch.
2025-10-11 06:33:00 +02:00
JC5
8c3e6c0189 🤖 Auto commit for release 'develop' on 2025-10-11 2025-10-11 06:32:47 +02:00
James Cole
cf7ee79c1c Fix two bugs in requests. 2025-10-11 06:27:55 +02:00
github-actions[bot]
7e344e4332 Merge pull request #11047 from firefly-iii/release-1760124177
🤖 Automatically merge the PR into the develop branch.
2025-10-10 21:23:04 +02:00
JC5
0a55e9fb4e 🤖 Auto commit for release 'develop' on 2025-10-10 2025-10-10 21:22:57 +02:00
James Cole
ed2e0e86dc Don't validate on empty string. 2025-10-10 20:54:51 +02:00
James Cole
9d1fb2cd6a Make sure that null|string passed is always a string 2025-10-10 20:54:31 +02:00
github-actions[bot]
57617b750f Merge pull request #11045 from firefly-iii/release-1760116335
🤖 Automatically merge the PR into the develop branch.
2025-10-10 19:12:23 +02:00
JC5
f6411fdc5a 🤖 Auto commit for release 'develop' on 2025-10-10 2025-10-10 19:12:15 +02:00
James Cole
02e24fc919 Whoops. 2025-10-10 19:07:28 +02:00
github-actions[bot]
dbc0210304 Merge pull request #11044 from firefly-iii/release-1760115302
🤖 Automatically merge the PR into the develop branch.
2025-10-10 18:55:11 +02:00
JC5
a709e224d4 🤖 Auto commit for release 'develop' on 2025-10-10 2025-10-10 18:55:02 +02:00
James Cole
83f3eddf44 Small code changes for @ctrl-f5's PR.
- Dropped some "setParameters" calls if unused in transformer.
- Add correct copyright
- Sprintf instead of string concat
- Small ident changes courtesy of phpstorm.
2025-10-10 18:50:39 +02:00
James Cole
7cfc4c2671 Merge pull request #11039 from ctrl-f5/feat/improve-request-objects
proposal for improved request handling
2025-10-10 18:38:02 +02:00
mergify[bot]
1c6055cb2d Merge branch 'develop' into feat/improve-request-objects 2025-10-10 14:42:25 +00:00
James Cole
4f4576e458 Add option to select date, fix #11042 2025-10-10 16:41:46 +02:00
mergify[bot]
84d3bcbb37 Merge branch 'develop' into feat/improve-request-objects 2025-10-10 11:33:40 +00:00
mergify[bot]
ad67bb80f3 Merge branch 'develop' into feat/improve-request-objects 2025-10-10 11:29:39 +00:00
mergify[bot]
569f553d26 Merge branch 'develop' into feat/improve-request-objects 2025-10-10 06:58:56 +00:00
mergify[bot]
58c76bee94 Merge branch 'develop' into feat/improve-request-objects 2025-10-10 06:46:55 +00:00
Nicky De Maeyer
52f3ec7d3d improved request handling 2025-10-09 15:05:52 +02:00
192 changed files with 2528 additions and 1410 deletions

View File

@@ -402,16 +402,16 @@
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.88.2", "version": "v3.89.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "a8d15584bafb0f0d9d938827840060fd4a3ebc99" "reference": "f34967da2866ace090a2b447de1f357356474573"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a8d15584bafb0f0d9d938827840060fd4a3ebc99", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/f34967da2866ace090a2b447de1f357356474573",
"reference": "a8d15584bafb0f0d9d938827840060fd4a3ebc99", "reference": "f34967da2866ace090a2b447de1f357356474573",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -426,7 +426,6 @@
"php": "^7.4 || ^8.0", "php": "^7.4 || ^8.0",
"react/child-process": "^0.6.6", "react/child-process": "^0.6.6",
"react/event-loop": "^1.5", "react/event-loop": "^1.5",
"react/promise": "^3.3",
"react/socket": "^1.16", "react/socket": "^1.16",
"react/stream": "^1.4", "react/stream": "^1.4",
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0",
@@ -494,7 +493,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.88.2" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.89.1"
}, },
"funding": [ "funding": [
{ {
@@ -502,7 +501,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-09-27T00:24:15+00:00" "time": "2025-10-24T12:05:10+00:00"
}, },
{ {
"name": "psr/container", "name": "psr/container",
@@ -1252,16 +1251,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v7.3.4", "version": "v7.3.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db" "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/2b9c5fafbac0399a20a2e82429e2bd735dcfb7db", "url": "https://api.github.com/repos/symfony/console/zipball/cdb80fa5869653c83cfe1a9084a673b6daf57ea7",
"reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db", "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1326,7 +1325,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v7.3.4" "source": "https://github.com/symfony/console/tree/v7.3.5"
}, },
"funding": [ "funding": [
{ {
@@ -1346,7 +1345,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-09-22T15:31:00+00:00" "time": "2025-10-14T15:46:26+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@@ -1647,16 +1646,16 @@
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v7.3.2", "version": "v7.3.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" "reference": "9f696d2f1e340484b4683f7853b273abff94421f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f",
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", "reference": "9f696d2f1e340484b4683f7853b273abff94421f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1691,7 +1690,7 @@
"description": "Finds files and directories via an intuitive fluent interface", "description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/finder/tree/v7.3.2" "source": "https://github.com/symfony/finder/tree/v7.3.5"
}, },
"funding": [ "funding": [
{ {
@@ -1711,7 +1710,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-07-15T13:41:35+00:00" "time": "2025-10-15T18:45:57+00:00"
}, },
{ {
"name": "symfony/options-resolver", "name": "symfony/options-resolver",

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
@@ -79,20 +79,26 @@ class AccountController extends Controller
* @throws FireflyException * @throws FireflyException
* @throws FireflyException * @throws FireflyException
*/ */
public function accounts(AutocompleteRequest $request): JsonResponse public function accounts(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); [
$types = $data['types']; 'types' => $types,
$query = $data['query']; 'query' => $query,
$date = $data['date']; 'date' => $date,
$return = []; 'limit' => $limit,
$timer = Timer::getInstance(); ]
$timer->start(sprintf('AC accounts "%s"', $query)); = $request->attributes->all();
$result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit'));
$date ??= today(config('app.timezone'));
// set date to end-of-day for account balance. so it is at $date 23:59:59 // set date to end-of-day for account balance. so it is at $date 23:59:59
$date->endOfDay(); $date->endOfDay();
$return = [];
$timer = Timer::getInstance();
$timer->start(sprintf('AC accounts "%s"', $query));
$result = $this->repository->searchAccount((string)$query, $types, $limit);
$allBalances = Steam::accountsBalancesOptimized($result, $date, $this->primaryCurrency, $this->convertToPrimary); $allBalances = Steam::accountsBalancesOptimized($result, $date, $this->primaryCurrency, $this->convertToPrimary);
/** @var Account $account */ /** @var Account $account */
@@ -111,17 +117,17 @@ class AccountController extends Controller
} }
$return[] = [ $return[] = [
'id' => (string) $account->id, 'id' => (string)$account->id,
'name' => $account->name, 'name' => $account->name,
'name_with_balance' => $nameWithBalance, 'name_with_balance' => $nameWithBalance,
'active' => $account->active, 'active' => $account->active,
'type' => $account->accountType->type, 'type' => $account->accountType->type,
'currency_id' => (string) $useCurrency->id, 'currency_id' => (string)$useCurrency->id,
'currency_name' => $useCurrency->name, 'currency_name' => $useCurrency->name,
'currency_code' => $useCurrency->code, 'currency_code' => $useCurrency->code,
'currency_symbol' => $useCurrency->symbol, 'currency_symbol' => $useCurrency->symbol,
'currency_decimal_places' => $useCurrency->decimal_places, 'currency_decimal_places' => $useCurrency->decimal_places,
'account_currency_id' => (string) $currency->id, 'account_currency_id' => (string)$currency->id,
'account_currency_name' => $currency->name, 'account_currency_name' => $currency->name,
'account_currency_code' => $currency->code, 'account_currency_code' => $currency->code,
'account_currency_symbol' => $currency->symbol, 'account_currency_symbol' => $currency->symbol,
@@ -134,8 +140,8 @@ class AccountController extends Controller
$return, $return,
static function (array $left, array $right) { static function (array $left, array $right) {
$order = [AccountTypeEnum::ASSET->value, AccountTypeEnum::REVENUE->value, AccountTypeEnum::EXPENSE->value]; $order = [AccountTypeEnum::ASSET->value, AccountTypeEnum::REVENUE->value, AccountTypeEnum::EXPENSE->value];
$posA = (int) array_search($left['type'], $order, true); $posA = (int)array_search($left['type'], $order, true);
$posB = (int) array_search($right['type'], $order, true); $posB = (int)array_search($right['type'], $order, true);
return $posA - $posB; return $posA - $posB;
} }

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
@@ -61,10 +61,9 @@ class BillController extends Controller
* Documentation for this endpoint is at: * Documentation for this endpoint is at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getBillsAC * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getBillsAC
*/ */
public function bills(AutocompleteRequest $request): JsonResponse public function bills(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $result = $this->repository->searchBill($request->attributes->get('query'), $request->attributes->get('limit'));
$result = $this->repository->searchBill($data['query'], $this->parameters->get('limit'));
$filtered = $result->map( $filtered = $result->map(
static fn (Bill $item) => [ static fn (Bill $item) => [
'id' => (string) $item->id, 'id' => (string) $item->id,

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
@@ -61,10 +61,9 @@ class BudgetController extends Controller
* Documentation for this endpoint is at: * Documentation for this endpoint is at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getBudgetsAC * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getBudgetsAC
*/ */
public function budgets(AutocompleteRequest $request): JsonResponse public function budgets(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $result = $this->repository->searchBudget($request->attributes->get('query'), $request->attributes->get('limit'));
$result = $this->repository->searchBudget($data['query'], $this->parameters->get('limit'));
$filtered = $result->map( $filtered = $result->map(
static fn (Budget $item) => [ static fn (Budget $item) => [
'id' => (string) $item->id, 'id' => (string) $item->id,

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
@@ -61,10 +61,9 @@ class CategoryController extends Controller
* Documentation for this endpoint is at: * Documentation for this endpoint is at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getCategoriesAC * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getCategoriesAC
*/ */
public function categories(AutocompleteRequest $request): JsonResponse public function categories(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $result = $this->repository->searchCategory($request->attributes->get('query'), $request->attributes->get('limit'));
$result = $this->repository->searchCategory($data['query'], $this->parameters->get('limit'));
$filtered = $result->map( $filtered = $result->map(
static fn (Category $item) => [ static fn (Category $item) => [
'id' => (string) $item->id, 'id' => (string) $item->id,

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use Deprecated; use Deprecated;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
@@ -62,10 +63,9 @@ class CurrencyController extends Controller
* Documentation for this endpoint is at: * Documentation for this endpoint is at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getCurrenciesAC * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getCurrenciesAC
*/ */
public function currencies(AutocompleteRequest $request): JsonResponse public function currencies(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $collection = $this->repository->searchCurrency($request->attributes->get('query'), $request->attributes->get('limit'));
$collection = $this->repository->searchCurrency($data['query'], $this->parameters->get('limit'));
$result = []; $result = [];
/** @var TransactionCurrency $currency */ /** @var TransactionCurrency $currency */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\ObjectGroup; use FireflyIII\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface; use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
@@ -61,11 +61,10 @@ class ObjectGroupController extends Controller
* Documentation for this endpoint is at: * Documentation for this endpoint is at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getObjectGroupsAC * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getObjectGroupsAC
*/ */
public function objectGroups(AutocompleteRequest $request): JsonResponse public function objectGroups(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData();
$return = []; $return = [];
$result = $this->repository->search($data['query'], $this->parameters->get('limit')); $result = $this->repository->search($request->attributes->get('query'), $request->attributes->get('limit'));
/** @var ObjectGroup $objectGroup */ /** @var ObjectGroup $objectGroup */
foreach ($result as $objectGroup) { foreach ($result as $objectGroup) {

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
@@ -64,10 +64,9 @@ class PiggyBankController extends Controller
); );
} }
public function piggyBanks(AutocompleteRequest $request): JsonResponse public function piggyBanks(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $piggies = $this->piggyRepository->searchPiggyBank($request->attributes->get('query'), $request->attributes->get('limit'));
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $this->parameters->get('limit'));
$response = []; $response = [];
/** @var PiggyBank $piggy */ /** @var PiggyBank $piggy */
@@ -90,10 +89,9 @@ class PiggyBankController extends Controller
return response()->api($response); return response()->api($response);
} }
public function piggyBanksWithBalance(AutocompleteRequest $request): JsonResponse public function piggyBanksWithBalance(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $piggies = $this->piggyRepository->searchPiggyBank($request->attributes->get('query'), $request->attributes->get('limit'));
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $this->parameters->get('limit'));
$response = []; $response = [];
/** @var PiggyBank $piggy */ /** @var PiggyBank $piggy */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Recurrence; use FireflyIII\Models\Recurrence;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
@@ -57,10 +57,9 @@ class RecurrenceController extends Controller
); );
} }
public function recurring(AutocompleteRequest $request): JsonResponse public function recurring(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $recurrences = $this->repository->searchRecurrence($request->attributes->get('query'), $request->attributes->get('limit'));
$recurrences = $this->repository->searchRecurrence($data['query'], $this->parameters->get('limit'));
$response = []; $response = [];
/** @var Recurrence $recurrence */ /** @var Recurrence $recurrence */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Rule; use FireflyIII\Models\Rule;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface; use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
@@ -57,10 +57,9 @@ class RuleController extends Controller
); );
} }
public function rules(AutocompleteRequest $request): JsonResponse public function rules(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $rules = $this->repository->searchRule($request->attributes->get('query'), $request->attributes->get('limit'));
$rules = $this->repository->searchRule($data['query'], $this->parameters->get('limit'));
$response = []; $response = [];
/** @var Rule $rule */ /** @var Rule $rule */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\RuleGroup; use FireflyIII\Models\RuleGroup;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
@@ -57,10 +57,9 @@ class RuleGroupController extends Controller
); );
} }
public function ruleGroups(AutocompleteRequest $request): JsonResponse public function ruleGroups(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $groups = $this->repository->searchRuleGroup($request->attributes->get('query'), $request->attributes->get('limit'));
$groups = $this->repository->searchRuleGroup($data['query'], $this->parameters->get('limit'));
$response = []; $response = [];
/** @var RuleGroup $group */ /** @var RuleGroup $group */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface;
@@ -57,10 +57,9 @@ class TagController extends Controller
); );
} }
public function tags(AutocompleteRequest $request): JsonResponse public function tags(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $result = $this->repository->searchTags($request->attributes->get('query'), $request->attributes->get('limit'));
$result = $this->repository->searchTags($data['query'], $this->parameters->get('limit'));
$array = []; $array = [];
/** @var Tag $tag */ /** @var Tag $tag */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
@@ -64,10 +64,9 @@ class TransactionController extends Controller
); );
} }
public function transactions(AutocompleteRequest $request): JsonResponse public function transactions(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $result = $this->repository->searchJournalDescriptions($request->attributes->get('query'), $request->attributes->get('limit'));
$result = $this->repository->searchJournalDescriptions($data['query'], $this->parameters->get('limit'));
// limit and unique // limit and unique
$filtered = $result->unique('description'); $filtered = $result->unique('description');
@@ -86,13 +85,12 @@ class TransactionController extends Controller
return response()->api($array); return response()->api($array);
} }
public function transactionsWithID(AutocompleteRequest $request): JsonResponse public function transactionsWithID(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData();
$result = new Collection(); $result = new Collection();
if (is_numeric($data['query'])) { if (is_numeric($request->attributes->get('query'))) {
// search for group, not journal. // search for group, not journal.
$firstResult = $this->groupRepository->find((int) $data['query']); $firstResult = $this->groupRepository->find((int) $request->attributes->get('query'));
if ($firstResult instanceof TransactionGroup) { if ($firstResult instanceof TransactionGroup) {
// group may contain multiple journals, each a result: // group may contain multiple journals, each a result:
foreach ($firstResult->transactionJournals as $journal) { foreach ($firstResult->transactionJournals as $journal) {
@@ -100,8 +98,8 @@ class TransactionController extends Controller
} }
} }
} }
if (!is_numeric($data['query'])) { if (!is_numeric($request->attributes->get('query'))) {
$result = $this->repository->searchJournalDescriptions($data['query'], $this->parameters->get('limit')); $result = $this->repository->searchJournalDescriptions($request->attributes->get('query'), $request->attributes->get('limit'));
} }
// limit and unique // limit and unique

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete; namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface; use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface;
@@ -55,10 +55,9 @@ class TransactionTypeController extends Controller
); );
} }
public function transactionTypes(AutocompleteRequest $request): JsonResponse public function transactionTypes(AutocompleteApiRequest $request): JsonResponse
{ {
$data = $request->getData(); $types = $this->repository->searchTypes($request->attributes->get('query'), $request->attributes->get('limit'));
$types = $this->repository->searchTypes($data['query'], $this->parameters->get('limit'));
$array = []; $array = [];
/** @var TransactionType $type */ /** @var TransactionType $type */

View File

@@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\SameDateRequest; use FireflyIII\Api\V1\Requests\DateRangeRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
@@ -83,15 +83,13 @@ class BudgetController extends Controller
* *
* @throws FireflyException * @throws FireflyException
*/ */
public function overview(SameDateRequest $request): JsonResponse public function overview(DateRangeRequest $request): JsonResponse
{ {
$params = $request->getAll();
/** @var Carbon $start */ /** @var Carbon $start */
$start = $params['start']; $start = $request->attributes->get('start');
/** @var Carbon $end */ /** @var Carbon $end */
$end = $params['end']; $end = $request->attributes->get('end');
// code from FrontpageChartGenerator, but not in separate class // code from FrontpageChartGenerator, but not in separate class
$budgets = $this->repository->getActiveBudgets(); $budgets = $this->repository->getActiveBudgets();

View File

@@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\SameDateRequest; use FireflyIII\Api\V1\Requests\DateRangeRequest;
use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
@@ -80,13 +80,13 @@ class CategoryController extends Controller
* *
* @SuppressWarnings("PHPMD.UnusedFormalParameter") * @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/ */
public function overview(SameDateRequest $request): JsonResponse public function overview(DateRangeRequest $request): JsonResponse
{ {
/** @var Carbon $start */ /** @var Carbon $start */
$start = $this->parameters->get('start'); $start = $request->attributes->get('start');
/** @var Carbon $end */ /** @var Carbon $end */
$end = $this->parameters->get('end'); $end = $request->attributes->get('end');
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value]); $accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value]);
$currencies = []; $currencies = [];
$return = []; $return = [];

View File

@@ -29,6 +29,7 @@ use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Exceptions\BadHttpHeaderException; use FireflyIII\Exceptions\BadHttpHeaderException;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\AbstractTransformer; use FireflyIII\Transformers\AbstractTransformer;
@@ -67,6 +68,8 @@ abstract class Controller extends BaseController
protected bool $convertToPrimary = false; protected bool $convertToPrimary = false;
protected TransactionCurrency $primaryCurrency; protected TransactionCurrency $primaryCurrency;
/** @deprecated use Request classes */
protected ParameterBag $parameters; protected ParameterBag $parameters;
/** /**
@@ -98,7 +101,8 @@ abstract class Controller extends BaseController
} }
/** /**
* Method to grab all parameters from the URL. * @deprecated use Request classes
* Method to grab all parameters from the URL
*/ */
private function getParameters(): ParameterBag private function getParameters(): ParameterBag
{ {
@@ -156,7 +160,7 @@ abstract class Controller extends BaseController
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
$pageSize = (int)app('preferences')->getForUser($user, 'listPageSize', 50)->data; $pageSize = (int)Preferences::getForUser($user, 'listPageSize', 50)->data;
$bag->set($integer, $pageSize); $bag->set($integer, $pageSize);
} }
} }

View File

@@ -46,6 +46,7 @@ use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\AccountDestroyService; use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
use FireflyIII\Services\Internal\Destroy\JournalDestroyService; use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -102,7 +103,7 @@ class DestroyController extends Controller
default => throw new FireflyException(sprintf('200033: This endpoint can\'t handle object "%s"', $objects)), default => throw new FireflyException(sprintf('200033: This endpoint can\'t handle object "%s"', $objects)),
}; };
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Account;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
/** /**
@@ -60,7 +61,7 @@ class DestroyController extends Controller
public function destroy(Account $account): JsonResponse public function destroy(Account $account): JsonResponse
{ {
$this->repository->destroy($account, null); $this->repository->destroy($account, null);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\Account; namespace FireflyIII\Api\V1\Controllers\Models\Account;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\PaginationRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
@@ -69,22 +70,25 @@ class ListController extends Controller
); );
} }
public function attachments(Account $account): JsonResponse public function attachments(PaginationRequest $request, Account $account): JsonResponse
{ {
$manager = $this->getManager(); $manager = $this->getManager();
$pageSize = $this->parameters->get('limit'); [
'limit' => $limit,
'offset' => $offset,
'page' => $page,
] = $request->attributes->all();
$collection = $this->repository->getAttachments($account); $collection = $this->repository->getAttachments($account);
$count = $collection->count(); $count = $collection->count();
$attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $attachments = $collection->slice($offset, $limit);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($attachments, $count, $limit, $page);
$paginator->setPath(route('api.v1.accounts.attachments', [$account->id]).$this->buildParams()); $paginator->setPath(route('api.v1.accounts.attachments', [$account->id]).$this->buildParams());
/** @var AttachmentTransformer $transformer */ /** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class); $transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($attachments, $transformer, 'attachments'); $resource = new FractalCollection($attachments, $transformer, 'attachments');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
@@ -92,18 +96,21 @@ class ListController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
} }
public function piggyBanks(Account $account): JsonResponse public function piggyBanks(PaginationRequest $request, Account $account): JsonResponse
{ {
// create some objects: // create some objects:
$manager = $this->getManager(); $manager = $this->getManager();
// types to get, page size: [
$pageSize = $this->parameters->get('limit'); 'limit' => $limit,
'offset' => $offset,
'page' => $page,
] = $request->attributes->all();
// get list of piggy banks. Count it and split it. // get list of piggy banks. Count it and split it.
$collection = $this->repository->getPiggyBanks($account); $collection = $this->repository->getPiggyBanks($account);
$count = $collection->count(); $count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $piggyBanks = $collection->slice(($page - 1) * $limit, $limit);
// enrich // enrich
/** @var User $admin */ /** @var User $admin */
@@ -113,12 +120,12 @@ class ListController extends Controller
$piggyBanks = $enrichment->enrich($piggyBanks); $piggyBanks = $enrichment->enrich($piggyBanks);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($piggyBanks, $count, $limit, $page);
$paginator->setPath(route('api.v1.accounts.piggy-banks', [$account->id]).$this->buildParams()); $paginator->setPath(route('api.v1.accounts.piggy-banks', [$account->id]).$this->buildParams());
/** @var PiggyBankTransformer $transformer */ /** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters); // $transformer->setParameters($this->parameters);
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy-banks'); $resource = new FractalCollection($piggyBanks, $transformer, 'piggy-banks');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));

View File

@@ -71,45 +71,45 @@ class ShowController extends Controller
public function index(ShowRequest $request): JsonResponse public function index(ShowRequest $request): JsonResponse
{ {
$manager = $this->getManager(); $manager = $this->getManager();
$params = $request->getParameters(); [
$this->parameters->set('type', $params['type']); 'types' => $types,
'page' => $page,
// types to get, page size: 'limit' => $limit,
$types = $this->mapAccountTypes($params['type']); 'offset' => $offset,
'sort' => $sort,
'start' => $start,
'end' => $end,
'date' => $date,
]
= $request->attributes->all();
// get list of accounts. Count it and split it. // get list of accounts. Count it and split it.
$this->repository->resetAccountOrder(); $this->repository->resetAccountOrder();
$collection = $this->repository->getAccountsByType($types, $params['sort']); $collection = $this->repository->getAccountsByType($types, $sort);
$count = $collection->count(); $count = $collection->count();
// continue sort: // continue sort:
// TODO if the user sorts on DB dependent field there must be no slice before enrichment, only after. // TODO if the user sorts on DB dependent field there must be no slice before enrichment, only after.
// TODO still need to figure out how to do this easily. // TODO still need to figure out how to do this easily.
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $params['limit'], $params['limit']); $accounts = $collection->slice($offset, $limit);
// #11007 go to the end of the previous day.
$this->parameters->set('start', $this->parameters->get('start')?->subSecond());
// #11018 also end of the day.
$this->parameters->set('end', $this->parameters->get('end')?->endOfDay());
// enrich // enrich
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setSort($params['sort']); $enrichment->setSort($sort);
$enrichment->setDate($this->parameters->get('date')); $enrichment->setDate($date);
$enrichment->setStart($this->parameters->get('start')); $enrichment->setStart($start);
$enrichment->setEnd($this->parameters->get('end')); $enrichment->setEnd($end);
$enrichment->setUser($admin); $enrichment->setUser($admin);
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($accounts, $count, $params['limit'], $this->parameters->get('page')); $paginator = new LengthAwarePaginator($accounts, $count, $limit, $page);
$paginator->setPath(route('api.v1.accounts.index').$this->buildParams()); $paginator->setPath(route('api.v1.accounts.index').$this->buildParams());
/** @var AccountTransformer $transformer */ /** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class); $transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($accounts, $transformer, self::RESOURCE_KEY); $resource = new FractalCollection($accounts, $transformer, self::RESOURCE_KEY);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
@@ -128,28 +128,25 @@ class ShowController extends Controller
// get list of accounts. Count it and split it. // get list of accounts. Count it and split it.
$this->repository->resetAccountOrder(); $this->repository->resetAccountOrder();
$account->refresh(); $account->refresh();
$manager = $this->getManager(); $manager = $this->getManager();
['start' => $start,
// #11007 go to the end of the previous day. 'end' => $end,
$this->parameters->set('start', $this->parameters->get('start')?->subSecond()); 'date' => $date,] = $request->attributes->all();
// #11018 also end of the day.
$this->parameters->set('end', $this->parameters->get('end')?->endOfDay());
// enrich // enrich
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date')); $enrichment->setDate($date);
$enrichment->setStart($this->parameters->get('start')); $enrichment->setStart($start);
$enrichment->setEnd($this->parameters->get('end')); $enrichment->setEnd($end);
$enrichment->setUser($admin); $enrichment->setUser($admin);
$account = $enrichment->enrichSingle($account); $account = $enrichment->enrichSingle($account);
/** @var AccountTransformer $transformer */ /** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class); $transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters); $resource = new Item($account, $transformer, self::RESOURCE_KEY);
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
} }

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Account\UpdateRequest; use FireflyIII\Api\V1\Requests\Models\Account\UpdateRequest;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use FireflyIII\Transformers\AccountTransformer; use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\User; use FireflyIII\User;
@@ -74,7 +75,7 @@ class UpdateController extends Controller
$account = $this->repository->update($account, $data); $account = $this->repository->update($account, $data);
$manager = $this->getManager(); $manager = $this->getManager();
$account->refresh(); $account->refresh();
app('preferences')->mark(); Preferences::mark();
// enrich // enrich
/** @var User $admin */ /** @var User $admin */

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Middleware\ApiDemoUser; use FireflyIII\Api\V1\Middleware\ApiDemoUser;
use FireflyIII\Models\Attachment; use FireflyIII\Models\Attachment;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -74,7 +75,7 @@ class DestroyController extends Controller
} }
$this->repository->destroy($attachment); $this->repository->destroy($attachment);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Bill;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
/** /**
@@ -61,7 +62,7 @@ class DestroyController extends Controller
public function destroy(Bill $bill): JsonResponse public function destroy(Bill $bill): JsonResponse
{ {
$this->repository->destroy($bill); $this->repository->destroy($bill);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Budget;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
/** /**
@@ -61,7 +62,7 @@ class DestroyController extends Controller
public function destroy(Budget $budget): JsonResponse public function destroy(Budget $budget): JsonResponse
{ {
$this->repository->destroy($budget); $this->repository->destroy($budget);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -71,7 +72,7 @@ class DestroyController extends Controller
throw new FireflyException('20028: The budget limit does not belong to the budget.'); throw new FireflyException('20028: The budget limit does not belong to the budget.');
} }
$this->blRepository->destroyBudgetLimit($budgetLimit); $this->blRepository->destroyBudgetLimit($budgetLimit);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -172,7 +172,6 @@ class ShowController extends Controller
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($budgetLimit, $transformer, 'budget_limits'); $resource = new Item($budgetLimit, $transformer, 'budget_limits');

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Category;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
/** /**
@@ -61,7 +62,7 @@ class DestroyController extends Controller
public function destroy(Category $category): JsonResponse public function destroy(Category $category): JsonResponse
{ {
$this->repository->destroy($category); $this->repository->destroy($category);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -28,6 +28,7 @@ use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\DestroyRequest; use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\DestroyRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\CurrencyExchangeRate; use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface; use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
@@ -75,6 +76,9 @@ class DestroyController extends Controller
if ($exchangeRate instanceof CurrencyExchangeRate) { if ($exchangeRate instanceof CurrencyExchangeRate) {
$this->repository->deleteRate($exchangeRate); $this->repository->deleteRate($exchangeRate);
} }
if (!$exchangeRate instanceof CurrencyExchangeRate) {
throw new FireflyException('Bla');
}
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -82,7 +82,6 @@ class UpdateController extends Controller
$exchangeRate = $this->repository->updateExchangeRate($exchangeRate, $rate, $date); $exchangeRate = $this->repository->updateExchangeRate($exchangeRate, $rate, $date);
$transformer = new ExchangeRateTransformer(); $transformer = new ExchangeRateTransformer();
$transformer->setParameters($this->parameters);
return response() return response()
->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer)) ->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer))

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\ObjectGroup;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\ObjectGroup; use FireflyIII\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface; use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -64,7 +65,7 @@ class DestroyController extends Controller
public function destroy(ObjectGroup $objectGroup): JsonResponse public function destroy(ObjectGroup $objectGroup): JsonResponse
{ {
$this->repository->destroy($objectGroup); $this->repository->destroy($objectGroup);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\PiggyBank;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
/** /**
@@ -61,7 +62,7 @@ class DestroyController extends Controller
public function destroy(PiggyBank $piggyBank): JsonResponse public function destroy(PiggyBank $piggyBank): JsonResponse
{ {
$this->repository->destroy($piggyBank); $this->repository->destroy($piggyBank);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Recurrence;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\Recurrence; use FireflyIII\Models\Recurrence;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
/** /**
@@ -61,7 +62,7 @@ class DestroyController extends Controller
public function destroy(Recurrence $recurrence): JsonResponse public function destroy(Recurrence $recurrence): JsonResponse
{ {
$this->repository->destroy($recurrence); $this->repository->destroy($recurrence);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Rule;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\Rule; use FireflyIII\Models\Rule;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface; use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -65,7 +66,7 @@ class DestroyController extends Controller
public function destroy(Rule $rule): JsonResponse public function destroy(Rule $rule): JsonResponse
{ {
$this->ruleRepository->destroy($rule); $this->ruleRepository->destroy($rule);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\RuleGroup;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\RuleGroup; use FireflyIII\Models\RuleGroup;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -65,7 +66,7 @@ class DestroyController extends Controller
public function destroy(RuleGroup $ruleGroup): JsonResponse public function destroy(RuleGroup $ruleGroup): JsonResponse
{ {
$this->ruleGroupRepository->destroy($ruleGroup, null); $this->ruleGroupRepository->destroy($ruleGroup, null);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Tag;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -65,7 +66,7 @@ class DestroyController extends Controller
public function destroy(Tag $tag): JsonResponse public function destroy(Tag $tag): JsonResponse
{ {
$this->repository->destroy($tag); $this->repository->destroy($tag);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -32,6 +32,7 @@ use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepository; use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepository;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -92,7 +93,7 @@ class DestroyController extends Controller
$this->groupRepository->destroy($transactionGroup); $this->groupRepository->destroy($transactionGroup);
app('preferences')->mark(); Preferences::mark();
/** @var Account $account */ /** @var Account $account */
foreach ($accounts as $account) { foreach ($accounts as $account) {
@@ -112,7 +113,7 @@ class DestroyController extends Controller
public function destroyJournal(TransactionJournal $transactionJournal): JsonResponse public function destroyJournal(TransactionJournal $transactionJournal): JsonResponse
{ {
$this->repository->destroyJournal($transactionJournal); $this->repository->destroyJournal($transactionJournal);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -33,6 +33,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Rules\IsDuplicateTransaction; use FireflyIII\Rules\IsDuplicateTransaction;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\Transformers\TransactionGroupTransformer;
@@ -107,7 +108,7 @@ class StoreController extends Controller
throw new ValidationException($validator); throw new ValidationException($validator);
} }
app('preferences')->mark(); Preferences::mark();
$applyRules = $data['apply_rules'] ?? true; $applyRules = $data['apply_rules'] ?? true;
$fireWebhooks = $data['fire_webhooks'] ?? true; $fireWebhooks = $data['fire_webhooks'] ?? true;
event(new StoredTransactionGroup($transactionGroup, $applyRules, $fireWebhooks)); event(new StoredTransactionGroup($transactionGroup, $applyRules, $fireWebhooks));

View File

@@ -30,6 +30,7 @@ use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User; use FireflyIII\User;
@@ -79,7 +80,7 @@ class UpdateController extends Controller
$newHash = $this->groupRepository->getCompareHash($transactionGroup); $newHash = $this->groupRepository->getCompareHash($transactionGroup);
$manager = $this->getManager(); $manager = $this->getManager();
app('preferences')->mark(); Preferences::mark();
$applyRules = $data['apply_rules'] ?? true; $applyRules = $data['apply_rules'] ?? true;
$fireWebhooks = $data['fire_webhooks'] ?? true; $fireWebhooks = $data['fire_webhooks'] ?? true;
$runRecalculations = $oldHash !== $newHash; $runRecalculations = $oldHash !== $newHash;

View File

@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
@@ -89,7 +90,7 @@ class DestroyController extends Controller
} }
$this->repository->destroy($currency); $this->repository->destroy($currency);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionCurrency;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\StoreRequest; use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\StoreRequest;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\AccountFilter; use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\CurrencyTransformer; use FireflyIII\Transformers\CurrencyTransformer;
@@ -71,7 +72,7 @@ class StoreController extends Controller
$currency = $this->repository->store($request->getAll()); $currency = $this->repository->store($request->getAll());
if (true === $request->boolean('default')) { if (true === $request->boolean('default')) {
$this->repository->makePrimary($currency); $this->repository->makePrimary($currency);
app('preferences')->mark(); Preferences::mark();
} }
$manager = $this->getManager(); $manager = $this->getManager();

View File

@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\UpdateRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\AccountFilter; use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\CurrencyTransformer; use FireflyIII\Transformers\CurrencyTransformer;
@@ -105,7 +106,7 @@ class UpdateController extends Controller
$this->repository->enable($currency); $this->repository->enable($currency);
$this->repository->makePrimary($currency); $this->repository->makePrimary($currency);
app('preferences')->mark(); Preferences::mark();
$manager = $this->getManager(); $manager = $this->getManager();
$currency->refreshForUser($user); $currency->refreshForUser($user);
@@ -172,14 +173,13 @@ class UpdateController extends Controller
$currency = $this->repository->update($currency, $data); $currency = $this->repository->update($currency, $data);
app('preferences')->mark(); Preferences::mark();
$manager = $this->getManager(); $manager = $this->getManager();
$currency->refreshForUser($user); $currency->refreshForUser($user);
/** @var CurrencyTransformer $transformer */ /** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class); $transformer = app(CurrencyTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($currency, $transformer, 'currencies'); $resource = new Item($currency, $transformer, 'currencies');

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionLink;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Models\TransactionJournalLink; use FireflyIII\Models\TransactionJournalLink;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -66,7 +67,7 @@ class DestroyController extends Controller
public function destroy(TransactionJournalLink $link): JsonResponse public function destroy(TransactionJournalLink $link): JsonResponse
{ {
$this->repository->destroyLink($link); $this->repository->destroyLink($link);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\LinkType; use FireflyIII\Models\LinkType;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -73,7 +74,7 @@ class DestroyController extends Controller
throw new FireflyException('200020: Link type cannot be changed.'); throw new FireflyException('200020: Link type cannot be changed.');
} }
$this->repository->destroy($linkType); $this->repository->destroy($linkType);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\UserGroup; namespace FireflyIII\Api\V1\Controllers\Models\UserGroup;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\DateRequest; use FireflyIII\Api\V1\Requests\PaginationRequest;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface; use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Transformers\UserGroupTransformer; use FireflyIII\Transformers\UserGroupTransformer;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -52,17 +52,19 @@ class IndexController extends Controller
); );
} }
public function index(DateRequest $request): JsonResponse public function index(PaginationRequest $request): JsonResponse
{ {
$administrations = $this->repository->get(); $administrations = $this->repository->get();
$pageSize = $this->parameters->get('limit'); [
'page' => $page,
'limit' => $limit,
'offset' => $offset,
] = $request->attributes->all();
$count = $administrations->count(); $count = $administrations->count();
$administrations = $administrations->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $administrations = $administrations->slice($offset, $limit);
$paginator = new LengthAwarePaginator($administrations, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($administrations, $count, $limit, $page);
$transformer = new UserGroupTransformer(); $transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response() return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer)) ->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE) ->header('Content-Type', self::CONTENT_TYPE)

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\UserGroup\UpdateRequest; use FireflyIII\Api\V1\Requests\Models\UserGroup\UpdateRequest;
use FireflyIII\Models\UserGroup; use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface; use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Transformers\UserGroupTransformer; use FireflyIII\Transformers\UserGroupTransformer;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -59,7 +60,7 @@ class UpdateController extends Controller
$data = $request->getData(); $data = $request->getData();
$userGroup = $this->repository->update($userGroup, $data); $userGroup = $this->repository->update($userGroup, $data);
$userGroup->refresh(); $userGroup->refresh();
app('preferences')->mark(); Preferences::mark();
$transformer = new UserGroupTransformer(); $transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -27,7 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Summary;
use Carbon\Carbon; use Carbon\Carbon;
use Exception; use Exception;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\DateRequest; use FireflyIII\Api\V1\Requests\Summary\BasicRequest;
use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
@@ -88,34 +88,25 @@ class BasicController extends Controller
); );
} }
/** public function basic(BasicRequest $request): JsonResponse
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/summary/getBasicSummary
*
* @throws Exception
*/
public function basic(DateRequest $request): JsonResponse
{ {
// parameters for boxes: // parameters for boxes:
$dates = $request->getAll(); ['start' => $start, 'end' => $end, 'code' => $code] = $request->attributes->all();
$start = $dates['start'];
$end = $dates['end'];
$code = $request->get('currency_code');
// balance information: // balance information:
$balanceData = $this->getBalanceInformation($start, $end); $balanceData = $this->getBalanceInformation($start, $end);
$billData = $this->getSubscriptionInformation($start, $end); $billData = $this->getSubscriptionInformation($start, $end);
$spentData = $this->getLeftToSpendInfo($start, $end); $spentData = $this->getLeftToSpendInfo($start, $end);
$netWorthData = $this->getNetWorthInfo($end); $netWorthData = $this->getNetWorthInfo($end);
// $balanceData = []; // $balanceData = [];
// $billData = []; // $billData = [];
// $spentData = []; // $spentData = [];
// $netWorthData = []; // $netWorthData = [];
$total = array_merge($balanceData, $billData, $spentData, $netWorthData); $total = array_merge($balanceData, $billData, $spentData, $netWorthData);
// give new keys // give new keys
$return = []; $return = [];
foreach ($total as $entry) { foreach ($total as $entry) {
if (null === $code || ($code === $entry['currency_code'])) { if ('' === $code || ($code === $entry['currency_code'])) {
$return[$entry['key']] = $entry; $return[$entry['key']] = $entry;
} }
} }

View File

@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\User\PreferenceStoreRequest;
use FireflyIII\Api\V1\Requests\User\PreferenceUpdateRequest; use FireflyIII\Api\V1\Requests\User\PreferenceUpdateRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Transformers\PreferenceTransformer; use FireflyIII\Transformers\PreferenceTransformer;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
@@ -52,7 +53,7 @@ class PreferencesController extends Controller
*/ */
public function index(): JsonResponse public function index(): JsonResponse
{ {
$collection = app('preferences')->all(); $collection = Preferences::all();
$manager = $this->getManager(); $manager = $this->getManager();
$count = $collection->count(); $count = $collection->count();
$pageSize = $this->parameters->get('limit'); $pageSize = $this->parameters->get('limit');
@@ -110,7 +111,7 @@ class PreferencesController extends Controller
throw new FireflyException('Please use api/v1/currencies/default instead.'); throw new FireflyException('Please use api/v1/currencies/default instead.');
} }
$pref = app('preferences')->set($data['name'], $data['data']); $pref = Preferences::set($data['name'], $data['data']);
/** @var PreferenceTransformer $transformer */ /** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class); $transformer = app(PreferenceTransformer::class);
@@ -135,7 +136,7 @@ class PreferencesController extends Controller
$manager = $this->getManager(); $manager = $this->getManager();
$data = $request->getAll(); $data = $request->getAll();
$pref = app('preferences')->set($preference->name, $data['data']); $pref = Preferences::set($preference->name, $data['data']);
/** @var PreferenceTransformer $transformer */ /** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class); $transformer = app(PreferenceTransformer::class);

View File

@@ -30,6 +30,7 @@ use FireflyIII\Models\Webhook;
use FireflyIII\Models\WebhookAttempt; use FireflyIII\Models\WebhookAttempt;
use FireflyIII\Models\WebhookMessage; use FireflyIII\Models\WebhookMessage;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface; use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -70,7 +71,7 @@ class DestroyController extends Controller
Log::channel('audit')->info(sprintf('User destroys webhook #%d.', $webhook->id)); Log::channel('audit')->info(sprintf('User destroys webhook #%d.', $webhook->id));
$this->repository->destroy($webhook); $this->repository->destroy($webhook);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }
@@ -101,7 +102,7 @@ class DestroyController extends Controller
Log::channel('audit')->info(sprintf('User destroys webhook #%d, message #%d, attempt #%d.', $webhook->id, $message->id, $attempt->id)); Log::channel('audit')->info(sprintf('User destroys webhook #%d, message #%d, attempt #%d.', $webhook->id, $message->id, $attempt->id));
$this->repository->destroyAttempt($attempt); $this->repository->destroyAttempt($attempt);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }
@@ -128,7 +129,7 @@ class DestroyController extends Controller
Log::channel('audit')->info(sprintf('User destroys webhook #%d, message #%d.', $webhook->id, $message->id)); Log::channel('audit')->info(sprintf('User destroys webhook #%d, message #%d.', $webhook->id, $message->id));
$this->repository->destroyMessage($message); $this->repository->destroyMessage($message);
app('preferences')->mark(); Preferences::mark();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -0,0 +1,97 @@
<?php
/*
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Validator;
use RuntimeException;
abstract class AggregateFormRequest extends ApiRequest
{
/**
* @var ApiRequest[]
*/
protected array $requests = [];
/** @return class-string[] */
abstract protected function getRequests(): array;
public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): void
{
parent::initialize($query, $request, $attributes, $cookies, $files, $server, $content);
// instantiate all subrequests and share current requests' bags with them
Log::debug('Initializing AggregateFormRequest.');
foreach ($this->getRequests() as $config) {
$requestClass = is_array($config) ? array_shift($config) : $config;
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));
$instance = $this->requests[] = new $requestClass();
$instance->request = $this->request;
$instance->query = $this->query;
$instance->attributes = $this->attributes;
$instance->cookies = $this->cookies;
$instance->files = $this->files;
$instance->server = $this->server;
$instance->headers = $this->headers;
if ($instance instanceof ApiRequest) {
$instance->handleConfig(is_array($config) ? $config : []);
}
}
Log::debug('Done initializing AggregateFormRequest.');
}
public function rules(): array
{
// check all subrequests for rules and combine them
return array_reduce(
$this->requests,
static fn (array $rules, FormRequest $request) => $rules
+ (
method_exists($request, 'rules')
? $request->rules()
: []
),
[],
);
}
public function withValidator(Validator $validator): void
{
// register all subrequests' validators
foreach ($this->requests as $request) {
if (method_exists($request, 'withValidator')) {
Log::debug(sprintf('Process withValidator from class %s', get_class($request)));
$request->withValidator($validator);
}
}
}
}

View File

@@ -0,0 +1,43 @@
<?php
/*
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
class ApiRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected string $required = '';
public function handleConfig(array $config): void
{
if (in_array('required', $config, true)) {
$this->required = 'required';
}
}
}

View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
/*
* AutocompleteApiRequest.php
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Requests\Autocomplete;
use FireflyIII\Api\V1\Requests\AggregateFormRequest;
use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Api\V1\Requests\Generic\QueryRequest;
use FireflyIII\Api\V1\Requests\Models\Account\AccountTypesApiRequest;
use FireflyIII\Api\V1\Requests\PaginationRequest;
use FireflyIII\Models\Account;
use Override;
class AutocompleteApiRequest extends AggregateFormRequest
{
#[Override]
protected function getRequests(): array
{
return [
DateRequest::class,
[PaginationRequest::class, 'sort_class' => Account::class],
AccountTypesApiRequest::class,
QueryRequest::class,
];
}
}

View File

@@ -31,6 +31,8 @@ use Illuminate\Foundation\Http\FormRequest;
/** /**
* Class AutocompleteRequest * Class AutocompleteRequest
*
* @deprecated
*/ */
class AutocompleteRequest extends FormRequest class AutocompleteRequest extends FormRequest
{ {

View File

@@ -1,82 +0,0 @@
<?php
/*
* DateRequest.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Data;
use FireflyIII\Exceptions\ValidationException;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Request class for end points that require date parameters.
*
* Class DateRequest
*/
class DateRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
/**
* Get all data from the request.
*/
public function getAll(): array
{
$start = $this->getCarbonDate('start');
$end = $this->getCarbonDate('end');
if (null === $start) {
$start = now()->startOfMonth();
}
if (null === $end) {
$end = now()->endOfMonth();
}
// sanity check on dates:
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
$start->startOfDay();
$end->endOfDay();
if ($start->diffInYears($end, true) > 5) {
throw new ValidationException('Date range out of range.');
}
return [
'start' => $start,
'end' => $end,
'date' => $this->getCarbonDate('date'),
];
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'date' => 'date|after:1970-01-02|before:2038-01-17',
'start' => 'date|after:1970-01-02|before:2038-01-17|before:end|required_with:end',
'end' => 'date|after:1970-01-02|before:2038-01-17|after:start|required_with:start',
];
}
}

View File

@@ -32,6 +32,8 @@ use Illuminate\Foundation\Http\FormRequest;
* Request class for end points that require date parameters. * Request class for end points that require date parameters.
* *
* Class SameDateRequest * Class SameDateRequest
*
* @deprecated Replaced by DateRangeRequest
*/ */
class SameDateRequest extends FormRequest class SameDateRequest extends FormRequest
{ {

View File

@@ -0,0 +1,57 @@
<?php
/*
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use Illuminate\Validation\Validator;
class DateRangeRequest extends ApiRequest
{
public function rules(): array
{
return [
'start' => sprintf('date|after:1970-01-02|before:2038-01-17|before:end|required_with:end|%s', $this->required),
'end' => sprintf('date|after:1970-01-02|before:2038-01-17|after:start|required_with:start|%s', $this->required),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if ($validator->failed()) {
// set null values
$this->attributes->set('start', null);
$this->attributes->set('end', null);
return;
}
$start = $this->getCarbonDate('start')?->startOfDay();
$end = $this->getCarbonDate('end')?->endOfDay();
$this->attributes->set('start', $start);
$this->attributes->set('end', $end);
}
);
}
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon;
use Illuminate\Validation\Validator;
class DateRequest extends ApiRequest
{
public function rules(): array
{
return [
'date' => 'date|after:1970-01-02|before:2038-01-17|'.$this->required,
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if ($validator->failed()) {
return;
}
$date = $this->getCarbonDate('date')?->endOfDay();
// if we also have a range, date must be in that range
$start = $this->attributes->get('start');
$end = $this->attributes->get('end');
if ($date instanceof Carbon && $start instanceof Carbon && $end instanceof Carbon && !$date->between($start, $end)) {
$validator->errors()->add('date', (string)trans('validation.between_date'));
}
$this->attributes->set('date', $date);
}
);
}
}

View File

@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
/*
* QueryRequest.php
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Requests\Generic;
use FireflyIII\Api\V1\Requests\ApiRequest;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Validation\Validator;
class QueryRequest extends ApiRequest
{
use ChecksLogin;
use ConvertsDataTypes;
public function rules(): array
{
return [
'query' => sprintf('min:1|max:50|%s', $this->required),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if ($validator->failed()) {
return;
}
$query = $this->convertString('query');
$this->attributes->set('query', $query);
}
);
}
}

View File

@@ -33,6 +33,8 @@ use Illuminate\Foundation\Http\FormRequest;
* Request class for end points that require a date parameter. * Request class for end points that require a date parameter.
* *
* Class SingleDateRequest * Class SingleDateRequest
*
* @deprecated
*/ */
class SingleDateRequest extends FormRequest class SingleDateRequest extends FormRequest
{ {

View File

@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/*
* AccountTypeApiRequest.php
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Requests\Models\Account;
use FireflyIII\Api\V1\Requests\ApiRequest;
use FireflyIII\Support\Http\Api\AccountFilter;
use Illuminate\Validation\Validator;
class AccountTypeApiRequest extends ApiRequest
{
use AccountFilter;
public function rules(): array
{
return [
'type' => sprintf('in:%s', implode(',', array_keys($this->types))),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if ($validator->failed()) {
return;
}
$type = $this->convertString('type', 'all');
$this->attributes->add([
'type' => $type,
'types' => $this->mapAccountTypes($type),
]);
}
);
}
}

View File

@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
/*
* AccountTypeApiRequest.php
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Requests\Models\Account;
use FireflyIII\Api\V1\Requests\ApiRequest;
use FireflyIII\Rules\Account\IsValidAccountTypeList;
use FireflyIII\Support\Http\Api\AccountFilter;
use Illuminate\Validation\Validator;
class AccountTypesApiRequest extends ApiRequest
{
use AccountFilter;
public function rules(): array
{
// sprintf('in:%s', implode(',', array_keys($this->types))),
return [
'types' => new IsValidAccountTypeList(),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if ($validator->failed()) {
return;
}
$type = $this->convertString('types', 'all');
$this->attributes->add([
'types' => $this->mapAccountTypes($type),
]);
}
);
}
}

View File

@@ -23,77 +23,21 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Account; namespace FireflyIII\Api\V1\Requests\Models\Account;
use Carbon\Carbon; use FireflyIII\Api\V1\Requests\AggregateFormRequest;
use FireflyIII\Api\V1\Requests\DateRangeRequest;
use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Api\V1\Requests\PaginationRequest;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Rules\IsValidSortInstruction;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
class ShowRequest extends FormRequest class ShowRequest extends AggregateFormRequest
{ {
use AccountFilter; protected function getRequests(): array
use ConvertsDataTypes;
public function getParameters(): array
{ {
$limit = $this->convertInteger('limit');
if (0 === $limit) {
// get default for user:
/** @var User $user */
$user = auth()->user();
$limit = (int)Preferences::getForUser($user, 'listPageSize', 50)->data;
}
$page = $this->convertInteger('page');
$page = min(max(1, $page), 2 ** 16);
return [ return [
'type' => $this->convertString('type', 'all'), [PaginationRequest::class, 'sort_class' => Account::class],
'limit' => $limit, DateRangeRequest::class,
'sort' => $this->convertSortParameters('sort', Account::class), DateRequest::class,
'page' => $page, AccountTypeApiRequest::class,
]; ];
} }
public function rules(): array
{
$keys = implode(',', array_keys($this->types));
return [
'date' => 'date',
'start' => 'date|present_with:end|before_or_equal:end|before:2038-01-17|after:1970-01-02',
'end' => 'date|present_with:start|after_or_equal:start|before:2038-01-17|after:1970-01-02',
'sort' => ['nullable', new IsValidSortInstruction(Account::class)],
'type' => sprintf('in:%s', $keys),
'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();
if (array_key_exists('date', $data) && array_key_exists('start', $data) && array_key_exists('end', $data)) {
// assume valid dates, before we got here.
$start = Carbon::parse($data['start'], config('app.timezone'))->startOfDay();
$end = Carbon::parse($data['end'], config('app.timezone'))->endOfDay();
$date = Carbon::parse($data['date'], config('app.timezone'));
if (!$date->between($start, $end)) {
$validator->errors()->add('date', (string)trans('validation.between_date'));
}
}
}
);
}
} }

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
/*
* CurrencyCodeRequest.php
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Requests\Models\TransactionCurrency;
use FireflyIII\Api\V1\Requests\ApiRequest;
use Illuminate\Validation\Validator;
class CurrencyCodeRequest extends ApiRequest
{
public function rules(): array
{
return [
'code' => sprintf('exists:transaction_currencies,code|%s', $this->required),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if (!$validator->valid()) {
return;
}
$code = $this->convertString('code', '');
$this->attributes->set('code', $code);
}
);
}
}

View File

@@ -0,0 +1,84 @@
<?php
/*
* Copyright (c) 2025 https://github.com/ctrl-f5
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsValidSortInstruction;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Validation\Validator;
use RuntimeException;
class PaginationRequest extends ApiRequest
{
private ?string $sortClass = null;
public function handleConfig(array $config): void
{
parent::handleConfig($config);
$this->sortClass = $config['sort_class'] ?? null;
if (!$this->sortClass) {
throw new RuntimeException('PaginationRequest requires a sort_class config');
}
}
public function rules(): array
{
return [
'sort' => ['nullable', new IsValidSortInstruction((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 ($validator->failed()) {
return;
}
$limit = $this->convertInteger('limit');
if (0 === $limit) {
// get default for user:
/** @var User $user */
$user = auth()->user();
$limit = (int)Preferences::getForUser($user, 'listPageSize', 50)->data;
}
$page = $this->convertInteger('page');
$page = min(max(1, $page), 2 ** 16);
$offset = ($page - 1) * $limit;
$sort = $this->sortClass ? $this->convertSortParameters('sort', $this->sortClass) : $this->get('sort');
$this->attributes->set('limit', $limit);
$this->attributes->set('sort', $sort);
$this->attributes->set('page', $page);
$this->attributes->set('offset', $offset);
}
);
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
/*
* BasicRequest.php
* Copyright (c) 2025 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Requests\Summary;
use FireflyIII\Api\V1\Requests\AggregateFormRequest;
use FireflyIII\Api\V1\Requests\DateRangeRequest;
use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\CurrencyCodeRequest;
class BasicRequest extends AggregateFormRequest
{
protected function getRequests(): array
{
return [
[DateRangeRequest::class, 'required'],
CurrencyCodeRequest::class,
];
}
}

View File

@@ -28,6 +28,7 @@ use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -47,7 +48,7 @@ class CorrectsFrontpageAccounts extends Command
/** @var User $user */ /** @var User $user */
foreach ($users as $user) { foreach ($users as $user) {
$preference = app('preferences')->getForUser($user, 'frontpageAccounts'); $preference = Preferences::getForUser($user, 'frontpageAccounts');
if (null !== $preference) { if (null !== $preference) {
$this->fixPreference($preference); $this->fixPreference($preference);
} }
@@ -79,6 +80,6 @@ class CorrectsFrontpageAccounts extends Command
} }
} }
} }
app('preferences')->setForUser($preference->user, 'frontpageAccounts', $fixed); Preferences::setForUser($preference->user, 'frontpageAccounts', $fixed);
} }
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Console\Commands\Correction;
use Exception; use Exception;
use FireflyIII\Console\Commands\ShowsFriendlyMessages; use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -54,10 +55,10 @@ class CreatesAccessTokens extends Command
/** @var User $user */ /** @var User $user */
foreach ($users as $user) { foreach ($users as $user) {
$pref = app('preferences')->getForUser($user, 'access_token'); $pref = Preferences::getForUser($user, 'access_token');
if (null === $pref) { if (null === $pref) {
$token = $user->generateAccessToken(); $token = $user->generateAccessToken();
app('preferences')->setForUser($user, 'access_token', $token); Preferences::setForUser($user, 'access_token', $token);
$this->friendlyInfo(sprintf('Generated access token for user %s', $user->email)); $this->friendlyInfo(sprintf('Generated access token for user %s', $user->email));
++$count; ++$count;
} }

View File

@@ -46,7 +46,7 @@ class SetsLatestVersion extends Command
return 0; return 0;
} }
FireflyConfig::set('ff3_version', config('firefly.version')); FireflyConfig::set('ff3_build_time', (int) config('firefly.build_time'));
$this->friendlyInfo('Updated version.'); $this->friendlyInfo('Updated version.');
return 0; return 0;

View File

@@ -33,6 +33,7 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface; use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -114,7 +115,7 @@ class UpgradesBillsToRules extends Command
$this->ruleRepository->setUser($user); $this->ruleRepository->setUser($user);
/** @var Preference $lang */ /** @var Preference $lang */
$lang = app('preferences')->getForUser($user, 'language', 'en_US'); $lang = Preferences::getForUser($user, 'language', 'en_US');
$language = null !== $lang->data && !is_array($lang->data) ? (string) $lang->data : 'en_US'; $language = null !== $lang->data && !is_array($lang->data) ? (string) $lang->data : 'en_US';
$groupTitle = (string) trans('firefly.rulegroup_for_bills_title', [], $language); $groupTitle = (string) trans('firefly.rulegroup_for_bills_title', [], $language);
$ruleGroup = $this->ruleGroupRepository->findByTitle($groupTitle); $ruleGroup = $this->ruleGroupRepository->findByTitle($groupTitle);

View File

@@ -87,7 +87,7 @@ class UpgradesDatabase extends Command
$this->call($command, $args); $this->call($command, $args);
} }
// index will set FF3 version. // index will set FF3 version.
FireflyConfig::set('ff3_version', (string) config('firefly.version')); FireflyConfig::set('ff3_build_time', (int) config('firefly.build_time'));
return 0; return 0;
} }

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Console\Commands;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -79,7 +80,7 @@ trait VerifiesAccessToken
return false; return false;
} }
$accessToken = app('preferences')->getForUser($user, 'access_token'); $accessToken = Preferences::getForUser($user, 'access_token');
if (null === $accessToken) { if (null === $accessToken) {
Log::error(sprintf('User #%d has no access token, so cannot access command line options.', $userId)); Log::error(sprintf('User #%d has no access token, so cannot access command line options.', $userId));

View File

@@ -84,8 +84,10 @@ class AttachmentFactory
return $attachment; return $attachment;
} }
public function setUser(User $user): void public function setUser(User $user): static
{ {
$this->user = $user; $this->user = $user;
return $this;
} }
} }

View File

@@ -221,10 +221,26 @@ class TransactionJournalFactory
]; ];
Log::debug('Source info:', $sourceInfo); Log::debug('Source info:', $sourceInfo);
Log::debug('Destination info:', $destInfo); Log::debug('Destination info:', $destInfo);
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo); $destinationAccount = null;
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo, $sourceAccount); $sourceAccount = null;
if (TransactionTypeEnum::DEPOSIT->value === $type->type) {
Log::debug('Transaction type is deposit, start with destination first.');
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo);
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo, $destinationAccount);
}
if (TransactionTypeEnum::DEPOSIT->value !== $type->type) {
Log::debug('Transaction type is not deposit, start with source first.');
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo);
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo, $sourceAccount);
}
Log::debug('Done with getAccount(2x)'); Log::debug('Done with getAccount(2x)');
// there is a safety catch here. If either account is NULL, they will be replaced with the cash account.
if (null === $destinationAccount) {
Log::warning('Destination account is NULL, will replace with cash account.');
$destinationAccount = $this->accountRepository->getCashAccount();
}
// this is the moment for a reconciliation sanity check (again). // this is the moment for a reconciliation sanity check (again).
if (TransactionTypeEnum::RECONCILIATION->value === $type->type) { if (TransactionTypeEnum::RECONCILIATION->value === $type->type) {

View File

@@ -30,6 +30,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
use FireflyIII\Notifications\User\TransactionCreation; use FireflyIII\Notifications\User\TransactionCreation;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\Transformers\TransactionGroupTransformer;
use Illuminate\Support\Facades\Notification; use Illuminate\Support\Facades\Notification;
@@ -52,7 +53,7 @@ class AutomationHandler
$user = $repository->find($event->userId); $user = $repository->find($event->userId);
/** @var bool $sendReport */ /** @var bool $sendReport */
$sendReport = app('preferences')->getForUser($user, 'notification_transaction_creation', false)->data; $sendReport = Preferences::getForUser($user, 'notification_transaction_creation', false)->data;
if (false === $sendReport) { if (false === $sendReport) {
app('log')->debug('Not sending report, because config says so.'); app('log')->debug('Not sending report, because config says so.');

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Handlers\Events\Model;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject; use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
use FireflyIII\Notifications\User\RuleActionFailed; use FireflyIII\Notifications\User\RuleActionFailed;
use FireflyIII\Support\Facades\Preferences;
use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Exception\ClientException;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification; use Illuminate\Support\Facades\Notification;
@@ -42,7 +43,7 @@ class RuleHandler
$rule = $ruleAction->rule; $rule = $ruleAction->rule;
/** @var bool $preference */ /** @var bool $preference */
$preference = app('preferences')->getForUser($rule->user, 'notification_rule_action_failures', true)->data; $preference = Preferences::getForUser($rule->user, 'notification_rule_action_failures', true)->data;
if (false === $preference) { if (false === $preference) {
return; return;
} }
@@ -71,7 +72,7 @@ class RuleHandler
$rule = $ruleAction->rule; $rule = $ruleAction->rule;
/** @var bool $preference */ /** @var bool $preference */
$preference = app('preferences')->getForUser($rule->user, 'notification_rule_action_failures', true)->data; $preference = Preferences::getForUser($rule->user, 'notification_rule_action_failures', true)->data;
if (false === $preference) { if (false === $preference) {
return; return;
} }

View File

@@ -27,6 +27,7 @@ use FireflyIII\Enums\WebhookTrigger;
use FireflyIII\Events\RequestedSendWebhookMessages; use FireflyIII\Events\RequestedSendWebhookMessages;
use FireflyIII\Events\StoredTransactionGroup; use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Generator\Webhook\MessageGeneratorInterface; use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\PeriodStatistic\PeriodStatisticRepositoryInterface; use FireflyIII\Repositories\PeriodStatistic\PeriodStatisticRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
@@ -105,10 +106,18 @@ class StoredGroupEventHandler
/** @var TransactionJournal $journal */ /** @var TransactionJournal $journal */
foreach ($event->transactionGroup->transactionJournals as $journal) { foreach ($event->transactionGroup->transactionJournals as $journal) {
/** @var null|Transaction $source */
$source = $journal->transactions()->where('amount', '<', '0')->first(); $source = $journal->transactions()->where('amount', '<', '0')->first();
/** @var null|Transaction $dest */
$dest = $journal->transactions()->where('amount', '>', '0')->first(); $dest = $journal->transactions()->where('amount', '>', '0')->first();
$repository->deleteStatisticsForModel($source->account, $journal->date);
$repository->deleteStatisticsForModel($dest->account, $journal->date); if (null !== $source) {
$repository->deleteStatisticsForModel($source->account, $journal->date);
}
if (null !== $dest) {
$repository->deleteStatisticsForModel($dest->account, $journal->date);
}
$categories = $journal->categories; $categories = $journal->categories;
$tags = $journal->tags; $tags = $journal->tags;
$budgets = $journal->budgets; $budgets = $journal->budgets;

View File

@@ -51,6 +51,7 @@ use FireflyIII\Notifications\User\UserLogin;
use FireflyIII\Notifications\User\UserNewPassword; use FireflyIII\Notifications\User\UserNewPassword;
use FireflyIII\Notifications\User\UserRegistration as UserRegistrationNotification; use FireflyIII\Notifications\User\UserRegistration as UserRegistrationNotification;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Auth\Events\Login; use Illuminate\Auth\Events\Login;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -174,9 +175,10 @@ class UserEventHandler
$user = $event->user; $user = $event->user;
if ($repository->hasRole($user, 'demo')) { if ($repository->hasRole($user, 'demo')) {
// set user back to English. // set user back to English.
app('preferences')->setForUser($user, 'language', 'en_US'); Preferences::setForUser($user, 'language', 'en_US');
app('preferences')->setForUser($user, 'locale', 'equal'); Preferences::setForUser($user, 'locale', 'equal');
app('preferences')->mark(); Preferences::setForUser($user, 'anonymous', false);
Preferences::mark();
} }
} }
@@ -188,7 +190,7 @@ class UserEventHandler
return; // do not email demo user. return; // do not email demo user.
} }
$list = app('preferences')->getForUser($user, 'login_ip_history', [])->data; $list = Preferences::getForUser($user, 'login_ip_history', [])->data;
if (!is_array($list)) { if (!is_array($list)) {
$list = []; $list = [];
} }
@@ -217,12 +219,12 @@ class UserEventHandler
$list[$index]['notified'] = true; $list[$index]['notified'] = true;
} }
app('preferences')->setForUser($user, 'login_ip_history', $list); Preferences::setForUser($user, 'login_ip_history', $list);
} }
public function sendAdminRegistrationNotification(RegisteredUser $event): void public function sendAdminRegistrationNotification(RegisteredUser $event): void
{ {
$sendMail = (bool) app('fireflyconfig')->get('notification_admin_new_reg', true)->data; $sendMail = (bool)app('fireflyconfig')->get('notification_admin_new_reg', true)->data;
if ($sendMail) { if ($sendMail) {
$owner = $event->owner; $owner = $event->owner;
@@ -257,7 +259,7 @@ class UserEventHandler
$newEmail = $event->newEmail; $newEmail = $event->newEmail;
$oldEmail = $event->oldEmail; $oldEmail = $event->oldEmail;
$user = $event->user; $user = $event->user;
$token = app('preferences')->getForUser($user, 'email_change_confirm_token', 'invalid'); $token = Preferences::getForUser($user, 'email_change_confirm_token', 'invalid');
$url = route('profile.confirm-email-change', [$token->data]); $url = route('profile.confirm-email-change', [$token->data]);
try { try {
@@ -281,8 +283,8 @@ class UserEventHandler
$newEmail = $event->newEmail; $newEmail = $event->newEmail;
$oldEmail = $event->oldEmail; $oldEmail = $event->oldEmail;
$user = $event->user; $user = $event->user;
$token = app('preferences')->getForUser($user, 'email_change_undo_token', 'invalid'); $token = Preferences::getForUser($user, 'email_change_undo_token', 'invalid');
$hashed = hash('sha256', sprintf('%s%s', (string) config('app.key'), $oldEmail)); $hashed = hash('sha256', sprintf('%s%s', (string)config('app.key'), $oldEmail));
$url = route('profile.undo-email-change', [$token->data, $hashed]); $url = route('profile.undo-email-change', [$token->data, $hashed]);
try { try {
@@ -365,7 +367,7 @@ class UserEventHandler
*/ */
public function sendRegistrationMail(RegisteredUser $event): void public function sendRegistrationMail(RegisteredUser $event): void
{ {
$sendMail = (bool) app('fireflyconfig')->get('notification_user_new_reg', true)->data; $sendMail = (bool)app('fireflyconfig')->get('notification_user_new_reg', true)->data;
if ($sendMail) { if ($sendMail) {
try { try {
Notification::send($event->user, new UserRegistrationNotification()); Notification::send($event->user, new UserRegistrationNotification());
@@ -455,7 +457,7 @@ class UserEventHandler
try { try {
/** @var array $preference */ /** @var array $preference */
$preference = app('preferences')->getForUser($user, 'login_ip_history', [])->data; $preference = Preferences::getForUser($user, 'login_ip_history', [])->data;
} catch (FireflyException $e) { } catch (FireflyException $e) {
// don't care. // don't care.
app('log')->error($e->getMessage()); app('log')->error($e->getMessage());
@@ -491,8 +493,8 @@ class UserEventHandler
$preference = array_values($preference); $preference = array_values($preference);
/** @var bool $send */ /** @var bool $send */
$send = app('preferences')->getForUser($user, 'notification_user_login', true)->data; $send = Preferences::getForUser($user, 'notification_user_login', true)->data;
app('preferences')->setForUser($user, 'login_ip_history', $preference); Preferences::setForUser($user, 'login_ip_history', $preference);
if (false === $inArray && true === $send) { if (false === $inArray && true === $send) {
event(new DetectedNewIPAddress($user)); event(new DetectedNewIPAddress($user));

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Helpers\Fiscal; namespace FireflyIII\Helpers\Fiscal;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Support\Facades\Preferences;
use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface; use Psr\Container\NotFoundExceptionInterface;
@@ -40,7 +41,7 @@ class FiscalHelper implements FiscalHelperInterface
*/ */
public function __construct() public function __construct()
{ {
$this->useCustomFiscalYear = (bool) app('preferences')->get('customFiscalYear', false)->data; $this->useCustomFiscalYear = (bool) Preferences::get('customFiscalYear', false)->data;
} }
/** /**
@@ -74,7 +75,7 @@ class FiscalHelper implements FiscalHelperInterface
// get start mm-dd. Then create a start date in the year passed. // get start mm-dd. Then create a start date in the year passed.
$startDate = clone $date; $startDate = clone $date;
if (true === $this->useCustomFiscalYear) { if (true === $this->useCustomFiscalYear) {
$prefStartStr = app('preferences')->get('fiscalYearStart', '01-01')->data; $prefStartStr = Preferences::get('fiscalYearStart', '01-01')->data;
if (is_array($prefStartStr)) { if (is_array($prefStartStr)) {
$prefStartStr = '01-01'; $prefStartStr = '01-01';
} }

View File

@@ -96,11 +96,10 @@ class CreateController extends Controller
]; ];
// interest calculation periods: // interest calculation periods:
$interestPeriods = [ $interestPeriods = [];
'daily' => (string) trans('firefly.interest_calc_daily'), foreach (config('firefly.interest_periods') as $period) {
'monthly' => (string) trans('firefly.interest_calc_monthly'), $interestPeriods[$period] = trans(sprintf('firefly.interest_calc_%s', $period));
'yearly' => (string) trans('firefly.interest_calc_yearly'), }
];
// pre fill some data // pre fill some data
$request->session()->flash( $request->session()->flash(

View File

@@ -108,11 +108,10 @@ class EditController extends Controller
]; ];
// interest calculation periods: // interest calculation periods:
$interestPeriods = [ $interestPeriods = [];
'daily' => (string) trans('firefly.interest_calc_daily'), foreach (config('firefly.interest_periods') as $period) {
'monthly' => (string) trans('firefly.interest_calc_monthly'), $interestPeriods[$period] = trans(sprintf('firefly.interest_calc_%s', $period));
'yearly' => (string) trans('firefly.interest_calc_yearly'), }
];
// put previous url in session if not redirect from store (not "return_to_edit"). // put previous url in session if not redirect from store (not "return_to_edit").
if (true !== session('accounts.edit.fromUpdate')) { if (true !== session('accounts.edit.fromUpdate')) {

View File

@@ -77,6 +77,7 @@ abstract class Controller extends BaseController
View::share('DEMO_USERNAME', config('firefly.demo_username')); View::share('DEMO_USERNAME', config('firefly.demo_username'));
View::share('DEMO_PASSWORD', config('firefly.demo_password')); View::share('DEMO_PASSWORD', config('firefly.demo_password'));
View::share('FF_VERSION', config('firefly.version')); View::share('FF_VERSION', config('firefly.version'));
View::share('FF_BUILD_TIME', config('firefly.build_time'));
// is webhooks enabled? // is webhooks enabled?
View::share('featuringWebhooks', true === config('firefly.feature_flags.webhooks') && true === config('firefly.allow_webhooks')); View::share('featuringWebhooks', true === config('firefly.feature_flags.webhooks') && true === config('firefly.allow_webhooks'));
@@ -131,6 +132,7 @@ abstract class Controller extends BaseController
$this->primaryCurrency = null; $this->primaryCurrency = null;
// get shown-intro-preference: // get shown-intro-preference:
if (auth()->check()) { if (auth()->check()) {
View::share('anonymous', Steam::anonymous());
$this->primaryCurrency = Amount::getPrimaryCurrency(); $this->primaryCurrency = Amount::getPrimaryCurrency();
$language = Steam::getLanguage(); $language = Steam::getLanguage();
$locale = Steam::getLocale(); $locale = Steam::getLocale();

View File

@@ -81,11 +81,11 @@ class DebugController extends Controller
*/ */
public function displayError(): void public function displayError(): void
{ {
app('log')->debug('This is a test message at the DEBUG level.'); Log::debug('This is a test message at the DEBUG level.');
app('log')->info('This is a test message at the INFO level.'); Log::info('This is a test message at the INFO level.');
Log::notice('This is a test message at the NOTICE level.'); Log::notice('This is a test message at the NOTICE level.');
app('log')->warning('This is a test message at the WARNING level.'); Log::warning('This is a test message at the WARNING level.');
app('log')->error('This is a test message at the ERROR level.'); Log::error('This is a test message at the ERROR level.');
Log::critical('This is a test message at the CRITICAL level.'); Log::critical('This is a test message at the CRITICAL level.');
Log::alert('This is a test message at the ALERT level.'); Log::alert('This is a test message at the ALERT level.');
Log::emergency('This is a test message at the EMERGENCY level.'); Log::emergency('This is a test message at the EMERGENCY level.');
@@ -187,6 +187,8 @@ class DebugController extends Controller
return [ return [
'php_version' => PHP_VERSION, 'php_version' => PHP_VERSION,
'php_os' => PHP_OS, 'php_os' => PHP_OS,
'build_time' => config('firefly.build_time'),
'build_time_nice' => Carbon::parse(config('firefly.build_time'), 'Europe/Amsterdam')->setTimezone('Europe/Amsterdam')->format('Y-m-d H:i:s e'),
'uname' => php_uname('m'), 'uname' => php_uname('m'),
'interface' => PHP_SAPI, 'interface' => PHP_SAPI,
'bits' => PHP_INT_SIZE * 8, 'bits' => PHP_INT_SIZE * 8,
@@ -212,11 +214,11 @@ class DebugController extends Controller
try { try {
if (file_exists('/var/www/counter-main.txt')) { if (file_exists('/var/www/counter-main.txt')) {
$return['build'] = trim(file_get_contents('/var/www/counter-main.txt')); $return['build'] = trim(file_get_contents('/var/www/counter-main.txt'));
app('log')->debug(sprintf('build is now "%s"', $return['build'])); Log::debug(sprintf('build is now "%s"', $return['build']));
} }
} catch (Exception $e) { } catch (Exception $e) {
app('log')->debug('Could not check build counter, but thats ok.'); Log::debug('Could not check build counter, but thats ok.');
app('log')->warning($e->getMessage()); Log::warning($e->getMessage());
} }
try { try {
@@ -224,8 +226,8 @@ class DebugController extends Controller
$return['build_date'] = trim(file_get_contents('/var/www/build-date-main.txt')); $return['build_date'] = trim(file_get_contents('/var/www/build-date-main.txt'));
} }
} catch (Exception $e) { } catch (Exception $e) {
app('log')->debug('Could not check build date, but thats ok.'); Log::debug('Could not check build date, but thats ok.');
app('log')->warning($e->getMessage()); Log::warning($e->getMessage());
} }
if ('' !== (string) env('BASE_IMAGE_BUILD')) { // @phpstan-ignore-line if ('' !== (string) env('BASE_IMAGE_BUILD')) { // @phpstan-ignore-line
$return['base_build'] = env('BASE_IMAGE_BUILD'); // @phpstan-ignore-line $return['base_build'] = env('BASE_IMAGE_BUILD'); // @phpstan-ignore-line
@@ -282,7 +284,7 @@ class DebugController extends Controller
$parts = Steam::getLocaleArray(Steam::getLocale()); $parts = Steam::getLocaleArray(Steam::getLocale());
foreach ($parts as $code) { foreach ($parts as $code) {
$code = trim($code); $code = trim($code);
app('log')->debug(sprintf('Trying to set %s', $code)); Log::debug(sprintf('Trying to set %s', $code));
$result = setlocale(LC_ALL, $code); $result = setlocale(LC_ALL, $code);
$localeAttempts[$code] = $result === $code; $localeAttempts[$code] = $result === $code;
} }

View File

@@ -30,6 +30,7 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Controllers\GetConfigurationData; use FireflyIII\Support\Http\Controllers\GetConfigurationData;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
@@ -114,6 +115,7 @@ class JavascriptController extends Controller
'currencyCode' => $currency->code, 'currencyCode' => $currency->code,
'currencySymbol' => $currency->symbol, 'currencySymbol' => $currency->symbol,
'accountingLocaleInfo' => $accounting, 'accountingLocaleInfo' => $accounting,
'anonymous' => var_export(Steam::anonymous(), true),
'language' => $lang, 'language' => $lang,
'dateRangeTitle' => $dateRange['title'], 'dateRangeTitle' => $dateRange['title'],
'locale' => $locale, 'locale' => $locale,

View File

@@ -268,7 +268,6 @@ class CreateController extends Controller
public function store(RuleFormRequest $request) public function store(RuleFormRequest $request)
{ {
$data = $request->getRuleData(); $data = $request->getRuleData();
$rule = $this->ruleRepos->store($data); $rule = $this->ruleRepos->store($data);
session()->flash('success_url', route('rules.select-transactions', [$rule->id])); session()->flash('success_url', route('rules.select-transactions', [$rule->id]));
session()->flash('success', (string) trans('firefly.stored_new_rule', ['title' => $rule->title])); session()->flash('success', (string) trans('firefly.stored_new_rule', ['title' => $rule->title]));
@@ -283,6 +282,9 @@ class CreateController extends Controller
if ((int) $request->get('bill_id') > 0) { if ((int) $request->get('bill_id') > 0) {
return redirect($this->getPreviousUrl('bills.create.url')); return redirect($this->getPreviousUrl('bills.create.url'));
} }
if (true === $data['run_after_form']) {
return redirect(route('rules.select-transactions', [$rule->id]));
}
$redirect = redirect($this->getPreviousUrl('rules.create.url')); $redirect = redirect($this->getPreviousUrl('rules.create.url'));

View File

@@ -205,6 +205,11 @@ class EditController extends Controller
session()->flash('success', (string) trans('firefly.updated_rule', ['title' => $rule->title])); session()->flash('success', (string) trans('firefly.updated_rule', ['title' => $rule->title]));
app('preferences')->mark(); app('preferences')->mark();
$redirect = redirect($this->getPreviousUrl('rules.edit.url')); $redirect = redirect($this->getPreviousUrl('rules.edit.url'));
if (true === $data['run_after_form']) {
return redirect(route('rules.select-transactions', [$rule->id]));
}
if (1 === (int) $request->get('return_to_edit')) { if (1 === (int) $request->get('return_to_edit')) {
session()->put('rules.edit.fromUpdate', true); session()->put('rules.edit.fromUpdate', true);

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Rule; namespace FireflyIII\Http\Controllers\Rule;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\SelectTransactionsRequest; use FireflyIII\Http\Requests\SelectTransactionsRequest;
@@ -56,7 +57,7 @@ class SelectController extends Controller
$this->middleware( $this->middleware(
static function ($request, $next) { static function ($request, $next) {
app('view')->share('title', (string) trans('firefly.rules')); app('view')->share('title', (string)trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random'); app('view')->share('mainTitleIcon', 'fa-random');
return $next($request); return $next($request);
@@ -73,11 +74,20 @@ class SelectController extends Controller
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
$accounts = implode(',', $request->get('accounts')); $accounts = implode(',', $request->get('accounts'));
// create new rule engine: // create new rule engine:
$newRuleEngine = app(RuleEngineInterface::class); $newRuleEngine = app(RuleEngineInterface::class);
$newRuleEngine->setUser($user); $newRuleEngine->setUser($user);
// add date operators.
if (null !== $request->get('start')) {
$startDate = new Carbon($request->get('start'));
$newRuleEngine->addOperator(['type' => 'date_after', 'value' => $startDate->format('Y-m-d')]);
}
if (null !== $request->get('end')) {
$endDate = new Carbon($request->get('end'));
$newRuleEngine->addOperator(['type' => 'date_before', 'value' => $endDate->format('Y-m-d')]);
}
// add extra operators: // add extra operators:
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]); $newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);
@@ -102,7 +112,7 @@ class SelectController extends Controller
return redirect(route('rules.index')); return redirect(route('rules.index'));
} }
// does the user have shared accounts? // does the user have shared accounts?
$subTitle = (string) trans('firefly.apply_rule_selection', ['title' => $rule->title]); $subTitle = (string)trans('firefly.apply_rule_selection', ['title' => $rule->title]);
return view('rules.rule.select-transactions', compact('rule', 'subTitle')); return view('rules.rule.select-transactions', compact('rule', 'subTitle'));
} }
@@ -127,7 +137,7 @@ class SelectController extends Controller
// warn if nothing. // warn if nothing.
if (0 === count($textTriggers)) { if (0 === count($textTriggers)) {
return response()->json(['html' => '', 'warning' => (string) trans('firefly.warning_no_valid_triggers')]); return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]);
} }
foreach ($textTriggers as $textTrigger) { foreach ($textTriggers as $textTrigger) {
@@ -160,7 +170,7 @@ class SelectController extends Controller
// Warn the user if only a subset of transactions is returned // Warn the user if only a subset of transactions is returned
$warning = ''; $warning = '';
if (0 === count($collection)) { if (0 === count($collection)) {
$warning = (string) trans('firefly.warning_no_matching_transactions'); $warning = (string)trans('firefly.warning_no_matching_transactions');
} }
// Return json response // Return json response
@@ -190,7 +200,7 @@ class SelectController extends Controller
$triggers = $rule->ruleTriggers; $triggers = $rule->ruleTriggers;
if (0 === count($triggers)) { if (0 === count($triggers)) {
return response()->json(['html' => '', 'warning' => (string) trans('firefly.warning_no_valid_triggers')]); return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]);
} }
// create new rule engine: // create new rule engine:
$newRuleEngine = app(RuleEngineInterface::class); $newRuleEngine = app(RuleEngineInterface::class);
@@ -202,7 +212,7 @@ class SelectController extends Controller
$warning = ''; $warning = '';
if (0 === count($collection)) { if (0 === count($collection)) {
$warning = (string) trans('firefly.warning_no_matching_transactions'); $warning = (string)trans('firefly.warning_no_matching_transactions');
} }
// Return json response // Return json response

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\RuleGroup; namespace FireflyIII\Http\Controllers\RuleGroup;
use Carbon\Carbon;
use Exception; use Exception;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\SelectTransactionsRequest; use FireflyIII\Http\Requests\SelectTransactionsRequest;
@@ -73,6 +74,16 @@ class ExecutionController extends Controller
$newRuleEngine = app(RuleEngineInterface::class); $newRuleEngine = app(RuleEngineInterface::class);
$newRuleEngine->setUser($user); $newRuleEngine->setUser($user);
// add date operators.
if (null !== $request->get('start')) {
$startDate = new Carbon($request->get('start'));
$newRuleEngine->addOperator(['type' => 'date_after', 'value' => $startDate->format('Y-m-d')]);
}
if (null !== $request->get('end')) {
$endDate = new Carbon($request->get('end'));
$newRuleEngine->addOperator(['type' => 'date_before', 'value' => $endDate->format('Y-m-d')]);
}
// add extra operators: // add extra operators:
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]); $newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);

View File

@@ -34,6 +34,7 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use Laravel\Passport\Passport; use Laravel\Passport\Passport;
use phpseclib3\Crypt\RSA; use phpseclib3\Crypt\RSA;
@@ -81,8 +82,10 @@ class InstallController extends Controller
public function index() public function index()
{ {
app('view')->share('FF_VERSION', config('firefly.version')); app('view')->share('FF_VERSION', config('firefly.version'));
// index will set FF3 version. // index will set FF3 version.
FireflyConfig::set('ff3_version', (string) config('firefly.version')); FireflyConfig::set('ff3_version', (string) config('firefly.version'));
FireflyConfig::set('ff3_build_time', (int) config('firefly.build_time'));
return view('install.index'); return view('install.index');
} }
@@ -98,18 +101,18 @@ class InstallController extends Controller
'errorMessage' => null, 'errorMessage' => null,
]; ];
app('log')->debug(sprintf('Will now run commands. Request index is %d', $requestIndex)); Log::debug(sprintf('Will now run commands. Request index is %d', $requestIndex));
$indexes = array_keys($this->upgradeCommands); $indexes = array_keys($this->upgradeCommands);
if (array_key_exists($requestIndex, $indexes)) { if (array_key_exists($requestIndex, $indexes)) {
$command = $indexes[$requestIndex]; $command = $indexes[$requestIndex];
$parameters = $this->upgradeCommands[$command]; $parameters = $this->upgradeCommands[$command];
app('log')->debug(sprintf('Will now execute command "%s" with parameters', $command), $parameters); Log::debug(sprintf('Will now execute command "%s" with parameters', $command), $parameters);
try { try {
$result = $this->executeCommand($command, $parameters); $result = $this->executeCommand($command, $parameters);
} catch (FireflyException $e) { } catch (FireflyException $e) {
app('log')->error($e->getMessage()); Log::error($e->getMessage());
app('log')->error($e->getTraceAsString()); Log::error($e->getTraceAsString());
if (str_contains($e->getMessage(), 'open_basedir restriction in effect')) { if (str_contains($e->getMessage(), 'open_basedir restriction in effect')) {
$this->lastError = self::BASEDIR_ERROR; $this->lastError = self::BASEDIR_ERROR;
} }
@@ -134,7 +137,7 @@ class InstallController extends Controller
*/ */
private function executeCommand(string $command, array $args): bool private function executeCommand(string $command, array $args): bool
{ {
app('log')->debug(sprintf('Will now call command %s with args.', $command), $args); Log::debug(sprintf('Will now call command %s with args.', $command), $args);
try { try {
if ('generate-keys' === $command) { if ('generate-keys' === $command) {
@@ -142,7 +145,7 @@ class InstallController extends Controller
} }
if ('generate-keys' !== $command) { if ('generate-keys' !== $command) {
Artisan::call($command, $args); Artisan::call($command, $args);
app('log')->debug(Artisan::output()); Log::debug(Artisan::output());
} }
} catch (Exception $e) { // intentional generic exception } catch (Exception $e) { // intentional generic exception
throw new FireflyException($e->getMessage(), 0, $e); throw new FireflyException($e->getMessage(), 0, $e);

View File

@@ -54,6 +54,7 @@ class RuleFormRequest extends FormRequest
'description' => $this->stringWithNewlines('description'), 'description' => $this->stringWithNewlines('description'),
'stop_processing' => $this->boolean('stop_processing'), 'stop_processing' => $this->boolean('stop_processing'),
'strict' => $this->boolean('strict'), 'strict' => $this->boolean('strict'),
'run_after_form' => $this->boolean('run_after_form'),
'triggers' => $this->getRuleTriggerData(), 'triggers' => $this->getRuleTriggerData(),
'actions' => $this->getRuleActionData(), 'actions' => $this->getRuleActionData(),
]; ];
@@ -140,16 +141,17 @@ class RuleFormRequest extends FormRequest
// initial set of rules: // initial set of rules:
$rules = [ $rules = [
'title' => 'required|min:1|max:255|uniqueObjectForUser:rules,title', 'title' => 'required|min:1|max:255|uniqueObjectForUser:rules,title',
'description' => 'min:1|max:32768|nullable', 'description' => 'min:1|max:32768|nullable',
'stop_processing' => 'boolean', 'stop_processing' => 'boolean',
'rule_group_id' => 'required|belongsToUser:rule_groups', 'rule_group_id' => 'required|belongsToUser:rule_groups',
'trigger' => 'required|in:store-journal,update-journal,manual-activation', 'trigger' => 'required|in:store-journal,update-journal,manual-activation',
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), 'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
'triggers.*.value' => sprintf('required_if:triggers.*.type,%s|max:1024|min:1|ruleTriggerValue', $contextTriggers), 'triggers.*.value' => sprintf('required_if:triggers.*.type,%s|max:1024|min:1|ruleTriggerValue', $contextTriggers),
'actions.*.type' => 'required|in:'.implode(',', $validActions), 'actions.*.type' => 'required|in:'.implode(',', $validActions),
'actions.*.value' => [sprintf('required_if:actions.*.type,%s|min:0|max:1024', $contextActions), new IsValidActionExpression(), 'ruleActionValue'], 'actions.*.value' => [sprintf('required_if:actions.*.type,%s|min:0|max:1024', $contextActions), new IsValidActionExpression(), 'ruleActionValue'],
'strict' => 'in:0,1', 'strict' => 'in:0,1',
'run_after_form' => 'in:0,1',
]; ];
/** @var null|Rule $rule */ /** @var null|Rule $rule */

View File

@@ -31,6 +31,8 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use Safe\Exceptions\FilesystemException;
use Safe\Exceptions\JsonException;
use Symfony\Component\Mailer\Exception\TransportException; use Symfony\Component\Mailer\Exception\TransportException;
use function Safe\file_get_contents; use function Safe\file_get_contents;
@@ -54,7 +56,7 @@ class MailError extends Job implements ShouldQueue
$debug = $this->exception; $debug = $this->exception;
unset($debug['stackTrace'], $debug['headers']); unset($debug['stackTrace'], $debug['headers']);
app('log')->error(sprintf('Exception is: %s', json_encode($debug))); Log::error(sprintf('Exception is: %s', json_encode($debug)));
} }
/** /**
@@ -90,17 +92,17 @@ class MailError extends Job implements ShouldQueue
} catch (Exception|TransportException $e) { } catch (Exception|TransportException $e) {
$message = $e->getMessage(); $message = $e->getMessage();
if (str_contains($message, 'Bcc')) { if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not email or log the error. Please validate your email settings, use the .env.example file as a guide.'); Log::warning('[Bcc] Could not email or log the error. Please validate your email settings, use the .env.example file as a guide.');
return; return;
} }
if (str_contains($message, 'RFC 2822')) { if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not email or log the error. Please validate your email settings, use the .env.example file as a guide.'); Log::warning('[RFC] Could not email or log the error. Please validate your email settings, use the .env.example file as a guide.');
return; return;
} }
app('log')->error($e->getMessage()); Log::error($e->getMessage());
app('log')->error($e->getTraceAsString()); Log::error($e->getTraceAsString());
} }
} }
} }
@@ -125,11 +127,25 @@ class MailError extends Job implements ShouldQueue
if (!file_exists($file)) { if (!file_exists($file)) {
Log::debug(sprintf('Wrote new file in "%s"', $file)); Log::debug(sprintf('Wrote new file in "%s"', $file));
file_put_contents($file, json_encode($limits, JSON_PRETTY_PRINT));
try {
file_put_contents($file, json_encode($limits, JSON_PRETTY_PRINT));
} catch (FilesystemException $e) {
Log::warning(sprintf('[a] Could not write file "%s": %s', $file, $e->getMessage()));
} catch (JsonException $e) {
Log::warning(sprintf('[b] Could not parse file "%s": %s', $file, $e->getMessage()));
}
} }
if (file_exists($file)) { if (file_exists($file)) {
Log::debug(sprintf('Read file in "%s"', $file)); Log::debug(sprintf('Read file in "%s"', $file));
$limits = json_decode(file_get_contents($file), true);
try {
$limits = json_decode(file_get_contents($file), true);
} catch (FilesystemException $e) {
Log::warning(sprintf('[c] Could not read file "%s": %s', $file, $e->getMessage()));
} catch (JsonException $e) {
Log::warning(sprintf('[d] Could not parse file "%s": %s', $file, $e->getMessage()));
}
} }
// limit reached? // limit reached?
foreach ($types as $type => $info) { foreach ($types as $type => $info) {
@@ -157,7 +173,14 @@ class MailError extends Job implements ShouldQueue
} }
++$limits[$type]['sent']; ++$limits[$type]['sent'];
} }
file_put_contents($file, json_encode($limits, JSON_PRETTY_PRINT));
try {
file_put_contents($file, json_encode($limits, JSON_PRETTY_PRINT));
} catch (FilesystemException $e) {
Log::warning(sprintf('[c] Could not write file "%s": %s', $file, $e->getMessage()));
} catch (JsonException $e) {
Log::warning(sprintf('[c] Could not parse file "%s": %s', $file, $e->getMessage()));
}
Log::debug('No limits reached, return FALSE.'); Log::debug('No limits reached, return FALSE.');
return false; return false;

View File

@@ -0,0 +1,56 @@
<?php
/*
* IsValidAccountType.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Rules\Account;
use Closure;
use FireflyIII\Support\Http\Api\AccountFilter;
use Illuminate\Contracts\Validation\ValidationRule;
use Override;
class IsValidAccountTypeList implements ValidationRule
{
use AccountFilter;
#[Override]
public function validate(string $attribute, mixed $value, Closure $fail): void
{
// only check the type.
$values = [];
if (is_string($value)) {
$values = explode(',', $value);
}
if (!is_array($values)) {
$fail('validation.invalid_account_list')->translate();
}
$keys = array_keys($this->types);
foreach ($values as $entry) {
$entry = (string) $entry;
if (!in_array($entry, $keys, true)) {
$fail('validation.invalid_account_list')->translate();
}
}
}
}

View File

@@ -38,6 +38,11 @@ class IsValidSortInstruction implements ValidationRule
return; return;
} }
if ('' === $value) {
// don't validate.
return;
}
$validParameters = config(sprintf('firefly.allowed_sort_parameters.%s', $shortClass)); $validParameters = config(sprintf('firefly.allowed_sort_parameters.%s', $shortClass));
if (!is_array($validParameters)) { if (!is_array($validParameters)) {
$fail('validation.no_sort_instructions')->translate(['object' => $shortClass]); $fail('validation.no_sort_instructions')->translate(['object' => $shortClass]);

View File

@@ -88,6 +88,7 @@ trait JournalServiceTrait
// the account that Firefly III creates must be "creatable", aka select the one we can create from the list just in case // the account that Firefly III creates must be "creatable", aka select the one we can create from the list just in case
$creatableType = $this->getCreatableType($expectedTypes[$transactionType]); $creatableType = $this->getCreatableType($expectedTypes[$transactionType]);
Log::debug(sprintf('Creatable type is "%s"', $creatableType), $expectedTypes[$transactionType]);
// if the result is NULL but the ID is set, an account could exist of the wrong type. // if the result is NULL but the ID is set, an account could exist of the wrong type.
// that data can be used to create a new account of the right type. // that data can be used to create a new account of the right type.
@@ -227,9 +228,11 @@ trait JournalServiceTrait
} }
// find by preferred type. // find by preferred type.
Log::debug('Find by preferred type.');
$result = $this->accountRepository->findByName($data['name'], [$types[0]]); $result = $this->accountRepository->findByName($data['name'], [$types[0]]);
// or any expected type. // or any expected type.
Log::debug('Find by any expected type.');
$result ??= $this->accountRepository->findByName($data['name'], $types); $result ??= $this->accountRepository->findByName($data['name'], $types);
if (null !== $result) { if (null !== $result) {

View File

@@ -163,6 +163,7 @@ class Amount
*/ */
public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string
{ {
$amount = Steam::anonymous() ? '0' : $amount;
$locale = Steam::getLocale(); $locale = Steam::getLocale();
$rounded = Steam::bcround($amount, $decimalPlaces); $rounded = Steam::bcround($amount, $decimalPlaces);
$coloured ??= true; $coloured ??= true;

View File

@@ -634,10 +634,10 @@ trait PeriodOverview
$currencySymbol = $journal['currency_symbol']; $currencySymbol = $journal['currency_symbol'];
$currencyDecimalPlaces = $journal['currency_decimal_places']; $currencyDecimalPlaces = $journal['currency_decimal_places'];
$foreignCurrencyId = $journal['foreign_currency_id']; $foreignCurrencyId = $journal['foreign_currency_id'];
$amount = $journal['amount'] ?? '0'; $amount = (string) ($journal['amount'] ?? '0');
if ($this->convertToPrimary && $currencyId !== $this->primaryCurrency->id && $foreignCurrencyId !== $this->primaryCurrency->id) { if ($this->convertToPrimary && $currencyId !== $this->primaryCurrency->id && $foreignCurrencyId !== $this->primaryCurrency->id) {
$amount = $journal['pc_amount'] ?? '0'; $amount = (string) ($journal['pc_amount'] ?? '0');
$currencyId = $this->primaryCurrency->id; $currencyId = $this->primaryCurrency->id;
$currencyCode = $this->primaryCurrency->code; $currencyCode = $this->primaryCurrency->code;
$currencyName = $this->primaryCurrency->name; $currencyName = $this->primaryCurrency->name;
@@ -650,7 +650,7 @@ trait PeriodOverview
$currencyName = $journal['foreign_currency_name']; $currencyName = $journal['foreign_currency_name'];
$currencySymbol = $journal['foreign_currency_symbol']; $currencySymbol = $journal['foreign_currency_symbol'];
$currencyDecimalPlaces = $journal['foreign_currency_decimal_places']; $currencyDecimalPlaces = $journal['foreign_currency_decimal_places'];
$amount = $journal['foreign_amount'] ?? '0'; $amount = (string) ($journal['foreign_amount'] ?? '0');
} }
$return[$currencyId] ??= [ $return[$currencyId] ??= [
'amount' => '0', 'amount' => '0',

View File

@@ -154,6 +154,9 @@ class BudgetLimitEnrichment implements EnrichmentInterface
$this->start = $this->collection->min('start_date') ?? Carbon::now()->startOfMonth(); $this->start = $this->collection->min('start_date') ?? Carbon::now()->startOfMonth();
$this->end = $this->collection->max('end_date') ?? Carbon::now()->endOfMonth(); $this->end = $this->collection->max('end_date') ?? Carbon::now()->endOfMonth();
// #11096 make sure that the max end date is also at the end of the day,
$this->end->endOfDay();
/** @var BudgetLimit $limit */ /** @var BudgetLimit $limit */
foreach ($this->collection as $limit) { foreach ($this->collection as $limit) {
$id = (int)$limit->id; $id = (int)$limit->id;

View File

@@ -88,7 +88,7 @@ trait UserGroupTrait
public function setUserGroup(UserGroup $userGroup): void public function setUserGroup(UserGroup $userGroup): void
{ {
if (null === $this->user) { if (null === $this->user) {
Log::warning(sprintf('User is not set in repository %s', static::class)); Log::warning(sprintf('User is not set in repository %s. This does not have to be a problem.', static::class));
} }
$this->userGroup = $userGroup; $this->userGroup = $userGroup;
} }

View File

@@ -52,13 +52,23 @@ class QueryParser implements QueryParserInterface
$inQuotes = false; $inQuotes = false;
$fieldName = ''; $fieldName = '';
$prohibited = false; $prohibited = false;
$chrArray = preg_split('//u', $this->query, -1, PREG_SPLIT_NO_EMPTY);
while ($this->position < strlen($this->query)) { $count = count($chrArray);
$char = $this->query[$this->position]; while ($this->position < $count) {
$char = $chrArray[$this->position];
$nextChar = $chrArray[$this->position + 1] ?? '';
// Log::debug(sprintf('Char #%d: %s', $this->position, $char)); // Log::debug(sprintf('Char #%d: %s', $this->position, $char));
// If we're in a quoted string, we treat all characters except another quote as ordinary characters // If we're in a quoted string, we treat all characters except another quote as ordinary characters
if ($inQuotes) { if ($inQuotes) {
if ('\\' === $char && '"' === $nextChar) {
// Log::debug('BACKSLASH!');
// escaped quote, pretend it's a normal char and continue two places (skipping the actual character).
$tokenUnderConstruction .= '\\'.$nextChar;
$this->position += 2;
continue;
}
if ('"' !== $char) { if ('"' !== $char) {
$tokenUnderConstruction .= $char; $tokenUnderConstruction .= $char;
++$this->position; ++$this->position;
@@ -67,11 +77,9 @@ class QueryParser implements QueryParserInterface
} }
// char is " // char is "
++$this->position; ++$this->position;
Log::debug(sprintf('Constructed token: %s', $tokenUnderConstruction));
return new NodeResult( return new NodeResult($this->createNode($tokenUnderConstruction, $fieldName, $prohibited), false);
$this->createNode($tokenUnderConstruction, $fieldName, $prohibited),
false
);
} }
switch ($char) { switch ($char) {
@@ -197,9 +205,13 @@ class QueryParser implements QueryParserInterface
private function createNode(string $token, string $fieldName, bool $prohibited): Node private function createNode(string $token, string $fieldName, bool $prohibited): Node
{ {
if ('' !== $fieldName) { if ('' !== $fieldName) {
Log::debug(sprintf('Create FieldNode %s:%s (%s)', $fieldName, $token, var_export($prohibited, true))); // OK dus hoe trim je \" correct?
$token = ltrim($token, ':"'); $token = ltrim($token, ':"');
$token = rtrim($token, '"'); if (!str_ends_with($token, '\"')) {
$token = rtrim($token, '"');
}
$token = str_replace('\"', '"', $token);
Log::debug(sprintf('Create FieldNode %s:%s (%s)', $fieldName, $token, var_export($prohibited, true)));
return new FieldNode(trim($fieldName), trim($token), $prohibited); return new FieldNode(trim($fieldName), trim($token), $prohibited);
} }

View File

@@ -627,6 +627,19 @@ class Steam
return $locale; return $locale;
} }
public function anonymous(): bool // get preference
{
$singleton = PreferencesSingleton::getInstance();
$cached = $singleton->getPreference('anonymous');
if (null !== $cached) {
return $cached;
}
$anonymous = app('preferences')->get('anonymous', config('firefly.default_preferences.anonymous', false))->data;
$singleton->setPreference('anonymous', $anonymous);
return $anonymous;
}
public function getLocaleArray(string $locale): array public function getLocaleArray(string $locale): array
{ {
return [ return [

View File

@@ -67,32 +67,16 @@ trait IsOldVersion
protected function isOldVersionInstalled(): bool protected function isOldVersionInstalled(): bool
{ {
// version compare thing. // version compare thing.
$configVersion = (string)config('firefly.version'); $configBuildTime = (int)config('firefly.build_time');
$dbVersion = (string)FireflyConfig::getFresh('ff3_version', '1.0')->data; $dbBuildTime = (int)FireflyConfig::getFresh('ff3_build_time', 123)->data;
$compare = 0; $configTime = Carbon::createFromTimestamp($configBuildTime, config('app.timezone'));
// compare develop to develop $dbTime = Carbon::createFromTimestamp($dbBuildTime, config('app.timezone'));
if (str_starts_with($configVersion, 'develop') && str_starts_with($dbVersion, 'develop')) { if ($dbBuildTime < $configBuildTime) {
$compare = $this->compareDevelopVersions($configVersion, $dbVersion); Log::warning(sprintf('Your database was last managed by an older version of Firefly III (I see %s, I expect %s). Redirect to migrate routine.', $dbTime->format('Y-m-d H:i:s'), $configTime->format('Y-m-d H:i:s')));
}
// user has develop installed, goes to normal version.
if (!str_starts_with($configVersion, 'develop') && str_starts_with($dbVersion, 'develop')) {
return true;
}
// user has normal, goes to develop version.
if (str_starts_with($configVersion, 'develop') && !str_starts_with($dbVersion, 'develop')) {
return true;
}
// compare normal with normal.
if (!str_starts_with($configVersion, 'develop') && !str_starts_with($dbVersion, 'develop')) {
$compare = version_compare($configVersion, $dbVersion);
}
if (-1 === $compare) {
Log::warning(sprintf('The current configured Firefly III version (%s) is older than the required version (%s). Redirect to migrate routine.', $dbVersion, $configVersion));
return true; return true;
} }
Log::debug(sprintf('Your database is up to date (I see %s, I expect %s).', $dbTime->format('Y-m-d H:i:s'), $configTime->format('Y-m-d H:i:s')));
return false; return false;
} }

Some files were not shown because too many files have changed in this diff Show More