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 ( a70b7c...7d482a )
by James
21:49 queued 11:38
created

app/Api/V1/Controllers/Chart/AccountController.php (4 issues)

Labels
1
<?php
2
3
/**
4
 * AccountController.php
5
 * Copyright (c) 2019 [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
declare(strict_types=1);
24
25
namespace FireflyIII\Api\V1\Controllers\Chart;
26
27
use Carbon\Carbon;
28
use FireflyIII\Api\V1\Controllers\Controller;
29
use FireflyIII\Exceptions\FireflyException;
30
use FireflyIII\Models\Account;
31
use FireflyIII\Models\AccountType;
32
use FireflyIII\Models\TransactionCurrency;
33
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
34
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
35
use FireflyIII\User;
36
use Illuminate\Http\JsonResponse;
37
use Illuminate\Http\Request;
38
use Illuminate\Support\Collection;
39
40
/**
41
 * Class AccountController
42
 */
43
class AccountController extends Controller
44
{
45
    /** @var CurrencyRepositoryInterface */
46
    private $currencyRepository;
47
    /** @var AccountRepositoryInterface */
48
    private $repository;
49
50
    /**
51
     * AccountController constructor.
52
     */
53
    public function __construct()
54
    {
55
        parent::__construct();
56
        $this->middleware(
57
            function ($request, $next) {
58
                /** @var User $user */
59
                $user             = auth()->user();
60
                $this->repository = app(AccountRepositoryInterface::class);
61
                $this->repository->setUser($user);
62
63
                $this->currencyRepository = app(CurrencyRepositoryInterface::class);
64
                $this->currencyRepository->setUser($user);
65
66
                return $next($request);
67
            }
68
        );
69
    }
70
71
    /**
72
     * @param Request $request
73
     *
74
     * @return JsonResponse
75
     * @throws FireflyException
76
     */
77
    public function expenseOverview(Request $request): JsonResponse
78
    {
79
        // parameters for chart:
80
        $start = (string)$request->get('start');
81
        $end   = (string)$request->get('end');
82
        if ('' === $start || '' === $end) {
83
            throw new FireflyException('Start and end are mandatory parameters.');
84
        }
85
86
        $start = Carbon::createFromFormat('Y-m-d', $start);
87
        $end   = Carbon::createFromFormat('Y-m-d', $end);
88
        $start->subDay();
89
90
        // prep some vars:
91
        $currencies = [];
92
        $chartData  = [];
93
        $tempData   = [];
94
95
        // grab all accounts and names
96
        $accounts      = $this->repository->getAccountsByType([AccountType::EXPENSE]);
97
        $accountNames  = $this->extractNames($accounts);
98
        $startBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $start);
0 ignored issues
show
The method balancesPerCurrencyByAccounts() does not exist on FireflyIII\Support\Facades\Steam. Did you maybe mean balance()? ( Ignorable by Annotation )

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

98
        $startBalances = app('steam')->/** @scrutinizer ignore-call */ balancesPerCurrencyByAccounts($accounts, $start);

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...
99
        $endBalances   = app('steam')->balancesPerCurrencyByAccounts($accounts, $end);
100
101
        // loop the end balances. This is an array for each account ($expenses)
102
        foreach ($endBalances as $accountId => $expenses) {
103
            $accountId = (int)$accountId;
104
            // loop each expense entry (each entry can be a different currency).
105
            foreach ($expenses as $currencyId => $endAmount) {
106
                $currencyId = (int)$currencyId;
107
108
                // see if there is an accompanying start amount.
109
                // grab the difference and find the currency.
110
                $startAmount             = $startBalances[$accountId][$currencyId] ?? '0';
111
                $diff                    = bcsub($endAmount, $startAmount);
112
                $currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->findNull($currencyId);
113
                if (0 !== bccomp($diff, '0')) {
114
                    // store the values in a temporary array.
115
                    $tempData[] = [
116
                        'name'        => $accountNames[$accountId],
117
                        'difference'  => $diff,
118
                        'diff_float'  => (float)$diff,
119
                        'currency_id' => $currencyId,
120
                    ];
121
                }
122
            }
123
        }
124
125
        // sort temp array by amount.
126
        $amounts = array_column($tempData, 'diff_float');
127
        array_multisort($amounts, SORT_DESC, $tempData);
128
129
        // loop all found currencies and build the data array for the chart.
130
        /**
131
         * @var int                 $currencyId
132
         * @var TransactionCurrency $currency
133
         */
134
        foreach ($currencies as $currencyId => $currency) {
135
            $currentSet             = [
136
                'label'                   => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
137
                'currency_id'             => $currency->id,
138
                'currency_code'           => $currency->code,
139
                'currency_symbol'         => $currency->symbol,
140
                'currency_decimal_places' => $currency->decimal_places,
141
                'type'                    => 'bar', // line, area or bar
142
                'yAxisID'                 => 0, // 0, 1, 2
143
                'entries'                 => $this->expandNames($tempData),
144
            ];
145
            $chartData[$currencyId] = $currentSet;
146
        }
147
148
        // loop temp data and place data in correct array:
149
        foreach ($tempData as $entry) {
150
            $currencyId                               = $entry['currency_id'];
151
            $name                                     = $entry['name'];
152
            $chartData[$currencyId]['entries'][$name] = round($entry['difference'], $chartData[$currencyId]['currency_decimal_places']);
153
        }
154
        $chartData = array_values($chartData);
155
156
        return response()->json($chartData);
157
    }
