Completed
Push — master ( e821af...b81c51 )
by Osma
41s queued 31s
created

Vocabulary::getConceptHierarchy()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 7

Duplication

Lines 7
Ratio 100 %

Importance

Changes 0
Metric Value
cc 3
nc 4
nop 2
dl 7
loc 7
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
        return $this->resource->get('void:sparqlEndpoint')->getUri();
35
    }
36
37
    /**
38
     * Get the SPARQL graph URI for this vocabulary
39
     *
40
     * @return string|null graph URI
41
     */
42
    public function getGraph()
43
    {
44
        $graph = $this->resource->get('skosmos:sparqlGraph');
45
        if ($graph) {
46
            $graph = $graph->getUri();
47
        }
48
49
        return $graph;
50
    }
51
52
    /**
53
     * Get the SPARQL implementation for this vocabulary
54
     *
55
     * @return GenericSparql SPARQL object
56
     */
57
    public function getSparql()
58
    {
59
        $endpoint = $this->getEndpoint();
60
        $graph = $this->getGraph();
61
        $dialect = $this->resource->get('skosmos:sparqlDialect');
62
        $dialect = $dialect ? $dialect->getValue() : $this->model->getConfig()->getDefaultSparqlDialect();
63
64
        return $this->model->getSparqlImplementation($dialect, $endpoint, $graph);
65
    }
66
67
    /**
68
     * Get the URI space of concepts in this vocabulary.
69
     *
70
     * @return string full URI of concept
71
     */
72
    public function getUriSpace()
73
    {
74
        if ($this->urispace === null) // initialize cache
75
        {
76
            $this->urispace = $this->resource->getLiteral('void:uriSpace')->getValue();
77
        }
78
79
        return $this->urispace;
80
    }
81
82
    /**
83
     * Return true if the URI is within the URI space of this vocabulary.
84
     *
85
     * @param string full URI of concept
86
     * @return bool true if URI is within URI namespace, false otherwise
87
     */
88
89
    public function containsURI($uri)
90
    {
91
        return (strpos($uri, $this->getUriSpace()) === 0);
92
    }
93
94
    /**
95
     * Get the full URI of a concept in a vocabulary. If the passed local
96
     * name is already a full URI, return it unchanged.
97
     *
98
     * @param $lname string local name of concept
99
     * @return string full URI of concept
100
     */
101
    public function getConceptURI($lname)
102
    {
103
        if (strpos($lname, 'http') === 0) {
104
            return $lname;
105
        }
106
        // already a full URI
107
        return $this->getUriSpace() . $lname;
108
    }
109
110
    /**
111
     * Asks the sparql implementation to make a label query for a uri.
112
     * @param string $uri
113
     * @param string $lang
114
     */
115
    public function getConceptLabel($uri, $lang)
116
    {
117
        return $this->getSparql()->queryLabel($uri, $lang);
118
    }
119
120
    /**
121
     * Get the localname of a concept in the vocabulary. If the URI is not
122
     * in the URI space of this vocabulary, return the full URI.
123
     *
124
     * @param $uri string full URI of concept
125
     * @return string local name of concept, or original full URI if the local name cannot be determined
126
     */
127
    public function getLocalName($uri)
128
    {
129
        return str_replace($this->getUriSpace(), "", $uri);
130
    }
131
132
    /**
133
     * Retrieves all the information about the Vocabulary
134
     * from the SPARQL-endpoint.
135
     */
136
    public function getInfo($lang = null)
