Compare commits

..

30 Commits

Author SHA1 Message Date
github-actions[bot]
1047e3290b Merge pull request #11886 from firefly-iii/release-1772780441
🤖 Automatically merge the PR into the develop branch.
2026-03-06 08:00:49 +01:00
JC5
8ac4c535b4 🤖 Auto commit for release 'develop' on 2026-03-06 2026-03-06 08:00:41 +01:00
James Cole
2c997d8d95 Removed last phpstan errors 2026-03-06 07:55:04 +01:00
James Cole
419382f9e0 Remove broken code. 2026-03-06 07:45:28 +01:00
James Cole
12f19c6c34 Remove all "@phpstan-ignore-line" entries. 2026-03-06 07:39:12 +01:00
github-actions[bot]
705138aa27 Merge pull request #11885 from firefly-iii/release-1772775428
🤖 Automatically merge the PR into the develop branch.
2026-03-06 06:37:15 +01:00
JC5
36d20137b2 🤖 Auto commit for release 'develop' on 2026-03-06 2026-03-06 06:37:08 +01:00
James Cole
7f08a3f594 Use safe function. 2026-03-06 06:21:36 +01:00
James Cole
a897229958 Add changelog for v6.5.4 2026-03-06 06:12:15 +01:00
James Cole
1fa4632be5 Fix transaction search. 2026-03-06 06:03:12 +01:00
James Cole
221a00a23b Add debug info to track available budget creation. 2026-03-06 05:36:05 +01:00
James Cole
09c3318408 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2026-03-05 20:50:32 +01:00
Sander Dorigo
25ba87babb Better validation for webhook URLs 2026-03-05 10:11:09 +01:00
James Cole
d7e9a42f58 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2026-03-04 20:24:25 +01:00
James Cole
8fd6d99c11 Fix date issues in piggy banks for #11873 2026-03-04 20:21:12 +01:00
github-actions[bot]
463ae00ec2 Merge pull request #11876 from firefly-iii/release-1772642273
🤖 Automatically merge the PR into the develop branch.
2026-03-04 17:38:02 +01:00
JC5
969460d271 🤖 Auto commit for release 'develop' on 2026-03-04 2026-03-04 17:37:53 +01:00
James Cole
8ecfa4b619 Fix #11873 2026-03-04 17:31:42 +01:00
James Cole
55ae86ad62 Merge branch 'main' into develop 2026-03-04 17:28:57 +01:00
github-actions[bot]
5e68d948f3 Merge pull request #11874 from firefly-iii/release-1772634907
🤖 Automatically merge the PR into the develop branch.
2026-03-04 15:35:20 +01:00
JC5
77cae13b95 🤖 Auto commit for release 'develop' on 2026-03-04 2026-03-04 15:35:07 +01:00
Sander Dorigo
49d8a3c32e Catch not numeric numbers 2026-03-04 15:25:32 +01:00
github-actions[bot]
0ad4db8a71 Merge pull request #11872 from firefly-iii/release-1772618461
🤖 Automatically merge the PR into the develop branch.
2026-03-04 11:01:10 +01:00
JC5
ed9754c8d4 🤖 Auto commit for release 'develop' on 2026-03-04 2026-03-04 11:01:01 +01:00
James Cole
7315825475 Update CI workflow to manage environment file
Copy .env.example to .env before running CI and remove .env afterward.

Signed-off-by: James Cole <james@firefly-iii.org>
2026-03-04 10:55:56 +01:00
James Cole
eea23ed756 Update composer update command in CI workflow
Removed the '--no-plugins' option from composer update command.

Signed-off-by: James Cole <james@firefly-iii.org>
2026-03-04 10:42:51 +01:00
James Cole
04875728b4 Remove staticMethod.notFound from ignoreErrors
Signed-off-by: James Cole <james@firefly-iii.org>
2026-03-04 10:42:22 +01:00
James Cole
1fa51a92c6 Ignore staticMethod.notFound error in PHPStan
Signed-off-by: James Cole <james@firefly-iii.org>
2026-03-04 10:24:47 +01:00
Sander Dorigo
f8687d4fc1 New config 2026-03-04 10:01:24 +01:00
James Cole
9b5cf09cc0 Update release.yml to enforce error handling
Removed '|| true' from Mago format, PHPCS, and lint commands to ensure they fail the workflow if errors occur.

Signed-off-by: James Cole <james@firefly-iii.org>
2026-03-04 09:26:08 +01:00
102 changed files with 468 additions and 277 deletions

View File

@@ -1,15 +1,54 @@
parameters:
ergebnis:
noExtends:
enabled: false
final:
enabled: false
noParameterWithNullDefaultValue:
enabled: false
noParameterWithNullableTypeDeclaration:
enabled: false
noCompact:
enabled: false
noSwitch:
enabled: false
noNullableReturnTypeDeclaration:
enabled: false
privateInFinalClass:
enabled: false
noIsset:
enabled: false
finalInAbstractClass:
enabled: false
noConstructorParameterWithDefaultValue:
enabled: false
noNamedArgument:
enabled: false
noParameterWithContainerTypeDeclaration:
enabled: false
paths:
- ../app
- ../database
- ../routes
- ../config
- ../bootstrap/app.php
- ../bootstrap/providers.php
universalObjectCratesClasses:
- Illuminate\Database\Eloquent\Model
reportUnmatchedIgnoredErrors: true
ignoreErrors:
# these are actually interesting but not right now:
- identifier: staticMethod.dynamicCall
- identifier: argument.templateType
- identifier: method.childReturnType
- identifier: instanceof.alwaysFalse
- identifier: deadCode.unreachable
- identifier: method.dynamicName
- identifier: larastan.noEnvCallsOutsideOfConfig
- identifier: property.notFound
- identifier: arguments.count
- identifier: staticMethod.dynamicName
- identifier: catch.neverThrown
- identifier: notIdentical.alwaysTrue
- identifier: method.notFound
- identifier: nullsafe.neverNull
@@ -64,7 +103,7 @@ parameters:
path: ../app/Console/Commands/System/CreatesDatabase.php
- identifier: missingType.iterableValue # not interesting enough to fix.
- identifier: varTag.type # needs a custom extension for every repository, not gonna happen.
- '#Dynamic call to static method Illuminate#'
# - '#Dynamic call to static method Illuminate#'
# - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::before#' # is custom scope
# - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::after#' # is custom scope
# - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::withTrashed#' # is to allow soft delete

View File

@@ -174,22 +174,24 @@ jobs:
uses: nhedger/setup-mago@v1
- name: Run CI
run: |
cp .env.example .env
# install all packages etc.
rm -rf vendor composer.lock
composer update --no-scripts --no-plugins -q
composer update --no-scripts -q
# format code.
echo "Will now run Mago Format"
mago format || true
mago format
sudo chown -R runner:docker resources/lang
echo "Will now run PHPCS"
.ci/phpcs.sh || true
.ci/phpcs.sh
# lint and check
echo "Will now run Mago Lint"
mago lint || true
mago lint
echo "Will now run PHPstan"
.ci/phpstan.sh || true
.ci/phpstan.sh
rm .env
- name: Calculate variables
run: |

View File