158
159
    /**
160
     * @param Request $request
161
     *
162
     * @return JsonResponse
163
     * @throws FireflyException
164
     */
165
    public function overview(Request $request): JsonResponse
166
    {
167
        // parameters for chart:
168
        $start = (string)$request->get('start');
169
        $end   = (string)$request->get('end');
170
        if ('' === $start || '' === $end) {
171
            throw new FireflyException('Start and end are mandatory parameters.');
172
        }
173
174
        $start = Carbon::createFromFormat('Y-m-d', $start);
175
        $end   = Carbon::createFromFormat('Y-m-d', $end);
176
177
        // user's preferences
178
        $defaultSet = $this->repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray();
179
        $frontPage  = app('preferences')->get('frontPageAccounts', $defaultSet);
180
        $default    = app('amount')->getDefaultCurrency();
181
        if (0 === \count($frontPage->data)) {
0 ignored issues
show
$frontPage->data of type string is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

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

181
        if (0 === \count(/** @scrutinizer ignore-type */ $frontPage->data)) {
Loading history...
182
            $frontPage->data = $defaultSet;
183
            $frontPage->save();
184
        }
185
186
        // get accounts:
187
        $accounts  = $this->repository->getAccountsById($frontPage->data);
0 ignored issues
show
$frontPage->data of type string is incompatible with the type array expected by parameter $accountIds of FireflyIII\Repositories\...face::getAccountsById(). ( Ignorable by Annotation )

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

187
        $accounts  = $this->repository->getAccountsById(/** @scrutinizer ignore-type */ $frontPage->data);
Loading history...
188
        $chartData = [];
189
        /** @var Account $account */
190
        foreach ($accounts as $account) {
191
            $currency = $this->repository->getAccountCurrency($account);
192
            if (null === $currency) {
193
                $currency = $default;
194
            }
195
            $currentSet = [
196
                'label'                   => $account->name,
197
                'currency_id'             => $currency->id,
198
                'currency_code'           => $currency->code,
199
                'currency_symbol'         => $currency->symbol,
200
                'currency_decimal_places' => $currency->decimal_places,
201
                'type'                    => 'line', // line, area or bar
202
                'yAxisID'                 => 0, // 0, 1, 2
203
                'entries'                 => [],
204
            ];
205
206
            $currentStart = clone $start;
207
            $range        = app('steam')->balanceInRange($account, $start, clone $end);
0 ignored issues
show
It seems like $start can also be of type false; however, parameter $start of FireflyIII\Support\Facades\Steam::balanceInRange() does only seem to accept Carbon\Carbon, 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

207
            $range        = app('steam')->balanceInRange($account, /** @scrutinizer ignore-type */ $start, clone $end);
Loading history...
208
            $previous     = round(array_values($range)[0], 12);
209
            while ($currentStart <= $end) {
210
                $format   = $currentStart->format('Y-m-d');
211
                $label    = $currentStart->format('Y-m-d');
212
                $balance  = isset($range[$format]) ? round($range[$format], 12) : $previous;
213
                $previous = $balance;
214
                $currentStart->addDay();
215
                $currentSet['entries'][$label] = $balance;
216
            }
217
            $chartData[] = $currentSet;
218
        }
219
220
        return response()->json($chartData);
221
    }
222
223
    /**
224
     * @param Request $request
225
     *
226
     * @return JsonResponse
227
     * @throws FireflyException
228
     */
229
    public function revenueOverview(Request $request): JsonResponse
230
    {
231
        // parameters for chart:
232
        $start = (string)$request->get('start');
233
        $end   = (string)$request->get('end');
234
        if ('' === $start || '' === $end) {
235
            throw new FireflyException('Start and end are mandatory parameters.');
236
        }
237
238
        $start = Carbon::createFromFormat('Y-m-d', $start);
239
        $end   = Carbon::createFromFormat('Y-m-d', $end);
240
        $start->subDay();
241
242
        // prep some vars:
243
        $currencies = [];
244
        $chartData  = [];
245
        $tempData   = [];
246
247
        // grab all accounts and names
248
        $accounts      = $this->repository->getAccountsByType([AccountType::REVENUE]);
249
        $accountNames  = $this->extractNames($accounts);
250
        $startBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $start);
251
        $endBalances   = app('steam')->balancesPerCurrencyByAccounts($accounts, $end);
252
253
        // loop the end balances. This is an array for each account ($expenses)
254
        foreach ($endBalances as $accountId => $expenses) {
255
            $accountId = (int)$accountId;
256
            // loop each expense entry (each entry can be a different currency).
257
            foreach ($expenses as $currencyId => $endAmount) {
258
                $currencyId = (int)$currencyId;
259
260
                // see if there is an accompanying start amount.
261
                // grab the difference and find the currency.
262
                $startAmount             = $startBalances[$accountId][$currencyId] ?? '0';
263
                $diff                    = bcsub($endAmount, $startAmount);
264
                $currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->findNull($currencyId);
265
                if (0 !== bccomp($diff, '0')) {
266
                    // store the values in a temporary array.
267
                    $tempData[] = [
268
                        'name'        => $accountNames[$accountId],
269
                        'difference'  => bcmul($diff, '-1'),
270
                        'diff_float'  => (float)$diff * -1,
271
                        'currency_id' => $currencyId,
272
                    ];
273
                }
274
            }
275
        }
276
277
        // sort temp array by amount.
278
        $amounts = array_column($tempData, 'diff_float');
279
        array_multisort($amounts, SORT_DESC, $tempData);
280
281
        // loop all found currencies and build the data array for the chart.
282
        /**
283
         * @var int                 $currencyId
284
         * @var TransactionCurrency $currency
285
         */
286
        foreach ($currencies as $currencyId => $currency) {
287
            $currentSet             = [
288
                'label'                   => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
289
                'currency_id'             => $currency->id,
290
                'currency_code'           => $currency->code,
291
                'currency_symbol'         => $currency->symbol,
292
                'currency_decimal_places' => $currency->decimal_places,
293
                'type'                    => 'bar', // line, area or bar
294
                'yAxisID'                 => 0, // 0, 1, 2
295
                'entries'                 => $this->expandNames($tempData),
296
            ];
297
            $chartData[$currencyId] = $currentSet;
298
        }
299
300
        // loop temp data and place data in correct array:
301
        foreach ($tempData as $entry) {
302
            $currencyId                               = $entry['currency_id'];
303
            $name                                     = $entry['name'];
304
            $chartData[$currencyId]['entries'][$name] = round($entry['difference'], $chartData[$currencyId]['currency_decimal_places']);
305
        }
306
        $chartData = array_values($chartData);
307
308
        return response()->json($chartData);
309
    }
310
311
    /**
312
     * Small helper function for the revenue and expense account charts.
313
     * TODO should include Trait instead of doing this.
314
     *
315
     * @param array $names
316
     *
317
     * @return array
318
     */
319
    protected function expandNames(array $names): array
320
    {
321
        $result = [];
322
        foreach ($names as $entry) {
323
            $result[$entry['name']] = 0;
324
        }
325
326
        return $result;
327
    }
328
329
    /**
330
     * Small helper function for the revenue and expense account charts.
331
     * TODO should include Trait instead of doing this.
332
     *
333
     * @param Collection $accounts
334
     *
335
     * @return array
336
     */
337
    protected function extractNames(Collection $accounts): array
338
    {
339
        $return = [];
340
        /** @var Account $account */
341
        foreach ($accounts as $account) {
342
            $return[$account->id] = $account->name;
343
        }
344
345
        return $return;
346
    }
347
348
}
349