137
    {
138
        $ret = array();
139
        if (!$lang) {
140
            $lang = $this->getEnvLang();
141
        }
142
143
        // get metadata (literals only e.g. name) from vocabulary configuration file
144
        foreach ($this->resource->properties() as $prop) {
145
            foreach ($this->resource->allLiterals($prop, $lang) as $val) {
146
                $ret[$prop][] = $val->getValue();
147
            }
148
        }
149
150
        // also include ConceptScheme metadata from SPARQL endpoint
151
        $defaultcs = $this->getDefaultConceptScheme();
152
153
        // query everything the endpoint knows about the ConceptScheme
154
        $sparql = $this->getSparql();
155
        $result = $sparql->queryConceptScheme($defaultcs);
156
        $conceptscheme = $result->resource($defaultcs);
0 ignored issues
show
Bug introduced by
The method resource does only exist in EasyRdf\Graph, but not in EasyRdf\Http\Response and EasyRdf\Sparql\Result.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
157
        $this->order = array("dc:title", "dc11:title", "skos:prefLabel", "rdfs:label", "dc:subject", "dc11:subject", "dc:description", "dc11:description", "dc:publisher", "dc11:publisher", "dc:creator", "dc11:creator", "dc:contributor", "dc:language", "dc11:language", "owl:versionInfo", "dc:source", "dc11:source");
158
159
        foreach ($conceptscheme->properties() as $prop) {
160
            foreach ($conceptscheme->allLiterals($prop, $lang) as $val) {
161
                $prop = (substr($prop, 0, 5) == 'dc11:') ? str_replace('dc11:', 'dc:', $prop) : $prop;
162
                $ret[$prop][$val->getValue()] = $val;
163
            }
164
            if (!isset($ret[$prop]) || sizeof($ret[$prop]) == 0) { // not found with language tag
165
                foreach ($conceptscheme->allLiterals($prop, null) as $val) {
166
                    $prop = (substr($prop, 0, 5) == 'dc11:') ? str_replace('dc11:', 'dc:', $prop) : $prop;
167
                    if ($val->getValue() instanceof DateTime) {
168
                        $val = Punic\Calendar::formatDate($val->getValue(), 'full', $lang) . ' ' . Punic\Calendar::format($val->getValue(), 'HH:mm:ss', $lang);
169
                    }
170
                    $ret[$prop][] = $val;
171
                }
172
            }
173
            foreach ($conceptscheme->allResources($prop) as $val) {
174
                $prop = (substr($prop, 0, 5) == 'dc11:') ? str_replace('dc11:', 'dc:', $prop) : $prop;
175
                $exvocab = $this->model->guessVocabularyFromURI($val->getURI());
176
                $exlabel = $this->getExternalLabel($exvocab, $val->getURI(), $lang);
0 ignored issues
show
Bug introduced by
It seems like $exvocab defined by $this->model->guessVocab...FromURI($val->getURI()) on line 175 can be null; however, DataObject::getExternalLabel() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
177
                if (isset($exlabel)) {
178
                    $val->add('skosmos:vocab', $exvocab->getId());
179
                    $val->add('skosmos:label', $exlabel);
180
                }
181
                $label = $val->label($lang) ? $val->label($lang)->getValue() : $val->getUri();
182
                $ret[$prop][$exlabel ? $exlabel->getValue() : $label] = $val;
183
            }
184
            if (isset($ret[$prop])) {
185
                ksort($ret[$prop]);
186
            }
187
        }
188
        if (isset($ret['owl:versionInfo'])) { // if version info availible for vocabulary convert it to a more readable format
189
            $ret['owl:versionInfo'][0] = $this->parseVersionInfo($ret['owl:versionInfo'][0]);
190
        }
191
        // remove duplicate values
192
        foreach (array_keys($ret) as $prop) {
193
            $ret[$prop] = array_unique($ret[$prop]);
194
        }
195
196
        $ret = $this->arbitrarySort($ret);
197
198
        // filtering multiple labels
199
        if (isset($ret['dc:title'])) {
200
            unset($ret['dc11:title'], $ret['skos:prefLabel'], $ret['rdfs:label']);
201
        } else if (isset($ret['dc11:title'])) {
202
            unset($ret['skos:prefLabel'], $ret['rdfs:label']);
203
        } else if (isset($ret['skos:prefLabel'])) {
204
            unset($ret['rdfs:label']);
205
        }
206
207
        return $ret;
208
    }
209
210
    /**
211
     * Return all concept schemes in the vocabulary.
212
     * @return array Array with concept scheme URIs (string) as keys and labels (string) as values
213
     */
214
215
    public function getConceptSchemes($lang = '')
216
    {
217
        if ($lang === '') {
218
            $lang = $this->getEnvLang();
219
        }
220
221
        return $this->getSparql()->queryConceptSchemes($lang);
222
    }
