Issues (496)

lib/Controller/OutputController.php (10 issues)

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\DataSession;
12
use OCA\Analytics\Service\ReportService;
13
use OCA\Analytics\Service\ShareService;
14
use OCA\Analytics\Service\ThresholdService;
15
use OCA\Analytics\Service\StorageService;
16
use OCA\Analytics\Service\VariableService;
17
use OCA\Analytics\Service\PanoramaService;
18
use OCP\AppFramework\Controller;
0 ignored issues
show
The type OCP\AppFramework\Controller 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\AppFramework\Http;
0 ignored issues
show
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...
20
use OCP\AppFramework\Http\DataResponse;
0 ignored issues
show
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...
21
use OCP\AppFramework\Http\NotFoundResponse;
0 ignored issues
show
The type OCP\AppFramework\Http\NotFoundResponse 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 OCP\Constants;
0 ignored issues
show
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...
23
use OCP\DB\Exception;
0 ignored issues
show
The type OCP\DB\Exception 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...
24
use OCP\Files\NotFoundException;
0 ignored issues
show
The type OCP\Files\NotFoundException 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...
25
use OCP\IRequest;
0 ignored issues
show
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...
26
use Psr\Log\LoggerInterface;
0 ignored issues
show
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...
27
28
class OutputController extends Controller
29
{
30
    private $userId;
31
    private $logger;
32
    private $ReportService;
33
    private $DataSession;
34
    private $ShareService;
35
    private $DatasourceController;
36
    private $StorageService;
37
    private $ThresholdService;
38
    private $VariableService;
39
	private $PanoramaService;
40
41
    public function __construct(
42
        $userId,
43
        string $appName,
44
        IRequest $request,
45
        LoggerInterface $logger,
46
        ReportService $ReportService,
47
        ShareService $ShareService,
48
        DataSession $DataSession,
49
        DatasourceController $DatasourceController,
50
        StorageService $StorageService,
51
        ThresholdService $ThresholdService,
52
        VariableService $VariableService,
53
		PanoramaService $PanoramaService
54
    )
55
    {
56
        parent::__construct($appName, $request);
57
        $this->userId = $userId;
58
        $this->logger = $logger;
59
        $this->ReportService = $ReportService;
60
        $this->DataSession = $DataSession;
61
        $this->ShareService = $ShareService;
62
        $this->DatasourceController = $DatasourceController;
63
        $this->StorageService = $StorageService;
64
        $this->ThresholdService = $ThresholdService;
65
        $this->VariableService = $VariableService;
66
		$this->PanoramaService = $PanoramaService;
67
    }
68
69
    /**
70
     * get the data when requested from internal page
71
     *
72
     * @NoAdminRequired
73
     * @param int $reportId
74
     * @param $filteroptions
75
     * @param $dataoptions
76
     * @param $chartoptions
77
     * @param $tableoptions
78
     * @return DataResponse|NotFoundResponse
79
     * @throws Exception
80
     */
81
    public function read(int $reportId, $filteroptions, $dataoptions, $chartoptions, $tableoptions)
82
    {
83
        $reportMetadata = $this->ReportService->read($reportId);
84
        if (empty($reportMetadata)) $reportMetadata = $this->ShareService->getSharedReport($reportId);
85
86
        if (!empty($reportMetadata)) {
87
            $reportMetadata = $this->evaluateCanFilter($reportMetadata, $filteroptions, $dataoptions, $chartoptions, $tableoptions);
88
            $result = $this->getData($reportMetadata);
89
            return new DataResponse($result, HTTP::STATUS_OK);
90
        } else {
91
            return new NotFoundResponse();
92
        }
93
    }
94
95
	/**
96
	 * get the data when requested from a panorama
97
	 *
98
	 * @NoAdminRequired
99
	 * @param int $reportIds
100
	 * @return DataResponse|NotFoundResponse
101
	 * @throws Exception
102
	 */
103
	public function readPanorama(int $reportId)
104
	{
105
		$reportMetadata = $this->ReportService->read($reportId);
106
		if (empty($reportMetadata)) $reportMetadata = $this->ShareService->getSharedPanoramaReport($reportId);
107
108
		if (!empty($reportMetadata)) {
109
			$result = $this->getData($reportMetadata);
110
			return new DataResponse($result, HTTP::STATUS_OK);
111
		} else {
112
			return new NotFoundResponse();
113
		}
114
	}
115
116
	/**
117
     * Preview the data
118
     *
119
     * @NoAdminRequired
120
     * @param $type
121
     * @param $options
122
     * @return DataResponse|NotFoundResponse
123
     * @throws Exception
124
     */
125
    public function readPreview ($type, $options)
126
    {
127
        $reportMetadata = [];
128
         $array = json_decode($options, true);
129
        foreach ($array as $key => $value) {
130
            $array[$key] = htmlspecialchars($value, ENT_NOQUOTES, 'UTF-8');
131
        }
132
        $reportMetadata['link'] = json_encode($array);
133
        $reportMetadata['type'] = $type;
134
        $reportMetadata['dataset'] = 0;
135
        $reportMetadata['filteroptions'] = '';
136
        $reportMetadata['user_id'] = $this->userId;
137
        $reportMetadata['id'] = 0;
138
139
        $result = $this->getData($reportMetadata);
140
        unset($result['options']
141
            , $result['dimensions']
142
            , $result['filterApplied']
143
            , $result['thresholds']
144
        );
145
        $result['data'] = array_slice($result['data'], 0, 1);
146
147
        return new DataResponse($result, HTTP::STATUS_OK);
148
    }
149
150
151
    /**
152
     * Get the data from backend;
153
     * pre-evaluation of valid datasetId within read & readPublic is trusted here
154
     * also used in Pagecontroller-indexPublicMin ToDo: make this private
155
     *
156
     * @NoAdminRequired
157
     * @param $reportMetadata
158
     * @return array
159
     * @throws Exception
160
     */
161
    public function getData($reportMetadata)
162
    {
163
        $datasource = (int)$reportMetadata['type'];
164
        $datasetId = (int)$reportMetadata['dataset'];
165
166
        $filterWithVariables = $reportMetadata['filteroptions']; // need to remember the filter with original text variables
167
        $reportMetadata = $this->VariableService->replaceFilterVariables($reportMetadata); // replace %xx% dynamic variables
168
169
        if ($datasource === DatasourceController::DATASET_TYPE_INTERNAL_DB) {
170
            // Internal data
171
            if ($datasetId !== 0) {
172
                $result = $this->StorageService->read($datasetId, $reportMetadata);
173
            } else {
174
                $result['error'] = 'inconsistent report';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$result was never initialized. Although not strictly required by PHP, it is generally a good practice to add $result = array(); before regardless.
Loading history...
175
            }
176
        } else {
177
            // Realtime data
178
            $result = $this->DatasourceController->read($datasource, $reportMetadata);
179
            unset($result['rawdata']);
180
        }
181
182
        unset($reportMetadata['parent']
183
            , $reportMetadata['user_id']
184
            , $reportMetadata['link']
185
            , $reportMetadata['dimension1']
186
            , $reportMetadata['dimension2']
187
            , $reportMetadata['dimension3']
188
            , $reportMetadata['value']
189
            , $reportMetadata['password']
190
            , $reportMetadata['dataset']
191
        );
192
193
        $result['filterApplied'] = $reportMetadata['filteroptions'];
194
        $reportMetadata['filteroptions'] = $filterWithVariables; // keep the original filters
195
        // there can be different values for no options. null during creation; empty after removal; => harmonize them
196
        if (array_key_exists('chartoptions', $reportMetadata)) {
197
            $reportMetadata['chartoptions'] = ($reportMetadata['chartoptions'] === '' || $reportMetadata['chartoptions'] === 'null') ? null : $reportMetadata['chartoptions'];
198
        }
199
200
        if (array_key_exists('dataoptions', $reportMetadata)) {
201
            $reportMetadata['dataoptions'] = ($reportMetadata['dataoptions'] === '' || $reportMetadata['dataoptions'] === 'null') ? null : $reportMetadata['dataoptions'];
202
        }
203
        $result['options'] = $reportMetadata;
204
        $result['thresholds'] = $this->ThresholdService->read($reportMetadata['id']);
205
        return $result;
206
    }
207
208
    /**
209
     * get the data when requested from public page
210
     *
211
     * @NoAdminRequired
212
     * @PublicPage
213
     * @UseSession
214
     * @param $token
215
     * @param $filteroptions
216
     * @param $dataoptions
217
     * @param $chartoptions
218
     * @param $tableoptions
219
     * @return DataResponse|NotFoundResponse
220
     * @throws Exception
221
     */
222
    public function readPublic($token, $filteroptions, $dataoptions, $chartoptions, $tableoptions)
223
    {
224
        $share = $this->ShareService->getReportByToken($token);
225
        if (empty($share)) {
226
            // Dataset not shared or wrong token
227
            return new NotFoundResponse();
228
        } else {
229
            if ($share['password'] !== null) {
230
                $password = $this->DataSession->getPasswordForShare($token);
231
                $passwordVerification = $this->ShareService->verifyPassword($password, $share['password']);
232
                if ($passwordVerification === false) {
233
                    return new NotFoundResponse();
234
                }
235
            }
236
            $share = $this->evaluateCanFilter($share, $filteroptions, $dataoptions, $chartoptions, $tableoptions);
237
            $result = $this->getData($share);
238
            return new DataResponse($result, HTTP::STATUS_OK);
239
        }
240
    }
241
242
    /**
243
     * evaluate if the user did filter in the report and if he is allowed to filter (shared reports)
244
     *
245
     * @param $metadata
246
     * @param $filteroptions
247
     * @param $dataoptions
248
     * @param $chartoptions
249
     * @param $tableoptions
250
     * @return mixed
251
     */
252
    private function evaluateCanFilter($metadata, $filteroptions, $dataoptions, $chartoptions, $tableoptions)
253
    {
254
        // send current user filter options to the data request
255
        // only if the report has update-permissions
256
        // if nothing is changed by the user, the filter which is stored for the report, will be used
257
        if ($filteroptions and $filteroptions !== '' and (int)$metadata['permissions'] === Constants::PERMISSION_UPDATE) {
258
            $metadata['filteroptions'] = $filteroptions;
259
            $metadata['dataoptions'] = $dataoptions;
260
            $metadata['chartoptions'] = $chartoptions;
261
            $metadata['tableoptions'] = $tableoptions;
262
        }
263
        return $metadata;
264
    }
265
}