Passed
Push — master ( 0b1a33...6372a5 )
by Marcel
06:49
created

ReportService::update()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 5
c 1
b 0
f 0
nc 4
nop 14
dl 0
loc 9
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * Analytics
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the LICENSE.md file.
7
 *
8
 * @author Marcel Scherello <[email protected]>
9
 * @copyright 2021 Marcel Scherello
10
 */
11
12
namespace OCA\Analytics\Service;
13
14
use OCA\Analytics\Activity\ActivityManager;
15
use OCA\Analytics\Controller\DatasourceController;
16
use OCA\Analytics\Db\DataloadMapper;
17
use OCA\Analytics\Db\ReportMapper;
18
use OCA\Analytics\Db\StorageMapper;
19
use OCP\AppFramework\Http\DataDownloadResponse;
20
use OCP\AppFramework\Http\DataResponse;
21
use OCP\Files\IRootFolder;
22
use OCP\ITagManager;
23
use Psr\Log\LoggerInterface;
24
25
class ReportService
26
{
27
    private $userId;
28
    private $logger;
29
    private $tagManager;
30
    private $ShareService;
31
    private $DatasetService;
32
    private $StorageMapper;
33
    private $ReportMapper;
34
    private $ThresholdService;
35
    private $DataloadMapper;
36
    private $ActivityManager;
37
    private $rootFolder;
38
    private $VariableService;
39
40
    public function __construct(
41
        $userId,
42
        LoggerInterface $logger,
43
        ITagManager $tagManager,
44
        ShareService $ShareService,
45
        DatasetService $DatasetService,
46
        StorageMapper $StorageMapper,
47
        ReportMapper $ReportMapper,
48
        ThresholdService $ThresholdService,
49
        DataloadMapper $DataloadMapper,
50
        ActivityManager $ActivityManager,
51
        IRootFolder $rootFolder,
52
        VariableService $VariableService
53
    )
54
    {
55
        $this->userId = $userId;
56
        $this->logger = $logger;
57
        $this->tagManager = $tagManager;
58
        $this->ShareService = $ShareService;
59
        $this->DatasetService = $DatasetService;
60
        $this->ThresholdService = $ThresholdService;
61
        $this->StorageMapper = $StorageMapper;
62
        $this->ReportMapper = $ReportMapper;
63
        $this->DataloadMapper = $DataloadMapper;
64
        $this->ActivityManager = $ActivityManager;
65
        $this->rootFolder = $rootFolder;
66
        $this->VariableService = $VariableService;
67
    }
68
69
    /**
70
     * get all reports
71
     *
72
     * @return DataResponse
73
     */
74
    public function index()
75
    {
76
        $ownReports = $this->ReportMapper->index();
77
78
        // get dataload indicators for icons shown in the advanced screen
79
        $dataloads = $this->DataloadMapper->getAllDataloadMetadata();
80
        foreach ($dataloads as $dataload) {
81
            $key = array_search($dataload['dataset'], array_column($ownReports, 'dataset'));
82
            if ($key !== '') {
83
                if ($dataload['schedules'] !== '' and $dataload['schedules'] !== null) {
84
                    $dataload['schedules'] = 1;
85
                } else {
86
                    $dataload['schedules'] = 0;
87
                }
88
                $ownReports[$key]['dataloads'] = $dataload['dataloads'];
89
                $ownReports[$key]['schedules'] = $dataload['schedules'];
90
            }
91
        }
92
93
        // get shared reports and remove doublicates
94
        $sharedReports = $this->ShareService->getSharedReports();
95
        foreach ($sharedReports as $sharedReport) {
96
            if (!array_search($sharedReport['id'], array_column($ownReports, 'id'))) {
97
                $sharedReport['type'] = '99';
98
                $sharedReport['parrent'] = '0';
99
                array_push($ownReports, $sharedReport);
100
            }
101
        }
102
103
        $favorites = $this->tagManager->load('analytics')->getFavorites();
104
        foreach ($ownReports as &$ownReport) {
105
            $hasTag = 0;
106
            if (is_array($favorites) and in_array($ownReport['id'], $favorites)) {
107
                $hasTag = 1;
108
            }
109
            $ownReport['favorite'] = $hasTag;
110
            $ownReport = $this->VariableService->replaceTextVariables($ownReport);
111
        }
112
113
        return new DataResponse($ownReports);
114
    }
115
116
    /**
117
     * get own report details
118
     *
119
     * @param int $reportId
120
     * @return array
121
     */
122
    public function read(int $reportId)
123
    {
124
        $ownReport = $this->ReportMapper->read($reportId);
125
        if (!empty($ownReport)) {
126
            $ownReport['permissions'] = \OCP\Constants::PERMISSION_UPDATE;
127
            $ownReport = $this->VariableService->replaceTextVariables($ownReport);
128
        }
129
        return $ownReport;
130
    }
131
132
    /**
133
     * get own reports which are marked as favorites
134
     *
135
     * @return array|bool
136
     */
137
    public function getOwnFavoriteReports()
138
    {
139
        $ownReports = $this->ReportMapper->index();
140
        $favorits = $this->tagManager->load('analytics')->getFavorites();
141
        $sharedReports = $this->ShareService->getSharedReports();
142
143
        foreach ($favorits as $favorite) {
144
            if (array_search($favorite, array_column($ownReports, 'id')) === false
145
                && array_search($favorite, array_column($sharedReports, 'id')) === false) {
146
                unset($favorits[$favorite]);
147
                $this->tagManager->load('analytics')->removeFromFavorites($favorite);
148
            }
149
        }
150
151
        return $favorits;
152
    }
153
154
    /**
155
     * create new blank report
156
     *
157
     * @return int
158
     */
159
    public function create(): int
160
    {
161
        $this->ActivityManager->triggerEvent(0, ActivityManager::OBJECT_DATASET, ActivityManager::SUBJECT_DATASET_ADD);
162
        return $this->ReportMapper->create();
163
    }
164
165
    /**
166
     * copy an existing report with the current navigation status
167
     *
168
     * @NoAdminRequired
169
     * @param int $reportId
170
     * @param $chartoptions
171
     * @param $dataoptions
172
     * @param $filteroptions
173
     * @return int
174
     */
175
    public function createCopy(int $reportId, $chartoptions, $dataoptions, $filteroptions)
176
    {
177
178
        $newId = $this->ReportMapper->create();
179
        $template = $this->ReportMapper->read($reportId);
180
        $this->ReportMapper->update($newId,
181
            $template['name'] . ' copy',
182
            $template['subheader'],
183
            $template['parent'],
184
            $template['type'],
185
            $template['dataset'],
186
            $template['link'],
187
            $template['visualization'],
188
            $template['chart'],
189
            $template['chartoptions'],
190
            $template['dataoptions'],
191
            $template['dimension1'],
192
            $template['dimension2'],
193
            $template['value']);
194
        $this->ReportMapper->updateOptions($newId, $chartoptions, $dataoptions, $filteroptions);
195
        return $newId;
196
    }
197
198
    /**
199
     * create new report
200
     *
201
     * @param string $file
202
     * @return int
203
     */
204
    public function createFromFile($file = '')
205
    {
206
        $this->ActivityManager->triggerEvent(0, ActivityManager::OBJECT_DATASET, ActivityManager::SUBJECT_DATASET_ADD);
207
        $reportId = $this->ReportMapper->create();
208
209
        if ($file !== '') {
210
            $name = explode('.', end(explode('/', $file)))[0];
211
            $subheader = $file;
212
            $parent = 0;
213
            $type = DatasourceController::DATASET_TYPE_FILE;
214
            $link = $file;
215
            $visualization = 'table';
216
            $chart = 'line';
217
            $this->update($reportId, $name, $subheader, $parent, $type, $link, $visualization, $chart, '', '');
0 ignored issues
show
Bug introduced by
$link of type string is incompatible with the type integer expected by parameter $dataset of OCA\Analytics\Service\ReportService::update(). ( Ignorable by Annotation )

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

217
            $this->update($reportId, $name, $subheader, $parent, $type, /** @scrutinizer ignore-type */ $link, $visualization, $chart, '', '');
Loading history...
Bug introduced by
The call to OCA\Analytics\Service\ReportService::update() has too few arguments starting with dataoptions. ( Ignorable by Annotation )

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

217
            $this->/** @scrutinizer ignore-call */ 
218
                   update($reportId, $name, $subheader, $parent, $type, $link, $visualization, $chart, '', '');

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
218
        }
219
        return $reportId;
220
    }
221
222
    /**
223
     * update report details
224
     *
225
     * @param int $reportId
226
     * @param $name
227
     * @param $subheader
228
     * @param int $parent
229
     * @param int $type
230
     * @param int $dataset
231
     * @param $link
232
     * @param $visualization
233
     * @param $chart
234
     * @param $chartoptions
235
     * @param $dataoptions
236
     * @param null $dimension1
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $dimension1 is correct as it would always require null to be passed?
Loading history...
237
     * @param null $dimension2
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $dimension2 is correct as it would always require null to be passed?
Loading history...
238
     * @param null $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
239
     * @return bool
240
     * @throws \OCP\DB\Exception
241
     */
242
    public function update(int $reportId, $name, $subheader, int $parent, int $type, int $dataset, $link, $visualization, $chart, $chartoptions, $dataoptions, $dimension1 = null, $dimension2 = null, $value = null)
243
    {
244
        if ($type === DatasourceController::DATASET_TYPE_GROUP) {
245
            $parent = 0;
246
        }
247
        if ($type === DatasourceController::DATASET_TYPE_INTERNAL_DB && $dataset === 0) { // New dataset
248
            $dataset = $this->DatasetService->create($name, $dimension1, $dimension2, $value);
249
        }
250
        return $this->ReportMapper->update($reportId, $name, $subheader, $parent, $type, $dataset, $link, $visualization, $chart, $chartoptions, $dataoptions, $dimension1, $dimension2, $value);
251
    }
252
253
    /**
254
     * set/remove the favorite flag for a report
255
     *
256
     * @param int $reportId
257
     * @param string $favorite
258
     * @return bool
259
     */
260
    public function setFavorite(int $reportId, string $favorite)
261
    {
262
        if ($favorite === 'true') {
263
            $return = $this->tagManager->load('analytics')->addToFavorites($reportId);
264
        } else {
265
            $return = $this->tagManager->load('analytics')->removeFromFavorites($reportId);
266
        }
267
        return $return;
268
    }
269
270
    /**
271
     * Import Report from File
272
     *
273
     * @param string|null $path
274
     * @param string|null $raw
275
     * @return int
276
     * @throws \OCP\Files\NotFoundException
277
     * @throws \OCP\Files\NotPermittedException
278
     */
279
    public function import(string $path = null, string $raw = null)
280
    {
281
        if ($path !== '') {
282
            $file = $this->rootFolder->getUserFolder($this->userId)->get($path);
283
            $data = $file->getContent();
0 ignored issues
show
Bug introduced by
The method getContent() does not exist on OCP\Files\Node. It seems like you code against a sub-type of OCP\Files\Node such as OCP\Files\File. ( Ignorable by Annotation )

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

283
            /** @scrutinizer ignore-call */ 
284
            $data = $file->getContent();
Loading history...
284
        } else if ($raw !== null) {
285
            $data = $raw;
286
        } else {
287
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
288
        }
289
        $data = json_decode($data, true);
290
291
        $dataset = $data['dataset'];
292
        isset($dataset['name']) ? $name = $dataset['name'] : $name = '';
293
        isset($dataset['subheader']) ? $subheader = $dataset['subheader'] : $subheader = '';
294
        $parent = 0;
295
        isset($dataset['type']) ? $type = $dataset['type'] : $type = null;
296
        isset($dataset['link']) ? $link = $dataset['link'] : $link = null;
297
        isset($dataset['visualization']) ? $visualization = $dataset['visualization'] : $visualization = null;
298
        isset($dataset['chart']) ? $chart = $dataset['chart'] : $chart = null;
299
        isset($dataset['chartoptions']) ? $chartoptions = $dataset['chartoptions'] : $chartoptions = null;
300
        isset($dataset['dataoptions']) ? $dataoptions = $dataset['dataoptions'] : $dataoptions = null;
301
        isset($dataset['filteroptions']) ? $filteroptions = $dataset['filteroptions'] : $filteroptions = null;
302
        isset($dataset['dimension1']) ? $dimension1 = $dataset['dimension1'] : $dimension1 = null;
303
        isset($dataset['dimension2']) ? $dimension2 = $dataset['dimension2'] : $dimension2 = null;
304
        isset($dataset['value']) ? $value = $dataset['value'] : $value = null;
305
306
        $reportId = $this->ReportMapper->create();
307
        $this->ReportMapper->update($reportId, $name, $subheader, $parent, $type, $link, $visualization, $chart, $chartoptions, $dataoptions, $dimension1, $dimension2, $value, $filteroptions);
308
309
        foreach ($data['dataload'] as $dataload) {
310
            isset($dataload['datasource']) ? $datasource = $dataload['datasource'] : $datasource = null;
311
            isset($dataload['name']) ? $name = $dataload['name'] : $name = null;
312
            isset($dataload['option']) ? $option = $dataload['option'] : $option = null;
313
            $schedule = null;
314
315
            /**todo**/
316
            $dataloadId = $this->DataloadMapper->create($reportId, $datasource);
317
            $this->DataloadMapper->update($dataloadId, $name, $option, $schedule);
318
        }
319
320
        foreach ($data['threshold'] as $threshold) {
321
            isset($threshold['dimension1']) ? $dimension1 = $threshold['dimension1'] : $dimension1 = null;
322
            isset($threshold['value']) ? $value = $threshold['value'] : $value = null;
323
            isset($threshold['option']) ? $option = $threshold['option'] : $option = null;
324
            isset($threshold['severity']) ? $severity = $threshold['severity'] : $severity = null;
325
            $this->ThresholdService->create($reportId, $dimension1, $option, $value, $severity);
326
        }
327
328
        foreach ($data['data'] as $dData) {
329
            isset($dData[0]) ? $dimension1 = $dData[0] : $dimension1 = null;
330
            isset($dData[1]) ? $dimension2 = $dData[1] : $dimension2 = null;
331
            isset($dData[2]) ? $value = $dData[2] : $value = null;
332
            $this->StorageMapper->create($reportId, $dimension1, $dimension2, $value);
333
        }
334
335
        if (isset($data['favorite'])) {
336
            $this->setFavorite($reportId, $data['favorite']);
337
        }
338
339
        return $reportId;
340
    }
341
342
    /**
343
     * Export Report
344
     *
345
     * @param int $reportId
346
     * @return DataDownloadResponse
347
     */
348
    public function export(int $reportId)
349
    {
350
        /**todo**/
351
        $result = array();
352
        $result['dataset'] = $this->ReportMapper->read($reportId);
353
        $result['dataload'] = $this->DataloadMapper->read($datasetId);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $datasetId seems to be never defined.
Loading history...
354
        $result['threshold'] = $this->ThresholdService->read($reportId);
355
        $result['favorite'] = '';
356
357
        if ($result['dataset']['type'] === DatasourceController::DATASET_TYPE_INTERNAL_DB) {
358
            $result['data'] = $this->StorageMapper->read($datasetId);
359
        }
360
361
        unset($result['dataset']['id'], $result['dataset']['user_id'], $result['dataset']['user_id'], $result['dataset']['parent']);
362
        $data = json_encode($result);
363
        return new DataDownloadResponse($data, $result['dataset']['name'] . '.export.txt', 'text/plain; charset=utf-8');
364
    }
365
366
    /**
367
     * Delete Dataset and all depending objects
368
     *
369
     * @param int $reportId
370
     * @return bool
371
     */
372
    public function delete(int $reportId): bool
373
    {
374
        $this->ShareService->deleteShareByReport($reportId);
375
        $this->StorageMapper->deleteByDataset($reportId);
376
        /**todo**/
377
        // delete dataset when last report
378
        $this->ReportMapper->delete($reportId);
379
        $this->ThresholdService->deleteThresholdByReport($reportId);
380
        $this->DataloadMapper->deleteDataloadByDataset($reportId);
381
        $this->ActivityManager->triggerEvent(0, ActivityManager::OBJECT_DATASET, ActivityManager::SUBJECT_DATASET_DELETE);
382
        $this->setFavorite($reportId, 'false');
383
        return true;
384
    }
385
386
    /**
387
     * Update report options
388
     *
389
     * @param int $reportId
390
     * @param $chartoptions
391
     * @param $dataoptions
392
     * @param $filteroptions
393
     * @return bool
394
     */
395
    public function updateOptions(int $reportId, $chartoptions, $dataoptions, $filteroptions)
396
    {
397
        return $this->ReportMapper->updateOptions($reportId, $chartoptions, $dataoptions, $filteroptions);
398
    }
399
400
    /**
401
     * get report refresh options
402
     *
403
     * @NoAdminRequired
404
     * @param int $reportId
405
     * @param $refresh
406
     * @return bool
407
     */
408
    public function updateRefresh(int $reportId, $refresh)
409
    {
410
        return $this->ReportMapper->updateRefresh($reportId, $refresh);
411
    }
412
413
    /**
414
     * search for reports
415
     *
416
     * @param string $searchString
417
     * @return array
418
     */
419
    public function search(string $searchString)
420
    {
421
        return $this->ReportMapper->search($searchString);
422
    }
423
424
}