223
224
    /**
225
     * Return the URI of the default concept scheme of this vocabulary. If the skosmos:mainConceptScheme property is set in the
226
     * vocabulary configuration, that will be returned. Otherwise an arbitrary concept scheme will be returned.
227
     * @return string concept scheme URI
228
     */
229
230
    public function getDefaultConceptScheme()
231
    {
232
        $conceptScheme = $this->config->getMainConceptSchemeURI();
233
        if ($conceptScheme) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $conceptScheme of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
234
            return $conceptScheme;
235
        }
236
237
        // mainConceptScheme not explicitly set, guess it
238
        $conceptSchemes = $this->getConceptSchemes();
239
        $conceptSchemeURIs = array_keys($conceptSchemes);
240
        // return the URI of the last concept scheme
241
        return array_pop($conceptSchemeURIs);
242
    }
243
244
    /**
245
     * Returns the main Concept Scheme of that Vocabulary, or null if not set.
246
     * @param string $defaultConceptSchemeURI default concept scheme URI
247
     * @return \EasyRdf\Graph|mixed
248
     */
249
    public function getConceptScheme(string $defaultConceptSchemeURI)
250
    {
251
        return $this->getSparql()->queryConceptScheme($defaultConceptSchemeURI);
252
    }
253
254
    /**
255
     * Return the top concepts of a concept scheme in the vocabulary.
256
     * @param string $conceptScheme URI of concept scheme whose top concepts to return. If not set,
257
     *                              the default concept scheme of the vocabulary will be used.
258
     * @param string $lang preferred language for the concept labels,
259
     * @return array Array with concept URIs (string) as keys and labels (string) as values
260
     */
261
262
    public function getTopConcepts($conceptScheme = null, $lang = '')
263
    {
264
        if ($lang === '') {
265
            $lang = $this->getEnvLang();
266
        }
267
        $fallback = $this->config->getDefaultLanguage();
268
269
        if ($conceptScheme === null || $conceptScheme == '') {
270
            $conceptScheme = $this->getDefaultConceptScheme();
271
        }
272
273
        return $this->getSparql()->queryTopConcepts($conceptScheme, $lang, $fallback);
274
    }
275
276
    /**
277
     * Tries to parse version, date and time from sparql version information into a readable format.
278
     * @param string $version
279
     * @return string
280
     */
281
    private function parseVersionInfo($version)
282
    {
283
        $parts = explode(' ', $version);
284
        if ($parts[0] != '$Id:') {
285
            return $version;
286
        }
287
        // don't know how to parse
288
        $rev = $parts[2];
289
        $datestr = $parts[3] . ' ' . $parts[4];
290
291
        return "$datestr (r$rev)";
292
    }
293
294
    /**
295
     * Counts the statistics of the vocabulary.
296
     * @return array of the concept/group counts
297
     */
298
    public function getStatistics($lang = '', $array=null, $group=null)
299
    {
300
        $sparql = $this->getSparql();
301
        // find the number of concepts
302
        return $sparql->countConcepts($lang, $array, $group);
303
    }
304
305
    /**
306
     * Counts the statistics of the vocabulary.
307
     * @return array of the concept counts in different languages
308
     */
309
    public function getLabelStatistics()
310
    {
311
        $sparql = $this->getSparql();
312
        $ret = array();
313
        // count the number of different types of concepts in all languages
314
        $ret['terms'] = $sparql->countLangConcepts($this->config->getLanguages(), $this->config->getIndexClasses());
315
316
        return $ret;
317
    }
318
319
    /**
320
     * Gets the parent concepts of a concept and child concepts for all of those.
321
     * @param string $uri
322
     * @param string $lang language identifier.
323
     */
324 View Code Duplication
    public function getConceptHierarchy($uri, $lang)
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...
325
    {
326
        $lang = $lang ? $lang : $this->getEnvLang();
327
        $fallback = count($this->config->getLanguageOrder($lang)) > 1 ? $this->config->getLanguageOrder($lang)[1] : $this->config->getDefaultLanguage();
328
        $props = $this->config->getHierarchyProperty();
329
        return $this->getSparql()->queryParentList($uri, $lang, $fallback, $props);
330
    }
331
332
    /**
333
     * Gets the child relations of a concept and whether these children have more children.
334
     * @param string $uri
335
     */
