WebController::listStyle()   B
last analyzed

Complexity

Conditions 8
Paths 4

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 8
c 0
b 0
f 0
nc 4
nop 0
dl 0
loc 10
rs 8.4444
1
<?php
2
3
/**
4
 * Importing the dependencies.
5
 */
6
use \Punic\Language;
0 ignored issues
show
Bug introduced by
The type \Punic\Language 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...
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
45
        // pass the GlobalConfig object to templates so they can access configuration
46
        $this->twig->addGlobal("GlobalConfig", $this->model->getConfig());
47
48
        // setting the list of properties to be displayed in the search results
49
        $this->twig->addGlobal("PreferredProperties", array('skos:prefLabel', 'skos:narrower', 'skos:broader', 'skosmos:memberOf', 'skos:altLabel', 'skos:related'));
50
51
        // register a Twig filter for generating URLs for vocabulary resources (concepts and groups)
52
        $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

52
        $this->twig->addFilter(/** @scrutinizer ignore-deprecated */ new Twig_SimpleFilter('link_url', array($this, 'linkUrlFilter')));
Loading history...
53
54
        // register a Twig filter for generating strings from language codes with CLDR
55
        $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

55
        $langFilter = /** @scrutinizer ignore-deprecated */ new Twig_SimpleFilter('lang_name', function ($langcode, $lang) {
Loading history...
56
            return Language::getName($langcode, $lang);
57
        });
58
        $this->twig->addFilter($langFilter);
59
60
        // create the honeypot
61
        $this->honeypot = new \Honeypot();
62
        if (!$this->model->getConfig()->getHoneypotEnabled()) {
63
            $this->honeypot->disable();
64
        }
65
        $this->twig->addGlobal('honeypot', $this->honeypot);
66
    }
67
68
    /**
69
     * Guess the language of the user. Return a language string that is one
70
     * of the supported languages defined in the $LANGUAGES setting, e.g. "fi".
71
     * @param Request $request HTTP request
72
     * @param string $vocid identifier for the vocabulary eg. 'yso'.
73
     * @return string returns the language choice as a numeric string value
74
     */
75
    public function guessLanguage($request, $vocid = null)
76
    {
77
        // 1. select language based on SKOSMOS_LANGUAGE cookie
78
        $languageCookie = $request->getCookie('SKOSMOS_LANGUAGE');
79
        if ($languageCookie) {
80
            return $languageCookie;
81
        }
82
83
        // 2. if vocabulary given, select based on the default language of the vocabulary
84
        if ($vocid !== null && $vocid !== '') {
85
            try {
86
                $vocab = $this->model->getVocabulary($vocid);
87
                return $vocab->getConfig()->getDefaultLanguage();
88
            } catch (Exception $e) {
89
                // vocabulary id not found, move on to the next selection method
90
            }
91
        }
92
93
        // 3. select language based on Accept-Language header
94
        header('Vary: Accept-Language'); // inform caches that a decision was made based on Accept header
95
        $this->negotiator = new \Negotiation\LanguageNegotiator();
96
        $langcodes = array_keys($this->languages);
97
        // using a random language from the configured UI languages when there is no accept language header set
98
        $acceptLanguage = $request->getServerConstant('HTTP_ACCEPT_LANGUAGE') ? $request->getServerConstant('HTTP_ACCEPT_LANGUAGE') : $langcodes[0];
99
100
        $bestLang = $this->negotiator->getBest($acceptLanguage, $langcodes);
101
        if (isset($bestLang) && in_array($bestLang->getValue(), $langcodes)) {
102
            return $bestLang->getValue();
103
        }
104
105
        // show default site or prompt for language
106
        return $langcodes[0];
107
    }
108
109
    /**
110
     * Determines a css class that controls width and positioning of the vocabulary list element.
111
     * The layout is wider if the left/right box templates have not been provided.
112
     * @return string css class for the container eg. 'voclist-wide' or 'voclist-right'
113
     */
114
    private function listStyle() {
115
        $left = file_exists('view/left.inc');
116
        $right = file_exists('view/right.inc');
117
        $ret = 'voclist';
118
        if (!$left && !$right) {
119
            $ret .= '-wide';
120
        } else if (!($left && $right) && ($right || $left)) {
121
            $ret .= ($right) ? '-left' : '-right';
122
        }
123
        return $ret;
124
    }
125
126
    /**
127
     * Loads and renders the view containing all the vocabularies.
128
     * @param Request $request
129
     */
130
    public function invokeVocabularies($request)
