Vocabulary::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Vocabulary dataobjects provide access to the vocabularies on the SPARQL endpoint.
5
 */
6
class Vocabulary extends DataObject implements Modifiable
7
{
8
    /** cached value of URI space */
9
    private $urispace = null;
10
    private $config;
11
12
    public function __construct($model, $resource)
13
    {
14
        parent::__construct($model, $resource);
15
        $this->config = new VocabularyConfig($resource, $model->getConfig()->getGlobalPlugins());
16
    }
17
18
    /**
19
     * Returns the VocabularyConfig object
20
     * @return VocabularyConfig
21
     */
22
    public function getConfig()
23
    {
24
      return $this->config;
25
    }
26
27
    /**
28
     * Get the SPARQL endpoint URL for this vocabulary
29
     *
30
     * @return string endpoint URL
31
     */
32
    public function getEndpoint()
33
    {
34
        $endpoint = $this->config->getSparqlEndpoint();
35
        if ($endpoint === null) {
36
            $endpoint = $this->model->getConfig()->getDefaultEndpoint();
37
        }
38
        return $endpoint;
39
    }
40
41
    /**
42
     * Get the SPARQL graph URI for this vocabulary
43
     *
44
     * @return string|null graph URI
45
     */
46
    public function getGraph()
47
    {
48
        return $this->config->getSparqlGraph();
49
    }
50
51
    /**
52
     * Get the SPARQL implementation for this vocabulary
53
     *
54
     * @return GenericSparql SPARQL object
55
     */
56
    public function getSparql()
57
    {
58
        $endpoint = $this->getEndpoint();
59
        $graph = $this->getGraph();
60
        $dialect = $this->config->getSparqlDialect() ?? $this->model->getConfig()->getDefaultSparqlDialect();
61
62
        return $this->model->getSparqlImplementation($dialect, $endpoint, $graph);
63
    }
64
65
    /**
66
     * Get the URI space of concepts in this vocabulary.
67
     *
68
     * @return string full URI of concept
69
     */
70
    public function getUriSpace()
71
    {
72
        if ($this->urispace === null) // initialize cache
73
        {
74
            $urispace = $this->resource->getLiteral('void:uriSpace');
75
            if ($urispace) {
0 ignored issues
show
introduced by
$urispace is of type EasyRdf\Literal, thus it always evaluated to true.
Loading history...
76
                $this->urispace = $urispace->getValue();
77
            }
78
        }
79
80
        return $this->urispace;
81
    }
82
83
    /**
84
     * Return true if the URI is within the URI space of this vocabulary.
85
     *
86
     * @param string full URI of concept
0 ignored issues
show
Bug introduced by
The type full 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...
87
     * @return bool true if URI is within URI namespace, false otherwise
88
     */
89
90
    public function containsURI($uri)
91
    {
92
        return (strpos($uri, $this->getUriSpace()) === 0);
93
    }
94
95
    /**
96
     * Get the full URI of a concept in a vocabulary. If the passed local
97
     * name is already a full URI, return it unchanged.
98
     *
99
     * @param $lname string local name of concept
100
     * @return string full URI of concept
101
     */
102
    public function getConceptURI($lname)
103
    {
104
        if (strpos($lname, 'http') === 0) {
105
            return $lname;
106
        }
107
        // already a full URI
108
        return $this->getUriSpace() . $lname;
109
    }
110
111
    /**
112
     * Asks the sparql implementation to make a label query for a uri.
113
     * @param string $uri
114
     * @param string $lang
115
     */
116
    public function getConceptLabel($uri, $lang)
117
    {
118
        return $this->getSparql()->queryLabel($uri, $lang);
119
    }
120
121
    /**
122
     * Asks the sparql implementation to make a label query for a uri.
123
     * @param string $uri
124
     * @param string $lang
125
     * @return array array of altLabels
126
     */
127
    public function getAllConceptLabels($uri, $lang)
128
    {
129
        return $this->getSparql()->queryAllConceptLabels($uri, $lang);
130
    }
131
    /**
132
     * Get the localname of a concept in the vocabulary. If the URI is not
133
     * in the URI space of this vocabulary, return the full URI.
134
     *
135
     * @param $uri string full URI of concept
136
     * @return string local name of concept, or original full URI if the local name cannot be determined
137
     */
138
    public function getLocalName($uri)
139
    {
140
        return ($uri !== null) ? str_replace($this->getUriSpace(), "", $uri) : '';
141
    }
142
143
    /**
144
     * Retrieves all the information about the Vocabulary
145
     * from the SPARQL-endpoint.
146
     */
147
    public function getInfo($lang = null)
148
    {
149
        $ret = array();
150
        if (!$lang) {
151
            $lang = $this->getEnvLang();
152
        }
153
154
        // get metadata (literals only e.g. name) from vocabulary configuration file
155
        foreach ($this->resource->properties() as $prop) {
156
            foreach ($this->resource->allLiterals($prop, $lang) as $val) {
157
                $ret[$prop][] = $val->getValue();
158
            }
159
        }
160
161
        try {
162
            // also include ConceptScheme metadata from SPARQL endpoint
163
            $defaultcs = $this->getDefaultConceptScheme();
164
165
            // query everything the endpoint knows about the ConceptScheme
166
            $sparql = $this->getSparql();
167
            $result = $sparql->queryConceptScheme($defaultcs);
168
        } catch (EasyRdf\Http\Exception | EasyRdf\Exception | Throwable $e) {
169
             if ($this->model->getConfig()->getLogCaughtExceptions()) {
170
                 error_log('Caught exception: ' . $e->getMessage());
171
             }
172
             return null;
173
        }
174
        $conceptscheme = $result->resource($defaultcs);
175
        $this->order = array(
176
            "dc:title", "dc11:title", "skos:prefLabel", "rdfs:label",
177
            "dc:subject", "dc11:subject",
178
            "dc:description", "dc11:description",
179
            "foaf:homepage",
180
            "dc:publisher", "dc11:publisher",
181
            "dc:creator", "dc11:creator",
182
            "dc:contributor",
183
            "dc:license",
184
            "dc:rights", "dc11:rights",
185
            "dc:language", "dc11:language",
186
            "owl:versionInfo",
187
            "dc:source", "dc11:source",
188
            "dc:relation", "dc11:relation",
189
            "dc:created",
190
            "dc:modified",
191
            "dc:date", "dc11:date"
192
        );
193
194
        foreach ($conceptscheme->properties() as $prop) {
195
            foreach ($conceptscheme->allLiterals($prop, $lang) as $val) {
196
                $prop = (substr($prop, 0, 5) == 'dc11:') ? str_replace('dc11:', 'dc:', $prop) : $prop;
197
                if ($prop === 'dc:description') {
198
                    $ret[$prop] = [$val->getValue() => $val]; // override description from vocabulary config
199
                } else {
200
                    $ret[$prop][$val->getValue()] = $val;
201
                }
202
            }
203
            if (!isset($ret[$prop]) || sizeof($ret[$prop]) == 0) { // not found with language tag
204
                foreach ($conceptscheme->allLiterals($prop, null) as $val) {
205
                    $prop = (substr($prop, 0, 5) == 'dc11:') ? str_replace('dc11:', 'dc:', $prop) : $prop;
206
                    if ($val->getValue() instanceof DateTime) {
207
                        $val = Punic\Calendar::formatDate($val->getValue(), 'full', $lang) . ' ' . Punic\Calendar::format($val->getValue(), 'HH:mm:ss', $lang);
208
                    }
209
                    if ($prop === 'dc:description') {
210
                        $ret[$prop] = [$val->getValue() => $val]; // override description from vocabulary config
211
                    } else {
212
                        $ret[$prop][] = $val;
213
                    }
214
                }
215
            }
216
            foreach ($conceptscheme->allResources($prop) as $val) {
217
                $prop = (substr($prop, 0, 5) == 'dc11:') ? str_replace('dc11:', 'dc:', $prop) : $prop;
218
                $exvocab = $this->model->guessVocabularyFromURI($val->getURI());
219
                $exlabel = $this->getExternalLabel($exvocab, $val->getURI(), $lang);
220
                if (isset($exlabel)) {
221
                    $val->add('skosmos:vocab', $exvocab->getId());
222
                    $val->add('skosmos:label', $exlabel);
223
                }
224
                $label = $val->label($lang) ? $val->label($lang)->getValue() : $val->getUri();
225
                $ret[$prop][$exlabel ? $exlabel->getValue() : $label] = $val;
226
            }
227
            if (isset($ret[$prop])) {
228
                ksort($ret[$prop]);
229
            }
230
        }
231
        if (isset($ret['owl:versionInfo'])) { // if version info available for vocabulary convert it to a more readable format
232
            $ret['owl:versionInfo'][0] = $this->parseVersionInfo($ret['owl:versionInfo'][0]);
233
        }
234
        // remove duplicate values
235
        foreach (array_keys($ret) as $prop) {
236
            $ret[$prop] = array_unique($ret[$prop]);
237
        }
238
239
        $ret = $this->arbitrarySort($ret);
240
241
        // filtering multiple labels
242
        if (isset($ret['dc:title'])) {
243
            unset($ret['dc11:title'], $ret['skos:prefLabel'], $ret['rdfs:label']);
244
        } else if (isset($ret['dc11:title'])) {
245
            unset($ret['skos:prefLabel'], $ret['rdfs:label']);
246
        } else if (isset($ret['skos:prefLabel'])) {
247
            unset($ret['rdfs:label']);
248
        }
249
250
        return $ret;
251
    }
252
253
    /**
254
     * Return all concept schemes in the vocabulary.
255
     * @return array Array with concept scheme URIs (string) as keys and labels (string) as values
256
     */
257
258
    public function getConceptSchemes($lang = '')
259
    {
260
        if ($lang === '') {
261
            $lang = $this->getEnvLang();
262
        }
263
        $conceptSchemes = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $conceptSchemes is dead and can be removed.
Loading history...
264
        try {
265
            $conceptSchemes = $this->getSparql()->queryConceptSchemes($lang);
266
        } catch (EasyRdf\Http\Exception | EasyRdf\Exception | Throwable $e) {
267
             if ($this->model->getConfig()->getLogCaughtExceptions()) {
268
                 error_log('Caught exception: ' . $e->getMessage());
269
             }
270
        }
271
        return $conceptSchemes;
272
    }
273
274
    /**
275
     * Return the URI of the default concept scheme of this vocabulary. If the skosmos:mainConceptScheme property is set in the
276
     * vocabulary configuration, that will be returned. Otherwise an arbitrary concept scheme will be returned.
277
     * @return string concept scheme URI
278
     */
279
280
    public function getDefaultConceptScheme()
281
    {
282
        $conceptScheme = $this->config->getMainConceptSchemeURI();
283
        if ($conceptScheme) {
284
            return $conceptScheme;
285
        }
286
287
        // mainConceptScheme not explicitly set, guess it
288
        $conceptSchemes = $this->getConceptSchemes();
289
        $conceptSchemeURIs = array_keys($conceptSchemes);
290
        // return the URI of the last concept scheme
291
        return array_pop($conceptSchemeURIs);
292
    }
293
294
    /**
295
     * Returns the main Concept Scheme of that Vocabulary, or null if not set.
296
     * @param string $defaultConceptSchemeURI default concept scheme URI
297
     * @return \EasyRdf\Graph|mixed
298
     */
299
    public function getConceptScheme(string $defaultConceptSchemeURI)
300
    {
301
        return $this->getSparql()->queryConceptScheme($defaultConceptSchemeURI);
302
    }
303
304
    /**
305
     * Return the top concepts of a concept scheme in the vocabulary.
306
     * @param string $conceptScheme URI of concept scheme whose top concepts to return. If not set,
307
     *                              the default concept scheme of the vocabulary will be used.
308
     * @param string $lang preferred language for the concept labels,
309
     * @return array Array with concept URIs (string) as keys and labels (string) as values
310
     */
311
312
    public function getTopConcepts($conceptScheme = null, $lang = '')
313
    {
314
        if ($lang === '') {
315
            $lang = $this->getEnvLang();
316
        }
317
        $fallback = $this->config->getDefaultLanguage();
318
319
        if ($conceptScheme === null || $conceptScheme == '') {
320
            $conceptScheme = $this->getDefaultConceptScheme();
321
        }
322
323
        return $this->getSparql()->queryTopConcepts($conceptScheme, $lang, $fallback);
324
    }
325
326
    /**
327
     * Tries to parse version, date and time from sparql version information into a readable format.
328
     * @param string $version
329
     * @return string
330
     */
331
    private function parseVersionInfo($version)
332
    {
333
        $parts = explode(' ', $version);
334
        if ($parts[0] != '$Id:') {
335
            return $version;
336
        }
337
        // don't know how to parse
338
        $rev = $parts[2];
339
        $datestr = $parts[3] . ' ' . $parts[4];
340
341
        return "$datestr (r$rev)";
342
    }
343
344
    /**
345
     * Counts the statistics of the vocabulary.
346
     * @return Array containing the label counts
347
     * @param string $array the uri of the concept array class, eg. isothes:ThesaurusArray
348
     * @param string $group the uri of the  concept group class, eg. isothes:ConceptGroup
349
     */
350
    public function getStatistics($lang = '', $array=null, $group=null)
351
    {
352
        $sparql = $this->getSparql();
353
        // find the number of concepts
354
        return $sparql->countConcepts($lang, $array, $group);
355
    }
356
357
    /**
358
     * Counts the statistics of the vocabulary.
359
     * @return array of the concept counts in different languages
360
     */
361
    public function getLabelStatistics()
362
    {
363
        $sparql = $this->getSparql();
364
        $ret = array();
365
        // count the number of different types of concepts in all languages
366
        $ret['terms'] = $sparql->countLangConcepts($this->config->getLanguages(), $this->config->getIndexClasses());
367
368
        return $ret;
369
    }
370
371
    /**
372
     * Gets the parent concepts of a concept and child concepts for all of those.
373
     * @param string $uri
374
     * @param string $lang language identifier.
375
     */
376
    public function getConceptHierarchy($uri, $lang)
377
    {
378
        $lang = $lang ? $lang : $this->getEnvLang();
379
        $fallback = count($this->config->getLanguageOrder($lang)) > 1 ? $this->config->getLanguageOrder($lang)[1] : $this->config->getDefaultLanguage();
380
        $props = $this->config->getHierarchyProperty();
381
        return $this->getSparql()->queryParentList($uri, $lang, $fallback, $props);
382
    }
383
384
    /**
385
     * Gets the child relations of a concept and whether these children have more children.
386
     * @param string $uri
387
     */
388
    public function getConceptChildren($uri, $lang)
389
    {
390
        $lang = $lang ? $lang : $this->getEnvLang();
391
        $fallback = count($this->config->getLanguageOrder($lang)) > 1 ? $this->config->getLanguageOrder($lang)[1] : $this->config->getDefaultLanguage();
392
        $props = $this->config->getHierarchyProperty();
393
        return $this->getSparql()->queryChildren($uri, $lang, $fallback, $props);
394
    }
395
396
    /**
397
     * Gets the skos:narrower relations of a concept.
398
     * @param string $uri
399
     * @param string $lang language identifier.
400
     */
401
    public function getConceptNarrowers($uri, $lang)
402
    {
403
        $lang = $lang ? $lang : $this->getEnvLang();
404
        return $this->getSparql()->queryProperty($uri, 'skos:narrower', $lang);
405
    }
406
407
    /**
408
     * Gets the skos:narrowerTransitive relations of a concept.
409
     * @param string $uri
410
     * @param integer $limit
411
     * @param string $lang language identifier.
412
     */
413
    public function getConceptTransitiveNarrowers($uri, $limit, $lang)
414
    {
415
        $lang = $lang ? $lang : $this->getEnvLang();
416
        return $this->getSparql()->queryTransitiveProperty($uri, array('skos:narrower'), $lang, $limit);
417
    }
418
419
    /**
420
     * Gets the skos:broader relations of a concept.
421
     * @param string $uri
422
     * @param string $lang language identifier.
423
     */
424
    public function getConceptBroaders($uri, $lang)
425
    {
426
        $lang = $lang ? $lang : $this->getEnvLang();
427
        return $this->getSparql()->queryProperty($uri, 'skos:broader', $lang);
428
    }
429
430
    /**
431
     * Gets the skos:broaderTransitive relations of a concept.
432
     * @param string $uri
433
     * @param integer $limit
434
     * @param boolean $any set to true if you want to have a label even in case of a correct language one missing.
435
     * @param string $lang language identifier.
436
     */
437
    public function getConceptTransitiveBroaders($uri, $limit, $any, $lang)
438
    {
439
        $lang = $lang ? $lang : $this->getEnvLang();
440
        $fallback = $this->config->getDefaultLanguage();
441
        return $this->getSparql()->queryTransitiveProperty($uri, array('skos:broader'), $lang, $limit, $any, $fallback);
442
    }
443
444
    /**
445
     * Gets all the skos:related concepts of a concept.
446
     * @param string $uri
447
     * @param string $lang language identifier.
448
     */
449
    public function getConceptRelateds($uri, $lang)
450
    {
451
        $lang = $lang ? $lang : $this->getEnvLang();
452
        return $this->getSparql()->queryProperty($uri, 'skos:related', $lang);
453
    }
454
455
    /**
456
     * Makes a query into the sparql endpoint for a concept.
457
     * @param string $uri the full URI of the concept
458
     * @return Concept[]
459
     */
460
    public function getConceptInfo($uri, $clang)
461
    {
462
        $sparql = $this->getSparql();
463
        $conceptInfo = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $conceptInfo is dead and can be removed.
Loading history...
464
        try {
465
            $conceptInfo = $sparql->queryConceptInfo($uri, $this->config->getArrayClassURI(), array($this), $clang);
466
        } catch (EasyRdf\Http\Exception | EasyRdf\Exception | Throwable $e) {
467
             if ($this->model->getConfig()->getLogCaughtExceptions()) {
468
                 error_log('Caught exception: ' . $e->getMessage());
469
             }
470
        }
471
        return $conceptInfo;
472
    }
473
474
    /**
475
     * Lists the different concept groups available in the vocabulary.
476
     * @param string $clang content language parameter
477
     * @return array
478
     */
479
    public function listConceptGroups($clang = null)
480
    {
481
        if ($clang === null || $clang == '') {
482
            $clang = $this->getEnvLang();
483
        }
484
485
        $ret = array();
486
        $gclass = $this->config->getGroupClassURI();
487
        if ($gclass === null) {
0 ignored issues
show
introduced by
The condition $gclass === null is always false.
Loading history...
488
            return $ret;
489
        }
490
        // no group class defined, so empty result
491
        $groups = $this->getSparql()->listConceptGroups($gclass, $clang);
492
        foreach ($groups as $uri => $label) {
493
            $ret[$uri] = $label;
494
        }
495
496
        return $ret;
497
    }
498
499
    /**
500
     * Lists the concepts available in the concept group.
501
     * @param $clname
502
     * @return array
503
     */
504
    public function listConceptGroupContents($glname, $clang)
505
    {
506
        if (!$clang) {
507
            $clang = $this->config->getEnvLang();
508
        }
509
510
        $ret = array();
511
        $gclass = $this->config->getGroupClassURI();
512
        if ($gclass === null) {
0 ignored issues
show
introduced by
The condition $gclass === null is always false.
Loading history...
513
            return $ret;
514
        }
515
        // no group class defined, so empty result
516
        $group = $this->getConceptURI($glname);
517
        $contents = $this->getSparql()->listConceptGroupContents($gclass, $group, $clang, $this->config->getShowDeprecated());
518
        foreach ($contents as $uri => $label) {
519
            $ret[$uri] = $label;
520
        }
521
522
        return $ret;
523
    }
524
525
    /**
526
     * Returns the letters of the alphabet which have been used in this vocabulary.
527
     * The returned letters may also include specials such as '0-9' (digits) and '!*' (special characters).
528
     * @param $clang content language
0 ignored issues
show
Bug introduced by
The type content 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...
529
     * @return array array of letters
530
     */
531
    public function getAlphabet($clang)
532
    {
533
        $chars = $this->getSparql()->queryFirstCharacters($clang, $this->config->getIndexClasses());
534
        $letters = array();
535
        $digits = false;
536
        $specials = false;
537
        foreach ($chars as $char) {
538
            if (preg_match('/\p{L}/u', $char)) {
539
                $letters[] = $char;
540
            } elseif (preg_match('/\d/u', $char)) {
541
                $digits = true;
542
            } else {
543
                $specials = true;
544
            }
545
        }
546
        usort($letters, 'strcoll');
547
        if ($specials) {
548
            $letters[] = '!*';
549
        }
550
551
        if ($digits) {
552
            $letters[] = '0-9';
553
        }
554
555
        return $letters;
556
    }
557
558
    /**
559
     * Searches for concepts with a label starting with the specified letter.
560
     * Also the special tokens '0-9' (digits), '!*' (special characters) and '*'
561
     * (everything) are supported.
562
     * @param $letter letter (or special token) to search for
0 ignored issues
show
Bug introduced by
The type letter 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...
563
     */
564
    public function searchConceptsAlphabetical($letter, $limit = null, $offset = null, $clang = null)
565
    {
566
        return $this->getSparql()->queryConceptsAlphabetical($letter, $clang, $limit, $offset, $this->config->getIndexClasses(), $this->config->getShowDeprecated(), $this->config->getAlphabeticalListQualifier());
567
    }
568
569
    /**
570
     * Makes a query for the transitive broaders of a concept and returns the concepts hierarchy processed for the view.
571
     * @param string $lang
572
     * @param string $uri
573
     */
574
    public function getBreadCrumbs($lang, $uri)
575
    {
576
        $broaders = $this->getConceptTransitiveBroaders($uri, 1000, true, $lang);
577
        $origCrumbs = $this->getCrumbs($broaders, $uri);
578
        return $this->combineCrumbs($origCrumbs);
579
    }
580
581
    /**
582
     * Takes the crumbs as a parameter and combines the crumbs if the path they form is too long.
583
     * @return array
584
     */
585
    private function combineCrumbs($origCrumbs)
586
    {
587
        $combined = array();
588
        foreach ($origCrumbs as $pathKey => $path) {
589
            $firstToCombine = true;
590
            $combinedPath = array();
591
            foreach ($path as $crumbKey => $crumb) {
592
                if ($crumb->getPrefLabel() === '...') {
593
                    array_push($combinedPath, $crumb);
594
                    if ($firstToCombine) {
595
                        $firstToCombine = false;
596
                    } else {
597
                        unset($origCrumbs[$pathKey][$crumbKey]);
598
                    }
599
                }
600
            }
601
            $combined[] = $combinedPath;
602
        }
603
604
        return array('combined' => $combined, 'breadcrumbs' => $origCrumbs);
605
    }
606
607
    /**
608
     * Recursive function for building the breadcrumb paths for the view.
609
     * @param array $bTresult contains the results of the broaderTransitive query.
610
     * @param string $uri
611
     * @param array $path
612
     */
613
    private function getCrumbs($bTresult, $uri, $path = null)
614
    {
615
        $crumbs = array();
616
        if (!isset($path)) {
617
            $path = array();
618
        }
619
620
        // check that there is no cycle (issue #220)
621
        foreach ($path as $childcrumb) {
622
            if ($childcrumb->getUri() == $uri) {
623
                // found a cycle - short-circuit and stop
624
                return $crumbs;
625
            }
626
        }
627
        if (isset($bTresult[$uri]['direct'])) {
628
            foreach ($bTresult[$uri]['direct'] as $broaderUri) {
629
                $newpath = array_merge($path, array(new Breadcrumb($uri, $bTresult[$uri]['label'])));
630
                if ($uri !== $broaderUri) {
631
                    $crumbs = array_merge($crumbs, $this->getCrumbs($bTresult, $broaderUri, $newpath));
632
                }
633
            }
634
        } else { // we have reached the end of a path and we need to start a new row in the 'stack'
635
            if (isset($bTresult[$uri])) {
636
                $path = array_merge($path, array(new Breadcrumb($uri, $bTresult[$uri]['label'])));
637
            }
638
639
            $index = 1;
640
            $length = sizeof($path);
641
            $limit = $length - 5;
642
            foreach ($path as $crumb) {
643
                if ($length > 5 && $index > $length - $limit) { // displays 5 concepts closest to the concept.
644
                    $crumb->hideLabel();
645
                }
646
                $index++;
647
            }
648
            $crumbs[] = array_reverse($path);
649
        }
650
        return $crumbs;
651
    }
652
653
    /**
654
     * Verify that the requested language is supported by the vocabulary. If not, returns
655
     * the default language of the vocabulary.
656
     * @param string $lang language to check
657
     * @return string language tag that is supported by the vocabulary
658
     */
659
660
    public function verifyVocabularyLanguage($lang)
661
    {
662
        return (in_array($lang, $this->config->getLanguages())) ? $lang : $this->config->getDefaultLanguage();
663
    }
664
665
    /**
666
     * Returns a list of recently changed or entirely new concepts.
667
     * @param string $prop the property uri pointing to timestamps, eg. 'dc:modified'
668
     * @param string $clang content language for the labels
669
     * @param int $offset starting index offset
670
     * @param int $limit maximum number of concepts to return
671
     * @return Array
672
     */
673
    public function getChangeList($prop, $clang, $offset, $limit)
674
    {
675
        $showDeprecated = $this->getConfig()->getShowDeprecatedChanges();
676
        return $this->getSparql()->queryChangeList($prop, $clang, $offset, $limit, $showDeprecated);
677
    }
678
679
    public function getTitle($lang=null) {
680
      return $this->config->getTitle($lang);
681
    }
682
683
    public function getShortName() {
684
      return $this->config->getShortName();
685
    }
686
687
    public function getId() {
688
      return $this->config->getId();
689
    }
690
691
    public function getModifiedDate()
692
    {
693
        $modifiedDate = null;
694
695
        $conceptSchemeURI = $this->getDefaultConceptScheme();
696
        if ($conceptSchemeURI) {
697
            $conceptSchemeGraph = $this->getConceptScheme($conceptSchemeURI);
698
            if (!$conceptSchemeGraph->isEmpty()) {
699
                $literal = $conceptSchemeGraph->getLiteral($conceptSchemeURI, "dc:modified");
700
                if ($literal) {
0 ignored issues
show
introduced by
$literal is of type EasyRdf\Literal, thus it always evaluated to true.
Loading history...
701
                    $modifiedDate = $literal->getValue();
702
                }
703
            }
704
        }
705
706
        return $modifiedDate;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $modifiedDate also could return the type boolean|integer|string which is incompatible with the return type mandated by Modifiable::getModifiedDate() of DateTime|null.
Loading history...
707
    }
708
709
    public function isUseModifiedDate()
710
    {
711
        return $this->getConfig()->isUseModifiedDate();
712
    }
713
}
714