Merge pull request #11201 from firefly-iii/release-1762675915

🤖 Automatically merge the PR into the develop branch.
This commit is contained in:
github-actions[bot]
2025-11-09 09:12:04 +01:00
committed by GitHub
78 changed files with 183 additions and 179 deletions

View File

@@ -102,9 +102,9 @@ abstract class Controller extends BaseController
} }
#[Deprecated(message: <<<'TXT' #[Deprecated(message: <<<'TXT'
use Request classes use Request classes
Method to grab all parameters from the URL Method to grab all parameters from the URL
TXT)] TXT)]
private function getParameters(): ParameterBag private function getParameters(): ParameterBag
{ {
$bag = new ParameterBag(); $bag = new ParameterBag();

View File

@@ -651,6 +651,7 @@ class BasicController extends Controller
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) { if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
return true; return true;
} }
// start and end in the past? use $end // start and end in the past? use $end
return $start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date); return $start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date);
} }

View File

@@ -251,6 +251,7 @@ class CorrectsUnevenAmount extends Command
/** @var Transaction $source */ /** @var Transaction $source */
$source = $journal->transactions()->where('amount', '<', 0)->first(); $source = $journal->transactions()->where('amount', '<', 0)->first();
// safety catch on NULL should not be necessary, we just had that catch. // safety catch on NULL should not be necessary, we just had that catch.
// source amount = dest foreign amount // source amount = dest foreign amount
// source currency = dest foreign currency // source currency = dest foreign currency

View File

@@ -136,6 +136,7 @@ class UpgradesLiabilitiesEight extends Command
if (null === $liabilityJournal) { if (null === $liabilityJournal) {
return false; return false;
} }
return (bool) $openingJournal->date->isSameDay($liabilityJournal->date); return (bool) $openingJournal->date->isSameDay($liabilityJournal->date);
} }

View File

