ApiDataController::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 9
dl 0
loc 24
rs 9.9
c 0
b 0
f 0

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
 * SPDX-FileCopyrightText: 2019-2022 Marcel Scherello
6
 * SPDX-License-Identifier: AGPL-3.0-or-later
7
 */
8
9
namespace OCA\Analytics\Controller;
10
11
use OCA\Analytics\Activity\ActivityManager;
12
use OCA\Analytics\Db\StorageMapper;
13
use OCA\Analytics\Service\DatasetService;
14
use OCA\Analytics\Service\ReportService;
15
use OCA\Analytics\Service\StorageService;
16
use OCP\AppFramework\ApiController;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\ApiController 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...
17
use OCP\AppFramework\Http;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Http 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\AppFramework\Http\DataResponse;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Http\DataResponse 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\Constants;
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...
20
use OCP\IRequest;
0 ignored issues
show
Bug introduced by
The type OCP\IRequest 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\IUserSession;
0 ignored issues
show
Bug introduced by
The type OCP\IUserSession 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 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...
23
24
class ApiDataController extends ApiController
25
{
26
    const UNKNOWN = 9001;
27
    const MISSING_PARAM = 9002;
28
    const NOT_FOUND = 9003;
29
    const NOT_ALLOWED = 9004;
30
31
    protected $errors = [];
32
    private $logger;
33
    private $userSession;
34
    private $ActivityManager;
35
    private $DatasetService;
36
    private $ReportService;
37
    private $StorageService;
38
	private $StorageMapper;
39
40
    public function __construct(
41
        $appName,
42
        IRequest $request,
43
        LoggerInterface $logger,
44
        IUserSession $userSession,
45
        ActivityManager $ActivityManager,
46
        DatasetService $DatasetService,
47
        ReportService $ReportService,
48
        StorageService $StorageService,
49
        StorageMapper $StorageMapper
50
    )
51
    {
52
        parent::__construct(
53
            $appName,
54
            $request,
55
            'POST'
56
            );
57
        $this->logger = $logger;
58
        $this->userSession = $userSession;
59
        $this->ActivityManager = $ActivityManager;
60
        $this->DatasetService = $DatasetService;
61
        $this->ReportService = $ReportService;
62
        $this->StorageService = $StorageService;
63
        $this->StorageMapper = $StorageMapper;
64
    }
65
66
    /**
67
     * add data via there database names
68
     * @CORS
69
     * @NoCSRFRequired
70
     * @NoAdminRequired
71
     * @param int $datasetId
72
     * @return DataResponse
73
     * @throws \Exception
74
     */
75
    public function addData(int $datasetId)
76
    {
77
        $params = $this->request->getParams();
78
        $datasetMetadata = $this->DatasetService->readOwn($datasetId);
79
80
        $response = $this->deriveMaintenancePossible($datasetMetadata);
81
        if ($response !== true) return $response;
82
83
        if (!isset($params['dimension1'])) {
84
            $this->errors[] = 'Dimension 1 required';
85
        } elseif (!isset($params['dimension2'])) {
86
            $this->errors[] = 'Dimension 2 required';
87
        } elseif (!isset($params['dimension3'])) {
88
            $this->errors[] = 'Dimension 3 required';
89
        }
90
        if (!empty($this->errors)) {
91
            return $this->requestResponse(false, self::MISSING_PARAM, implode(',', $this->errors));
92
        }
93
94
        $this->StorageService->update($datasetId, $params['dimension1'], $params['dimension2'], $params['dimension3']);
95
        //$this->ActivityManager->triggerEvent($datasetId, ActivityManager::OBJECT_DATA, ActivityManager::SUBJECT_DATA_ADD_API);
96
97
		// Update the Context Chat backend
98
		$this->DatasetService->provider($datasetId);
99
100
        return $this->requestResponse(
101
            true,
102
            Http::STATUS_OK,
103
            'Data update successful');
104
    }
105
106
    /**
107
     * add data via there real field names
108
     * @CORS
109
     * @NoCSRFRequired
110
     * @NoAdminRequired
111
     * @param int $datasetId
112
     * @return DataResponse
113
     * @throws \Exception
114
     */
115
    public function addDataV2(int $datasetId)
116
    {
117
        $message = 'No -data- parameter';
118
        $params = $this->request->getParams();
119
        $datasetMetadata = $this->DatasetService->readOwn($datasetId);
120
121
        $response = $this->deriveMaintenancePossible($datasetMetadata);
122
        if ($response !== true) return $response;
123
124
        foreach ($params['data'] as $dataArray) {
125
126
            $dimension1 = $this->deriveParameterNames($dataArray, $datasetMetadata, 'dimension1');
127
            $dimension2 = $this->deriveParameterNames($dataArray, $datasetMetadata, 'dimension2');
128
            $value = $this->deriveParameterNames($dataArray, $datasetMetadata, 'value');
129
130
            if (!empty($this->errors)) {
131
                return $this->requestResponse(false, self::MISSING_PARAM, implode(',', $this->errors));
132
            }
133
134
            $this->StorageService->update($datasetId, $dimension1, $dimension2, $value);
135
136
			// Update the Context Chat backend
137
			$this->DatasetService->provider($datasetId);
138
139
			//$this->ActivityManager->triggerEvent($datasetId, ActivityManager::OBJECT_DATA, ActivityManager::SUBJECT_DATA_ADD_API);
140
            $message = 'Data update successful';
141
        }
142
143
        return $this->requestResponse(
144
            true,
145
            Http::STATUS_OK,
146
            $message);
147
    }
148
149
    /**
150
     * delete data
151
     * @CORS
152
     * @NoCSRFRequired
153
     * @NoAdminRequired
154
     * @param int $datasetId
155
     * @return DataResponse
156
     * @throws \Exception
157
     */
158
    public function deleteDataV2(int $datasetId)
159
    {
160
        $message = 'No -delete- parameter';
161
        $params = $this->request->getParams();
162
        $datasetMetadata = $this->DatasetService->readOwn($datasetId);
163
164
        $response = $this->deriveMaintenancePossible($datasetMetadata);
165
        if ($response !== true) return $response;
166
167
        foreach ($params['delete'] as $dataArray) {
168
            $dimension1 = $this->deriveParameterNames($dataArray, $datasetMetadata, 'dimension1');
169
            $dimension2 = $this->deriveParameterNames($dataArray, $datasetMetadata, 'dimension2');
170
171
            if (!empty($this->errors)) {
172
                return $this->requestResponse(false, self::MISSING_PARAM, implode(',', $this->errors));
173
            }
174
175
            $this->StorageService->delete($datasetId, $dimension1, $dimension2);
176
            $message = 'Data deleted';
177
        }
178
179
        return $this->requestResponse(
180
            true,
181
            Http::STATUS_OK,
182
            $message);
183
    }
184
185
186
    ///
187
    /// API V3
188
    ///
189
190
    /**
191
     * get all data of a report and respect filter options
192
     * @CORS
193
     * @NoCSRFRequired
194
     * @NoAdminRequired
195
     * @return DataResponse
196
     * @throws \Exception
197
     */
198
    public function dataGetV3(int $reportId)
199
    {
200
        $params = $this->request->getParams();
0 ignored issues
show
Unused Code introduced by
The assignment to $params is dead and can be removed.
Loading history...
201
        $reportMetadata = $this->ReportService->read($reportId);
202
203
        if (!empty($reportMetadata)) {
204
            $options = json_decode($reportMetadata['filteroptions'], true);
205
            $allData = $this->StorageMapper->read((int)$reportMetadata['dataset'], $options);
206
207
            return new DataResponse($allData, HTTP::STATUS_OK);
208
        } else {
209
            return new DataResponse([
210
                'message' => 'No data available for given report id',
211
            ], HTTP::STATUS_OK);
212
        }
213
    }
214
215
    /**
216
     * delete data
217
     * @CORS
218
     * @NoCSRFRequired
219
     * @NoAdminRequired
220
     * @param int $datasetId
221
     * @return DataResponse
222
     * @throws \Exception
223
     */
224
    public function dataDeleteV3(int $datasetId)
225
    {
226
        return $this->deleteDataV2($datasetId);
227
    }
228
229
    /**
230
     * add data via there real field names
231
     * @CORS
232
     * @NoCSRFRequired
233
     * @NoAdminRequired
234
     * @param int $datasetId
235
     * @return DataResponse
236
     * @throws \Exception
237
     */
238
    public function dataAddV3(int $datasetId)
239
    {
240
        return $this->addDataV2($datasetId);
241
    }
242
243
    /**
244
     * list datasets
245
     * @CORS
246
     * @NoCSRFRequired
247
     * @NoAdminRequired
248
     * @return array
249
     * @throws \Exception
250
     */
251
    public function datasetIndexV3()
252
    {
253
        return $this->DatasetService->index();
254
    }
255
256
    /**
257
     * list reports
258
     * @CORS
259
     * @NoCSRFRequired
260
     * @NoAdminRequired
261
     * @return array
262
     * @throws \Exception
263
     */
264
    public function reportIndexV3()
265
    {
266
        return $this->ReportService->index();
267
    }
268
269
    /**
270
     * read data of a dataset with additional information for table and series
271
     * @CORS
272
     * @NoCSRFRequired
273
     * @NoAdminRequired
274
     * @return DataResponse
275
     * @throws \Exception
276
     */
277
    public function reportDetailV3(int $reportId)
278
    {
279
        $reportMetadata = $this->ReportService->read($reportId);
280
        unset($reportMetadata['user_id']
281
            , $reportMetadata['link']
282
            , $reportMetadata['permissions']
283
            , $reportMetadata['dimension3']
284
        );
285
286
        if (!empty($reportMetadata)) {
287
            return new DataResponse($reportMetadata, HTTP::STATUS_OK);
288
        } else {
289
            return new DataResponse([
290
                'message' => 'No metadata available for given $reportId',
291
            ], HTTP::STATUS_OK);
292
        }
293
    }
294
295
    /**
296
     * derive if the parameter is technical or the free text description from the report
297
     * @param $data
298
     * @param $datasetMetadata
299
     * @param $dimension
300
     * @return array | bool
301
     */
302
    protected function deriveParameterNames($data, $datasetMetadata, $dimension)
303
    {
304
        if (isset($data[$dimension])) {
305
            return $data[$dimension];
306
        } elseif (isset($data[$datasetMetadata[$dimension]])) {
307
            return $data[$datasetMetadata[$dimension]];
308
        } else {
309
            $this->errors[] = $dimension . ' required';
310
            return false;
311
        }
312
    }
313
314
    /**
315
     * derive if maintenance is possible
316
     * @param $datasetMetadata
317
     * @return bool|DataResponse
318
     */
319
    protected function deriveMaintenancePossible($datasetMetadata)
320
    {
321
        if (empty($datasetMetadata)) {
322
            $this->errors[] = 'Unknown or unauthorized report or dataset';
323
            return $this->requestResponse(false, self::NOT_FOUND, implode(',', $this->errors));
324
        } else {
325
            return true;
326
        }
327
    }
328
329
    /**
330
     * @param bool $success
331
     * @param int|null $code
332
     * @param string|null $message
333
     * @return DataResponse
334
     */
335
    protected function requestResponse($success, $code = null, $message = null)
336
    {
337
        if (!$success) {
338
            if ($code === null) {
339
                $code = self::UNKNOWN;
340
            }
341
            $array = [
342
                'success' => false,
343
                'error' => ['code' => $code,
344
                    'message' => $message
345
                ]
346
            ];
347
        } else {
348
            $array = [
349
                'success' => true,
350
                'message' => $message
351
            ];
352
        }
353
        $response = new DataResponse();
354
        $response->setData($array)->render();
355
        return $response;
356
    }
357
    // curl -u Admin:2sroW-SxRcK-AmdsF-RYMJ5-CKSyf -d '{"data":[{"Spalte 1": "a", "Spalte 2": "a", "toller wert": "1"}, {"dimension1": "b", "dimension2": "b", "value": "2"}]}' -X POST -H "Content-Type: application/json" http://ncxx/nextcloud/apps/analytics/api/2.0/adddata/158
358
359
    // curl -u Admin:2sroW-SxRcK-AmdsF-RYMJ5-CKSyf -d '{"delete":[{"dimension1": "a", "dimension2": "a"}]}' -X POST -H "Content-Type: application/json" http://ncxx/nextcloud/apps/analytics/api/2.0/deletedata/158
360
    // curl -u Admin:2sroW-SxRcK-AmdsF-RYMJ5-CKSyf -d '{"del":[{"dimension1": "a", "dimension2": "a"}]}' -X POST -H "Content-Type: application/json" http://ncxx/nextcloud/apps/analytics/api/2.0/deletedata/158
361
    // curl -u admin:cZMLJ-DTpYA-Ci5QM-M4ZRy-KBcTp -X GET -H "Content-Type: application/json" https://ncxx/nextcloud/apps/analytics/api/3.0/data/52 --insecure
362
    // curl -u Admin:WW6pE-XAEd9-XJ8t3-raRCK-qqmdz -X GET -H "Content-Type: application/json" https://nc25/nextcloud/apps/analytics/api/3.0/data/6 --insecure
363
    // curl -u admin:cZMLJ-DTpYA-Ci5QM-M4ZRy-KBcTp -X GET -H "Content-Type: application/json" https://ncxx/nextcloud/apps/analytics/api/3.0/reports --insecure
364
}
365