Passed
Push — main ( 916bc5...9b27db )
by Osma
03:31 queued 14s
created

GlobalConfig   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 378
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 55
eloc 91
dl 0
loc 378
rs 6
c 0
b 0
f 0

33 Methods

Rating   Name   Duplication   Size   Complexity  
A getDefaultEndpoint() 0 9 3
A getConfigModifiedTime() 0 3 1
A getCache() 0 3 1
A getFeedbackAddress() 0 3 1
A getSearchResultsSize() 0 3 1
A getFeedbackSender() 0 3 1
A getTemplateCache() 0 3 1
A getGraph() 0 3 1
A getLoggingFilename() 0 3 1
A getLogCaughtExceptions() 0 3 1
A getDefaultTransitiveLimit() 0 3 1
A getLanguages() 0 17 6
A initializeNamespaces() 0 5 4
A getLoggingBrowserConsole() 0 3 1
A getFeedbackEnvelopeSender() 0 3 1
A __construct() 0 9 2
B initializeConfig() 0 30 9
A getServiceName() 0 3 1
A getSparqlTimeout() 0 3 1
A getHttpTimeout() 0 3 1
A parseConfig() 0 6 1
A getDefaultSparqlDialect() 0 3 1
A getServiceNameLong() 0 10 2
A getBaseHref() 0 3 1
A getUiLanguageDropdown() 0 3 1
A getCustomCss() 0 3 1
A getServiceDescription() 0 3 1
A getGlobalPlugins() 0 10 3
A getCollationEnabled() 0 3 1
A getHoneypotEnabled() 0 3 1
A getAboutDescription() 0 3 1
A getHoneypotTime() 0 3 1
A getFeedbackDescription() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like GlobalConfig often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use GlobalConfig, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Setting some often needed namespace prefixes
5
 */
