OutputController::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 11
nc 1
nop 12
dl 0
loc 26
rs 9.9
c 1
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
 * 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
Bug introduced by
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
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...
20
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...
21
use OCP\AppFramework\Http\NotFoundResponse;
0 ignored issues
show
Bug introduced by
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
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...
23
use OCP\DB\Exception;
0 ignored issues
show
Bug introduced by
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
Bug introduced by
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
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...
26
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...
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
}