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.
Passed
Push — master ( 37b02e...ebbbe1 )
by James
08:59
created

TransactionRequest::getAll()   D

Complexity

Conditions 10
Paths 257

Size

Total Lines 51
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 51
rs 4.2352
c 0
b 0
f 0
cc 10
eloc 39
nc 257
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
/**
4
 * TransactionRequest.php
5
 * Copyright (c) 2018 [email protected]
6
 *
7
 * This file is part of Firefly III.
8
 *
9
 * Firefly III is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation, either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * Firefly III is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
24
namespace FireflyIII\Api\V1\Requests;
25
26
use FireflyIII\Exceptions\FireflyException;
27
use FireflyIII\Models\Account;
28
use FireflyIII\Models\AccountType;
29
use FireflyIII\Models\Transaction;
30
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
31
use FireflyIII\Rules\BelongsUser;
32
use Illuminate\Validation\Validator;
33
34
35
/**
36
 * Class TransactionRequest
37
 */
38
class TransactionRequest extends Request
39
{
40
    /**
41
     * @return bool
42
     */
43
    public function authorize(): bool
44
    {
45
        // Only allow authenticated users
46
        return auth()->check();
47
    }
48
49
    /**
50
     * @return array
51
     */
52
    public function getAll(): array
53
    {
54
        $data = [
55
            // basic fields for journal:
56
            'type'               => $this->string('type'),
57
            'date'               => $this->date('date'),
58
            'description'        => $this->string('description'),
59
            'piggy_bank_id'      => $this->integer('piggy_bank_id'),
60
            'piggy_bank_name'    => $this->string('piggy_bank_name'),
61
            'bill_id'            => $this->integer('bill_id'),
62
            'bill_name'          => $this->string('bill_name'),
63
            'tags'               => explode(',', $this->string('tags')),
64
65
            // then, custom fields for journal
66
            'interest_date'      => $this->date('interest_date'),
67
            'book_date'          => $this->date('book_date'),
68
            'process_date'       => $this->date('process_date'),
69
            'due_date'           => $this->date('due_date'),
70
            'payment_date'       => $this->date('payment_date'),
71
            'invoice_date'       => $this->date('invoice_date'),
72
            'internal_reference' => $this->string('internal_reference'),
73
            'notes'              => $this->string('notes'),
74
75
            // then, transactions (see below).
76
            'transactions'       => [],
77
78
        ];
79
        foreach ($this->get('transactions') as $index => $transaction) {
80
            $array                  = [
81
                'description'           => $transaction['description'] ?? null,
82
                'amount'                => $transaction['amount'],
83
                'currency_id'           => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
84
                'currency_code'         => $transaction['currency_code'] ?? null,
85
                'foreign_amount'        => $transaction['foreign_amount'] ?? null,
86
                'foreign_currency_id'   => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
87
                'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
88
                'budget_id'             => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
89
                'budget_name'           => $transaction['budget_name'] ?? null,
90
                'category_id'           => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
91
                'category_name'         => $transaction['category_name'] ?? null,
92
                'source_id'             => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
93
                'source_name'           => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
94
                'destination_id'        => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
95
                'destination_name'      => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
96
                'reconciled'            => $transaction['reconciled'] ?? false,
97
                'identifier'            => $index,
98
            ];
99
            $data['transactions'][] = $array;
100
        }
101
102
        return $data;
103
    }
104
105
    /**
106
     * @return array
107
     */
108
    public function rules(): array
109
    {
110
        $rules = [
111
            // basic fields for journal:
112
            'type'                                 => 'required|in:withdrawal,deposit,transfer',
113
            'date'                                 => 'required|date',
114
            'description'                          => 'between:1,255',
115
            'piggy_bank_id'                        => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser],
116
            'piggy_bank_name'                      => ['between:1,255', 'nullable', new BelongsUser],
117
            'bill_id'                              => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser],
118
            'bill_name'                            => ['between:1,255', 'nullable', new BelongsUser],
119
            'tags'                                 => 'between:1,255',
120
121
            // then, custom fields for journal
122
            'interest_date'                        => 'date|nullable',
123
            'book_date'                            => 'date|nullable',
124
            'process_date'                         => 'date|nullable',
125
            'due_date'                             => 'date|nullable',
126
            'payment_date'                         => 'date|nullable',
127
            'invoice_date'                         => 'date|nullable',
128
            'internal_reference'                   => 'min:1,max:255|nullable',
129
            'notes'                                => 'min:1,max:50000|nullable',
130
131
            // transaction rules (in array for splits):
132
            'transactions.*.description'           => 'nullable|between:1,255',
133
            'transactions.*.amount'                => 'required|numeric|more:0',
134
            'transactions.*.currency_id'           => 'numeric|exists:transaction_currencies,id|required_without:transactions.*.currency_code',
135
            'transactions.*.currency_code'         => 'min:3|max:3|exists:transaction_currencies,code|required_without:transactions.*.currency_id',
136
            'transactions.*.foreign_amount'        => 'numeric|more:0',
137
            'transactions.*.foreign_currency_id'   => 'numeric|exists:transaction_currencies,id',
138
            'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
139
            'transactions.*.budget_id'             => ['mustExist:budgets,id', new BelongsUser],
140
            'transactions.*.budget_name'           => ['between:1,255', 'nullable', new BelongsUser],
141
            'transactions.*.category_id'           => ['mustExist:categories,id', new BelongsUser],
142
            'transactions.*.category_name'         => 'between:1,255|nullable',
143
            'transactions.*.reconciled'            => 'boolean|nullable',
144
            // basic rules will be expanded later.
145
            'transactions.*.source_id'             => ['numeric', 'nullable', new BelongsUser],
146
            'transactions.*.source_name'           => 'between:1,255|nullable',
147
            'transactions.*.destination_id'        => ['numeric', 'nullable', new BelongsUser],
148
            'transactions.*.destination_name'      => 'between:1,255|nullable',
149
        ];
