Completed
Pull Request — master (#1033)
by
unknown
01:46
created

WebController::invokeGlobalSearch()   C

Complexity

Conditions 12
Paths 168

Size

Total Lines 77

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
nc 168
nop 1
dl 0
loc 77
rs 5.6218
c 0
b 0
f 0

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');
39
        // initialize Twig environment
40
        $this->twig = new Twig_Environment($loader, array('cache' => $tmpDir,'auto_reload' => true));
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) {
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) {
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')));
61
62
        // register a Twig filter for generating strings from language codes with CLDR
63
        $langFilter = new Twig_SimpleFilter('lang_name', function ($langcode, $lang) {
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();
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
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
        /** @var \Twig\Template $template */
183
        $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');
184
185
        $crumbs = $vocab->getBreadCrumbs($request->getContentLang(), $uri);
186
        echo $template->render(array(
187
            'search_results' => $results,
188
            'vocab' => $vocab,
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
        $feedbackMsg = null;
210
        if ($request->getQueryParamPOST('message')) {
211
            $feedbackSent = true;
212
            $feedbackMsg = $request->getQueryParamPOST('message');
213
        }
214
        $feedbackName = $request->getQueryParamPOST('name');
215
        $feedbackEmail = $request->getQueryParamPOST('email');
216
        $feedbackVocab = $request->getQueryParamPOST('vocab');
217
218
        $feedbackVocabEmail = ($feedbackVocab !== null && $feedbackVocab !== '') ?
219
            $this->model->getVocabulary($feedbackVocab)->getConfig()->getFeedbackRecipient() : null;
220
221
        // if the hidden field has been set a value we have found a spam bot
222
        // and we do not actually send the message.
223
        if ($this->honeypot->validateHoneypot($request->getQueryParamPOST('item-description')) &&
224
            $this->honeypot->validateHoneytime($request->getQueryParamPOST('user-captcha'), $this->model->getConfig()->getHoneypotTime())) {
0 ignored issues
show
Documentation introduced by
$this->model->getConfig()->getHoneypotTime() is of type integer, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
225
            $this->sendFeedback($request, $feedbackMsg, $feedbackName, $feedbackEmail, $feedbackVocab, $feedbackVocabEmail);
226
        }
227
228
        echo $template->render(
229
            array(
230
                'languages' => $this->languages,
231
                'vocab' => $vocab,
232
                'vocabList' => $vocabList,
233
                'feedback_sent' => $feedbackSent,
234
                'request' => $request,
235
            ));
236
    }
237
238
    private function createFeedbackHeaders($fromName, $fromEmail, $toMail, $sender)
239
    {
240
        $headers = "MIME-Version: 1.0" . "\r\n";
241
        $headers .= "Content-type: text/html; charset=UTF-8" . "\r\n";
242
        if (!empty($toMail)) {
243
            $headers .= "Cc: " . $this->model->getConfig()->getFeedbackAddress() . "\r\n";
244
        }
245
        if (!empty($fromEmail)) {
246
            $headers .= "Reply-To: $fromName <$fromEmail>\r\n";
247
        }
248
249
        $service = $this->model->getConfig()->getServiceName();
250
        return $headers . "From: $fromName via $service <$sender>";
251
    }
252
253
    /**
254
     * Sends the user entered message through the php's mailer.
255
     * @param string $message only required parameter is the actual message.
256
     * @param string $fromName senders own name.
257
     * @param string $fromEmail senders email address.
258
     * @param string $fromVocab which vocabulary is the feedback related to.
259
     */
260
    public function sendFeedback($request, $message, $fromName = null, $fromEmail = null, $fromVocab = null, $toMail = null)
261
    {
262
        $toAddress = ($toMail) ? $toMail : $this->model->getConfig()->getFeedbackAddress();
263
        if ($fromVocab !== null && $fromVocab !== '') {
264
            $message = 'Feedback from vocab: ' . strtoupper($fromVocab) . "<br />" . $message;
265
        }
266
267
        $envelopeSender = $this->model->getConfig()->getFeedbackEnvelopeSender();
268
        $subject = $this->model->getConfig()->getServiceName() . " feedback";
269
        // determine the sender address of the message
270
        $sender = $this->model->getConfig()->getFeedbackSender();
271
        if (empty($sender)) $sender = $envelopeSender;
272
        if (empty($sender)) $sender = $this->model->getConfig()->getFeedbackAddress();
273
274
        // determine sender name - default to "anonymous user" if not given by user
275
        if (empty($fromName)) $fromName = "anonymous user";
276
277
        $headers = $this->createFeedbackHeaders($fromName, $fromEmail, $toMail, $sender);
278
        $params = empty($envelopeSender) ? '' : "-f $envelopeSender";
279
280
        // adding some information about the user for debugging purposes.
281
        $message = $message . "<br /><br /> Debugging information:"
282
            . "<br />Timestamp: " . date(DATE_RFC2822)
283
            . "<br />User agent: " . $request->getServerConstant('HTTP_USER_AGENT')
284
            . "<br />Referer: " . $request->getServerConstant('HTTP_REFERER');
285
286
        try {
287
            mail($toAddress, $subject, $message, $headers, $params);
288
        } catch (Exception $e) {
289
            header("HTTP/1.0 404 Not Found");
290
            $template = $this->twig->loadTemplate('error-page.twig');
291
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
292
                error_log('Caught exception: ' . $e->getMessage());
293
            }
294
295
            echo $template->render(
296
                array(
297
                    'languages' => $this->languages,
298
                ));
299
300
            return;
301
        }
302
    }
303
304
    /**
305
     * Invokes the about page for the Skosmos service.
306
     */
307 View Code Duplication
    public function invokeAboutPage($request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
308
    {
309
        $template = $this->twig->loadTemplate('about.twig');
310
        $this->setLanguageProperties($request->getLang());
311
        $url = $request->getServerConstant('HTTP_HOST');
312
        $version = $this->model->getVersion();
313
314
        echo $template->render(
315
            array(
316
                'languages' => $this->languages,
317
                'version' => $version,
318
                'server_instance' => $url,
319
                'request' => $request,
320
            ));
321
    }
322
323
    /**
324
     * Invokes the search for concepts in all the available ontologies.
325
     */
326
    public function invokeGlobalSearch($request)
327
    {
328
        $lang = $request->getLang();
329
        $template = $this->twig->loadTemplate('vocab-search-listing.twig');
330
        $this->setLanguageProperties($lang);
331
332
        $parameters = new ConceptSearchParameters($request, $this->model->getConfig());
333
334
        $vocabs = $request->getQueryParam('vocabs'); # optional
335
        // convert to vocids array to support multi-vocabulary search
336
        $vocids = ($vocabs !== null && $vocabs !== '') ? explode(' ', $vocabs) : null;
337
        $vocabObjects = array();
338
        if ($vocids) {
339
            foreach($vocids as $vocid) {
340
                try {
341
                    $vocabObjects[] = $this->model->getVocabulary($vocid);
342
                } catch (Exception $e) {
343
                    // skip vocabularies not found in configuration
344
                    // please note that this may result in global search
345
                    // NB: should not happen in normal UI interaction
346
                }
347
            }
348
        }
349
        $parameters->setVocabularies($vocabObjects);
350
351
        $nondefaultEndpointVocs = array();
352
353
        if (sizeOf($vocabObjects) != 1) {
354
            // global search, either from all (sizeOf($vocabObjects) == 0) or from selected ones
355
            if (sizeOf($vocabObjects) == 0) {
356
                $vocabObjects = $this->model->getVocabularies();
357
            }
358
            $defaultEndpoint = $this->model->getConfig()->getDefaultEndpoint();
359
            foreach($vocabObjects as $voc) {
360
                if ($voc->getEndpoint() !== $defaultEndpoint) {
361
                    $nondefaultEndpointVocs[] = $voc;
362
                }
363
            }
364
        }
365
366
        $counts = null;
367
        $searchResults = null;
368
        $errored = false;
369
370
        try {
371
            $countAndResults = $this->model->searchConceptsAndInfo($parameters);
372
            $counts = $countAndResults['count'];
373
            $searchResults = $countAndResults['results'];
374
        } catch (Exception $e) {
375
            $errored = true;
376
            header("HTTP/1.0 500 Internal Server Error");
377
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
378
                error_log('Caught exception: ' . $e->getMessage());
379
            }
380
        }
381
        $vocabList = $this->model->getVocabularyList();
382
        $sortedVocabs = $this->model->getVocabularyList(false, true);
383
        $langList = $this->model->getLanguages($lang);
384
385
        echo $template->render(
386
            array(
387
                'search_count' => $counts,
388
                'languages' => $this->languages,
389
                'search_results' => $searchResults,
390
                'rest' => $parameters->getOffset()>0,
391
                'global_search' => true,
392
                'search_failed' => $errored,
393
                'skipped_vocabs' => $nondefaultEndpointVocs,
394
                'term' => $request->getQueryParamRaw('q'),
395
                'lang_list' => $langList,
396
                'vocabs' => str_replace(' ', '+', $vocabs),
397
                'vocab_list' => $vocabList,
398
                'sorted_vocabs' => $sortedVocabs,
399
                'request' => $request,
400
                'parameters' => $parameters
401
            ));
402
    }
403
404
    /**
405
     * Invokes the search for a single vocabs concepts.
406
     */
407
    public function invokeVocabularySearch($request)
408
    {
409
        $template = $this->twig->loadTemplate('vocab-search-listing.twig');
410
        $this->setLanguageProperties($request->getLang());
411
        $vocab = $request->getVocab();
412
        $searchResults = null;
413
        try {
414
            $vocabTypes = $this->model->getTypes($request->getVocabid(), $request->getLang());
415
        } catch (Exception $e) {
416
            header("HTTP/1.0 500 Internal Server Error");
417
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
418
                error_log('Caught exception: ' . $e->getMessage());
419
            }
420
421
            echo $template->render(
422
                array(
423
                    'languages' => $this->languages,
424
                    'vocab' => $vocab,
425
                    'request' => $request,
426
                    'search_results' => $searchResults
427
                ));
428
429
            return;
430
        }
431
432
        $langcodes = $vocab->getConfig()->getShowLangCodes();
433
        $parameters = new ConceptSearchParameters($request, $this->model->getConfig());
434
435
        try {
436
            $countAndResults = $this->model->searchConceptsAndInfo($parameters);
437
            $counts = $countAndResults['count'];
438
            $searchResults = $countAndResults['results'];
439
        } catch (Exception $e) {
440
            header("HTTP/1.0 404 Not Found");
441
            if ($this->model->getConfig()->getLogCaughtExceptions()) {
442
                error_log('Caught exception: ' . $e->getMessage());
443
            }
444
445
            echo $template->render(
446
                array(
447
                    'languages' => $this->languages,
448
                    'vocab' => $vocab,
449
                    'term' => $request->getQueryParam('q'),
450
                    'search_results' => $searchResults
451
                ));
452
            return;
453
        }
454
        echo $template->render(
455
            array(
456
                'languages' => $this->languages,
457
                'vocab' => $vocab,
458
                'search_results' => $searchResults,
459
                'search_count' => $counts,
460
                'rest' => $parameters->getOffset()>0,
461
                'limit_parent' => $parameters->getParentLimit(),
462
                'limit_type' =>  $request->getQueryParam('type') ? explode('+', $request->getQueryParam('type')) : null,
463
                'limit_group' => $parameters->getGroupLimit(),
464
                'limit_scheme' =>  $request->getQueryParam('scheme') ? explode('+', $request->getQueryParam('scheme')) : null,
465
                'group_index' => $vocab->listConceptGroups($request->getContentLang()),
466
                'parameters' => $parameters,
467
                'term' => $request->getQueryParamRaw('q'),
468
                'types' => $vocabTypes,
469
                'explicit_langcodes' => $langcodes,
470
                'request' => $request,
471
            ));
472
    }
473
474
    /**
475
     * Invokes the alphabetical listing for a specific vocabulary.
476
     */
477
    public function invokeAlphabeticalIndex($request)
478
    {
479
        $lang = $request->getLang();
480
        $this->setLanguageProperties($lang);
481
        $template = $this->twig->loadTemplate('alphabetical-index.twig');
482
        $vocab = $request->getVocab();
483
484
        $offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
485
        if ($request->getQueryParam('limit')) {
486
            $count = $request->getQueryParam('limit');
487
        } else {
488
            $count = ($offset > 0) ? null : 250;
489
        }
490
491
        $contentLang = $request->getContentLang();
492
493
        $allAtOnce = $vocab->getConfig()->getAlphabeticalFull();
494
        if (!$allAtOnce) {
495
            $letters = $vocab->getAlphabet($contentLang);
496
            $letter = $request->getLetter();
497
            if ($letter === '') {
498
                $letter = $letters[0];
499
            }
500
            $searchResults = $vocab->searchConceptsAlphabetical($letter, $count, $offset, $contentLang);
501
        } else {
502
            $letters = null;
503
            $searchResults = $vocab->searchConceptsAlphabetical('*', null, null, $contentLang);
504
        }
505
506
        $request->setContentLang($contentLang);
507
508
        echo $template->render(
509
            array(
510
                'languages' => $this->languages,
511
                'vocab' => $vocab,
512
                'alpha_results' => $searchResults,
513
                'letters' => $letters,
514
                'all_letters' => $allAtOnce,
515
                'request' => $request,
516
            ));
517
    }
518
519
    /**
520
     * Invokes the vocabulary group index page template.
521
     * @param boolean $stats set to true to get vocabulary statistics visible.
522
     */
523 View Code Duplication
    public function invokeGroupIndex($request, $stats = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
524
    {
525
        $lang = $request->getLang();
526
        $this->setLanguageProperties($lang);
527
        $template = $this->twig->loadTemplate('group-index.twig');
528
        $vocab = $request->getVocab();
529
530
        echo $template->render(
531
            array(
532
                'languages' => $this->languages,
533
                'stats' => $stats,
534
                'vocab' => $vocab,
535
                'request' => $request,
536
            ));
537
    }
538
539
    /**
540
     * Loads and renders the view containing a specific vocabulary.
541
     */
542
    public function invokeVocabularyHome($request)
543
    {
544
        $lang = $request->getLang();
545
        // set language parameters for gettext
546
        $this->setLanguageProperties($lang);
547
        $vocab = $request->getVocab();
548
549
        $defaultView = $vocab->getConfig()->getDefaultSidebarView();
550
        // load template
551
        if ($defaultView === 'groups') {
552
            $this->invokeGroupIndex($request, true);
553
            return;
554
        }
555
        $pluginParameters = $vocab->getConfig()->getPluginParameters();
556
557
        $template = $this->twig->loadTemplate('vocab.twig');
558
559
        echo $template->render(
560
            array(
561
                'languages' => $this->languages,
562
                'vocab' => $vocab,
563
                'search_letter' => 'A',
564
                'active_tab' => $defaultView,
565
                'request' => $request,
566
                'plugin_params' => $pluginParameters
567
            ));
568
    }
569
570
    /**
571
     * Invokes a very generic errorpage.
572
     */
573
    public function invokeGenericErrorPage($request, $message = null)
574
    {
575
        $this->setLanguageProperties($request->getLang());
576
        header("HTTP/1.0 404 Not Found");
577
        $template = $this->twig->loadTemplate('error-page.twig');
578
        echo $template->render(
579
            array(
580
                'languages' => $this->languages,
581
                'request' => $request,
582
                'vocab' => $request->getVocab(),
583
                'message' => $message,
584
                'requested_page' => filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_STRING),
585
            ));
586
    }
587
588
    /**
589
     * Loads and renders the view containing a list of recent changes in the vocabulary.
590
     * @param Request $request
591
     */
592
    public function invokeChangeList($request, $prop='dc:created')
593
    {
594
        $offset = ($request->getQueryParam('offset') && is_numeric($request->getQueryParam('offset')) && $request->getQueryParam('offset') >= 0) ? $request->getQueryParam('offset') : 0;
595
        $limit = ($request->getQueryParam('limit') && is_numeric($request->getQueryParam('limit')) && $request->getQueryParam('limit') >= 0) ? $request->getQueryParam('limit') : 200;
596
597
        $changeList = $this->getChangeList($request, $prop, $offset, $limit);
598
        $bydate = $this->formatChangeList($changeList, $request->getLang());
599
600
        // load template
601
        $template = $this->twig->loadTemplate('changes.twig');
602
603
        // render template
604
        echo $template->render(
605
            array(
606
                'vocab' => $request->getVocab(),
607
                'languages' => $this->languages,
608
                'request' => $request,
609
                'changeList' => $bydate)
610
            );
611
    }
612
    /**
613
     * Gets the list of newest concepts for a vocabulary according to timestamp indicated by a property
614
     * @param Request $request
615
     * @param string $prop the name of the property eg. 'dc:modified'.
616
     * @param int $offset starting index offset
617
     * @param int $limit maximum number of concepts to return
618
     * @return Array list of concepts
619
     */
620
    public function getChangeList($request, $prop, $offset=0, $limit=200)
621
    {
622
        // set language parameters for gettext
623
        $this->setLanguageProperties($request->getLang());
624
625
        return $request->getVocab()->getChangeList($prop, $request->getContentLang(), $offset, $limit);
626
    }
627
628
    /**
629
    * Formats the list of concepts as labels arranged by modification month
630
    * @param Array $changeList
631
    * @param string $lang the language for displaying dates in the change list
632
    */
633
    public function formatChangeList($changeList, $lang)
634
    {
635
        $formatByDate = array();
636
        foreach($changeList as $concept) {
637
            $concept['datestring'] = Punic\Calendar::formatDate($concept['date'], 'medium', $lang);
638
            $formatByDate[Punic\Calendar::getMonthName($concept['date'], 'wide', $lang, true) . Punic\Calendar::format($concept['date'], ' y', $lang) ][strtolower($concept['prefLabel'])] = $concept;
639
        }
640
        return $formatByDate;
641
    }
642
643
}
644