Compare commits

...

11 Commits

Author SHA1 Message Date
github-actions[bot]
f9b7149fc7 Merge pull request #11919 from firefly-iii/release-1773028359
🤖 Automatically merge the PR into the develop branch.
2026-03-09 04:52:46 +01:00
JC5
7c3fb7a95a 🤖 Auto commit for release 'develop' on 2026-03-09 2026-03-09 04:52:39 +01:00
James Cole
91b7ee06d8 Fix moar phpstan issues. 2026-03-08 17:44:19 +01:00
James Cole
84ea19d14c Fix a bunch of phpstan errors. 2026-03-08 17:08:51 +01:00
James Cole
9950f79a6b Merge branch 'main' into develop 2026-03-08 11:57:21 +01:00
James Cole
e3df7675d3 Fix https://github.com/firefly-iii/firefly-iii/issues/11916 2026-03-08 11:56:53 +01:00
James Cole
15094097bc Update various templates. 2026-03-07 13:42:11 +01:00
github-actions[bot]
a07dc4dbc8 Merge pull request #11904 from firefly-iii/release-1772875617
🤖 Automatically merge the PR into the develop branch.
2026-03-07 10:27:06 +01:00
JC5
c86562554b 🤖 Auto commit for release 'develop' on 2026-03-07 2026-03-07 10:26:58 +01:00
James Cole
19b548a417 Fix null type issues. 2026-03-07 10:20:06 +01:00
James Cole
71698b36e2 Fix various phpstan issues. 2026-03-07 10:17:07 +01:00
49 changed files with 185 additions and 163 deletions

View File

@@ -33,29 +33,16 @@ parameters:
- Illuminate\Database\Eloquent\Model
reportUnmatchedIgnoredErrors: true
ignoreErrors:
# these are actually interesting but not right now:
- identifier: larastan.noUnnecessaryCollectionCall
- identifier: varTag.differentVariable
- identifier: identical.alwaysTrue
- identifier: assign.propertyReadOnly
- identifier: varTag.nativeType
- identifier: property.onlyWritten
- identifier: parameter.phpDocType
- identifier: property.dynamicName
- identifier: property.unusedType
- identifier: staticMethod.deprecated
# ignore everything but things that BREAK
- identifier: property.deprecated
- identifier: method.deprecated
- identifier: cast.useless
- identifier: parameter.deprecatedClass
- identifier: method.deprecatedClass
- identifier: argument.type
- identifier: return.type
- identifier: assign.propertyType
- identifier: return.unusedType
- identifier: return.phpDocType
# all errors below I will (probably) never fix.
- identifier: property.unusedType # one false positive
- identifier: varTag.nativeType # dont even know what im supposed to fix.
- identifier: method.notFound # way too many false positives
- identifier: catch.neverThrown # plenty of errors that are thrown undocumented
- identifier: staticMethod.dynamicName # dont care

View File

