Compare commits

..

79 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
184 changed files with 2061 additions and 1220 deletions

View File

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

View File

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

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
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\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
@@ -61,10 +61,9 @@ class BillController extends Controller
* Documentation for this endpoint is at:
* 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($data['query'], $this->parameters->get('limit'));
$result = $this->repository->searchBill($request->attributes->get('query'), $request->attributes->get('limit'));
$filtered = $result->map(
static fn (Bill $item) => [
'id' => (string) $item->id,

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
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\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
@@ -61,10 +61,9 @@ class BudgetController extends Controller
* Documentation for this endpoint is at:
* 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($data['query'], $this->parameters->get('limit'));
$result = $this->repository->searchBudget($request->attributes->get('query'), $request->attributes->get('limit'));
$filtered = $result->map(
static fn (Budget $item) => [
'id' => (string) $item->id,

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
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\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
@@ -61,10 +61,9 @@ class CategoryController extends Controller
* Documentation for this endpoint is at:
* 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($data['query'], $this->parameters->get('limit'));
$result = $this->repository->searchCategory($request->attributes->get('query'), $request->attributes->get('limit'));
$filtered = $result->map(
static fn (Category $item) => [
'id' => (string) $item->id,

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use Deprecated;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\TransactionCurrency;
@@ -62,10 +63,9 @@ class CurrencyController extends Controller
* Documentation for this endpoint is at:
* 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($data['query'], $this->parameters->get('limit'));
$collection = $this->repository->searchCurrency($request->attributes->get('query'), $request->attributes->get('limit'));
$result = [];
/** @var TransactionCurrency $currency */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
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\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
@@ -61,11 +61,10 @@ class ObjectGroupController extends Controller
* Documentation for this endpoint is at:
* 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 = [];
$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 */
foreach ($result as $objectGroup) {

View File

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

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
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\Models\Recurrence;
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($data['query'], $this->parameters->get('limit'));
$recurrences = $this->repository->searchRecurrence($request->attributes->get('query'), $request->attributes->get('limit'));
$response = [];
/** @var Recurrence $recurrence */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
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\Models\Rule;
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($data['query'], $this->parameters->get('limit'));
$rules = $this->repository->searchRule($request->attributes->get('query'), $request->attributes->get('limit'));
$response = [];
/** @var Rule $rule */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
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\Models\RuleGroup;
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($data['query'], $this->parameters->get('limit'));
$groups = $this->repository->searchRuleGroup($request->attributes->get('query'), $request->attributes->get('limit'));
$response = [];
/** @var RuleGroup $group */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
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\Models\Tag;
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($data['query'], $this->parameters->get('limit'));
$result = $this->repository->searchTags($request->attributes->get('query'), $request->attributes->get('limit'));
$array = [];
/** @var Tag $tag */

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
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\Models\TransactionGroup;
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($data['query'], $this->parameters->get('limit'));
$result = $this->repository->searchJournalDescriptions($request->attributes->get('query'), $request->attributes->get('limit'));
// limit and unique
$filtered = $result->unique('description');
@@ -86,13 +85,12 @@ class TransactionController extends Controller
return response()->api($array);
}
public function transactionsWithID(AutocompleteRequest $request): JsonResponse
public function transactionsWithID(AutocompleteApiRequest $request): JsonResponse
{
$data = $request->getData();
$result = new Collection();
if (is_numeric($data['query'])) {
if (is_numeric($request->attributes->get('query'))) {
// 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) {
// group may contain multiple journals, each a result:
foreach ($firstResult->transactionJournals as $journal) {
@@ -100,8 +98,8 @@ class TransactionController extends Controller
}
}
}
if (!is_numeric($data['query'])) {
$result = $this->repository->searchJournalDescriptions($data['query'], $this->parameters->get('limit'));
if (!is_numeric($request->attributes->get('query'))) {
$result = $this->repository->searchJournalDescriptions($request->attributes->get('query'), $request->attributes->get('limit'));
}
// limit and unique

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
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\Models\TransactionType;
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($data['query'], $this->parameters->get('limit'));
$types = $this->repository->searchTypes($request->attributes->get('query'), $request->attributes->get('limit'));
$array = [];
/** @var TransactionType $type */

View File

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

View File

@@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
use Carbon\Carbon;
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\TransactionTypeEnum;
use FireflyIII\Enums\UserRoleEnum;
@@ -80,13 +80,13 @@ class CategoryController extends Controller
*
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function overview(SameDateRequest $request): JsonResponse
public function overview(DateRangeRequest $request): JsonResponse
{
/** @var Carbon $start */
$start = $this->parameters->get('start');
$start = $request->attributes->get('start');
/** @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]);
$currencies = [];
$return = [];

View File

@@ -29,6 +29,7 @@ use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Exceptions\BadHttpHeaderException;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\AbstractTransformer;
@@ -159,7 +160,7 @@ abstract class Controller extends BaseController
/** @var User $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);
}
}

View File

@@ -46,6 +46,7 @@ use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse;
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)),
};
app('preferences')->mark();
Preferences::mark();
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\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse;
/**
@@ -60,7 +61,7 @@ class DestroyController extends Controller
public function destroy(Account $account): JsonResponse
{
$this->repository->destroy($account, null);
app('preferences')->mark();
Preferences::mark();
return response()->json([], 204);
}

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\Account;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\PaginationRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account;
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();
$pageSize = $this->parameters->get('limit');
[
'limit' => $limit,
'offset' => $offset,
'page' => $page,
] = $request->attributes->all();
$collection = $this->repository->getAttachments($account);
$count = $collection->count();
$attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$attachments = $collection->slice($offset, $limit);
// 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());
/** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($attachments, $transformer, 'attachments');
$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);
}
public function piggyBanks(Account $account): JsonResponse
public function piggyBanks(PaginationRequest $request, Account $account): JsonResponse
{
// create some objects:
$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.
$collection = $this->repository->getPiggyBanks($account);
$count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$piggyBanks = $collection->slice(($page - 1) * $limit, $limit);
// enrich
/** @var User $admin */
@@ -113,12 +120,12 @@ class ListController extends Controller
$piggyBanks = $enrichment->enrich($piggyBanks);
// 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());
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters);
// $transformer->setParameters($this->parameters);
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy-banks');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));

View File

@@ -128,23 +128,25 @@ class ShowController extends Controller
// get list of accounts. Count it and split it.
$this->repository->resetAccountOrder();
$account->refresh();
$manager = $this->getManager();
[$start, $end, $date] = $request->attributes->all();
$manager = $this->getManager();
['start' => $start,
'end' => $end,
'date' => $date,] = $request->attributes->all();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setDate($date);
$enrichment->setStart($start);
$enrichment->setEnd($end);
$enrichment->setUser($admin);
$account = $enrichment->enrichSingle($account);
$account = $enrichment->enrichSingle($account);
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
$transformer = app(AccountTransformer::class);
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
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\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\User;
@@ -74,7 +75,7 @@ class UpdateController extends Controller
$account = $this->repository->update($account, $data);
$manager = $this->getManager();
$account->refresh();
app('preferences')->mark();
Preferences::mark();
// enrich
/** @var User $admin */

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Middleware\ApiDemoUser;
use FireflyIII\Models\Attachment;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
@@ -74,7 +75,7 @@ class DestroyController extends Controller
}
$this->repository->destroy($attachment);
app('preferences')->mark();
Preferences::mark();
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\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse;
/**
@@ -61,7 +62,7 @@ class DestroyController extends Controller
public function destroy(Bill $bill): JsonResponse
{
$this->repository->destroy($bill);
app('preferences')->mark();
Preferences::mark();
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\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse;
/**
@@ -61,7 +62,7 @@ class DestroyController extends Controller
public function destroy(Budget $budget): JsonResponse
{
$this->repository->destroy($budget);
app('preferences')->mark();
Preferences::mark();
return response()->json([], 204);
}

View File

@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
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.');
}
$this->blRepository->destroyBudgetLimit($budgetLimit);
app('preferences')->mark();
Preferences::mark();
return response()->json([], 204);
}

View File

@@ -172,7 +172,6 @@ class ShowController extends Controller
/** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters);
$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\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse;
/**
@@ -61,7 +62,7 @@ class DestroyController extends Controller
public function destroy(Category $category): JsonResponse
{
$this->repository->destroy($category);
app('preferences')->mark();
Preferences::mark();
return response()->json([], 204);
}

View File

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

View File

@@ -82,7 +82,6 @@ class UpdateController extends Controller
$exchangeRate = $this->repository->updateExchangeRate($exchangeRate, $rate, $date);
$transformer = new ExchangeRateTransformer();
$transformer->setParameters($this->parameters);
return response()
->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\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@@ -64,7 +65,7 @@ class DestroyController extends Controller
public function destroy(ObjectGroup $objectGroup): JsonResponse
{
$this->repository->destroy($objectGroup);
app('preferences')->mark();
Preferences::mark();
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\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse;
/**
@@ -61,7 +62,7 @@ class DestroyController extends Controller
public function destroy(PiggyBank $piggyBank): JsonResponse
{
$this->repository->destroy($piggyBank);
app('preferences')->mark();
Preferences::mark();
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\Models\Recurrence;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse;
/**
@@ -61,7 +62,7 @@ class DestroyController extends Controller
public function destroy(Recurrence $recurrence): JsonResponse
{
$this->repository->destroy($recurrence);
app('preferences')->mark();
Preferences::mark();
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\Models\Rule;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@@ -65,7 +66,7 @@ class DestroyController extends Controller
public function destroy(Rule $rule): JsonResponse
{
$this->ruleRepository->destroy($rule);
app('preferences')->mark();
Preferences::mark();
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\Models\RuleGroup;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@@ -65,7 +66,7 @@ class DestroyController extends Controller
public function destroy(RuleGroup $ruleGroup): JsonResponse
{
$this->ruleGroupRepository->destroy($ruleGroup, null);
app('preferences')->mark();
Preferences::mark();
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\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@@ -65,7 +66,7 @@ class DestroyController extends Controller
public function destroy(Tag $tag): JsonResponse
{
$this->repository->destroy($tag);
app('preferences')->mark();
Preferences::mark();
return response()->json([], 204);
}

View File

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

View File

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

View File

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

View File

@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Validator;
@@ -89,7 +90,7 @@ class DestroyController extends Controller
}
$this->repository->destroy($currency);
app('preferences')->mark();
Preferences::mark();
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\Requests\Models\TransactionCurrency\StoreRequest;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\CurrencyTransformer;
@@ -71,7 +72,7 @@ class StoreController extends Controller
$currency = $this->repository->store($request->getAll());
if (true === $request->boolean('default')) {
$this->repository->makePrimary($currency);
app('preferences')->mark();
Preferences::mark();
}
$manager = $this->getManager();

View File

@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\UpdateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\CurrencyTransformer;
@@ -105,7 +106,7 @@ class UpdateController extends Controller
$this->repository->enable($currency);
$this->repository->makePrimary($currency);
app('preferences')->mark();
Preferences::mark();
$manager = $this->getManager();
$currency->refreshForUser($user);
@@ -172,14 +173,13 @@ class UpdateController extends Controller
$currency = $this->repository->update($currency, $data);
app('preferences')->mark();
Preferences::mark();
$manager = $this->getManager();
$currency->refreshForUser($user);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);
$transformer->setParameters($this->parameters);
$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\Models\TransactionJournalLink;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@@ -66,7 +67,7 @@ class DestroyController extends Controller
public function destroy(TransactionJournalLink $link): JsonResponse
{
$this->repository->destroyLink($link);
app('preferences')->mark();
Preferences::mark();
return response()->json([], 204);
}

View File

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

View File

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

View File

@@ -27,7 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Summary;
use Carbon\Carbon;
use Exception;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\DateRangeRequest;
use FireflyIII\Api\V1\Requests\Summary\BasicRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
@@ -88,34 +88,25 @@ class BasicController extends Controller
);
}
/**
* 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(DateRangeRequest $request): JsonResponse
public function basic(BasicRequest $request): JsonResponse
{
// parameters for boxes:
$dates = $request->attributes->all();
$start = $dates['start'];
$end = $dates['end'];
$code = $request->get('currency_code');
['start' => $start, 'end' => $end, 'code' => $code] = $request->attributes->all();
// balance information:
$balanceData = $this->getBalanceInformation($start, $end);
$billData = $this->getSubscriptionInformation($start, $end);
$spentData = $this->getLeftToSpendInfo($start, $end);
$netWorthData = $this->getNetWorthInfo($end);
$balanceData = $this->getBalanceInformation($start, $end);
$billData = $this->getSubscriptionInformation($start, $end);
$spentData = $this->getLeftToSpendInfo($start, $end);
$netWorthData = $this->getNetWorthInfo($end);
// $balanceData = [];
// $billData = [];
// $spentData = [];
// $netWorthData = [];
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
// give new keys
$return = [];
$return = [];
foreach ($total as $entry) {
if (null === $code || ($code === $entry['currency_code'])) {
if ('' === $code || ($code === $entry['currency_code'])) {
$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\Exceptions\FireflyException;
use FireflyIII\Models\Preference;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Transformers\PreferenceTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
@@ -52,7 +53,7 @@ class PreferencesController extends Controller
*/
public function index(): JsonResponse
{
$collection = app('preferences')->all();
$collection = Preferences::all();
$manager = $this->getManager();
$count = $collection->count();
$pageSize = $this->parameters->get('limit');
@@ -110,7 +111,7 @@ class PreferencesController extends Controller
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 */
$transformer = app(PreferenceTransformer::class);
@@ -135,7 +136,7 @@ class PreferencesController extends Controller
$manager = $this->getManager();
$data = $request->getAll();
$pref = app('preferences')->set($preference->name, $data['data']);
$pref = Preferences::set($preference->name, $data['data']);
/** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class);

View File

@@ -30,6 +30,7 @@ use FireflyIII\Models\Webhook;
use FireflyIII\Models\WebhookAttempt;
use FireflyIII\Models\WebhookMessage;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
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));
$this->repository->destroy($webhook);
app('preferences')->mark();
Preferences::mark();
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));
$this->repository->destroyAttempt($attempt);
app('preferences')->mark();
Preferences::mark();
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));
$this->repository->destroyMessage($message);
app('preferences')->mark();
Preferences::mark();
return response()->json([], 204);
}

View File

@@ -25,6 +25,7 @@ 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;
@@ -43,12 +44,14 @@ abstract class AggregateFormRequest extends ApiRequest
parent::initialize($query, $request, $attributes, $cookies, $files, $server, $content);
// instantiate all subrequests and share current requests' bags with them
Log::debug('Initializing AggregateFormRequest.');
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;
@@ -63,6 +66,7 @@ abstract class AggregateFormRequest extends ApiRequest
$instance->handleConfig(is_array($config) ? $config : []);
}
}
Log::debug('Done initializing AggregateFormRequest.');
}
public function rules(): array
@@ -85,6 +89,7 @@ abstract class AggregateFormRequest extends ApiRequest
// register all subrequests' validators
foreach ($this->requests as $request) {
if (method_exists($request, 'withValidator')) {
Log::debug(sprintf('Process withValidator from class %s', get_class($request)));
$request->withValidator($validator);
}
}

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
*
* @deprecated
*/
class AutocompleteRequest extends FormRequest
{

View File

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

View File

@@ -30,8 +30,8 @@ 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|', $this->required),
'end' => sprintf('date|after:1970-01-02|before:2038-01-17|after:start|required_with:start|', $this->required),
'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),
];
}
@@ -39,7 +39,11 @@ class DateRangeRequest extends ApiRequest
{
$validator->after(
function (Validator $validator): void {
if (!$validator->valid()) {
if ($validator->failed()) {
// set null values
$this->attributes->set('start', null);
$this->attributes->set('end', null);
return;
}
$start = $this->getCarbonDate('start')?->startOfDay();

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon;
use Illuminate\Validation\Validator;
class DateRequest extends ApiRequest
@@ -38,7 +39,7 @@ class DateRequest extends ApiRequest
{
$validator->after(
function (Validator $validator): void {
if (!$validator->valid()) {
if ($validator->failed()) {
return;
}
$date = $this->getCarbonDate('date')?->endOfDay();
@@ -46,7 +47,7 @@ class DateRequest extends ApiRequest
// if we also have a range, date must be in that range
$start = $this->attributes->get('start');
$end = $this->attributes->get('end');
if ($date && $start && $end && !$date->between($start, $end)) {
if ($date instanceof Carbon && $start instanceof Carbon && $end instanceof Carbon && !$date->between($start, $end)) {
$validator->errors()->add('date', (string)trans('validation.between_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.
*
* Class SingleDateRequest
*
* @deprecated
*/
class SingleDateRequest extends FormRequest
{

View File

@@ -42,7 +42,7 @@ class AccountTypeApiRequest extends ApiRequest
{
$validator->after(
function (Validator $validator): void {
if (!$validator->valid()) {
if ($validator->failed()) {
return;
}

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

@@ -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

@@ -47,7 +47,7 @@ class PaginationRequest extends ApiRequest
public function rules(): array
{
return [
'sort' => ['nullable', new IsValidSortInstruction($this->sortClass)],
'sort' => ['nullable', new IsValidSortInstruction((string)$this->sortClass)],
'limit' => 'numeric|min:1|max:131337',
'page' => 'numeric|min:1|max:131337',
];
@@ -57,7 +57,7 @@ class PaginationRequest extends ApiRequest
{
$validator->after(
function (Validator $validator): void {
if (!$validator->valid()) {
if ($validator->failed()) {
return;
}

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\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Console\Command;
@@ -47,7 +48,7 @@ class CorrectsFrontpageAccounts extends Command
/** @var User $user */
foreach ($users as $user) {
$preference = app('preferences')->getForUser($user, 'frontpageAccounts');
$preference = Preferences::getForUser($user, 'frontpageAccounts');
if (null !== $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 FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Console\Command;
@@ -54,10 +55,10 @@ class CreatesAccessTokens extends Command
/** @var User $user */
foreach ($users as $user) {
$pref = app('preferences')->getForUser($user, 'access_token');
$pref = Preferences::getForUser($user, 'access_token');
if (null === $pref) {
$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));
++$count;
}

View File

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

View File

@@ -33,6 +33,7 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Console\Command;
@@ -114,7 +115,7 @@ class UpgradesBillsToRules extends Command
$this->ruleRepository->setUser($user);
/** @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';
$groupTitle = (string) trans('firefly.rulegroup_for_bills_title', [], $language);
$ruleGroup = $this->ruleGroupRepository->findByTitle($groupTitle);

View File

@@ -87,7 +87,7 @@ class UpgradesDatabase extends Command
$this->call($command, $args);
}
// 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;
}

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Console\Commands;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Support\Facades\Log;
@@ -79,7 +80,7 @@ trait VerifiesAccessToken
return false;
}
$accessToken = app('preferences')->getForUser($user, 'access_token');
$accessToken = Preferences::getForUser($user, 'access_token');
if (null === $accessToken) {
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;
}
public function setUser(User $user): void
public function setUser(User $user): static
{
$this->user = $user;
return $this;
}
}

View File

@@ -221,10 +221,26 @@ class TransactionJournalFactory
];
Log::debug('Source info:', $sourceInfo);
Log::debug('Destination info:', $destInfo);
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo);
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo, $sourceAccount);
$destinationAccount = null;
$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)');
// 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).
if (TransactionTypeEnum::RECONCILIATION->value === $type->type) {

View File

@@ -30,6 +30,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Notifications\User\TransactionCreation;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Transformers\TransactionGroupTransformer;
use Illuminate\Support\Facades\Notification;
@@ -52,7 +53,7 @@ class AutomationHandler
$user = $repository->find($event->userId);
/** @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) {
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\RuleActionFailedOnObject;
use FireflyIII\Notifications\User\RuleActionFailed;
use FireflyIII\Support\Facades\Preferences;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
@@ -42,7 +43,7 @@ class RuleHandler
$rule = $ruleAction->rule;
/** @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) {
return;
}
@@ -71,7 +72,7 @@ class RuleHandler
$rule = $ruleAction->rule;
/** @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) {
return;
}

View File

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

View File

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

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Helpers\Fiscal;
use Carbon\Carbon;
use FireflyIII\Support\Facades\Preferences;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
@@ -40,7 +41,7 @@ class FiscalHelper implements FiscalHelperInterface
*/
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.
$startDate = clone $date;
if (true === $this->useCustomFiscalYear) {
$prefStartStr = app('preferences')->get('fiscalYearStart', '01-01')->data;
$prefStartStr = Preferences::get('fiscalYearStart', '01-01')->data;
if (is_array($prefStartStr)) {
$prefStartStr = '01-01';
}

View File

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

View File

@@ -108,11 +108,10 @@ class EditController extends Controller
];
// interest calculation periods:
$interestPeriods = [
'daily' => (string) trans('firefly.interest_calc_daily'),
'monthly' => (string) trans('firefly.interest_calc_monthly'),
'yearly' => (string) trans('firefly.interest_calc_yearly'),
];
$interestPeriods = [];
foreach (config('firefly.interest_periods') as $period) {
$interestPeriods[$period] = trans(sprintf('firefly.interest_calc_%s', $period));
}
// put previous url in session if not redirect from store (not "return_to_edit").
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_PASSWORD', config('firefly.demo_password'));
View::share('FF_VERSION', config('firefly.version'));
View::share('FF_BUILD_TIME', config('firefly.build_time'));
// is webhooks enabled?
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;
// get shown-intro-preference:
if (auth()->check()) {
View::share('anonymous', Steam::anonymous());
$this->primaryCurrency = Amount::getPrimaryCurrency();
$language = Steam::getLanguage();
$locale = Steam::getLocale();

View File

@@ -81,11 +81,11 @@ class DebugController extends Controller
*/
public function displayError(): void
{
app('log')->debug('This is a test message at the DEBUG level.');
app('log')->info('This is a test message at the INFO level.');
Log::debug('This is a test message at the DEBUG level.');
Log::info('This is a test message at the INFO level.');
Log::notice('This is a test message at the NOTICE level.');
app('log')->warning('This is a test message at the WARNING level.');
app('log')->error('This is a test message at the ERROR level.');
Log::warning('This is a test message at the WARNING level.');
Log::error('This is a test message at the ERROR level.');
Log::critical('This is a test message at the CRITICAL level.');
Log::alert('This is a test message at the ALERT level.');
Log::emergency('This is a test message at the EMERGENCY level.');
@@ -187,6 +187,8 @@ class DebugController extends Controller
return [
'php_version' => PHP_VERSION,
'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'),
'interface' => PHP_SAPI,
'bits' => PHP_INT_SIZE * 8,
@@ -212,11 +214,11 @@ class DebugController extends Controller
try {
if (file_exists('/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) {
app('log')->debug('Could not check build counter, but thats ok.');
app('log')->warning($e->getMessage());
Log::debug('Could not check build counter, but thats ok.');
Log::warning($e->getMessage());
}
try {
@@ -224,8 +226,8 @@ class DebugController extends Controller
$return['build_date'] = trim(file_get_contents('/var/www/build-date-main.txt'));
}
} catch (Exception $e) {
app('log')->debug('Could not check build date, but thats ok.');
app('log')->warning($e->getMessage());
Log::debug('Could not check build date, but thats ok.');
Log::warning($e->getMessage());
}
if ('' !== (string) 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());
foreach ($parts as $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);
$localeAttempts[$code] = $result === $code;
}

View File

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

View File

@@ -268,7 +268,6 @@ class CreateController extends Controller
public function store(RuleFormRequest $request)
{
$data = $request->getRuleData();
$rule = $this->ruleRepos->store($data);
session()->flash('success_url', route('rules.select-transactions', [$rule->id]));
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) {
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'));

View File

@@ -205,6 +205,11 @@ class EditController extends Controller
session()->flash('success', (string) trans('firefly.updated_rule', ['title' => $rule->title]));
app('preferences')->mark();
$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')) {
session()->put('rules.edit.fromUpdate', true);

View File

@@ -34,6 +34,7 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
use Laravel\Passport\Passport;
use phpseclib3\Crypt\RSA;
@@ -81,8 +82,10 @@ class InstallController extends Controller
public function index()
{
app('view')->share('FF_VERSION', config('firefly.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 view('install.index');
}
@@ -98,18 +101,18 @@ class InstallController extends Controller
'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);
if (array_key_exists($requestIndex, $indexes)) {
$command = $indexes[$requestIndex];
$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 {
$result = $this->executeCommand($command, $parameters);
} catch (FireflyException $e) {
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
if (str_contains($e->getMessage(), 'open_basedir restriction in effect')) {
$this->lastError = self::BASEDIR_ERROR;
}
@@ -134,7 +137,7 @@ class InstallController extends Controller
*/
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 {
if ('generate-keys' === $command) {
@@ -142,7 +145,7 @@ class InstallController extends Controller
}
if ('generate-keys' !== $command) {
Artisan::call($command, $args);
app('log')->debug(Artisan::output());
Log::debug(Artisan::output());
}
} catch (Exception $e) { // intentional generic exception
throw new FireflyException($e->getMessage(), 0, $e);

View File

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

View File

@@ -31,6 +31,8 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Safe\Exceptions\FilesystemException;
use Safe\Exceptions\JsonException;
use Symfony\Component\Mailer\Exception\TransportException;
use function Safe\file_get_contents;
@@ -54,7 +56,7 @@ class MailError extends Job implements ShouldQueue
$debug = $this->exception;
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) {
$message = $e->getMessage();
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;
}
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;
}
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
}
}
@@ -125,11 +127,25 @@ class MailError extends Job implements ShouldQueue
if (!file_exists($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)) {
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?
foreach ($types as $type => $info) {
@@ -157,7 +173,14 @@ class MailError extends Job implements ShouldQueue
}
++$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.');
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;
}
if ('' === $value) {
// don't validate.
return;
}
$validParameters = config(sprintf('firefly.allowed_sort_parameters.%s', $shortClass));
if (!is_array($validParameters)) {
$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
$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.
// that data can be used to create a new account of the right type.
@@ -227,9 +228,11 @@ trait JournalServiceTrait
}
// find by preferred type.
Log::debug('Find by preferred type.');
$result = $this->accountRepository->findByName($data['name'], [$types[0]]);
// or any expected type.
Log::debug('Find by any expected type.');
$result ??= $this->accountRepository->findByName($data['name'], $types);
if (null !== $result) {

View File

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

View File

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

View File

@@ -154,6 +154,9 @@ class BudgetLimitEnrichment implements EnrichmentInterface
$this->start = $this->collection->min('start_date') ?? Carbon::now()->startOfMonth();
$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 */
foreach ($this->collection as $limit) {
$id = (int)$limit->id;

View File

@@ -88,7 +88,7 @@ trait UserGroupTrait
public function setUserGroup(UserGroup $userGroup): void
{
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;
}

View File

@@ -52,13 +52,23 @@ class QueryParser implements QueryParserInterface
$inQuotes = false;
$fieldName = '';
$prohibited = false;
while ($this->position < strlen($this->query)) {
$char = $this->query[$this->position];
$chrArray = preg_split('//u', $this->query, -1, PREG_SPLIT_NO_EMPTY);
$count = count($chrArray);
while ($this->position < $count) {
$char = $chrArray[$this->position];
$nextChar = $chrArray[$this->position + 1] ?? '';
// 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 ($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) {
$tokenUnderConstruction .= $char;
++$this->position;
@@ -67,11 +77,9 @@ class QueryParser implements QueryParserInterface
}
// char is "
++$this->position;
Log::debug(sprintf('Constructed token: %s', $tokenUnderConstruction));
return new NodeResult(
$this->createNode($tokenUnderConstruction, $fieldName, $prohibited),
false
);
return new NodeResult($this->createNode($tokenUnderConstruction, $fieldName, $prohibited), false);
}
switch ($char) {
@@ -197,9 +205,13 @@ class QueryParser implements QueryParserInterface
private function createNode(string $token, string $fieldName, bool $prohibited): Node
{
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 = 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);
}

View File

@@ -627,6 +627,19 @@ class Steam
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
{
return [

View File

@@ -67,32 +67,16 @@ trait IsOldVersion
protected function isOldVersionInstalled(): bool
{
// version compare thing.
$configVersion = (string)config('firefly.version');
$dbVersion = (string)FireflyConfig::getFresh('ff3_version', '1.0')->data;
$compare = 0;
// compare develop to develop
if (str_starts_with($configVersion, 'develop') && str_starts_with($dbVersion, 'develop')) {
$compare = $this->compareDevelopVersions($configVersion, $dbVersion);
}
// 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));
$configBuildTime = (int)config('firefly.build_time');
$dbBuildTime = (int)FireflyConfig::getFresh('ff3_build_time', 123)->data;
$configTime = Carbon::createFromTimestamp($configBuildTime, config('app.timezone'));
$dbTime = Carbon::createFromTimestamp($dbBuildTime, config('app.timezone'));
if ($dbBuildTime < $configBuildTime) {
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')));
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;
}

View File

@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## 6.4.3 - 2025-11-01
### Added
- [PR 11019](https://github.com/firefly-iii/firefly-iii/pull/11019) (fix #11015 set end date time to end of day) reported by @ctrl-f5
- [PR 11024](https://github.com/firefly-iii/firefly-iii/pull/11024) (improved balance range date handling) reported by @ctrl-f5
- [PR 11028](https://github.com/firefly-iii/firefly-iii/pull/11028) (Adding Latin American Currency Support) reported by @codearena-bot
- [PR 11039](https://github.com/firefly-iii/firefly-iii/pull/11039) (proposal for improved request handling) reported by @ctrl-f5
- [PR 11041](https://github.com/firefly-iii/firefly-iii/pull/11041) (Add XML mimetypes to the allowedMimes list) reported by @jreyesr
- [PR 10993](https://github.com/firefly-iii/firefly-iii/pull/10993) (use correct translation key for category report income table) reported by @ctrl-f5
- [PR 11056](https://github.com/firefly-iii/firefly-iii/pull/11056) (account/attachments endpoint use request object for pagination, add test) reported by @ctrl-f5
- [PR 11052](https://github.com/firefly-iii/firefly-iii/pull/11052) (correct validator function to check for errors + `Account\ShowControllerTest`) reported by @ctrl-f5
- [Issue 11102](https://github.com/firefly-iii/firefly-iii/issues/11102) (Allow to redact account totals in web ui) reported by @edvgui
- [Issue 11109](https://github.com/firefly-iii/firefly-iii/issues/11109) (Could not find a transaction currency with code "Korean Won"/"Russian ruble") reported by @mattephi
- [Issue 11132](https://github.com/firefly-iii/firefly-iii/issues/11132) (Add a 6 month interest period) reported by @CiramorDev
### Fixed
- [Issue 11031](https://github.com/firefly-iii/firefly-iii/issues/11031) (Rule with trigger "When a transaction is created" being triggered on transaction updates) reported by @pvieira84
- [Issue 11038](https://github.com/firefly-iii/firefly-iii/issues/11038) (Missing date formats when using "MTD" on the frontpage) reported by @cristiangrossano
- [Issue 11042](https://github.com/firefly-iii/firefly-iii/issues/11042) (Option to apply rules on a specific date range has disappeared from the UI) reported by @angelbarrera92
- [Issue 11050](https://github.com/firefly-iii/firefly-iii/issues/11050) (Dev Version: `/api/v1/accounts/get/$id` requires (optional) `start` parameter, throws error otherwise) reported by @dreautall
- [Issue 11054](https://github.com/firefly-iii/firefly-iii/issues/11054) (Autocreation of revenue account when depositing to liability) reported by @Mr-Kanister
- [Issue 11096](https://github.com/firefly-iii/firefly-iii/issues/11096) (Budget Limit API ignores transactions on the last day of the month) reported by @edbingo
- [Issue 11063](https://github.com/firefly-iii/firefly-iii/issues/11063) ("bcadd: argument must be of type string, int given" when viewing categories or tags) reported by @df911
- [Discussion 11104](https://github.com/orgs/firefly-iii/discussions/11104) (Personal Access Token failing on 6.4.2 for data-importer) started by @marcoblancas
- [Discussion 11122](https://github.com/orgs/firefly-iii/discussions/11122) (Convenient Rules Creation) started by @viewmatic2025
- [Issue 11134](https://github.com/firefly-iii/firefly-iii/issues/11134) (Rules are not applied if description in quotes) reported by @beatbesmer
### Security
- Debug route is now behind 2FA
## 6.4.2 - 2055-10-07

311
composer.lock generated
View File

@@ -1878,16 +1878,16 @@
},
{
"name": "laravel/framework",
"version": "v12.33.0",
"version": "v12.36.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "124efc5f09d4668a4dc13f94a1018c524a58bcb1"
"reference": "cad110d7685fbab990a6bb8184d0cfd847d7c4d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/124efc5f09d4668a4dc13f94a1018c524a58bcb1",
"reference": "124efc5f09d4668a4dc13f94a1018c524a58bcb1",
"url": "https://api.github.com/repos/laravel/framework/zipball/cad110d7685fbab990a6bb8184d0cfd847d7c4d8",
"reference": "cad110d7685fbab990a6bb8184d0cfd847d7c4d8",
"shasum": ""
},
"require": {
@@ -1999,7 +1999,7 @@
"league/flysystem-sftp-v3": "^3.25.1",
"mockery/mockery": "^1.6.10",
"opis/json-schema": "^2.4.1",
"orchestra/testbench-core": "^10.6.5",
"orchestra/testbench-core": "^10.7.0",
"pda/pheanstalk": "^5.0.6|^7.0.0",
"php-http/discovery": "^1.15",
"phpstan/phpstan": "^2.0",
@@ -2093,7 +2093,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2025-10-07T14:30:39+00:00"
"time": "2025-10-29T14:20:57+00:00"
},
{
"name": "laravel/passport",
@@ -2296,16 +2296,16 @@
},
{
"name": "laravel/serializable-closure",
"version": "v2.0.5",
"version": "v2.0.6",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
"reference": "3832547db6e0e2f8bb03d4093857b378c66eceed"
"reference": "038ce42edee619599a1debb7e81d7b3759492819"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3832547db6e0e2f8bb03d4093857b378c66eceed",
"reference": "3832547db6e0e2f8bb03d4093857b378c66eceed",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/038ce42edee619599a1debb7e81d7b3759492819",
"reference": "038ce42edee619599a1debb7e81d7b3759492819",
"shasum": ""
},
"require": {
@@ -2353,7 +2353,7 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
"time": "2025-09-22T17:29:40+00:00"
"time": "2025-10-09T13:42:30+00:00"
},
{
"name": "laravel/slack-notification-channel",
@@ -2485,20 +2485,20 @@
},
{
"name": "lcobucci/clock",
"version": "3.4.0",
"version": "3.5.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/clock.git",
"reference": "f91d84f65cb3e974988bbe872b5da8ca132a155f"
"reference": "a3139d9e97d47826f27e6a17bb63f13621f86058"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/clock/zipball/f91d84f65cb3e974988bbe872b5da8ca132a155f",
"reference": "f91d84f65cb3e974988bbe872b5da8ca132a155f",
"url": "https://api.github.com/repos/lcobucci/clock/zipball/a3139d9e97d47826f27e6a17bb63f13621f86058",
"reference": "a3139d9e97d47826f27e6a17bb63f13621f86058",
"shasum": ""
},
"require": {
"php": "~8.3.0 || ~8.4.0",
"php": "~8.3.0 || ~8.4.0 || ~8.5.0",
"psr/clock": "^1.0"
},
"provide": {
@@ -2506,7 +2506,7 @@
},
"require-dev": {
"infection/infection": "^0.31",
"lcobucci/coding-standard": "^11.1.0",
"lcobucci/coding-standard": "^11.2.0",
"phpstan/extension-installer": "^1.3.1",
"phpstan/phpstan": "^2.0.0",
"phpstan/phpstan-deprecation-rules": "^2.0.0",
@@ -2533,7 +2533,7 @@
"description": "Yet another clock abstraction",
"support": {
"issues": "https://github.com/lcobucci/clock/issues",
"source": "https://github.com/lcobucci/clock/tree/3.4.0"
"source": "https://github.com/lcobucci/clock/tree/3.5.0"
},
"funding": [
{
@@ -2545,26 +2545,26 @@
"type": "patreon"
}
],
"time": "2025-10-08T18:00:48+00:00"
"time": "2025-10-27T09:03:17+00:00"
},
{
"name": "lcobucci/jwt",
"version": "5.5.0",
"version": "5.6.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "a835af59b030d3f2967725697cf88300f579088e"
"reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/a835af59b030d3f2967725697cf88300f579088e",
"reference": "a835af59b030d3f2967725697cf88300f579088e",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/bb3e9f21e4196e8afc41def81ef649c164bca25e",
"reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e",
"shasum": ""
},
"require": {
"ext-openssl": "*",
"ext-sodium": "*",
"php": "~8.2.0 || ~8.3.0 || ~8.4.0",
"php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
"psr/clock": "^1.0"
},
"require-dev": {
@@ -2606,7 +2606,7 @@
],
"support": {
"issues": "https://github.com/lcobucci/jwt/issues",
"source": "https://github.com/lcobucci/jwt/tree/5.5.0"
"source": "https://github.com/lcobucci/jwt/tree/5.6.0"
},
"funding": [
{
@@ -2618,7 +2618,7 @@
"type": "patreon"
}
],
"time": "2025-01-26T21:29:45+00:00"
"time": "2025-10-17T11:30:53+00:00"
},
{
"name": "league/commonmark",
@@ -2811,16 +2811,16 @@
},
{
"name": "league/csv",
"version": "9.26.0",
"version": "9.27.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/csv.git",
"reference": "7fce732754d043f3938899e5183e2d0f3d31b571"
"reference": "26de738b8fccf785397d05ee2fc07b6cd8749797"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/7fce732754d043f3938899e5183e2d0f3d31b571",
"reference": "7fce732754d043f3938899e5183e2d0f3d31b571",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/26de738b8fccf785397d05ee2fc07b6cd8749797",
"reference": "26de738b8fccf785397d05ee2fc07b6cd8749797",
"shasum": ""
},
"require": {
@@ -2898,7 +2898,7 @@
"type": "github"
}
],
"time": "2025-10-01T11:24:54+00:00"
"time": "2025-10-25T08:35:20+00:00"
},
{
"name": "league/event",
@@ -2956,16 +2956,16 @@
},
{
"name": "league/flysystem",
"version": "3.30.0",
"version": "3.30.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "2203e3151755d874bb2943649dae1eb8533ac93e"
"reference": "c139fd65c1f796b926f4aec0df37f6caa959a8da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e",
"reference": "2203e3151755d874bb2943649dae1eb8533ac93e",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/c139fd65c1f796b926f4aec0df37f6caa959a8da",
"reference": "c139fd65c1f796b926f4aec0df37f6caa959a8da",
"shasum": ""
},
"require": {
@@ -3033,9 +3033,9 @@
],
"support": {
"issues": "https://github.com/thephpleague/flysystem/issues",
"source": "https://github.com/thephpleague/flysystem/tree/3.30.0"
"source": "https://github.com/thephpleague/flysystem/tree/3.30.1"
},
"time": "2025-06-25T13:29:59+00:00"
"time": "2025-10-20T15:35:26+00:00"
},
{
"name": "league/flysystem-local",
@@ -3476,22 +3476,22 @@
},
{
"name": "mailersend/laravel-driver",
"version": "v2.11.0",
"version": "v2.12.0",
"source": {
"type": "git",
"url": "https://github.com/mailersend/mailersend-laravel-driver.git",
"reference": "63acebb5064745076df27b1a80423986b6d7b69e"
"reference": "15e1ec41e29e65d3ca226929c65804190aaa93eb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/63acebb5064745076df27b1a80423986b6d7b69e",
"reference": "63acebb5064745076df27b1a80423986b6d7b69e",
"url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/15e1ec41e29e65d3ca226929c65804190aaa93eb",
"reference": "15e1ec41e29e65d3ca226929c65804190aaa93eb",
"shasum": ""
},
"require": {
"ext-json": "*",
"illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0",
"mailersend/mailersend": "^0.34.0",
"mailersend/mailersend": "^0.35.0",
"nyholm/psr7": "^1.5",
"php": ">=8.0",
"php-http/guzzle7-adapter": "^1.0",
@@ -3539,22 +3539,22 @@
],
"support": {
"issues": "https://github.com/mailersend/mailersend-laravel-driver/issues",
"source": "https://github.com/mailersend/mailersend-laravel-driver/tree/v2.11.0"
"source": "https://github.com/mailersend/mailersend-laravel-driver/tree/v2.12.0"
},
"time": "2025-06-04T08:47:41+00:00"
"time": "2025-10-28T14:59:16+00:00"
},
{
"name": "mailersend/mailersend",
"version": "v0.34.0",
"version": "v0.35.0",
"source": {
"type": "git",
"url": "https://github.com/mailersend/mailersend-php.git",
"reference": "1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab"
"reference": "f1696cf9e727e9503fbc5882d2a111bd966ad276"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab",
"reference": "1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab",
"url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/f1696cf9e727e9503fbc5882d2a111bd966ad276",
"reference": "f1696cf9e727e9503fbc5882d2a111bd966ad276",
"shasum": ""
},
"require": {
@@ -3605,9 +3605,9 @@
],
"support": {
"issues": "https://github.com/mailersend/mailersend-php/issues",
"source": "https://github.com/mailersend/mailersend-php/tree/v0.34.0"
"source": "https://github.com/mailersend/mailersend-php/tree/v0.35.0"
},
"time": "2025-06-04T07:53:52+00:00"
"time": "2025-10-28T13:11:43+00:00"
},
{
"name": "monolog/monolog",
@@ -3819,25 +3819,25 @@
},
{
"name": "nette/schema",
"version": "v1.3.2",
"version": "v1.3.3",
"source": {
"type": "git",
"url": "https://github.com/nette/schema.git",
"reference": "da801d52f0354f70a638673c4a0f04e16529431d"
"reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d",
"reference": "da801d52f0354f70a638673c4a0f04e16529431d",
"url": "https://api.github.com/repos/nette/schema/zipball/2befc2f42d7c715fd9d95efc31b1081e5d765004",
"reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004",
"shasum": ""
},
"require": {
"nette/utils": "^4.0",
"php": "8.1 - 8.4"
"php": "8.1 - 8.5"
},
"require-dev": {
"nette/tester": "^2.5.2",
"phpstan/phpstan-nette": "^1.0",
"phpstan/phpstan-nette": "^2.0@stable",
"tracy/tracy": "^2.8"
},
"type": "library",
@@ -3847,6 +3847,9 @@
}
},
"autoload": {
"psr-4": {
"Nette\\": "src"
},
"classmap": [
"src/"
]
@@ -3875,9 +3878,9 @@
],
"support": {
"issues": "https://github.com/nette/schema/issues",
"source": "https://github.com/nette/schema/tree/v1.3.2"
"source": "https://github.com/nette/schema/tree/v1.3.3"
},
"time": "2024-10-06T23:10:23+00:00"
"time": "2025-10-30T22:57:59+00:00"
},
{
"name": "nette/utils",
@@ -4069,31 +4072,31 @@
},
{
"name": "nunomaduro/termwind",
"version": "v2.3.1",
"version": "v2.3.2",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/termwind.git",
"reference": "dfa08f390e509967a15c22493dc0bac5733d9123"
"reference": "eb61920a53057a7debd718a5b89c2178032b52c0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123",
"reference": "dfa08f390e509967a15c22493dc0bac5733d9123",
"url": "https://api.github.com/repos/nunomaduro/termwind/zipball/eb61920a53057a7debd718a5b89c2178032b52c0",
"reference": "eb61920a53057a7debd718a5b89c2178032b52c0",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": "^8.2",
"symfony/console": "^7.2.6"
"symfony/console": "^7.3.4"
},
"require-dev": {
"illuminate/console": "^11.44.7",
"laravel/pint": "^1.22.0",
"illuminate/console": "^11.46.1",
"laravel/pint": "^1.25.1",
"mockery/mockery": "^1.6.12",
"pestphp/pest": "^2.36.0 || ^3.8.2",
"phpstan/phpstan": "^1.12.25",
"pestphp/pest": "^2.36.0 || ^3.8.4",
"phpstan/phpstan": "^1.12.32",
"phpstan/phpstan-strict-rules": "^1.6.2",
"symfony/var-dumper": "^7.2.6",
"symfony/var-dumper": "^7.3.4",
"thecodingmachine/phpstan-strict-rules": "^1.0.0"
},
"type": "library",
@@ -4136,7 +4139,7 @@
],
"support": {
"issues": "https://github.com/nunomaduro/termwind/issues",
"source": "https://github.com/nunomaduro/termwind/tree/v2.3.1"
"source": "https://github.com/nunomaduro/termwind/tree/v2.3.2"
},
"funding": [
{
@@ -4152,7 +4155,7 @@
"type": "github"
}
],
"time": "2025-05-08T08:14:37+00:00"
"time": "2025-10-18T11:10:27+00:00"
},
{
"name": "nyholm/psr7",
@@ -6416,16 +6419,16 @@
},
{
"name": "symfony/cache",
"version": "v7.3.4",
"version": "v7.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache.git",
"reference": "bf8afc8ffd4bfd3d9c373e417f041d9f1e5b863f"
"reference": "4a55feb59664f49042a0824c0f955e2f4c1412ad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/cache/zipball/bf8afc8ffd4bfd3d9c373e417f041d9f1e5b863f",
"reference": "bf8afc8ffd4bfd3d9c373e417f041d9f1e5b863f",
"url": "https://api.github.com/repos/symfony/cache/zipball/4a55feb59664f49042a0824c0f955e2f4c1412ad",
"reference": "4a55feb59664f49042a0824c0f955e2f4c1412ad",
"shasum": ""
},
"require": {
@@ -6494,7 +6497,7 @@
"psr6"
],
"support": {
"source": "https://github.com/symfony/cache/tree/v7.3.4"
"source": "https://github.com/symfony/cache/tree/v7.3.5"
},
"funding": [
{
@@ -6514,7 +6517,7 @@
"type": "tidelift"
}
],
"time": "2025-09-11T10:12:26+00:00"
"time": "2025-10-16T13:55:38+00:00"
},
{
"name": "symfony/cache-contracts",
@@ -6668,16 +6671,16 @@
},
{
"name": "symfony/console",
"version": "v7.3.4",
"version": "v7.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db"
"reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/2b9c5fafbac0399a20a2e82429e2bd735dcfb7db",
"reference": "2b9c5fafbac0399a20a2e82429e2bd735dcfb7db",
"url": "https://api.github.com/repos/symfony/console/zipball/cdb80fa5869653c83cfe1a9084a673b6daf57ea7",
"reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7",
"shasum": ""
},
"require": {
@@ -6742,7 +6745,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v7.3.4"
"source": "https://github.com/symfony/console/tree/v7.3.5"
},
"funding": [
{
@@ -6762,7 +6765,7 @@
"type": "tidelift"
}
],
"time": "2025-09-22T15:31:00+00:00"
"time": "2025-10-14T15:46:26+00:00"
},
{
"name": "symfony/css-selector",
@@ -7207,16 +7210,16 @@
},
{
"name": "symfony/finder",
"version": "v7.3.2",
"version": "v7.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe"
"reference": "9f696d2f1e340484b4683f7853b273abff94421f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe",
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe",
"url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f",
"reference": "9f696d2f1e340484b4683f7853b273abff94421f",
"shasum": ""
},
"require": {
@@ -7251,7 +7254,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v7.3.2"
"source": "https://github.com/symfony/finder/tree/v7.3.5"
},
"funding": [
{
@@ -7271,7 +7274,7 @@
"type": "tidelift"
}
],
"time": "2025-07-15T13:41:35+00:00"
"time": "2025-10-15T18:45:57+00:00"
},
{
"name": "symfony/http-client",
@@ -7453,16 +7456,16 @@
},
{
"name": "symfony/http-foundation",
"version": "v7.3.4",
"version": "v7.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "c061c7c18918b1b64268771aad04b40be41dd2e6"
"reference": "ce31218c7cac92eab280762c4375fb70a6f4f897"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/c061c7c18918b1b64268771aad04b40be41dd2e6",
"reference": "c061c7c18918b1b64268771aad04b40be41dd2e6",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/ce31218c7cac92eab280762c4375fb70a6f4f897",
"reference": "ce31218c7cac92eab280762c4375fb70a6f4f897",
"shasum": ""
},
"require": {
@@ -7512,7 +7515,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-foundation/tree/v7.3.4"
"source": "https://github.com/symfony/http-foundation/tree/v7.3.5"
},
"funding": [
{
@@ -7532,20 +7535,20 @@
"type": "tidelift"
}
],
"time": "2025-09-16T08:38:17+00:00"
"time": "2025-10-24T21:42:11+00:00"
},
{
"name": "symfony/http-kernel",
"version": "v7.3.4",
"version": "v7.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
"reference": "b796dffea7821f035047235e076b60ca2446e3cf"
"reference": "24fd3f123532e26025f49f1abefcc01a69ef15ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/b796dffea7821f035047235e076b60ca2446e3cf",
"reference": "b796dffea7821f035047235e076b60ca2446e3cf",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/24fd3f123532e26025f49f1abefcc01a69ef15ab",
"reference": "24fd3f123532e26025f49f1abefcc01a69ef15ab",
"shasum": ""
},
"require": {
@@ -7630,7 +7633,7 @@
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-kernel/tree/v7.3.4"
"source": "https://github.com/symfony/http-kernel/tree/v7.3.5"
},
"funding": [
{
@@ -7650,20 +7653,20 @@
"type": "tidelift"
}
],
"time": "2025-09-27T12:32:17+00:00"
"time": "2025-10-28T10:19:01+00:00"
},
{
"name": "symfony/mailer",
"version": "v7.3.4",
"version": "v7.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
"reference": "ab97ef2f7acf0216955f5845484235113047a31d"
"reference": "fd497c45ba9c10c37864e19466b090dcb60a50ba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mailer/zipball/ab97ef2f7acf0216955f5845484235113047a31d",
"reference": "ab97ef2f7acf0216955f5845484235113047a31d",
"url": "https://api.github.com/repos/symfony/mailer/zipball/fd497c45ba9c10c37864e19466b090dcb60a50ba",
"reference": "fd497c45ba9c10c37864e19466b090dcb60a50ba",
"shasum": ""
},
"require": {
@@ -7714,7 +7717,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/mailer/tree/v7.3.4"
"source": "https://github.com/symfony/mailer/tree/v7.3.5"
},
"funding": [
{
@@ -7734,7 +7737,7 @@
"type": "tidelift"
}
],
"time": "2025-09-17T05:51:54+00:00"
"time": "2025-10-24T14:27:20+00:00"
},
{
"name": "symfony/mailgun-mailer",
@@ -9453,16 +9456,16 @@
},
{
"name": "symfony/var-dumper",
"version": "v7.3.4",
"version": "v7.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "b8abe7daf2730d07dfd4b2ee1cecbf0dd2fbdabb"
"reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/b8abe7daf2730d07dfd4b2ee1cecbf0dd2fbdabb",
"reference": "b8abe7daf2730d07dfd4b2ee1cecbf0dd2fbdabb",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/476c4ae17f43a9a36650c69879dcf5b1e6ae724d",
"reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d",
"shasum": ""
},
"require": {
@@ -9516,7 +9519,7 @@
"dump"
],
"support": {
"source": "https://github.com/symfony/var-dumper/tree/v7.3.4"
"source": "https://github.com/symfony/var-dumper/tree/v7.3.5"
},
"funding": [
{
@@ -9536,7 +9539,7 @@
"type": "tidelift"
}
],
"time": "2025-09-11T10:12:26+00:00"
"time": "2025-09-27T09:00:46+00:00"
},
{
"name": "symfony/var-exporter",
@@ -9815,16 +9818,16 @@
},
{
"name": "twig/twig",
"version": "v3.21.1",
"version": "v3.22.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d"
"reference": "4509984193026de413baf4ba80f68590a7f2c51d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d",
"reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/4509984193026de413baf4ba80f68590a7f2c51d",
"reference": "4509984193026de413baf4ba80f68590a7f2c51d",
"shasum": ""
},
"require": {
@@ -9878,7 +9881,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.21.1"
"source": "https://github.com/twigphp/Twig/tree/v3.22.0"
},
"funding": [
{
@@ -9890,7 +9893,7 @@
"type": "tidelift"
}
],
"time": "2025-05-03T07:21:55+00:00"
"time": "2025-10-29T15:56:47+00:00"
},
{
"name": "vlucas/phpdotenv",
@@ -10052,28 +10055,28 @@
},
{
"name": "webmozart/assert",
"version": "1.11.0",
"version": "1.12.1",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68",
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-date": "*",
"ext-filter": "*",
"php": "^7.2 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^8.5.13"
"suggest": {
"ext-intl": "",
"ext-simplexml": "",
"ext-spl": ""
},
"type": "library",
"extra": {
@@ -10104,9 +10107,9 @@
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
"source": "https://github.com/webmozarts/assert/tree/1.12.1"
},
"time": "2022-06-03T18:03:27+00:00"
"time": "2025-10-29T15:56:20+00:00"
}
],
"packages-dev": [
@@ -10549,16 +10552,16 @@
},
{
"name": "driftingly/rector-laravel",
"version": "2.0.7",
"version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/driftingly/rector-laravel.git",
"reference": "625dc02cee08d47ecf0ac86de2f02a55026cf34e"
"reference": "abc336cbf06f53d90ab74cecfd319379fc55d408"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/625dc02cee08d47ecf0ac86de2f02a55026cf34e",
"reference": "625dc02cee08d47ecf0ac86de2f02a55026cf34e",
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/abc336cbf06f53d90ab74cecfd319379fc55d408",
"reference": "abc336cbf06f53d90ab74cecfd319379fc55d408",
"shasum": ""
},
"require": {
@@ -10578,9 +10581,9 @@
"description": "Rector upgrades rules for Laravel Framework",
"support": {
"issues": "https://github.com/driftingly/rector-laravel/issues",
"source": "https://github.com/driftingly/rector-laravel/tree/2.0.7"
"source": "https://github.com/driftingly/rector-laravel/tree/2.1.1"
},
"time": "2025-08-19T20:49:47+00:00"
"time": "2025-10-23T13:53:44+00:00"
},
{
"name": "fakerphp/faker",
@@ -11036,16 +11039,16 @@
},
{
"name": "nikic/php-parser",
"version": "v5.6.1",
"version": "v5.6.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2"
"reference": "3a454ca033b9e06b63282ce19562e892747449bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb",
"reference": "3a454ca033b9e06b63282ce19562e892747449bb",
"shasum": ""
},
"require": {
@@ -11088,9 +11091,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1"
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2"
},
"time": "2025-08-13T20:13:15+00:00"
"time": "2025-10-21T19:32:17+00:00"
},
{
"name": "phar-io/manifest",
@@ -11815,16 +11818,16 @@
},
{
"name": "phpunit/phpunit",
"version": "12.4.1",
"version": "12.4.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "fc5413a2e6d240d2f6d9317bdf7f0a24e73de194"
"reference": "a94ea4d26d865875803b23aaf78c3c2c670ea2ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc5413a2e6d240d2f6d9317bdf7f0a24e73de194",
"reference": "fc5413a2e6d240d2f6d9317bdf7f0a24e73de194",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a94ea4d26d865875803b23aaf78c3c2c670ea2ea",
"reference": "a94ea4d26d865875803b23aaf78c3c2c670ea2ea",
"shasum": ""
},
"require": {
@@ -11892,7 +11895,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.1"
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.4.2"
},
"funding": [
{
@@ -11916,20 +11919,20 @@
"type": "tidelift"
}
],
"time": "2025-10-09T14:08:29+00:00"
"time": "2025-10-30T08:41:39+00:00"
},
{
"name": "rector/rector",
"version": "2.2.2",
"version": "2.2.7",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
"reference": "5b353f7457b9a0c63fc91ef340f5d119a40991ed"
"reference": "022038537838bc8a4e526af86c2d6e38eaeff7ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/5b353f7457b9a0c63fc91ef340f5d119a40991ed",
"reference": "5b353f7457b9a0c63fc91ef340f5d119a40991ed",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/022038537838bc8a4e526af86c2d6e38eaeff7ef",
"reference": "022038537838bc8a4e526af86c2d6e38eaeff7ef",
"shasum": ""
},
"require": {
@@ -11968,7 +11971,7 @@
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.2.2"
"source": "https://github.com/rectorphp/rector/tree/2.2.7"
},
"funding": [
{
@@ -11976,7 +11979,7 @@
"type": "github"
}
],
"time": "2025-10-09T19:50:20+00:00"
"time": "2025-10-29T15:46:12+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2025-10-10',
'build_time' => 1760115185,
'version' => 'develop/2025-10-31',
'build_time' => 1761889339,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.
@@ -182,6 +182,7 @@ return [
'darkMode' => 'browser',
'list_length' => 10, // to be removed if v1 is cancelled.
'default_preferences' => [
'anonymous' => false,
'frontpageAccounts' => [],
'listPageSize' => 50,
'currencyPreference' => 'EUR',
@@ -308,7 +309,7 @@ return [
// "period must be in this list" values
'bill_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'interest_periods' => ['weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'interest_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
// settings to translate X to Y
'range_to_repeat_freq' => [

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Database\Factories;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\AccountType;
use Illuminate\Database\Eloquent\Factories\Factory;
class AccountFactory extends Factory
{
public function definition(): array
{
return [
'name' => $this->faker->name(),
'active' => true,
];
}
public function withType(AccountTypeEnum $type): static
{
return $this->for(AccountType::where('type', $type->value)->first());
}
}

View File

@@ -11,34 +11,36 @@ return new class extends Migration
*/
public function up(): void
{
Schema::create('period_statistics', function (Blueprint $table) {
$table->id();
$table->timestamps();
if (!Schema::hasTable('period_statistics')) {
Schema::create('period_statistics', function (Blueprint $table) {
$table->id();
$table->timestamps();
// reference to user group id.
$table->bigInteger('user_group_id', false, true);
// reference to user group id.
$table->bigInteger('user_group_id', false, true);
$table->integer('primary_statable_id', false, true)->nullable();
$table->string('primary_statable_type', 255)->nullable();
$table->integer('primary_statable_id', false, true)->nullable();
$table->string('primary_statable_type', 255)->nullable();
$table->integer('secondary_statable_id', false, true)->nullable();
$table->string('secondary_statable_type', 255)->nullable();
$table->integer('secondary_statable_id', false, true)->nullable();
$table->string('secondary_statable_type', 255)->nullable();
$table->integer('tertiary_statable_id', false, true)->nullable();
$table->string('tertiary_statable_type', 255)->nullable();
$table->integer('tertiary_statable_id', false, true)->nullable();
$table->string('tertiary_statable_type', 255)->nullable();
$table->integer('transaction_currency_id', false, true);
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
$table->integer('transaction_currency_id', false, true);
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
$table->dateTime('start')->nullable();
$table->string('start_tz', 50)->nullable();
$table->dateTime('end')->nullable();
$table->string('end_tz', 50)->nullable();
$table->string('type',255);
$table->integer('count', false, true)->default(0);
$table->decimal('amount', 32, 12);
$table->foreign('user_group_id')->references('id')->on('user_groups')->onDelete('cascade');
});
$table->dateTime('start')->nullable();
$table->string('start_tz', 50)->nullable();
$table->dateTime('end')->nullable();
$table->string('end_tz', 50)->nullable();
$table->string('type', 255);
$table->integer('count', false, true)->default(0);
$table->decimal('amount', 32, 12);
$table->foreign('user_group_id')->references('id')->on('user_groups')->onDelete('cascade');
});
}
}
/**

730
package-lock.json generated

File diff suppressed because it is too large Load Diff

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