336 View Code Duplication
    public function getConceptChildren($uri, $lang)
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...
337
    {
338
        $lang = $lang ? $lang : $this->getEnvLang();
339
        $fallback = count($this->config->getLanguageOrder($lang)) > 1 ? $this->config->getLanguageOrder($lang)[1] : $this->config->getDefaultLanguage();
340
        $props = $this->config->getHierarchyProperty();
341
        return $this->getSparql()->queryChildren($uri, $lang, $fallback, $props);
342
    }
343
344
    /**
345
     * Gets the skos:narrower relations of a concept.
346
     * @param string $uri
347
     * @param string $lang language identifier.
348
     */
349
    public function getConceptNarrowers($uri, $lang)
350
    {
351
        $lang = $lang ? $lang : $this->getEnvLang();
352
        return $this->getSparql()->queryProperty($uri, 'skos:narrower', $lang);
353
    }
354
355
    /**
356
     * Gets the skos:narrowerTransitive relations of a concept.
357
     * @param string $uri
358
     * @param integer $limit
359
     * @param string $lang language identifier.
360
     */
361
    public function getConceptTransitiveNarrowers($uri, $limit, $lang)
362
    {
363
        $lang = $lang ? $lang : $this->getEnvLang();
364
        return $this->getSparql()->queryTransitiveProperty($uri, array('skos:narrower'), $lang, $limit);
365
    }
366
367
    /**
368
     * Gets the skos:broader relations of a concept.
369
     * @param string $uri
370
     * @param string $lang language identifier.
371
     */
372
    public function getConceptBroaders($uri, $lang)
373
    {
374
        $lang = $lang ? $lang : $this->getEnvLang();
375
        return $this->getSparql()->queryProperty($uri, 'skos:broader', $lang);
376
    }
377
378
    /**
379
     * Gets the skos:broaderTransitive relations of a concept.
380
     * @param string $uri
381
     * @param integer $limit
382
     * @param boolean $any set to true if you want to have a label even in case of a correct language one missing.
383
     * @param string $lang language identifier.
384
     */
385
    public function getConceptTransitiveBroaders($uri, $limit, $any = false, $lang)
386
    {
387
        $lang = $lang ? $lang : $this->getEnvLang();
388
        $fallback = $this->config->getDefaultLanguage();
389
        return $this->getSparql()->queryTransitiveProperty($uri, array('skos:broader'), $lang, $limit, $any, $fallback);
390
    }
391
392
    /**
393
     * Gets all the skos:related concepts of a concept.
394
     * @param string $uri
395
     * @param string $lang language identifier.
396
     */
397
    public function getConceptRelateds($uri, $lang)
398
    {
399
        $lang = $lang ? $lang : $this->getEnvLang();
400
        return $this->getSparql()->queryProperty($uri, 'skos:related', $lang);
401
    }
402
403
    /**
404
     * Makes a query into the sparql endpoint for a concept.
405
     * @param string $uri the full URI of the concept
406
     * @return Concept[]
407
     */
408
    public function getConceptInfo($uri, $clang)
409
    {
410
        $sparql = $this->getSparql();
411
412
        return $sparql->queryConceptInfo($uri, $this->config->getArrayClassURI(), array($this), $clang);
413
    }
414
415
    /**
416
     * Lists the different concept groups available in the vocabulary.
417
     * @param string $clang content language parameter
418
     * @return array
419
     */
420
    public function listConceptGroups($clang = null)
421
    {
422
        if ($clang === null || $clang == '') {
423
            $clang = $this->getEnvLang();
424
        }
425
426
        $ret = array();
427
        $gclass = $this->config->getGroupClassURI();
428
        if ($gclass === null) {
429
            return $ret;
430
        }
431
        // no group class defined, so empty result
432
        $groups = $this->getSparql()->listConceptGroups($gclass, $clang);
433
        foreach ($groups as $uri => $label) {
434
            $ret[$uri] = $label;
435
        }
436
437
        return $ret;
438
    }
439
440
    /**
441
     * Lists the concepts available in the concept group.
442
     * @param $clname
443
     * @return array
444
     */
445
    public function listConceptGroupContents($glname, $clang)
