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/Export/ExpandedProcessor.php (1 issue)

Severity
1
<?php
2
/**
3
 * ExpandedProcessor.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
/** @noinspection PhpDynamicAsStaticMethodCallInspection */
23
24
declare(strict_types=1);
25
26
namespace FireflyIII\Export;
27
28
use DB;
29
use FireflyIII\Exceptions\FireflyException;
30
use FireflyIII\Export\Collector\AttachmentCollector;
31
use FireflyIII\Export\Collector\UploadCollector;
32
use FireflyIII\Export\Entry\Entry;
33
use FireflyIII\Export\Exporter\ExporterInterface;
34
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
35
use FireflyIII\Helpers\Filter\InternalTransferFilter;
36
use FireflyIII\Models\AccountMeta;
37
use FireflyIII\Models\ExportJob;
38
use FireflyIII\Models\Note;
39
use FireflyIII\Models\Transaction;
40
use FireflyIII\Models\TransactionJournal;
41
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
42
use Illuminate\Support\Collection;
43
use Illuminate\Support\Facades\Storage;
44
use Log;
45
use ZipArchive;
46
47
/**
48
 * Class ExpandedProcessor.
49
 *
50
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) // its doing a lot.
51
 *
52
 * @codeCoverageIgnore
53
 * @deprecated
54
 */
55
class ExpandedProcessor implements ProcessorInterface
0 ignored issues
show
Deprecated Code introduced by
The interface FireflyIII\Export\ProcessorInterface has been deprecated. ( Ignorable by Annotation )

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

55
class ExpandedProcessor implements /** @scrutinizer ignore-deprecated */ ProcessorInterface

This interface has been deprecated. The supplier of the interface has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the interface will be removed and what other interface to use instead.

