Refactor phpstan errors.

This commit is contained in:
James Cole 2023-10-29 17:41:14 +01:00
parent 5e32878d01
commit 12675dd950
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
60 changed files with 297 additions and 386 deletions

View File

@ -5,14 +5,21 @@ includes:
- ../vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon
parameters:
universalObjectCratesClasses:
- Illuminate\Database\Eloquent\Model
reportUnmatchedIgnoredErrors: false
ignoreErrors:
- '#is not allowed to extend#'
- '#is neither abstract nor final#'
- '#has a nullable return type declaration#'
- '#with a nullable type declaration#'
- '#with null as default value#'
- 'No error to ignore is reported on#'
- '#is not covariant with PHPDoc type array#'
-
message: '#Constructor in [a-zA-Z0-9\\_]+ has parameter \$[a-zA-Z0-9\\_]+ with default value#'
paths:
- ../app/Exceptions/IntervalException.php
- ../app/Support/Navigation.php
-
message: '#but containers should not be injected#'
paths:
@ -67,5 +74,5 @@ parameters:
- ../bootstrap/app.php
# The level 8 is the highest level. original was 5
level: 1
level: 2

View File

@ -38,8 +38,6 @@ use Illuminate\Http\JsonResponse;
*/
class ShowController extends Controller
{
use ConvertsExchangeRates;
private BudgetRepositoryInterface $repository;
/**
@ -69,7 +67,6 @@ class ShowController extends Controller
{
$data = $request->getAll();
$result = $this->repository->budgetedInPeriodForBudget($budget, $data['start'], $data['end']);
//$converted = $this->cerSum(array_values($result));
return response()->json($result);
}
@ -83,7 +80,6 @@ class ShowController extends Controller
{
$data = $request->getAll();
$result = $this->repository->spentInPeriodForBudget($budget, $data['start'], $data['end']);
// $converted = $this->cerSum(array_values($result));
return response()->json($result);
}

View File

@ -36,8 +36,6 @@ use Illuminate\Http\JsonResponse;
*/
class SumController extends Controller
{
use ConvertsExchangeRates;
private BudgetRepositoryInterface $repository;
/**
@ -65,12 +63,10 @@ class SumController extends Controller
*/
public function budgeted(DateRequest $request): JsonResponse
{
throw new FireflyException('Needs refactoring, uses deprecated method.');
$data = $request->getAll();
$result = $this->repository->budgetedInPeriod($data['start'], $data['end']);
$converted = $this->cerSum(array_values($result));
return response()->json($converted);
return response()->json($result);
}
/**
@ -83,11 +79,9 @@ class SumController extends Controller
*/
public function spent(DateRequest $request): JsonResponse
{
throw new FireflyException('Needs refactoring, uses deprecated method.');
$data = $request->getAll();
$result = $this->repository->spentInPeriod($data['start'], $data['end']);
$converted = $this->cerSum(array_values($result));
return response()->json($converted);
return response()->json($result);
}
}

View File

@ -40,7 +40,6 @@ use Illuminate\Http\JsonResponse;
class NetWorthController extends Controller
{
use ValidatesUserGroupTrait;
use ConvertsExchangeRates;
private NetWorthInterface $netWorth;
private AccountRepositoryInterface $repository;

View File

@ -167,7 +167,7 @@ class CorrectAmounts extends Command
return;
}
/** @var BudgetLimit $item */
/** @var CurrencyExchangeRate $item */
foreach ($set as $item) {
$item->rate = app('steam')->positive((string)$item->rate);
$item->save();
@ -207,7 +207,7 @@ class CorrectAmounts extends Command
return;
}
/** @var PiggyBankRepetition $item */
/** @var PiggyBank $item */
foreach ($set as $item) {
$item->targetamount = app('steam')->positive((string)$item->targetamount);
$item->save();
@ -229,7 +229,7 @@ class CorrectAmounts extends Command
return;
}
/** @var PiggyBankRepetition $item */
/** @var RecurrenceTransaction $item */
foreach ($set as $item) {
$item->amount = app('steam')->positive((string)$item->amount);
$item->foreign_amount = app('steam')->positive((string)$item->foreign_amount);

View File

@ -506,8 +506,8 @@ class ForceDecimalSize extends Command
continue;
}
// fix $field by rounding it down correctly.
$pow = pow(10, (int)$currency->decimal_places);
$correct = bcdiv((string)round($value * $pow), (string)$pow, 12);
$pow = (float)pow(10, (int)$currency->decimal_places);
$correct = bcdiv((string)round((float)$value * $pow), (string)$pow, 12);
$this->friendlyWarning(sprintf('Transaction #%d has amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct));
Transaction::find($item->id)->update(['amount' => $correct]);
}
@ -533,8 +533,8 @@ class ForceDecimalSize extends Command
continue;
}
// fix $field by rounding it down correctly.
$pow = pow(10, (int)$currency->decimal_places);
$correct = bcdiv((string)round($value * $pow), (string)$pow, 12);
$pow = (float)pow(10, (int)$currency->decimal_places);
$correct = bcdiv((string)round((float)$value * $pow), (string)$pow, 12);
$this->friendlyWarning(
sprintf('Transaction #%d has foreign amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct)
);

View File

@ -27,7 +27,9 @@ namespace FireflyIII\Console\Commands\System;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
use Illuminate\Database\QueryException;
use Illuminate\Filesystem\FilesystemAdapter;
use League\Flysystem\FilesystemException;
use League\Flysystem\FilesystemReader;
use Storage;
/**

View File

@ -3,7 +3,7 @@
/*
* IntervalException.php
* Copyright (c) 2023 Antonio Spinelli https://github.com/tonicospinelli
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -23,7 +23,7 @@
declare(strict_types=1);
namespace FireflyIII\Support\Calendar\Exceptions;
namespace FireflyIII\Exceptions;
use Exception;
use FireflyIII\Support\Calendar\Periodicity;
@ -34,9 +34,17 @@ use Throwable;
*/
final class IntervalException extends Exception
{
public readonly array $availableIntervals;
public readonly Periodicity $periodicity;
protected $message = 'The periodicity %s is unknown. Choose one of available periodicity: %s';
protected $message = 'The periodicity %s is unknown. Choose one of available periodicity: %s';
public function __construct(string $message = "", int $code = 0, ?Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
$this->availableIntervals = [];
$this->periodicity = Periodicity::Monthly;
}
/**
* @param Periodicity $periodicity
@ -51,7 +59,8 @@ final class IntervalException extends Exception
array $intervals,
int $code = 0,
?Throwable $previous = null
): IntervalException {
): IntervalException
{
$message = sprintf(
'The periodicity %s is unknown. Choose one of available periodicity: %s',
$periodicity->name,

View File

@ -1107,7 +1107,7 @@ class GroupCollector implements GroupCollectorInterface
/**
* Set the user object and start the query.
*
* @param User $user
* @param UserGroup $userGroup
*
* @return GroupCollectorInterface
*/

View File

@ -271,6 +271,11 @@ class InterestingMessage
return null !== $code && null !== $message;
}
/**
* @param Request $request
*
* @return void
*/
private function handleCurrencyMessage(Request $request): void
{
// params:
@ -278,7 +283,7 @@ class InterestingMessage
$code = $request->get('code');
$message = $request->get('message');
/** @var TransactionCurrency $webhook */
/** @var TransactionCurrency $currency */
$currency = TransactionCurrency::whereCode($code)->first();
if (null === $currency) {

View File

@ -227,7 +227,7 @@ class CreateAutoBudgetLimits implements ShouldQueue
* @param Carbon $end
* @param string|null $amount
*/
private function createBudgetLimit(AutoBudget $autoBudget, Carbon $start, Carbon $end, ?string $amount = null)
private function createBudgetLimit(AutoBudget $autoBudget, Carbon $start, Carbon $end, ?string $amount = null): void
{
app('log')->debug(sprintf('No budget limit exist. Must create one for auto-budget #%d', $autoBudget->id));
if (null !== $amount) {

View File

@ -78,19 +78,17 @@ class AccountMeta extends Model
/**
* @param mixed $value
*
* @return mixed
* @return string
*/
public function getDataAttribute($value): string
public function getDataAttribute(mixed $value): string
{
return (string)json_decode($value, true);
}
/**
* @param mixed $value
*
*/
public function setDataAttribute($value): void
public function setDataAttribute(mixed $value): void
{
$this->attributes['data'] = json_encode($value);
}

View File

@ -30,6 +30,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Carbon;
@ -145,7 +146,7 @@ class PiggyBank extends Model
}
/**
* Get all of the piggy bank's notes.
* Get all the piggy bank's notes.
*/
public function notes(): MorphMany
{
@ -155,7 +156,7 @@ class PiggyBank extends Model
/**
* Get all the tags for the post.
*/
public function objectGroups()
public function objectGroups(): MorphToMany
{
return $this->morphToMany(ObjectGroup::class, 'object_groupable');
}

View File

@ -60,7 +60,7 @@ class AccountTasker implements AccountTaskerInterface
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
$return = [
'accounts' => [],
@ -160,7 +160,7 @@ class AccountTasker implements AccountTaskerInterface
*/
private function groupExpenseByDestination(array $array): array
{
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
/** @var CurrencyRepositoryInterface $currencyRepos */
$currencyRepos = app(CurrencyRepositoryInterface::class);
$currencies = [$defaultCurrency->id => $defaultCurrency,];
@ -257,7 +257,7 @@ class AccountTasker implements AccountTaskerInterface
*/
private function groupIncomeBySource(array $array): array
{
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
/** @var CurrencyRepositoryInterface $currencyRepos */
$currencyRepos = app(CurrencyRepositoryInterface::class);
$currencies = [$defaultCurrency->id => $defaultCurrency,];

View File

@ -294,7 +294,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface
$factory = app(TransactionCurrencyFactory::class);
$currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null);
if (null === $currency) {
$currency = app('amount')->getDefaultCurrencyByUser($this->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
}
$currency->enabled = true;
$currency->save();
@ -371,7 +371,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface
}
// catch unexpected null:
if (null === $currency) {
$currency = $budgetLimit->transactionCurrency ?? app('amount')->getDefaultCurrencyByUser($this->user);
$currency = $budgetLimit->transactionCurrency ?? app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
}
$currency->enabled = true;
$currency->save();

View File

@ -416,7 +416,7 @@ class BudgetRepository implements BudgetRepositoryInterface
$autoBudget = $this->getAutoBudget($budget);
// grab default currency:
$currency = app('amount')->getDefaultCurrencyByUser($this->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
if (null === $autoBudget) {
// at this point it's a blind assumption auto_budget_type is 1 or 2.
@ -847,7 +847,7 @@ class BudgetRepository implements BudgetRepositoryInterface
$currency = $repos->findByCode((string)$data['currency_code']);
}
if (null === $currency) {
$currency = app('amount')->getDefaultCurrencyByUser($this->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
}
$autoBudget = new AutoBudget();

View File

@ -220,67 +220,6 @@ class OperationsRepository implements OperationsRepositoryInterface
return $repos->getActiveBudgets();
}
/**
* @param Collection $budgets
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
* @deprecated
*/
public function spentInPeriodMc(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array
{
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user);
$collector->setRange($start, $end)->setBudgets($budgets)->withBudgetInformation();
if ($accounts->count() > 0) {
$collector->setAccounts($accounts);
}
// TODO possible candidate for "get extracted groups" method.
$set = $collector->getGroups();
$return = [];
$total = [];
$currencies = [];
/** @var array $group */
foreach ($set as $group) {
/** @var array $transaction */
foreach ($group['transactions'] as $transaction) {
$code = $transaction['currency_code'];
if (!array_key_exists($code, $currencies)) {
$currencies[$code] = [
'id' => $transaction['currency_id'],
'decimal_places' => $transaction['currency_decimal_places'],
'code' => $transaction['currency_code'],
'name' => $transaction['currency_name'],
'symbol' => $transaction['currency_symbol'],
];
}
$total[$code] = array_key_exists($code, $total) ? bcadd($total[$code], $transaction['amount']) : $transaction['amount'];
}
}
/**
* @var string $code
* @var string $spent
*/
foreach ($total as $code => $spent) {
/** @var TransactionCurrency $currency */
$currency = $currencies[$code];
$return[] = [
'currency_id' => (string)$currency['id'],
'currency_code' => $code,
'currency_name' => $currency['name'],
'currency_symbol' => $currency['symbol'],
'currency_decimal_places' => $currency['decimal_places'],
'amount' => app('steam')->bcround($spent, $currency['decimal_places']),
];
}
return $return;
}
/**
* @param Carbon $start
* @param Carbon $end
@ -289,7 +228,6 @@ class OperationsRepository implements OperationsRepositoryInterface
* @param TransactionCurrency|null $currency
*
* @return array
* @deprecated
*/
public function sumExpenses(
Carbon $start,

View File

@ -75,29 +75,12 @@ interface OperationsRepositoryInterface
*/
public function setUser(User | Authenticatable | null $user): void;
/**
* Return multi-currency spent information.
*
* @param Collection $budgets
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
* @deprecated
*/
public function spentInPeriodMc(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array;
/**
* TODO this method was marked as deprecated but I'm not sure why.
*
* @param Carbon $start
* @param Carbon $end
* @param Collection|null $accounts
* @param Collection|null $budgets
* @param TransactionCurrency|null $currency
*
* @return array
*
*/

View File

@ -194,7 +194,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
$accountRepos = app(AccountRepositoryInterface::class);
$accountRepos->setUser($this->user);
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user);
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
$piggyBankCurrency = $accountRepos->getAccountCurrency($piggyBank->account) ?? $defaultCurrency;
app('log')->debug(sprintf('Piggy bank #%d currency is %s', $piggyBank->id, $piggyBankCurrency->code));

View File

@ -401,7 +401,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface
{
$return = [];
$journals = $group->transactionJournals->pluck('id')->toArray();
$currency = app('amount')->getDefaultCurrencyByUser($this->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
$data = PiggyBankEvent::whereIn('transaction_journal_id', $journals)
->with('piggyBank', 'piggyBank.account')
->get(['piggy_bank_events.*']);

View File

@ -299,10 +299,12 @@ class UserRepository implements UserRepositoryInterface
if (null === $user) {
return false;
}
/** @var Role $userRole */
foreach ($user->roles as $userRole) {
if ($userRole->name === $role) {
return true;
if ($user instanceof User) {
/** @var Role $userRole */
foreach ($user->roles as $userRole) {
if ($userRole->name === $role) {
return true;
}
}
}

View File

@ -220,7 +220,7 @@ class UserGroupRepository implements UserGroupRepositoryInterface
return $userGroup;
}
// count the number of members in the group right now:
$membershipCount = $userGroup->groupMemberships()->distinct()->get(['group_memberships.user_id'])->count();
$membershipCount = $userGroup->groupMemberships()->distinct()->count(['group_memberships.user_id']);
// if it's 1:
if (1 === $membershipCount) {

View File

@ -27,6 +27,7 @@ namespace FireflyIII\Repositories\UserGroups\Account;
use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\User;
use Illuminate\Support\Collection;
/**
@ -34,6 +35,14 @@ use Illuminate\Support\Collection;
*/
interface AccountRepositoryInterface
{
/**
* @param User $user
*
* @return void
*/
public function setUser(User $user): void;
/**
* @param int $accountId
*

View File

@ -27,6 +27,7 @@ namespace FireflyIII\Repositories\UserGroups\Bill;
use Carbon\Carbon;
use FireflyIII\Models\Bill;
use FireflyIII\User;
use Illuminate\Support\Collection;
/**
@ -34,6 +35,13 @@ use Illuminate\Support\Collection;
*/
interface BillRepositoryInterface
{
/**
* @param User $user
*
* @return void
*/
public function setUser(User $user): void;
/**
* TODO duplicate of other repos
* Add correct order to bills.

View File

@ -26,12 +26,19 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Budget;
use Carbon\Carbon;
use FireflyIII\User;
/**
* Interface AvailableBudgetRepositoryInterface
*/
interface AvailableBudgetRepositoryInterface
{
/**
* @param User $user
*
* @return void
*/
public function setUser(User $user): void;
/**
* @param Carbon $start
* @param Carbon $end

View File

@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Budget;
use FireflyIII\User;
use Illuminate\Support\Collection;
/**
@ -32,6 +33,12 @@ use Illuminate\Support\Collection;
*/
interface BudgetRepositoryInterface
{
/**
* @param User $user
*
* @return void
*/
public function setUser(User $user): void;
/**
* @return Collection
*/

View File

@ -26,6 +26,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Budget;
use Carbon\Carbon;
use FireflyIII\User;
use Illuminate\Support\Collection;
/**
@ -33,6 +34,13 @@ use Illuminate\Support\Collection;
*/
interface OperationsRepositoryInterface
{
/**
* @param User $user
*
* @return void
*/
public function setUser(User $user): void;
/**
* This method returns a list of all the withdrawal transaction journals (as arrays) set in that period
* which have the specified budget set to them. It's grouped per currency, with as few details in the array

View File

@ -262,7 +262,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
if (null === $result) {
app('log')->debug('Grabbing default currency for this user...');
$result = app('amount')->getDefaultCurrencyByUser($this->user);
$result = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
}
if (null === $result) {

View File

@ -27,10 +27,17 @@ namespace FireflyIII\Repositories\UserGroups\Currency;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\User;
use Illuminate\Support\Collection;
interface CurrencyRepositoryInterface
{
/**
* @param User $user
*
* @return void
*/
public function setUser(User $user): void;
/**
* @param TransactionCurrency $currency
*

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\UserGroups\Journal;
use FireflyIII\User;
use Illuminate\Support\Collection;
/**
@ -30,6 +31,13 @@ use Illuminate\Support\Collection;
*/
interface JournalRepositoryInterface
{
/**
* @param User $user
*
* @return void
*/
public function setUser(User $user): void;
/**
* Search in journal descriptions.
*

View File

@ -23,45 +23,35 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Closure;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidationRule;
/**
*
* Class IsAssetAccountId
*/
class IsAssetAccountId implements Rule
class IsAssetAccountId implements ValidationRule
{
/**
* Get the validation error message. This is not translated because only the API uses it.
* @param string $attribute
* @param mixed $value
* @param Closure $fail
*
* @return string
* @return void
*/
public function message(): string
{
return 'This is not an asset account.';
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
*
* @return bool
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$accountId = (int)$value;
$account = Account::with('accountType')->find($accountId);
/** @var Account|null $account */
$account = Account::with('accountType')->find($accountId);
if (null === $account) {
return false;
$fail('validation.no_asset_account')->translate();
return;
}
if ($account->accountType->type !== AccountType::ASSET && $account->accountType->type !== AccountType::DEFAULT) {
return false;
$fail('validation.no_asset_account')->translate();
}
return true;
}
}

View File

@ -24,46 +24,36 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Class IsBoolean
*/
class IsBoolean implements Rule
class IsBoolean implements ValidationRule
{
/**
* Get the validation error message.
*
* @return string
*/
public function message(): string
{
return (string)trans('validation.boolean');
}
/**
* Determine if the validation rule passes.
* @param string $attribute
* @param mixed $value
* @param Closure $fail
*
* @param string $attribute
* @param mixed $value
*
* @return bool
* @return void
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (is_bool($value)) {
return true;
return;
}
if (is_int($value) && 0 === $value) {
return true;
if (0 === $value) {
return;
}
if (is_int($value) && 1 === $value) {
return true;
if (1 === $value) {
return;
}
if (is_string($value) && in_array($value, ['0', '1', 'true', 'false', 'on', 'off', 'yes', 'no', 'y', 'n'], true)) {
return true;
if (in_array($value, ['0', '1', 'true', 'false', 'on', 'off', 'yes', 'no', 'y', 'n'], true)) {
return;
}
return false;
$fail('validation.boolean')->translate();
}
}

View File

@ -27,36 +27,28 @@ namespace FireflyIII\Rules;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Class IsDateOrTime
*/
class IsDateOrTime implements Rule
class IsDateOrTime implements ValidationRule
{
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return (string)trans('validation.date_or_time');
}
/**
* Determine if the validation rule passes.
* @param string $attribute
* @param mixed $value
* @param Closure $fail
*
* @param string $attribute
* @param mixed $value
*
* @return bool
* @return void
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$value = (string)$value;
if ('' === $value) {
return false;
$fail('validation.date_or_time')->translate();;
return;
}
if (10 === strlen($value)) {
// probably a date format.
@ -65,14 +57,16 @@ class IsDateOrTime implements Rule
} catch (InvalidDateException $e) {
app('log')->error(sprintf('"%s" is not a valid date: %s', $value, $e->getMessage()));
return false;
$fail('validation.date_or_time')->translate();;
return;
} catch (InvalidFormatException $e) {
app('log')->error(sprintf('"%s" is of an invalid format: %s', $value, $e->getMessage()));
return false;
$fail('validation.date_or_time')->translate();;
return;
}
return true;
return;
}
// is an atom string, I hope?
try {
@ -80,13 +74,13 @@ class IsDateOrTime implements Rule
} catch (InvalidDateException $e) {
app('log')->error(sprintf('"%s" is not a valid date or time: %s', $value, $e->getMessage()));
return false;
$fail('validation.date_or_time')->translate();;
return;
} catch (InvalidFormatException $e) {
app('log')->error(sprintf('"%s" is of an invalid format: %s', $value, $e->getMessage()));
return false;
$fail('validation.date_or_time')->translate();;
return;
}
return true;
}
}

View File

@ -23,30 +23,25 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* TODO not sure where this is used.
*
* Class IsDuplicateTransaction
*/
class IsDuplicateTransaction implements Rule
class IsDuplicateTransaction implements ValidationRule
{
private string $value;
/**
* @inheritDoc
*/
public function message()
{
return $this->value;
}
/**
* @inheritDoc
*/
public function passes($attribute, $value)
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$this->value = $value;
return false;
$fail($this->value);
}
}

View File

@ -24,34 +24,25 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Closure;
use FireflyIII\Models\TransactionType;
use FireflyIII\Validation\AccountValidator;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Class IsTransferAccount
*/
class IsTransferAccount implements Rule
class IsTransferAccount implements ValidationRule
{
/**
* Get the validation error message.
*
* @return string
*/
public function message(): string
{
return (string)trans('validation.not_transfer_account');
}
/**
* Determine if the validation rule passes.
* @param string $attribute
* @param mixed $value
* @param Closure $fail
*
* @param string $attribute
* @param mixed $value
*
* @return bool
* @return void
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
app('log')->debug(sprintf('Now in %s(%s)', __METHOD__, $value));
/** @var AccountValidator $validator */
@ -64,11 +55,13 @@ class IsTransferAccount implements Rule
app('log')->debug('Found account based on name. Return true.');
// found by name, use repos to return.
return true;
return;
}
$validAccount = $validator->validateSource(['id' => (int)$value,]);
app('log')->debug(sprintf('Search by id (%d), result is %s.', (int)$value, var_export($validAccount, true)));
return false !== $validAccount;
if(false === $validAccount) {
$fail('validation.not_transfer_account')->translate();
}
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Closure;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
@ -39,15 +40,15 @@ use FireflyIII\Repositories\Journal\JournalAPIRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Class IsValidAttachmentModel
*/
class IsValidAttachmentModel implements Rule
class IsValidAttachmentModel implements ValidationRule
{
/** @var string */
private $model;
private string $model;
/**
* IsValidAttachmentModel constructor.
@ -76,27 +77,17 @@ class IsValidAttachmentModel implements Rule
}
/**
* Get the validation error message.
* @param string $attribute
* @param mixed $value
* @param Closure $fail
*
* @return string
* @return void
*/
public function message(): string
{
return (string)trans('validation.model_id_invalid');
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
*
* @return bool
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (!auth()->check()) {
return false;
$fail('validation.model_id_invalid')->translate();
return;
}
$methods = [
Account::class => 'validateAccount',
@ -111,11 +102,15 @@ class IsValidAttachmentModel implements Rule
if (!array_key_exists($this->model, $methods)) {
app('log')->error(sprintf('Cannot validate model "%s" in %s.', substr($this->model, 0, 20), __METHOD__));
return false;
$fail('validation.model_id_invalid')->translate();
return;
}
$method = $methods[$this->model];
return $this->$method((int)$value);
$result = $this->$method((int)$value);
if(false === $result) {
$fail('validation.model_id_invalid')->translate();
}
}
/**

View File

@ -24,14 +24,15 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Facades\Validator;
use JsonException;
/**
* Class IsValidBulkClause
*/
class IsValidBulkClause implements Rule
class IsValidBulkClause implements ValidationRule
{
private string $error;
private array $rules;
@ -54,19 +55,18 @@ class IsValidBulkClause implements Rule
}
/**
* @param string $attribute
* @param mixed $value
* @param string $attribute
* @param mixed $value
* @param Closure $fail
*
* @return bool
* @return void
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$result = $this->basicValidation((string)$value);
if (false === $result) {
return false;
$fail($this->error);
}
return true;
}
/**

View File

@ -24,12 +24,13 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Class LessThanPiggyTarget
*/
class LessThanPiggyTarget implements Rule
class LessThanPiggyTarget implements ValidationRule
{
/**
* Get the validation error message.
@ -42,15 +43,14 @@ class LessThanPiggyTarget implements Rule
}
/**
* Determine if the validation rule passes.
* @param string $attribute
* @param mixed $value
* @param Closure $fail
*
* @param string $attribute
* @param mixed $value
*
* @return bool
* @return void
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
return true;
// TODO not sure if this is still used.
}
}

View File

@ -23,15 +23,16 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Closure;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\AccountType;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Class UniqueAccountNumber
*/
class UniqueAccountNumber implements Rule
class UniqueAccountNumber implements ValidationRule
{
private ?Account $account;
private ?string $expectedType;
@ -73,21 +74,19 @@ class UniqueAccountNumber implements Rule
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
*
* @return bool
* @param string $attribute
* @param mixed $value
* @param Closure $fail
*
* @return void
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (!auth()->check()) {
return true;
return;
}
if (null === $this->expectedType) {
return true;
return;
}
$maxCounts = $this->getMaxOccurrences();
@ -105,12 +104,11 @@ class UniqueAccountNumber implements Rule
)
);
return false;
$fail('validation.unique_account_number_for_user')->translate();
return;
}
}
app('log')->debug('Account number is valid.');
return true;
}
/**

View File

@ -24,40 +24,30 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Closure;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Class ValidJournals
*
*/
class ValidJournals implements Rule
class ValidJournals implements ValidationRule
{
/**
* Get the validation error message.
*
* @return string
*/
public function message(): string
{
return (string)trans('validation.invalid_selection');
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
*
* @return bool
* @param string $attribute
* @param mixed $value
* @param Closure $fail
*
* @return void
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
app('log')->debug('In ValidJournals::passes');
if (!is_array($value)) {
return true;
return;
}
$userId = auth()->user()->id;
foreach ($value as $journalId) {
@ -65,11 +55,10 @@ class ValidJournals implements Rule
if (0 === $count) {
app('log')->debug(sprintf('Count for transaction #%d and user #%d is zero! Return FALSE', $journalId, $userId));
return false;
$fail('validation.invalid_selection')->translate();
return;
}
}
app('log')->debug('Return true!');
return true;
}
}

View File

@ -23,25 +23,16 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Class ValidRecurrenceRepetitionType
*
*/
class ValidRecurrenceRepetitionType implements Rule
class ValidRecurrenceRepetitionType implements ValidationRule
{
/**
* Get the validation error message.
*
* @return string
*/
public function message(): string
{
return (string)trans('validation.valid_recurrence_rep_type');
}
/**
* Determine if the validation rule passes.
*
@ -51,24 +42,24 @@ class ValidRecurrenceRepetitionType implements Rule
* @return bool
*
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$value = (string)$value;
if ('daily' === $value) {
return true;
return;
}
//monthly,17
//ndom,3,7
if (in_array(substr($value, 0, 6), ['yearly', 'weekly'], true)) {
return true;
return;
}
if (str_starts_with($value, 'monthly')) {
return true;
return;
}
if (str_starts_with($value, 'ndom')) {
return true;
return;
}
return false;
$fail('validation.valid_recurrence_rep_type')->translate();
}
}

View File

@ -24,7 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use Carbon\Carbon;
use Illuminate\Contracts\Validation\Rule;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use InvalidArgumentException;
/**
@ -32,56 +33,44 @@ use InvalidArgumentException;
*
*/
class ValidRecurrenceRepetitionValue implements Rule
class ValidRecurrenceRepetitionValue implements ValidationRule
{
/**
* Get the validation error message.
* @param string $attribute
* @param mixed $value
* @param Closure $fail
*
* @return string
* @return void
*/
public function message(): string
{
return (string)trans('validation.valid_recurrence_rep_type');
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
*
* @return bool
*
*/
public function passes($attribute, $value): bool
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$value = (string)$value;
if ('daily' === $value) {
return true;
return;
}
if (str_starts_with($value, 'monthly')) {
return $this->validateMonthly($value);
if (str_starts_with($value, 'monthly') && $this->validateMonthly($value)) {
return;
}
// Value is like: ndom,3,7
// nth x-day of the month.
if (str_starts_with($value, 'ndom')) {
return $this->validateNdom($value);
if (str_starts_with($value, 'ndom') && $this->validateNdom($value)) {
return;
}
// Value is like: weekly,7
if (str_starts_with($value, 'weekly')) {
return $this->validateWeekly($value);
if (str_starts_with($value, 'weekly') && $this->validateWeekly($value)) {
return ;
}
// Value is like: yearly,2018-01-01
if (str_starts_with($value, 'yearly')) {
return $this->validateYearly($value);
if (str_starts_with($value, 'yearly') && $this->validateYearly($value)) {
return ;
}
return false;
$fail('validation.valid_recurrence_rep_type')->translate();
}
/**

View File

@ -255,7 +255,7 @@ trait AccountServiceTrait
// get or grab currency:
$currency = $this->accountRepository->getAccountCurrency($account);
if (null === $currency) {
$currency = app('default')->getDefaultCurrencyByUser($account->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
}
// submit to factory:
@ -386,7 +386,7 @@ trait AccountServiceTrait
if (null === $currency) {
// use default currency:
$currency = app('amount')->getDefaultCurrencyByUser($this->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
}
$currency->enabled = true;
$currency->save();
@ -433,7 +433,7 @@ trait AccountServiceTrait
// if exists, update:
$currency = $this->accountRepository->getAccountCurrency($account);
if (null === $currency) {
$currency = app('default')->getDefaultCurrencyByUser($account->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($account->user);
}
// simply grab the first journal and change it:
@ -500,7 +500,7 @@ trait AccountServiceTrait
// get or grab currency:
$currency = $this->accountRepository->getAccountCurrency($account);
if (null === $currency) {
$currency = app('default')->getDefaultCurrencyByUser($account->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
}
// submit to factory:
@ -632,7 +632,7 @@ trait AccountServiceTrait
// if exists, update:
$currency = $this->accountRepository->getAccountCurrency($account);
if (null === $currency) {
$currency = app('default')->getDefaultCurrencyByUser($account->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
}
// simply grab the first journal and change it:
@ -715,7 +715,7 @@ trait AccountServiceTrait
// get or grab currency:
$currency = $this->accountRepository->getAccountCurrency($account);
if (null === $currency) {
$currency = app('default')->getDefaultCurrencyByUser($account->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
}
// submit to factory:

View File

@ -119,7 +119,7 @@ trait RecurringTransactionTrait
$currency = $factory->find($array['currency_id'] ?? null, $array['currency_code'] ?? null);
$foreignCurrency = $factory->find($array['foreign_currency_id'] ?? null, $array['foreign_currency_code'] ?? null);
if (null === $currency) {
$currency = app('amount')->getDefaultCurrencyByUser($recurrence->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($recurrence->user->userGroup);
}
app('log')->debug(

View File

@ -60,7 +60,7 @@ class BillUpdateService
if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) {
$factory = app(TransactionCurrencyFactory::class);
$currency = $factory->find((int)($data['currency_id'] ?? null), $data['currency_code'] ?? null) ??
app('amount')->getDefaultCurrencyByUser($bill->user);
app('amount')->getDefaultCurrencyByUserGroup($bill->user->userGroup);
// enable the currency if it isn't.
$currency->enabled = true;

View File

@ -121,7 +121,7 @@ class Amount
/** @var User $user */
$user = auth()->user();
return $this->getDefaultCurrencyByUser($user);
return $this->getDefaultCurrencyByUserGroup($user->userGroup);
}
/**

View File

@ -26,7 +26,7 @@ declare(strict_types=1);
namespace FireflyIII\Support\Calendar;
use Carbon\Carbon;
use FireflyIII\Support\Calendar\Exceptions\IntervalException;
use FireflyIII\Exceptions\IntervalException;
use SplObjectStorage;
/**

View File

@ -37,7 +37,7 @@ abstract class Interval implements Interspacable
*
* @return int
*/
public function skip(int $skip): int
final public function skip(int $skip): int
{
return static::INTERVAL * $skip;
}

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Support\Form;
use Amount as Amt;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
@ -68,11 +67,10 @@ class CurrencyForm
$classes = $this->getHolderClasses($name);
$value = $this->fillFieldValue($name, $value);
$options['step'] = 'any';
$defaultCurrency = $options['currency'] ?? Amt::getDefaultCurrency();
$defaultCurrency = $options['currency'] ?? app('amount')->getDefaultCurrency();
/** @var Collection $currencies */
$currencies = app('amount')->getCurrencies();
unset($options['currency'], $options['placeholder']);
// perhaps the currency has been sent to us in the field $amount_currency_id_$name (amount_currency_id_amount)
$preFilled = session('preFilled');
if (!is_array($preFilled)) {
@ -140,7 +138,7 @@ class CurrencyForm
$classes = $this->getHolderClasses($name);
$value = $this->fillFieldValue($name, $value);
$options['step'] = 'any';
$defaultCurrency = $options['currency'] ?? Amt::getDefaultCurrency();
$defaultCurrency = $options['currency'] ?? app('amount')->getDefaultCurrency();
/** @var Collection $currencies */
$currencies = app('amount')->getAllCurrencies();
unset($options['currency'], $options['placeholder']);

View File

@ -25,9 +25,9 @@ namespace FireflyIII\Support;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Exceptions\IntervalException;
use FireflyIII\Helpers\Fiscal\FiscalHelperInterface;
use FireflyIII\Support\Calendar\Calculator;
use FireflyIII\Support\Calendar\Exceptions\IntervalException;
use FireflyIII\Support\Calendar\Periodicity;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
@ -111,7 +111,7 @@ class Navigation
return $this->calculator->nextDateByInterval($epoch, $periodicity, $skipInterval);
} catch (IntervalException $exception) {
app('log')->warning($exception->getMessage(), ['exception' => $exception]);
} catch (Throwable $exception) {
} catch (Throwable $exception) { // @phpstan-ignore-line
app('log')->error($exception->getMessage(), ['exception' => $exception]);
}
@ -144,8 +144,8 @@ class Navigation
$workEnd = clone $loopDate;
while ($loopCount < 13) {
// make range:
$workStart = \Navigation::startOfPeriod($workStart, $range);
$workEnd = \Navigation::endOfPeriod($workStart, $range);
$workStart = $this->startOfPeriod($workStart, $range);
$workEnd = $this->endOfPeriod($workStart, $range);
// make sure we don't go overboard
if ($workEnd->gt($start)) {

View File

@ -373,6 +373,6 @@ class BudgetReportGenerator
$this->blRepository->setUser($user);
$this->opsRepository->setUser($user);
$this->nbRepository->setUser($user);
$this->currency = app('amount')->getDefaultCurrencyByUser($user);
$this->currency = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup);
}
}

View File

@ -134,7 +134,7 @@ class Steam
if (null === $currency) {
$repository = app(AccountRepositoryInterface::class);
$repository->setUser($account->user);
$currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUser($account->user);
$currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
}
$currencyId = (int)$currency->id;
@ -211,7 +211,7 @@ class Steam
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
if (null === $currency) {
$currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUser($account->user);
$currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
}
// first part: get all balances in own currency:
$transactions = $account->transactions()

View File

@ -184,7 +184,7 @@ class AccountTransformer extends AbstractTransformer
// only grab default when result is null:
if (null === $currency) {
$currency = app('amount')->getDefaultCurrencyByUser($account->user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
}
$currencyId = (string)$currency->id;
$currencyCode = $currency->code;

View File

@ -67,7 +67,7 @@ class PiggyBankEventTransformer extends AbstractTransformer
$this->piggyRepos->setUser($account->user);
// get associated currency or fall back to the default:
$currency = $this->repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUser($account->user);
$currency = $this->repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
// get associated journal and transaction, if any:
$journalId = $event->transaction_journal_id;

View File

@ -67,7 +67,7 @@ class PiggyBankTransformer extends AbstractTransformer
$this->piggyRepos->setUser($account->user);
// get currency from account, or use default.
$currency = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUser($account->user);
$currency = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup);
// note
$notes = $this->piggyRepos->getNoteText($piggyBank);

View File

@ -131,7 +131,7 @@ class PiggyBankTransformer extends AbstractTransformer
$this->notes[$id] = $note;
}
$this->default = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->default = app('amount')->getDefaultCurrencyByUserGroup(auth()->user()->userGroup);
$this->converter = new ExchangeRateConverter();
}

View File

@ -43,7 +43,6 @@ use stdClass;
*/
class TransactionGroupTransformer extends AbstractTransformer
{
use ConvertsExchangeRates;
private ExchangeRateConverter $converter;
private array $currencies = [];

View File

@ -24,6 +24,7 @@
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

View File

@ -34,6 +34,7 @@ return [
'invalid_query_currency' => 'Your query contains accounts that have different currency settings, which is not allowed.',
'iban' => 'This is not a valid IBAN.',
'zero_or_more' => 'The value cannot be negative.',
'no_asset_account' => 'This is not an asset account.',
'date_or_time' => 'The value must be a valid date or time value (ISO 8601).',
'source_equals_destination' => 'The source account equals the destination account.',
'unique_account_number_for_user' => 'It looks like this account number is already in use.',

View File

@ -25,8 +25,8 @@ declare(strict_types=1);
namespace Tests\unit\Support\Calendar;
use FireflyIII\Exceptions\IntervalException;
use FireflyIII\Support\Calendar\Calculator;
use FireflyIII\Support\Calendar\Exceptions\IntervalException;
use FireflyIII\Support\Calendar\Periodicity;
use Generator;
use PHPUnit\Framework\TestCase;