Passed
Branch master (4b538d)
by Osma
10:57
created

WebController::getChangeList()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 4
dl 0
loc 6
rs 10
c 0
b 0
f 0
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
                $vocabObjects[] = $this->model->getVocabulary($vocid);
333
            }
334
        }
335
        $parameters->setVocabularies($vocabObjects);
336
337
        try {
338
            $countAndResults = $this->model->searchConceptsAndInfo($parameters);
339
        } catch (Exception $e) {
340
            header("HTTP/1.0 404 Not Found");
341
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
342
                error_log('Caught exception: ' . $e->getMessage());
343
            }
344
            $this->invokeGenericErrorPage($request, $e->getMessage());
345
            return;
346
        }
347
        $counts = $countAndResults['count'];
348
        $searchResults = $countAndResults['results'];
349
        $vocabList = $this->model->getVocabularyList();
350
        $sortedVocabs = $this->model->getVocabularyList(false, true);
351
        $langList = $this->model->getLanguages($lang);
352
353
        echo $template->render(
354
            array(
355
                'search_count' => $counts,
356
                'languages' => $this->languages,
357
                'search_results' => $searchResults,
358
                'rest' => $parameters->getOffset()>0,
359
                'global_search' => true,
360
                'term' => $request->getQueryParamRaw('q'),
361
                'lang_list' => $langList,
362
                'vocabs' => str_replace(' ', '+', $vocabs),
363
                'vocab_list' => $vocabList,
364
                'sorted_vocabs' => $sortedVocabs,
365
                'request' => $request,
366
                'parameters' => $parameters
367
            ));
368
    }
369
370
    /**
371
     * Invokes the search for a single vocabs concepts.
372
     */
373
    public function invokeVocabularySearch($request)
374
    {
375
        $template = $this->twig->loadTemplate('vocab-search-listing.twig');
376
        $this->setLanguageProperties($request->getLang());
377
        $vocab = $request->getVocab();
378
        try {
379
            $vocabTypes = $this->model->getTypes($request->getVocabid(), $request->getLang());
380
        } catch (Exception $e) {
381
            header("HTTP/1.0 404 Not Found");
382
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
383
                error_log('Caught exception: ' . $e->getMessage());
384
            }
385
386
            echo $template->render(
387
                array(
388
                    'languages' => $this->languages,
389
                ));
390
391
            return;
392
        }
393
394
        $langcodes = $vocab->getConfig()->getShowLangCodes();
395
        $parameters = new ConceptSearchParameters($request, $this->model->getConfig());
396
397
        try {
398
            $countAndResults = $this->model->searchConceptsAndInfo($parameters);
399
            $counts = $countAndResults['count'];
400
            $searchResults = $countAndResults['results'];
401
        } catch (Exception $e) {
402
            header("HTTP/1.0 404 Not Found");
403
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
404
                error_log('Caught exception: ' . $e->getMessage());
405
            }
406
407
            echo $template->render(
408
                array(
409
                    'languages' => $this->languages,
410
                    'vocab' => $vocab,
411
                    'term' => $request->getQueryParam('q'),
412
                ));
413
            return;
414
        }
415
        echo $template->render(
416
            array(
417
                'languages' => $this->languages,
418
                'vocab' => $vocab,
419
                'search_results' => $searchResults,
420
                'search_count' => $counts,
421
                'rest' => $parameters->getOffset()>0,
422
                'limit_parent' => $parameters->getParentLimit(),
423
                'limit_type' =>  $request->getQueryParam('type') ? explode('+', $request->getQueryParam('type')) : null,
424
                'limit_group' => $parameters->getGroupLimit(),
425
                'limit_scheme' =>  $request->getQueryParam('scheme') ? explode('+', $request->getQueryParam('scheme')) : null,
426
                'group_index' => $vocab->listConceptGroups($request->getContentLang()),
427
                'parameters' => $parameters,
428
                'term' => $request->getQueryParamRaw('q'),
429
                'types' => $vocabTypes,
430
                'explicit_langcodes' => $langcodes,
431
                'request' => $request,
432
            ));
433
    }
434
435
    /**
436
     * Invokes the alphabetical listing for a specific vocabulary.
437
     */
438
    public function invokeAlphabeticalIndex($request)
439
    {
440
        $lang = $request->getLang();
441
        $this->setLanguageProperties($lang);
442
        $template = $this->twig->loadTemplate('alphabetical-index.twig');
443
        $vocab = $request->getVocab();
444
445
        $offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
446
        if ($request->getQueryParam('limit')) {
447
            $count = $request->getQueryParam('limit');
448
        } else {
449
            $count = ($offset > 0) ? null : 250;
450
        }
451
452
        $contentLang = $request->getContentLang();
453
454
        $allAtOnce = $vocab->getConfig()->getAlphabeticalFull();
455
        if (!$allAtOnce) {
456
            $letters = $vocab->getAlphabet($contentLang);
457
            $letter = $request->getLetter();
458
            if ($letter === '' && isset($letters[0])) {
459
                $letter = $letters[0];
460
            }
461
            $searchResults = $vocab->searchConceptsAlphabetical($letter, $count, $offset, $contentLang);
462
        } else {
463
            $letters = null;
464
            $searchResults = $vocab->searchConceptsAlphabetical('*', null, null, $contentLang);
465
        }
466
467
        $request->setContentLang($contentLang);
468
469
        echo $template->render(
470
            array(
471
                'languages' => $this->languages,
472
                'vocab' => $vocab,
473
                'alpha_results' => $searchResults,
474
                'letters' => $letters,
475
                'all_letters' => $allAtOnce,
476
                'request' => $request,
477
            ));
478
    }
