Passed
Push — master ( ac5f58...0c3cf2 )
by Marcel
02:26
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
	 * list datasets
175
	 * @CORS
176
	 * @NoCSRFRequired
177
	 * @NoAdminRequired
178
	 * @return DataResponse
179
	 * @throws \Exception
180
	 */
181
	public function index() {
182
		return $this->DatasetService->index();
183
	}
184
185
	/**
186
	 * read data of a dataset with additional information for table and series
187
	 * @CORS
188
	 * @NoCSRFRequired
189
	 * @NoAdminRequired
190
	 * @return DataResponse
191
	 * @throws \Exception
192
	 */
193
	public function detail(int $datasetId)
194
	{
195
		$datasetMetadata = $this->DatasetService->getOwnDataset($datasetId);
196
197
		if (!empty($datasetMetadata)) {
198
			$allData = $this->StorageController->read($datasetMetadata);
199
			$series = array_values(array_unique(array_map('array_shift', $allData['data'])));
200
201
			return new DataResponse([
202
				'header' => $allData['header'],
203
				'dimensions' => $allData['dimensions'],
204
				'series' => $series,
205
			], HTTP::STATUS_OK);
206
		} else {
207
			return new DataResponse([
208
				'message' => 'No metadata available for given $datasetId',
209
			], HTTP::STATUS_OK);
210
		}
211
	}
212
213
	/**
214
	 * get all data of a dataset and respect filter options
215
	 * @CORS
216
	 * @NoCSRFRequired
217
	 * @NoAdminRequired
218
	 * @return DataResponse
219
	 * @throws \Exception
220
	 */
221
	public function data(int $datasetId)
222
	{
223
		$params = $this->request->getParams();
224
		$datasetMetadata = $this->DatasetService->getOwnDataset($datasetId);
225
226
		if (!empty($datasetMetadata)) {
227
			$options = json_decode($params['filteroptions'], true);
228
			$allData = $this->StorageMapper->read($datasetMetadata['id'], $options);
229
230
			return new DataResponse($allData, HTTP::STATUS_OK);
231
		} else {
232
			return new DataResponse([
233
				'message' => 'No data available for given $datasetId',
234
			], HTTP::STATUS_OK);
235
		}
236
	}
237
238
    /**
239
     * derive if the parameter is technical or the free text description from the report
240
     * @param $data
241
     * @param $datasetMetadata
242
     * @param $dimension
243
     * @return array | bool
244
     */
245
    protected function deriveParameterNames($data, $datasetMetadata, $dimension)
246
    {
247
        if (isset($data[$dimension])) {
248
            return $data[$dimension];
249
        } elseif (isset($data[$datasetMetadata[$dimension]])) {
250
            return $data[$datasetMetadata[$dimension]];
251
        } else {
252
            $this->errors[] = $dimension . ' required';
253
            return false;
254
        }
255
    }
256
257
    /**
258
     * derive if maintenance is possible
259
     * @param $datasetMetadata
260
     * @return DataResponse | bool
261
     */
262
    protected function deriveMaintenancePossible($datasetMetadata)
263
    {
264
        if (empty($datasetMetadata)) {
265
            $this->errors[] = 'Unknown report or dataset';
266
            return $this->requestResponse(false, self::NOT_FOUND, implode(',', $this->errors));
267
        } elseif ((int)$datasetMetadata['type'] !== DatasourceController::DATASET_TYPE_INTERNAL_DB) {
268
            $this->errors[] = 'Report does not allow data maintenance';
269
            return $this->requestResponse(false, self::NOT_ALLOWED, implode(',', $this->errors));
270
        }
271
        return true;
272
    }
273
274
    /**
275
     * @param bool $success
276
     * @param int|null $code
277
     * @param string|null $message
278
     * @return DataResponse
279
     */
280
    protected function requestResponse($success, $code = null, $message = null)
281
    {
282
        if (!$success) {
283
            if ($code === null) {
284
                $code = self::UNKNOWN;
285
            }
286
            $array = [
287
                'success' => false,
288
                'error' => ['code' => $code,
289
                    'message' => $message
290
                ]
291
            ];
292
        } else {
293
            $array = [
294
                'success' => true,
295
                'message' => $message
296
            ];
297
        }
298
        $response = new DataResponse();
299
        $response->setData($array)->render();
300
        return $response;
301
    }
302
    // 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
303
    // 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
304
    // 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
305
306
    // 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
307
    // 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
308
309
}
310