Loading history...
56
{
57
    /** @var Collection All accounts */
58
    public $accounts;
59
    /** @var string The export format */
60
    public $exportFormat;
61
    /** @var bool Should include attachments */
62
    public $includeAttachments;
63
    /** @var bool Should include old uploads */
64
    public $includeOldUploads;
65
    /** @var ExportJob The export job itself */
66
    public $job;
67
    /** @var array The settings */
68
    public $settings;
69
    /** @var Collection The entries to export. */
70
    private $exportEntries;
71
    /** @var Collection The files to export */
72
    private $files;
73
    /** @var Collection The journals. */
74
    private $journals;
75
76
    /**
77
     * Processor constructor.
78
     */
79
    public function __construct()
80
    {
81
        $this->journals      = new Collection;
82
        $this->exportEntries = new Collection;
83
        $this->files         = new Collection;
84
    }
85
86
    /**
87
     * Collect all attachments
88
     *
89
     * @return bool
90
     */
91
    public function collectAttachments(): bool
92
    {
93
        /** @var AttachmentCollector $attachmentCollector */
94
        $attachmentCollector = app(AttachmentCollector::class);
95
        $attachmentCollector->setJob($this->job);
96
        $attachmentCollector->setDates($this->settings['startDate'], $this->settings['endDate']);
97
        $attachmentCollector->run();
98
        $this->files = $this->files->merge($attachmentCollector->getEntries());
99
100
        return true;
101
    }
102
103
    /**
104
     * Collects all transaction journals.
105
     *
106
     * @return bool
107
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
108
     */
109
    public function collectJournals(): bool
110
    {
111
        // use journal collector thing.
112
        /** @var TransactionCollectorInterface $collector */
113
        $collector = app(TransactionCollectorInterface::class);
114
        $collector->setUser($this->job->user);
115
        $collector->setAccounts($this->accounts)->setRange($this->settings['startDate'], $this->settings['endDate'])
116
                  ->withOpposingAccount()->withBudgetInformation()->withCategoryInformation()
117
                  ->removeFilter(InternalTransferFilter::class);
118
        $transactions = $collector->getTransactions();
119
        // get some more meta data for each entry:
120
        $ids         = $transactions->pluck('journal_id')->toArray();
121
        $assetIds    = $transactions->pluck('account_id')->toArray();
122
        $opposingIds = $transactions->pluck('opposing_account_id')->toArray();
123
        $notes       = $this->getNotes($ids);
124
        $tags        = $this->getTags($ids);
125
        /** @var array $ibans */
126
        $ibans      = array_merge($this->getIbans($assetIds), $this->getIbans($opposingIds));
127
        $currencies = $this->getAccountCurrencies($ibans);
128
        $transactions->each(
129
            function (Transaction $transaction) use ($notes, $tags, $ibans, $currencies) {
130
                $journalId                            = (int)$transaction->journal_id;
131
                $accountId                            = (int)$transaction->account_id;
132
                $opposingId                           = (int)$transaction->opposing_account_id;
133
                $currencyId                           = (int)($ibans[$accountId]['currency_id'] ?? 0.0);
134
                $opposingCurrencyId                   = (int)($ibans[$opposingId]['currency_id'] ?? 0.0);
135
                $transaction->notes                   = $notes[$journalId] ?? '';
136
                $transaction->tags                    = implode(',', $tags[$journalId] ?? []);
137
                $transaction->account_number          = $ibans[$accountId]['accountNumber'] ?? '';
138
                $transaction->account_bic             = $ibans[$accountId]['BIC'] ?? '';
139
                $transaction->account_currency_code   = $currencies[$currencyId] ?? '';
140
                $transaction->opposing_account_number = $ibans[$opposingId]['accountNumber'] ?? '';
141
                $transaction->opposing_account_bic    = $ibans[$opposingId]['BIC'] ?? '';
142
                $transaction->opposing_currency_code  = $currencies[$opposingCurrencyId] ?? '';
143
            }
144
        );
145
146
        $this->journals = $transactions;
147
148
        return true;
149
    }
150
151
    /**
152
     * Get old oploads.
153
     *
154
     * @return bool
155
     */
156
    public function collectOldUploads(): bool
157
    {
158
        /** @var UploadCollector $uploadCollector */
159
        $uploadCollector = app(UploadCollector::class);
160
        $uploadCollector->setJob($this->job);
161
        $uploadCollector->run();
162
163
        $this->files = $this->files->merge($uploadCollector->getEntries());
164
165
        return true;
166
    }
167
168
    /**
169
     * Convert journals to export objects.
170
     *
171
     * @return bool
172
     */
173
    public function convertJournals(): bool
174
    {
175
        $this->journals->each(
176
            function (Transaction $transaction) {
177
                $this->exportEntries->push(Entry::fromTransaction($transaction));
178
            }
179
        );
180
        Log::debug(sprintf('Count %d entries in exportEntries (convertJournals)', $this->exportEntries->count()));
181
182
        return true;
183
    }
184
185
    /**
186
     * Create a ZIP file locally (!) in storage_path('export').
187
     *
188
     * @return bool
189
     *
190
     * @throws FireflyException
191
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
192
     */
193
    public function createZipFile(): bool
194
    {
195
        $zip       = new ZipArchive;
196
        $file      = $this->job->key . '.zip';
197
        $localPath = storage_path('export') . '/' . $file;
198
199
        if (true !== $zip->open($localPath, ZipArchive::CREATE)) {
200
            throw new FireflyException('Cannot store zip file.');
201
        }
202
        // for each file in the collection, add it to the zip file.
203
        $disk = Storage::disk('export');
204
        foreach ($this->getFiles() as $entry) {
205
            // is part of this job?
206
            $zipFileName = str_replace($this->job->key . '-', '', $entry);
207
            $zip->addFromString($zipFileName, $disk->get($entry));
208
        }
209
210
        $zip->close();
211
212
        // delete the files:
213
        $this->deleteFiles();
214
215
        return true;
216
    }
217
218
    /**
219
     * Export the journals.
220
     *
221
     * @return bool
222
     */
223
    public function exportJournals(): bool
224
    {
225
        $exporterClass = config('firefly.export_formats.' . $this->exportFormat);
226
        /** @var ExporterInterface $exporter */
227
        $exporter = app($exporterClass);
228
        $exporter->setJob($this->job);
229
        $exporter->setEntries($this->exportEntries);
230
        $exporter->run();
231
        $this->files->push($exporter->getFileName());
232
233
        return true;
234
    }
235
236
    /**
237
     * Get files.
238
     *
239
     * @return Collection
240
     */
241
    public function getFiles(): Collection
242
    {
243
        return $this->files;
244
    }
245
246
    /**
247
     * Save export job settings to class.
248
     *
249
     * @param array $settings
250
     */
251
    public function setSettings(array $settings): void
252
    {
253
        // save settings
254
        $this->settings           = $settings;
255
        $this->accounts           = $settings['accounts'];
256
        $this->exportFormat       = $settings['exportFormat'];
257
        $this->includeAttachments = $settings['includeAttachments'];
258
        $this->includeOldUploads  = $settings['includeOldUploads'];
259
        $this->job                = $settings['job'];
260
    }
261
262
    /**
263
     * Delete files.
264
     */
265
    private function deleteFiles(): void
266
    {
267
        $disk = Storage::disk('export');
268
        foreach ($this->getFiles() as $file) {
269
            $disk->delete($file);
270
        }
271
    }
272
273
    /**
274
     * Get currencies.
275
     *
276
     * @param array $array
277
     *
278
     * @return array
279
     */
280
    private function getAccountCurrencies(array $array): array
281
    {
282
        /** @var CurrencyRepositoryInterface $repository */
283
        $repository = app(CurrencyRepositoryInterface::class);
284
        $return     = [];
285
        $ids        = [];
286
        $repository->setUser($this->job->user);
287
        foreach ($array as $value) {
288
            $ids[] = (int)($value['currency_id'] ?? 0.0);
289
        }
290
        $ids    = array_unique($ids);
291
        $result = $repository->getByIds($ids);
292
293
        foreach ($result as $currency) {
294
            $return[$currency->id] = $currency->code;
295
        }
296
297
        return $return;
298
    }
299
300
    /**
301
     * Get all IBAN / SWIFT / account numbers.
302
     *
303
     * @param array $array
304
     *
305
     * @return array
306
     */
307
    private function getIbans(array $array): array
308
    {
309
        $array  = array_unique($array);
310
        $return = [];
311
        $set    = AccountMeta::whereIn('account_id', $array)
312
                             ->leftJoin('accounts', 'accounts.id', 'account_meta.account_id')
313
                             ->where('accounts.user_id', $this->job->user_id)
314
                             ->whereIn('account_meta.name', ['accountNumber', 'BIC', 'currency_id'])
315
                             ->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data']);
316
        /** @var AccountMeta $meta */
317
        foreach ($set as $meta) {
318
            $id                       = (int)$meta->account_id;
319
            $return[$id][$meta->name] = $meta->data;
320
        }
321
322
        return $return;
323
    }
324
325
    /**
326
     * Returns, if present, for the given journal ID's the notes.
327
     *
328
     * @param array $array
329
     *
330
     * @return array
331
     */
332
    private function getNotes(array $array): array
333
    {
334
        $array  = array_unique($array);
335
        $notes  = Note::where('notes.noteable_type', TransactionJournal::class)
336
                      ->whereIn('notes.noteable_id', $array)
337
                      ->get(['notes.*']);
338
        $return = [];
339
        /** @var Note $note */
340
        foreach ($notes as $note) {
341
            if ('' !== trim((string)$note->text)) {
342
                $id          = (int)$note->noteable_id;
343
                $return[$id] = $note->text;
344
            }
345
        }
346
347
        return $return;
348
    }
349
350
    /**
351
     * Returns a comma joined list of all the users tags linked to these journals.
352
     *
353
     * @param array $array
354
     *
355
     * @return array
356
     * @throws \Illuminate\Contracts\Encryption\DecryptException
357
     */
358
    private function getTags(array $array): array
359
    {
360
        $set    = DB::table('tag_transaction_journal')
361
                    ->whereIn('tag_transaction_journal.transaction_journal_id', $array)
362
                    ->leftJoin('tags', 'tag_transaction_journal.tag_id', '=', 'tags.id')
363
                    ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'tag_transaction_journal.transaction_journal_id')
364
                    ->where('transaction_journals.user_id', $this->job->user_id)
365
                    ->get(['tag_transaction_journal.transaction_journal_id', 'tags.tag']);
366
        $result = [];
367
        foreach ($set as $entry) {
368
            $id            = (int)$entry->transaction_journal_id;
369
            $result[$id]   = $result[$id] ?? [];
370
            $result[$id][] = $entry->tag;
371
        }
372
373
        return $result;
374
    }
375
}
376