@@ -222,11 +222,7 @@ abstract class Controller extends BaseController
$value = min(max(1, $value), 2 ** 16);
$bag->set($integer, $value);
}
if (
null === $value
&& 'limit' === $integer // @phpstan-ignore-line
&& auth()->check()
) {
if (null === $value && 'limit' === $integer && auth()->check()) {
// set default for user:
/** @var User $user */
$user = auth()->user();

View File

@@ -256,7 +256,7 @@ final class ListController extends Controller
$unfiltered = $recurringRepos->get();
// filter selection
$collection = $unfiltered->filter(static function (Recurrence $recurrence) use ($currency): null|Recurrence { // @phpstan-ignore-line
$collection = $unfiltered->filter(static function (Recurrence $recurrence) use ($currency): null|Recurrence {
if (array_any(
$recurrence->recurrenceTransactions,
static fn ($transaction): bool => $transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id
@@ -306,7 +306,7 @@ final class ListController extends Controller
$ruleRepos = app(RuleRepositoryInterface::class);
$unfiltered = $ruleRepos->getAll();
$collection = $unfiltered->filter(static function (Rule $rule) use ($currency): null|Rule { // @phpstan-ignore-line
$collection = $unfiltered->filter(static function (Rule $rule) use ($currency): null|Rule {
if (array_any(
$rule->ruleTriggers,
static fn ($trigger): bool => 'currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value

View File

@@ -68,7 +68,7 @@ final class TransactionController extends Controller
$description = (string) $request->attributes->get('description');
Log::debug(sprintf('Include deleted? %s', var_export($includeDeleted, true)));
if ('' !== $externalId) {
$count += $this->repository->countByMeta('external_identifier', $externalId, $includeDeleted);
$count += $this->repository->countByMeta('external_id', $externalId, $includeDeleted);
Log::debug(sprintf('Search for transactions with external_identifier "%s", count is now %d', $externalId, $count));
}
if ('' !== $internalRef) {

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Requests\Models\Webhook;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Webhook;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\Webhook\IsValidWebhookUrl;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
@@ -83,7 +84,7 @@ class CreateRequest extends FormRequest
'delivery' => 'prohibited',
'deliveries' => 'required|array|min:1|max:1',
'deliveries.*' => sprintf('required|in:%s', $deliveries),
'url' => ['required', sprintf('url:%s', $validProtocols)],
'url' => ['required', sprintf('url:%s', $validProtocols), new IsValidWebhookUrl()],
];
}
}

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Requests\Models\Webhook;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Webhook;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\Webhook\IsValidWebhookUrl;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
@@ -87,7 +88,7 @@ class UpdateRequest extends FormRequest
'delivery' => 'prohibited',
'deliveries' => 'required|array|min:1|max:1',
'deliveries.*' => sprintf('required|in:%s', $deliveries),
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)],
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id), new IsValidWebhookUrl()],
];
}
}

View File

@@ -83,10 +83,10 @@ class ConvertsDatesToUTC extends Command
}
$this->friendlyInfo(sprintf('Converting field "%s" of model "%s" to UTC.', $field, $shortModel));
$items->each(static function ($item) use ($field, $timezoneField): void {
$date = Carbon::parse($item->{$field}, $item->{$timezoneField}); // @phpstan-ignore-line
$date = Carbon::parse($item->{$field}, $item->{$timezoneField});
$date->setTimezone('UTC');
$item->{$field} = $date->format('Y-m-d H:i:s'); // @phpstan-ignore-line
$item->{$timezoneField} = 'UTC'; // @phpstan-ignore-line
$item->{$field} = $date->format('Y-m-d H:i:s');
$item->{$timezoneField} = 'UTC';
$item->save();
});
}

View File

@@ -322,12 +322,7 @@ class CorrectsUnevenAmount extends Command
foreach ($journals as $entry) {
$sum = (string) $entry->the_sum;
$sum = Steam::floatalize($sum);
if (
!is_numeric($sum)
|| '' === $sum // @phpstan-ignore-line
|| str_contains($sum, 'e')
|| str_contains($sum, ',')
) {
if (!is_numeric($sum) || '' === $sum || str_contains($sum, 'e') || str_contains($sum, ',')) {
$message = sprintf('Journal #%d has an invalid sum ("%s"). No sure what to do.', $entry->transaction_journal_id, $entry->the_sum);
$this->friendlyWarning($message);
Log::warning($message);

View File

@@ -57,7 +57,7 @@ class VerifySecurityAlerts extends Command
$version = config('firefly.version');
$disk = Storage::disk('resources');
// Next line is ignored because it's a Laravel Facade.
if (!$disk->has('alerts.json')) { // @phpstan-ignore-line
if (!$disk->has('alerts.json')) {
Log::debug('No alerts.json file present.');
return 0;

View File

@@ -70,7 +70,7 @@ class Cron extends Command
} catch (InvalidArgumentException $e) {
$this->friendlyError(sprintf('"%s" is not a valid date', $this->option('date')));
}
$force = (bool) $this->option('force'); // @phpstan-ignore-line
$force = (bool) $this->option('force');
// Fire exchange rates cron job.
if (true === FireflyConfig::get('enable_external_rates', config('cer.download_enabled'))->data && ($doAll || $this->option('download-cer'))) {

View File

@@ -68,7 +68,7 @@ class RemovesDatabaseDecryption extends Command
* @var string $table
* @var array $fields
*/
foreach ($tables as $table => $fields) { // @phpstan-ignore-line
foreach ($tables as $table => $fields) {
$this->decryptTable($table, $fields);
}

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Events\Model\BudgetLimit;
use FireflyIII\Events\Event;
use FireflyIII\Models\BudgetLimit;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class CreatedBudgetLimit extends Event
{
@@ -35,5 +36,7 @@ class CreatedBudgetLimit extends Event
public function __construct(
public BudgetLimit $budgetLimit,
public bool $createWebhookMessages
) {}
) {
Log::debug(sprintf('CreatedNewBudgetLimit(#%d) Event', $budgetLimit->id));
}
}

View File

@@ -29,6 +29,7 @@ use FireflyIII\Events\Event;
use FireflyIII\Models\Budget;
use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class DestroyedBudgetLimit extends Event
{
@@ -40,5 +41,7 @@ class DestroyedBudgetLimit extends Event
public Carbon $start,
public Carbon $end,
public bool $createWebhookMessages
) {}
) {
Log::debug(sprintf('DestroyedBudgetLimit(#%d) Event', $budget->id));
}
}

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Events\Model\BudgetLimit;
use FireflyIII\Events\Event;
use FireflyIII\Models\BudgetLimit;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class UpdatedBudgetLimit extends Event
{
@@ -35,5 +36,7 @@ class UpdatedBudgetLimit extends Event
public function __construct(
public BudgetLimit $budgetLimit,
public bool $createWebhookMessages
) {}
) {
Log::debug(sprintf('UpdatedBudgetLimit(#%d) Event', $budgetLimit->id));
}
}

View File

@@ -574,14 +574,14 @@ class TransactionJournalFactory
return [$sourceAccount, $account];
}
if (!$sourceAccount instanceof Account) { // @phpstan-ignore-line
if (!$sourceAccount instanceof Account) {
Log::debug('Source account is NULL, destination account is not.');
$account = $this->accountRepository->getReconciliation($destinationAccount);
Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type));
return [$account, $destinationAccount];
}
Log::debug('Unused fallback'); // @phpstan-ignore-line
Log::debug('Unused fallback');
return [$sourceAccount, $destinationAccount];
}

View File

@@ -178,7 +178,7 @@ trait AccountCollection
{
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$this->query->where(static function (EloquentBuilder $query) use ($accountIds): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $query) use ($accountIds): void {
$query->whereIn('source.account_id', $accountIds);
$query->orWhereIn('destination.account_id', $accountIds);
});
@@ -196,7 +196,7 @@ trait AccountCollection
{
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$this->query->where(static function (EloquentBuilder $query) use ($accountIds): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $query) use ($accountIds): void {
$query->whereIn('source.account_id', $accountIds);
$query->whereIn('destination.account_id', $accountIds);
});
@@ -228,7 +228,7 @@ trait AccountCollection
{
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$this->query->where(static function (EloquentBuilder $query) use ($accountIds): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $query) use ($accountIds): void {
$query->whereNotIn('source.account_id', $accountIds);
$query->whereNotIn('destination.account_id', $accountIds);
});
@@ -261,7 +261,7 @@ trait AccountCollection
{
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$this->query->where(static function (EloquentBuilder $q1) use ($accountIds): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q1) use ($accountIds): void {
// sourceAccount is in the set, and destination is NOT.
$q1->where(static function (EloquentBuilder $q2) use ($accountIds): void {

View File

@@ -38,7 +38,7 @@ trait AmountCollection
*/
public function amountIs(string $amount): GroupCollectorInterface
{
$this->query->where(static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($amount): void {
$q->where('source.amount', Steam::negative($amount));
});
@@ -47,7 +47,7 @@ trait AmountCollection
public function amountIsNot(string $amount): GroupCollectorInterface
{
$this->query->where(static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($amount): void {
$q->where('source.amount', '!=', Steam::negative($amount));
});
@@ -59,7 +59,7 @@ trait AmountCollection
*/
public function amountLess(string $amount): GroupCollectorInterface
{
$this->query->where(static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($amount): void {
$q->where('destination.amount', '<=', Steam::positive($amount));
});
@@ -71,7 +71,7 @@ trait AmountCollection
*/
public function amountMore(string $amount): GroupCollectorInterface
{
$this->query->where(static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($amount): void {
$q->where('destination.amount', '>=', Steam::positive($amount));
});
@@ -83,7 +83,7 @@ trait AmountCollection
*/
public function foreignAmountIs(string $amount): GroupCollectorInterface
{
$this->query->where(static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($amount): void {
$q->whereNotNull('source.foreign_amount');
$q->where('source.foreign_amount', Steam::negative($amount));
});
@@ -96,7 +96,7 @@ trait AmountCollection
*/
public function foreignAmountIsNot(string $amount): GroupCollectorInterface
{
$this->query->where(static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($amount): void {
$q->whereNull('source.foreign_amount');
$q->orWhere('source.foreign_amount', '!=', Steam::negative($amount));
});
@@ -109,7 +109,7 @@ trait AmountCollection
*/
public function foreignAmountLess(string $amount): GroupCollectorInterface
{
$this->query->where(static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($amount): void {
$q->whereNotNull('destination.foreign_amount');
$q->where('destination.foreign_amount', '<=', Steam::positive($amount));
});
@@ -122,7 +122,7 @@ trait AmountCollection
*/
public function foreignAmountMore(string $amount): GroupCollectorInterface
{
$this->query->where(static function (EloquentBuilder $q) use ($amount): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($amount): void {
$q->whereNotNull('destination.foreign_amount');
$q->where('destination.foreign_amount', '>=', Steam::positive($amount));
});

View File

@@ -483,7 +483,7 @@ trait AttachmentCollection
Log::debug('Add filter on no attachments.');
$this->joinAttachmentTables();
$this->query->where(static function (EloquentBuilder $q1): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q1): void {
$q1->whereNull('attachments.attachable_id')->orWhere(static function (EloquentBuilder $q2): void {
$q2->whereNotNull('attachments.attachable_id')->whereNotNull('attachments.deleted_at');
@@ -517,7 +517,7 @@ trait AttachmentCollection
$this->hasJoinedAttTables = true;
$this->query
->leftJoin('attachments', 'attachments.attachable_id', '=', 'transaction_journals.id')
->where(static function (EloquentBuilder $q1): void { // @phpstan-ignore-line
->where(static function (EloquentBuilder $q1): void {
$q1->where('attachments.attachable_type', TransactionJournal::class);
// $q1->where('attachments.uploaded', true);
// $q1->whereNull('attachments.deleted_at');

View File

@@ -46,7 +46,7 @@ trait MetaCollection
public function excludeBills(Collection $bills): GroupCollectorInterface
{
$this->withBillInformation();
$this->query->where(static function (EloquentBuilder $q1) use ($bills): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q1) use ($bills): void {
$q1->whereNotIn('transaction_journals.bill_id', $bills->pluck('id')->toArray());
$q1->orWhereNull('transaction_journals.bill_id');
});
@@ -61,7 +61,7 @@ trait MetaCollection
{
$this->withBudgetInformation();
$this->query->where(static function (EloquentBuilder $q2) use ($budget): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q2) use ($budget): void {
$q2->where('budgets.id', '!=', $budget->id);
$q2->orWhereNull('budgets.id');
});
@@ -73,7 +73,7 @@ trait MetaCollection
{
if ($budgets->count() > 0) {
$this->withBudgetInformation();
$this->query->where(static function (EloquentBuilder $q1) use ($budgets): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q1) use ($budgets): void {
$q1->whereNotIn('budgets.id', $budgets->pluck('id')->toArray());
$q1->orWhereNull('budgets.id');
});
@@ -86,7 +86,7 @@ trait MetaCollection
{
if ($categories->count() > 0) {
$this->withCategoryInformation();
$this->query->where(static function (EloquentBuilder $q1) use ($categories): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q1) use ($categories): void {
$q1->whereNotIn('categories.id', $categories->pluck('id')->toArray());
$q1->orWhereNull('categories.id');
});
@@ -102,7 +102,7 @@ trait MetaCollection
{
$this->withCategoryInformation();
$this->query->where(static function (EloquentBuilder $q2) use ($category): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q2) use ($category): void {
$q2->where('categories.id', '!=', $category->id);
$q2->orWhereNull('categories.id');
});
@@ -394,7 +394,7 @@ trait MetaCollection
public function notesDoNotContain(string $value): GroupCollectorInterface
{
$this->withNotes();
$this->query->where(static function (EloquentBuilder $q) use ($value): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($value): void {
$q->whereNull('notes.text');
$q->orWhereNotLike('notes.text', sprintf('%%%s%%', $value));
});
@@ -405,7 +405,7 @@ trait MetaCollection
public function notesDontEndWith(string $value): GroupCollectorInterface
{
$this->withNotes();
$this->query->where(static function (EloquentBuilder $q) use ($value): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($value): void {
$q->whereNull('notes.text');
$q->orWhereNotLike('notes.text', sprintf('%%%s', $value));
});
@@ -416,7 +416,7 @@ trait MetaCollection
public function notesDontStartWith(string $value): GroupCollectorInterface
{
$this->withNotes();
$this->query->where(static function (EloquentBuilder $q) use ($value): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($value): void {
$q->whereNull('notes.text');
$q->orWhereNotLike('notes.text', sprintf('%s%%', $value));
});
@@ -443,7 +443,7 @@ trait MetaCollection
public function notesExactlyNot(string $value): GroupCollectorInterface
{
$this->withNotes();
$this->query->where(static function (EloquentBuilder $q) use ($value): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q) use ($value): void {
$q->whereNull('notes.text');
$q->orWhere('notes.text', '!=', $value);
});
@@ -889,7 +889,7 @@ trait MetaCollection
{
$this->joinMetaDataTables();
// TODO not sure if this will work properly.
$this->query->where(static function (EloquentBuilder $q1): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q1): void {
$q1->where(static function (EloquentBuilder $q2): void {
$q2->where('journal_meta.name', '=', 'external_id');
$q2->whereNull('journal_meta.data');
@@ -910,7 +910,7 @@ trait MetaCollection
{
$this->joinMetaDataTables();
// TODO not sure if this will work properly.
$this->query->where(static function (EloquentBuilder $q1): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q1): void {
$q1->where(static function (EloquentBuilder $q2): void {
$q2->where('journal_meta.name', '=', 'external_url');
$q2->whereNull('journal_meta.data');
@@ -930,7 +930,7 @@ trait MetaCollection
public function withoutNotes(): GroupCollectorInterface
{
$this->withNotes();
$this->query->where(static function (EloquentBuilder $q): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q): void {
$q->whereNull('notes.text');
$q->orWhere('notes.text', '');
});

View File

@@ -314,7 +314,7 @@ class GroupCollector implements GroupCollectorInterface
public function excludeForeignCurrency(TransactionCurrency $currency): GroupCollectorInterface
{
$this->query->where(static function (EloquentBuilder $q2) use ($currency): void { // @phpstan-ignore-line
$this->query->where(static function (EloquentBuilder $q2) use ($currency): void {
$q2->where('source.foreign_currency_id', '!=', $currency->id);
$q2->orWhereNull('source.foreign_currency_id');
});
@@ -698,7 +698,7 @@ class GroupCollector implements GroupCollectorInterface
*/
foreach ($this->sorting as $field => $direction) {
$func = 'ASC' === $direction ? 'sortBy' : 'sortByDesc';
$collection = $collection->{$func}(static function (array $product, int $key) use ($field) { // @phpstan-ignore-line
$collection = $collection->{$func}(static function (array $product, int $key) use ($field) {
// depends on $field:
if ('description' === $field) {
if (1 === count($product['transactions'])) {

View File

@@ -135,7 +135,7 @@ final class ExpenseReportController extends Controller
while ($currentStart < $end) {
$currentEnd = clone $currentStart;
$currentEnd = $currentEnd->{$function}(); // @phpstan-ignore-line
$currentEnd = $currentEnd->{$function}();
// get expenses grouped by opposing name:
$expenses = $this->groupByName($this->getExpensesForOpposing($accounts, $all, $currentStart, $currentEnd));

View File

@@ -102,7 +102,7 @@ abstract class Controller extends BaseController
if ('true' === request()->get('force_default_layout') && 'v2' === config('view.layout')) {
// config('view.layout','v1');
Config::set('view.layout', 'v1');
View::getFinder()->setPaths([realpath(base_path('resources/views'))]); // @phpstan-ignore-line
View::getFinder()->setPaths([realpath(base_path('resources/views'))]);
}
View::share('authGuard', $authGuard);

View File

@@ -149,7 +149,7 @@ final class DebugController extends Controller
// get latest log file:
$logger = Log::driver();
// PHPstan doesn't recognize the method because of its polymorphic nature.
$handlers = $logger->getHandlers(); // @phpstan-ignore-line
$handlers = $logger->getHandlers();
$logContent = '';
foreach ($handlers as $handler) {
if ($handler instanceof RotatingFileHandler) {
@@ -323,7 +323,7 @@ final class DebugController extends Controller
private function getBuildInfo(): array
{
$return = [
'is_docker' => env('IS_DOCKER', false), // @phpstan-ignore-line
'is_docker' => env('IS_DOCKER', false),
'build' => '(unknown)',
'build_date' => '(unknown)',
'base_build' => '(unknown)',
@@ -348,11 +348,11 @@ final class DebugController extends Controller
Log::debug('Could not check build date, but thats ok.');
Log::warning($e->getMessage());
}
if ('' !== (string) env('BASE_IMAGE_BUILD')) { // @phpstan-ignore-line
$return['base_build'] = env('BASE_IMAGE_BUILD'); // @phpstan-ignore-line
if ('' !== (string) env('BASE_IMAGE_BUILD')) {
$return['base_build'] = env('BASE_IMAGE_BUILD');
}
if ('' !== (string) env('BASE_IMAGE_DATE')) { // @phpstan-ignore-line
$return['base_build_date'] = env('BASE_IMAGE_DATE'); // @phpstan-ignore-line
if ('' !== (string) env('BASE_IMAGE_DATE')) {
$return['base_build_date'] = env('BASE_IMAGE_DATE');
}
return $return;

View File

@@ -69,7 +69,7 @@ final class AmountController extends Controller
public function add(PiggyBank $piggyBank): Factory|\Illuminate\Contracts\View\View
{
/** @var Carbon $date */
$date = session('end', today(config('app.timezone')));
$date = now(config('app.timezone'));
$accounts = [];
$total = '0';
$totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank);
@@ -109,7 +109,7 @@ final class AmountController extends Controller
public function addMobile(PiggyBank $piggyBank): Factory|\Illuminate\Contracts\View\View
{
/** @var Carbon $date */
$date = session('end', today(config('app.timezone')));
$date = now(config('app.timezone'));
$accounts = [];
$total = '0';
$totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank);
@@ -143,7 +143,7 @@ final class AmountController extends Controller
/** @var Account $account */
foreach ($piggyBank->accounts as $account) {
$amount = (string) ($amounts[$account->id] ?? '0');
if ('' === $amount || 0 === bccomp($amount, '0')) {
if ('' === $amount || !is_numeric($amount) || 0 === bccomp($amount, '0')) {
continue;
}
if (-1 === bccomp($amount, '0')) {

View File

@@ -81,16 +81,6 @@ final class IndexController extends Controller
$this->piggyRepos->resetOrder();
$collection = $this->piggyRepos->getPiggyBanks();
session('end', today(config('app.timezone'))->endOfMonth());
// transform piggies using the transformer:
// $parameters = new ParameterBag();
// $parameters->set('end', $end);
// /** @var AccountTransformer $accountTransformer */
// $accountTransformer = app(AccountTransformer::class);
// $accountTransformer->setParameters($parameters);
// data
$piggyBanks = $this->groupPiggyBanks($collection);
$accounts = $this->collectAccounts($collection);
@@ -107,8 +97,8 @@ final class IndexController extends Controller
*/
public function setOrder(Request $request, PiggyBank $piggyBank): JsonResponse
{
$objectGroupTitle = (string) $request->get('objectGroupTitle');
$newOrder = (int) $request->get('order');
$objectGroupTitle = (string) $request->input('objectGroupTitle');
$newOrder = (int) $request->input('order');
$this->piggyRepos->setOrder($piggyBank, $newOrder);
if ('' !== $objectGroupTitle) {
$this->piggyRepos->setObjectGroup($piggyBank, $objectGroupTitle);
@@ -122,21 +112,15 @@ final class IndexController extends Controller
private function collectAccounts(Collection $collection): array
{
/** @var Carbon $end */
$end = session('end', today(config('app.timezone'))->endOfMonth());
// transform piggies using the transformer:
$parameters = new ParameterBag();
$parameters->set('end', $end);
$now = Carbon::now();
/** @var AccountTransformer $accountTransformer */
$accountTransformer = app(AccountTransformer::class);
$accountTransformer->setParameters($parameters);
// enrich each account.
$enrichment = new AccountEnrichment();
$enrichment->setUser(auth()->user());
$enrichment->setDate($end);
$enrichment->setDate($now);
$return = [];
/** @var PiggyBank $piggy */

View File

@@ -86,7 +86,7 @@ final class PreferencesController extends Controller
AccountTypeEnum::DEBT->value,
AccountTypeEnum::MORTGAGE->value,
]);
$isDocker = env('IS_DOCKER', false); // @phpstan-ignore-line
$isDocker = env('IS_DOCKER', false);
$groupedAccounts = [];
/** @var Account $account */

View File

@@ -42,6 +42,6 @@ final class CreateController extends Controller
$mainTitleIcon = 'fa-book';
Log::debug(sprintf('Now at %s', __METHOD__));
return view('administrations.create')->with(['title' => $title, 'subTitle' => $subTitle, 'mainTitleIcon' => $mainTitleIcon]); // @phpstan-ignore-line
return view('administrations.create')->with(['title' => $title, 'subTitle' => $subTitle, 'mainTitleIcon' => $mainTitleIcon]);
}
}

View File

@@ -67,7 +67,7 @@ class SecureHeaders
];
// overrule in development mode
if (true === env('IS_LOCAL_DEV')) { // @phpstan-ignore-line
if (true === env('IS_LOCAL_DEV')) {
$csp = [
"default-src 'none'",
"object-src 'none'",

View File

@@ -134,7 +134,7 @@ class RecurrenceFormRequest extends FormRequest
* @var int $index
* @var array $transaction
*/
foreach ($return['transactions'] as $index => $transaction) { // @phpstan-ignore-line
foreach ($return['transactions'] as $index => $transaction) {
$categoryName = $transaction['category_name'] ?? null;
if (null !== $categoryName) {
$category = $factory->findOrCreate(null, $categoryName);

View File

@@ -41,7 +41,7 @@ class ProcessesBudgetLimits implements ShouldQueue
{
public function handle(CreatedBudgetLimit|DestroyedBudgetLimit|UpdatedBudgetLimit $event): void
{
Log::debug(sprintf('Now in handle for event %s', get_class($event)));
Log::debug(sprintf('Now in ProcessesBudgetLimits::handle for event %s', get_class($event)));
if ($event instanceof DestroyedBudgetLimit && null !== $event->user) {
// need to recalculate all available budgets for this user.
$calculator = new AvailableBudgetCalculator();
@@ -70,6 +70,7 @@ class ProcessesBudgetLimits implements ShouldQueue
// do webhooks:
if ($event->createWebhookMessages) {
Log::debug('Event says to create webhook messages');
$this->createWebhookMessages($event->budgetLimit->budget->user, $event->budgetLimit->budget, WebhookTrigger::STORE_UPDATE_BUDGET_LIMIT);
}
}

View File

@@ -46,7 +46,7 @@ class OwnerNotifiable
if (method_exists($this, $method)) {
Log::debug(sprintf('Redirect for settings to "%s".', $method));
return $this->{$method}($notification); // @phpstan-ignore-line
return $this->{$method}($notification);
}
Log::debug(sprintf('No method "%s" found, return generic settings.', $method));

View File

@@ -63,7 +63,7 @@ class AccountServiceProvider extends ServiceProvider
$repository = app(AccountRepository::class);
// phpstan thinks auth does not exist.
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -75,7 +75,7 @@ class AccountServiceProvider extends ServiceProvider
$repository = app(OperationsRepository::class);
// phpstan thinks auth does not exist.
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -93,7 +93,7 @@ class AccountServiceProvider extends ServiceProvider
$tasker = app(AccountTasker::class);
// phpstan thinks auth does not exist.
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$tasker->setUser(auth()->user());
}

View File

@@ -57,7 +57,7 @@ class AdminServiceProvider extends ServiceProvider
/** @var LinkTypeRepository $repository */
$repository = app(LinkTypeRepository::class);
// reference to auth is not understood by phpstan.
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -49,7 +49,7 @@ class AttachmentServiceProvider extends ServiceProvider
/** @var AttachmentRepositoryInterface $repository */
$repository = app(AttachmentRepository::class);
// reference to auth is not understood by phpstan.
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -50,7 +50,7 @@ class BillServiceProvider extends ServiceProvider
$repository = app(BillRepository::class);
// reference to auth is not understood by phpstan.
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -59,7 +59,7 @@ class BudgetServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): BudgetRepositoryInterface {
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -70,7 +70,7 @@ class BudgetServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): AvailableBudgetRepositoryInterface {
/** @var AvailableBudgetRepositoryInterface $repository */
$repository = app(AvailableBudgetRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -81,7 +81,7 @@ class BudgetServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): BudgetLimitRepositoryInterface {
/** @var BudgetLimitRepositoryInterface $repository */
$repository = app(BudgetLimitRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -92,7 +92,7 @@ class BudgetServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): NoBudgetRepositoryInterface {
/** @var NoBudgetRepositoryInterface $repository */
$repository = app(NoBudgetRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -103,7 +103,7 @@ class BudgetServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): OperationsRepositoryInterface {
/** @var OperationsRepositoryInterface $repository */
$repository = app(OperationsRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -53,7 +53,7 @@ class CategoryServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): CategoryRepositoryInterface {
/** @var CategoryRepository $repository */
$repository = app(CategoryRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -63,7 +63,7 @@ class CategoryServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): OperationsRepositoryInterface {
/** @var OperationsRepository $repository */
$repository = app(OperationsRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -73,7 +73,7 @@ class CategoryServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): NoCategoryRepositoryInterface {
/** @var NoCategoryRepository $repository */
$repository = app(NoCategoryRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -52,7 +52,7 @@ class CurrencyServiceProvider extends ServiceProvider
/** @var CurrencyRepository $repository */
$repository = app(GroupCurrencyRepository::class);
// phpstan does not get the reference to auth
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -62,7 +62,7 @@ class CurrencyServiceProvider extends ServiceProvider
/** @var GroupCurrencyRepository $repository */
$repository = app(GroupCurrencyRepository::class);
// phpstan does not get the reference to auth
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -73,7 +73,7 @@ class CurrencyServiceProvider extends ServiceProvider
/** @var ExchangeRateRepository $repository */
$repository = app(ExchangeRateRepository::class);
// phpstan does not get the reference to auth
if ($app->auth->check()) { // @phpstan-ignore-line
if ($app->auth->check()) {
$repository->setUserGroup(auth()->user()->userGroup);
}

View File

@@ -132,7 +132,7 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): ObjectGroupRepositoryInterface {
/** @var ObjectGroupRepository $repository */
$repository = app(ObjectGroupRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -142,7 +142,7 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): PeriodStatisticRepositoryInterface {
/** @var PeriodStatisticRepository $repository */
$repository = app(PeriodStatisticRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -152,7 +152,7 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): WebhookRepositoryInterface {
/** @var WebhookRepository $repository */
$repository = app(WebhookRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -170,7 +170,7 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): RuleEngineInterface {
/** @var SearchRuleEngine $engine */
$engine = app(SearchRuleEngine::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$engine->setUser(auth()->user());
}
@@ -180,7 +180,7 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): UserGroupRepositoryInterface {
/** @var UserGroupRepository $repository */
$repository = app(UserGroupRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -63,7 +63,7 @@ class JournalServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): GroupCollectorInterface {
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollector::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$collector->setUser(auth()->user());
}
@@ -79,7 +79,7 @@ class JournalServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): TransactionGroupRepositoryInterface {
/** @var TransactionGroupRepositoryInterface $repository */
$repository = app(TransactionGroupRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -95,7 +95,7 @@ class JournalServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): JournalRepositoryInterface {
/** @var JournalRepositoryInterface $repository */
$repository = app(JournalRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -106,7 +106,7 @@ class JournalServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): JournalAPIRepositoryInterface {
/** @var JournalAPIRepositoryInterface $repository */
$repository = app(JournalAPIRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -117,7 +117,7 @@ class JournalServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): JournalCLIRepositoryInterface {
/** @var JournalCLIRepositoryInterface $repository */
$repository = app(JournalCLIRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -48,7 +48,7 @@ class PiggyBankServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): PiggyBankRepositoryInterface {
/** @var PiggyBankRepository $repository */
$repository = app(PiggyBankRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -49,7 +49,7 @@ class RecurringServiceProvider extends ServiceProvider
/** @var RecurringRepositoryInterface $repository */
$repository = app(RecurringRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -48,7 +48,7 @@ class RuleGroupServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): RuleGroupRepositoryInterface {
/** @var RuleGroupRepository $repository */
$repository = app(RuleGroupRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -48,7 +48,7 @@ class RuleServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): RuleRepositoryInterface {
/** @var RuleRepository $repository */
$repository = app(RuleRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -52,7 +52,7 @@ class SearchServiceProvider extends ServiceProvider
$this->app->bind(static function (Application $app): SearchInterface {
/** @var OperatorQuerySearch $search */
$search = app(OperatorQuerySearch::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$search->setUser(auth()->user());
}

View File

@@ -51,7 +51,7 @@ class TagServiceProvider extends ServiceProvider
/** @var TagRepository $repository */
$repository = app(TagRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}
@@ -62,7 +62,7 @@ class TagServiceProvider extends ServiceProvider
/** @var OperationsRepository $repository */
$repository = app(OperationsRepository::class);
if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth)
if ($app->auth->check()) {
$repository->setUser(auth()->user());
}

View File

@@ -271,7 +271,7 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
{
$query = $this->user
->accounts()
->with([ // @phpstan-ignore-line
->with([
'accountmeta' => static function (HasMany $query): void {
$query->where('name', 'account_role');
},
@@ -296,7 +296,7 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
/** @var Storage $disk */
$disk = Storage::disk('upload');
return $set->each(static function (Attachment $attachment) use ($disk): Attachment { // @phpstan-ignore-line
return $set->each(static function (Attachment $attachment) use ($disk): Attachment {
$notes = $attachment->notes()->first();
$attachment->file_exists = $disk->exists($attachment->fileName());
$attachment->notes_text = null !== $notes ? $notes->text : '';
@@ -335,7 +335,7 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
{
$query = $this->user
->accounts()
->with(['accountmeta' => static function (HasMany $query): void { // @phpstan-ignore-line
->with(['accountmeta' => static function (HasMany $query): void {
$query->where('name', 'account_role');
}])
;

View File

@@ -394,7 +394,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
];
$array[$currencyId]['transaction_journals'][$journalId] = [
'amount' => Steam::{$direction}((string) $journal['amount']), // @phpstan-ignore-line
'amount' => Steam::{$direction}((string) $journal['amount']),
'date' => $journal['date'],
'transaction_journal_id' => $journalId,
'budget_name' => $journal['budget_name'],

View File

@@ -187,7 +187,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
->bills()
->where('active', true)
->orderBy('bills.name', 'ASC')
->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount')]) // @phpstan-ignore-line
->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount')])
;
}
@@ -199,7 +199,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
$set = $bill->attachments()->get();
$disk = Storage::disk('upload');
return $set->each(static function (Attachment $attachment) use ($disk): Attachment { // @phpstan-ignore-line
return $set->each(static function (Attachment $attachment) use ($disk): Attachment {
$notes = $attachment->notes()->first();
$attachment->file_exists = $disk->exists($attachment->fileName());
$attachment->notes_text = null !== $notes ? $notes->text : '';

View File

@@ -126,6 +126,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup
$user = $budgetLimit->budget->user;
$start = $budgetLimit->start_date->clone();
$end = $budgetLimit->end_date->clone();
Log::debug(sprintf('Send event for DestroyedBudgetLimit (limit #%d, budget #%d)', $budgetLimit->id, $budgetLimit->budget_id));
event(new DestroyedBudgetLimit($user, $budgetLimit->budget, $start, $end, true));
$budgetLimit->delete();
event(new WebhookMessagesRequestSending());
@@ -399,6 +400,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup
if (array_key_exists('notes', $data)) {
$this->setNoteText($budgetLimit, (string) $data['notes']);
}
Log::debug(sprintf('Updated budget limit with ID #%d', $budgetLimit->id));
$generateMessages = $data['fire_webhooks'] ?? true;
event(new UpdatedBudgetLimit($budgetLimit, $generateMessages));
event(new WebhookMessagesRequestSending());

View File

@@ -345,7 +345,7 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
$disk = Storage::disk('upload');
return $set->each(static function (Attachment $attachment) use ($disk): Attachment { // @phpstan-ignore-line
return $set->each(static function (Attachment $attachment) use ($disk): Attachment {
$notes = $attachment->notes()->first();
$attachment->file_exists = $disk->exists($attachment->fileName());
$attachment->notes_text = null !== $notes ? $notes->text : '';

View File

@@ -170,7 +170,7 @@ class CategoryRepository implements CategoryRepositoryInterface, UserGroupInterf
$disk = Storage::disk('upload');
return $set->each(static function (Attachment $attachment) use ($disk): Attachment { // @phpstan-ignore-line
return $set->each(static function (Attachment $attachment) use ($disk): Attachment {
$notes = $attachment->notes()->first();
$attachment->file_exists = $disk->exists($attachment->fileName());
$attachment->notes_text = null !== $notes ? $notes->text : '';

View File

@@ -298,7 +298,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
->withPivot(['group_default'])
->get()
;
$all->map(static function (TransactionCurrency $current): TransactionCurrency { // @phpstan-ignore-line
$all->map(static function (TransactionCurrency $current): TransactionCurrency {
$current->userGroupEnabled = true;
$current->userGroupNative = 1 === (int) $current->pivot->group_default;

View File

@@ -86,7 +86,7 @@ class JournalAPIRepository implements JournalAPIRepositoryInterface, UserGroupIn
public function getPiggyBankEvents(TransactionJournal $journal): Collection
{
$events = $journal->piggyBankEvents()->get();
$events->each(static function (PiggyBankEvent $event): void { // @phpstan-ignore-line
$events->each(static function (PiggyBankEvent $event): void {
$event->piggyBank = PiggyBank::withTrashed()->find($event->piggy_bank_id);
});

View File

@@ -120,7 +120,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
$disk = Storage::disk('upload');
return $set->each(static function (Attachment $attachment) use ($disk): Attachment { // @phpstan-ignore-line
return $set->each(static function (Attachment $attachment) use ($disk): Attachment {
$notes = $attachment->notes()->first();
$attachment->file_exists = $disk->exists($attachment->fileName());
$attachment->notes_text = null !== $notes ? $notes->text : '';
@@ -143,7 +143,13 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
$amount = '' === $amount ? '0' : $amount;
$sum = bcadd($sum, $amount);
}
Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum));
Log::debug(sprintf(
'Current amount (at %s) in piggy bank #%d ("%s") is %s',
now(config('app.timezone'))->toW3cString(),
$piggyBank->id,
$piggyBank->name,
$sum
));
return $sum;
}
@@ -233,11 +239,11 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
$amount = null;
if ((int) $source->transaction_currency_id === $currency->id) {
Log::debug('Use normal amount');
$amount = Steam::{$operator}($source->amount); // @phpstan-ignore-line
$amount = Steam::{$operator}($source->amount);
}
if ((int) $source->foreign_currency_id === $currency->id) {
Log::debug('Use foreign amount');
$amount = Steam::{$operator}($source->foreign_amount); // @phpstan-ignore-line
$amount = Steam::{$operator}($source->foreign_amount);
}
if (null === $amount) {
Log::debug('No match on currency, so amount remains null, return "0".');

View File

@@ -177,7 +177,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface, UserGroupInte
$groups = $this->user
->ruleGroups()
->orderBy('order', 'ASC')
->with([ // @phpstan-ignore-line
->with([
'rules' => static function (HasMany $query): void {
$query->orderBy('order', 'ASC');
@@ -197,7 +197,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface, UserGroupInte
}
// Log::debug(sprintf('Will filter getRuleGroupsWithRules on "%s".', $filter));
return $groups->map(static function (RuleGroup $group) use ($filter): RuleGroup { // @phpstan-ignore-line
return $groups->map(static function (RuleGroup $group) use ($filter): RuleGroup {
// Log::debug(sprintf('Now filtering group #%d', $group->id));
// filter the rules in the rule group:
$group->rules = $group->rules->filter(static function (Rule $rule) use ($filter): bool {
@@ -231,7 +231,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface, UserGroupInte
->ruleGroups()
->orderBy('order', 'ASC')
->where('active', true)
->with([ // @phpstan-ignore-line
->with([
'rules' => static function (HasMany $query): void {
$query->orderBy('order', 'ASC');
$query->where('rules.active', true);
@@ -250,7 +250,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface, UserGroupInte
}
Log::debug(sprintf('Will filter getRuleGroupsWithRules on "%s".', $filter));
return $groups->map(static function (RuleGroup $group) use ($filter): RuleGroup { // @phpstan-ignore-line
return $groups->map(static function (RuleGroup $group) use ($filter): RuleGroup {
// Log::debug(sprintf('Now filtering group #%d', $group->id));
// filter the rules in the rule group:
$group->rules = $group->rules->filter(static function (Rule $rule) use ($filter): bool {

View File

@@ -126,7 +126,7 @@ class TagRepository implements TagRepositoryInterface, UserGroupInterface
$set = $tag->attachments()->get();
$disk = Storage::disk('upload');
return $set->each(static function (Attachment $attachment) use ($disk): void { // @phpstan-ignore-line
return $set->each(static function (Attachment $attachment) use ($disk): void {
/** @var null|Note $note */
$note = $attachment->notes()->first();
// only used in v1 view of tags

View File

@@ -101,7 +101,7 @@ class UserGroupRepository implements UserGroupRepositoryInterface, UserGroupInte
'webhooks',
];
foreach ($objects as $object) {
foreach ($userGroup->{$object}()->get() as $item) { // @phpstan-ignore-line
foreach ($userGroup->{$object}()->get() as $item) {
$item->delete();
}
}
@@ -255,11 +255,7 @@ class UserGroupRepository implements UserGroupRepositoryInterface, UserGroupInte
// if there are no other owners and the current users does not get or keep the owner role, refuse.
if (
0 === $ownerCount
&& (
0 === count($data['roles'])
|| count($data['roles']) > 0 // @phpstan-ignore-line
&& !in_array(UserRoleEnum::OWNER->value, $data['roles'], true)
)
&& (0 === count($data['roles']) || count($data['roles']) > 0 && !in_array(UserRoleEnum::OWNER->value, $data['roles'], true))
) {
Log::debug('User needs to keep owner role in this group, refuse to act');

View File

@@ -90,7 +90,7 @@ class WebhookRepository implements WebhookRepositoryInterface, UserGroupInterfac
->where('webhook_messages.sent', 0)
->where('webhook_messages.errored', 0)
->get(['webhook_messages.*'])
->filter(static fn (WebhookMessage $message): bool => $message->webhookAttempts()->count() <= 2) // @phpstan-ignore-line
->filter(static fn (WebhookMessage $message): bool => $message->webhookAttempts()->count() <= 2)
->splice(0, 3)
;
}

View File

@@ -82,7 +82,7 @@ class BelongsUser implements ValidationRule
}
$count = 0;
foreach ($objects as $object) {
$objectValue = trim((string) $object->{$field}); // @phpstan-ignore-line
$objectValue = trim((string) $object->{$field});
Log::debug(sprintf('Comparing object "%s" with value "%s"', $objectValue, $value));
if ($objectValue === $value) {
++$count;

View File

@@ -95,7 +95,7 @@ class BelongsUserGroup implements ValidationRule
}
$count = 0;
foreach ($objects as $object) {
$objectValue = trim((string) $object->{$field}); // @phpstan-ignore-line
$objectValue = trim((string) $object->{$field});
Log::debug(sprintf('Comparing object "%s" with value "%s"', $objectValue, $value));
if ($objectValue === $value) {
++$count;

View File

@@ -51,7 +51,7 @@ class IsDateOrTime implements ValidationRule
// probably a date format.
try {
Carbon::createFromFormat('Y-m-d', $value);
} catch (InvalidDateException $e) { // @phpstan-ignore-line
} catch (InvalidDateException $e) {
Log::error(sprintf('"%s" is not a valid date: %s', $value, $e->getMessage()));
$fail('validation.date_or_time')->translate();
@@ -71,7 +71,7 @@ class IsDateOrTime implements ValidationRule
// is an atom string, I hope?
try {
Carbon::parse($value);
} catch (InvalidDateException $e) { // @phpstan-ignore-line
} catch (InvalidDateException $e) {
Log::error(sprintf('"%s" is not a valid date or time: %s', $value, $e->getMessage()));
$fail('validation.date_or_time')->translate();

View File

@@ -94,7 +94,7 @@ class IsValidBulkClause implements ValidationRule
// validate!
$validator = Validator::make(['value' => $arrayValue], ['value' => $this->rules[$clause][$arrayKey]]);
if ($validator->fails()) {
$this->error = sprintf('%s: %s: %s', $clause, $arrayKey, implode(', ', $validator->errors()->get('value'))); // @phpstan-ignore-line
$this->error = sprintf('%s: %s: %s', $clause, $arrayKey, implode(', ', $validator->errors()->get('value')));
return false;
}

View File

@@ -54,7 +54,7 @@ class IsValidDateRange implements ValidationRule
try {
$left = Carbon::parse($value);
$right = Carbon::parse($otherValue);
} catch (InvalidDateException $e) { // @phpstan-ignore-line
} catch (InvalidDateException $e) {
Log::error(sprintf('"%s" or "%s" is not a valid date or time: %s', $value, $otherValue, $e->getMessage()));
$fail('validation.date_or_time')->translate();

View File

@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Rules\Webhook;
use Closure;
use FireflyIII\Support\Facades\FireflyConfig;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\IpUtils;
use function Safe\parse_url;
class IsValidWebhookUrl implements ValidationRule
{
/**
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$value = (string) $value;
$resolved = gethostbyname(parse_url($value, PHP_URL_HOST));
Log::debug(sprintf('Now validating URL "%s" with IP "%s".', $value, $resolved));
// IPv4 is allowed to be in 127 range.
if (filter_var($resolved, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && IpUtils::checkIp4($resolved, '127.0.0.0/8')) {
Log::debug(sprintf('Local IP "%s" is allowed', $resolved));
return;
}
if (false === filter_var($resolved, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)) {
Log::error(sprintf('The resolved IP address "%s" is invalid.', $resolved));
$fail('validation.no_reserved_ip')->translate();
}
$validProtocols = FireflyConfig::get('valid_url_protocols', config('firefly.valid_url_protocols'))->data;
$parts = explode(',', $validProtocols);
$valid = false;
foreach ($parts as $part) {
if (str_starts_with($value, $part)) {
$valid = true;
}
}
if (false === $valid) {
$fail('validation.bad_url_prefix')->translate();
}
}
}

View File

@@ -198,7 +198,7 @@ class PrimaryAmountRecalculationService
private function recalculatePiggyBankEvents(PiggyBank $piggyBank): void
{
$set = $piggyBank->piggyBankEvents()->get();
$set->each(static function (PiggyBankEvent $event): void { // @phpstan-ignore-line
$set->each(static function (PiggyBankEvent $event): void {
$event->touch();
});
Log::debug(sprintf('Recalculated %d piggy bank events.', $set->count()));

View File

@@ -675,7 +675,7 @@ class JournalUpdateService
)
);
$this->transactionJournal->{$fieldName} = $value; // @phpstan-ignore-line
$this->transactionJournal->{$fieldName} = $value;
Log::debug(sprintf('Updated %s', $fieldName));
}
}
@@ -822,7 +822,7 @@ class JournalUpdateService
if ($this->hasFields([$field])) {
try {
$value = '' === (string) $this->data[$field] ? null : new Carbon($this->data[$field]);
} catch (InvalidDateException|InvalidFormatException $e) { // @phpstan-ignore-line
} catch (InvalidDateException|InvalidFormatException $e) {
Log::debug(sprintf('%s is not a valid date value: %s', $this->data[$field], $e->getMessage()));
return;

View File

@@ -28,11 +28,13 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Webhook\SignatureGeneratorInterface;
use FireflyIII\Models\WebhookAttempt;
use FireflyIII\Models\WebhookMessage;
use FireflyIII\Rules\Webhook\IsValidWebhookUrl;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use JsonException;
use function Safe\json_encode;
@@ -63,6 +65,16 @@ class StandardWebhookSender implements WebhookSenderInterface
$this->message->sent = true;
$this->message->save();
// validate the webhook URL.
$data = [
'url' => $this->message->webhook->url,
];
$rules = [
'url' => [new IsValidWebhookUrl()],
];
$res = Validator::make($data, $rules)->validate();
Log::debug('Result of res', $res);
try {
$signature = $signatureGenerator->generate($this->message);
} catch (FireflyException $e) {

View File

@@ -144,7 +144,7 @@ class RemoteUserGuard implements Guard
return $this->user?->id;
}
public function setUser(Authenticatable|User|null $user): void // @phpstan-ignore-line
public function setUser(Authenticatable|User|null $user): void
{
// Log::debug(sprintf('Now at %s', __METHOD__));
if ($user instanceof User) {

View File

@@ -46,7 +46,7 @@ class BudgetList implements BinderInterface
$list = array_unique(array_map(\intval(...), explode(',', $value)));
if (0 === count($list)) { // @phpstan-ignore-line
if (0 === count($list)) {
Log::warning('Budget list count is zero, return 404.');
throw new NotFoundHttpException();

View File

@@ -44,7 +44,7 @@ class CategoryList implements BinderInterface
}
$list = array_unique(array_map(\intval(...), explode(',', $value)));
if (0 === count($list)) { // @phpstan-ignore-line
if (0 === count($list)) {
throw new NotFoundHttpException();
}

View File

@@ -69,7 +69,7 @@ class Date implements BinderInterface
try {
$result = new Carbon($value);
} catch (InvalidDateException|InvalidFormatException $e) { // @phpstan-ignore-line
} catch (InvalidDateException|InvalidFormatException $e) {
$message = sprintf('Could not parse date "%s" for user #%d: %s', $value, auth()->user()->id, $e->getMessage());
Log::error($message);

View File

@@ -66,7 +66,7 @@ class JournalList implements BinderInterface
protected static function parseList(string $value): array
{
$list = array_unique(array_map(\intval(...), explode(',', $value)));
if (0 === count($list)) { // @phpstan-ignore-line
if (0 === count($list)) {
throw new NotFoundHttpException();
}

View File

@@ -47,7 +47,7 @@ class TagList implements BinderInterface
$list = array_unique(array_map(\strtolower(...), explode(',', $value)));
Log::debug('List of tags is', $list);
if (0 === count($list)) { // @phpstan-ignore-line
if (0 === count($list)) {
Log::error('Tag list is empty.');
throw new NotFoundHttpException();

View File

@@ -89,7 +89,7 @@ trait ValidatesUserGroupTrait
throw new AuthorizationException((string) trans('validation.belongs_user_or_user_group'));
}
Log::debug(sprintf('validateUserGroup: validate access of user to group #%d ("%s").', $groupId, $group->title));
$roles = property_exists($this, 'acceptedRoles') ? $this->acceptedRoles : []; // @phpstan-ignore-line
$roles = property_exists($this, 'acceptedRoles') ? $this->acceptedRoles : [];
if (0 === count($roles)) {
Log::debug('validateUserGroup: no roles defined, so no access.');

View File

@@ -48,6 +48,11 @@ class AvailableBudgetCalculator
private AvailableBudgetRepositoryInterface $abRepository;
private BudgetLimitRepositoryInterface $blRepository;
public function __construct()
{
Log::debug('Created new AvailableBudgetCalculator');
}
public function recalculateByRange(): void
{
Log::debug(sprintf('Now in recalculateByRange(%s, %s)', $this->start->format('Y-m-d'), $this->start->format('Y-m-d')));

View File

@@ -128,9 +128,7 @@ class BillDateCalculator
}
}
Log::debug('end of loop');
$simple = $set->map( // @phpstan-ignore-line
static fn (Carbon $date) => $date->format('Y-m-d')
);
$simple = $set->map(static fn (Carbon $date) => $date->format('Y-m-d'));
Log::debug(sprintf('Found %d pay dates', $set->count()), $simple->toArray());
return $simple->toArray();

View File

@@ -156,7 +156,7 @@ class Navigation
}
$func = $map[$period];
// first do the diff
$floatDiff = $beginning->{$func}($end, true); // @phpstan-ignore-line
$floatDiff = $beginning->{$func}($end, true);
// then correct for quarterly or half-year
if ('quarterly' === $period) {
@@ -345,7 +345,7 @@ class Navigation
$function = $functionMap[$repeatFreq];
if (array_key_exists($repeatFreq, $modifierMap)) {
$currentEnd->{$function}($modifierMap[$repeatFreq])->milli(0); // @phpstan-ignore-line
$currentEnd->{$function}($modifierMap[$repeatFreq])->milli(0);
if (in_array($repeatFreq, $subDay, true)) {
$currentEnd->subDay();
}
@@ -363,7 +363,7 @@ class Navigation
return $currentEnd;
}
$currentEnd->{$function}(); // @phpstan-ignore-line
$currentEnd->{$function}();
$currentEnd->endOfDay()->milli(0);
if (in_array($repeatFreq, $subDay, true)) {
$currentEnd->subDay();
@@ -406,7 +406,7 @@ class Navigation
if (array_key_exists($repeatFreq, $functionMap)) {
$function = $functionMap[$repeatFreq];
$currentEnd->{$function}(); // @phpstan-ignore-line
$currentEnd->{$function}();
}
if ($maxDate instanceof Carbon && $currentEnd > $maxDate) {
@@ -470,7 +470,7 @@ class Navigation
$formatted = $begin->format($format);
$displayed = $begin->isoFormat($displayFormat);
$entries[$formatted] = $displayed;
$begin->{$increment}(); // @phpstan-ignore-line
$begin->{$increment}();
}
Log::debug('listOfPeriods end of loop.');
@@ -677,13 +677,13 @@ class Navigation
// Log::debug(sprintf('Function is ->%s()', $function));
if (array_key_exists($function, $parameterMap)) {
// Log::debug(sprintf('Parameter map, function becomes ->%s(%s)', $function, implode(', ', $parameterMap[$function])));
$date->{$function}($parameterMap[$function][0]); // @phpstan-ignore-line
$date->{$function}($parameterMap[$function][0]);
// Log::debug(sprintf('Result is "%s"', $date->toIso8601String()));
return $date;
}
$date->{$function}(); // @phpstan-ignore-line
$date->{$function}();
// Log::debug(sprintf('Result is "%s"', $date->toIso8601String()));
return $date;
@@ -747,7 +747,7 @@ class Navigation
$modifierMap = ['quarter' => 3, '3M' => 3, 'quarterly' => 3, 'half-year' => 6, '6M' => 6];
if (array_key_exists($repeatFreq, $functionMap)) {
$function = $functionMap[$repeatFreq];
$date->{$function}($subtract); // @phpstan-ignore-line
$date->{$function}($subtract);
return $date;
}
@@ -826,7 +826,7 @@ class Navigation
if (array_key_exists($range, $functionMap)) {
$function = $functionMap[$range];
$end->{$function}(); // @phpstan-ignore-line
$end->{$function}();
Log::debug(sprintf('updateEndDate returns "%s"', $end->format('Y-m-d')));
@@ -877,7 +877,7 @@ class Navigation
];
if (array_key_exists($range, $functionMap)) {
$function = $functionMap[$range];
$start->{$function}(); // @phpstan-ignore-line
$start->{$function}();
Log::debug(sprintf('updateStartDate returns "%s"', $start->format('Y-m-d')));
return $start;

View File

@@ -36,7 +36,6 @@ class NullArrayObject extends ArrayObject
*
* @param null $default
*/
/** @phpstan-ignore-next-line */
public function __construct(
array $array,
public $default = null

View File

@@ -353,7 +353,7 @@ class ParseDateString
}
$func = $functions[$direction][$period];
Log::debug(sprintf('Will now do %s(%d) on %s', $func, $number, $today->format('Y-m-d')));
$today->{$func}($number); // @phpstan-ignore-line
$today->{$func}($number);
Log::debug(sprintf('Resulting date is %s', $today->format('Y-m-d')));
}

View File

@@ -195,7 +195,7 @@ class TransactionSummarizer
];
// add the data from the $field to the array.
$array[$key]['sum'] = bcadd($array[$key]['sum'], (string) Steam::{$method}((string) ($journal[$field] ?? '0'))); // @phpstan-ignore-line
$array[$key]['sum'] = bcadd($array[$key]['sum'], (string) Steam::{$method}((string) ($journal[$field] ?? '0')));
Log::debug(sprintf(
'Field for transaction #%d is "%s" (%s). Sum: %s',
$journal['transaction_group_id'],
@@ -225,7 +225,7 @@ class TransactionSummarizer
'currency_code' => $journal['foreign_currency_code'],
'currency_decimal_places' => $journal['foreign_currency_decimal_places'],
];
$array[$key]['sum'] = bcadd($array[$key]['sum'], (string) Steam::{$method}((string) $journal['foreign_amount'])); // @phpstan-ignore-line
$array[$key]['sum'] = bcadd($array[$key]['sum'], (string) Steam::{$method}((string) $journal['foreign_amount']));
}
}

View File

@@ -45,7 +45,7 @@ trait ChecksLogin
if (!$check) {
return false;
}
if (!property_exists($this, 'acceptedRoles')) { // @phpstan-ignore-line
if (!property_exists($this, 'acceptedRoles')) {
Log::debug(sprintf('Request class %s has no acceptedRoles array', static::class));
return true; // check for false already took place.

View File

@@ -205,7 +205,7 @@ trait ConvertsDataTypes
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
if (method_exists($this, 'validateUserGroup')) { // @phpstan-ignore-line
if (method_exists($this, 'validateUserGroup')) {
$userGroup = $this->validateUserGroup($this);
$repository->setUserGroup($userGroup);
}
@@ -290,11 +290,11 @@ trait ConvertsDataTypes
// probably a date format.
try {
$carbon = Carbon::createFromFormat('Y-m-d', $value, config('app.timezone'));
} catch (InvalidDateException $e) { // @phpstan-ignore-line
} catch (InvalidDateException $e) {
Log::error(sprintf('[1] "%s" is not a valid date: %s', $value, $e->getMessage()));
return null;
} catch (InvalidFormatException $e) { // @phpstan-ignore-line
} catch (InvalidFormatException $e) {
Log::error(sprintf('[2] "%s" is of an invalid format: %s', $value, $e->getMessage()));
return null;
@@ -312,7 +312,7 @@ trait ConvertsDataTypes
try {
$carbon = Carbon::parse($value);
$carbon->setTimezone(config('app.timezone'));
} catch (InvalidDateException $e) { // @phpstan-ignore-line
} catch (InvalidDateException $e) {
Log::error(sprintf('[3] "%s" is not a valid date or time: %s', $value, $e->getMessage()));
return null;
@@ -385,7 +385,7 @@ trait ConvertsDataTypes
foreach ($fields as $field => $info) {
if (true === $this->has($info[0])) {
$method = $info[1];
$return[$field] = $this->{$method}($info[0]); // @phpstan-ignore-line
$return[$field] = $this->{$method}($info[0]);
}
}

View File

@@ -552,7 +552,7 @@ class OperatorQuerySearch implements SearchInterface
return;
}
Log::debug(sprintf('Left with %d, set as %s().', $filtered->count(), $collectorMethod));
$this->collector->{$collectorMethod}($filtered); // @phpstan-ignore-line
$this->collector->{$collectorMethod}($filtered);
}
/**
@@ -661,7 +661,7 @@ class OperatorQuerySearch implements SearchInterface
return;
}
Log::debug(sprintf('Left with %d, set as %s().', $filtered->count(), $collectorMethod));
$this->collector->{$collectorMethod}($filtered); // @phpstan-ignore-line
$this->collector->{$collectorMethod}($filtered);
}
/**

View File

@@ -475,7 +475,7 @@ class Steam
->groupBy('transactions.transaction_currency_id')
->orderBy('transaction_journals.date', 'ASC')
->whereNull('transaction_journals.deleted_at')
->get(['transaction_journals.date', 'transactions.transaction_currency_id', DB::raw('SUM(transactions.amount) AS sum_of_day')]) // @phpstan-ignore-line
->get(['transaction_journals.date', 'transactions.transaction_currency_id', DB::raw('SUM(transactions.amount) AS sum_of_day')])
;
$currentBalance = $startBalance;
@@ -619,7 +619,7 @@ class Steam
->transactions()
->whereIn('transactions.account_id', $accounts)
->groupBy(['transactions.account_id', 'transaction_journals.user_id'])
->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line
->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) AS max_date')])
;
/** @var Transaction $entry */

View File

@@ -99,7 +99,7 @@ class SearchRuleEngine implements RuleEngineInterface
Log::debug(sprintf('SearchRuleEngine:: found %d rule(s) to fire.', $this->rules->count()));
/** @var Rule $rule */
foreach ($this->rules as $rule) { // @phpstan-ignore-line
foreach ($this->rules as $rule) {
$result = $this->fireRule($rule);
if ($result && true === $rule->stop_processing) {
Log::debug(sprintf(
@@ -120,7 +120,7 @@ class SearchRuleEngine implements RuleEngineInterface
// fire each group:
/** @var RuleGroup $group */
foreach ($this->groups as $group) { // @phpstan-ignore-line
foreach ($this->groups as $group) {
$this->fireGroup($group);
}
}

View File

@@ -319,7 +319,7 @@ class User extends Authenticatable
{
$method = 'routeNotificationFor'.Str::studly($driver);
if (method_exists($this, $method)) {
return $this->{$method}($notification); // @phpstan-ignore-line
return $this->{$method}($notification);
}
$email = $this->email;
// see if user has alternative email address:

View File

@@ -262,7 +262,7 @@ class FireflyValidator extends Validator
try {
$checksum = bcmod($iban, '97');
} catch (ValueError $e) { // @phpstan-ignore-line
} catch (ValueError $e) {
$message = sprintf('Could not validate IBAN check value "%s" (IBAN "%s")', $iban, $value);
Log::error($message);
Log::error($e->getTraceAsString());

View File

@@ -395,7 +395,7 @@ trait RecurrenceValidation
{
try {
Carbon::createFromFormat('Y-m-d', $moment);
} catch (InvalidArgumentException $e) { // @phpstan-ignore-line
} catch (InvalidArgumentException $e) {
Log::debug(sprintf('Invalid argument for Carbon: %s', $e->getMessage()));
$validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string) trans('validation.valid_recurrence_rep_moment'));
}

View File

@@ -70,7 +70,7 @@ if (!function_exists('envNonEmpty')) {
*/
function envNonEmpty(string $key, string | int | bool | null $default = null)
{
$result = env($key, $default); // @phpstan-ignore-line
$result = env($key, $default);
if ('' === $result) {
return $default;
}

View File

@@ -19,6 +19,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
use FireflyIII\Providers\AccountServiceProvider;
use FireflyIII\Providers\AdminServiceProvider;
use FireflyIII\Providers\AppServiceProvider;

View File

@@ -3,6 +3,26 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## 6.5.4 - 2026-03-06
### Added
- Add some debug info to find
### Fixed
- [Issue 11873](https://github.com/firefly-iii/firefly-iii/issues/11873) (Piggy bank +/- sometimes sends 0.00 and fails with “Cannot add 0 because canAddAmount returned false”) reported by @ralle06
- Transaction count would search for the wrong meta field.
### Security
- Published security advisory https://github.com/firefly-iii/firefly-iii/security/advisories/GHSA-5q8v-j673-m5v4 found and reported by @lighthousekeeper1212
- It's possible to submit webhook URLs that point to internal IP addresses. This will still be the case in the future, though some reserved ranges are no blocked. Let me know if this impacts you.
### API
- Initial release.
## 6.5.3 - 2026-03-05
This release fixes some sloppy coding on my part, but good news everyone! A new linter is in place that should prevent that from happening. Turns out I had disabled it in the past :(.

View File

@@ -125,7 +125,8 @@
"phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "^12",
"rector/rector": "^2.3",
"thecodingmachine/phpstan-safe-rule": "^1.4"
"thecodingmachine/phpstan-safe-rule": "^1.4",
"ergebnis/phpstan-rules": "^2"
},
"suggest": {},

151
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "94727a98e7468c09f3529378b9cb2457",
"content-hash": "93912463b9c00da1cf4afbd38edd36a1",
"packages": [
{
"name": "bacon/bacon-qr-code",
@@ -1009,16 +1009,16 @@
},
{
"name": "firebase/php-jwt",
"version": "v6.11.1",
"version": "v7.0.3",
"source": {
"type": "git",
"url": "https://github.com/firebase/php-jwt.git",
"reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66"
"reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/d1e91ecf8c598d073d0995afa8cd5c75c6e19e66",
"reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66",
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/28aa0694bcfdfa5e2959c394d5a1ee7a5083629e",
"reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e",
"shasum": ""
},
"require": {
@@ -1066,9 +1066,9 @@
],
"support": {
"issues": "https://github.com/firebase/php-jwt/issues",
"source": "https://github.com/firebase/php-jwt/tree/v6.11.1"
"source": "https://github.com/firebase/php-jwt/tree/v7.0.3"
},
"time": "2025-04-09T20:32:01+00:00"
"time": "2026-02-25T22:16:40+00:00"
},
{
"name": "fruitcake/php-cors",
@@ -2100,21 +2100,21 @@
},
{
"name": "laravel/passport",
"version": "v12.4.2",
"version": "v12.4.3",
"source": {
"type": "git",
"url": "https://github.com/laravel/passport.git",
"reference": "65a885607b62d361aedaeb10a946bc6b5a954262"
"reference": "1d2e0170a52f150d5c35c9a6fc1f7ccebcde7626"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/passport/zipball/65a885607b62d361aedaeb10a946bc6b5a954262",
"reference": "65a885607b62d361aedaeb10a946bc6b5a954262",
"url": "https://api.github.com/repos/laravel/passport/zipball/1d2e0170a52f150d5c35c9a6fc1f7ccebcde7626",
"reference": "1d2e0170a52f150d5c35c9a6fc1f7ccebcde7626",
"shasum": ""
},
"require": {
"ext-json": "*",
"firebase/php-jwt": "^6.4",
"firebase/php-jwt": "^6.4|^7.0",
"illuminate/auth": "^9.21|^10.0|^11.0|^12.0",
"illuminate/console": "^9.21|^10.0|^11.0|^12.0",
"illuminate/container": "^9.21|^10.0|^11.0|^12.0",
@@ -2172,7 +2172,7 @@
"issues": "https://github.com/laravel/passport/issues",
"source": "https://github.com/laravel/passport"
},
"time": "2025-02-12T16:11:33+00:00"
"time": "2026-02-19T14:14:05+00:00"
},
{
"name": "laravel/prompts",
@@ -2561,16 +2561,16 @@
},
{
"name": "league/commonmark",
"version": "2.8.0",
"version": "2.8.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
"reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb"
"reference": "84b1ca48347efdbe775426f108622a42735a6579"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb",
"reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/84b1ca48347efdbe775426f108622a42735a6579",
"reference": "84b1ca48347efdbe775426f108622a42735a6579",
"shasum": ""
},
"require": {
@@ -2595,9 +2595,9 @@
"phpstan/phpstan": "^1.8.2",
"phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0",
"scrutinizer/ocular": "^1.8.1",
"symfony/finder": "^5.3 | ^6.0 | ^7.0",
"symfony/process": "^5.4 | ^6.0 | ^7.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
"symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0",
"symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0 || ^8.0",
"unleashedtech/php-coding-standard": "^3.1.1",
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
},
@@ -2664,7 +2664,7 @@
"type": "tidelift"
}
],
"time": "2025-11-26T21:48:24+00:00"
"time": "2026-03-05T21:37:03+00:00"
},
{
"name": "league/config",
@@ -10115,16 +10115,16 @@
},
{
"name": "barryvdh/reflection-docblock",
"version": "v2.4.0",
"version": "v2.4.1",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/ReflectionDocBlock.git",
"reference": "d103774cbe7e94ddee7e4870f97f727b43fe7201"
"reference": "4f5ba70c30c81f2ce03a16a9965832cfcc31ed3b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/d103774cbe7e94ddee7e4870f97f727b43fe7201",
"reference": "d103774cbe7e94ddee7e4870f97f727b43fe7201",
"url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/4f5ba70c30c81f2ce03a16a9965832cfcc31ed3b",
"reference": "4f5ba70c30c81f2ce03a16a9965832cfcc31ed3b",
"shasum": ""
},
"require": {
@@ -10161,9 +10161,9 @@
}
],
"support": {
"source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.4.0"
"source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.4.1"
},
"time": "2025-07-17T06:07:30+00:00"
"time": "2026-03-05T20:09:01+00:00"
},
{
"name": "cloudcreativity/json-api-testing",
@@ -10373,16 +10373,16 @@
},
{
"name": "driftingly/rector-laravel",
"version": "2.1.9",
"version": "2.1.11",
"source": {
"type": "git",
"url": "https://github.com/driftingly/rector-laravel.git",
"reference": "aee9d4a1d489e7ec484fc79f33137f8ee051b3f7"
"reference": "84ea7e03f4a2d9d33e303559ed7e3280bfdb8d01"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/aee9d4a1d489e7ec484fc79f33137f8ee051b3f7",
"reference": "aee9d4a1d489e7ec484fc79f33137f8ee051b3f7",
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/84ea7e03f4a2d9d33e303559ed7e3280bfdb8d01",
"reference": "84ea7e03f4a2d9d33e303559ed7e3280bfdb8d01",
"shasum": ""
},
"require": {
@@ -10403,9 +10403,82 @@
"description": "Rector upgrades rules for Laravel Framework",
"support": {
"issues": "https://github.com/driftingly/rector-laravel/issues",
"source": "https://github.com/driftingly/rector-laravel/tree/2.1.9"
"source": "https://github.com/driftingly/rector-laravel/tree/2.1.11"
},
"time": "2025-12-25T23:31:36+00:00"
"time": "2026-03-05T19:46:28+00:00"
},
{
"name": "ergebnis/phpstan-rules",
"version": "2.13.1",
"source": {
"type": "git",
"url": "https://github.com/ergebnis/phpstan-rules.git",
"reference": "f69db86b98595c34fc1f61c89fe3b380141aa519"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/f69db86b98595c34fc1f61c89fe3b380141aa519",
"reference": "f69db86b98595c34fc1f61c89fe3b380141aa519",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
"phpstan/phpstan": "^2.1.35"
},
"require-dev": {
"codeception/codeception": "^4.0.0 || ^5.0.0",
"doctrine/orm": "^2.20.0 || ^3.3.0",
"ergebnis/composer-normalize": "^2.49.0",
"ergebnis/license": "^2.7.0",
"ergebnis/php-cs-fixer-config": "^6.59.0",
"ergebnis/phpunit-slow-test-detector": "^2.20.0",
"fakerphp/faker": "^1.24.1",
"phpstan/extension-installer": "^1.4.3",
"phpstan/phpstan-deprecation-rules": "^2.0.3",
"phpstan/phpstan-phpunit": "^2.0.12",
"phpstan/phpstan-strict-rules": "^2.0.8",
"phpunit/phpunit": "^9.6.21",
"psr/container": "^2.0.2",
"symfony/finder": "^5.4.45",
"symfony/process": "^5.4.47"
},
"type": "phpstan-extension",
"extra": {
"phpstan": {
"includes": [
"rules.neon"
]
}
},
"autoload": {
"psr-4": {
"Ergebnis\\PHPStan\\Rules\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Andreas Möller",
"email": "am@localheinz.com",
"homepage": "https://localheinz.com"
}
],
"description": "Provides rules for phpstan/phpstan.",
"homepage": "https://github.com/ergebnis/phpstan-rules",
"keywords": [
"PHPStan",
"phpstan-rules"
],
"support": {
"issues": "https://github.com/ergebnis/phpstan-rules/issues",
"security": "https://github.com/ergebnis/phpstan-rules/blob/main/.github/SECURITY.md",
"source": "https://github.com/ergebnis/phpstan-rules"
},
"time": "2026-01-27T17:13:06+00:00"
},
{
"name": "fakerphp/faker",
@@ -11140,16 +11213,16 @@
},
{
"name": "php-debugbar/php-debugbar",
"version": "v3.4.1",
"version": "v3.5.1",
"source": {
"type": "git",
"url": "https://github.com/php-debugbar/php-debugbar.git",
"reference": "ee9c718797a4c1fdf6c4d980cb3edcc1eeeddcc7"
"reference": "486b32fd98efe9a3c10f0b24c0caabc187f78f04"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/ee9c718797a4c1fdf6c4d980cb3edcc1eeeddcc7",
"reference": "ee9c718797a4c1fdf6c4d980cb3edcc1eeeddcc7",
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/486b32fd98efe9a3c10f0b24c0caabc187f78f04",
"reference": "486b32fd98efe9a3c10f0b24c0caabc187f78f04",
"shasum": ""
},
"require": {
@@ -11226,7 +11299,7 @@
],
"support": {
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
"source": "https://github.com/php-debugbar/php-debugbar/tree/v3.4.1"
"source": "https://github.com/php-debugbar/php-debugbar/tree/v3.5.1"
},
"funding": [
{
@@ -11238,7 +11311,7 @@
"type": "github"
}
],
"time": "2026-02-26T11:40:30+00:00"
"time": "2026-03-05T20:37:33+00:00"
},
{
"name": "php-debugbar/symfony-bridge",

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => (bool)envNonEmpty('USE_RUNNING_BALANCE', true), // this is only the default value, is not used.
// see cer.php for exchange rates feature flag.
],
'version' => '6.5.3',
'build_time' => 1772606967,
'version' => 'develop/2026-03-06',
'build_time' => 1772780248,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.

View File

@@ -37,7 +37,7 @@ class TransactionTypeSeeder extends Seeder
public function run(): void
{
/** @var TransactionTypeEnum $type */
foreach (TransactionTypeEnum::cases() as $type) { // @phpstan-ignore-line
foreach (TransactionTypeEnum::cases() as $type) {
if (null === TransactionType::where('type', $type->value)->first()) {
try {
TransactionType::create(['type' => $type->value]);

View File

@@ -41,7 +41,7 @@ class UserRoleSeeder extends Seeder
public function run(): void
{
/** @var UserRoleEnum $role */
foreach (UserRoleEnum::cases() as $role) { // @phpstan-ignore-line
foreach (UserRoleEnum::cases() as $role) {
if (null === UserRole::where('title', $role->value)->first()) {
try {
UserRole::create(['title' => $role->value]);

46
package-lock.json generated
View File

@@ -2969,16 +2969,6 @@
"win32"
]
},
"node_modules/@trysound/sax": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
"dev": true,
"license": "ISC",
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -3246,9 +3236,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "25.3.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.3.tgz",
"integrity": "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==",
"version": "25.3.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz",
"integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3273,9 +3263,9 @@
"license": "MIT"
},
"node_modules/@types/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz",
"integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==",
"dev": true,
"license": "MIT"
},
@@ -4597,9 +4587,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001776",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001776.tgz",
"integrity": "sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==",
"version": "1.0.30001777",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz",
"integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==",
"dev": true,
"funding": [
{
@@ -10284,6 +10274,16 @@
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/sax": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz",
"integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=11.0.0"
}
},
"node_modules/schema-utils": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
@@ -10968,18 +10968,18 @@
}
},
"node_modules/svgo": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz",
"integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==",
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.2.tgz",
"integrity": "sha512-TyzE4NVGLUFy+H/Uy4N6c3G0HEeprsVfge6Lmq+0FdQQ/zqoVYB62IsBZORsiL+o96s6ff/V6/3UQo/C0cgCAA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@trysound/sax": "0.2.0",
"commander": "^7.2.0",
"css-select": "^4.1.3",
"css-tree": "^1.1.3",
"csso": "^4.2.0",
"picocolors": "^1.0.0",
"sax": "^1.5.0",
"stable": "^0.1.8"
},
"bin": {

View File

@@ -30,7 +30,7 @@
---
<p>
<img align="left" src=".github/assets/img/europe.png" alt="Flag of Europe" height="50"> Billionaires and fascists are breaking democracies and international alliances. Their profits are costing us our safety. (Digital) sovereignty is more important than ever. <strong>Firefly III</strong> is free open source software and lives in the European Union.
<img align="left" src=".github/assets/img/europe.png" alt="Flag of Europe" height="50"> Billionaires and fascists are breaking democracies and international alliances. Their profits are costing us our safety. (Digital) sovereignty is more important than ever. <strong>Firefly III</strong> is free open source software and originates from, and lives in the European Union (🇳🇱).
</p>
---

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