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 ( 4d9763...76aa8a )
by James
23:28 queued 10:43
created

app/Api/V1/Controllers/RuleGroupController.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * RuleGroupController.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\Api\V1\Controllers;
25
26
use Carbon\Carbon;
27
use FireflyIII\Api\V1\Requests\RuleGroupRequest;
28
use FireflyIII\Exceptions\FireflyException;
29
use FireflyIII\Jobs\ExecuteRuleOnExistingTransactions;
30
use FireflyIII\Models\AccountType;
31
use FireflyIII\Models\Rule;
32
use FireflyIII\Models\RuleGroup;
33
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
34
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
35
use FireflyIII\TransactionRules\TransactionMatcher;
36
use FireflyIII\Transformers\RuleGroupTransformer;
37
use FireflyIII\Transformers\RuleTransformer;
38
use FireflyIII\Transformers\TransactionTransformer;
39
use FireflyIII\User;
40
use Illuminate\Http\JsonResponse;
41
use Illuminate\Http\Request;
42
use Illuminate\Pagination\LengthAwarePaginator;
43
use Illuminate\Support\Collection;
44
use League\Fractal\Manager;
45
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
46
use League\Fractal\Resource\Collection as FractalCollection;
47
use League\Fractal\Resource\Item;
48
use League\Fractal\Serializer\JsonApiSerializer;
49
use Log;
50
51
52
/**
53
 * Class RuleGroupController
54
 */