479
480
    /**
481
     * Invokes the vocabulary group index page template.
482
     * @param boolean $stats set to true to get vocabulary statistics visible.
483
     */
484
    public function invokeGroupIndex($request, $stats = false)
485
    {
486
        $lang = $request->getLang();
487
        $this->setLanguageProperties($lang);
488
        $template = $this->twig->loadTemplate('group-index.twig');
489
        $vocab = $request->getVocab();
490
491
        echo $template->render(
492
            array(
493
                'languages' => $this->languages,
494
                'stats' => $stats,
495
                'vocab' => $vocab,
496
                'request' => $request,
497
            ));
498
    }
499
500
    /**
501
     * Loads and renders the view containing a specific vocabulary.
502
     */
503
    public function invokeVocabularyHome($request)
504
    {
505
        $lang = $request->getLang();
506
        // set language parameters for gettext
507
        $this->setLanguageProperties($lang);
508
        $vocab = $request->getVocab();
509
510
        $defaultView = $vocab->getConfig()->getDefaultSidebarView();
511
        // load template
512
        if ($defaultView === 'groups') {
513
            $this->invokeGroupIndex($request, true);
514
            return;
515
        }
516
        $pluginParameters = $vocab->getConfig()->getPluginParameters();
517
518
        $template = $this->twig->loadTemplate('vocab.twig');
519
520
        echo $template->render(
521
            array(
522
                'languages' => $this->languages,
523
                'vocab' => $vocab,
524
                'search_letter' => 'A',
525
                'active_tab' => $defaultView,
526
                'request' => $request,
527
                'plugin_params' => $pluginParameters
528
            ));
529
    }
530
531
    /**
532
     * Invokes a very generic errorpage.
533
     */
534
    public function invokeGenericErrorPage($request, $message = null)
535
    {
536
        $this->setLanguageProperties($request->getLang());
537
        header("HTTP/1.0 404 Not Found");
538
        $template = $this->twig->loadTemplate('error-page.twig');
539
        echo $template->render(
540
            array(
541
                'languages' => $this->languages,
542
                'request' => $request,
543
                'message' => $message,
544
                'requested_page' => filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_STRING),
545
            ));
546
    }
547
548
    /**
549
     * Loads and renders the view containing a list of recent changes in the vocabulary.
550
     * @param Request $request
551
     */
552
    public function invokeChangeList($request, $prop='dc:created')
553
    {
554
        $offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
555
        $limit = ($request->getQueryParam('limit') && is_numeric($request->getQueryParam('limit')) && $request->getQueryParam('limit') >= 0) ? $request->getQueryParam('limit') : 200;
556
557
        $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

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

557
        $changeList = $this->getChangeList($request, $prop, /** @scrutinizer ignore-type */ $offset, $limit);
Loading history...
558
        $bydate = $this->formatChangeList($changeList, $request->getLang());
559
560
        // load template
561
        $template = $this->twig->loadTemplate('changes.twig');
562
563
        // render template
564
        echo $template->render(
565
            array(
566
                'vocab' => $request->getVocab(),
567
                'languages' => $this->languages,
568
                'request' => $request,
569
                'changeList' => $bydate)
570
            );
571
    }
572
    /**
573
     * Gets the list of newest concepts for a vocabulary according to timestamp indicated by a property
574
     * @param Request $request
575
     * @param string $prop the name of the property eg. 'dc:modified'.
576
     * @param int $offset starting index offset
577
     * @param int $limit maximum number of concepts to return
578
     * @return Array list of concepts
579
     */
580
    public function getChangeList($request, $prop, $offset=0, $limit=200)
581
    {
582
        // set language parameters for gettext
583
        $this->setLanguageProperties($request->getLang());
584
585
        return $request->getVocab()->getChangeList($prop, $request->getContentLang(), $offset, $limit);
586
    }
587
588
    /**
589
     * Formats the list of concepts as labels arranged by modification month
590
     * @param Array $changeList
591
     * @param string $lang the language for displaying dates in the change list
592
     * @return array list of concepts as labels by month
593
     */
594
    public function formatChangeList($changeList, $lang)
595
    {
596
        $formatByDate = array();
597
        foreach($changeList as $concept) {
598
            $concept['datestring'] = Punic\Calendar::formatDate($concept['date'], 'medium', $lang);
599
            $formatByDate[Punic\Calendar::getMonthName($concept['date'], 'wide', $lang, true) . Punic\Calendar::format($concept['date'], ' y', $lang) ][strtolower($concept['prefLabel'])] = $concept;
600
        }
601
        return $formatByDate;
602
    }
603
604
}
605