131
    {
132
        // set language parameters for gettext
133
        $this->setLanguageProperties($request->getLang());
134
        // load template
135
        $template = $this->twig->loadTemplate('landing.twig');
136
        // set template variables
137
        $categoryLabel = $this->model->getClassificationLabel($request->getLang());
138
        $sortedVocabs = $this->model->getVocabularyList(false, true);
139
        $langList = $this->model->getLanguages($request->getLang());
140
        $listStyle = $this->listStyle();
141
142
        // render template
143
        echo $template->render(
144
            array(
145
                'sorted_vocabs' => $sortedVocabs,
146
                'category_label' => $categoryLabel,
147
                'languages' => $this->languages,
148
                'lang_list' => $langList,
149
                'request' => $request,
150
                'list_style' => $listStyle
151
            ));
152
    }
153
154
    /**
155
     * Invokes the concept page of a single concept in a specific vocabulary.
156
     *
157
     * @param Request $request
158
     */
159
    public function invokeVocabularyConcept(Request $request)
160
    {
161
        $lang = $request->getLang();
162
        $this->setLanguageProperties($lang);
163
        $vocab = $request->getVocab();
164
165
        $langcodes = $vocab->getConfig()->getShowLangCodes();
166
        $uri = $vocab->getConceptURI($request->getUri()); // make sure it's a full URI
167
168
        $results = $vocab->getConceptInfo($uri, $request->getContentLang());
169
        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...
170
            $this->invokeGenericErrorPage($request);
171
            return;
172
        }
173
        if ($this->notModified($results[0])) {
174
            return;
175
        }
176
        $customLabels = $vocab->getConfig()->getPropertyLabelOverrides();
177
178
        $pluginParameters = json_encode($vocab->getConfig()->getPluginParameters());
179
        $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');
180
181
        $crumbs = $vocab->getBreadCrumbs($request->getContentLang(), $uri);
182
        echo $template->render(array(
183
            'search_results' => $results,
184
            'vocab' => $vocab,
185
            'concept_uri' => $uri,
186
            'languages' => $this->languages,
187
            'explicit_langcodes' => $langcodes,
188
            'bread_crumbs' => $crumbs['breadcrumbs'],
189
            'combined' => $crumbs['combined'],
190
            'request' => $request,
191
            'plugin_params' => $pluginParameters,
192
            'custom_labels' => $customLabels)
193
        );
194
    }
195
196
    /**
197
     * Invokes the feedback page with information of the users current vocabulary.
198
     */
199
    public function invokeFeedbackForm($request)
200
    {
201
        $template = $this->twig->loadTemplate('feedback.twig');
202
        $this->setLanguageProperties($request->getLang());
203
        $vocabList = $this->model->getVocabularyList(false);
204
        $vocab = $request->getVocab();
205
206
        $feedbackSent = false;
207
        if ($request->getQueryParamPOST('message')) {
208
            $feedbackSent = true;
209
            $feedbackMsg = $request->getQueryParamPOST('message');
210
            $feedbackName = $request->getQueryParamPOST('name', 255);
211
            $feedbackEmail = $request->getQueryParamPOST('email', 255);
212
            $msgSubject = $request->getQueryParamPOST('msgsubject', 255);
213
            $feedbackVocab = $request->getQueryParamPOST('vocab');
214
            $feedbackVocabEmail = ($feedbackVocab !== null && $feedbackVocab !== '') ?
215
                $this->model->getVocabulary($feedbackVocab)->getConfig()->getFeedbackRecipient() : null;
216
            // if the hidden field has been set a value we have found a spam bot
217
            // and we do not actually send the message.
218
            if ($this->honeypot->validateHoneypot($request->getQueryParamPOST('item-description')) &&
219
                $this->honeypot->validateHoneytime($request->getQueryParamPOST('user-captcha'), $this->model->getConfig()->getHoneypotTime())) {
220
                $this->sendFeedback($request, $feedbackMsg, $msgSubject, $feedbackName, $feedbackEmail, $feedbackVocab, $feedbackVocabEmail);
221
            }
222
        }
223
        echo $template->render(
224
            array(
225
                'languages' => $this->languages,
226
                'vocab' => $vocab,
227
                'vocabList' => $vocabList,
228
                'feedback_sent' => $feedbackSent,
229
                'request' => $request,
230
            ));
231
    }
232
233
    private function createFeedbackHeaders($fromName, $fromEmail, $toMail, $sender)