446
    {
447
        if (!$clang) {
448
            $clang = $this->config->getEnvLang();
449
        }
450
451
        $ret = array();
452
        $gclass = $this->config->getGroupClassURI();
453
        if ($gclass === null) {
454
            return $ret;
455
        }
456
        // no group class defined, so empty result
457
        $group = $this->getConceptURI($glname);
458
        $contents = $this->getSparql()->listConceptGroupContents($gclass, $group, $clang, $this->config->getShowDeprecated());
459
        foreach ($contents as $uri => $label) {
460
            $ret[$uri] = $label;
461
        }
462
463
        return $ret;
464
    }
465
466
    /**
467
     * Returns the letters of the alphabet which have been used in this vocabulary.
468
     * The returned letters may also include specials such as '0-9' (digits) and '!*' (special characters).
469
     * @param $clang content language
470
     * @return array array of letters
471
     */
472
    public function getAlphabet($clang)
473
    {
474
        $chars = $this->getSparql()->queryFirstCharacters($clang, $this->config->getIndexClasses());
475
        $letters = array();
476
        $digits = false;
477
        $specials = false;
478
        foreach ($chars as $char) {
479
            if (preg_match('/\p{L}/u', $char)) {
480
                $letters[] = $char;
481
            } elseif (preg_match('/\d/u', $char)) {
482
                $digits = true;
483
            } else {
484
                $specials = true;
485
            }
486
        }
487
        usort($letters, 'strcoll');
488
        if ($specials) {
489
            $letters[] = '!*';
490
        }
491
492
        if ($digits) {
493
            $letters[] = '0-9';
494
        }
495
496
        return $letters;
497
    }
498
499
    /**
500
     * Searches for concepts with a label starting with the specified letter.
501
     * Also the special tokens '0-9' (digits), '!*' (special characters) and '*'
502
     * (everything) are supported.
503
     * @param $letter letter (or special token) to search for
504
     */
505
    public function searchConceptsAlphabetical($letter, $limit = null, $offset = null, $clang = null)
506
    {
507
        return $this->getSparql()->queryConceptsAlphabetical($letter, $clang, $limit, $offset, $this->config->getIndexClasses(), $this->config->getShowDeprecated(), $this->config->getAlphabeticalListQualifier());
508
    }
509
510
    /**
511
     * Makes a query for the transitive broaders of a concept and returns the concepts hierarchy processed for the view.
512
     * @param string $lang
513
     * @param string $uri
514
     */
515
    public function getBreadCrumbs($lang, $uri)
516
    {
517
        $broaders = $this->getConceptTransitiveBroaders($uri, 1000, true, $lang);
518
        $origCrumbs = $this->getCrumbs($broaders, $uri);
0 ignored issues
show
Bug introduced by
It seems like $broaders defined by $this->getConceptTransit...uri, 1000, true, $lang) on line 517 can also be of type null; however, Vocabulary::getCrumbs() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
519
        return $this->combineCrumbs($origCrumbs);
520
    }
521
522
    /**
523
     * Takes the crumbs as a parameter and combines the crumbs if the path they form is too long.
524
     * @return array
525
     */
526
    private function combineCrumbs($origCrumbs)
527
    {
528
        $combined = array();
529
        foreach ($origCrumbs as $pathKey => $path) {
530
            $firstToCombine = true;
531
            $combinedPath = array();
532
            foreach ($path as $crumbKey => $crumb) {
533
                if ($crumb->getPrefLabel() === '...') {
534
                    array_push($combinedPath, $crumb);
535
                    if ($firstToCombine) {
536
                        $firstToCombine = false;
537
                    } else {
538
                        unset($origCrumbs[$pathKey][$crumbKey]);
539
                    }
540
                }
541
            }
542
            $combined[] = $combinedPath;
543
        }
544
545
        return array('combined' => $combined, 'breadcrumbs' => $origCrumbs);
546
    }
547
548
    /**
549
     * Recursive function for building the breadcrumb paths for the view.
550
     * @param array $bTresult contains the results of the broaderTransitive query.
551
     * @param string $uri
552
     * @param array $path
553
     */
554
    private function getCrumbs($bTresult, $uri, $path = null)