150
151
        switch ($this->method()) {
152
            default:
153
                break;
154
            case 'PUT':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
155
            case 'PATCH':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
156
                unset($rules['type'], $rules['piggy_bank_id'], $rules['piggy_bank_name']);
157
                break;
158
        }
159
160
        return $rules;
161
162
163
    }
164
165
    /**
166
     * Configure the validator instance.
167
     *
168
     * @param  Validator $validator
169
     *
170
     * @return void
171
     * @throws \FireflyIII\Exceptions\FireflyException
172
     */
173
    public function withValidator(Validator $validator): void
174
    {
175
        $validator->after(
176
            function (Validator $validator) {
177
                $this->atLeastOneTransaction($validator);
178
                $this->checkValidDescriptions($validator);
179
                $this->equalToJournalDescription($validator);
180
                $this->emptySplitDescriptions($validator);
181
                $this->foreignCurrencyInformation($validator);
182
                $this->validateAccountInformation($validator);
183
                $this->validateSplitAccounts($validator);
184
            }
185
        );
186
    }
187
188
    /**
189
     * Throws an error when this asset account is invalid.
190
     *
191
     * @param Validator   $validator
192
     * @param int|null    $accountId
193
     * @param null|string $accountName
194
     * @param string      $idField
195
     * @param string      $nameField
196
     *
197
     * @return null|Account
198
     */
199
    protected function assetAccountExists(Validator $validator, ?int $accountId, ?string $accountName, string $idField, string $nameField): ?Account
200
    {
201
202
        $accountId   = (int)$accountId;
203
        $accountName = (string)$accountName;
204
        // both empty? hard exit.
205
        if ($accountId < 1 && strlen($accountName) === 0) {
206
            $validator->errors()->add($idField, trans('validation.filled', ['attribute' => $idField]));
0 ignored issues
show
Bug introduced by
It seems like trans('validation.filled...ttribute' => $idField)) can also be of type array; however, parameter $message of Illuminate\Support\MessageBag::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

206
            $validator->errors()->add($idField, /** @scrutinizer ignore-type */ trans('validation.filled', ['attribute' => $idField]));
Loading history...
207
208
            return null;
209
        }
210
        // ID belongs to user and is asset account:
211
        /** @var AccountRepositoryInterface $repository */
212
        $repository = app(AccountRepositoryInterface::class);
213
        $repository->setUser(auth()->user());
214
        $set = $repository->getAccountsById([$accountId]);
215
        if ($set->count() === 1) {
216
            /** @var Account $first */
217
            $first = $set->first();
218
            if ($first->accountType->type !== AccountType::ASSET) {
0 ignored issues
show
Bug introduced by
The property type does not seem to exist on FireflyIII\Models\AccountType. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
219
                $validator->errors()->add($idField, trans('validation.belongs_user'));
220
221
                return null;
222
            }
223
224
            // we ignore the account name at this point.
225
            return $first;
226
        }
227
228
        $account = $repository->findByNameNull($accountName, [AccountType::ASSET]);