234
    {
235
        $headers = "MIME-Version: 1.0" . "\r\n";
236
        $headers .= "Content-type: text/html; charset=UTF-8" . "\r\n";
237
        if (!empty($toMail)) {
238
            $headers .= "Cc: " . $this->model->getConfig()->getFeedbackAddress() . "\r\n";
239
        }
240
        if (!empty($fromEmail)) {
241
            $headers .= "Reply-To: $fromName <$fromEmail>\r\n";
242
        }
243
        $service = $this->model->getConfig()->getServiceName();
244
        return $headers . "From: $fromName via $service <$sender>";
245
    }
246
247
    /**
248
     * Sends the user entered message through the php's mailer.
249
     * @param string $message content given by user.
250
     * @param string $messageSubject subject line given by user.
251
     * @param string $fromName senders own name.
252
     * @param string $fromEmail senders email address.
253
     * @param string $fromVocab which vocabulary is the feedback related to.
254
     */
255
    public function sendFeedback($request, $message, $messageSubject, $fromName = null, $fromEmail = null, $fromVocab = null, $toMail = null)
256
    {
257
        $toAddress = ($toMail) ? $toMail : $this->model->getConfig()->getFeedbackAddress();
258
        $messageSubject = "[" . $this->model->getConfig()->getServiceName() . "] " . $messageSubject;
259
        if ($fromVocab !== null && $fromVocab !== '') {
260
            $message = 'Feedback from vocab: ' . strtoupper($fromVocab) . "<br />" . $message;
261
        }
262
        $envelopeSender = $this->model->getConfig()->getFeedbackEnvelopeSender();
263
        // determine the sender address of the message
264
        $sender = $this->model->getConfig()->getFeedbackSender();
265
        if (empty($sender)) $sender = $envelopeSender;
266
        if (empty($sender)) $sender = $this->model->getConfig()->getFeedbackAddress();
267
268
        // determine sender name - default to "anonymous user" if not given by user
269
        if (empty($fromName)) $fromName = "anonymous user";
270
        $headers = $this->createFeedbackHeaders($fromName, $fromEmail, $toMail, $sender);
271
        $params = empty($envelopeSender) ? '' : "-f $envelopeSender";
272
        // adding some information about the user for debugging purposes.
273
        $message = $message . "<br /><br /> Debugging information:"
274
            . "<br />Timestamp: " . date(DATE_RFC2822)
275
            . "<br />User agent: " . $request->getServerConstant('HTTP_USER_AGENT')
276
            . "<br />Referer: " . $request->getServerConstant('HTTP_REFERER');
277
278
        try {
279
            mail($toAddress, $messageSubject, $message, $headers, $params);
280
        } catch (Exception $e) {
281
            header("HTTP/1.0 404 Not Found");
282
            $template = $this->twig->loadTemplate('error-page.twig');
283
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
284
                error_log('Caught exception: ' . $e->getMessage());
285
            }
286
287
            echo $template->render(
288
                array(
289
                    'languages' => $this->languages,
290
                ));
291
292
            return;
293
        }
294
    }
295
296
    /**
297
     * Invokes the about page for the Skosmos service.
298
     */
299
    public function invokeAboutPage($request)
300
    {
301
        $template = $this->twig->loadTemplate('about.twig');
302
        $this->setLanguageProperties($request->getLang());
303
        $url = $request->getServerConstant('HTTP_HOST');
304
305
        echo $template->render(
306
            array(
307
                'languages' => $this->languages,
308
                'server_instance' => $url,
309
                'request' => $request,
310
            ));
311
    }
312
313
    /**
314
     * Invokes the search for concepts in all the available ontologies.
315
     */
316
    public function invokeGlobalSearch($request)
