Statistics   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 223
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 125
c 3
b 0
f 0
dl 0
loc 223
rs 10
wmc 22

4 Methods

Rating   Name   Duplication   Size   Complexity  
A metadata() 0 19 3
A __construct() 0 5 1
B getBaseURL() 0 25 8
C main() 0 128 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\Module\statistics\Controller;
6
7
use Exception;
8
use SimpleSAML\Configuration;
9
use SimpleSAML\Module;
10
use SimpleSAML\Module\statistics\AccessCheck;
11
use SimpleSAML\Module\statistics\Aggregator;
12
use SimpleSAML\Module\statistics\Graph;
13
use SimpleSAML\Module\statistics\Ruleset;
14
use SimpleSAML\Session;
15
use SimpleSAML\XHTML\Template;
16
use Symfony\Component\HttpFoundation\Request;
17
18
/**
19
 * Controller class for the statistics module.
20
 *
21
 * This class serves the statistics views available in the module.
22
 *
23
 * @package SimpleSAML\Module\statistics
24
 */
25
class Statistics
26
{
27
    /** @var \SimpleSAML\Configuration */
28
    protected $config;
29
30
    /** @var \SimpleSAML\Configuration */
31
    protected $moduleConfig;
32
33
    /** @var \SimpleSAML\Session */
34
    protected $session;
35
36
37
    /**
38
     * StatisticsController constructor.
39
     *
40
     * @param \SimpleSAML\Configuration $config The configuration to use.
41
     * @param \SimpleSAML\Session $session The current user session.
42
     */
43
    public function __construct(Configuration $config, Session $session)
44
    {
45
        $this->config = $config;
46
        $this->moduleConfig = Configuration::getConfig('module_statistics.php');
47
        $this->session = $session;
48
    }
49
50
51
    /**
52
     * Display statistics metadata.
53
     *
54
     * @param Request $request The current request.
55
     *
56
     * @return \SimpleSAML\XHTML\Template
57
     */
58
    public function metadata(Request $request): Template
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

58
    public function metadata(/** @scrutinizer ignore-unused */ Request $request): Template

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
59
    {
60
        AccessCheck::checkAccess($this->moduleConfig);
61
62
        $aggr = new Aggregator();
63
        $aggr->loadMetadata();
64
        $metadata = $aggr->getMetadata();
65
        if ($metadata !== null) {
66
            if (array_key_exists('memory', $metadata)) {
67
                $metadata['memory'] = number_format($metadata['memory'] / (1024 * 1024), 2);
68
            }
69
        }
70
71
        $t = new Template($this->config, 'statistics:statmeta.twig');
72
        $t->data = [
73
            'metadata' => $metadata,
74
        ];
75
76
        return $t;
77
    }
78
79
80
    /**
81
     * Display the main admin page.
82
     *
83
     * @return \SimpleSAML\XHTML\Template
84
     */
85
    public function main(Request $request): Template
86
    {
87
        AccessCheck::checkAccess($this->moduleConfig);
88
89
        /**
90
         * Check input parameters
91
         */
92
        $preferRule = $request->query->get('rule');
93
        $preferRule2 = $request->query->get('rule2');
94
        if ($preferRule2 === '_') {
95
            $preferRule2 = null;
96
        }
97
98
        $preferTime = strval($request->query->get('time'));
99
        $preferTimeRes = strval($request->query->get('res'));
100
        $delimiter = strval($request->query->get('delimiter'));
101
102
        /**
103
         * Create statistics data.
104
         */
105
        $ruleset = new Ruleset($this->moduleConfig);
106
        $statrule = $ruleset->getRule($preferRule);
107
        $rule = $statrule->getRuleID();
108
109
        /**
110
         * Prepare template.
111
         */
112
        $t = new Template($this->config, 'statistics:statistics.twig');
113
        $t->data = [
114
            'delimiter' => $delimiter,
115
            'pageid' => 'statistics',
116
            'header' => 'stat',
117
            'available_rules' => $ruleset->availableRulesNames(),
118
            'selected_rule' => $rule,
119
            'selected_rule2' => $preferRule2,
120
        ];
121
122
        $t->data['available_rules'] = $ruleset->availableRulesNames();
123
        $t->data['current_rule'] = $t->data['available_rules'][$rule];
124
        $t->data['post_rule'] = $this->getBaseURL($t, 'post', 'rule');
125
        $t->data['post_res'] = $this->getBaseURL($t, 'post', 'res');
126
        $t->data['post_time'] = $this->getBaseURL($t, 'post', 'time');
127
        $t->data['available_timeres'] = [];
128
        $t->data['available_times'] = [];
129
130
        try {
131
            $dataset = $statrule->getDataset($preferTimeRes, $preferTime);
132
            $delimiter = $dataset->getDelimiter();
133
            $dataset->setDelimiter($delimiter);
134
            $dataset->aggregateSummary();
135
            $dataset->calculateMax();
136
        } catch (Exception $e) {
137
            $t->data['error'] = "No data available";
138
            return $t;
139
        }
140
141
        $fileslot = $dataset->getFileslot();
142
        $timeres = $dataset->getTimeRes();
143
        $timeNavigation = $statrule->getTimeNavigation($timeres, $preferTime);
144
        $piedata = $dataset->getPieData();
145
        $datasets = [$dataset->getPercentValues()];
146
        $axis = $dataset->getAxis();
147
        $maxes = [$dataset->getMax()];
148
149
        if (isset($preferRule2)) {
150
            $statrule = $ruleset->getRule($preferRule2);
151
            $t->data['available_timeres'] = $statrule->availableTimeRes();
152
            $t->data['available_times'] = $statrule->availableFileSlots($timeres);
153
        }
154
155
156
        $t->data['results'] = $dataset->getResults();
157
        $t->data['summaryDataset'] = $dataset->getSummary();
158
        $t->data['debugdata'] = $dataset->getDebugData();
159
        $t->data['topdelimiters'] = $dataset->getTopDelimiters();
160
        $t->data['availdelimiters'] = $dataset->availDelimiters();
161
        $t->data['available_times_prev'] = $timeNavigation['prev'];
162
        $t->data['available_times_next'] = $timeNavigation['next'];
163
        $t->data['selected_rule'] = $rule;
164
        $t->data['selected_time'] = $fileslot;
165
        $t->data['selected_timeres'] = $timeres;
166
        $t->data['post_d'] = $this->getBaseURL($t, 'post', 'd');
167
168
        $dimx = $this->moduleConfig->getOptionalValue('dimension.x', 800);
169
        $dimy = $this->moduleConfig->getOptionalValue('dimension.y', 350);
170
        $grapher = new Graph\GoogleCharts($dimx, $dimy);
171
        $t->data['imgurl'] = $grapher->show($axis['axis'], $axis['axispos'], $datasets, $maxes);
172
173
        if (isset($preferRule2)) {
174
            try {
175
                $dataset2 = $statrule->getDataset($preferTimeRes, $preferTime);
176
                $dataset2->aggregateSummary();
177
                $dataset2->calculateMax();
178
                $datasets[] = $dataset2->getPercentValues();
179
                $maxes[] = $dataset2->getMax();
180
181
                if ($request->query->get('format') === 'csv') {
182
                    header('Content-type: text/csv');
183
                    header('Content-Disposition: attachment; filename="simplesamlphp-data.csv"');
184
                    $data = $dataset->getDebugData();
185
                    foreach ($data as $de) {
186
                        if (isset($de[1])) {
187
                            echo '"' . $de[0] . '",' . $de[1] . "\n";
188
                        }
189
                    }
190
                    exit;
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return SimpleSAML\XHTML\Template. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
191
                } else {
192
                    $t->data['error'] = 'Export format not supported';
193
                    return $t;
194
                }
195
            } catch (Exception $e) {
196
                $t->data['error'] = "No data available to compare";
197
                return $t;
198
            }
199
        }
200
201
        if (!empty($piedata)) {
202
            $t->data['pieimgurl'] = $grapher->showPie($dataset->getDelimiterPresentationPie(), $piedata);
203
        }
204
205
        $t->data['selected_rule2'] = $preferRule2;
206
        $t->data['selected_delimiter'] = $delimiter;
207
        $t->data['post_rule2'] = $this->getBaseURL($t, 'post', 'rule2');
208
        $t->data['get_times_prev'] = $this->getBaseURL($t, 'get', 'time', $t->data['available_times_prev']);
209
        $t->data['get_times_next'] = $this->getBaseURL($t, 'get', 'time', $t->data['available_times_next']);
210
        $t->data['delimiterPresentation'] = $dataset->getDelimiterPresentation();
211
212
        return $t;
213
    }
214
215
216
    /**
217
     * @param \SimpleSAML\XHTML\Template $t
218
     * @param string $type
219
     * @param string|null $key
220
     * @param string|null $value
221
     * @return string|array
222
     */
223
    private function getBaseURL(Template $t, string $type = 'get', ?string $key = null, ?string $value = null)
224
    {
225
        $vars = [
226
            'rule' => $t->data['selected_rule'],
227
            'time' => $t->data['selected_time'],
228
            'res' => $t->data['selected_timeres'],
229
        ];
230
        if (isset($t->data['selected_delimiter'])) {
231
            $vars['d'] = $t->data['selected_delimiter'];
232
        }
233
        if (!empty($t->data['selected_rule2']) && $t->data['selected_rule2'] !== '_') {
234
            $vars['rule2'] = $t->data['selected_rule2'];
235
        }
236
        if (isset($key)) {
237
            if (isset($vars[$key])) {
238
                unset($vars[$key]);
239
            }
240
            if (isset($value)) {
241
                $vars[$key] = $value;
242
            }
243
        }
244
        if ($type === 'get') {
245
            return Module::getModuleURL("statistics/") . '?' . http_build_query($vars, '', '&');
246
        }
247
        return $vars;
248
    }
249
}
250