0 ignored issues
show
Bug introduced by
The method findByNameNull() does not exist on FireflyIII\Repositories\...ountRepositoryInterface. Did you maybe mean findByName()? ( Ignorable by Annotation )

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

228
        /** @scrutinizer ignore-call */ 
229
        $account = $repository->findByNameNull($accountName, [AccountType::ASSET]);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
229
        if (null === $account) {
230
            $validator->errors()->add($nameField, trans('validation.belongs_user'));
231
232
            return null;
233
        }
234
235
        return $account;
236
    }
237
238
    /**
239
     * Adds an error to the validator when there are no transactions in the array of data.
240
     *
241
     * @param Validator $validator
242
     */
243
    protected function atLeastOneTransaction(Validator $validator): void
244
    {
245
        $data         = $validator->getData();
246
        $transactions = $data['transactions'] ?? [];
247
        // need at least one transaction
248
        if (count($transactions) === 0) {
249
            $validator->errors()->add('description', trans('validation.at_least_one_transaction'));
0 ignored issues
show
Bug introduced by
It seems like trans('validation.at_least_one_transaction') can also be of type array; however, parameter $message of Illuminate\Support\MessageBag::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

249
            $validator->errors()->add('description', /** @scrutinizer ignore-type */ trans('validation.at_least_one_transaction'));
Loading history...
250
        }
251
    }
252
253
    /**
254
     * Adds an error to the "description" field when the user has submitted no descriptions and no
255
     * journal description.
256
     *
257
     * @param Validator $validator
258
     */
259
    protected function checkValidDescriptions(Validator $validator)
260
    {
261
        $data               = $validator->getData();
262
        $transactions       = $data['transactions'] ?? [];
263
        $journalDescription = (string)($data['description'] ?? '');
264
        $validDescriptions  = 0;
265
        foreach ($transactions as $index => $transaction) {
266
            if (strlen((string)($transaction['description'] ?? '')) > 0) {
267
                $validDescriptions++;
268
            }
269
        }
270
271
        // no valid descriptions and empty journal description? error.
272
        if ($validDescriptions === 0 && strlen($journalDescription) === 0) {
273
            $validator->errors()->add('description', trans('validation.filled', ['attribute' => trans('validation.attributes.description')]));
0 ignored issues
show
Bug introduced by
It seems like trans('validation.filled...ributes.description'))) can also be of type array; however, parameter $message of Illuminate\Support\MessageBag::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

273
            $validator->errors()->add('description', /** @scrutinizer ignore-type */ trans('validation.filled', ['attribute' => trans('validation.attributes.description')]));
Loading history...
274
        }
275
276
    }
277
278
    /**
279
     * Adds an error to the validator when the user submits a split transaction (more than 1 transactions)
280
     * but does not give them a description.
281
     *
282
     * @param Validator $validator
283
     */
284
    protected function emptySplitDescriptions(Validator $validator): void
285
    {
286
        $data         = $validator->getData();
287
        $transactions = $data['transactions'] ?? [];
288
        foreach ($transactions as $index => $transaction) {
289
            $description = (string)($transaction['description'] ?? '');
290
            // filled description is mandatory for split transactions.
291
            if (count($transactions) > 1 && strlen($description) === 0) {
292
                $validator->errors()->add(
293
                    'transactions.' . $index . '.description',
294
                    trans('validation.filled', ['attribute' => trans('validation.attributes.transaction_description')])
0 ignored issues
show
Bug introduced by
It seems like trans('validation.filled...saction_description'))) can also be of type array; however, parameter $message of Illuminate\Support\MessageBag::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

294
                    /** @scrutinizer ignore-type */ trans('validation.filled', ['attribute' => trans('validation.attributes.transaction_description')])
Loading history...
295
                );
296
            }
297
        }
298
    }
299
300
    /**
301
     * Adds an error to the validator when any transaction descriptions are equal to the journal description.
302
     *
303
     * @param Validator $validator
304
     */
305
    protected function equalToJournalDescription(Validator $validator): void
306
    {
307
        $data               = $validator->getData();
308
        $transactions       = $data['transactions'] ?? [];
309
        $journalDescription = (string)($data['description'] ?? '');
310
        foreach ($transactions as $index => $transaction) {
311
            $description = (string)($transaction['description'] ?? '');
312
            // description cannot be equal to journal description.
313
            if ($description === $journalDescription) {
314
                $validator->errors()->add('transactions.' . $index . '.description', trans('validation.equal_description'));
0 ignored issues
show
Bug introduced by
It seems like trans('validation.equal_description') can also be of type array; however, parameter $message of Illuminate\Support\MessageBag::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

314
                $validator->errors()->add('transactions.' . $index . '.description', /** @scrutinizer ignore-type */ trans('validation.equal_description'));
Loading history...
315
            }
316
        }
317
    }
