ApiDataController::requestResponse()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 14
nc 3
nop 3
dl 0
loc 21
rs 9.7998
c 1
b 0
f 0
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