GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (724)

app/Validation/FireflyValidator.php (14 issues)

1
<?php
2
/**
3
 * FireflyValidator.php
4
 * Copyright (c) 2019 [email protected]
5
 *
6
 * This file is part of Firefly III (https://github.com/firefly-iii).
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
declare(strict_types=1);
22
23
namespace FireflyIII\Validation;
24
25
use Config;
26
use DB;
27
use FireflyIII\Models\Account;
28
use FireflyIII\Models\AccountMeta;
29
use FireflyIII\Models\AccountType;
30
use FireflyIII\Models\Budget;
31
use FireflyIII\Models\PiggyBank;
32
use FireflyIII\Models\TransactionType;
33
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
34
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
35
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
36
use FireflyIII\Services\Password\Verifier;
37
use FireflyIII\TransactionRules\Triggers\TriggerInterface;
38
use FireflyIII\User;
39
use Google2FA;
40
use Illuminate\Support\Collection;
41
use Illuminate\Validation\Validator;
42
43
/**
44
 * Class FireflyValidator.
45
 */
46
class FireflyValidator extends Validator
47
{
48
    /**
49
     * @param $attribute
50
     * @param $value
51
     *
52
     * @return bool
53
     */
54
    public function validate2faCode($attribute, $value): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

54
    public function validate2faCode(/** @scrutinizer ignore-unused */ $attribute, $value): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
55
    {
56
        if (!\is_string($value) || null === $value || 6 !== strlen($value)) {
57
            return false;
58
        }
59
60
        $secret = session('two-factor-secret');
61
62
        return Google2FA::verifyKey($secret, $value);
63
    }
64
65
    /**
66
     * @param $attribute
67
     * @param $value
68
     * @param $parameters
69
     *
70
     * @return bool
71
     */
72
    public function validateBelongsToUser($attribute, $value, $parameters): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

72
    public function validateBelongsToUser(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
73
    {
74
        $field = $parameters[1] ?? 'id';
75
76
        if (0 === (int)$value) {
77
            return true;
78
        }
79
        $count = DB::table($parameters[0])->where('user_id', auth()->user()->id)->where($field, $value)->count();
80
81
        return 1 === $count;
82
    }
83
84
    /**
85
     * @param $attribute
86
     * @param $value
87
     *
88
     * @return bool
89
     */
90
    public function validateBic($attribute, $value): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

90
    public function validateBic(/** @scrutinizer ignore-unused */ $attribute, $value): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
91
    {
92
        $regex  = '/^[a-z]{6}[0-9a-z]{2}([0-9a-z]{3})?\z/i';
93
        $result = preg_match($regex, $value);
94
        if (false === $result) {
95
            return false;
96
        }
97
        if (0 === $result) {
98
            return false;
99
        }
100
101
        return true;
102
    }
103
104
    /**
105
     * @param $attribute
106
     * @param $value
107
     *
108
     * @return bool
109
     */
110
    public function validateIban($attribute, $value): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

110
    public function validateIban(/** @scrutinizer ignore-unused */ $attribute, $value): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
111
    {
112
        if (!\is_string($value) || null === $value || strlen($value) < 6) {
113
            return false;
114
        }
115
        // strip spaces
116
        $search  = [
117
            "\x20", // normal space
118
            "\u{0001}", // start of heading
119
            "\u{0002}", // start of text
120
            "\u{0003}", // end of text
121
            "\u{0004}", // end of transmission
122
            "\u{0005}", // enquiry
123
            "\u{0006}", // ACK
124
            "\u{0007}", // BEL
125
            "\u{0008}", // backspace
126
            "\u{000E}", // shift out
127
            "\u{000F}", // shift in
128
            "\u{0010}", // data link escape
129
            "\u{0011}", // DC1
130
            "\u{0012}", // DC2
131
            "\u{0013}", // DC3
132
            "\u{0014}", // DC4
133
            "\u{0015}", // NAK
134
            "\u{0016}", // SYN
135
            "\u{0017}", // ETB
136
            "\u{0018}", // CAN
137
            "\u{0019}", // EM
138
            "\u{001A}", // SUB
139
            "\u{001B}", // escape
140
            "\u{001C}", // file separator
141
            "\u{001D}", // group separator
142
            "\u{001E}", // record separator
143
            "\u{001F}", // unit separator
144
            "\u{007F}", // DEL
145
            "\u{00A0}", // non-breaking space
146
            "\u{1680}", // ogham space mark
147
            "\u{180E}", // mongolian vowel separator
148
            "\u{2000}", // en quad
149
            "\u{2001}", // em quad
150
            "\u{2002}", // en space
151
            "\u{2003}", // em space
152
            "\u{2004}", // three-per-em space
153
            "\u{2005}", // four-per-em space
154
            "\u{2006}", // six-per-em space
155
            "\u{2007}", // figure space
156
            "\u{2008}", // punctuation space
157
            "\u{2009}", // thin space
158
            "\u{200A}", // hair space
159
            "\u{200B}", // zero width space
160
            "\u{202F}", // narrow no-break space
161
            "\u{3000}", // ideographic space
162
            "\u{FEFF}", // zero width no -break space
163
        ];
164
        $replace = '';
165
        $value   = str_replace($search, $replace, $value);
166
        $value   = strtoupper($value);
167
168
        $search  = [' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
169
        $replace = ['', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31',
170
                    '32', '33', '34', '35',];
171
172
        // take
173
        $first    = substr($value, 0, 4);
174
        $last     = substr($value, 4);
175
        $iban     = $last . $first;
176
        $iban     = str_replace($search, $replace, $iban);
177
        $checksum = bcmod($iban, '97');
178
179
        return 1 === (int)$checksum;
180
    }
181
182
    /**
183
     * @param $attribute
184
     * @param $value
185
     * @param $parameters
186
     * @return bool
187
     */
188
    public function validateLess($attribute, $value, $parameters): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

188
    public function validateLess(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
189
    {
190
        /** @var mixed $compare */
191
        $compare = $parameters[0] ?? '0';
192
193
        return bccomp((string)$value, (string)$compare) < 0;
194
    }
195
196
    /**
197
     * @param $attribute
198
     * @param $value
199
     * @param $parameters
200
     * @return bool
201
     */
202
    public function validateMore($attribute, $value, $parameters): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

202
    public function validateMore(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
203
    {
204
        /** @var mixed $compare */
205
        $compare = $parameters[0] ?? '0';
206
207
        return bccomp((string)$value, (string)$compare) > 0;
208
    }
209
210
    /**
211
     * @param $attribute
212
     * @param $value
213
     * @param $parameters
214
     *
215
     * @return bool
216
     */
217
    public function validateMustExist($attribute, $value, $parameters): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

217
    public function validateMustExist(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
218
    {
219
        $field = $parameters[1] ?? 'id';
220
221
        if (0 === (int)$value) {
222
            return true;
223
        }
224
        $count = DB::table($parameters[0])->where($field, $value)->count();
225
226
        return 1 === $count;
227
    }
228
229
    /**
230
     * @param string $attribute
231
     *
232
     * @param string $value
233
     *
234
     * @return bool
235
     */
236
    public function validateRuleActionValue(string $attribute, string $value = null): bool
237
    {
238
        // first, get the index from this string:
239
        $value = $value ?? '';
240
        $parts = explode('.', $attribute);
241
        $index = (int)($parts[1] ?? '0');
242
243
        // get the name of the trigger from the data array:
244
        $actionType = $this->data['actions'][$index]['type'] ?? 'invalid';
245
246
        // if it's "invalid" return false.
247
        if ('invalid' === $actionType) {
248
            return false;
249
        }
250
251
        // if it's set_budget, verify the budget name:
252
        if ('set_budget' === $actionType) {
253
            /** @var BudgetRepositoryInterface $repository */
254
            $repository = app(BudgetRepositoryInterface::class);
255
            $budgets    = $repository->getBudgets();
256
            // count budgets, should have at least one
257
            // TODO no longer need to loop like this
258
            $count = $budgets->filter(
259
                function (Budget $budget) use ($value) {
260
                    return $budget->name === $value;
261
                }
262
            )->count();
263
264
            return 1 === $count;
265
        }
266
267
        // if it's link to bill, verify the name of the bill.
268
        if ('link_to_bill' === $actionType) {
269
            /** @var BillRepositoryInterface $repository */
270
            $repository = app(BillRepositoryInterface::class);
271
            $bill       = $repository->findByName($value);
272
273
            return null !== $bill;
274
        }
275
276
        // if it's convert_transfer, it must be a valid asset account name.
277
        if ('convert_transfer' === $actionType) {
278
            /** @var AccountRepositoryInterface $repository */
279
            $repository = app(AccountRepositoryInterface::class);
280
            $account    = $repository->findByName(
281
                $value,
282
                [AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE,
283
                 AccountType::CREDITCARD]
284
            );
285
286
            return null !== $account;
287
        }
288
289
        // return true for the rest.
290
        return true;
291
    }
292
293
    /**
294
     * $attribute has the format triggers.%d.value.
295
     *
296
     * @param string $attribute
297
     * @param string $value
298
     *
299
     * @return bool
300
     */
301
    public function validateRuleTriggerValue(string $attribute, string $value = null): bool
302
    {
303
        // first, get the index from this string:
304
        $parts = explode('.', $attribute);
305
        $index = (int)($parts[1] ?? '0');
306
307
        // get the name of the trigger from the data array:
308
        $triggerType = $this->data['triggers'][$index]['type'] ?? 'invalid';
309
310
        // invalid always returns false:
311
        if ('invalid' === $triggerType) {
312
            return false;
313
        }
314
315
        // these trigger types need a numerical check:
316
        $numerical = ['amount_less', 'amount_more', 'amount_exactly'];
317
        if (in_array($triggerType, $numerical, true)) {
318
            return is_numeric($value);
319
        }
320
321
        // these trigger types need a simple strlen check:
322
        $length = ['from_account_starts', 'from_account_ends', 'from_account_is', 'from_account_contains', 'to_account_starts', 'to_account_ends',
323
                   'to_account_is', 'to_account_contains', 'description_starts', 'description_ends', 'description_contains', 'description_is', 'category_is',
324
                   'budget_is', 'tag_is', 'currency_is', 'notes_contain', 'notes_start', 'notes_end', 'notes_are',];
325
        if (in_array($triggerType, $length, true)) {
326
            return '' !== $value;
327
        }
328
329
        // check transaction type.
330
        if ('transaction_type' === $triggerType) {
331
            $count = TransactionType::where('type', ucfirst($value))->count();
332
333
            return 1 === $count;
334
        }
335
336
        // and finally a "will match everything check":
337
        $classes = app('config')->get('firefly.rule-triggers');
338
        /** @var TriggerInterface $class */
339
        $class = $classes[$triggerType] ?? false;
340
        if (false === $class) {
0 ignored issues
show
The condition false === $class is always false.
Loading history...
341
            return false;
342
        }
343
344
        return !$class::willMatchEverything($value);
345
    }
346
347
    /**
348
     * @param $attribute
349
     * @param $value
350
     *
351
     * @return bool
352
     */
353
    public function validateSecurePassword($attribute, $value): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

353
    public function validateSecurePassword(/** @scrutinizer ignore-unused */ $attribute, $value): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
354
    {
355
        $verify = false;
356
        if (isset($this->data['verify_password'])) {
357
            $verify = 1 === (int)$this->data['verify_password'];
358
        }
359
        if ($verify) {
360
            /** @var Verifier $service */
361
            $service = app(Verifier::class);
362
363
            return $service->validPassword($value);
364
        }
365
366
        return true;
367
    }
368
369
    /**
370
     * @param $attribute
371
     * @param $value
372
     * @param $parameters
373
     *
374
     * @return bool
375
     */
376
    public function validateUniqueAccountForUser($attribute, $value, $parameters): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

376
    public function validateUniqueAccountForUser(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
377
    {
378
379
        // because a user does not have to be logged in (tests and what-not).
380
        if (!auth()->check()) {
381
            return $this->validateAccountAnonymously();
382
        }
383
        if (isset($this->data['objectType'])) {
384
385
            return $this->validateByAccountTypeString($value, $parameters, $this->data['objectType']);
386
        }
387
        if (isset($this->data['type'])) {
388
            return $this->validateByAccountTypeString($value, $parameters, $this->data['type']);
389
        }
390
        if (isset($this->data['account_type_id'])) {
391
            return $this->validateByAccountTypeId($value, $parameters);
392
        }
393
        $parameterId = $parameters[0] ?? null;
394
        if (null !== $parameterId) {
395
            return $this->validateByParameterId((int)$parameterId, $value);
396
        }
397
        if (isset($this->data['id'])) {
398
            return $this->validateByAccountId($value);
399
        }
400
401
        // without type, just try to validate the name.
402
        return $this->validateByAccountName($value);
403
    }
404
405
    /**
406
     * @param $attribute
407
     * @param $value
408
     * @param $parameters
409
     *
410
     * @return bool
411
     */
412
    public function validateUniqueAccountNumberForUser($attribute, $value, $parameters): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

412
    public function validateUniqueAccountNumberForUser(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
413
    {
414
        $accountId = (int)($this->data['id'] ?? 0.0);
415
        if (0 === $accountId) {
416
            $accountId = (int)($parameters[0] ?? 0.0);
417
        }
418
419
        $query = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id')
420
                            ->whereNull('accounts.deleted_at')
421
                            ->where('accounts.user_id', auth()->user()->id)
422
                            ->where('account_meta.name', 'account_number');
423
424
        if ($accountId > 0) {
425
            // exclude current account from check.
426
            $query->where('account_meta.account_id', '!=', $accountId);
427
        }
428
        $set = $query->get(['account_meta.*']);
429
430
        /** @var AccountMeta $entry */
431
        foreach ($set as $entry) {
432
            if ($entry->data === $value) {
433
                return false;
434
            }
435
        }
436
437
        return true;
438
    }
439
440
    /**
441
     *
442
     * Validate an object and its unicity. Checks for encryption / encrypted values as well.
443
     *
444
     * parameter 0: the table
445
     * parameter 1: the field
446
     * parameter 2: an id to ignore (when editing)
447
     *
448
     * @param $attribute
449
     * @param $value
450
     * @param $parameters
451
     *
452
     * @return bool
453
     */
454
    public function validateUniqueObjectForUser($attribute, $value, $parameters): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

454
    public function validateUniqueObjectForUser(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
455
    {
456
        [$table, $field] = $parameters;
457
        $exclude = (int)($parameters[2] ?? 0.0);
458
459
        /*
460
         * If other data (in $this->getData()) contains
461
         * ID field, set that field to be the $exclude.
462
         */
463
        $data = $this->getData();
464
        if (!isset($parameters[2]) && isset($data['id']) && (int)$data['id'] > 0) {
465
            $exclude = (int)$data['id'];
466
        }
467
468
469
        // get entries from table
470
        $set = DB::table($table)->where('user_id', auth()->user()->id)->whereNull('deleted_at')
471
                 ->where('id', '!=', $exclude)->get([$field]);
472
473
        foreach ($set as $entry) {
474
            $fieldValue = $entry->$field;
475
476
            if ($fieldValue === $value) {
477
                return false;
478
            }
479
        }
480
481
        return true;
482
    }
483
484
    /**
485
     * @param $attribute
486
     * @param $value
487
     * @param $parameters
488
     *
489
     * @return bool
490
     */
491
    public function validateUniquePiggyBankForUser($attribute, $value, $parameters): bool
0 ignored issues
show
The parameter $attribute is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

491
    public function validateUniquePiggyBankForUser(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
492
    {
493
        $exclude = $parameters[0] ?? null;
494
        $query   = DB::table('piggy_banks')->whereNull('piggy_banks.deleted_at')
495
                     ->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')->where('accounts.user_id', auth()->user()->id);
496
        if (null !== $exclude) {
497
            $query->where('piggy_banks.id', '!=', (int)$exclude);
498
        }
499
        $set = $query->get(['piggy_banks.*']);
500
501
        /** @var PiggyBank $entry */
502
        foreach ($set as $entry) {
503
504
            $fieldValue = $entry->name;
505
            if ($fieldValue === $value) {
506
                return false;
507
            }
508
        }
509
510
        return true;
511
    }
512
513
    /**
514
     * @return bool
515
     */
516
    private function validateAccountAnonymously(): bool
517
    {
518
        if (!isset($this->data['user_id'])) {
519
            return false;
520
        }
521
522
        $user  = User::find($this->data['user_id']);
523
        $type  = AccountType::find($this->data['account_type_id'])->first();
524
        $value = $this->data['name'];
525
526
        $set = $user->accounts()->where('account_type_id', $type->id)->get();
527
        // TODO no longer need to loop like this
528
        /** @var Account $entry */
529
        foreach ($set as $entry) {
530
            if ($entry->name === $value) {
531
                return false;
532
            }
533
        }
534
535
        return true;
536
    }
537
538
    /**
539
     * @param $value
540
     *
541
     * @return bool
542
     */
543
    private function validateByAccountId($value): bool
544
    {
545
        /** @var Account $existingAccount */
546
        $existingAccount = Account::find($this->data['id']);
547
548
        $type   = $existingAccount->accountType;
549
        $ignore = $existingAccount->id;
550
551
        /** @var Collection $set */
552
        $entry = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)
553
                       ->where('name', $value)
554
                       ->first();
555
556
        return null === $entry;
557
    }
558
559
560
    /**
561
     * @param $value
562
     *
563
     * @return bool
564
     */
565
    private function validateByParameterId(int $accountId, $value): bool
566
    {
567
        /** @var Account $existingAccount */
568
        $existingAccount = Account::find($accountId);
569
570
        $type   = $existingAccount->accountType;
571
        $ignore = $existingAccount->id;
572
573
        /** @var Collection $set */
574
        $entry = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)
575
                       ->where('name', $value)
576
                       ->first();
577
578
        return null === $entry;
579
    }
580
581
    /**
582
     * @param $value
583
     * @param $parameters
584
     *
585
     * @return bool
586
     */
587
    private function validateByAccountTypeId($value, $parameters): bool
588
    {
589
        $type   = AccountType::find($this->data['account_type_id'])->first();
590
        $ignore = (int)($parameters[0] ?? 0.0);
591
592
        /** @var Collection $set */
593
        $set = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get();
594
        // TODO no longer need to loop like this
595
        /** @var Account $entry */
596
        foreach ($set as $entry) {
597
            // TODO no longer need to loop like this.
598
            if ($entry->name === $value) {
599
                return false;
600
            }
601
        }
602
603
        return true;
604
    }
605
606
    /**
607
     * @param string $value
608
     * @param array $parameters
609
     * @param string $type
610
     *
611
     * @return bool
612
     */
613
    private function validateByAccountTypeString(string $value, array $parameters, string $type): bool
614
    {
615
        /** @var array $search */
616
        $search = Config::get('firefly.accountTypeByIdentifier.' . $type);
617
618
        if (null === $search) {
0 ignored issues
show
The condition null === $search is always false.
Loading history...
619
            return false;
620
        }
621
622
        /** @var Collection $accountTypes */
623
        $accountTypes   = AccountType::whereIn('type', $search)->get();
624
        $ignore         = (int)($parameters[0] ?? 0.0);
625
        $accountTypeIds = $accountTypes->pluck('id')->toArray();
626
        /** @var Collection $set */
627
        $set = auth()->user()->accounts()->whereIn('account_type_id', $accountTypeIds)->where('id', '!=', $ignore)->get();
628
        // TODO no longer need to loop like this
629
        /** @var Account $entry */
630
        foreach ($set as $entry) {
631
            if ($entry->name === $value) {
632
                return false;
633
            }
634
        }
635
636
        return true;
637
    }
638
639
    /**
640
     * @param string $value
641
     * @return bool
642
     */
643
    private function validateByAccountName(string $value): bool
644
    {
645
        return auth()->user()->accounts()->where('name', $value)->count() === 0;
646
    }
647
}
648