@@ -171,6 +171,9 @@ abstract class Controller extends BaseController
return $manager->createData($resource)->toArray();
}
/**
* @deprecated
*/
#[Deprecated(message: <<<'TXT'
use Request classes
Method to grab all parameters from the URL
@@ -224,7 +227,8 @@ abstract class Controller extends BaseController
$value = min(max(1, $value), 2 ** 16);
$bag->set($integer, $value);
}
if (null === $value && 'limit' === $integer && auth()->check()) {
// && 'limit' === $integer
if (null === $value && auth()->check()) {
// set default for user:
/** @var User $user */
$user = auth()->user();

View File

@@ -83,7 +83,6 @@ final class StoreController extends Controller
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($bill, $transformer, 'bills');

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\BudgetLimit;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\SameDateRequest;
use FireflyIII\Api\V1\Requests\DateRangeRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
@@ -118,12 +118,12 @@ final class ShowController extends Controller
*
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function indexAll(SameDateRequest $request): JsonResponse
public function indexAll(DateRangeRequest $request): JsonResponse
{
$manager = $this->getManager();
$manager->parseIncludes('budget');
$pageSize = $this->parameters->get('limit');
$collection = $this->blRepository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end'));
$collection = $this->blRepository->getAllBudgetLimits($request->attributes->get('start'), $request->attributes->get('end'));
$count = $collection->count();
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\Recurrence;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Generic\SingleDateRequest;
use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Jobs\CreateRecurringTransactions;
use FireflyIII\Models\Recurrence;
@@ -59,12 +59,12 @@ final class TriggerController extends Controller
});
}
public function trigger(SingleDateRequest $request, Recurrence $recurrence): JsonResponse
public function trigger(DateRequest $request, Recurrence $recurrence): JsonResponse
{
// find recurrence occurrence for this date and trigger it.
// grab the date from the last time the recurrence fired:
$backupDate = $recurrence->latest_date;
$date = $request->getDate();
$date = $request->attributes->get('date');
// fire the recurring cron job on the given date, then post-date the created transaction.
Log::info(sprintf('Trigger: will now fire recurring cron job task for date "%s".', $date->format('Y-m-d H:i:s')));

View File

@@ -48,6 +48,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
final class UpdateController extends Controller
{
private TransactionGroupRepositoryInterface $groupRepository;
protected array $acceptedRoles = [];
/**
* TransactionController constructor.

View File

@@ -28,6 +28,7 @@ use Carbon\Carbon;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Support\Facades\FireflyConfig;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\QueryException;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
@@ -82,7 +83,7 @@ class ConvertsDatesToUTC extends Command
return;
}
$this->friendlyInfo(sprintf('Converting field "%s" of model "%s" to UTC.', $field, $shortModel));
$items->each(static function ($item) use ($field, $timezoneField): void {
$items->each(static function (Model $item) use ($field, $timezoneField): void {
$date = Carbon::parse($item->{$field}, $item->{$timezoneField});
$date->setTimezone('UTC');
$item->{$field} = $date->format('Y-m-d H:i:s');

View File

@@ -229,12 +229,24 @@ class CorrectsAccountTypes extends Command
private function getDestinationTransaction(TransactionJournal $journal): Transaction
{
return $journal->transactions->firstWhere('amount', '>', 0);
/** @var null|Transaction $res */
$res = $journal->transactions->firstWhere('amount', '>', 0);
if (null === $res) {
throw new FireflyException('Could not find transaction.');
}
return $res;
}
private function getSourceTransaction(TransactionJournal $journal): Transaction
{
return $journal->transactions->firstWhere('amount', '<', 0);
/** @var null|Transaction $res */
$res = $journal->transactions->firstWhere('amount', '<', 0);
if (null === $res) {
throw new FireflyException('Could not find transaction.');
}
return $res;
}
private function giveNewDestinationAccount(TransactionJournal $journal, Account $newDestination): void

View File

@@ -64,10 +64,6 @@ class RemovesDatabaseDecryption extends Command
'journal_links' => ['comment'],
];
/**
* @var string $table
* @var array $fields
*/
foreach ($tables as $table => $fields) {
$this->decryptTable($table, $fields);
}

View File

@@ -94,6 +94,7 @@ class UpgradesToGroups extends Command
return $amount && $identifier;
});
/** @var null|Transaction */
return $set->first();
}

View File

@@ -106,17 +106,20 @@ class UpgradesVariousCurrencyInformation extends Command
break;
case TransactionTypeEnum::WITHDRAWAL->value:
/** @var null|Transaction $lead */
$lead = $journal->transactions()->where('amount', '<', 0)->first();
break;
case TransactionTypeEnum::DEPOSIT->value:
/** @var null|Transaction $lead */
$lead = $journal->transactions()->where('amount', '>', 0)->first();
break;
case TransactionTypeEnum::OPENING_BALANCE->value:
// whichever isn't an initial balance account:
/** @var null|Transaction $lead */
$lead = $journal
->transactions()
->leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')
@@ -129,6 +132,7 @@ class UpgradesVariousCurrencyInformation extends Command
case TransactionTypeEnum::RECONCILIATION->value:
// whichever isn't the reconciliation account:
/** @var null|Transaction $lead */
$lead = $journal
->transactions()
->leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')

