Passed
Pull Request — master (#1197)
by Osma
04:15
created

WebController::invokeGlobalSearch()   C

Complexity

Conditions 13
Paths 176

Size

Total Lines 79
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 13
eloc 57
c 2
b 0
f 0
nc 176
nop 1
dl 0
loc 79
rs 5.9833

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Importing the dependencies.
5
 */
6
use \Punic\Language;
7
8
/**
9
 * WebController is an extension of the Controller that handles all
10
 * the requests originating from the view of the website.
11
 */
12
class WebController extends Controller
13
{
14
    /**
15
     * Provides access to the templating engine.
16
     * @property object $twig the twig templating engine.
17
     */
18
    public $twig;
19
    public $honeypot;
20
21
    /**
22
     * Constructor for the WebController.
23
     * @param Model $model
24
     */
25
    public function __construct($model)
26
    {
27
        parent::__construct($model);
28
29
        // initialize Twig templates
30
        $tmpDir = $model->getConfig()->getTemplateCache();
31
32
        // check if the cache pointed by config.ttl exists, if not we create it.
33
        if (!file_exists($tmpDir)) {
34
            mkdir($tmpDir);
35
        }
36
37
        // specify where to look for templates and cache
38
        $loader = new Twig_Loader_Filesystem('view');
0 ignored issues
show
Deprecated Code introduced by
The class Twig_Loader_Filesystem has been deprecated: since Twig 2.7, use "Twig\Loader\FilesystemLoader" instead ( Ignorable by Annotation )

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

38
        $loader = /** @scrutinizer ignore-deprecated */ new Twig_Loader_Filesystem('view');
Loading history...
39
        // initialize Twig environment
40
        $this->twig = new Twig_Environment($loader, array('cache' => $tmpDir,'auto_reload' => true));
0 ignored issues
show
Deprecated Code introduced by
The class Twig_Environment has been deprecated: since Twig 2.7, use "Twig\Environment" instead ( Ignorable by Annotation )

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

40
        $this->twig = /** @scrutinizer ignore-deprecated */ new Twig_Environment($loader, array('cache' => $tmpDir,'auto_reload' => true));
Loading history...
41
        $this->twig->addExtension(new Twig_Extensions_Extension_I18n());
42
        // used for setting the base href for the relative urls
43
        $this->twig->addGlobal("BaseHref", $this->getBaseHref());
44
        // setting the service name string from the config.ttl
45
        $this->twig->addGlobal("ServiceName", $this->model->getConfig()->getServiceName());
46
47
        // setting the service custom css file from the config.ttl
48
        if ($this->model->getConfig()->getCustomCss() !== null) {
0 ignored issues
show
introduced by
The condition $this->model->getConfig(...getCustomCss() !== null is always true.
Loading history...
49
            $this->twig->addGlobal("ServiceCustomCss", $this->model->getConfig()->getCustomCss());
50
        }
51
        // used for displaying the ui language selection as a dropdown
52
        if ($this->model->getConfig()->getUiLanguageDropdown() !== null) {
0 ignored issues
show
introduced by
The condition $this->model->getConfig(...uageDropdown() !== null is always true.
Loading history...
53
            $this->twig->addGlobal("LanguageDropdown", $this->model->getConfig()->getUiLanguageDropdown());
54
        }
55
56
        // setting the list of properties to be displayed in the search results
57
        $this->twig->addGlobal("PreferredProperties", array('skos:prefLabel', 'skos:narrower', 'skos:broader', 'skosmos:memberOf', 'skos:altLabel', 'skos:related'));
58
59
        // register a Twig filter for generating URLs for vocabulary resources (concepts and groups)
60
        $this->twig->addFilter(new Twig_SimpleFilter('link_url', array($this, 'linkUrlFilter')));
0 ignored issues
show
Deprecated Code introduced by
The class Twig_SimpleFilter has been deprecated: since Twig 2.7, use "Twig\TwigFilter" instead ( Ignorable by Annotation )

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

60
        $this->twig->addFilter(/** @scrutinizer ignore-deprecated */ new Twig_SimpleFilter('link_url', array($this, 'linkUrlFilter')));
Loading history...
61
62
        // register a Twig filter for generating strings from language codes with CLDR
63
        $langFilter = new Twig_SimpleFilter('lang_name', function ($langcode, $lang) {
0 ignored issues
show
Deprecated Code introduced by
The class Twig_SimpleFilter has been deprecated: since Twig 2.7, use "Twig\TwigFilter" instead ( Ignorable by Annotation )

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

63
        $langFilter = /** @scrutinizer ignore-deprecated */ new Twig_SimpleFilter('lang_name', function ($langcode, $lang) {
Loading history...
64
            return Language::getName($langcode, $lang);
65
        });
66
        $this->twig->addFilter($langFilter);
67
68
        // create the honeypot
69
        $this->honeypot = new \Honeypot();
70
        if (!$this->model->getConfig()->getHoneypotEnabled()) {
71
            $this->honeypot->disable();
72
        }
73
        $this->twig->addGlobal('honeypot', $this->honeypot);
74
    }
75
76
    /**
77
     * Guess the language of the user. Return a language string that is one
78
     * of the supported languages defined in the $LANGUAGES setting, e.g. "fi".
79
     * @param string $vocid identifier for the vocabulary eg. 'yso'.
80
     * @return string returns the language choice as a numeric string value
81
     */
82
    public function guessLanguage($vocid = null)
83
    {
84
        // 1. select language based on SKOSMOS_LANGUAGE cookie
85
        if (filter_input(INPUT_COOKIE, 'SKOSMOS_LANGUAGE', FILTER_SANITIZE_STRING)) {
86
            return filter_input(INPUT_COOKIE, 'SKOSMOS_LANGUAGE', FILTER_SANITIZE_STRING);
87
        }
88
89
        // 2. if vocabulary given, select based on the default language of the vocabulary
90
        if ($vocid !== null && $vocid !== '') {
91
            try {
92
                $vocab = $this->model->getVocabulary($vocid);
93
                return $vocab->getConfig()->getDefaultLanguage();
94
            } catch (Exception $e) {
95
                // vocabulary id not found, move on to the next selection method
96
            }
97
        }
98
99
        // 3. select language based on Accept-Language header
100
        header('Vary: Accept-Language'); // inform caches that a decision was made based on Accept header
101
        $this->negotiator = new \Negotiation\LanguageNegotiator();
0 ignored issues
show
Bug introduced by
The type Negotiation\LanguageNegotiator 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...
102
        $langcodes = array_keys($this->languages);
103
        // using a random language from the configured UI languages when there is no accept language header set
104
        $acceptLanguage = filter_input(INPUT_SERVER, 'HTTP_ACCEPT_LANGUAGE', FILTER_SANITIZE_STRING) ? filter_input(INPUT_SERVER, 'HTTP_ACCEPT_LANGUAGE', FILTER_SANITIZE_STRING) : $langcodes[0];
105
        $bestLang = $this->negotiator->getBest($acceptLanguage, $langcodes);
106
        if (isset($bestLang) && in_array($bestLang, $langcodes)) {
107
            return $bestLang->getValue();
108
        }
109
110
        // show default site or prompt for language
111
        return $langcodes[0];
112
    }
113
114
    /**
115
     * Determines a css class that controls width and positioning of the vocabulary list element.
116
     * The layout is wider if the left/right box templates have not been provided.
117
     * @return string css class for the container eg. 'voclist-wide' or 'voclist-right'
118
     */
119
    private function listStyle() {
120
        $left = file_exists('view/left.inc');
121
        $right = file_exists('view/right.inc');
122
        $ret = 'voclist';
123
        if (!$left && !$right) {
124
            $ret .= '-wide';
125
        } else if (!($left && $right) && ($right || $left)) {
126
            $ret .= ($right) ? '-left' : '-right';
127
        }
128
        return $ret;
129
    }
130
131
    /**
132
     * Loads and renders the view containing all the vocabularies.
133
     * @param Request $request
134
     */
135
    public function invokeVocabularies($request)
136
    {
137
        // set language parameters for gettext
138
        $this->setLanguageProperties($request->getLang());
139
        // load template
140
        $template = $this->twig->loadTemplate('light.twig');
141
        // set template variables
142
        $categoryLabel = $this->model->getClassificationLabel($request->getLang());
143
        $sortedVocabs = $this->model->getVocabularyList(false, true);
144
        $langList = $this->model->getLanguages($request->getLang());
145
        $listStyle = $this->listStyle();
146
147
        // render template
148
        echo $template->render(
149
            array(
150
                'sorted_vocabs' => $sortedVocabs,
151
                'category_label' => $categoryLabel,
152
                'languages' => $this->languages,
153
                'lang_list' => $langList,
154
                'request' => $request,
155
                'list_style' => $listStyle
156
            ));
157
    }
158
159
    /**
160
     * Invokes the concept page of a single concept in a specific vocabulary.
161
     *
162
     * @param Request $request
163
     */
164
    public function invokeVocabularyConcept(Request $request)
165
    {
166
        $lang = $request->getLang();
167
        $this->setLanguageProperties($lang);
168
        $vocab = $request->getVocab();
169
170
        $langcodes = $vocab->getConfig()->getShowLangCodes();
171
        $uri = $vocab->getConceptURI($request->getUri()); // make sure it's a full URI
172
173
        $results = $vocab->getConceptInfo($uri, $request->getContentLang());
174
        if (!$results) {
0 ignored issues
show
introduced by
$results is a non-empty array, thus ! $results is always false.
Loading history...
Bug Best Practice introduced by
The expression $results of type Concept[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
175
            $this->invokeGenericErrorPage($request);
176
            return;
177
        }
178
        if ($this->notModified($results[0])) {
179
            return;
180
        }
181
        $pluginParameters = $vocab->getConfig()->getPluginParameters();
182
        $template = (in_array('skos:Concept', $results[0]->getType()) || in_array('skos:ConceptScheme', $results[0]->getType())) ? $this->twig->loadTemplate('concept-info.twig') : $this->twig->loadTemplate('group-contents.twig');
183
184
        $crumbs = $vocab->getBreadCrumbs($request->getContentLang(), $uri);
185
        echo $template->render(array(
186
            'search_results' => $results,
187
            'vocab' => $vocab,
188
            'concept_uri' => $uri,
189
            'languages' => $this->languages,
190
            'explicit_langcodes' => $langcodes,
191
            'bread_crumbs' => $crumbs['breadcrumbs'],
192
            'combined' => $crumbs['combined'],
193
            'request' => $request,
194
            'plugin_params' => $pluginParameters)
195
        );
196
    }
197
198
    /**
199
     * Invokes the feedback page with information of the users current vocabulary.
200
     */
201
    public function invokeFeedbackForm($request)
202
    {
203
        $template = $this->twig->loadTemplate('feedback.twig');
204
        $this->setLanguageProperties($request->getLang());
205
        $vocabList = $this->model->getVocabularyList(false);
206
        $vocab = $request->getVocab();
207
208
        $feedbackSent = false;
209
        if ($request->getQueryParamPOST('message')) {
210
            $feedbackSent = true;
211
            $feedbackMsg = $request->getQueryParamPOST('message');
212
            $feedbackName = $request->getQueryParamPOST('name');
213
            $feedbackEmail = $request->getQueryParamPOST('email');
214
            $msgSubject = $request->getQueryParamPOST('msgsubject');
215
            $feedbackVocab = $request->getQueryParamPOST('vocab');
216
            $feedbackVocabEmail = ($feedbackVocab !== null && $feedbackVocab !== '') ?
217
                $this->model->getVocabulary($feedbackVocab)->getConfig()->getFeedbackRecipient() : null;
218
            // if the hidden field has been set a value we have found a spam bot
219
            // and we do not actually send the message.
220
            if ($this->honeypot->validateHoneypot($request->getQueryParamPOST('item-description')) &&
221
                $this->honeypot->validateHoneytime($request->getQueryParamPOST('user-captcha'), $this->model->getConfig()->getHoneypotTime())) {
222
                $this->sendFeedback($request, $feedbackMsg, $msgSubject, $feedbackName, $feedbackEmail, $feedbackVocab, $feedbackVocabEmail);
223
            }
224
        }
225
        echo $template->render(
226
            array(
227
                'languages' => $this->languages,
228
                'vocab' => $vocab,
229
                'vocabList' => $vocabList,
230
                'feedback_sent' => $feedbackSent,
231
                'request' => $request,
232
            ));
233
    }
234
235
    private function createFeedbackHeaders($fromName, $fromEmail, $toMail, $sender)
236
    {
237
        $headers = "MIME-Version: 1.0" . "\r\n";
238
        $headers .= "Content-type: text/html; charset=UTF-8" . "\r\n";
239
        if (!empty($toMail)) {
240
            $headers .= "Cc: " . $this->model->getConfig()->getFeedbackAddress() . "\r\n";
241
        }
242
        if (!empty($fromEmail)) {
243
            $headers .= "Reply-To: $fromName <$fromEmail>\r\n";
244
        }
245
        $service = $this->model->getConfig()->getServiceName();
246
        return $headers . "From: $fromName via $service <$sender>";
247
    }
248
249
    /**
250
     * Sends the user entered message through the php's mailer.
251
     * @param string $message content given by user.
252
     * @param string $messageSubject subject line given by user.
253
     * @param string $fromName senders own name.
254
     * @param string $fromEmail senders email address.
255
     * @param string $fromVocab which vocabulary is the feedback related to.
256
     */
257
    public function sendFeedback($request, $message, $messageSubject, $fromName = null, $fromEmail = null, $fromVocab = null, $toMail = null)
258
    {
259
        $toAddress = ($toMail) ? $toMail : $this->model->getConfig()->getFeedbackAddress();
260
        $messageSubject = "[" . $this->model->getConfig()->getServiceName() . "] " . $messageSubject;
261
        if ($fromVocab !== null && $fromVocab !== '') {
262
            $message = 'Feedback from vocab: ' . strtoupper($fromVocab) . "<br />" . $message;
263
        }
264
        $envelopeSender = $this->model->getConfig()->getFeedbackEnvelopeSender();
265
        // determine the sender address of the message
266
        $sender = $this->model->getConfig()->getFeedbackSender();
267
        if (empty($sender)) $sender = $envelopeSender;
268
        if (empty($sender)) $sender = $this->model->getConfig()->getFeedbackAddress();
269
270
        // determine sender name - default to "anonymous user" if not given by user
271
        if (empty($fromName)) $fromName = "anonymous user";
272
        $headers = $this->createFeedbackHeaders($fromName, $fromEmail, $toMail, $sender);
273
        $params = empty($envelopeSender) ? '' : "-f $envelopeSender";
274
        // adding some information about the user for debugging purposes.
275
        $message = $message . "<br /><br /> Debugging information:"
276
            . "<br />Timestamp: " . date(DATE_RFC2822)
277
            . "<br />User agent: " . $request->getServerConstant('HTTP_USER_AGENT')
278
            . "<br />Referer: " . $request->getServerConstant('HTTP_REFERER');
279
280
        try {
281
            mail($toAddress, $messageSubject, $message, $headers, $params);
282
        } catch (Exception $e) {
283
            header("HTTP/1.0 404 Not Found");
284
            $template = $this->twig->loadTemplate('error-page.twig');
285
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
286
                error_log('Caught exception: ' . $e->getMessage());
287
            }
288
289
            echo $template->render(
290
                array(
291
                    'languages' => $this->languages,
292
                ));
293
294
            return;
295
        }
296
    }
297
298
    /**
299
     * Invokes the about page for the Skosmos service.
300
     */
301
    public function invokeAboutPage($request)
302
    {
303
        $template = $this->twig->loadTemplate('about.twig');
304
        $this->setLanguageProperties($request->getLang());
305
        $url = $request->getServerConstant('HTTP_HOST');
306
307
        echo $template->render(
308
            array(
309
                'languages' => $this->languages,
310
                'server_instance' => $url,
311
                'request' => $request,
312
            ));
313
    }
314
315
    /**
316
     * Invokes the search for concepts in all the available ontologies.
317
     */
318
    public function invokeGlobalSearch($request)
319
    {
320
        $lang = $request->getLang();
321
        $template = $this->twig->loadTemplate('vocab-search-listing.twig');
322
        $this->setLanguageProperties($lang);
323
324
        $parameters = new ConceptSearchParameters($request, $this->model->getConfig());
325
326
        $vocabs = $request->getQueryParam('vocabs'); # optional
327
        // convert to vocids array to support multi-vocabulary search
328
        $vocids = ($vocabs !== null && $vocabs !== '') ? explode(' ', $vocabs) : null;
329
        $vocabObjects = array();
330
        if ($vocids) {
331
            foreach($vocids as $vocid) {
332
                try {
333
                    $vocabObjects[] = $this->model->getVocabulary($vocid);
334
                } catch (ValueError $e) {
335
                    // fail fast with an error page if the vocabulary cannot be found
336
                    if ($this->model->getConfig()->getLogCaughtExceptions()) {
337
                        error_log('Caught exception: ' . $e->getMessage());
338
                    }
339
                    header("HTTP/1.0 400 Bad Request");
340
                    $this->invokeGenericErrorPage($request, $e->getMessage());
341
                    return;
342
                }
343
            }
344
        }
345
        $parameters->setVocabularies($vocabObjects);
346
347
        $nondefaultEndpointVocs = array();
348
349
        if (sizeOf($vocabObjects) != 1) {
350
            // global search, either from all (sizeOf($vocabObjects) == 0) or from selected ones
351
            if (empty($vocabObjects)) {
352
                $vocabObjects = $this->model->getVocabularies();
353
            }
354
            $defaultEndpoint = $this->model->getConfig()->getDefaultEndpoint();
355
            foreach($vocabObjects as $voc) {
356
                if ($voc->getEndpoint() !== $defaultEndpoint) {
357
                    $nondefaultEndpointVocs[] = $voc;
358
                }
359
            }
360
        }
361
362
        $counts = null;
363
        $searchResults = null;
364
        $errored = false;
365
366
        try {
367
            $countAndResults = $this->model->searchConceptsAndInfo($parameters);
368
            $counts = $countAndResults['count'];
369
            $searchResults = $countAndResults['results'];
370
        } catch (Exception $e) {
371
            $errored = true;
372
            header("HTTP/1.0 500 Internal Server Error");
373
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
374
                error_log('Caught exception: ' . $e->getMessage());
375
            }
376
        }
377
        $vocabList = $this->model->getVocabularyList();
378
        $sortedVocabs = $this->model->getVocabularyList(false, true);
379
        $langList = $this->model->getLanguages($lang);
380
381
        echo $template->render(
382
            array(
383
                'search_count' => $counts,
384
                'languages' => $this->languages,
385
                'search_results' => $searchResults,
386
                'rest' => $parameters->getOffset()>0,
387
                'global_search' => true,
388
                'search_failed' => $errored,
389
                'skipped_vocabs' => $nondefaultEndpointVocs,
390
                'term' => $request->getQueryParamRaw('q'),
391
                'lang_list' => $langList,
392
                'vocabs' => str_replace(' ', '+', $vocabs),
393
                'vocab_list' => $vocabList,
394
                'sorted_vocabs' => $sortedVocabs,
395
                'request' => $request,
396
                'parameters' => $parameters
397
            ));
398
    }
399
400
    /**
401
     * Invokes the search for a single vocabs concepts.
402
     */
403
    public function invokeVocabularySearch($request)
404
    {
405
        $template = $this->twig->loadTemplate('vocab-search-listing.twig');
406
        $this->setLanguageProperties($request->getLang());
407
        $vocab = $request->getVocab();
408
        $searchResults = null;
409
        try {
410
            $vocabTypes = $this->model->getTypes($request->getVocabid(), $request->getLang());
411
        } catch (Exception $e) {
412
            header("HTTP/1.0 500 Internal Server Error");
413
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
414
                error_log('Caught exception: ' . $e->getMessage());
415
            }
416
417
            echo $template->render(
418
                array(
419
                    'languages' => $this->languages,
420
                    'vocab' => $vocab,
421
                    'request' => $request,
422
                    'search_results' => $searchResults
423
                ));
424
425
            return;
426
        }
427
428
        $langcodes = $vocab->getConfig()->getShowLangCodes();
429
        $parameters = new ConceptSearchParameters($request, $this->model->getConfig());
430
431
        try {
432
            $countAndResults = $this->model->searchConceptsAndInfo($parameters);
433
            $counts = $countAndResults['count'];
434
            $searchResults = $countAndResults['results'];
435
        } catch (Exception $e) {
436
            header("HTTP/1.0 404 Not Found");
437
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
438
                error_log('Caught exception: ' . $e->getMessage());
439
            }
440
441
            echo $template->render(
442
                array(
443
                    'languages' => $this->languages,
444
                    'vocab' => $vocab,
445
                    'term' => $request->getQueryParam('q'),
446
                    'search_results' => $searchResults
447
                ));
448
            return;
449
        }
450
        echo $template->render(
451
            array(
452
                'languages' => $this->languages,
453
                'vocab' => $vocab,
454
                'search_results' => $searchResults,
455
                'search_count' => $counts,
456
                'rest' => $parameters->getOffset()>0,
457
                'limit_parent' => $parameters->getParentLimit(),
458
                'limit_type' =>  $request->getQueryParam('type') ? explode('+', $request->getQueryParam('type')) : null,
459
                'limit_group' => $parameters->getGroupLimit(),
460
                'limit_scheme' =>  $request->getQueryParam('scheme') ? explode('+', $request->getQueryParam('scheme')) : null,
461
                'group_index' => $vocab->listConceptGroups($request->getContentLang()),
462
                'parameters' => $parameters,
463
                'term' => $request->getQueryParamRaw('q'),
464
                'types' => $vocabTypes,
465
                'explicit_langcodes' => $langcodes,
466
                'request' => $request,
467
            ));
468
    }
469
470
    /**
471
     * Invokes the alphabetical listing for a specific vocabulary.
472
     */
473
    public function invokeAlphabeticalIndex($request)
474
    {
475
        $lang = $request->getLang();
476
        $this->setLanguageProperties($lang);
477
        $template = $this->twig->loadTemplate('alphabetical-index.twig');
478
        $vocab = $request->getVocab();
479
480
        $offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
481
        if ($request->getQueryParam('limit')) {
482
            $count = $request->getQueryParam('limit');
483
        } else {
484
            $count = ($offset > 0) ? null : 250;
485
        }
486
487
        $contentLang = $request->getContentLang();
488
489
        $allAtOnce = $vocab->getConfig()->getAlphabeticalFull();
490
        if (!$allAtOnce) {
491
            $letters = $vocab->getAlphabet($contentLang);
492
            $letter = $request->getLetter();
493
            if ($letter === '' && isset($letters[0])) {
494
                $letter = $letters[0];
495
            }
496
            $searchResults = $vocab->searchConceptsAlphabetical($letter, $count, $offset, $contentLang);
497
        } else {
498
            $letters = null;
499
            $searchResults = $vocab->searchConceptsAlphabetical('*', null, null, $contentLang);
500
        }
501
502
        $request->setContentLang($contentLang);
503
504
        echo $template->render(
505
            array(
506
                'languages' => $this->languages,
507
                'vocab' => $vocab,
508
                'alpha_results' => $searchResults,
509
                'letters' => $letters,
510
                'all_letters' => $allAtOnce,
511
                'request' => $request,
512
            ));
513
    }
514
515
    /**
516
     * Invokes the vocabulary group index page template.
517
     * @param boolean $stats set to true to get vocabulary statistics visible.
518
     */
519
    public function invokeGroupIndex($request, $stats = false)
520
    {
521
        $lang = $request->getLang();
522
        $this->setLanguageProperties($lang);
523
        $template = $this->twig->loadTemplate('group-index.twig');
524
        $vocab = $request->getVocab();
525
526
        echo $template->render(
527
            array(
528
                'languages' => $this->languages,
529
                'stats' => $stats,
530
                'vocab' => $vocab,
531
                'request' => $request,
532
            ));
533
    }
534
535
    /**
536
     * Loads and renders the view containing a specific vocabulary.
537
     */
538
    public function invokeVocabularyHome($request)
539
    {
540
        $lang = $request->getLang();
541
        // set language parameters for gettext
542
        $this->setLanguageProperties($lang);
543
        $vocab = $request->getVocab();
544
545
        $defaultView = $vocab->getConfig()->getDefaultSidebarView();
546
        // load template
547
        if ($defaultView === 'groups') {
548
            $this->invokeGroupIndex($request, true);
549
            return;
550
        }
551
        $pluginParameters = $vocab->getConfig()->getPluginParameters();
552
553
        $template = $this->twig->loadTemplate('vocab.twig');
554
555
        echo $template->render(
556
            array(
557
                'languages' => $this->languages,
558
                'vocab' => $vocab,
559
                'search_letter' => 'A',
560
                'active_tab' => $defaultView,
561
                'request' => $request,
562
                'plugin_params' => $pluginParameters
563
            ));
564
    }
565
566
    /**
567
     * Invokes a very generic errorpage.
568
     */
569
    public function invokeGenericErrorPage($request, $message = null)
570
    {
571
        $this->setLanguageProperties($request->getLang());
572
        header("HTTP/1.0 404 Not Found");
573
        $template = $this->twig->loadTemplate('error-page.twig');
574
        echo $template->render(
575
            array(
576
                'languages' => $this->languages,
577
                'request' => $request,
578
                'vocab' => $request->getVocab(),
579
                'message' => $message,
580
                'requested_page' => filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_STRING),
581
            ));
582
    }
583
584
    /**
585
     * Loads and renders the view containing a list of recent changes in the vocabulary.
586
     * @param Request $request
587
     */
588
    public function invokeChangeList($request, $prop='dc:created')
589
    {
590
        $offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
591
        $limit = ($request->getQueryParam('limit') && is_numeric($request->getQueryParam('limit')) && $request->getQueryParam('limit') >= 0) ? $request->getQueryParam('limit') : 200;
592
593
        $changeList = $this->getChangeList($request, $prop, $offset, $limit);
0 ignored issues
show
Bug introduced by
It seems like $limit can also be of type string; however, parameter $limit of WebController::getChangeList() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

593
        $changeList = $this->getChangeList($request, $prop, $offset, /** @scrutinizer ignore-type */ $limit);
Loading history...
Bug introduced by
It seems like $offset can also be of type string; however, parameter $offset of WebController::getChangeList() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

593
        $changeList = $this->getChangeList($request, $prop, /** @scrutinizer ignore-type */ $offset, $limit);
Loading history...
594
        $bydate = $this->formatChangeList($changeList, $request->getLang());
595
596
        // load template
597
        $template = $this->twig->loadTemplate('changes.twig');
598
599
        // render template
600
        echo $template->render(
601
            array(
602
                'vocab' => $request->getVocab(),
603
                'languages' => $this->languages,
604
                'request' => $request,
605
                'changeList' => $bydate)
606
            );
607
    }
608
    /**
609
     * Gets the list of newest concepts for a vocabulary according to timestamp indicated by a property
610
     * @param Request $request
611
     * @param string $prop the name of the property eg. 'dc:modified'.
612
     * @param int $offset starting index offset
613
     * @param int $limit maximum number of concepts to return
614
     * @return Array list of concepts
615
     */
616
    public function getChangeList($request, $prop, $offset=0, $limit=200)
617
    {
618
        // set language parameters for gettext
619
        $this->setLanguageProperties($request->getLang());
620
621
        return $request->getVocab()->getChangeList($prop, $request->getContentLang(), $offset, $limit);
622
    }
623
624
    /**
625
     * Formats the list of concepts as labels arranged by modification month
626
     * @param Array $changeList
627
     * @param string $lang the language for displaying dates in the change list
628
     * @return array list of concepts as labels by month
629
     */
630
    public function formatChangeList($changeList, $lang)
631
    {
632
        $formatByDate = array();
633
        foreach($changeList as $concept) {
634
            $concept['datestring'] = Punic\Calendar::formatDate($concept['date'], 'medium', $lang);
635
            $formatByDate[Punic\Calendar::getMonthName($concept['date'], 'wide', $lang, true) . Punic\Calendar::format($concept['date'], ' y', $lang) ][strtolower($concept['prefLabel'])] = $concept;
636
        }
637
        return $formatByDate;
638
    }
639
640
}
641