318
319
    /**
320
     * If the transactions contain foreign amounts, there must also be foreign currency information.
321
     *
322
     * @param Validator $validator
323
     */
324
    protected function foreignCurrencyInformation(Validator $validator): void
325
    {
326
        $data         = $validator->getData();
327
        $transactions = $data['transactions'] ?? [];
328
        foreach ($transactions as $index => $transaction) {
329
            // must have currency info.
330
            if (isset($transaction['foreign_amount'])
331
                && !(isset($transaction['foreign_currency_id'])
332
                     || isset($transaction['foreign_currency_code']))) {
333
                $validator->errors()->add(
334
                    'transactions.' . $index . '.foreign_amount',
335
                    trans('validation.require_currency_info')
0 ignored issues
show
Bug introduced by
It seems like trans('validation.require_currency_info') can also be of type array; however, parameter $message of Illuminate\Support\MessageBag::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

335
                    /** @scrutinizer ignore-type */ trans('validation.require_currency_info')
Loading history...
336
                );
337
            }
338
        }
339
    }
340
341
    /**
342
     * Throws an error when the given opposing account (of type $type) is invalid.
343
     * Empty data is allowed, system will default to cash.
344
     *
345
     * @param Validator   $validator
346
     * @param string      $type
347
     * @param int|null    $accountId
348
     * @param null|string $accountName
349
     * @param string      $idField
350
     *
351
     * @return null|Account
352
     */
353
    protected function opposingAccountExists(Validator $validator, string $type, ?int $accountId, ?string $accountName, string $idField): ?Account
354
    {
355
        $accountId   = (int)$accountId;
356
        $accountName = (string)$accountName;
357
        // both empty? done!
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
358
        if ($accountId < 1 && strlen($accountName) === 0) {
359
            return null;
360
        }
361
        if ($accountId !== 0) {
362
            // ID belongs to user and is $type account:
363
            /** @var AccountRepositoryInterface $repository */
364
            $repository = app(AccountRepositoryInterface::class);
365
            $repository->setUser(auth()->user());
366
            $set = $repository->getAccountsById([$accountId]);
367
            if ($set->count() === 1) {
368
                /** @var Account $first */
369
                $first = $set->first();
370
                if ($first->accountType->type !== $type) {
0 ignored issues
show
Bug introduced by
The property type does not seem to exist on FireflyIII\Models\AccountType. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
371
                    $validator->errors()->add($idField, trans('validation.belongs_user'));
0 ignored issues
show
Bug introduced by
It seems like trans('validation.belongs_user') can also be of type array; however, parameter $message of Illuminate\Support\MessageBag::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

371
                    $validator->errors()->add($idField, /** @scrutinizer ignore-type */ trans('validation.belongs_user'));
Loading history...
372
373
                    return null;
374
                }
375
376
                // we ignore the account name at this point.
377
                return $first;
378
            }
379
        }
380
381
        // not having an opposing account by this name is NOT a problem.
382
        return null;
383
    }
384
385
    /**
386
     * Validates the given account information. Switches on given transaction type.
387
     *
388
     * @param Validator $validator
389
     *
390
     * @throws FireflyException
391
     */
392
    protected function validateAccountInformation(Validator $validator): void
393
    {
394
        $data         = $validator->getData();
395
        $transactions = $data['transactions'] ?? [];
396
        if (!isset($data['type'])) {
397
            // the journal may exist in the request:
398
            /** @var Transaction $transaction */
399
            $transaction = $this->route()->parameter('transaction');
400
            if (null === $transaction) {
401
                return; // @codeCoverageIgnore
402
            }
403
            $data['type'] = strtolower($transaction->transactionJournal->transactionType->type);
0 ignored issues
show
Bug introduced by
The property type does not seem to exist on FireflyIII\Models\TransactionType. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
404
        }
405
        foreach ($transactions as $index => $transaction) {
406
            $sourceId           = isset($transaction['source_id']) ? (int)$transaction['source_id'] : null;
407
            $sourceName         = $transaction['source_name'] ?? null;
408
            $destinationId      = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null;
409
            $destinationName    = $transaction['destination_name'] ?? null;
410
            $sourceAccount      = null;
411
            $destinationAccount = null;
412
            switch ($data['type']) {
413
                case 'withdrawal':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
414
                    $idField            = 'transactions.' . $index . '.source_id';
415
                    $nameField          = 'transactions.' . $index . '.source_name';
416
                    $sourceAccount      = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField);
417
                    $idField            = 'transactions.' . $index . '.destination_id';
418
                    $destinationAccount = $this->opposingAccountExists($validator, AccountType::EXPENSE, $destinationId, $destinationName, $idField);
419
                    break;
420
                case 'deposit':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
421
                    $idField       = 'transactions.' . $index . '.source_id';
422
                    $sourceAccount = $this->opposingAccountExists($validator, AccountType::REVENUE, $sourceId, $sourceName, $idField);
423
424
                    $idField            = 'transactions.' . $index . '.destination_id';
425
                    $nameField          = 'transactions.' . $index . '.destination_name';
426
                    $destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField);
427
                    break;
428
                case 'transfer':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
429
                    $idField       = 'transactions.' . $index . '.source_id';
430
                    $nameField     = 'transactions.' . $index . '.source_name';
431
                    $sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField);