View File

@@ -54,11 +54,10 @@ class DeletedAccountObserver
->pluck('transaction_journal_id')
->toArray()
;
$groupIds = TransactionJournal::whereIn('id', $journalIds)
->get(['transaction_journals.transaction_group_id'])
->pluck('transaction_group_id')
->toArray()
;
$groupIds = array_map(function (array $item) {
return $item['transaction_group_id'];
}, TransactionJournal::whereIn('id', $journalIds)->get(['transaction_journals.transaction_group_id'])->toArray());
if (count($journalIds) > 0) {
Transaction::whereIn('transaction_journal_id', $journalIds)->delete();

View File

@@ -34,7 +34,6 @@ use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\User;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
@@ -70,9 +69,6 @@ final class UserController extends Controller
$this->externalIdentity = 'web' !== config('firefly.authentication_guard');
}
/**
* @return Application|Factory|Redirector|RedirectResponse|View
*/
public function delete(User $user): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse
{
if ($this->externalIdentity) {

View File

@@ -27,7 +27,6 @@ use Carbon\Carbon;
use FireflyIII\Events\Security\System\UnknownUserTriedLogin;
use FireflyIII\Events\Security\User\UserFailedLoginAttempt;
use FireflyIII\Events\Security\User\UserSuccessfullyLoggedIn;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Providers\RouteServiceProvider;
use FireflyIII\Repositories\User\UserRepositoryInterface;
@@ -48,8 +47,6 @@ use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
/**
@@ -181,12 +178,6 @@ final class LoginController extends Controller
/**
* Show the application's login form.
*
* @return Application|Factory|Redirector|RedirectResponse|View
*
* @throws FireflyException
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function showLoginForm(Request $request): Factory|Redirector|RedirectResponse|View
{

View File

@@ -38,7 +38,6 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
@@ -75,14 +74,6 @@ final class RegisterController extends Controller
}
}
/**
* Handle a registration request for the application.
*
* @return Application|Redirector|RedirectResponse
*
* @throws FireflyException
* @throws ValidationException
*/
public function register(Request $request): Redirector|RedirectResponse
{
$allowRegistration = $this->allowedToRegister();

View File

@@ -224,7 +224,7 @@ final class IndexController extends Controller
Log::debug(sprintf('(getAllBudgets) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
// complement budget with budget limits in range, and expenses in currency X in range.
/** @var Budget $current */
/** @var Budget $budget */
foreach ($collection as $budget) {
Log::debug(sprintf('Working on budget #%d ("%s")', $budget->id, $budget->name));
$array = $budget->toArray();

View File

@@ -29,7 +29,6 @@ use FireflyIII\Http\Requests\ObjectGroupFormRequest;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
@@ -77,8 +76,6 @@ final class EditController extends Controller
/**
* Update a piggy bank.
*
* @return Application|Redirector|RedirectResponse
*/
public function update(ObjectGroupFormRequest $request, ObjectGroup $objectGroup): Redirector|RedirectResponse
{

View File

@@ -38,7 +38,6 @@ use FireflyIII\Support\Http\Controllers\CreateStuff;
use FireflyIII\User;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@@ -342,8 +341,6 @@ final class ProfileController extends Controller
}
/**
* @return Application|Redirector|RedirectResponse
*
* @throws AuthenticationException
*/
public function postLogoutOtherSessions(Request $request): Redirector|RedirectResponse

View File

@@ -24,7 +24,6 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\System;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
@@ -34,9 +33,6 @@ use Illuminate\Support\Facades\Log;
*/
final class CronController
{
/**
* @return Application|Response|ResponseFactory
*/
public function cron(): Response|ResponseFactory
{
Log::error('The cron endpoint has moved to GET /api/v1/cron/[token]');

View File

@@ -34,7 +34,6 @@ use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector;
@@ -47,8 +46,7 @@ use Illuminate\View\View;
*/
final class BulkController extends Controller
{
/** @var JournalRepositoryInterface Journals and transactions overview */
private $repository;
private JournalRepositoryInterface $repository;
/**
* BulkController constructor.
@@ -91,8 +89,6 @@ final class BulkController extends Controller
/**
* Update all journals.
*
* @return Application|Redirector|RedirectResponse
*/
public function update(BulkEditJournalRequest $request): Redirector|RedirectResponse
{

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Http\Controllers\Transaction;
use Carbon\Carbon;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Events\Model\TransactionGroup\DestroyedSingleTransactionGroup;
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventFlags;
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventObjects;
use FireflyIII\Events\Model\TransactionGroup\UpdatedSingleTransactionGroup;
@@ -41,7 +42,6 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Services\Internal\Update\JournalUpdateService;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Facades\Steam;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log;
@@ -84,16 +84,14 @@ final class MassController extends Controller
return view('transactions.mass.delete', ['journals' => $journals, 'subTitle' => $subTitle]);
}
/**
* Do the mass delete.
*
* @return Application|Redirector|RedirectResponse
*/
public function destroy(MassDeleteJournalRequest $request): Redirector|RedirectResponse
{
Log::debug(sprintf('Now in %s', __METHOD__));
$ids = $request->get('confirm_mass_delete');
$count = 0;
$ids = $request->input('confirm_mass_delete');
$count = 0;
$objects = new TransactionGroupEventObjects();
if (is_array($ids)) {
Log::debug('Array of IDs', $ids);
@@ -104,7 +102,9 @@ final class MassController extends Controller
/** @var null|TransactionJournal $journal */
$journal = $this->repository->find((int) $journalId);
if (null !== $journal && (int) $journalId === $journal->id) {
$objects->appendFromTransactionGroup($journal->transactionGroup);
$this->repository->destroyJournal($journal);
++$count;
Log::debug(sprintf('Deleted transaction journal #%d', $journalId));
@@ -116,6 +116,11 @@ final class MassController extends Controller
Preferences::mark();
session()->flash('success', trans_choice('firefly.mass_deleted_transactions_success', $count));
// trigger just after destruction
$flags = new TransactionGroupEventFlags();
event(new DestroyedSingleTransactionGroup($flags, $objects));
event(new WebhookMessagesRequestSending());
// redirect to previous URL:
return redirect($this->getPreviousUrl('transactions.mass-delete.url'));
}

View File

@@ -27,7 +27,6 @@ namespace FireflyIII\Http\Controllers\Webhooks;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Webhook;
use FireflyIII\Support\Facades\FireflyConfig;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Log;
@@ -56,11 +55,6 @@ final class DeleteController extends Controller
});
}
/**
* Delete account screen.
*
* @return Application|Factory|View
*/
public function index(Webhook $webhook): Factory|View
{
if (false === FireflyConfig::get('allow_webhooks', config('firefly.allow_webhooks'))->data) {

View File

@@ -27,7 +27,6 @@ namespace FireflyIII\Http\Controllers\Webhooks;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Webhook;
use FireflyIII\Support\Facades\FireflyConfig;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Log;
@@ -55,11 +54,6 @@ final class EditController extends Controller
});
}
/**
* Delete account screen.
*
* @return Application|Factory|View
*/
public function index(Webhook $webhook): Factory|View
{
if (false === FireflyConfig::get('allow_webhooks', config('firefly.allow_webhooks'))->data) {

View File

@@ -27,7 +27,6 @@ namespace FireflyIII\Http\Controllers\Webhooks;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Webhook;
use FireflyIII\Support\Facades\FireflyConfig;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Log;
@@ -55,11 +54,6 @@ final class ShowController extends Controller
});
}
/**
* Delete account screen.
*
* @return Application|Factory|View
*/
public function index(Webhook $webhook): Factory|View
{
if (false === FireflyConfig::get('allow_webhooks', config('firefly.allow_webhooks'))->data) {

View File

@@ -42,6 +42,9 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* @property AccountType $accountType
*/
#[ObservedBy([DeletedAccountObserver::class])]
class Account extends Model
{

View File

@@ -33,7 +33,8 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property Carbon $date
* @property Carbon $date
* @property null|PiggyBank $piggyBank
*/
#[ObservedBy([PiggyBankEventObserver::class])]
class PiggyBankEvent extends Model

View File

@@ -33,10 +33,12 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* @property User $user
* @property User $user
* @property Collection<RuleTrigger> $ruleTriggers
*/
#[ObservedBy([DeletedRuleObserver::class])]
class Rule extends Model

View File

@@ -102,13 +102,14 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U
public function findById(int $id): ?AvailableBudget
{
/** @var null|AvailableBudget */
return $this->user->availableBudgets->find($id);
}
#[Override]
public function findInRange(TransactionCurrency $currency, Carbon $start, Carbon $end): Collection
{
/** @var null|AvailableBudget */
/** @var Collection */
return $this->user
->availableBudgets()
->where('transaction_currency_id', $currency->id)

View File

@@ -305,6 +305,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
return $current;
});
/** @var Collection */
return $all;
}

View File

@@ -129,6 +129,7 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
*/
public function firstNull(): ?TransactionJournal
{
/** @var null|TransactionJournal */
return $this->user
->transactionJournals()
->orderBy('date', 'ASC')
@@ -150,7 +151,13 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
throw new FireflyException(sprintf('Your administration is broken. Transaction journal #%d has no destination transaction.', $journal->id));
}
return $transaction->account;
/** @var null|Account $res */
$res = $transaction->account;
if (null === $res) {
throw new FireflyException('Account is unexpectedly NULL.');
}
return $res;
}
/**
@@ -175,6 +182,7 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
public function getLast(): ?TransactionJournal
{
/** @var null|TransactionJournal */
return $this->user
->transactionJournals()
->orderBy('date', 'DESC')
@@ -221,7 +229,13 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
throw new FireflyException(sprintf('Your administration is broken. Transaction journal #%d has no source transaction.', $journal->id));
}
return $transaction->account;
/** @var null|Account $res */
$res = $transaction->account;
if (null === $res) {
throw new FireflyException('Account is unexpectedly NULL.');
}
return $res;
}
#[Override]

View File

@@ -33,6 +33,7 @@ use FireflyIII\Models\Category;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
/**
@@ -81,6 +82,8 @@ class BelongsUser implements ValidationRule
$objects = $class::where('user_id', '=', auth()->user()->id)->get();
}
$count = 0;
/** @var Model $object */
foreach ($objects as $object) {
$objectValue = trim((string) $object->{$field});
Log::debug(sprintf('Comparing object "%s" with value "%s"', $objectValue, $value));

View File

@@ -34,6 +34,7 @@ use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\UserGroup;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
/**
@@ -94,6 +95,8 @@ class BelongsUserGroup implements ValidationRule
$objects = $class::where('user_group_id', '=', $this->userGroup->id)->get();
}
$count = 0;
/** @var Model $object */
foreach ($objects as $object) {
$objectValue = trim((string) $object->{$field});
Log::debug(sprintf('Comparing object "%s" with value "%s"', $objectValue, $value));

View File

@@ -70,6 +70,8 @@ class IsAllowedGroupAction implements ValidationRule
private function validateUserGroup(): void
{
Log::debug('This method is not yet in use', $this->acceptedRoles);
try {
throw new FireflyException('Here we are');
} catch (FireflyException $e) {

View File

@@ -103,13 +103,9 @@ class GitHubUpdateRequest implements UpdateRequestInterface
return $response;
}
if (1 === $res) {
$response->setNewVersionAvailable(true);
$response->setNewVersionAvailable(true);
return $response;
}
// return $response;
return $response;
}
private function filterReleases(array $releases): array

View File

@@ -52,9 +52,6 @@ class CategoryUpdateService
}
}
/**
* @param mixed $user
*/
public function setUser(User $user): void
{
$this->user = $user;

View File

@@ -633,6 +633,9 @@ class JournalUpdateService
*/
private function updateField(string $fieldName): void
{
if (null === $this->transactionJournal) {
return;
}
if (array_key_exists($fieldName, $this->data) && '' !== (string) $this->data[$fieldName]) {
$value = $this->data[$fieldName];

View File

@@ -59,9 +59,9 @@ use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use League\Csv\AbstractCsv;
use League\Csv\CannotInsertRecord;
use League\Csv\Exception;
use League\Csv\Writer;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
@@ -88,7 +88,8 @@ class ExportDataGenerator
private bool $exportTransactions = false;
private Carbon $start;
private User $user;
private UserGroup $userGroup;
// private UserGroup $userGroup;
public function __construct()
{
@@ -222,7 +223,7 @@ class ExportDataGenerator
public function setUserGroup(UserGroup $userGroup): void
{
$this->userGroup = $userGroup;
// $this->userGroup = $userGroup;
}
/**
@@ -283,7 +284,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = AbstractCsv::fromString();
// insert the header
try {
@@ -352,7 +353,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = AbstractCsv::fromString();
// insert the header
try {
@@ -411,7 +412,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = AbstractCsv::fromString();
// insert the header
try {
@@ -456,7 +457,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = AbstractCsv::fromString();
// insert the header
try {
@@ -536,7 +537,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = AbstractCsv::fromString();
// insert the header
try {
@@ -703,7 +704,7 @@ class ExportDataGenerator
}
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = AbstractCsv::fromString();
// insert the header
try {
@@ -850,7 +851,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = AbstractCsv::fromString();
// insert the header
try {
@@ -906,7 +907,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = AbstractCsv::fromString();
// insert the header
try {
@@ -1102,7 +1103,7 @@ class ExportDataGenerator
}
// load the CSV document from a string
$csv = Writer::createFromString();
$csv = AbstractCsv::fromString();
// insert the header
try {

View File

@@ -105,10 +105,10 @@ class AvailableBudgetCalculator
$this->user = $user;
$this->abRepository = app(AvailableBudgetRepositoryInterface::class);
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
$this->abRepository->setUser($user);
$this->blRepository->setUser($user);
$this->abRepository->setUser($this->user);
$this->blRepository->setUser($this->user);
$viewRange = Preferences::getForUser($user, 'viewRange', '1M')->data;
$viewRange = Preferences::getForUser($this->user, 'viewRange', '1M')->data;
$viewRange = !is_string($viewRange) ? '1M' : $viewRange;
$this->viewRange = $this->correctViewRange($viewRange);
}

View File

@@ -71,7 +71,7 @@ class OperatorQuerySearch implements SearchInterface
private array $excludeTags = [];
private array $includeAnyTags = [];
// added to fix #8632
private array $includeTags = [];
// private array $includeTags = [];
// added to fix #11473
private array $includeAllTags = [];
private array $invalidOperators = [];

View File

@@ -247,13 +247,19 @@ class ConvertToDeposit implements ActionInterface
*/
private function getDestinationAccount(TransactionJournal $journal): Account
{
/** @var null|Transaction $destAccount */
$destAccount = $journal->transactions()->where('amount', '>', 0)->first();
if (null === $destAccount) {
/** @var null|Transaction $destTransaction */
$destTransaction = $journal->transactions()->where('amount', '>', 0)->first();
if (null === $destTransaction) {
throw new FireflyException(sprintf('Cannot find destination transaction for journal #%d', $journal->id));
}
return $destAccount->account;
/** @var null|Account $res */
$res = $destTransaction->account;
if (null === $res) {
throw new FireflyException('Account is unexpectedly NULL.');
}
return $res;
}
/**
@@ -267,6 +273,12 @@ class ConvertToDeposit implements ActionInterface
throw new FireflyException(sprintf('Cannot find source transaction for journal #%d', $journal->id));
}
return $sourceTransaction->account;
/** @var null|Account $res */
$res = $sourceTransaction->account;
if (null === $res) {
throw new FireflyException('Account is unexpectedly NULL.');
}
return $res;
}
}

View File

@@ -299,13 +299,19 @@ class ConvertToTransfer implements ActionInterface
*/
private function getDestinationAccount(TransactionJournal $journal): Account
{
/** @var null|Transaction $destAccount */
$destAccount = $journal->transactions()->where('amount', '>', 0)->first();
if (null === $destAccount) {
/** @var null|Transaction $destTransaction */
$destTransaction = $journal->transactions()->where('amount', '>', 0)->first();
if (null === $destTransaction) {
throw new FireflyException(sprintf('Cannot find destination transaction for journal #%d', $journal->id));
}
return $destAccount->account;
/** @var null|Account $res */
$res = $destTransaction->account;
if (null === $res) {
throw new FireflyException('Account is unexpectedly NULL.');
}
return $res;
}
private function getDestinationType(int $journalId): string
@@ -332,7 +338,13 @@ class ConvertToTransfer implements ActionInterface
throw new FireflyException(sprintf('Cannot find source transaction for journal #%d', $journal->id));
}
return $sourceTransaction->account;
/** @var null|Account $res */
$res = $sourceTransaction->account;
if (null === $res) {
throw new FireflyException('Account is unexpectedly NULL.');
}
return $res;
}
private function getSourceType(int $journalId): string

View File

@@ -238,13 +238,19 @@ class ConvertToWithdrawal implements ActionInterface
*/
private function getDestinationAccount(TransactionJournal $journal): Account
{
/** @var null|Transaction $destAccount */
$destAccount = $journal->transactions()->where('amount', '>', 0)->first();
if (null === $destAccount) {
/** @var null|Transaction $destTransaction */
$destTransaction = $journal->transactions()->where('amount', '>', 0)->first();
if (null === $destTransaction) {
throw new FireflyException(sprintf('Cannot find destination transaction for journal #%d', $journal->id));
}
return $destAccount->account;
/** @var null|Account $res */
$res = $destTransaction->account;
if (null === $res) {
throw new FireflyException('Account is unexpectedly NULL.');
}
return $res;
}
/**
@@ -258,6 +264,12 @@ class ConvertToWithdrawal implements ActionInterface
throw new FireflyException(sprintf('Cannot find source transaction for journal #%d', $journal->id));
}
return $sourceTransaction->account;
/** @var null|Account $res */
$res = $sourceTransaction->account;
if (null === $res) {
throw new FireflyException('Account is unexpectedly NULL.');
}
return $res;
}
}

View File

@@ -35,12 +35,18 @@ abstract class AbstractTransformer extends TransformerAbstract
{
protected ParameterBag $parameters;
/**
* @deprecated
*/
#[Deprecated]
final public function getParameters(): ParameterBag
{
return $this->parameters;
}
/**
* @deprecated
*/
#[Deprecated]
final public function setParameters(ParameterBag $parameters): void
{

View File

@@ -182,6 +182,7 @@ class TransactionGroupTransformer extends AbstractTransformer
*/
private function getDestinationTransaction(TransactionJournal $journal): Transaction
{
/** @var null|Transaction $result */
$result = $journal->transactions->first(static fn (Transaction $transaction): bool => (float) $transaction->amount > 0);
if (null === $result) {
throw new FireflyException(sprintf('Journal #%d unexpectedly has no destination transaction.', $journal->id));
@@ -224,6 +225,7 @@ class TransactionGroupTransformer extends AbstractTransformer
*/
private function getSourceTransaction(TransactionJournal $journal): Transaction
{
/** @var null|Transaction $result */
$result = $journal->transactions->first(static fn (Transaction $transaction): bool => (float) $transaction->amount < 0);
if (null === $result) {
throw new FireflyException(sprintf('Journal #%d unexpectedly has no source transaction.', $journal->id));

View File

@@ -90,7 +90,7 @@ class AccountValidator
Log::debug('AccountValidator source is set to NULL');
}
if ($account instanceof Account) {
Log::debug(sprintf('AccountValidator source is set to #%d: "%s" (%s)', $account->id, $account->name, $account->accountType?->type));
Log::debug(sprintf('AccountValidator source is set to #%d: "%s" (%s)', $account->id, $account->name, $account->accountType->type));
}
$this->source = $account;
}

View File

@@ -499,13 +499,7 @@ class FireflyValidator extends Validator
return true;
}
/**
* @param mixed $attribute
* @param mixed $value
*
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function validateSecurePassword($attribute, ?string $value): bool
public function validateSecurePassword(mixed $attribute, ?string $value): bool
{
$value = (string) $value;
$verify = false;

View File

@@ -2589,6 +2589,8 @@ problems:
## x.x.x - 20xx-xx-xx
<!-- summary: If you can read this I forgot to update the summary! -->
### Added
- Initial release.

18
composer.lock generated
View File

@@ -10545,16 +10545,16 @@
},
{
"name": "fruitcake/laravel-debugbar",
"version": "v4.0.10",
"version": "v4.1.1",
"source": {
"type": "git",
"url": "https://github.com/fruitcake/laravel-debugbar.git",
"reference": "96afd5efc93c2cb3140df356893381296259695b"
"reference": "048876cf8ffdd8af2b82306289e2c0453fa0b059"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/96afd5efc93c2cb3140df356893381296259695b",
"reference": "96afd5efc93c2cb3140df356893381296259695b",
"url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/048876cf8ffdd8af2b82306289e2c0453fa0b059",
"reference": "048876cf8ffdd8af2b82306289e2c0453fa0b059",
"shasum": ""
},
"require": {
@@ -10562,7 +10562,7 @@
"illuminate/session": "^11|^12|^13.0",
"illuminate/support": "^11|^12|^13.0",
"php": "^8.2",
"php-debugbar/php-debugbar": "^3.3.1",
"php-debugbar/php-debugbar": "^3.5",
"php-debugbar/symfony-bridge": "^1.1"
},
"replace": {
@@ -10576,7 +10576,7 @@
"laravel/telescope": "^5.16",
"livewire/livewire": "^3.7|^4",
"mockery/mockery": "^1.3.3",
"orchestra/testbench-dusk": "^9|^10",
"orchestra/testbench-dusk": "^9|^10|^11",
"php-debugbar/twig-bridge": "^2.0",
"phpstan/phpstan-phpunit": "^2",
"phpstan/phpstan-strict-rules": "^2.0",
@@ -10594,7 +10594,7 @@
]
},
"branch-alias": {
"dev-master": "4.0-dev"
"dev-master": "4.1-dev"
}
},
"autoload": {
@@ -10631,7 +10631,7 @@
],
"support": {
"issues": "https://github.com/fruitcake/laravel-debugbar/issues",
"source": "https://github.com/fruitcake/laravel-debugbar/tree/v4.0.10"
"source": "https://github.com/fruitcake/laravel-debugbar/tree/v4.1.1"
},
"funding": [
{
@@ -10643,7 +10643,7 @@
"type": "github"
}
],
"time": "2026-02-26T11:45:48+00:00"
"time": "2026-03-08T08:20:19+00:00"
},
{
"name": "hamcrest/hamcrest-php",

View File

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