Various code cleanup.

This commit is contained in:
James Cole
2018-07-26 06:10:17 +02:00
parent e8c9554dd6
commit 6bcfea1de4
37 changed files with 351 additions and 185 deletions

View File

@@ -23,7 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use Carbon\Carbon;
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\BudgetLimit;
@@ -34,13 +34,13 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use InvalidArgumentException;
use League\Fractal\Manager;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\JsonApiSerializer;
use Log;
/**
* Class BudgetLimitController.

View File

@@ -265,8 +265,8 @@ class CreateImport extends Command
*/
private function validArguments(): bool
{
$file = $this->argument('file');
$configuration = $this->argument('configuration');
$file = (string)$this->argument('file');
$configuration = (string)$this->argument('configuration');
$cwd = getcwd();
$validTypes = config('import.options.file.import_formats');
$type = strtolower($this->option('type'));

View File

@@ -63,8 +63,8 @@ class DecryptAttachment extends Command
$repository = app(AttachmentRepositoryInterface::class);
$attachmentId = (int)$this->argument('id');
$attachment = $repository->findWithoutUser($attachmentId);
$attachmentName = trim($this->argument('name'));
$storagePath = realpath(trim($this->argument('directory')));
$attachmentName = trim((string)$this->argument('name'));
$storagePath = realpath(trim((string)$this->argument('directory')));
if (null === $attachment) {
$this->error(sprintf('No attachment with id #%d', $attachmentId));
Log::error(sprintf('DecryptAttachment: No attachment with id #%d', $attachmentId));

View File

@@ -62,7 +62,7 @@ class Import extends Command
public function handle(): int
{
Log::debug('Start start-import command');
$jobKey = $this->argument('key');
$jobKey = (string)$this->argument('key');
$job = ImportJob::where('key', $jobKey)->first();
if (null === $job) {
$this->errorLine(sprintf('No job found with key "%s"', $jobKey));

View File

@@ -48,10 +48,10 @@ class UpgradeFireflyInstructions extends Command
*/
public function handle(): int
{
if ('update' === $this->argument('task')) {
if ('update' === (string)$this->argument('task')) {
$this->updateInstructions();
}
if ('install' === $this->argument('task')) {
if ('install' === (string)$this->argument('task')) {
$this->installInstructions();
}
return 0;

View File

@@ -189,7 +189,7 @@ class AccountFactory
}
if (null === $result) {
/** @var string $type */
$type = (string)config('firefly.accountTypeByIdentifier.' . (string)$accountType);
$type = (string)config('firefly.accountTypeByIdentifier.' . $accountType);
$result = AccountType::whereType($type)->first();
if (null === $result && null !== $accountType) {
// try as full name:

View File

@@ -24,14 +24,14 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Events;
use Carbon\Carbon;
use FireflyConfig;
use FireflyIII\Events\RequestedVersionCheckStatus;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Update\UpdateTrait;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Services\Github\Object\Release;
use FireflyIII\Services\Github\Request\UpdateRequest;
use FireflyIII\User;
use Log;
@@ -66,7 +66,6 @@ class VersionCheckEventHandler
return;
}
$permission = FireflyConfig::get('permission_update_check', -1);
$lastCheckTime = FireflyConfig::get('last_update_check', time());
$now = time();
$diff = $now - $lastCheckTime->data;

View File

@@ -185,7 +185,7 @@ class ReconcileController extends Controller
if (TransactionType::RECONCILIATION !== $journal->transactionType->type) {
return redirect(route('transactions.show', [$journal->id]));
}
$subTitle = (string)trans('firefly.reconciliation') . ' "' . $journal->description . '"';
$subTitle = trans('firefly.reconciliation') . ' "' . $journal->description . '"';
// get main transaction:
$transaction = $this->repository->getAssetTransaction($journal);

View File

@@ -146,8 +146,9 @@ class AttachmentController extends Controller
$this->rememberPreviousUri('attachments.edit.uri');
}
$request->session()->forget('attachments.edit.fromUpdate');
$preFilled['notes'] = $this->repository->getNoteText($attachment);
$preFilled = [
'notes' => $this->repository->getNoteText($attachment),
];
$request->session()->flash('preFilled', $preFilled);
return view('attachments.edit', compact('attachment', 'subTitleIcon', 'subTitle'));

View File

@@ -29,7 +29,7 @@ use FireflyIII\Helpers\Collector\JournalCollectorInterface;
use FireflyIII\Helpers\Filter\InternalTransferFilter;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Http\Request;

View File

@@ -22,7 +22,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use Cache;
use FireflyIII\Http\Requests\CurrencyFormRequest;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;

View File

@@ -78,7 +78,7 @@ class HelpController extends Controller
private function getHelpText(string $route, string $language): string
{
// get language and default variables.
$content = '<p>' . (string)trans('firefly.route_has_no_help') . '</p>';
$content = '<p>' . trans('firefly.route_has_no_help') . '</p>';
// if no such route, log error and return default text.
if (!$this->help->hasRoute($route)) {
@@ -120,6 +120,6 @@ class HelpController extends Controller
return $content;
}
return '<p>' . (string)trans('firefly.route_has_no_help') . '</p>';
return '<p>' . trans('firefly.route_has_no_help') . '</p>';
}
}

View File

@@ -97,8 +97,8 @@ class JobStatusController extends Controller
if ('file' === $importJob->provider) {
$json['download_config'] = true;
$json['download_config_text']
= (string)trans('import.should_download_config', ['route' => route('import.job.download', [$importJob->key])]) . ' '
. (string)trans('import.share_config_file');
= trans('import.should_download_config', ['route' => route('import.job.download', [$importJob->key])]) . ' '
. trans('import.share_config_file');
}
// if count is zero:

View File

@@ -463,6 +463,7 @@ class ImportArrayStorage
foreach ($transaction['transactions'] as $current) {
// get the amount:
/** @noinspection UnnecessaryCastingInspection */
$amount = (string)($current['amount'] ?? '0');
if (bccomp($amount, '0') === -1) {
$amount = bcmul($amount, '-1'); // @codeCoverageIgnore

View File

@@ -31,6 +31,7 @@ use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
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\SoftDeletes;
use Illuminate\Support\Collection;
use Log;
@@ -200,7 +201,7 @@ class Account extends Model
* @codeCoverageIgnore
* Get all of the notes.
*/
public function notes()
public function notes(): MorphMany
{
return $this->morphMany(Note::class, 'noteable');
}

View File

@@ -27,6 +27,7 @@ use Crypt;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -180,7 +181,7 @@ class Attachment extends Model
* @codeCoverageIgnore
* Get all of the notes.
*/
public function notes()
public function notes(): MorphMany
{
return $this->morphMany(Note::class, 'noteable');
}

View File

@@ -28,6 +28,7 @@ use FireflyIII\User;
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\SoftDeletes;
use Illuminate\Support\Collection;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -155,7 +156,7 @@ class Bill extends Model
* @codeCoverageIgnore
* Get all of the notes.
*/
public function notes()
public function notes(): MorphMany
{
return $this->morphMany(Note::class, 'noteable');
}

View File

@@ -24,6 +24,7 @@ namespace FireflyIII\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
@@ -58,7 +59,7 @@ class Note extends Model
*
* Get all of the owning noteable models.
*/
public function noteable()
public function noteable(): MorphTo
{
return $this->morphTo();
}

View File

@@ -26,6 +26,7 @@ use Carbon\Carbon;
use Crypt;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -123,7 +124,7 @@ class PiggyBank extends Model
* @codeCoverageIgnore
* Get all of the piggy bank's notes.
*/
public function notes()
public function notes(): MorphMany
{
return $this->morphMany(Note::class, 'noteable');
}

View File

@@ -28,6 +28,7 @@ use FireflyIII\User;
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\SoftDeletes;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -112,7 +113,7 @@ class Recurrence extends Model
* @codeCoverageIgnore
* Get all of the notes.
*/
public function notes()
public function notes(): MorphMany
{
return $this->morphMany(Note::class, 'noteable');
}

View File

@@ -30,6 +30,7 @@ use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -59,6 +60,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property string period_marker
* @property Carbon $date
* @property string $transaction_type_type
* @property int $id
* @property TransactionType $transactionType
*
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -248,7 +251,7 @@ class TransactionJournal extends Model
* @codeCoverageIgnore
* Get all of the notes.
*/
public function notes()
public function notes(): MorphMany
{
return $this->morphMany(Note::class, 'noteable');
}

View File

@@ -26,6 +26,7 @@ use Carbon\Carbon;
use Crypt;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
@@ -111,7 +112,7 @@ class TransactionJournalLink extends Model
* @codeCoverageIgnore
* Get all of the notes.
*/
public function notes()
public function notes(): MorphMany
{
return $this->morphMany(Note::class, 'noteable');
}

View File

@@ -106,7 +106,7 @@ class EventServiceProvider extends ServiceProvider
* @codeCoverageIgnore
* Register any events for your application.
*/
public function boot()
public function boot(): void
{
parent::boot();
$this->registerCreateEvents();

View File

@@ -34,7 +34,7 @@ class SessionServiceProvider extends BaseSessionServiceProvider
/**
* Register the service provider.
*/
public function register()
public function register(): void
{
$this->registerSessionManager();

View File

@@ -24,8 +24,8 @@ namespace FireflyIII\Repositories\Account;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Note;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\User;
use Illuminate\Support\Collection;

View File

@@ -31,6 +31,7 @@ use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Models\Attachment;
use FireflyIII\Models\Note;
use FireflyIII\User;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\Collection;
use Log;
use Storage;
@@ -81,6 +82,7 @@ class AttachmentRepository implements AttachmentRepositoryInterface
/**
* @param int $attachmentId
*
* @return Attachment|null
*/
public function findWithoutUser(int $attachmentId): ?Attachment
@@ -119,8 +121,6 @@ class AttachmentRepository implements AttachmentRepositoryInterface
* @param Attachment $attachment
*
* @return string
*
* @throws \Illuminate\Contracts\Encryption\DecryptException
*/
public function getContent(Attachment $attachment): string
{
@@ -130,7 +130,12 @@ class AttachmentRepository implements AttachmentRepositoryInterface
$content = '';
if ($disk->exists($file)) {
$content = Crypt::decrypt($disk->get($file));
try {
$content = Crypt::decrypt($disk->get($file));
} catch (FileNotFoundException $e) {
Log::debug(sprintf('File not found: %e', $e->getMessage()));
$content = false;
}
}
if (\is_bool($content)) {
Log::error(sprintf('Attachment #%d may be corrupted: the content could not be decrypted.', $attachment->id));

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Repositories\ExportJob;
use Carbon\Carbon;
use FireflyIII\Models\ExportJob;
use FireflyIII\User;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\Str;
use Log;
use Storage;
@@ -120,6 +121,7 @@ class ExportJobRepository implements ExportJobRepositoryInterface
/**
* @param string $key
*
* @return ExportJob|null
*/
public function findByKey(string $key): ?ExportJob
@@ -137,14 +139,19 @@ class ExportJobRepository implements ExportJobRepositoryInterface
* @param ExportJob $job
*
* @return string
*
*/
public function getContent(ExportJob $job): string
{
$disk = Storage::disk('export');
$file = $job->key . '.zip';
$disk = Storage::disk('export');
$file = $job->key . '.zip';
$content = '';
try {
$content = $disk->get($file);
} catch (FileNotFoundException $e) {
Log::warning(sprintf('File not found: %s', $e->getMessage()));
}
return $disk->get($file);
return $content;
}
/**

View File

@@ -25,7 +25,7 @@ namespace FireflyIII\Repositories\Journal;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\Note;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionJournalMeta;

View File

@@ -65,8 +65,11 @@ class BelongsUser implements Rule
*
* @return bool
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function passes($attribute, $value)
public function passes($attribute, $value): bool
{
$attribute = $this->parseAttribute($attribute);
if (!auth()->check()) {
@@ -75,48 +78,22 @@ class BelongsUser implements Rule
$attribute = (string)$attribute;
switch ($attribute) {
case 'piggy_bank_id':
$count = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
->where('piggy_banks.id', '=', (int)$value)
->where('accounts.user_id', '=', auth()->user()->id)->count();
return $count === 1;
break;
return $this->validatePiggyBankId((int)$value);
case 'piggy_bank_name':
$count = $this->countField(PiggyBank::class, 'name', $value);
return $count === 1;
break;
return $this->validatePiggyBankName($value);
case 'bill_id':
$count = Bill::where('id', '=', (int)$value)->where('user_id', '=', auth()->user()->id)->count();
return $count === 1;
return $this->validateBillId((int)$value);
case 'bill_name':
$count = $this->countField(Bill::class, 'name', $value);
return $count === 1;
break;
return $this->validateBillName($value);
case 'budget_id':
$count = Budget::where('id', '=', (int)$value)->where('user_id', '=', auth()->user()->id)->count();
return $count === 1;
break;
return $this->validateBudgetId((int)$value);
case 'category_id':
$count = Category::where('id', '=', (int)$value)->where('user_id', '=', auth()->user()->id)->count();
return $count === 1;
break;
return $this->validateCategoryId((int)$value);
case 'budget_name':
$count = $this->countField(Budget::class, 'name', $value);
return $count === 1;
break;
return $this->validateBudgetName($value);
case 'source_id':
case 'destination_id':
$count = Account::where('id', '=', (int)$value)->where('user_id', '=', auth()->user()->id)->count();
return $count === 1;
break;
return $this->validateAccountId((int)$value);
default:
throw new FireflyException(sprintf('Rule BelongUser cannot handle "%s"', $attribute)); // @codeCoverageIgnore
}
@@ -128,18 +105,20 @@ class BelongsUser implements Rule
* @param string $value
*
* @return int
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
protected function countField(string $class, string $field, string $value): int
{
$objects = [];
// get all objects belonging to user:
switch ($class) {
case PiggyBank::class:
$objects = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
->where('accounts.user_id', '=', auth()->user()->id)->get(['piggy_banks.*']);
break;
default:
$objects = $class::where('user_id', '=', auth()->user()->id)->get();
break;
if (PiggyBank::class === $class) {
$objects = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
->where('accounts.user_id', '=', auth()->user()->id)->get(['piggy_banks.*']);
}
if (PiggyBank::class !== $class) {
$objects = $class::where('user_id', '=', auth()->user()->id)->get();
}
$count = 0;
foreach ($objects as $object) {
@@ -159,13 +138,111 @@ class BelongsUser implements Rule
private function parseAttribute(string $attribute): string
{
$parts = explode('.', $attribute);
if (\count($parts) === 1) {
if (1 === \count($parts)) {
return $attribute;
}
if (\count($parts) === 3) {
if (3 === \count($parts)) {
return $parts[2];
}
return $attribute; // @codeCoverageIgnore
}
/**
* @param int $value
*
* @return bool
*/
private function validateAccountId(int $value): bool
{
$count = Account::where('id', '=', (int)$value)->where('user_id', '=', auth()->user()->id)->count();
return 1 === $count;
}
/**
* @param int $value
*
* @return bool
*/
private function validateBillId(int $value): bool
{
$count = Bill::where('id', '=', $value)->where('user_id', '=', auth()->user()->id)->count();
return 1 === $count;
}
/**
* @param string $value
*
* @return bool
*/
private function validateBillName(string $value): bool
{
$count = $this->countField(Bill::class, 'name', $value);
return 1 === $count;
}
/**
* @param int $value
*
* @return bool
*/
private function validateBudgetId(int $value): bool
{
$count = Budget::where('id', '=', $value)->where('user_id', '=', auth()->user()->id)->count();
return 1 === $count;
}
/**
* @param string $value
*
* @return bool
*/
private function validateBudgetName(string $value): bool
{
$count = $this->countField(Budget::class, 'name', $value);
return 1 === $count;
}
/**
* @param int $value
*
* @return bool
*/
private function validateCategoryId(int $value): bool
{
$count = Category::where('id', '=', $value)->where('user_id', '=', auth()->user()->id)->count();
return 1 === $count;
}
/**
* @param int $value
*
* @return bool
*/
private function validatePiggyBankId(int $value): bool
{
$count = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
->where('piggy_banks.id', '=', $value)
->where('accounts.user_id', '=', auth()->user()->id)->count();
return 1 === $count;
}
/**
* @param string $value
*
* @return bool
*/
private function validatePiggyBankName(string $value): bool
{
$count = $this->countField(PiggyBank::class, 'name', $value);
return 1 === $count;
}
}

View File

@@ -49,6 +49,8 @@ class IsAssetAccountId implements Rule
* @param mixed $value
*
* @return bool
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function passes($attribute, $value): bool
{

View File

@@ -24,7 +24,6 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Contracts\Validation\Rule;
@@ -64,25 +63,25 @@ class IsValidAttachmentModel implements Rule
* @param mixed $value
*
* @return bool
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function passes($attribute, $value): bool
{
if (!auth()->check()) {
return false;
}
$user = auth()->user();
switch ($this->model) {
default:
throw new FireflyException(sprintf('Model "%s" cannot be validated.', $this->model));
case TransactionJournal::class:
/** @var JournalRepositoryInterface $repository */
$repository = app(JournalRepositoryInterface::class);
$repository->setUser($user);
$result = $repository->findNull((int)$value);
return null !== $result;
break;
if (TransactionJournal::class === $this->model) {
$repository = app(JournalRepositoryInterface::class);
$user = auth()->user();
$repository->setUser($user);
$result = $repository->findNull((int)$value);
return null !== $result;
}
return false;
}
}

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Rules;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use Illuminate\Contracts\Validation\Rule;
@@ -57,7 +56,7 @@ class UniqueIban implements Rule
*
* @return string
*/
public function message()
public function message(): string
{
return (string)trans('validation.unique_iban_for_user');
}
@@ -69,9 +68,10 @@ class UniqueIban implements Rule
* @param mixed $value
*
* @return bool
* @throws FireflyException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function passes($attribute, $value)
public function passes($attribute, $value): bool
{
if (!auth()->check()) {
return true; // @codeCoverageIgnore
@@ -79,50 +79,11 @@ class UniqueIban implements Rule
if (null === $this->expectedType) {
return true;
}
$maxCounts = [
AccountType::ASSET => 0,
AccountType::EXPENSE => 0,
AccountType::REVENUE => 0,
];
switch ($this->expectedType) {
case 'asset':
case AccountType::ASSET:
// iban should be unique amongst asset accounts
// should not be in use with expense or revenue accounts.
// ie: must be totally unique.
break;
case 'expense':
case AccountType::EXPENSE:
// should be unique amongst expense and asset accounts.
// may appear once in revenue accounts
$maxCounts[AccountType::REVENUE] = 1;
break;
case 'revenue':
case AccountType::REVENUE:
// should be unique amongst revenue and asset accounts.
// may appear once in expense accounts
$maxCounts[AccountType::EXPENSE] = 1;
break;
default:
throw new FireflyException(sprintf('UniqueIban cannot handle type "%s"', $this->expectedType));
}
$maxCounts = $this->getMaxOccurrences();
foreach ($maxCounts as $type => $max) {
$count = 0;
$query = auth()->user()
->accounts()
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.type', $type);
if (null !== $this->account) {
$query->where('accounts.id', '!=', $this->account->id);
}
$result = $query->get(['accounts.*']);
foreach ($result as $account) {
if ($account->iban === $value) {
$count++;
}
}
$count = $this->countHits($type, $value);
if ($count > $max) {
Log::debug(
sprintf(
@@ -137,4 +98,57 @@ class UniqueIban implements Rule
return true;
}
/**
* @param string $type
* @param string $iban
*
* @return int
*/
private function countHits(string $type, string $iban): int
{
$count = 0;
/** @noinspection NullPointerExceptionInspection */
$query = auth()->user()
->accounts()
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.type', $type);
if (null !== $this->account) {
$query->where('accounts.id', '!=', $this->account->id);
}
$result = $query->get(['accounts.*']);
foreach ($result as $account) {
if ($account->iban === $iban) {
$count++;
}
}
return $count;
}
/**
* @return array
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function getMaxOccurrences(): array
{
$maxCounts = [
AccountType::ASSET => 0,
AccountType::EXPENSE => 0,
AccountType::REVENUE => 0,
];
if ('expense' === $this->expectedType || AccountType::EXPENSE === $this->expectedType) {
// IBAN should be unique amongst expense and asset accounts.
// may appear once in revenue accounts
$maxCounts[AccountType::REVENUE] = 1;
}
if ('revenue' === $this->expectedType || AccountType::EXPENSE === $this->expectedType) {
// IBAN should be unique amongst revenue and asset accounts.
// may appear once in expense accounts
$maxCounts[AccountType::EXPENSE] = 1;
}
return $maxCounts;
}
}

View File

@@ -48,11 +48,13 @@ class ValidRecurrenceRepetitionType implements Rule
* @param mixed $value
*
* @return bool
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function passes($attribute, $value): bool
{
$value = (string)$value;
if ($value === 'daily') {
if ('daily' === $value) {
return true;
}
//monthly,17

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Rules;
use Carbon\Carbon;
use Illuminate\Contracts\Validation\Rule;
use InvalidArgumentException;
use Log;
/**
* Class ValidRecurrenceRepetitionValue
@@ -51,57 +52,103 @@ class ValidRecurrenceRepetitionValue implements Rule
* @param mixed $value
*
* @return bool
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function passes($attribute, $value): bool
{
$value = (string)$value;
if ($value === 'daily') {
if ('daily' === $value) {
return true;
}
if (0 === strpos($value, 'monthly')) {
$dayOfMonth = (int)substr($value, 8);
return $dayOfMonth > 0 && $dayOfMonth < 32;
return $this->validateMonthly($value);
}
//ndom,3,7
// nth x-day of the month.
if (0 === strpos($value, 'ndom')) {
$parameters = explode(',', substr($value, 5));
if (\count($parameters) !== 2) {
return false;
}
$nthDay = (int)($parameters[0] ?? 0.0);
$dayOfWeek = (int)($parameters[1] ?? 0.0);
if ($nthDay < 1 || $nthDay > 5) {
return false;
}
return $dayOfWeek > 0 && $dayOfWeek < 8;
return $this->validateNdom($value);
}
//weekly,7
if (0 === strpos($value, 'weekly')) {
$dayOfWeek = (int)substr($value, 7);
return $dayOfWeek > 0 && $dayOfWeek < 8;
return $this->validateWeekly($value);
}
//yearly,2018-01-01
if (0 === strpos($value, 'yearly')) {
// rest of the string must be valid date:
$dateString = substr($value, 7);
try {
$date = Carbon::createFromFormat('Y-m-d', $dateString);
} catch (InvalidArgumentException $e) {
return false;
}
return true;
return $this->validateYearly($value);
}
return false;
}
/**
* @param string $value
*
* @return bool
*/
private function validateMonthly(string $value): bool
{
$dayOfMonth = (int)substr($value, 8);
return $dayOfMonth > 0 && $dayOfMonth < 32;
}
/**
* @param string $value
*
* @return bool
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function validateNdom(string $value): bool
{
$parameters = explode(',', substr($value, 5));
if (2 !== \count($parameters)) {
return false;
}
$nthDay = (int)($parameters[0] ?? 0.0);
$dayOfWeek = (int)($parameters[1] ?? 0.0);
if ($nthDay < 1 || $nthDay > 5) {
return false;
}
return $dayOfWeek > 0 && $dayOfWeek < 8;
}
/**
* @param string $value
*
* @return bool
*/
private function validateWeekly(string $value): bool
{
$dayOfWeek = (int)substr($value, 7);
return $dayOfWeek > 0 && $dayOfWeek < 8;
}
/**
* @param string $value
*
* @return bool
*/
private function validateYearly(string $value): bool
{
// rest of the string must be valid date:
$dateString = substr($value, 7);
try {
Carbon::createFromFormat('Y-m-d', $dateString);
} catch (InvalidArgumentException $e) {
Log::debug(sprintf('Could not parse date %s: %s', $dateString, $e->getMessage()));
return false;
}
return true;
}
}

View File

@@ -49,7 +49,7 @@ class ValidTransactions implements Rule
*
* @return string
*/
public function message()
public function message(): string
{
return (string)trans('validation.invalid_selection');
}
@@ -61,8 +61,9 @@ class ValidTransactions implements Rule
* @param mixed $value
*
* @return bool
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function passes($attribute, $value)
public function passes($attribute, $value): bool
{
Log::debug('In ValidTransactions::passes');
if (!\is_array($value)) {
@@ -73,7 +74,7 @@ class ValidTransactions implements Rule
$count = Transaction::where('transactions.id', $transactionId)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->where('accounts.user_id', $userId)->count();
if ($count === 0) {
if (0 === $count) {
Log::debug(sprintf('Count for transaction #%d and user #%d is zero! Return FALSE', $transactionId, $userId));
return false;

View File

@@ -75,7 +75,8 @@ class TransactionUpdateService
$currency = $this->findCurrency($data['currency_id'], $data['currency_code']);
$journal = $transaction->transactionJournal;
$description = $journal->description === $data['description'] ? null : $data['description'];
$amount = (string)$data['amount'];
$account = null;
// update description:
$transaction->description = $description;
$foreignAmount = null;
@@ -83,7 +84,7 @@ class TransactionUpdateService
// this is the source transaction.
$type = $this->accountType($journal, 'source');
$account = $this->findAccount($type, $data['source_id'], $data['source_name']);
$amount = app('steam')->negative((string)$data['amount']);
$amount = app('steam')->negative($amount);
$foreignAmount = app('steam')->negative((string)$data['foreign_amount']);
}
@@ -91,7 +92,7 @@ class TransactionUpdateService
// this is the destination transaction.
$type = $this->accountType($journal, 'destination');
$account = $this->findAccount($type, $data['destination_id'], $data['destination_name']);
$amount = app('steam')->positive((string)$data['amount']);
$amount = app('steam')->positive($amount);
$foreignAmount = app('steam')->positive((string)$data['foreign_amount']);
}

View File

@@ -124,8 +124,8 @@ class PiggyBankTransformer extends TransformerAbstract
$accountRepos = app(AccountRepositoryInterface::class);
$accountRepos->setUser($account->user);
$currencyId = (int)$accountRepos->getMetaValue($account, 'currency_id');
if ($currencyId === 0) {
$currency = null;
if (0 === $currencyId) {
$currency = app('amount')->getDefaultCurrencyByUser($account->user);
}