ReportService   F
last analyzed

Complexity

Total Complexity 86

Size/Duplication

Total Lines 519
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 216
dl 0
loc 519
rs 2
c 1
b 0
f 0
wmc 86

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 30 1
A floatvalue() 0 14 4
A createFromDataFile() 0 15 2
A reportsForDataset() 0 2 1
B index() 0 41 11
B create() 0 35 8
A search() 0 2 1
A updateOptions() 0 2 1
A getOwnFavoriteReports() 0 14 4
A setFavorite() 0 7 2
A read() 0 15 5
A deleteByUser() 0 9 2
A export() 0 15 2
A updateGroup() 0 2 1
A updateRefresh() 0 2 1
A isOwn() 0 6 2
A createCopy() 0 7 1
A delete() 0 13 3
F import() 0 71 32
A update() 0 21 2

How to fix   Complexity   

Complex Class

Complex classes like ReportService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ReportService, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Analytics
4
 *
5
 * SPDX-FileCopyrightText: 2019-2022 Marcel Scherello
6
 * SPDX-License-Identifier: AGPL-3.0-or-later
7
 */
8
9
namespace OCA\Analytics\Service;
10
11
use OCA\Analytics\Activity\ActivityManager;
12
use OCA\Analytics\Controller\DatasourceController;
13
use OCA\Analytics\Db\DataloadMapper;
14
use OCA\Analytics\Db\ReportMapper;
15
use OCA\Analytics\Db\StorageMapper;
16
use OCA\Analytics\Db\ThresholdMapper;
17
use OCP\AppFramework\Http\DataDownloadResponse;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Http\DataDownloadResponse was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use OCP\DB\Exception;
0 ignored issues
show
Bug introduced by
The type OCP\DB\Exception was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use OCP\Files\IRootFolder;
0 ignored issues
show
Bug introduced by
The type OCP\Files\IRootFolder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use OCP\ITagManager;
0 ignored issues
show
Bug introduced by
The type OCP\ITagManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
use OCP\IConfig;
0 ignored issues
show
Bug introduced by
The type OCP\IConfig was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
use OCP\PreConditionNotMetException;
0 ignored issues
show
Bug introduced by
The type OCP\PreConditionNotMetException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use Psr\Log\LoggerInterface;
0 ignored issues
show
Bug introduced by
The type Psr\Log\LoggerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use OCP\IL10N;
0 ignored issues
show
Bug introduced by
The type OCP\IL10N was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
26
class ReportService {
27
	/** @var IConfig */
28
	protected $config;
29
	private $userId;
30
	private $logger;
31
	private $tagManager;
32
	private $ShareService;
33
	private $DatasetService;
34
	private $StorageMapper;
35
	private $ReportMapper;
36
	private $ThresholdMapper;
37
	private $DataloadMapper;
38
	private $ActivityManager;
39
	private $rootFolder;
40
	private $VariableService;
41
	private $l10n;
42
43
	const REPORT_TYPE_GROUP = 0;
44
45
	public function __construct(
46
		$userId,
47
		IL10N $l10n,
48
		LoggerInterface $logger,
49
		ITagManager $tagManager,
50
		ShareService $ShareService,
51
		DatasetService $DatasetService,
52
		StorageMapper $StorageMapper,
53
		ReportMapper $ReportMapper,
54
		ThresholdMapper $ThresholdMapper,
55
		DataloadMapper $DataloadMapper,
56
		ActivityManager $ActivityManager,
57
		IRootFolder $rootFolder,
58
		IConfig $config,
59
		VariableService $VariableService
60
	) {
61
		$this->userId = $userId;
62
		$this->logger = $logger;
63
		$this->tagManager = $tagManager;
64
		$this->ShareService = $ShareService;
65
		$this->DatasetService = $DatasetService;
66
		$this->ThresholdMapper = $ThresholdMapper;
67
		$this->StorageMapper = $StorageMapper;
68
		$this->ReportMapper = $ReportMapper;
69
		$this->DataloadMapper = $DataloadMapper;
70
		$this->ActivityManager = $ActivityManager;
71
		$this->rootFolder = $rootFolder;
72
		$this->VariableService = $VariableService;
73
		$this->config = $config;
74
		$this->l10n = $l10n;
75
	}
76
77
	/**
78
	 * get all reports
79
	 *
80
	 * @return array
81
	 * @throws PreConditionNotMetException
82
	 */
83
	public function index(): array {
84
		$ownReports = $this->ReportMapper->index();
85
		$sharedReports = $this->ShareService->getSharedItems(ShareService::SHARE_ITEM_TYPE_REPORT);
86
		$keysToKeep = array('id', 'name', 'dataset', 'favorite', 'parent', 'type', 'isShare', 'shareId');
87
88
		// get shared reports and remove duplicates
89
		foreach ($sharedReports as $sharedReport) {
90
			if (!array_search($sharedReport['id'], array_column($ownReports, 'id'))) {
91
				// just keep the necessary fields
92
				$ownReports[] = array_intersect_key($sharedReport, array_flip($keysToKeep));;
93
			}
94
		}
95
		if (count($ownReports) === 0) return $ownReports;
96
97
		// get data load indicators for icons shown in the advanced screen
98
		$dataloads = $this->DataloadMapper->getAllDataloadMetadata();
99
		foreach ($dataloads as $dataload) {
100
			$key = array_search($dataload['dataset'], array_column($ownReports, 'dataset'));
101
			if ($key !== '') {
102
				if ($dataload['schedules'] !== '' and $dataload['schedules'] !== null) {
103
					$dataload['schedules'] = 1;
104
				} else {
105
					$dataload['schedules'] = 0;
106
				}
107
				$ownReports[$key]['dataloads'] = $dataload['dataloads'];
108
				$ownReports[$key]['schedules'] = $dataload['schedules'];
109
			}
110
		}
111
112
		$favorites = $this->tagManager->load('analytics')->getFavorites();
113
		foreach ($ownReports as &$ownReport) {
114
			$hasTag = 0;
115
			if (is_array($favorites) and in_array($ownReport['id'], $favorites)) {
116
				$hasTag = 1;
117
			}
118
			$ownReport['favorite'] = $hasTag;
119
			$ownReport['item_type'] = ShareService::SHARE_ITEM_TYPE_REPORT;
120
			$ownReport = $this->VariableService->replaceTextVariables($ownReport);
121
		}
122
123
		return $ownReports;
124
	}
125
126
	/**
127
	 * get own report details
128
	 *
129
	 * @param int $reportId
130
	 * @return array
131
	 * @throws Exception
132
	 */
133
	public function read(int $reportId, $replace = true) {
134
		$ownReport = $this->ReportMapper->readOwn($reportId);
135
		if (!empty($ownReport)) {
136
			$ownReport['permissions'] = \OCP\Constants::PERMISSION_UPDATE;
0 ignored issues
show
Bug introduced by
The type OCP\Constants was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
137
			if ($replace) $ownReport = $this->VariableService->replaceTextVariables($ownReport);
138
139
			if ($ownReport['type'] === DatasourceController::DATASET_TYPE_INTERNAL_DB && $ownReport['dataset'] !== 0) {
140
				$dataset = $this->DatasetService->readOwn($ownReport['dataset']);
141
				$ownReport['dimension1'] = $dataset['dimension1'];
142
				$ownReport['dimension2'] = $dataset['dimension2'];
143
				$ownReport['value'] = $dataset['value'];
144
			}
145
146
		}
147
		return $ownReport;
148
	}
149
150
	/**
151
	 * check if own report
152
	 *
153
	 * @param int $reportId
154
	 * @return bool
155
	 */
156
	public function isOwn(int $reportId) {
157
		$ownReport = $this->ReportMapper->readOwn($reportId);
158
		if (!empty($ownReport)) {
159
			return true;
160
		} else {
161
			return false;
162
		}
163
	}
164
165
	/**
166
	 * create new blank report
167
	 *
168
	 * @return int
169
	 * @throws Exception
170
	 */
171
	public function create(
172
		$name,
173
		$subheader,
174
		$parent,
175
		$type,
176
		int $dataset,
177
		$link,
178
		$visualization,
179
		$chart,
180
		$dimension1,
181
		$dimension2,
182
		$value,
183
		$addReport = null
184
	): int {
185
		$array = json_decode($link, true);
186
		if (is_array($array)) {
187
			foreach ($array as $key => $value) {
0 ignored issues
show
introduced by
$value is overwriting one of the parameters of this function.
Loading history...
188
				$array[$key] = htmlspecialchars($value, ENT_NOQUOTES, 'UTF-8');
189
			}
190
		}
191
		$link = json_encode($array);
192
193
		if ($type === DatasourceController::DATASET_TYPE_GROUP) {
194
			$parent = 0;
195
		}
196
		if ($type === DatasourceController::DATASET_TYPE_INTERNAL_DB && $dataset === 0) { // New dataset
197
			$dataset = $this->DatasetService->create($name, $dimension1, $dimension2, $value);
198
		}
199
		$reportId = $this->ReportMapper->create($name, $subheader, $parent, $type, $dataset, $link, $visualization, $chart, $dimension1, $dimension2, $value);
200
		$this->ActivityManager->triggerEvent($reportId, ActivityManager::OBJECT_REPORT, ActivityManager::SUBJECT_REPORT_ADD);
201
202
		if ($addReport !== null && $addReport !== '') {
203
			$this->updateGroup($addReport, $reportId);
204
		}
205
		return $reportId;
206
	}
207
208
	/**
209
	 * copy an existing report with the current navigation status
210
	 *
211
	 * @NoAdminRequired
212
	 * @param int $reportId
213
	 * @param $chartoptions
214
	 * @param $dataoptions
215
	 * @param $filteroptions
216
	 * @return int
217
	 * @throws Exception
218
	 */
219
	public function createCopy(int $reportId, $chartoptions, $dataoptions, $filteroptions, $tableoptions) {
220
221
		$template = $this->ReportMapper->readOwn($reportId);
222
		$newId = $this->ReportMapper->create(// TRANSLATORS Noun
223
			$template['name'] . ' - ' . $this->l10n->t('copy'), $template['subheader'], $template['parent'], $template['type'], $template['dataset'], $template['link'], $template['visualization'], $template['chart'], $template['dimension1'], $template['dimension2'], $template['value']);
224
		$this->ReportMapper->updateOptions($newId, $chartoptions, $dataoptions, $filteroptions, $tableoptions);
225
		return $newId;
226
	}
227
228
	/**
229
	 * create new report
230
	 *
231
	 * @param string $file
232
	 * @return int
233
	 */
234
	public function createFromDataFile($file = '') {
235
		$this->ActivityManager->triggerEvent(0, ActivityManager::OBJECT_REPORT, ActivityManager::SUBJECT_REPORT_ADD);
236
237
		if ($file !== '') {
238
			$name = explode('.', end(explode('/', $file)))[0];
239
			$subheader = $file;
240
			$parent = 0;
241
			$dataset = 0;
242
			$type = DatasourceController::DATASET_TYPE_FILE;
243
			$link = $file;
244
			$visualization = 'table';
245
			$chart = 'line';
246
			$reportId = $this->ReportMapper->create($name, $subheader, $parent, $type, $dataset, $link, $visualization, $chart, '', '', '');
247
		}
248
		return $reportId;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $reportId does not seem to be defined for all execution paths leading up to this point.
Loading history...
249
	}
250
251
	/**
252
	 * update report details
253
	 *
254
	 * @param int $reportId
255
	 * @param $name
256
	 * @param $subheader
257
	 * @param int $parent
258
	 * @param $options
259
	 * @param $visualization
260
	 * @param $chart
261
	 * @param $chartoptions
262
	 * @param $dataoptions
263
	 * @param $dimension1
264
	 * @param $dimension2
265
	 * @param $value
266
	 * @return bool
267
	 */
268
	public function update(
269
		int $reportId,
270
			$name,
271
			$subheader,
272
		int $parent,
273
			$options,
274
			$visualization,
275
			$chart,
276
			$chartoptions,
277
			$dataoptions,
278
			$dimension1 = null,
279
			$dimension2 = null,
280
			$value = null
281
	) {
282
		$array = json_decode($options, true);
283
		foreach ($array as $key => $value) {
284
			$array[$key] = htmlspecialchars($value, ENT_NOQUOTES, 'UTF-8');
285
		}
286
		$options = json_encode($array);
287
288
		return $this->ReportMapper->update($reportId, $name, $subheader, $parent, $options, $visualization, $chart, $chartoptions, $dataoptions, $dimension1, $dimension2, $value);
289
	}
290
291
	/**
292
	 * Delete Dataset and all depending objects
293
	 *
294
	 * @param int $reportId
295
	 * @return string
296
	 * @throws Exception
297
	 */
298
	public function delete(int $reportId) {
299
		$metadata = $this->ReportMapper->readOwn($reportId);
300
		$this->ActivityManager->triggerEvent($reportId, ActivityManager::OBJECT_REPORT, ActivityManager::SUBJECT_REPORT_DELETE);
301
		$this->ShareService->deleteSharesByItem(ShareService::SHARE_ITEM_TYPE_REPORT, $reportId);
302
		$this->ThresholdMapper->deleteThresholdByReport($reportId);
303
		$this->setFavorite($reportId, 'false');
304
		$this->ReportMapper->delete($reportId);
305
306
		$report = $this->reportsForDataset((int)$metadata['dataset']);
307
		if (empty($report) && (int)$metadata['type'] === DatasourceController::DATASET_TYPE_INTERNAL_DB) {
308
			return $metadata['dataset'];
309
		} else {
310
			return 'true';
311
		}
312
	}
313
314
	/**
315
	 * get dataset by user
316
	 *
317
	 * @param string $userId
318
	 * @return array|bool
319
	 * @throws Exception
320
	 */
321
	public function deleteByUser(string $userId) {
322
		$reports = $this->ReportMapper->indexByUser($userId);
323
		foreach ($reports as $report) {
324
			$this->ShareService->deleteSharesByItem(ShareService::SHARE_ITEM_TYPE_REPORT, $report['id']);
325
			$this->ThresholdMapper->deleteThresholdByReport($report['id']);
326
			$this->setFavorite($report['id'], 'false');
327
			$this->ReportMapper->delete($report['id']);
328
		}
329
		return true;
330
	}
331
332
	/**
333
	 * get own reports which are marked as favorites
334
	 *
335
	 * @return array|bool
336
	 * @throws Exception
337
	 */
338
	public function getOwnFavoriteReports() {
339
		$ownReports = $this->ReportMapper->index();
340
		$sharedReports = $this->ShareService->getSharedItems(ShareService::SHARE_ITEM_TYPE_REPORT);
341
		$favorites = $this->tagManager->load('analytics')->getFavorites();
342
343
		// remove the favorite if the report is not existing anymore
344
		foreach ($favorites as $favorite) {
345
			if (!in_array($favorite, array_column($ownReports, 'id')) && !in_array($favorite, array_column($sharedReports, 'id'))) {
346
				unset($favorites[$favorite]);
347
				$this->tagManager->load('analytics')->removeFromFavorites($favorite);
348
			}
349
		}
350
351
		return $favorites;
352
	}
353
354
	/**
355
	 * set/remove the favorite flag for a report
356
	 *
357
	 * @param int $reportId
358
	 * @param string $favorite
359
	 * @return bool
360
	 */
361
	public function setFavorite(int $reportId, string $favorite) {
362
		if ($favorite === 'true') {
363
			$return = $this->tagManager->load('analytics')->addToFavorites($reportId);
364
		} else {
365
			$return = $this->tagManager->load('analytics')->removeFromFavorites($reportId);
366
		}
367
		return $return;
368
	}
369
370
	/**
371
	 * Import Report from File
372
	 *
373
	 * @param string|null $path
374
	 * @param string|null $raw
375
	 * @return int
376
	 * @throws \OCP\Files\NotFoundException
377
	 * @throws \OCP\Files\NotPermittedException
378
	 */
379
	public function import(string $path = null, string $raw = null) {
380
		if ($path !== '' and $path !== null) {
381
			$file = $this->rootFolder->getUserFolder($this->userId)->get($path);
382
			$data = $file->getContent();
383
		} else if ($raw !== null) {
384
			$data = $raw;
385
		} else {
386
			return 0;
387
		}
388
		$data = json_decode($data, true);
389
390
		$report = $data['report'];
391
		isset($report['name']) ? $name = $report['name'] : $name = '';
392
		isset($report['subheader']) ? $subheader = $report['subheader'] : $subheader = '';
393
		$parent = 0;
394
		$dataset = 0;
395
		isset($report['type']) ? $type = (int)$report['type'] : $type = null;
396
		isset($report['link']) ? $link = $report['link'] : $link = null;
397
		isset($report['visualization']) ? $visualization = $report['visualization'] : $visualization = null;
398
		isset($report['chart']) ? $chart = $report['chart'] : $chart = null;
399
		isset($report['chartoptions']) ? $chartoptions = $report['chartoptions'] : $chartoptions = null;
400
		isset($report['dataoptions']) ? $dataoptions = $report['dataoptions'] : $dataoptions = null;
401
		isset($report['filteroptions']) ? $filteroptions = $report['filteroptions'] : $filteroptions = null;
402
		isset($report['tableoptions']) ? $tableoptions = $report['tableoptions'] : $tableoptions = null;
403
		isset($report['dimension1']) ? $dimension1 = $report['dimension1'] : $dimension1 = null;
404
		isset($report['dimension2']) ? $dimension2 = $report['dimension2'] : $dimension2 = null;
405
		isset($report['value']) ? $value = $report['value'] : $value = null;
406
407
		if ($type === DatasourceController::DATASET_TYPE_INTERNAL_DB) { // New dataset
408
			$dataset = $this->DatasetService->create($name, $dimension1, $dimension2, $value);
409
		}
410
		$reportId = $this->create($name, $subheader, $parent, $type, $dataset, $link, $visualization, $chart, $dimension1, $dimension2, $value);
411
		$this->updateOptions($reportId, $chartoptions, $dataoptions, $filteroptions, $tableoptions);
412
		$report = $this->ReportMapper->readOwn($reportId);
413
		$datasetId = $report['dataset'];
414
415
		$this->DataloadMapper->beginTransaction();
416
417
		foreach ($data['dataload'] as $dataload) {
418
			isset($dataload['datasource']) ? $datasource = $dataload['datasource'] : $datasource = null;
419
			isset($dataload['name']) ? $name = $dataload['name'] : $name = null;
420
			isset($dataload['option']) ? $option = $dataload['option'] : $option = null;
421
			$schedule = null;
422
423
			$dataloadId = $this->DataloadMapper->create($datasetId, $datasource);
424
			$this->DataloadMapper->update($dataloadId, $name, $option, $schedule);
425
		}
426
427
		foreach ($data['threshold'] as $threshold) {
428
			isset($threshold['dimension1']) ? $dimension1 = $threshold['dimension1'] : $dimension1 = null;
429
			isset($threshold['value']) ? $value = $threshold['value'] : $value = null;
430
			isset($threshold['option']) ? $option = $threshold['option'] : $option = null;
431
			isset($threshold['severity']) ? $severity = $threshold['severity'] : $severity = null;
432
			$value = $this->floatvalue($value);
433
			$this->ThresholdMapper->create($reportId, $dimension1, $value, $option, $severity);
434
		}
435
436
		foreach ($data['data'] as $dData) {
437
			isset($dData[0]) ? $dimension1 = $dData[0] : $dimension1 = null;
438
			isset($dData[1]) ? $dimension2 = $dData[1] : $dimension2 = null;
439
			isset($dData[2]) ? $value = $dData[2] : $value = null;
440
			$this->StorageMapper->create($datasetId, $dimension1, $dimension2, $value);
441
		}
442
443
		$this->DataloadMapper->commit();
444
445
		if (isset($data['favorite'])) {
446
			$this->setFavorite($reportId, $data['favorite']);
447
		}
448
449
		return $reportId;
450
	}
451
452
	/**
453
	 * Export Report
454
	 *
455
	 * @param int $reportId
456
	 * @return DataDownloadResponse
457
	 */
458
	public function export(int $reportId) {
459
		$result = array();
460
		$result['report'] = $this->ReportMapper->readOwn($reportId);
461
		$datasetId = $result['report']['dataset'];
462
		$result['dataload'] = $this->DataloadMapper->read($datasetId);
463
		$result['threshold'] = $this->ThresholdMapper->getThresholdsByReport($reportId);
464
		$result['favorite'] = '';
465
466
		if ($result['report']['type'] === DatasourceController::DATASET_TYPE_INTERNAL_DB) {
467
			$result['data'] = $this->StorageMapper->read($datasetId);
468
		}
469
470
		unset($result['report']['id'], $result['report']['user_id'], $result['report']['user_id'], $result['report']['parent'], $result['report']['dataset']);
471
		$data = json_encode($result);
472
		return new DataDownloadResponse($data, $result['report']['name'] . '.export.txt', 'text/plain; charset=utf-8');
473
	}
474
475
	/**
476
	 * Update report options
477
	 *
478
	 * @param int $reportId
479
	 * @param $chartoptions
480
	 * @param $dataoptions
481
	 * @param $filteroptions
482
	 * @param $tableoptions
483
	 * @return bool
484
	 * @throws Exception
485
	 */
486
	public function updateOptions(int $reportId, $chartoptions, $dataoptions, $filteroptions, $tableoptions) {
487
		return $this->ReportMapper->updateOptions($reportId, $chartoptions, $dataoptions, $filteroptions, $tableoptions);
488
	}
489
490
	/**
491
	 * get report refresh options
492
	 *
493
	 * @NoAdminRequired
494
	 * @param int $reportId
495
	 * @param $refresh
496
	 * @return bool
497
	 */
498
	public function updateRefresh(int $reportId, $refresh) {
499
		return $this->ReportMapper->updateRefresh($reportId, $refresh);
500
	}
501
502
	/**
503
	 * update report group assignment (from drag & drop)
504
	 *
505
	 * @NoAdminRequired
506
	 * @param int $reportId
507
	 * @param $groupId
508
	 * @return bool
509
	 */
510
	public function updateGroup(int $reportId, $groupId) {
511
		return $this->ReportMapper->updateGroup($reportId, $groupId);
512
	}
513
514
	/**
515
	 * search for reports
516
	 *
517
	 * @param string $searchString
518
	 * @return array
519
	 */
520
	public function search(string $searchString) {
521
		return $this->ReportMapper->search($searchString);
522
	}
523
524
	/**
525
	 * @throws Exception
526
	 */
527
	public function reportsForDataset($datasetId) {
528
		return $this->ReportMapper->reportsForDataset($datasetId);
529
	}
530
531
	private function floatvalue($val) {
532
		// if value is a 3 digit comma number with one leading zero like 0,111, it should not go through the 1000 separator removal
533
		if (preg_match('/(?<=\b0)\,(?=\d{3}\b)/', $val) === 0 && preg_match('/(?<=\b0)\.(?=\d{3}\b)/', $val) === 0) {
534
			// remove , as 1000 separator
535
			$val = preg_replace('/(?<=\d)\,(?=\d{3}\b)/', '', $val);
536
			// remove . as 1000 separator
537
			$val = preg_replace('/(?<=\d)\.(?=\d{3}\b)/', '', $val);
538
		}
539
		// convert remaining comma to decimal point
540
		$val = str_replace(",", ".", $val);
541
		if (is_numeric($val)) {
542
			return number_format(floatval($val), 2, '.', '');
543
		} else {
544
			return false;
545
		}
546
	}
547
548
}
549