Passed
Push — master ( cf86d0...003506 )
by Marcel
03:25
created

ApiDataController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 10
c 2
b 0
f 0
nc 1
nop 8
dl 0
loc 22
rs 9.9332

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