Passed
Push — master ( 9179ab...b51dc7 )
by Marcel
02:24
created

ApiDataController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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

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