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

DataloadController::deleteData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 3
dl 0
loc 8
rs 10
c 0
b 0
f 0
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
}