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 ( 49de82...9f1fc0 )
by James
35:45 queued 23:44
created

Services/Internal/Support/JournalServiceTrait.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * JournalServiceTrait.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
22
declare(strict_types=1);
23
24
namespace FireflyIII\Services\Internal\Support;
25
26
use Exception;
27
use FireflyIII\Exceptions\FireflyException;
28
use FireflyIII\Factory\AccountMetaFactory;
29
use FireflyIII\Factory\TagFactory;
30
use FireflyIII\Models\Account;
31
use FireflyIII\Models\AccountType;
32
use FireflyIII\Models\Note;
33
use FireflyIII\Models\TransactionJournal;
34
use FireflyIII\Models\TransactionType;
35
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
36
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
37
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
38
use FireflyIII\Support\NullArrayObject;
39
use Log;
40
41
/**
42
 * Trait JournalServiceTrait
43
 *
44
 */
45
trait JournalServiceTrait
46
{
47
    /** @var AccountRepositoryInterface */
48
    private $accountRepository;
49
    /** @var BudgetRepositoryInterface */
50
    private $budgetRepository;
51
    /** @var CategoryRepositoryInterface */
52
    private $categoryRepository;
53
    /** @var TagFactory */
54
    private $tagFactory;
55
56
57
    /**
58
     * @param string|null $amount
59
     *
60
     * @return string
61
     * @codeCoverageIgnore
62
     */
63
    protected function getForeignAmount(?string $amount): ?string
64
    {
65
        if (null === $amount) {
66
            Log::debug('No foreign amount info in array. Return NULL');
67
68
            return null;
69
        }
70
        if ('' === $amount) {
71
            Log::debug('Foreign amount is empty string, return NULL.');
72
73
            return null;
74
        }
75
        if (0 === bccomp('0', $amount)) {
76
            Log::debug('Foreign amount is 0.0, return NULL.');
77
78
            return null;
79
        }
80
        Log::debug(sprintf('Foreign amount is %s', $amount));
81
82
        return $amount;
83
    }
84
85
    /**
86
     * @param string $transactionType
87
     * @param string $direction
88
     * @param array  $data
89
     *
90
     * @return Account
91
     * @codeCoverageIgnore
92
     */
93
    protected function getAccount(string $transactionType, string $direction, array $data): Account
94
    {
95
        // some debug logging:
96
        Log::debug(sprintf('Now in getAccount(%s)', $direction), $data);
97
98
        // final result:
99
        $result = null;
100
101
        // expected type of source account, in order of preference
102
        /** @var array $array */
103
        $array         = config('firefly.expected_source_types');
104
        $expectedTypes = $array[$direction];
105
        unset($array);
106
107
        // and now try to find it, based on the type of transaction.
108
        $message = 'Based on the fact that the transaction is a %s, the %s account should be in: %s';
109
        Log::debug(sprintf($message, $transactionType, $direction, implode(', ', $expectedTypes[$transactionType])));
110
111
        // first attempt, find by ID.
112
        if (null !== $data['id']) {
113
            $search = $this->accountRepository->findNull($data['id']);
114
            if (null !== $search && in_array($search->accountType->type, $expectedTypes[$transactionType], true)) {
115
                Log::debug(
116
                    sprintf('Found "account_id" object  for %s: #%d, "%s" of type %s', $direction, $search->id, $search->name, $search->accountType->type)
117
                );
118
                $result = $search;
119
            }
120
        }
121
122
        // second attempt, find by name.
123
        if (null === $result && null !== $data['name']) {
124
            Log::debug('Found nothing by account ID.');
125
            // find by preferred type.
126
            $source = $this->accountRepository->findByName($data['name'], [$expectedTypes[$transactionType][0]]);
127
            // or any expected type.
128
            $source = $source ?? $this->accountRepository->findByName($data['name'], $expectedTypes[$transactionType]);
129
130
            if (null !== $source) {
131
                Log::debug(sprintf('Found "account_name" object for %s: #%d, %s', $direction, $source->id, $source->name));
132
133
                $result = $source;
134
            }
135
        }
136
137
        // third attempt, find by IBAN
138
        if (null === $result && null !== $data['iban']) {
139
            Log::debug('Found nothing by account name.');
140
            // find by preferred type.
141
            $source = $this->accountRepository->findByIbanNull($data['iban'], [$expectedTypes[$transactionType][0]]);
142
            // or any expected type.
143
            $source = $source ?? $this->accountRepository->findByIbanNull($data['iban'], $expectedTypes[$transactionType]);
144
145
            if (null !== $source) {
146
                Log::debug(sprintf('Found "account_iban" object for %s: #%d, %s', $direction, $source->id, $source->name));
147
148
                $result = $source;
149
            }
150
        }
151
152
        // return cash account.
153
        if (null === $result && null === $data['name']
154
            && in_array(AccountType::CASH, $expectedTypes[$transactionType], true)) {
155
            $result = $this->accountRepository->getCashAccount();
156
        }
157
158
        // return new account.
159
        if (null === $result) {
160
            $data['name'] = $data['name'] ?? '(no name)';
161
            // final attempt, create it.
162
            $preferredType = $expectedTypes[$transactionType][0];
163
            if (AccountType::ASSET === $preferredType) {
164
                throw new FireflyException('TransactionFactory: Cannot create asset account with these values', $data);
0 ignored issues
show
$data of type array is incompatible with the type integer expected by parameter $code of FireflyIII\Exceptions\Fi...xception::__construct(). ( Ignorable by Annotation )

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

164
                throw new FireflyException('TransactionFactory: Cannot create asset account with these values', /** @scrutinizer ignore-type */ $data);
Loading history...
165
            }
166
167
            $result = $this->accountRepository->store(
168
                [
169
                    'account_type_id' => null,
170
                    'account_type'    => $preferredType,
171
                    'name'            => $data['name'],
172
                    'active'          => true,
173
                    'iban'            => $data['iban'],
174
                ]
175
            );
176
            // store BIC
177
            if (null !== $data['bic']) {
178
                /** @var AccountMetaFactory $metaFactory */
179
                $metaFactory = app(AccountMetaFactory::class);
180
                $metaFactory->create(['account_id' => $result->id, 'name' => 'BIC', 'data' => $data['bic']]);
181
            }
182
            // store account number
183
            if (null !== $data['number']) {
184
                /** @var AccountMetaFactory $metaFactory */
185
                $metaFactory = app(AccountMetaFactory::class);
186
                $metaFactory->create(['account_id' => $result->id, 'name' => 'account_number', 'data' => $data['bic']]);
187
            }
188
        }
189
190
        return $result;
191
    }
192
193
    /**
194
     * @param string $amount
195
     *
196
     * @return string
197
     * @throws FireflyException
198
     * @codeCoverageIgnore
199
     */
200
    protected function getAmount(string $amount): string
201
    {
202
        if ('' === $amount) {
203
            throw new FireflyException(sprintf('The amount cannot be an empty string: "%s"', $amount));
204
        }
205
        if (0 === bccomp('0', $amount)) {
206
            throw new FireflyException(sprintf('The amount seems to be zero: "%s"', $amount));
207
        }
208
209
        return $amount;
210
    }
211
212
    /**
213
     * @param TransactionJournal $journal
214
     * @param NullArrayObject    $data
215
     *
216
     * @codeCoverageIgnore
217
     */
218
    protected function storeBudget(TransactionJournal $journal, NullArrayObject $data): void
219
    {
220
        if (TransactionType::WITHDRAWAL !== $journal->transactionType->type) {
221
            $journal->budgets()->sync([]);
222
223
            return;
224
        }
225
        $budget = $this->budgetRepository->findBudget($data['budget_id'], $data['budget_name']);
226
        if (null !== $budget) {
227
            Log::debug(sprintf('Link budget #%d to journal #%d', $budget->id, $journal->id));
228
            $journal->budgets()->sync([$budget->id]);
229
230
            return;
231
        }
232
        // if the budget is NULL, sync empty.
233
        $journal->budgets()->sync([]);
234
    }
235
236
    /**
237
     * @param TransactionJournal $journal
238
     * @param NullArrayObject    $data
239
     *
240
     * @codeCoverageIgnore
241
     */
242
    protected function storeCategory(TransactionJournal $journal, NullArrayObject $data): void
243
    {
244
        $category = $this->categoryRepository->findCategory($data['category_id'], $data['category_name']);
245
        if (null !== $category) {
246
            Log::debug(sprintf('Link category #%d to journal #%d', $category->id, $journal->id));
247
            $journal->categories()->sync([$category->id]);
248
249
            return;
250
        }
251
        // if the category is NULL, sync empty.
252
        $journal->categories()->sync([]);
253
    }
254
255
    /**
256
     * @param TransactionJournal $journal
257
     * @param string             $notes
258
     *
259
     * @codeCoverageIgnore
260
     */
261
    protected function storeNotes(TransactionJournal $journal, ?string $notes): void
262
    {
263
        $notes = (string)$notes;
264
        $note  = $journal->notes()->first();
265
        if ('' !== $notes) {
266
            if (null === $note) {
267
                $note = new Note;
268
                $note->noteable()->associate($journal);
269
            }
270
            $note->text = $notes;
271
            $note->save();
272
            Log::debug(sprintf('Stored notes for journal #%d', $journal->id));
273
274
            return;
275
        }
276
        if ('' === $notes && null !== $note) {
277
            // try to delete existing notes.
278
            try {
279
                $note->delete();
280
                // @codeCoverageIgnoreStart
281
            } catch (Exception $e) {
282
                Log::debug(sprintf('Could not delete journal notes: %s', $e->getMessage()));
283
            }
284
            // @codeCoverageIgnoreEnd
285
        }
286
    }
287
288
    /**
289
     * Link tags to journal.
290
     *
291
     * @param TransactionJournal $journal
292
     * @param array              $tags
293
     *
294
     * @codeCoverageIgnore
295
     */
296
    protected function storeTags(TransactionJournal $journal, ?array $tags): void
297
    {
298
299
        $this->tagFactory->setUser($journal->user);
300
        $set = [];
301
        if (!is_array($tags)) {
302
            return;
303
        }
304
        foreach ($tags as $string) {
305
            $string = (string)$string;
306
            if ('' !== $string) {
307
                $tag = $this->tagFactory->findOrCreate($string);
308
                if (null !== $tag) {
309
                    $set[] = $tag->id;
310
                }
311
            }
312
        }
313
        $journal->tags()->sync($set);
314
    }
315
316
317
}
318