317
    {
318
        $lang = $request->getLang();
319
        $template = $this->twig->loadTemplate('vocab-search-listing.twig');
320
        $this->setLanguageProperties($lang);
321
322
        $parameters = new ConceptSearchParameters($request, $this->model->getConfig());
323
324
        $vocabs = $request->getQueryParam('vocabs'); # optional
325
        // convert to vocids array to support multi-vocabulary search
326
        $vocids = ($vocabs !== null && $vocabs !== '') ? explode(' ', $vocabs) : null;
327
        $vocabObjects = array();
328
        if ($vocids) {
329
            foreach($vocids as $vocid) {
330
                try {
331
                    $vocabObjects[] = $this->model->getVocabulary($vocid);
332
                } catch (ValueError $e) {
333
                    // fail fast with an error page if the vocabulary cannot be found
334
                    if ($this->model->getConfig()->getLogCaughtExceptions()) {
335
                        error_log('Caught exception: ' . $e->getMessage());
336
                    }
337
                    header("HTTP/1.0 400 Bad Request");
338
                    $this->invokeGenericErrorPage($request, $e->getMessage());
339
                    return;
340
                }
341
            }
342
        }
343
        $parameters->setVocabularies($vocabObjects);
344
345
        $counts = null;
346
        $searchResults = null;
347
        $errored = false;
348
349
        try {
350
            $countAndResults = $this->model->searchConceptsAndInfo($parameters);
351
            $counts = $countAndResults['count'];
352
            $searchResults = $countAndResults['results'];
353
        } catch (Exception $e) {
354
            $errored = true;
355
            header("HTTP/1.0 500 Internal Server Error");
356
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
357
                error_log('Caught exception: ' . $e->getMessage());
358
            }
359
        }
360
        $vocabList = $this->model->getVocabularyList();
361
        $sortedVocabs = $this->model->getVocabularyList(false, true);
362
        $langList = $this->model->getLanguages($lang);
363
364
        echo $template->render(
365
            array(
366
                'search_count' => $counts,
367
                'languages' => $this->languages,
368
                'search_results' => $searchResults,
369
                'rest' => $parameters->getOffset()>0,
370
                'global_search' => true,
371
                'search_failed' => $errored,
372
                'term' => $request->getQueryParamRaw('q'),
373
                'lang_list' => $langList,
374
                'vocabs' => str_replace(' ', '+', $vocabs),
375
                'vocab_list' => $vocabList,
376
                'sorted_vocabs' => $sortedVocabs,
377
                'request' => $request,
378
                'parameters' => $parameters
379
            ));
380
    }
381
382
    /**
383
     * Invokes the search for a single vocabs concepts.
384
     */
385
    public function invokeVocabularySearch($request)
386
    {
387
        $template = $this->twig->loadTemplate('vocab-search-listing.twig');
388
        $this->setLanguageProperties($request->getLang());
389
        $vocab = $request->getVocab();
390
        $searchResults = null;
391
        try {
392
            $vocabTypes = $this->model->getTypes($request->getVocabid(), $request->getLang());
393
        } catch (Exception $e) {
394
            header("HTTP/1.0 500 Internal Server Error");
395
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
396
                error_log('Caught exception: ' . $e->getMessage());
397
            }
398
399
            echo $template->render(
400
                array(
401
                    'languages' => $this->languages,
402
                    'vocab' => $vocab,
403
                    'request' => $request,
404
                    'search_results' => $searchResults
405
                ));
406
407
            return;
408
        }
409
410
        $langcodes = $vocab->getConfig()->getShowLangCodes();
411
        $parameters = new ConceptSearchParameters($request, $this->model->getConfig());
412
413
        try {
414
            $countAndResults = $this->model->searchConceptsAndInfo($parameters);
415
            $counts = $countAndResults['count'];
416
            $searchResults = $countAndResults['results'];
417
        } catch (Exception $e) {
418
            header("HTTP/1.0 404 Not Found");
419
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
420
                error_log('Caught exception: ' . $e->getMessage());
421
            }
422
423
            echo $template->render(
424
                array(
425
                    'languages' => $this->languages,
426
                    'vocab' => $vocab,
427
                    'term' => $request->getQueryParam('q'),
428
                    'search_results' => $searchResults
429
                ));
430
            return;
431
        }
432
        echo $template->render(
433
            array(
434
                'languages' => $this->languages,
435
                'vocab' => $vocab,
436
                'search_results' => $searchResults,
437
                'search_count' => $counts,
438
                'rest' => $parameters->getOffset()>0,
439
                'limit_parent' => $parameters->getParentLimit(),
440
                'limit_type' =>  $request->getQueryParam('type') ? explode('+', $request->getQueryParam('type')) : null,
441
                'limit_group' => $parameters->getGroupLimit(),
442
                'limit_scheme' =>  $request->getQueryParam('scheme') ? explode('+', $request->getQueryParam('scheme')) : null,
443
                'group_index' => $vocab->listConceptGroups($request->getContentLang()),
444
                'parameters' => $parameters,
445
                'term' => $request->getQueryParamRaw('q'),
446
                'types' => $vocabTypes,
447
                'explicit_langcodes' => $langcodes,
448
                'request' => $request,
449
            ));
450
    }
