Passed
Push — master ( 3660fa...998d5d )
by Marcel
03:22
created

DataloadController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 10
dl 0
loc 22
rs 9.9666
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
 * 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 2020 Marcel Scherello
10
 */
11
12
namespace OCA\Analytics\Controller;
13
14
use Exception;
15
use OCA\Analytics\Activity\ActivityManager;
16
use OCA\Analytics\Db\DataloadMapper;
17
use OCA\Analytics\Service\DataloadService;
18
use OCA\Analytics\Service\DatasetService;
19
use OCP\AppFramework\Controller;
20
use OCP\AppFramework\Http\DataResponse;
21
use OCP\AppFramework\Http\NotFoundResponse;
22
use OCP\Files\NotFoundException;
23
use OCP\IL10N;
24
use OCP\ILogger;
25
use OCP\IRequest;
26
27
class DataloadController extends Controller
28
{
29
    private $logger;
30
    private $StorageController;
31
    private $DatasourceController;
32
    private $ActivityManager;
33
    private $DatasetService;
34
    private $DataloadService;
35
    private $l10n;
36
    private $DataloadMapper;
37
38
    public function __construct(
39
        string $AppName,
40
        IRequest $request,
41
        IL10N $l10n,
42
        ILogger $logger,
43
        ActivityManager $ActivityManager,
44
        DatasourceController $DatasourceController,
45
        DatasetService $DatasetService,
46
        DataloadService $DataloadService,
47
        StorageController $StorageController,
48
        DataloadMapper $DataloadMapper
49
    )
50
    {
51
        parent::__construct($AppName, $request);
52
        $this->l10n = $l10n;
53
        $this->logger = $logger;
54
        $this->StorageController = $StorageController;
55
        $this->ActivityManager = $ActivityManager;
56
        $this->DatasourceController = $DatasourceController;
57
        $this->DatasetService = $DatasetService;
58
        $this->DataloadService = $DataloadService;
59
        $this->DataloadMapper = $DataloadMapper;
60
    }
61
62
    /**
63
     * create a new dataload
64
     *
65
     * @NoAdminRequired
66
     * @param int $datasetId
67
     * @param int $datasourceId
68
     * @return DataResponse
69
     */
70
    public function create(int $datasetId, int $datasourceId)
71
    {
72
        return new DataResponse(['id' => $this->DataloadService->create($datasetId, $datasourceId)]);
73
    }
74
75
    /**
76
     * get all dataloads for a dataset
77
     *
78
     * @NoAdminRequired
79
     * @param int $datasetId
80
     * @return DataResponse
81
     */
82
    public function read(int $datasetId)
83
    {
84
        $result = array();
85
        $result['dataloads'] = $this->DataloadService->read($datasetId);
86
        return new DataResponse($result);
87
    }
88
89
    /**
90
     * update dataload
91
     *
92
     * @NoAdminRequired
93
     * @param int $dataloadId
94
     * @param $name
95
     * @param $option
96
     * @param $schedule
97
     * @return DataResponse
98
     */
99
    public function update(int $dataloadId, $name, $option, $schedule)
100
    {
101
        return new DataResponse(['update' => $this->DataloadService->update($dataloadId, $name, $option, $schedule)]);
102
    }
103
104
    /**
105
     * delete a dataload
106
     *
107
     * @NoAdminRequired
108
     * @param int $dataloadId
109
     * @return bool
110
     */
111
    public function delete(int $dataloadId)
112
    {
113
        return $this->DataloadService->delete($dataloadId);
114
    }
115
116
    /**
117
     * simulate a dataload and output its data
118
     *
119
     * @NoAdminRequired
120
     * @param int $dataloadId
121
     * @return DataResponse
122
     * @throws NotFoundException
123
     */
124
    public function simulate(int $dataloadId)
125
    {
126
        return new DataResponse($this->DataloadService->getDataFromDatasource($dataloadId));
127
    }
128
129
    /**
130
     * execute a dataload from datasource and store into dataset
131
     *
132
     * @NoAdminRequired
133
     * @param int $dataloadId
134
     * @return DataResponse
135
     * @throws Exception
136
     */
137
    public function execute(int $dataloadId)
138
    {
139
        return new DataResponse($this->DataloadService->execute($dataloadId));
140
    }
141
142
143
    // Data Manipulation
144
    // Data Manipulation
145
    // Data Manipulation
146
147
    /**
148
     * update data from input form
149
     *
150
     * @NoAdminRequired
151
     * @param int $datasetId
152
     * @param $dimension1
153
     * @param $dimension2
154
     * @param $value
155
     * @return DataResponse|NotFoundResponse
156
     * @throws Exception
157
     */
158
    public function updateData(int $datasetId, $dimension1, $dimension2, $value)
159
    {
160
        $datasetMetadata = $this->DatasetService->getOwnDataset($datasetId);
161
        if (!empty($datasetMetadata)) {
162
            $insert = $update = $errorMessage = 0;
163
            $action = array();
164
            $value = $this->floatvalue($value);
165
            if ($value === false) {
166
                $errorMessage = $this->l10n->t('3rd field must be a valid number');
167
            } else {
168
                $action = $this->StorageController->update($datasetId, $dimension1, $dimension2, $value);
169
                $insert = $insert + $action['insert'];
170
                $update = $update + $action['update'];
171
            }
172
173
            $result = [
174
                'insert' => $insert,
175
                'update' => $update,
176
                'error' => $errorMessage,
177
                'validate' => $action['validate'],
178
            ];
179
180
            //$this->logger->error('DataLoadController 88:'.$errorMessage);
181
            if ($errorMessage === 0) $this->ActivityManager->triggerEvent($datasetId, ActivityManager::OBJECT_DATA, ActivityManager::SUBJECT_DATA_ADD);
182
            return new DataResponse($result);
183
        } else {
184
            return new NotFoundResponse();
185
        }
186
    }
187
188
    /**
189
     * delete data from input form
190
     *
191
     * @NoAdminRequired
192
     * @param int $datasetId
193
     * @param $dimension1
194
     * @param $dimension2
195
     * @return DataResponse|NotFoundResponse
196
     */
197
    public function deleteData(int $datasetId, $dimension1, $dimension2)
198
    {
199
        $datasetMetadata = $this->DatasetService->getOwnDataset($datasetId);
200
        if (!empty($datasetMetadata)) {
201
            $result = $this->StorageController->delete($datasetId, $dimension1, $dimension2);
202
            return new DataResponse(['delete' => $result]);
203
        } else {
204
            return new NotFoundResponse();
205
        }
206
    }
207
208
    /**
209
     * Simulate delete data from input form
210
     *
211
     * @NoAdminRequired
212
     * @param int $datasetId
213
     * @param $dimension1
214
     * @param $dimension2
215
     * @return DataResponse|NotFoundResponse
216
     */
217
    public function deleteDataSimulate(int $datasetId, $dimension1, $dimension2)
218
    {
219
        $datasetMetadata = $this->DatasetService->getOwnDataset($datasetId);
220
        if (!empty($datasetMetadata)) {
221
            $result = $this->StorageController->deleteSimulate($datasetId, $dimension1, $dimension2);
222
            return new DataResponse(['delete' => $result]);
223
        } else {
224
            return new NotFoundResponse();
225
        }
226
    }
227
228
    /**
229
     * Import clipboard data
230
     *
231
     * @NoAdminRequired
232
     * @param int $datasetId
233
     * @param $import
234
     * @return DataResponse|NotFoundResponse
235
     * @throws Exception
236
     */
237
    public function importClipboard($datasetId, $import)
238
    {
239
        $datasetMetadata = $this->DatasetService->getOwnDataset($datasetId);
240
        if (!empty($datasetMetadata)) {
241
            $insert = $update = $errorMessage = $errorCounter = 0;
242
            $delimiter = '';
243
244
            if ($import === '') {
245
                $errorMessage = $this->l10n->t('No data');
246
            } else {
247
                $delimiter = $this->detectDelimiter($import);
248
                $rows = str_getcsv($import, "\n");
249
250
                foreach ($rows as &$row) {
251
                    $row = str_getcsv($row, $delimiter);
252
                    $numberOfColumns = count($row);
253
                    // last column needs to be a float
254
                    $row[2] = $this->floatvalue($row[$numberOfColumns - 1]);
255
                    if ($row[2] === false) {
256
                        $errorCounter++;
257
                    } else {
258
                        if ($numberOfColumns << 3) $row[1] = null;
259
                        $action = $this->StorageController->update($datasetId, $row[0], $row[1], $row[2]);
260
                        $insert = $insert + $action['insert'];
261
                        $update = $update + $action['update'];
262
                    }
263
                    if ($errorCounter === 2) {
264
                        // first error is ignored; might be due to header row
265
                        $errorMessage = $this->l10n->t('Last field must be a valid number');
266
                        break;
267
                    }
268
                }
269
            }
270
271
            $result = [
272
                'insert' => $insert,
273
                'update' => $update,
274
                'delimiter' => $delimiter,
275
                'error' => $errorMessage,
276
            ];
277
278
            if ($errorMessage === 0) $this->ActivityManager->triggerEvent($datasetId, ActivityManager::OBJECT_DATA, ActivityManager::SUBJECT_DATA_ADD_IMPORT);
279
            return new DataResponse($result);
280
        } else {
281
            return new NotFoundResponse();
282
        }
283
    }
284
285
    /**
286
     * Import data into dataset from an internal or external file
287
     *
288
     * @NoAdminRequired
289
     * @param int $datasetId
290
     * @param $path
291
     * @return DataResponse|NotFoundResponse
292
     * @throws NotFoundException
293
     * @throws Exception
294
     */
295
    public function importFile(int $datasetId, $path)
296
    {
297
        //$this->logger->debug('DataLoadController 378:' . $datasetId . $path);
298
        $datasetMetadata = $this->DatasetService->getOwnDataset($datasetId);
299
        if (!empty($datasetMetadata)) {
300
            $insert = $update = 0;
301
            $option = array();
302
            $option['user_id'] = $datasetMetadata['user_id'];
303
            $option['path'] = $path;
304
            $option['link'] = $datasetMetadata['link'];
305
            $result = $this->DatasourceController->read(DatasourceController::DATASET_TYPE_INTERNAL_FILE, $option);
306
307
            if ($result['error'] === 0) {
308
                foreach ($result['data'] as &$row) {
309
                    $action = $this->StorageController->update($datasetId, $row[0], $row[1], $row[2]);
310
                    $insert = $insert + $action['insert'];
311
                    $update = $update + $action['update'];
312
                }
313
            }
314
315
            $result = [
316
                'insert' => $insert,
317
                'update' => $update,
318
                'error' => $result['error'],
319
            ];
320
321
            if ($result['error'] === 0) $this->ActivityManager->triggerEvent($datasetId, ActivityManager::OBJECT_DATA, ActivityManager::SUBJECT_DATA_ADD_IMPORT);
322
            return new DataResponse($result);
323
        } else {
324
            return new NotFoundResponse();
325
        }
326
    }
327
328
    private function detectDelimiter($data): string
329
    {
330
        $delimiters = ["\t", ";", "|", ","];
331
        $data_2 = null;
332
        $delimiter = $delimiters[0];
333
        foreach ($delimiters as $d) {
334
            $firstRow = str_getcsv($data, "\n")[0];
335
            $data_1 = str_getcsv($firstRow, $d);
336
            if (sizeof($data_1) > sizeof($data_2)) {
337
                $delimiter = $d;
338
                $data_2 = $data_1;
339
            }
340
        }
341
        return $delimiter;
342
    }
343
344
    private function floatvalue($val)
345
    {
346
        $val = str_replace(",", ".", $val);
347
        $val = preg_replace('/\.(?=.*\.)/', '', $val);
348
        $val = preg_replace('/[^0-9-.]+/', '', $val);
349
        if (is_numeric($val)) {
350
            return number_format(floatval($val), 2, '.', '');
351
        } else {
352
            return false;
353
        }
354
    }
355
}