55
class RuleGroupController extends Controller
56
{
57
    /** @var AccountRepositoryInterface Account repository */
58
    private $accountRepository;
59
    /** @var RuleGroupRepositoryInterface The rule group repository */
60
    private $ruleGroupRepository;
61
62
    /**
63
     * RuleGroupController constructor.
64
     */
65
    public function __construct()
66
    {
67
        parent::__construct();
68
        $this->middleware(
69
            function ($request, $next) {
70
                /** @var User $user */
71
                $user = auth()->user();
72
73
                $this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
74
                $this->ruleGroupRepository->setUser($user);
75
76
                $this->accountRepository = app(AccountRepositoryInterface::class);
77
                $this->accountRepository->setUser($user);
78
79
                return $next($request);
80
            }
81
        );
82
    }
83
84
    /**
85
     * Delete the resource.
86
     *
87
     * @param RuleGroup $ruleGroup
88
     *
89
     * @return JsonResponse
90
     */
91
    public function delete(RuleGroup $ruleGroup): JsonResponse
92
    {
93
        $this->ruleGroupRepository->destroy($ruleGroup, null);
94
95
        return response()->json([], 204);
96
    }
97
98
    /**
99
     * List all of them.
100
     *
101
     * @param Request $request
102
     *
103
     * @return JsonResponse]
104
     */
105
    public function index(Request $request): JsonResponse
106
    {
107
        // create some objects:
108
        $manager = new Manager;
109
        $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
110
111
        // types to get, page size:
112
        $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
113
114
        // get list of rule groups. Count it and split it.
115
        $collection = $this->ruleGroupRepository->get();
116
        $count      = $collection->count();
117
        $ruleGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
118
119
        // make paginator:
120
        $paginator = new LengthAwarePaginator($ruleGroups, $count, $pageSize, $this->parameters->get('page'));
121
        $paginator->setPath(route('api.v1.rule_groups.index') . $this->buildParams());
122
123
        // present to user.
124
        $manager->setSerializer(new JsonApiSerializer($baseUrl));
125
126
        /** @var RuleGroupTransformer $transformer */
127
        $transformer = app(RuleGroupTransformer::class);
128
        $transformer->setParameters($this->parameters);
129
130
        $resource = new FractalCollection($ruleGroups, $transformer, 'rule_groups');
131
        $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
132
133
        return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
134
    }
135
136
    /**
137
     * @param Request   $request
138
     * @param RuleGroup $group
139
     *
140
     * @return JsonResponse
141
     */
142
    public function rules(Request $request, RuleGroup $group): JsonResponse
143
    {
144
        // create some objects:
145
        $manager = new Manager;
146
        $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
147
148
        // types to get, page size:
149
        $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
150
151
        // get list of budgets. Count it and split it.
152
        $collection = $this->ruleGroupRepository->getRules($group);
153
        $count      = $collection->count();
154
        $rules      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
155
156
        // make paginator:
157
        $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
158
        $paginator->setPath(route('api.v1.rule_groups.rules', [$group->id]) . $this->buildParams());
159
160
        // present to user.
161
        $manager->setSerializer(new JsonApiSerializer($baseUrl));
162
163
        /** @var RuleTransformer $transformer */
164
        $transformer = app(RuleTransformer::class);
165
        $transformer->setParameters($this->parameters);
166
167
        $resource = new FractalCollection($rules, $transformer, 'rules');
168
        $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
169
170
        return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
171
172
    }
173
174
    /**
175
     * List single resource.
176
     *
177
     * @param Request   $request
178
     * @param RuleGroup $ruleGroup
179
     *
180
     * @return JsonResponse
181
     */
182
    public function show(Request $request, RuleGroup $ruleGroup): JsonResponse
183
    {
184
        $manager = new Manager();
185
        $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
186
        $manager->setSerializer(new JsonApiSerializer($baseUrl));
187
188
        /** @var RuleGroupTransformer $transformer */
189
        $transformer = app(RuleGroupTransformer::class);
190
        $transformer->setParameters($this->parameters);
191
192
        $resource = new Item($ruleGroup, $transformer, 'rule_groups');
193
194
        return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
195
196
    }
197
198
    /**
199
     * Store new object.
200
     *
201
     * @param RuleGroupRequest $request
202
     *
203
     * @return JsonResponse
204
     */
205
    public function store(RuleGroupRequest $request): JsonResponse
206
    {
207
        $ruleGroup = $this->ruleGroupRepository->store($request->getAll());
208
        $manager   = new Manager();
209
        $baseUrl   = $request->getSchemeAndHttpHost() . '/api/v1';
210
        $manager->setSerializer(new JsonApiSerializer($baseUrl));
211
212
        /** @var RuleGroupTransformer $transformer */
213
        $transformer = app(RuleGroupTransformer::class);
214
        $transformer->setParameters($this->parameters);
215
216
        $resource = new Item($ruleGroup, $transformer, 'rule_groups');
217
218
        return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
219
220
    }
221
222
    /**
223
     * @param Request   $request
224
     * @param RuleGroup $group
225
     *
226
     * @return JsonResponse
227
     * @throws FireflyException
228
     */
229
    public function testGroup(Request $request, RuleGroup $group): JsonResponse
230
    {
231
        Log::debug('Now in testGroup()');
232
        /** @var Collection $rules */
233
        $rules = $this->ruleGroupRepository->getActiveRules($group);
234
        if (0 === $rules->count()) {
235
            throw new FireflyException('No rules in this rule group.');
236
        }
237
        $parameters           = $this->getTestParameters($request);
238
        $accounts             = $this->getAccountParameter($parameters['account_list']);
239
        $matchingTransactions = new Collection;
240
241
        Log::debug(sprintf('Going to test %d rules', $rules->count()));
242
        /** @var Rule $rule */
243
        foreach ($rules as $rule) {
244
            Log::debug(sprintf('Now testing rule #%d, "%s"', $rule->id, $rule->title));
245
            /** @var TransactionMatcher $matcher */
246
            $matcher = app(TransactionMatcher::class);
247
            // set all parameters:
248
            $matcher->setRule($rule);
249
            $matcher->setStartDate($parameters['start_date']);
250
            $matcher->setEndDate($parameters['end_date']);
251
            $matcher->setSearchLimit($parameters['search_limit']);
252
            $matcher->setTriggeredLimit($parameters['trigger_limit']);
253
            $matcher->setAccounts($accounts);
254
255
            $result               = $matcher->findTransactionsByRule();
256
            $matchingTransactions = $result->merge($matchingTransactions);
257
        }
258
        $matchingTransactions = $matchingTransactions->unique('id');
259
260
        // make paginator out of results.
261
        $count        = $matchingTransactions->count();
262
        $transactions = $matchingTransactions->slice(($parameters['page'] - 1) * $parameters['page_size'], $parameters['page_size']);
263
        // make paginator:
264
        $paginator = new LengthAwarePaginator($transactions, $count, $parameters['page_size'], $parameters['page']);
265
        $paginator->setPath(route('api.v1.rule_groups.test', [$group->id]) . $this->buildParams());
266
267
        // resulting list is presented as JSON thing.
268
        $manager = new Manager();
269
        $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
270
        $manager->setSerializer(new JsonApiSerializer($baseUrl));
271
272
        /** @var TransactionTransformer $transformer */
273
        $transformer = app(TransactionTransformer::class);
274
        $transformer->setParameters($this->parameters);
275
276
        $resource = new FractalCollection($matchingTransactions, $transformer, 'transactions');
277
        $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
278
279
        return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
280
    }
281
282
    /**
283
     * Execute the given rule group on a set of existing transactions.
284
     *
285
     * @param Request   $request
286
     * @param RuleGroup $group
287
     *
288
     * @return JsonResponse
289
     */
290
    public function triggerGroup(Request $request, RuleGroup $group): JsonResponse
291
    {
292
        // Get parameters specified by the user
293
        /** @var User $user */
294
        $user        = auth()->user();
295
        $startDate   = new Carbon($request->get('start_date'));
296
        $endDate     = new Carbon($request->get('end_date'));
297
        $accountList = '' === (string)$request->query('accounts') ? [] : explode(',', $request->query('accounts'));
298
        $accounts    = new Collection;
299
300
        foreach ($accountList as $accountId) {
301
            Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
302
            $account = $this->accountRepository->findNull((int)$accountId);
303
            if (null !== $account && AccountType::ASSET === $account->accountType->type) {
304
                Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
305
                $accounts->push($account);
306
            }
307
            if (null === $account) {
308
                Log::debug(sprintf('No asset account with id "%s"', $accountId));
309
            }
310
        }
311
312
        /** @var Collection $rules */
313
        $rules = $this->ruleGroupRepository->getActiveRules($group);
314
        foreach ($rules as $rule) {
315
            // Create a job to do the work asynchronously
316
            $job = new ExecuteRuleOnExistingTransactions($rule);
317
318
            // Apply parameters to the job
319
            $job->setUser($user);
320
            $job->setAccounts($accounts);
321
            $job->setStartDate($startDate);
322
            $job->setEndDate($endDate);
323
324
            // Dispatch a new job to execute it in a queue
325
            $this->dispatch($job);
326
        }
327
328
        return response()->json([], 204);
329
    }
330
331
    /**
332
     * Update a rule group.
333
     * TODO update order of rule group
334
     *
335
     * @param RuleGroupRequest $request
336
     * @param RuleGroup        $ruleGroup
337
     *
338
     * @return JsonResponse
339
     */
340
    public function update(RuleGroupRequest $request, RuleGroup $ruleGroup): JsonResponse
341
    {
342
        $ruleGroup = $this->ruleGroupRepository->update($ruleGroup, $request->getAll());
343
        $manager   = new Manager();
344
        $baseUrl   = $request->getSchemeAndHttpHost() . '/api/v1';
345
        $manager->setSerializer(new JsonApiSerializer($baseUrl));
346
347
        /** @var RuleGroupTransformer $transformer */
348
        $transformer = app(RuleGroupTransformer::class);
349
        $transformer->setParameters($this->parameters);
350
351
        $resource = new Item($ruleGroup, $transformer, 'rule_groups');
352
353
        return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
354
355
    }
356
357
    /**
358
     * @param array $accounts
359
     *
360
     * @return Collection
361
     */
362
    private function getAccountParameter(array $accounts): Collection
363
    {
364
        $return = new Collection;
365
        foreach ($accounts as $accountId) {
366
            Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
367
            $account = $this->accountRepository->findNull((int)$accountId);
368
            if (null !== $account && AccountType::ASSET === $account->accountType->type) {
369
                Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
370
                $return->push($account);
371
            }
372
            if (null === $account) {
373
                Log::debug(sprintf('No asset account with id "%s"', $accountId));
374
            }
375
        }
376
377
        return $return;
378
    }
379
380
    /**
381
     * @param Request $request
382
     *
383
     * @return array
384
     */
385
    private function getTestParameters(Request $request): array
386
    {
387
        return [
388
            'page_size'     => (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data,
389
            'page'          => 0 === (int)$request->query('page') ? 1 : (int)$request->query('page'),
390
            'start_date'    => null === $request->query('start_date') ? null : Carbon::createFromFormat('Y-m-d', $request->query('start_date')),
0 ignored issues
show
It seems like $request->query('start_date') can also be of type array; however, parameter $time of Carbon\Carbon::createFromFormat() 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

390
            'start_date'    => null === $request->query('start_date') ? null : Carbon::createFromFormat('Y-m-d', /** @scrutinizer ignore-type */ $request->query('start_date')),
Loading history...
391
            'end_date'      => null === $request->query('end_date') ? null : Carbon::createFromFormat('Y-m-d', $request->query('end_date')),
392
            'search_limit'  => 0 === (int)$request->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$request->query('search_limit'),
393
            'trigger_limit' => 0 === (int)$request->query('triggered_limit')
394
                ? (int)config('firefly.test-triggers.range')
395
                : (int)$request->query(
396
                    'triggered_limit'
397
                ),
398
            'account_list'  => '' === (string)$request->query('accounts') ? [] : explode(',', $request->query('accounts')),
399
        ];
400
    }
401
}
402