555
    {
556
        $crumbs = array();
557
        if (!isset($path)) {
558
            $path = array();
559
        }
560
561
        // check that there is no cycle (issue #220)
562
        foreach ($path as $childcrumb) {
563
            if ($childcrumb->getUri() == $uri) {
564
                // found a cycle - short-circuit and stop
565
                return $crumbs;
566
            }
567
        }
568
        if (isset($bTresult[$uri]['direct'])) {
569
            foreach ($bTresult[$uri]['direct'] as $broaderUri) {
570
                $newpath = array_merge($path, array(new Breadcrumb($uri, $bTresult[$uri]['label'])));
571
                if ($uri !== $broaderUri) {
572
                    $crumbs = array_merge($crumbs, $this->getCrumbs($bTresult, $broaderUri, $newpath));
573
                }
574
            }
575
        } else { // we have reached the end of a path and we need to start a new row in the 'stack'
576
            if (isset($bTresult[$uri])) {
577
                $path = array_merge($path, array(new Breadcrumb($uri, $bTresult[$uri]['label'])));
578
            }
579
580
            $index = 1;
581
            $length = sizeof($path);
582
            $limit = $length - 5;
583
            foreach ($path as $crumb) {
584
                if ($length > 5 && $index > $length - $limit) { // displays 5 concepts closest to the concept.
585
                    $crumb->hideLabel();
586
                }
587
                $index++;
588
            }
589
            $crumbs[] = array_reverse($path);
590
        }
591
        return $crumbs;
592
    }
593
594
    /**
595
     * Verify that the requested language is supported by the vocabulary. If not, returns
596
     * the default language of the vocabulary.
597
     * @param string $lang language to check
598
     * @return string language tag that is supported by the vocabulary
599
     */
600
601
    public function verifyVocabularyLanguage($lang)
602
    {
603
        return (in_array($lang, $this->config->getLanguages())) ? $lang : $this->config->getDefaultLanguage();
604
    }
605
606
    /**
607
     * Returns a list of recently changed or entirely new concepts.
608
     * @param string $clang content language for the labels
609
     * @param string $lang UI language for the dates
610
     * @return Array
611
     */
612
    public function getChangeList($prop, $clang, $lang, $offset)
613
    {
614
      $changelist = $this->getSparql()->queryChangeList($clang, $offset, $prop);
615
      $bydate = array();
616
      foreach($changelist as $concept) {
617
        $concept['datestring'] = Punic\Calendar::formatDate($concept['date'], 'medium', $lang);
618
        $bydate[Punic\Calendar::getMonthName($concept['date'], 'wide', $lang, true) . Punic\Calendar::format($concept['date'], ' y', $lang) ][strtolower($concept['prefLabel'])] = $concept;
619
      }
620
      return $bydate;
621
    }
622
623
    public function getTitle($lang=null) {
624
      return $this->config->getTitle($lang);
625
    }
626
627
    public function getShortName() {
628
      return $this->config->getShortName();
629
    }
630
631
    public function getId() {
632
      return $this->config->getId();
633
    }
634
635
    public function getModifiedDate()
636
    {
637
        $modifiedDate = null;
638
639
        $conceptSchemeURI = $this->getDefaultConceptScheme();
640
        if ($conceptSchemeURI) {
641
            $conceptSchemeGraph = $this->getConceptScheme($conceptSchemeURI);
642
            if (!$conceptSchemeGraph->isEmpty()) {
0 ignored issues
show
Bug introduced by
The method isEmpty does only exist in EasyRdf\Graph, but not in EasyRdf\Http\Response and EasyRdf\Sparql\Result.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
643
                $literal = $conceptSchemeGraph->getLiteral($conceptSchemeURI, "dc:modified");
0 ignored issues
show
Bug introduced by
The method getLiteral does only exist in EasyRdf\Graph, but not in EasyRdf\Http\Response and EasyRdf\Sparql\Result.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
644
                if ($literal) {
645
                    $modifiedDate = $literal->getValue();
646
                }
647
            }
648
        }
649
650
        return $modifiedDate;
651
    }
652
653
    public function isUseModifiedDate()
654
    {
655
        return $this->getConfig()->isUseModifiedDate();
656
    }
657
}
658