6
EasyRdf\RdfNamespace::set('skosmos', 'http://purl.org/net/skosmos#');
7
EasyRdf\RdfNamespace::set('skosext', 'http://purl.org/finnonto/schema/skosext#');
8
EasyRdf\RdfNamespace::delete('geo');
9
EasyRdf\RdfNamespace::set('wgs84', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
10
EasyRdf\RdfNamespace::set('isothes', 'http://purl.org/iso25964/skos-thes#');
11
EasyRdf\RdfNamespace::set('mads', 'http://www.loc.gov/mads/rdf/v1#');
12
EasyRdf\RdfNamespace::set('wd', 'http://www.wikidata.org/entity/');
13
EasyRdf\RdfNamespace::set('wdt', 'http://www.wikidata.org/prop/direct/');
14
15
/**
16
 * GlobalConfig provides access to the Skosmos configuration in config.ttl.
17
 */
18
class GlobalConfig extends BaseConfig
19
{
20
    /** Cache reference */
21
    private $cache;
22
    /** Location of the configuration file. Used for caching. */
23
    private $filePath;
24
    /** Namespaces from vocabularies configuration file. */
25
    private $namespaces;
26
    /** EasyRdf\Graph graph */
27
    private $graph;
28
    /**
29
     * @var int the time the config file was last modified
30
     */
31
    private $configModifiedTime = null;
32
33
    public function __construct(Model $model, string $config_name='../../config.ttl')
34
    {
35
        $this->cache = new Cache();
36
        $this->filePath = realpath(dirname(__FILE__) . "/" . $config_name);
37
        if (!file_exists($this->filePath)) {
38
            throw new Exception('config.ttl file is missing, please provide one.');
39
        }
40
        $resource = $this->initializeConfig();
41
        parent::__construct($model, $resource);
42
    }
43
44
    public function getCache()
45
    {
46
        return $this->cache;
47
    }
48
49
    /**
50
     * @return int the time the config file was last modified
51
     */
52
    public function getConfigModifiedTime()
53
    {
54
        return $this->configModifiedTime;
55
    }
56
57
    /**
58
     * Initialize configuration, reading the configuration file from the disk,
59
     * and creating the graph and resources objects. Uses a cache if available,
60
     * in order to avoid re-loading the complete configuration on each request.
61
     */
62
    private function initializeConfig(): EasyRdf\Resource
63
    {
64
        // retrieve last modified time for config file (filemtime returns int|bool!)
65
        $configModifiedTime = filemtime($this->filePath);
66
        if (!is_bool($configModifiedTime)) {
0 ignored issues
show
introduced by
The condition is_bool($configModifiedTime) is always false.
Loading history...
67
            $this->configModifiedTime = $configModifiedTime;
68
        }
69
        // use APC user cache to store parsed config.ttl configuration
70
        if ($this->cache->isAvailable() && !is_null($this->configModifiedTime)) {
71
            // @codeCoverageIgnoreStart
72
            $key = realpath($this->filePath) . ", " . $this->configModifiedTime;
73
            $nskey = "namespaces of " . $key;
74
            $this->graph = $this->cache->fetch($key);
75
            $this->namespaces = $this->cache->fetch($nskey);
76
            if ($this->graph === false || $this->namespaces === false) { // was not found in cache
77
                $this->parseConfig($this->filePath);
78
                $this->cache->store($key, $this->graph);
79
                $this->cache->store($nskey, $this->namespaces);
80
            }
81
        // @codeCoverageIgnoreEnd
82
        } else { // APC not available, parse on every request
83
            $this->parseConfig($this->filePath);
84
        }
85
        $this->initializeNamespaces();
86
87
        $configResources = $this->graph->allOfType("skosmos:Configuration");
88
        if (is_null($configResources) || !is_array($configResources) || count($configResources) !== 1) {
0 ignored issues
show
introduced by
The condition is_array($configResources) is always true.
Loading history...
89
            throw new Exception("config.ttl must have exactly one skosmos:Configuration");
90
        }
91
        return $configResources[0];
92
    }
93
94
    /**
95
     * Parses configuration from the config.ttl file
96
     * @param string $filename path to config.ttl file
97
     * @throws \EasyRdf\Exception
98
     */
99
    private function parseConfig($filename)
100
    {
101
        $this->graph = new EasyRdf\Graph();
102
        $parser = new SkosmosTurtleParser();
103
        $parser->parse($this->graph, file_get_contents($filename), 'turtle', $filename);
104
        $this->namespaces = $parser->getNamespaces();
105
    }
106
107
    /**
108
     * Returns the graph created after parsing the configuration file.
109
     * @return \EasyRdf\Graph
110
     */
111
    public function getGraph()
112
    {
113
        return $this->graph;
114
    }
115
116
    /**
117
     * Registers RDF namespaces from the config.ttl file for use by EasyRdf (e.g. serializing)
118
     */
119
    private function initializeNamespaces()
120
    {
121
        foreach ($this->namespaces as $prefix => $fullUri) {
122
            if ($prefix != '' && EasyRdf\RdfNamespace::get($prefix) === null) { // if not already defined
123
                EasyRdf\RdfNamespace::set($prefix, $fullUri);
124
            }
125
        }
126
    }
127
128
    /**
129
     * Returns the UI languages specified in the configuration or defaults to
130
     * only show English
131
     * @return array
132
     */
133
    public function getLanguages()
134
    {
135
        $languageResources = $this->getResource()->getResource('skosmos:languages');
136
        if (!is_null($languageResources) && !empty($languageResources)) {
137
            $languages = array();
138
            foreach ($languageResources as $languageResource) {
139
                /** @var \EasyRdf\Literal $languageName */
140
                $languageName = $languageResource->getLiteral('rdfs:label');
141
                /** @var \EasyRdf\Literal $languageValue */
142
                $languageValue = $languageResource->getLiteral('rdf:value');
143
                if ($languageName && $languageValue) {
144
                    $languages[$languageName->getValue()] = $languageValue->getValue();
145
                }
146
            }
147
            return $languages;
148
        } else {
149
            return array('en' => 'en_GB.utf8');
150
        }
151
    }
152
153
    /**
154
     * Returns the external HTTP request timeout in seconds or the default value
155
     * of 5 seconds if not specified in the configuration.
156
     * @return integer
157
     */
158
    public function getHttpTimeout()
159
    {
160
        return $this->getLiteral('skosmos:httpTimeout', 5);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getLiteral...kosmos:httpTimeout', 5) returns the type string which is incompatible with the documented return type integer.
Loading history...
161
    }
162
163
    /**
164
     * Returns the SPARQL HTTP request timeout in seconds or the default value
165
     * of 20 seconds if not specified in the configuration.
166
     * @return integer
167
     */
168
    public function getSparqlTimeout()
169
    {
170
        return $this->getLiteral('skosmos:sparqlTimeout', 20);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getLiteral...mos:sparqlTimeout', 20) returns the type string which is incompatible with the documented return type integer.
Loading history...
171
    }
172
173
    /**
174
     * Returns the sparql endpoint address defined in the configuration. If
175
     * not then defaulting to http://localhost:3030/ds/sparql
176
     * @return string
177
     */
178
    public function getDefaultEndpoint()
179
    {
180
        $endpoint = $this->resource->get('skosmos:sparqlEndpoint');
181
        if ($endpoint) {
182
            return $endpoint->getUri();
183
        } elseif (getenv('SKOSMOS_SPARQL_ENDPOINT')) {
184
            return getenv('SKOSMOS_SPARQL_ENDPOINT');
185
        } else {
186
            return 'http://localhost:3030/ds/sparql';
187
        }
188
    }
189
190
    /**
191
     * Returns the maximum number of items to return in transitive queries if defined
192
     * in the configuration or the default value of 1000.
193
     * @return integer
194
     */
195
    public function getDefaultTransitiveLimit()
196
    {
197
        return $this->getLiteral('skosmos:transitiveLimit', 1000);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getLiteral...transitiveLimit', 1000) returns the type string which is incompatible with the documented return type integer.
Loading history...
198
    }
199
200
    /**
201
     * Returns the maximum number of items to load at a time if defined
202
     * in the configuration or the default value of 20.
203
     * @return integer
204
     */
205
    public function getSearchResultsSize()
206
    {
207
        return $this->getLiteral('skosmos:searchResultsSize', 20);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getLiteral...searchResultsSize', 20) returns the type string which is incompatible with the documented return type integer.
Loading history...
208
    }
209
210
    /**
211
     * Returns the configured location for the twig template cache and if not
212
     * defined defaults to "/tmp/skosmos-template-cache"
213
     * @return string
214
     */
215
    public function getTemplateCache()
216
    {
217
        return $this->getLiteral('skosmos:templateCache', '/tmp/skosmos-template-cache');
218
    }
219
220
    /**
221
     * Returns the defined sparql-query extension eg. "JenaText" or
222
     * if not defined falling back to SPARQL 1.1
223
     * @return string
224
     */
225
    public function getDefaultSparqlDialect()
226
    {
227
        return $this->getLiteral('skosmos:sparqlDialect', 'Generic');
228
    }
229
230
    /**
231
     * Returns the feedback address defined in the configuration.
232
     * @return string
233
     */
234
    public function getFeedbackAddress()
235
    {
236
        return $this->getLiteral('skosmos:feedbackAddress', null);
237
    }
238
239
    /**
240
     * Returns the feedback sender address defined in the configuration.
241
     * @return string
242
     */
243
    public function getFeedbackSender()
244
    {
245
        return $this->getLiteral('skosmos:feedbackSender', null);
246
    }
247
248
    /**
249
     * Returns the feedback envelope sender address defined in the configuration.
250
     * @return string
251
     */
252
    public function getFeedbackEnvelopeSender()
253
    {
254
        return $this->getLiteral('skosmos:feedbackEnvelopeSender', null);
255
    }
256
257
    /**
258
     * Returns true if exception logging has been configured.
259
     * @return boolean
260
     */
261
    public function getLogCaughtExceptions()
262
    {
263
        return $this->getBoolean('skosmos:logCaughtExceptions', false);
264
    }
265
266
    /**
267
     * Returns true if browser console logging has been enabled,
268
     * @return boolean
269
     */
270
    public function getLoggingBrowserConsole()
271
    {
272
        return $this->getBoolean('skosmos:logBrowserConsole', false);
273
    }
274
275
    /**
276
     * Returns the name of a log file if configured, or NULL otherwise.
277
     * @return string
278
     */
279
    public function getLoggingFilename()
280
    {
281
        return $this->getLiteral('skosmos:logFileName', null);
282
    }
283
284
    /**
285
     * @return string
286
     */
287
    public function getServiceName()
288
    {
289
        return $this->getLiteral('skosmos:serviceName', 'Skosmos');
290
    }
291
292
    /**
293
     * Returns the long version of the service name in the requested language.
294
     * @return string the long name of the service
295
     */
296
    public function getServiceNameLong($lang)
297
    {
298
        $val = $this->getLiteral('skosmos:serviceNameLong', false, $lang);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $default of BaseConfig::getLiteral(). ( Ignorable by Annotation )

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

298
        $val = $this->getLiteral('skosmos:serviceNameLong', /** @scrutinizer ignore-type */ false, $lang);
Loading history...
299
300
        if ($val === false) {
0 ignored issues
show
introduced by
The condition $val === false is always false.
Loading history...
301
            // fall back to short service name if not configured
302
            return $this->getServiceName();
303
        }
304
305
        return $val;
306
    }
307
308
    /**
309
     * Returns the service description in the requested language.
310
     * @return string the description of the service
311
     */
312
    public function getServiceDescription($lang)
313
    {
314
        return $this->getLiteral('skosmos:serviceDescription', null, $lang);
315
    }
316
317
    /**
318
     * Returns the feedback page description in the requested language.
319
     * @return string the description of the feedback page
320
     */
321
    public function getFeedbackDescription($lang)
322
    {
323
        return $this->getLiteral('skosmos:feedbackDescription', null, $lang);
324
    }
325
326
    /**
327
     * Returns the about page description in the requested language.
328
     * @return string the description of the about page
329
     */
330
    public function getAboutDescription($lang)
331
    {
332
        return $this->getLiteral('skosmos:aboutDescription', null, $lang);
333
    }
334
335
    /**
336
     * @return string
337
     */
338
    public function getCustomCss()
339
    {
340
        return $this->getLiteral('skosmos:customCss', null);
341
    }
342
343
    /**
344
     * @return boolean
345
     */
346
    public function getUiLanguageDropdown()
347
    {
348
        return $this->getBoolean('skosmos:uiLanguageDropdown', false);
349
    }
350
351
    /**
352
     * @return string
353
     */
354
    public function getBaseHref()
355
    {
356
        return $this->getLiteral('skosmos:baseHref', null);
357
    }
358
359
    /**
360
     * @return array
361
     */
362
    public function getGlobalPlugins()
363
    {
364
        $globalPlugins = array();
365
        $globalPluginsResource =  $this->getResource()->getResource("skosmos:globalPlugins");
366
        if ($globalPluginsResource) {
0 ignored issues
show
introduced by
$globalPluginsResource is of type EasyRdf\Resource, thus it always evaluated to true.
Loading history...
367
            foreach ($globalPluginsResource as $resource) {
368
                $globalPlugins[] = $resource->getValue();
369
            }
370
        }
371
        return $globalPlugins;
372
    }
373
374
    /**
375
     * @return boolean
376
     */
377
    public function getHoneypotEnabled()
378
    {
379
        return $this->getBoolean('skosmos:uiHoneypotEnabled', true);
380
    }
381
382
    /**
383
     * @return integer
384
     */
385
    public function getHoneypotTime()
386
    {
387
        return $this->getLiteral('skosmos:uiHoneypotTime', 5);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getLiteral...mos:uiHoneypotTime', 5) returns the type string which is incompatible with the documented return type integer.
Loading history...
388
    }
389
390
    /**
391
     * @return boolean
392
     */
393
    public function getCollationEnabled()
394
    {
395
        return $this->getBoolean('skosmos:sparqlCollationEnabled', false);
396
    }
397
}
398