Compare commits

...

15 Commits

Author SHA1 Message Date
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
62 changed files with 382 additions and 159 deletions

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

@@ -70,7 +70,7 @@ class ListController extends Controller
);
}
public function attachments(Account $account, PaginationRequest $request): JsonResponse
public function attachments(PaginationRequest $request, Account $account): JsonResponse
{
$manager = $this->getManager();
[
@@ -96,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 */
@@ -117,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

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

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

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

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

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

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

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

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

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

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

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

@@ -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,9 @@ 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::mark();
}
}
@@ -188,7 +189,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,7 +218,7 @@ 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
@@ -257,7 +258,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,7 +282,7 @@ class UserEventHandler
$newEmail = $event->newEmail;
$oldEmail = $event->oldEmail;
$user = $event->user;
$token = app('preferences')->getForUser($user, 'email_change_undo_token', 'invalid');
$token = Preferences::getForUser($user, 'email_change_undo_token', 'invalid');
$hashed = hash('sha256', sprintf('%s%s', (string) config('app.key'), $oldEmail));
$url = route('profile.undo-email-change', [$token->data, $hashed]);
@@ -455,7 +456,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 +492,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

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

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

@@ -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-26',
'build_time' => 1761467848,
'version' => 'develop/2025-10-27',
'build_time' => 1761535807,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.

6
package-lock.json generated
View File

@@ -3776,9 +3776,9 @@
}
},
"node_modules/alpinejs": {
"version": "3.15.0",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.0.tgz",
"integrity": "sha512-lpokA5okCF1BKh10LG8YjqhfpxyHBk4gE7boIgVHltJzYoM7O9nK3M7VlntLEJGsVmu7U/RzUWajmHREGT38Eg==",
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.1.tgz",
"integrity": "sha512-HLO1TtiE92VajFHtLLPK8BWaK1YepV/uj31UrfoGnQ00lyFOJZ+oVY3F0DghPAwvg8sLU79pmjGQSytERa2gEg==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "~3.1.1"

View File

@@ -35,5 +35,5 @@ return [
'currencies-index' => 'Firefly III supports multiple currencies. Although it defaults to the Euro it can be set to the US Dollar and many other currencies. As you can see a small selection of currencies has been included but you can add your own if you wish to. Changing the default currency will not change the currency of existing transactions however: Firefly III supports the use of multiple currencies at the same time.',
'transactions-index' => 'These expenses, deposits and transfers are not particularly imaginative. They have been generated automatically.',
'piggy-banks-index' => 'As you can see, there are three piggy banks. Use the plus and minus buttons to influence the amount of money in each piggy bank. Click the name of the piggy bank to see the administration for each piggy bank.',
'profile-index' => 'Keep in mind that the demo site resets every four hours. Your access may be revoked at any time. This happens automatically and is not a bug.',
'profile-index' => 'Keep in mind that the demo site resets every four hours. Standard user agents (curl, Postman, wget) are blocked. Your access may be revoked at any time. This happens automatically and is not a bug.',
];

View File

@@ -121,11 +121,11 @@ Route::group(
Route::post('logout', ['uses' => 'Auth\LoginController@logout', 'as' => 'logout']);
Route::get('flush', ['uses' => 'DebugController@flush', 'as' => 'flush']);
Route::get('routes', ['uses' => 'DebugController@routes', 'as' => 'routes']);
Route::get('debug', 'DebugController@index')->name('debug');
Route::get('debug/api-test', 'DebugController@apiTest')->name('api-test');
}
);
// For the two factor routes, the user must be logged in, but NOT 2FA. Account confirmation does not matter here.
Route::group(
['middleware' => 'user-logged-in-no-2fa', 'prefix' => 'two-factor', 'as' => 'two-factor.', 'namespace' => 'FireflyIII\Http\Controllers\Auth'],
@@ -137,6 +137,16 @@ Route::group(
// For all other routes, the user must be fully authenticated and have an activated account.
// For some other routes, it is only relevant that the user is authenticated.
Route::group(
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers'],
static function (): void {
Route::get('debug', 'DebugController@index')->name('debug');
Route::get('debug/api-test', 'DebugController@apiTest')->name('api-test');
}
);
// Home Controller.
Route::group(
['middleware' => ['user-full-auth'], 'namespace' => 'FireflyIII\Http\Controllers'],