432
433
                    $idField            = 'transactions.' . $index . '.destination_id';
434
                    $nameField          = 'transactions.' . $index . '.destination_name';
435
                    $destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField);
436
                    break;
437
                default:
438
                    // @codeCoverageIgnoreStart
439
                    throw new FireflyException(
440
                        sprintf('The validator cannot handle transaction type "%s" in validateAccountInformation().', $data['type'])
441
                    );
442
                // @codeCoverageIgnoreEnd
443
444
            }
445
            // add some errors in case of same account submitted:
446
            if (null !== $sourceAccount && null !== $destinationAccount && $sourceAccount->id === $destinationAccount->id) {
447
                $validator->errors()->add($idField, trans('validation.source_equals_destination'));
0 ignored issues
show
Bug introduced by
It seems like trans('validation.source_equals_destination') can also be of type array; however, parameter $message of Illuminate\Support\MessageBag::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

447
                $validator->errors()->add($idField, /** @scrutinizer ignore-type */ trans('validation.source_equals_destination'));
Loading history...
448
            }
449
        }
450
    }
451
452
    /**
453
     * @param Validator $validator
454
     *
455
     * @throws FireflyException
456
     */
457
    protected function validateSplitAccounts(Validator $validator)
458
    {
459
        $data  = $validator->getData();
460
        $count = isset($data['transactions']) ? count($data['transactions']) : 0;
461
        if ($count < 2) {
462
            return;
463
        }
464
        // this is pretty much impossible:
465
        // @codeCoverageIgnoreStart
466
        if (!isset($data['type'])) {
467
            // the journal may exist in the request:
468
            /** @var Transaction $transaction */
469
            $transaction = $this->route()->parameter('transaction');
470
            if (null === $transaction) {
471
                return;
472
            }
473
            $data['type'] = strtolower($transaction->transactionJournal->transactionType->type);
0 ignored issues
show
Bug introduced by
The property type does not seem to exist on FireflyIII\Models\TransactionType. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
474
        }
475
        // @codeCoverageIgnoreEnd
476
477
        // collect all source ID's and destination ID's, if present:
478
        $sources      = [];
479
        $destinations = [];
480
481
        foreach ($data['transactions'] as $transaction) {
482
            $sources[]      = isset($transaction['source_id']) ? (int)$transaction['source_id'] : 0;
483
            $destinations[] = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : 0;
484
        }
485
        $destinations = array_unique($destinations);
486
        $sources      = array_unique($sources);
487
        // switch on type:
488
        switch ($data['type']) {
489
            case 'withdrawal':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
490
                if (count($sources) > 1) {
491
                    $validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal'));
0 ignored issues
show
Bug introduced by
It seems like trans('validation.all_accounts_equal') can also be of type array; however, parameter $message of Illuminate\Support\MessageBag::add() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

491
                    $validator->errors()->add('transactions.0.source_id', /** @scrutinizer ignore-type */ trans('validation.all_accounts_equal'));
Loading history...
492
                }
493
                break;
494
            case 'deposit':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
495
                if (count($destinations) > 1) {
496
                    $validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal'));
497
                }
498
                break;
499
            case 'transfer':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
500
                if (count($sources) > 1 || count($destinations) > 1) {
501
                    $validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal'));
502
                    $validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal'));
503
                }
504
                break;
505
            default:
506
                // @codeCoverageIgnoreStart
507
                throw new FireflyException(
508
                    sprintf('The validator cannot handle transaction type "%s" in validateSplitAccounts().', $data['type'])
509
                );
510
            // @codeCoverageIgnoreEnd
511
        }
512
    }
513
514
}
515