@@ -34,10 +34,10 @@ use Throwable;
final class IntervalException extends Exception final class IntervalException extends Exception
{ {
public array $availableIntervals = []; public array $availableIntervals = [];
public Periodicity $periodicity = Periodicity::Monthly; public Periodicity $periodicity = Periodicity::Monthly;
/** @var mixed */ /** @var mixed */
protected $message = 'The periodicity %s is unknown. Choose one of available periodicity: %s'; protected $message = 'The periodicity %s is unknown. Choose one of available periodicity: %s';
public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null) public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null)
{ {

View File

@@ -43,9 +43,9 @@ class TransactionFactory
private Account $account; private Account $account;
private array $accountInformation = []; private array $accountInformation = [];
private TransactionCurrency $currency; private TransactionCurrency $currency;
private ?TransactionCurrency $foreignCurrency = null; private ?TransactionCurrency $foreignCurrency = null;
private TransactionJournal $journal; private TransactionJournal $journal;
private bool $reconciled = false; private bool $reconciled = false;
/** /**
* Create transaction with negative amount (for source accounts). * Create transaction with negative amount (for source accounts).

View File

@@ -42,7 +42,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
private Collection $categories; private Collection $categories;
private Carbon $end; private Carbon $end;
private array $expenses = []; private array $expenses = [];
private array $income = []; private array $income = [];
private Carbon $start; private Carbon $start;
/** /**

View File

@@ -39,10 +39,10 @@ class MonthReportGenerator implements ReportGeneratorInterface
private ?Collection $accounts = null; private ?Collection $accounts = null;
/** @var Carbon The end date. */ /** @var Carbon The end date. */
private ?Carbon $end = null; private ?Carbon $end = null;
/** @var Carbon The start date. */ /** @var Carbon The start date. */
private ?Carbon $start = null; private ?Carbon $start = null;
/** /**
* Generates the report. * Generates the report.

View File

@@ -39,10 +39,10 @@ class MultiYearReportGenerator implements ReportGeneratorInterface
private ?Collection $accounts = null; private ?Collection $accounts = null;
/** @var Carbon The end date. */ /** @var Carbon The end date. */
private ?Carbon $end = null; private ?Carbon $end = null;
/** @var Carbon The start date. */ /** @var Carbon The start date. */
private ?Carbon $start = null; private ?Carbon $start = null;
/** /**
* Generates the report. * Generates the report.

View File

@@ -39,10 +39,10 @@ class YearReportGenerator implements ReportGeneratorInterface
private ?Collection $accounts = null; private ?Collection $accounts = null;
/** @var Carbon The end date. */ /** @var Carbon The end date. */
private ?Carbon $end = null; private ?Carbon $end = null;
/** @var Carbon The start date. */ /** @var Carbon The start date. */
private ?Carbon $start = null; private ?Carbon $start = null;
/** /**
* Generates the report. * Generates the report.

View File

@@ -42,9 +42,7 @@ class ReportHelper implements ReportHelperInterface
public function __construct( public function __construct(
/** @var BudgetRepositoryInterface The budget repository */ /** @var BudgetRepositoryInterface The budget repository */
protected BudgetRepositoryInterface $budgetRepository protected BudgetRepositoryInterface $budgetRepository
) ) {}
{
}
/** /**
* This method generates a full report for the given period on all * This method generates a full report for the given period on all

View File

@@ -66,7 +66,7 @@ class DeleteController extends Controller
* *
* @return Factory|Redirector|RedirectResponse|View * @return Factory|Redirector|RedirectResponse|View
*/ */
public function delete(Account $account): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function delete(Account $account): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
if (!$this->isEditableAccount($account)) { if (!$this->isEditableAccount($account)) {
return $this->redirectAccountToAccount($account); return $this->redirectAccountToAccount($account);

View File

@@ -76,7 +76,7 @@ class EditController extends Controller
* *
* @return Factory|Redirector|RedirectResponse|View * @return Factory|Redirector|RedirectResponse|View
*/ */
public function edit(Request $request, Account $account, AccountRepositoryInterface $repository): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function edit(Request $request, Account $account, AccountRepositoryInterface $repository): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
if (!$this->isEditableAccount($account)) { if (!$this->isEditableAccount($account)) {
return $this->redirectAccountToAccount($account); return $this->redirectAccountToAccount($account);

View File

@@ -78,7 +78,7 @@ class ReconcileController extends Controller
* *
* @throws FireflyException * @throws FireflyException
* */ * */
public function reconcile(Account $account, ?Carbon $start = null, ?Carbon $end = null): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function reconcile(Account $account, ?Carbon $start = null, ?Carbon $end = null): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
if (!$this->isEditableAccount($account)) { if (!$this->isEditableAccount($account)) {
return $this->redirectAccountToAccount($account); return $this->redirectAccountToAccount($account);
@@ -146,7 +146,6 @@ class ReconcileController extends Controller
/** /**
* Submit a new reconciliation. * Submit a new reconciliation.
* *
*
* @throws DuplicateTransactionException * @throws DuplicateTransactionException
*/ */
public function submit(ReconciliationStoreRequest $request, Account $account, Carbon $start, Carbon $end): Redirector|RedirectResponse public function submit(ReconciliationStoreRequest $request, Account $account, Carbon $start, Carbon $end): Redirector|RedirectResponse

View File

@@ -84,7 +84,7 @@ class ShowController extends Controller
* @throws FireflyException * @throws FireflyException
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
*/ */
public function show(Request $request, Account $account, ?Carbon $start = null, ?Carbon $end = null): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function show(Request $request, Account $account, ?Carbon $start = null, ?Carbon $end = null): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
if (0 === $account->id) { if (0 === $account->id) {
throw new NotFoundHttpException(); throw new NotFoundHttpException();
@@ -187,47 +187,47 @@ class ShowController extends Controller
* @throws ContainerExceptionInterface * @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
*/ */
public function showAll(Request $request, Account $account): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function showAll(Request $request, Account $account): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
if (!$this->isEditableAccount($account)) { if (!$this->isEditableAccount($account)) {
return $this->redirectAccountToAccount($account); return $this->redirectAccountToAccount($account);
} }
$location = $this->repository->getLocation($account); $location = $this->repository->getLocation($account);
$isLiability = $this->repository->isLiability($account); $isLiability = $this->repository->isLiability($account);
$attachments = $this->repository->getAttachments($account); $attachments = $this->repository->getAttachments($account);
$objectType = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type)); $objectType = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type));
$end = today(config('app.timezone')); $end = today(config('app.timezone'));
$today = today(config('app.timezone')); $today = today(config('app.timezone'));
$this->repository->getAccountCurrency($account); $this->repository->getAccountCurrency($account);
$start = $this->repository->oldestJournalDate($account) ?? today(config('app.timezone'))->startOfMonth(); $start = $this->repository->oldestJournalDate($account) ?? today(config('app.timezone'))->startOfMonth();
$subTitleIcon = config('firefly.subIconsByIdentifier.'.$account->accountType->type); $subTitleIcon = config('firefly.subIconsByIdentifier.'.$account->accountType->type);
$page = (int) $request->get('page'); $page = (int) $request->get('page');
$pageSize = (int) app('preferences')->get('listPageSize', 50)->data; $pageSize = (int) app('preferences')->get('listPageSize', 50)->data;
$currency = $this->repository->getAccountCurrency($account) ?? $this->primaryCurrency; $currency = $this->repository->getAccountCurrency($account) ?? $this->primaryCurrency;
$subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]); $subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]);
$periods = new Collection(); $periods = new Collection();
$end->endOfDay(); $end->endOfDay();
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection()->push($account))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation(); $collector->setAccounts(new Collection()->push($account))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation();
// this search will not include transaction groups where this asset account (or liability) // this search will not include transaction groups where this asset account (or liability)
// is just part of ONE of the journals. To force this: // is just part of ONE of the journals. To force this:
$collector->setExpandGroupSearch(true); $collector->setExpandGroupSearch(true);
$groups = $collector->getPaginatedGroups(); $groups = $collector->getPaginatedGroups();
$groups->setPath(route('accounts.show.all', [$account->id])); $groups->setPath(route('accounts.show.all', [$account->id]));
$chartUrl = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]); $chartUrl = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]);
$showAll = true; $showAll = true;
// correct // correct
Log::debug(sprintf('showAll: Call accountsBalancesOptimized with date/time "%s"', $end->toIso8601String())); Log::debug(sprintf('showAll: Call accountsBalancesOptimized with date/time "%s"', $end->toIso8601String()));
// 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized. // 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized.
// $balances = Steam::finalAccountBalance($account, $end); // $balances = Steam::finalAccountBalance($account, $end);
// $balances = Steam::filterAccountBalance($balances, $account, $this->convertToPrimary, $accountCurrency); // $balances = Steam::filterAccountBalance($balances, $account, $this->convertToPrimary, $accountCurrency);
$balances = Steam::accountsBalancesOptimized(new Collection()->push($account), $end)[$account->id]; $balances = Steam::accountsBalancesOptimized(new Collection()->push($account), $end)[$account->id];
return view( return view(
'accounts.show', 'accounts.show',

View File

@@ -86,7 +86,7 @@ class LinkController extends Controller
* *
* @return Factory|Redirector|RedirectResponse|View * @return Factory|Redirector|RedirectResponse|View
*/ */
public function delete(Request $request, LinkType $linkType): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function delete(Request $request, LinkType $linkType): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
if (false === $linkType->editable) { if (false === $linkType->editable) {
$request->session()->flash('error', (string) trans('firefly.cannot_edit_link_type', ['name' => e($linkType->name)])); $request->session()->flash('error', (string) trans('firefly.cannot_edit_link_type', ['name' => e($linkType->name)]));
@@ -135,7 +135,7 @@ class LinkController extends Controller
* *
* @return Factory|Redirector|RedirectResponse|View * @return Factory|Redirector|RedirectResponse|View
*/ */
public function edit(Request $request, LinkType $linkType): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function edit(Request $request, LinkType $linkType): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
if (false === $linkType->editable) { if (false === $linkType->editable) {
$request->session()->flash('error', (string) trans('firefly.cannot_edit_link_type', ['name' => e($linkType->name)])); $request->session()->flash('error', (string) trans('firefly.cannot_edit_link_type', ['name' => e($linkType->name)]));

View File

@@ -73,7 +73,7 @@ class UserController extends Controller
/** /**
* @return Application|Factory|Redirector|RedirectResponse|View * @return Application|Factory|Redirector|RedirectResponse|View
*/ */
public function delete(User $user): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function delete(User $user): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
if ($this->externalIdentity) { if ($this->externalIdentity) {
request()->session()->flash('error', trans('firefly.external_user_mgt_disabled')); request()->session()->flash('error', trans('firefly.external_user_mgt_disabled'));

View File

@@ -68,7 +68,7 @@ class LoginController extends Controller
protected string $redirectTo = RouteServiceProvider::HOME; protected string $redirectTo = RouteServiceProvider::HOME;
private UserRepositoryInterface $repository; private UserRepositoryInterface $repository;
private string $username = 'email'; private string $username = 'email';
/** /**
* Create a new controller instance. * Create a new controller instance.
@@ -222,7 +222,7 @@ class LoginController extends Controller
* @throws ContainerExceptionInterface * @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
*/ */
public function showLoginForm(Request $request): Redirector|RedirectResponse|Factory|View public function showLoginForm(Request $request): Factory|Redirector|RedirectResponse|View
{ {
Log::channel('audit')->info('Show login form (1.1).'); Log::channel('audit')->info('Show login form (1.1).');

View File

@@ -114,6 +114,7 @@ class ResetPasswordController extends Controller
* *
* If no token is present, display the link request form. * If no token is present, display the link request form.
* *
* @param null|mixed $token
* *
* @return Factory|View * @return Factory|View
* *

View File

@@ -59,7 +59,6 @@ class TwoFactorController extends Controller
} }
/** /**
*
* @throws ContainerExceptionInterface * @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
*/ */
@@ -211,6 +210,7 @@ class TwoFactorController extends Controller
if (!is_array($list)) { if (!is_array($list)) {
$list = []; $list = [];
} }
return in_array($mfaCode, $list, true); return in_array($mfaCode, $list, true);
} }

View File

@@ -96,7 +96,6 @@ class DebugController extends Controller
/** /**
* Clear log and session. * Clear log and session.
* *
*
* @throws FireflyException * @throws FireflyException
*/ */
public function flush(Request $request): Redirector|RedirectResponse public function flush(Request $request): Redirector|RedirectResponse
@@ -514,30 +513,40 @@ class DebugController extends Controller
case 'userGroup': case 'userGroup':
return '1'; return '1';
case 'start_date': case 'start_date':
case 'date': case 'date':
return '20241201'; return '20241201';
case 'end_date': case 'end_date':
return '20241231'; return '20241231';
case 'fromCurrencyCode': case 'fromCurrencyCode':
return 'EUR'; return 'EUR';
case 'toCurrencyCode': case 'toCurrencyCode':
return 'USD'; return 'USD';
case 'accountList': case 'accountList':
return '1,6'; return '1,6';
case 'budgetList': case 'budgetList':
case 'categoryList': case 'categoryList':
case 'doubleList': case 'doubleList':
case 'tagList': case 'tagList':
case 'journalList': case 'journalList':
return '1,2'; return '1,2';
case 'route': case 'route':
return 'accounts'; return 'accounts';
case 'specificPage': case 'specificPage':
return 'show'; return 'show';
case 'reportType': case 'reportType':
return 'default'; return 'default';
case 'transactionType': case 'transactionType':
return 'withdrawal'; return 'withdrawal';

View File

@@ -64,7 +64,7 @@ class NewUserController extends Controller
* *
* @return Factory|Redirector|RedirectResponse|View * @return Factory|Redirector|RedirectResponse|View
*/ */
public function index(): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function index(): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
app('view')->share('title', (string) trans('firefly.welcome')); app('view')->share('title', (string) trans('firefly.welcome'));
app('view')->share('mainTitleIcon', 'fa-fire'); app('view')->share('mainTitleIcon', 'fa-fire');

View File

@@ -188,7 +188,6 @@ class PreferencesController extends Controller
/** /**
* Store new preferences. * Store new preferences.
* *
*
* @throws FireflyException * @throws FireflyException
* *
* @SuppressWarnings("PHPMD.ExcessiveMethodLength") * @SuppressWarnings("PHPMD.ExcessiveMethodLength")

View File

@@ -228,7 +228,6 @@ class MfaController extends Controller
/** /**
* Submit 2FA for the first time. * Submit 2FA for the first time.
* *
*
* @throws ContainerExceptionInterface * @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
*/ */

View File

@@ -288,7 +288,7 @@ class ProfileController extends Controller
* *
* @return Factory|Redirector|RedirectResponse|View * @return Factory|Redirector|RedirectResponse|View
*/ */
public function changePassword(Request $request): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function changePassword(Request $request): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
if (!$this->internalAuth) { if (!$this->internalAuth) {
$request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); $request->session()->flash('error', trans('firefly.external_user_mgt_disabled'));
@@ -361,7 +361,6 @@ class ProfileController extends Controller
/** /**
* Regenerate access token. * Regenerate access token.
* *
*
* @throws Exception * @throws Exception
*/ */
public function regenerate(Request $request): Redirector|RedirectResponse public function regenerate(Request $request): Redirector|RedirectResponse
@@ -384,7 +383,6 @@ class ProfileController extends Controller
/** /**
* Undo change of user email address. * Undo change of user email address.
* *
*
* @throws FireflyException * @throws FireflyException
*/ */
public function undoEmailChange(UserRepositoryInterface $repository, string $token, string $hash): Redirector|RedirectResponse public function undoEmailChange(UserRepositoryInterface $repository, string $token, string $hash): Redirector|RedirectResponse

View File

@@ -193,7 +193,6 @@ class ReportController extends Controller
/** /**
* Show account report. * Show account report.
* *
*
* @throws FireflyException * @throws FireflyException
*/ */
public function doubleReport(Collection $accounts, Collection $expense, Carbon $start, Carbon $end): string public function doubleReport(Collection $accounts, Collection $expense, Carbon $start, Carbon $end): string

View File

@@ -37,7 +37,7 @@ class CronController
/** /**
* @return Application|Response|ResponseFactory * @return Application|Response|ResponseFactory
*/ */
public function cron(): ResponseFactory|Response public function cron(): Response|ResponseFactory
{ {
Log::error('The cron endpoint has moved to GET /api/v1/cron/[token]'); Log::error('The cron endpoint has moved to GET /api/v1/cron/[token]');

View File

@@ -51,9 +51,9 @@ class InstallController extends Controller
public const string BASEDIR_ERROR = 'Firefly III cannot execute the upgrade commands. It is not allowed to because of an open_basedir restriction.'; public const string BASEDIR_ERROR = 'Firefly III cannot execute the upgrade commands. It is not allowed to because of an open_basedir restriction.';
public const string FORBIDDEN_ERROR = 'Internal PHP function "proc_close" is disabled for your installation. Auto-migration is not possible.'; public const string FORBIDDEN_ERROR = 'Internal PHP function "proc_close" is disabled for your installation. Auto-migration is not possible.';
public const string OTHER_ERROR = 'An unknown error prevented Firefly III from executing the upgrade commands. Sorry.'; public const string OTHER_ERROR = 'An unknown error prevented Firefly III from executing the upgrade commands. Sorry.';
private string $lastError = ''; private string $lastError = '';
// empty on purpose. // empty on purpose.
private array $upgradeCommands = [ private array $upgradeCommands = [
// there are 5 initial commands // there are 5 initial commands
// Check 4 places: InstallController, Docker image, UpgradeDatabase, composer.json // Check 4 places: InstallController, Docker image, UpgradeDatabase, composer.json
'migrate' => ['--seed' => true, '--force' => true], 'migrate' => ['--seed' => true, '--force' => true],

View File

@@ -87,7 +87,7 @@ class ConvertController extends Controller
* *
* @throws Exception * @throws Exception
*/ */
public function index(TransactionType $destinationType, TransactionGroup $group): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function index(TransactionType $destinationType, TransactionGroup $group): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
if (!$this->isEditableGroup($group)) { if (!$this->isEditableGroup($group)) {
return $this->redirectGroupToAccount($group); return $this->redirectGroupToAccount($group);

View File

@@ -100,7 +100,6 @@ class CreateController extends Controller
/** /**
* Create a new transaction group. * Create a new transaction group.
* *
*
* @throws ContainerExceptionInterface * @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
* @throws UrlException * @throws UrlException

View File

@@ -68,7 +68,7 @@ class DeleteController extends Controller
/** /**
* Shows the form that allows a user to delete a transaction journal. * Shows the form that allows a user to delete a transaction journal.
*/ */
public function delete(TransactionGroup $group): Redirector|RedirectResponse|Factory|View public function delete(TransactionGroup $group): Factory|Redirector|RedirectResponse|View
{ {
if (!$this->isEditableGroup($group)) { if (!$this->isEditableGroup($group)) {
return $this->redirectGroupToAccount($group); return $this->redirectGroupToAccount($group);

View File

@@ -74,7 +74,7 @@ class EditController extends Controller
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
* @throws UrlException * @throws UrlException
*/ */
public function edit(TransactionGroup $transactionGroup): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function edit(TransactionGroup $transactionGroup): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
app('preferences')->mark(); app('preferences')->mark();

View File

@@ -154,7 +154,6 @@ class MassController extends Controller
/** /**
* Mass update of journals. * Mass update of journals.
* *
*
* @throws FireflyException * @throws FireflyException
*/ */
public function update(MassEditJournalRequest $request): Redirector|RedirectResponse public function update(MassEditJournalRequest $request): Redirector|RedirectResponse

View File

@@ -70,7 +70,7 @@ class CreateController extends Controller
* *
* @return Factory|Redirector|RedirectResponse|View * @return Factory|Redirector|RedirectResponse|View
*/ */
public function create(Request $request): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function create(Request $request): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();

View File

@@ -71,7 +71,7 @@ class DeleteController extends Controller
* *
* @throws FireflyException * @throws FireflyException
*/ */
public function delete(Request $request, TransactionCurrency $currency): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function delete(Request $request, TransactionCurrency $currency): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
@@ -102,7 +102,6 @@ class DeleteController extends Controller
/** /**
* Destroys a currency. * Destroys a currency.
* *
*
* @throws FireflyException * @throws FireflyException
*/ */
public function destroy(Request $request, TransactionCurrency $currency): Redirector|RedirectResponse public function destroy(Request $request, TransactionCurrency $currency): Redirector|RedirectResponse

View File

@@ -67,7 +67,7 @@ class EditController extends Controller
* *
* @return Factory|Redirector|RedirectResponse|View * @return Factory|Redirector|RedirectResponse|View
*/ */
public function edit(Request $request, TransactionCurrency $currency): Redirector|RedirectResponse|Factory|\Illuminate\Contracts\View\View public function edit(Request $request, TransactionCurrency $currency): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{ {
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
@@ -107,7 +107,6 @@ class EditController extends Controller
/** /**
* Updates a currency. * Updates a currency.
* *
*
* @throws FireflyException * @throws FireflyException
*/ */
public function update(CurrencyFormRequest $request, TransactionCurrency $currency): Redirector|RedirectResponse public function update(CurrencyFormRequest $request, TransactionCurrency $currency): Redirector|RedirectResponse

View File

@@ -139,6 +139,7 @@ class Authenticate
app('session')->flash('logoutMessage', $message); app('session')->flash('logoutMessage', $message);
// @noinspection PhpUndefinedMethodInspection // @noinspection PhpUndefinedMethodInspection
$this->auth->logout(); $this->auth->logout();
// @phpstan-ignore-line (thinks function is undefined) // @phpstan-ignore-line (thinks function is undefined)
throw new AuthenticationException('Blocked account.', $guards); throw new AuthenticationException('Blocked account.', $guards);
} }

View File

@@ -45,8 +45,8 @@ class Binder
public function __construct(/** public function __construct(/**
* The authentication factory instance. * The authentication factory instance.
*/ */
protected Auth $auth) protected Auth $auth
{ ) {
$this->binders = Domain::getBindables(); $this->binders = Domain::getBindables();
} }

View File

@@ -127,6 +127,7 @@ class WarnAboutBills implements ShouldQueue
$diff = $this->getDiff($bill, $field); $diff = $this->getDiff($bill, $field);
$list = config('firefly.bill_reminder_periods'); $list = config('firefly.bill_reminder_periods');
Log::debug(sprintf('Difference in days for field "%s" ("%s") is %d day(s)', $field, $bill->{$field}->format('Y-m-d'), $diff)); Log::debug(sprintf('Difference in days for field "%s" ("%s") is %d day(s)', $field, $bill->{$field}->format('Y-m-d'), $diff));
return in_array($diff, $list, true); return in_array($diff, $list, true);
} }
@@ -189,6 +190,7 @@ class WarnAboutBills implements ShouldQueue
Log::debug(sprintf('Earliest expected pay date is %s', $earliest->toAtomString())); Log::debug(sprintf('Earliest expected pay date is %s', $earliest->toAtomString()));
$diff = $earliest->diffInDays($this->date); $diff = $earliest->diffInDays($this->date);
Log::debug(sprintf('Difference in days is %s', $diff)); Log::debug(sprintf('Difference in days is %s', $diff));
return $diff >= 2; return $diff >= 2;
} }

View File

@@ -79,6 +79,7 @@ class AppServiceProvider extends ServiceProvider
$params = Route::getCurrentRoute()->parameters(); $params = Route::getCurrentRoute()->parameters();
$params ??= []; $params ??= [];
$objectType = $params['objectType'] ?? ''; $objectType = $params['objectType'] ?? '';
return $objectType === $firstParam && str_contains($name, $route); return $objectType === $firstParam && str_contains($name, $route);
}); });
} }

View File

@@ -77,8 +77,7 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
public function firstNull(): ?TransactionJournal public function firstNull(): ?TransactionJournal
{ {
/** @var null|TransactionJournal $entry */ /** @var null|TransactionJournal $entry */
$entry = $this->user->transactionJournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']); return $this->user->transactionJournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']);
return $entry;
} }
public function getDestinationAccount(TransactionJournal $journal): Account public function getDestinationAccount(TransactionJournal $journal): Account
@@ -115,8 +114,7 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
public function getLast(): ?TransactionJournal public function getLast(): ?TransactionJournal
{ {
/** @var null|TransactionJournal $entry */ /** @var null|TransactionJournal $entry */
$entry = $this->user->transactionJournals()->orderBy('date', 'DESC')->first(['transaction_journals.*']); return $this->user->transactionJournals()->orderBy('date', 'DESC')->first(['transaction_journals.*']);
return $entry;
} }
public function getLinkNoteText(TransactionJournalLink $link): string public function getLinkNoteText(TransactionJournalLink $link): string

View File

@@ -38,9 +38,7 @@ class IsAllowedGroupAction implements ValidationRule
// you need these roles to do anything with any endpoint. // you need these roles to do anything with any endpoint.
private array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL]; private array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL];
public function __construct(private readonly string $className, private readonly string $methodName) public function __construct(private readonly string $className, private readonly string $methodName) {}
{
}
/** /**
* @throws AuthorizationException * @throws AuthorizationException
@@ -74,6 +72,7 @@ class IsAllowedGroupAction implements ValidationRule
} catch (FireflyException $e) { } catch (FireflyException $e) {
Log::error($e->getTraceAsString()); Log::error($e->getTraceAsString());
} }
exit('here we are'); exit('here we are');
} }
} }

View File

@@ -78,6 +78,7 @@ trait AccountServiceTrait
// not set, so false. // not set, so false.
return false; return false;
} }
// if is set, but is empty: // if is set, but is empty:
return (array_key_exists('opening_balance', $data) && '' === $data['opening_balance']) return (array_key_exists('opening_balance', $data) && '' === $data['opening_balance'])
|| (array_key_exists('opening_balance_date', $data) && '' === $data['opening_balance_date']); || (array_key_exists('opening_balance_date', $data) && '' === $data['opening_balance_date']);

View File

@@ -41,9 +41,9 @@ use Illuminate\Support\Facades\Log;
class CreditRecalculateService class CreditRecalculateService
{ {
private ?Account $account = null; private ?Account $account = null;
private ?TransactionGroup $group = null; private ?TransactionGroup $group = null;
private AccountRepositoryInterface $repository; private AccountRepositoryInterface $repository;
private array $work = []; private array $work = [];
public function recalculate(): void public function recalculate(): void
{ {

View File

@@ -105,6 +105,7 @@ class GroupUpdateService
$result = array_diff($existing, $updated); $result = array_diff($existing, $updated);
Log::debug('Result of DIFF: ', $result); Log::debug('Result of DIFF: ', $result);
/** @var string $deletedId */ /** @var string $deletedId */
foreach ($result as $deletedId) { foreach ($result as $deletedId) {
/** @var TransactionJournal $journal */ /** @var TransactionJournal $journal */

View File

@@ -63,11 +63,11 @@ class JournalUpdateService
private CurrencyRepositoryInterface $currencyRepository; private CurrencyRepositoryInterface $currencyRepository;
private TransactionGroupRepositoryInterface $transactionGroupRepository; private TransactionGroupRepositoryInterface $transactionGroupRepository;
private array $data; private array $data;
private ?Account $destinationAccount = null; private ?Account $destinationAccount = null;
private ?Transaction $destinationTransaction = null; private ?Transaction $destinationTransaction = null;
private array $metaDate = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', private array $metaDate = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date',
'invoice_date', ]; 'invoice_date', ];
private array $metaString = [ private array $metaString = [
'sepa_cc', 'sepa_cc',
'sepa_ct_op', 'sepa_ct_op',
'sepa_ct_id', 'sepa_ct_id',
@@ -82,11 +82,11 @@ class JournalUpdateService
'external_id', 'external_id',
'external_url', 'external_url',
]; ];
private ?Account $sourceAccount = null; private ?Account $sourceAccount = null;
private ?Transaction $sourceTransaction = null; private ?Transaction $sourceTransaction = null;
private ?TransactionGroup $transactionGroup = null; private ?TransactionGroup $transactionGroup = null;
private ?TransactionJournal $transactionJournal = null; private ?TransactionJournal $transactionJournal = null;
private string $startCompareHash = ''; private string $startCompareHash = '';
/** /**
* JournalUpdateService constructor. * JournalUpdateService constructor.

View File

@@ -31,7 +31,6 @@ use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
/** /**

View File

@@ -39,7 +39,7 @@ use Illuminate\Support\Facades\Log;
*/ */
class FrontpageChartGenerator class FrontpageChartGenerator
{ {
public bool $convertToPrimary = false; public bool $convertToPrimary = false;
public TransactionCurrency $default; public TransactionCurrency $default;
protected OperationsRepositoryInterface $opsRepository; protected OperationsRepositoryInterface $opsRepository;
private readonly BudgetLimitRepositoryInterface $blRepository; private readonly BudgetLimitRepositoryInterface $blRepository;
@@ -53,9 +53,9 @@ class FrontpageChartGenerator
*/ */
public function __construct() public function __construct()
{ {
$this->budgetRepository = app(BudgetRepositoryInterface::class); $this->budgetRepository = app(BudgetRepositoryInterface::class);
$this->blRepository = app(BudgetLimitRepositoryInterface::class); $this->blRepository = app(BudgetLimitRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class); $this->opsRepository = app(OperationsRepositoryInterface::class);
} }
/** /**

View File

@@ -45,7 +45,7 @@ class FrontpageChartGenerator
public bool $convertToPrimary = false; public bool $convertToPrimary = false;
public TransactionCurrency $primaryCurrency; public TransactionCurrency $primaryCurrency;
private AccountRepositoryInterface $accountRepos; private AccountRepositoryInterface $accountRepos;
private array $currencies = []; private array $currencies = [];
private NoCategoryRepositoryInterface $noCatRepos; private NoCategoryRepositoryInterface $noCatRepos;
private OperationsRepositoryInterface $opsRepos; private OperationsRepositoryInterface $opsRepos;
private CategoryRepositoryInterface $repository; private CategoryRepositoryInterface $repository;

View File

@@ -31,20 +31,20 @@ use Carbon\Carbon;
*/ */
abstract class AbstractCronjob abstract class AbstractCronjob
{ {
public bool $jobErrored = false; public bool $jobErrored = false;
public bool $jobFired = false; public bool $jobFired = false;
public bool $jobSucceeded = false; public bool $jobSucceeded = false;
public ?string $message = null; public ?string $message = null;
public int $timeBetweenRuns = 43200; public int $timeBetweenRuns = 43200;
protected Carbon $date; protected Carbon $date;
protected bool $force = false; protected bool $force = false;
/** /**
* AbstractCronjob constructor. * AbstractCronjob constructor.
*/ */
public function __construct() public function __construct()
{ {
$this->date = today(config('app.timezone')); $this->date = today(config('app.timezone'));
} }
abstract public function fire(): void; abstract public function fire(): void;

View File

@@ -225,6 +225,8 @@ class ExpandedForm
} }
/** /**
* @param null|mixed $value
*
* @throws FireflyException * @throws FireflyException
*/ */
public function objectGroup($value = null, ?array $options = null): string public function objectGroup($value = null, ?array $options = null): string

View File

@@ -72,18 +72,18 @@ class ExportDataGenerator
{ {
use ConvertsDataTypes; use ConvertsDataTypes;
private const string ADD_RECORD_ERR = 'Could not add record to set: %s'; private const string ADD_RECORD_ERR = 'Could not add record to set: %s';
private const string EXPORT_ERR = 'Could not export to string: %s'; private const string EXPORT_ERR = 'Could not export to string: %s';
private Collection $accounts; private Collection $accounts;
private Carbon $end; private Carbon $end;
private bool $exportAccounts = false; private bool $exportAccounts = false;
private bool $exportBills = false; private bool $exportBills = false;
private bool $exportBudgets = false; private bool $exportBudgets = false;
private bool $exportCategories = false; private bool $exportCategories = false;
private bool $exportPiggies = false; private bool $exportPiggies = false;
private bool $exportRecurring = false; private bool $exportRecurring = false;
private bool $exportRules = false; private bool $exportRules = false;
private bool $exportTags = false; private bool $exportTags = false;
private bool $exportTransactions = false; private bool $exportTransactions = false;
private Carbon $start; private Carbon $start;
private User $user; private User $user;
@@ -91,10 +91,10 @@ class ExportDataGenerator
public function __construct() public function __construct()
{ {
$this->accounts = new Collection(); $this->accounts = new Collection();
$this->start = today(config('app.timezone')); $this->start = today(config('app.timezone'));
$this->start->subYear(); $this->start->subYear();
$this->end = today(config('app.timezone')); $this->end = today(config('app.timezone'));
} }
/** /**

View File

@@ -52,7 +52,7 @@ class AccountBalanceGrouped
public function __construct() public function __construct()
{ {
$this->converter = app(ExchangeRateConverter::class); $this->converter = app(ExchangeRateConverter::class);
} }
/** /**

View File

@@ -31,12 +31,12 @@ use Illuminate\Support\Facades\Log;
class SummaryBalanceGrouped class SummaryBalanceGrouped
{ {
private const string SUM = 'sum'; private const string SUM = 'sum';
private array $amounts = []; private array $amounts = [];
private array $currencies = []; private array $currencies = [];
private readonly CurrencyRepositoryInterface $currencyRepository; private readonly CurrencyRepositoryInterface $currencyRepository;
private TransactionCurrency $default; private TransactionCurrency $default;
private array $keys = [self::SUM]; private array $keys = [self::SUM];
public function __construct() public function __construct()
{ {

View File

@@ -132,6 +132,7 @@ trait RequestInformation
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) { if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
return true; return true;
} }
// start and end in the past? use $end // start and end in the past? use $end
return $start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date); return $start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date);
} }

View File

@@ -83,12 +83,10 @@ class BudgetLimitEnrichment implements EnrichmentInterface
public function setUser(User $user): void public function setUser(User $user): void
{ {
$this->user = $user; $this->user = $user;
} }
public function setUserGroup(UserGroup $userGroup): void public function setUserGroup(UserGroup $userGroup): void {}
{
}
private function appendCollectedData(): void private function appendCollectedData(): void
{ {

View File

@@ -90,9 +90,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
$this->setUserGroup($user->userGroup); $this->setUserGroup($user->userGroup);
} }
public function setUserGroup(UserGroup $userGroup): void public function setUserGroup(UserGroup $userGroup): void {}
{
}
private function appendCollectedData(): void private function appendCollectedData(): void
{ {

View File

@@ -78,9 +78,7 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
$this->setUserGroup($user->userGroup); $this->setUserGroup($user->userGroup);
} }
public function setUserGroup(UserGroup $userGroup): void public function setUserGroup(UserGroup $userGroup): void {}
{
}
private function appendCollectedData(): void private function appendCollectedData(): void
{ {

View File

@@ -163,12 +163,10 @@ class SubscriptionEnrichment implements EnrichmentInterface
public function setUser(User $user): void public function setUser(User $user): void
{ {
$this->user = $user; $this->user = $user;
} }
public function setUserGroup(UserGroup $userGroup): void public function setUserGroup(UserGroup $userGroup): void {}
{
}
/** /**
* Returns the latest date in the set, or start when set is empty. * Returns the latest date in the set, or start when set is empty.

View File

@@ -94,13 +94,9 @@ class TransactionGroupEnrichment implements EnrichmentInterface
throw new FireflyException('Cannot enrich single model.'); throw new FireflyException('Cannot enrich single model.');
} }
public function setUser(User $user): void public function setUser(User $user): void {}
{
}
public function setUserGroup(UserGroup $userGroup): void public function setUserGroup(UserGroup $userGroup): void {}
{
}
private function appendCollectedData(): void private function appendCollectedData(): void
{ {

View File

@@ -73,13 +73,9 @@ class WebhookEnrichment implements EnrichmentInterface
return $collection->first(); return $collection->first();
} }
public function setUser(User $user): void public function setUser(User $user): void {}
{
}
public function setUserGroup(UserGroup $userGroup): void public function setUserGroup(UserGroup $userGroup): void {}
{
}
private function appendCollectedInfo(): void private function appendCollectedInfo(): void
{ {

View File

@@ -64,6 +64,7 @@ class ParseDateString
if ('xxxx-xx-xx' === strtolower($date)) { if ('xxxx-xx-xx' === strtolower($date)) {
return false; return false;
} }
// no x'es // no x'es
return !(!str_contains($date, 'xx') && !str_contains($date, 'xxxx')); return !(!str_contains($date, 'xx') && !str_contains($date, 'xxxx'));
} }

View File

@@ -51,9 +51,11 @@ trait AppendsLocationData
/** /**
* Abstract method stolen from "InteractsWithInput". * Abstract method stolen from "InteractsWithInput".
* *
* @param bool $default * @param bool $default
* @param null|mixed $key
* *
* @return mixed * @return mixed
*
* @SuppressWarnings("PHPMD.BooleanArgumentFlag") * @SuppressWarnings("PHPMD.BooleanArgumentFlag")
*/ */
abstract public function boolean($key = null, $default = false); abstract public function boolean($key = null, $default = false);

View File

@@ -274,6 +274,7 @@ trait ConvertsDataTypes
if ('y' === $value) { if ('y' === $value) {
return true; return true;
} }
return '1' === $value; return '1' === $value;
} }

View File

@@ -47,7 +47,7 @@ class AccountSearch implements GenericSearchInterface
public const string SEARCH_NUMBER = 'number'; public const string SEARCH_NUMBER = 'number';
private string $field; private string $field;
private string $query; private string $query;
private array $types = []; private array $types = [];
private User $user; private User $user;
public function search(): Collection public function search(): Collection

View File

@@ -66,19 +66,19 @@ class OperatorQuerySearch implements SearchInterface
private readonly CategoryRepositoryInterface $categoryRepository; private readonly CategoryRepositoryInterface $categoryRepository;
private GroupCollectorInterface $collector; private GroupCollectorInterface $collector;
private readonly CurrencyRepositoryInterface $currencyRepository; private readonly CurrencyRepositoryInterface $currencyRepository;
private array $excludeTags = []; private array $excludeTags = [];
private array $includeAnyTags = []; private array $includeAnyTags = [];
// added to fix #8632 // added to fix #8632
private array $includeTags = []; private array $includeTags = [];
private array $invalidOperators = []; private array $invalidOperators = [];
private int $limit = 25; private int $limit = 25;
private readonly Collection $operators; private readonly Collection $operators;
private int $page = 1; private int $page = 1;
private array $prohibitedWords = []; private array $prohibitedWords = [];
private readonly float $startTime; private readonly float $startTime;
private readonly TagRepositoryInterface $tagRepository; private readonly TagRepositoryInterface $tagRepository;
private readonly array $validOperators; private readonly array $validOperators;
private array $words = []; private array $words = [];
/** /**
* OperatorQuerySearch constructor. * OperatorQuerySearch constructor.

View File

@@ -291,20 +291,20 @@ class Steam
} }
#[Deprecated(message: <<<'TXT' #[Deprecated(message: <<<'TXT'
By default this method returns "smaller than or equal to", so be careful with END OF DAY. By default this method returns "smaller than or equal to", so be careful with END OF DAY.
If you need end of day balance, use "inclusive = false". If you need end of day balance, use "inclusive = false".
Returns the balance of an account at exact moment given. Array with at least one value. Returns the balance of an account at exact moment given. Array with at least one value.
Always returns: Always returns:
"balance": balance in the account's currency OR user's primary currency if the account has no currency "balance": balance in the account's currency OR user's primary currency if the account has no currency
"EUR": balance in EUR (or whatever currencies the account has balance in) "EUR": balance in EUR (or whatever currencies the account has balance in)
If the user has $convertToPrimary: If the user has $convertToPrimary:
"balance": balance in the account's currency OR user's primary currency if the account has no currency "balance": balance in the account's currency OR user's primary currency if the account has no currency
--> "pc_balance": balance in the user's primary currency, with all amounts converted to the primary currency. --> "pc_balance": balance in the user's primary currency, with all amounts converted to the primary currency.
"EUR": balance in EUR (or whatever currencies the account has balance in) "EUR": balance in EUR (or whatever currencies the account has balance in)
TXT)] TXT)]
public function finalAccountBalance(Account $account, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null, bool $inclusive = true): array public function finalAccountBalance(Account $account, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null, bool $inclusive = true): array
{ {

View File

@@ -74,6 +74,7 @@ class OAuthKeys
Log::error($e->getTraceAsString()); Log::error($e->getTraceAsString());
} }
} }
return '' !== $privateKey && '' !== $publicKey; return '' !== $privateKey && '' !== $publicKey;
} }

View File

@@ -292,6 +292,7 @@ class General extends AbstractExtension
'hasRole', 'hasRole',
static function (string $role): bool { static function (string $role): bool {
$repository = app(UserRepositoryInterface::class); $repository = app(UserRepositoryInterface::class);
return $repository->hasRole(auth()->user(), $role); return $repository->hasRole(auth()->user(), $role);
} }
); );

View File

@@ -81,7 +81,7 @@ class TransactionGroupTwig extends AbstractExtension
{ {
return new TwigFunction( return new TwigFunction(
'journalGetMetaDate', 'journalGetMetaDate',
static function (int $journalId, string $metaField): CarbonInterface|Carbon { static function (int $journalId, string $metaField): Carbon|CarbonInterface {
/** @var null|TransactionJournalMeta $entry */ /** @var null|TransactionJournalMeta $entry */
$entry = DB::table('journal_meta') $entry = DB::table('journal_meta')
->where('name', $metaField) ->where('name', $metaField)

View File

@@ -59,7 +59,7 @@ class Translation extends AbstractExtension
{ {
return new TwigFunction( return new TwigFunction(
'journalLinkTranslation', 'journalLinkTranslation',
static function (string $direction, string $original): string|Translator|array { static function (string $direction, string $original): array|string|Translator {
$key = sprintf('firefly.%s_%s', $original, $direction); $key = sprintf('firefly.%s_%s', $original, $direction);
$translation = trans($key); $translation = trans($key);
if ($key === $translation) { if ($key === $translation) {
@@ -76,7 +76,7 @@ class Translation extends AbstractExtension
{ {
return new TwigFunction( return new TwigFunction(
'__', '__',
static function (string $key): string|Translator|array { static function (string $key): array|string|Translator {
$translation = trans($key); $translation = trans($key);
if ($key === $translation) { if ($key === $translation) {
return $key; return $key;

View File

@@ -45,17 +45,17 @@ use Illuminate\Support\Facades\Log;
class SearchRuleEngine implements RuleEngineInterface class SearchRuleEngine implements RuleEngineInterface
{ {
private readonly Collection $groups; private readonly Collection $groups;
private array $operators = []; private array $operators = [];
// always collect the triggers from the database, unless indicated otherwise. // always collect the triggers from the database, unless indicated otherwise.
private bool $refreshTriggers = true; private bool $refreshTriggers = true;
private array $resultCount = []; private array $resultCount = [];
private readonly Collection $rules; private readonly Collection $rules;
private User $user; private User $user;
public function __construct() public function __construct()
{ {
$this->rules = new Collection(); $this->rules = new Collection();
$this->groups = new Collection(); $this->groups = new Collection();
} }
public function addOperator(array $operator): void public function addOperator(array $operator): void

View File

@@ -259,6 +259,7 @@ class TransactionGroupTransformer extends AbstractTransformer
return (string) $array[$key]; return (string) $array[$key];
} }
return $default; return $default;
} }

View File

@@ -36,8 +36,8 @@ use Illuminate\Support\Collection;
*/ */
class UserGroupTransformer extends AbstractTransformer class UserGroupTransformer extends AbstractTransformer
{ {
private array $inUse = []; private array $inUse = [];
private array $memberships = []; private array $memberships = [];
private array $membershipsVisible = []; private array $membershipsVisible = [];
public function collectMetaData(Collection $objects): Collection public function collectMetaData(Collection $objects): Collection

View File

@@ -50,10 +50,10 @@ class AccountValidator
use TransferValidation; use TransferValidation;
use WithdrawalValidation; use WithdrawalValidation;
public bool $createMode = false; public bool $createMode = false;
public string $destError = 'No error yet.'; public string $destError = 'No error yet.';
public ?Account $destination = null; public ?Account $destination = null;
public ?Account $source = null; public ?Account $source = null;
public string $sourceError = 'No error yet.'; public string $sourceError = 'No error yet.';
private AccountRepositoryInterface $accountRepository; private AccountRepositoryInterface $accountRepository;
private array $combinations; private array $combinations;
@@ -230,6 +230,7 @@ class AccountValidator
protected function canCreateType(string $accountType): bool protected function canCreateType(string $accountType): bool
{ {
$canCreate = [AccountTypeEnum::EXPENSE->value, AccountTypeEnum::REVENUE->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value]; $canCreate = [AccountTypeEnum::EXPENSE->value, AccountTypeEnum::REVENUE->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value];
return in_array($accountType, $canCreate, true); return in_array($accountType, $canCreate, true);
} }

View File

@@ -123,6 +123,7 @@ class FireflyValidator extends Validator
} }
$regex = '/^[a-z]{6}[0-9a-z]{2}([0-9a-z]{3})?\z/i'; $regex = '/^[a-z]{6}[0-9a-z]{2}([0-9a-z]{3})?\z/i';
$result = preg_match($regex, $value); $result = preg_match($regex, $value);
return 0 !== $result; return 0 !== $result;
} }

View File

@@ -302,6 +302,7 @@ trait TransactionValidation
private function isLiability(Account $account): bool private function isLiability(Account $account): bool
{ {
$type = $account->accountType->type; $type = $account->accountType->type;
return in_array($type, config('firefly.valid_liabilities'), true); return in_array($type, config('firefly.valid_liabilities'), true);
} }
@@ -323,6 +324,7 @@ trait TransactionValidation
if ('' === $transaction['foreign_amount']) { if ('' === $transaction['foreign_amount']) {
return false; return false;
} }
return 0 !== bccomp('0', (string) $transaction['foreign_amount']); return 0 !== bccomp('0', (string) $transaction['foreign_amount']);
} }
@@ -750,6 +752,7 @@ trait TransactionValidation
// source ID's are equal, return void. // source ID's are equal, return void.
return true; return true;
} }
// source names are equal, return void. // source names are equal, return void.
return (bool) $this->arrayEqual($comparison['source_name']); return (bool) $this->arrayEqual($comparison['source_name']);
} }
@@ -765,6 +768,7 @@ trait TransactionValidation
// destination ID's are equal, return void. // destination ID's are equal, return void.
return true; return true;
} }
// destination names are equal, return void. // destination names are equal, return void.
return (bool) $this->arrayEqual($comparison['destination_name']); return (bool) $this->arrayEqual($comparison['destination_name']);
} }
@@ -783,6 +787,7 @@ trait TransactionValidation
// destination ID's are equal, return void. // destination ID's are equal, return void.
return true; return true;
} }
// destination names are equal, return void. // destination names are equal, return void.
return (bool) $this->arrayEqual($comparison['destination_name']); return (bool) $this->arrayEqual($comparison['destination_name']);
} }

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false), 'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag. // see cer.php for exchange rates feature flag.
], ],
'version' => '6.4.6', 'version' => 'develop/2025-11-09',
'build_time' => 1762641809, 'build_time' => 1762675805,
'api_version' => '2.1.0', // field is no longer used. 'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used. 'db_version' => 28, // field is no longer used.