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

app/Transformers/BillTransformer.php (2 issues)

Labels
Severity
1
<?php
2
/**
3
 * BillTransformer.php
4
 * Copyright (c) 2018 [email protected]
5
 *
6
 * This file is part of Firefly III.
7
 *
8
 * Firefly III is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * Firefly III 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 General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
declare(strict_types=1);
23
24
namespace FireflyIII\Transformers;
25
26
use Carbon\Carbon;
27
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
28
use FireflyIII\Models\Bill;
29
use FireflyIII\Models\Note;
30
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
31
use Illuminate\Support\Collection;
32
use League\Fractal\Resource\Collection as FractalCollection;
33
use League\Fractal\Resource\Item;
34
use League\Fractal\TransformerAbstract;
35
use Log;
36
use Symfony\Component\HttpFoundation\ParameterBag;
37
38
/**
39
 * Class BillTransformer
40
 */
41
class BillTransformer extends TransformerAbstract
42
{
43
    /**
44
     * List of resources possible to include
45
     *
46
     * @var array
47
     */
48
    protected $availableIncludes = ['attachments', 'transactions', 'user'];
49
    /**
50
     * List of resources to automatically include
51
     *
52
     * @var array
53
     */
54
    protected $defaultIncludes = [];
55
56
    /** @var ParameterBag */
57
    protected $parameters;
58
59
    /**
60
     * BillTransformer constructor.
61
     *
62
     * @codeCoverageIgnore
63
     *
64
     * @param ParameterBag $parameters
65
     */
66
    public function __construct(ParameterBag $parameters)
67
    {
68
        $this->parameters = $parameters;
69
    }
70
71
    /**
72
     * Include any attachments.
73
     *
74
     * @param Bill $bill
75
     *
76
     * @codeCoverageIgnore
77
     * @return FractalCollection
78
     */
79
    public function includeAttachments(Bill $bill): FractalCollection
80
    {
81
        $attachments = $bill->attachments()->get();
82
83
        return $this->collection($attachments, new AttachmentTransformer($this->parameters), 'attachments');
84
    }
85
86
    /**
87
     * Include any transactions.
88
     *
89
     * @param Bill $bill
90
     *
91
     * @codeCoverageIgnore
92
     * @return FractalCollection
93
     */
94
    public function includeTransactions(Bill $bill): FractalCollection
95
    {
96
        $pageSize = intval(app('preferences')->getForUser($bill->user, 'listPageSize', 50)->data);
97
98
        // journals always use collector and limited using URL parameters.
99
        $collector = app(JournalCollectorInterface::class);
100
        $collector->setUser($bill->user);
101
        $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
102
        $collector->setAllAssetAccounts();
103
        $collector->setBills(new Collection([$bill]));
104
        if (!is_null($this->parameters->get('start')) && !is_null($this->parameters->get('end'))) {
105
            $collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
106
        }
107
        $collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
108
        $journals = $collector->getJournals();
109
110
        return $this->collection($journals, new TransactionTransformer($this->parameters), 'transactions');
111
    }
112
113
    /**
114
     * Include the user.
115
     *
116
     * @param Bill $bill
117
     *
118
     * @codeCoverageIgnore
119
     * @return \League\Fractal\Resource\Item
120
     */
121
    public function includeUser(Bill $bill): Item
122
    {
123
        return $this->item($bill->user, new UserTransformer($this->parameters), 'users');
124
    }
125
126
    /**
127
     * Transform the bill.
128
     *
129
     * @param Bill $bill
130
     *
131
     * @return array
132
     */
133
    public function transform(Bill $bill): array
134
    {
135
        $paidData = $this->paidData($bill);
136
        $payDates = $this->payDates($bill);
137
        $data     = [
138
            'id'                  => (int)$bill->id,
139
            'updated_at'          => $bill->updated_at->toAtomString(),
140
            'created_at'          => $bill->created_at->toAtomString(),
141
            'name'                => $bill->name,
142
            'match'               => explode(',', $bill->match),
143
            'amount_min'          => round($bill->amount_min, 2),
144
            'amount_max'          => round($bill->amount_max, 2),
145
            'date'                => $bill->date->format('Y-m-d'),
146
            'repeat_freq'         => $bill->repeat_freq,
147
            'skip'                => (int)$bill->skip,
148
            'automatch'           => intval($bill->automatch) === 1,
0 ignored issues
show
The property automatch does not seem to exist on FireflyIII\Models\Bill. 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...
149
            'active'              => intval($bill->active) === 1,
0 ignored issues
show
The property active does not seem to exist on FireflyIII\Models\Bill. 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...
150
            'attachments_count'   => $bill->attachments()->count(),
151
            'pay_dates'           => $payDates,
152
            'paid_dates'          => $paidData['paid_dates'],
153
            'next_expected_match' => $paidData['next_expected_match'],
154
            'notes'               => null,
155
            'links'               => [
156
                [
157
                    'rel' => 'self',
158
                    'uri' => '/bills/' . $bill->id,
159
                ],
160
            ],
161
        ];
162
        /** @var Note $note */
163
        $note = $bill->notes()->first();
164
        if (!is_null($note)) {
165
            $data['notes'] = $note->text;
166
        }
167
168
        return $data;
169
170
    }
171
172
    /**
173
     * Returns the latest date in the set, or start when set is empty.
174
     *
175
     * @param Collection $dates
176
     * @param Carbon     $default
177
     *
178
     * @return Carbon
179
     */
180
    protected function lastPaidDate(Collection $dates, Carbon $default): Carbon
181
    {
182
        if (0 === $dates->count()) {
183
            return $default; // @codeCoverageIgnore
184
        }
185
        $latest = $dates->first();
186
        /** @var Carbon $date */
187
        foreach ($dates as $date) {
188
            if ($date->gte($latest)) {
189
                $latest = $date;
190
            }
191
        }
192
193
        return $latest;
194
    }
195
196
    /**
197
     * Given a bill and a date, this method will tell you at which moment this bill expects its next
198
     * transaction. Whether or not it is there already, is not relevant.
199
     *
200
     * @param Bill   $bill
201
     * @param Carbon $date
202
     *
203
     * @return \Carbon\Carbon
204
     */
205
    protected function nextDateMatch(Bill $bill, Carbon $date): Carbon
206
    {
207
        $start = clone $bill->date;
208
        while ($start < $date) {
209
            $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
210
        }
211
212
        return $start;
213
    }
214
215
    /**
216
     * Get the data the bill was paid and predict the next expected match.
217
     *
218
     * @param Bill $bill
219
     *
220
     * @return array
221
     */
222
    protected function paidData(Bill $bill): array
223
    {
224
        Log::debug(sprintf('Now in paidData for bill #%d', $bill->id));
225
        if (is_null($this->parameters->get('start')) || is_null($this->parameters->get('end'))) {
226
            Log::debug('parameters are NULL, return empty array');
227
228
            return [
229
                'paid_dates'          => [],
230
                'next_expected_match' => null,
231
            ];
232
        }
233
234
        /** @var BillRepositoryInterface $repository */
235
        $repository = app(BillRepositoryInterface::class);
236
        $repository->setUser($bill->user);
237
        $set = $repository->getPaidDatesInRange($bill, $this->parameters->get('start'), $this->parameters->get('end'));
238
        Log::debug(sprintf('Count %d entries in getPaidDatesInRange()', $set->count()));
239
        $simple = $set->map(
240
            function (Carbon $date) {
241
                return $date->format('Y-m-d');
242
            }
243
        );
244
245
        // calculate next expected match:
246
        $lastPaidDate = $this->lastPaidDate($set, $this->parameters->get('start'));
247
        $nextMatch    = clone $bill->date;
248
        while ($nextMatch < $lastPaidDate) {
249
            $nextMatch = app('navigation')->addPeriod($nextMatch, $bill->repeat_freq, $bill->skip);
250
        }
251
        $end          = app('navigation')->addPeriod($nextMatch, $bill->repeat_freq, $bill->skip);
252
        $journalCount = $repository->getPaidDatesInRange($bill, $nextMatch, $end)->count();
253
        if ($journalCount > 0) {
254
            $nextMatch = clone $end;
255
        }
256
257
        return [
258
            'paid_dates'          => $simple->toArray(),
259
            'next_expected_match' => $nextMatch->format('Y-m-d'),
260
        ];
261
    }
262
263
    /**
264
     * @param Bill $bill
265
     *
266
     * @return array
267
     */
268
    protected function payDates(Bill $bill): array
269
    {
270
        if (is_null($this->parameters->get('start')) || is_null($this->parameters->get('end'))) {
271
            return [];
272
        }
273
        $set          = new Collection;
274
        $currentStart = clone $this->parameters->get('start');
275
        while ($currentStart <= $this->parameters->get('end')) {
276
            $nextExpectedMatch = $this->nextDateMatch($bill, $currentStart);
277
            // If nextExpectedMatch is after end, we continue:
278
            if ($nextExpectedMatch > $this->parameters->get('end')) {
279
                break;
280
            }
281
            // add to set
282
            $set->push(clone $nextExpectedMatch);
283
            $nextExpectedMatch->addDay();
284
            $currentStart = clone $nextExpectedMatch;
285
        }
286
        $simple = $set->map(
287
            function (Carbon $date) {
288
                return $date->format('Y-m-d');
289
            }
290
        );
291
292
        return $simple->toArray();
293
    }
294
}
295