451
452
    /**
453
     * Invokes the alphabetical listing for a specific vocabulary.
454
     */
455
    public function invokeAlphabeticalIndex($request)
456
    {
457
        $lang = $request->getLang();
458
        $this->setLanguageProperties($lang);
459
        $template = $this->twig->loadTemplate('alphabetical-index.twig');
460
        $vocab = $request->getVocab();
461
462
        $offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
463
        if ($request->getQueryParam('limit')) {
464
            $count = $request->getQueryParam('limit');
465
        } else {
466
            $count = ($offset > 0) ? null : 250;
467
        }
468
469
        $contentLang = $request->getContentLang();
470
471
        $allAtOnce = $vocab->getConfig()->getAlphabeticalFull();
472
        if (!$allAtOnce) {
473
            $letters = $vocab->getAlphabet($contentLang);
474
            $letter = $request->getLetter();
475
            if ($letter === '' && isset($letters[0])) {
476
                $letter = $letters[0];
477
            }
478
            $searchResults = $vocab->searchConceptsAlphabetical($letter, $count, $offset, $contentLang);
479
        } else {
480
            $letters = null;
481
            $searchResults = $vocab->searchConceptsAlphabetical('*', null, null, $contentLang);
482
        }
483
484
        $request->setContentLang($contentLang);
485
486
        echo $template->render(
487
            array(
488
                'languages' => $this->languages,
489
                'vocab' => $vocab,
490
                'alpha_results' => $searchResults,
491
                'letters' => $letters,
492
                'all_letters' => $allAtOnce,
493
                'request' => $request,
494
            ));
495
    }
496
497
    /**
498
     * Invokes the vocabulary group index page template.
499
     * @param boolean $stats set to true to get vocabulary statistics visible.
500
     */
501
    public function invokeGroupIndex($request, $stats = false)
502
    {
503
        $lang = $request->getLang();
504
        $this->setLanguageProperties($lang);
505
        $template = $this->twig->loadTemplate('group-index.twig');
506
        $vocab = $request->getVocab();
507
508
        echo $template->render(
509
            array(
510
                'languages' => $this->languages,
511
                'stats' => $stats,
512
                'vocab' => $vocab,
513
                'request' => $request,
514
            ));
515
    }
516
517
    /**
518
     * Loads and renders the view containing a specific vocabulary.
519
     */
520
    public function invokeVocabularyHome($request)
521
    {
522
        $lang = $request->getLang();
523
        // set language parameters for gettext
524
        $this->setLanguageProperties($lang);
525
        $vocab = $request->getVocab();
526
527
        $defaultView = $vocab->getConfig()->getDefaultSidebarView();
528
        // load template
529
        if ($defaultView === 'groups') {
530
            $this->invokeGroupIndex($request, true);
531
            return;
532
        } else if ($defaultView === 'new') {
533
            $this->invokeChangeList($request);
534
        }
535
        $pluginParameters = json_encode($vocab->getConfig()->getPluginParameters());
536
537
        $template = $this->twig->loadTemplate('vocab.twig');
538
539
        echo $template->render(
540
            array(
541
                'languages' => $this->languages,
542
                'vocab' => $vocab,
543
                'search_letter' => 'A',
544
                'active_tab' => $defaultView,
545
                'request' => $request,
546
                'plugin_params' => $pluginParameters
547
            ));
548
    }
549
550
    /**
551
     * Invokes a very generic errorpage.
552
     */
553
    public function invokeGenericErrorPage($request, $message = null)
554
    {
555
        $this->setLanguageProperties($request->getLang());
556
        header("HTTP/1.0 404 Not Found");
557
        $template = $this->twig->loadTemplate('error-page.twig');
558
        echo $template->render(
559
            array(
560
                'languages' => $this->languages,
561
                'request' => $request,
562
                'vocab' => $request->getVocab(),
563
                'message' => $message,
564
                'requested_page' => filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
0 ignored issues
show
Bug introduced by
The constant FILTER_SANITIZE_FULL_SPECIAL_CHARS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
565
            ));
566
    }
567
568
    /**
569
     * Loads and renders the view containing a list of recent changes in the vocabulary.
570
     * @param Request $request
571
     */
572
    public function invokeChangeList($request, $prop='dc:created')
573
    {
574
        $offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
575
        $limit = ($request->getQueryParam('limit') && is_numeric($request->getQueryParam('limit')) && $request->getQueryParam('limit') >= 0) ? $request->getQueryParam('limit') : 200;
576
577
        $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

577
        $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

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