Passed
Pull Request — main (#1863)
by
unknown
03:47
created

ConceptPropertyValue::addSubMember()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Class for handling concept property values.
5
 */
6
class ConceptPropertyValue extends VocabularyDataObject
7
{
8
    /** submembers */
9
    private $submembers;
10
    /** property type */
11
    private $type;
12
    /** content language */
13
    private $clang;
14
    /** whether the property value is external w.r.t. to the subject resource */
15
    private $external;
16
    /** ordered list items if this value is an RDF list */
17
    private $listItems;
18
    /** whether the RDF list was truncated due to max limit */
19
    private $listTruncated;
20
21
    public function __construct($model, $vocab, $resource, $prop, $clang = '')
22
    {
23
        parent::__construct($model, $vocab, $resource);
24
        $this->submembers = array();
25
        $this->type = $prop;
26
        $this->clang = $clang;
27
        $this->listItems = null;
28
        $this->listTruncated = false;
29
        // check if the resource is external to the current vocabulary
30
        $this->external = ($this->getLabel('', 'null', false) === null);
31
        if ($this->external) {
32
            // if we find the resource in another vocabulary, use it instead
33
            $exvocab = $this->getExVocab();
34
            if ($exvocab !== null) {
35
                $this->vocab = $exvocab;
36
            }
37
        }
38
        // check if this resource is an RDF list and parse it
39
        $this->parseRdfList();
40
    }
41
42
    public function __toString()
43
    {
44
        return is_string($this->getLabel()) ? $this->getLabel() : $this->getLabel()->getValue();
0 ignored issues
show
introduced by
The condition is_string($this->getLabel()) is always false.
Loading history...
45
    }
46
47
    public function getLang()
48
    {
49
        return $this->model->getLocale();
50
    }
51
52
    public function getSortKey()
53
    {
54
        return strtolower($this->getLabel());
0 ignored issues
show
Bug introduced by
It seems like $this->getLabel() can also be of type null; however, parameter $string of strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

54
        return strtolower(/** @scrutinizer ignore-type */ $this->getLabel());
Loading history...
55
    }
56
57
    public function getLabel($lang = '', $fallbackToUri = 'uri', $allowExternal = true)
58
    {
59
        if ($this->clang) {
60
            $lang = $this->clang;
61
        }
62
        if ($this->vocab->getConfig()->getLanguageOrder($lang)) {
63
            foreach ($this->vocab->getConfig()->getLanguageOrder($lang) as $fallback) {
64
                if ($this->resource->label($fallback) !== null) {
65
                    return $this->resource->label($fallback);
66
                }
67
                // We need to check all the labels in case one of them matches a subtag of the current language
68
                if ($this->resource->allLiterals('skos:prefLabel')) {
69
                    foreach ($this->resource->allLiterals('skos:prefLabel') as $label) {
70
                        // the label lang code is a subtag of the UI lang eg. en-GB - create a new literal with the main language
71
                        if ($label !== null && strpos($label->getLang(), $fallback . '-') === 0) {
72
                            return EasyRdf\Literal::create($label, $fallback);
73
                        }
74
                    }
75
                }
76
            }
77
        }
78
79
        if ($this->resource->label($lang) !== null) { // current language
80
            return $this->resource->label($lang);
81
        } elseif ($this->resource->label($this->vocab->getConfig()->getDefaultLanguage()) !== null) { // vocab default language
82
            return $this->resource->label($this->vocab->getConfig()->getDefaultLanguage());
83
        } elseif ($this->resource->label() !== null) { // any language
84
            return $this->resource->label();
85
        } elseif ($this->resource->getLiteral('rdf:value', $lang) !== null) { // current language
86
            return $this->resource->getLiteral('rdf:value', $lang);
87
        } elseif ($this->resource->getLiteral('rdf:value') !== null) { // any language
88
            return $this->resource->getLiteral('rdf:value');
89
        }
90
91
        // see if we can find a label in another vocabulary known by the skosmos instance
92
        if ($allowExternal) {
93
            $label = $this->getExternalLabel($this->vocab, $this->getUri(), $lang);
94
            if ($label) {
0 ignored issues
show
introduced by
$label is of type EasyRdf\Literal, thus it always evaluated to true.
Loading history...
95
                return $label;
96
            }
97
        }
98
99
        if ($fallbackToUri == 'uri') {
100
            // return uri if no label is found
101
            return $this->resource->shorten() ? $this->resource->shorten() : $this->getUri();
102
        }
103
        return null;
104
    }
105
106
    public function getType()
107
    {
108
        return $this->type;
109
    }
110
111
    public function getUri()
112
    {
113
        return $this->resource->getUri();
114
    }
115
116
    public function getExVocab()
117
    {
118
        return $this->model->guessVocabularyFromURI($this->getUri(), $this->vocab->getId());
119
    }
120
121
    public function getVocab()
122
    {
123
        return $this->vocab;
124
    }
125
126
    public function getVocabName()
127
    {
128
        return $this->vocab->getShortName();
129
    }
130
131
    public function addSubMember($member, $lang = '')
132
    {
133
        $label = $member->getLabel($lang) ? $member->getLabel($lang) : $member->getLabel();
134
        $this->submembers[$label->getValue()] = $member;
135
        $this->sortSubMembers();
136
    }
137
138
    public function getSubMembers()
139
    {
140
        if (empty($this->submembers)) {
141
            return null;
142
        }
143
144
        return $this->submembers;
145
    }
146
147
    private function sortSubMembers()
148
    {
149
        if (!empty($this->submembers)) {
150
            ksort($this->submembers);
151
        }
152
153
    }
154
155
    public function isExternal()
156
    {
157
        return $this->external;
158
    }
159
160
    public function getNotation()
161
    {
162
        if ($this->vocab->getConfig()->showNotation() && $this->resource->get('skos:notation')) {
163
            return $this->resource->get('skos:notation')->getValue();
164
        }
165
166
    }
167
168
    public function isReified()
169
    {
170
        return (!$this->resource->label() && $this->resource->getLiteral('rdf:value'));
171
    }
172
173
    public function getReifiedPropertyValues()
174
    {
175
        $ret = array();
176
        $props = $this->resource->propertyUris();
177
        foreach ($props as $prop) {
178
            $prop = (EasyRdf\RdfNamespace::shorten($prop) !== null) ? EasyRdf\RdfNamespace::shorten($prop) : $prop;
179
            $propkey = str_starts_with($prop, 'dc11:') ?
180
                str_replace('dc11:', 'dc:', $prop) : $prop;
181
            foreach ($this->resource->allLiterals($prop) as $val) {
182
                if ($prop !== 'rdf:value') { // shown elsewhere
183
                    $ret[$this->model->getText($propkey)] = new ConceptPropertyValueLiteral($this->model, $this->vocab, $this->resource, $val, $prop);
184
                }
185
            }
186
            foreach ($this->resource->allResources($prop) as $val) {
187
                $ret[$this->model->getText($propkey)] = new ConceptPropertyValue($this->model, $this->vocab, $val, $prop, $this->clang);
188
            }
189
        }
190
        return $ret;
191
    }
192
193
    /**
194
     * Check if this resource represents an RDF list (has rdf:first property)
195
     * and parse the list items in order
196
     */
197
    private function parseRdfList()
198
    {
199
        // Check if this resource has rdf:first (indicating it's a list node)
200
        if ($this->resource->getResource('rdf:first') === null) {
201
            return; // Not an RDF list
202
        }
203
204
        $this->listItems = array();
205
        $currentNode = $this->resource;
206
        $itemsLimit = $this->model->getConfig()->getRdfListItemsLimit();
207
        $iteration = 0;
208
209
        while ($currentNode !== null && !($itemsLimit > 0 && $iteration >= $itemsLimit)) {
210
            $item = $currentNode->getResource('rdf:first');
211
            if ($item !== null) {
212
                $listItemValue = new ConceptPropertyValue($this->model, $this->vocab, $item, $this->type, $this->clang);
213
                $this->listItems[] = $listItemValue;
214
            }
215
            $iteration++;
216
217
            $restNode = $currentNode->getResource('rdf:rest');
218
            $isEndOfList = $restNode === null || $restNode->getUri() === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil';
219
220
            if ($isEndOfList) {
221
                $this->listTruncated = false;
222
                $currentNode = null;
223
            } else {
224
                $currentNode = $restNode;
225
            }
226
        }
227
228
        if ($currentNode !== null && $itemsLimit > 0 && $iteration >= $itemsLimit) {
229
            $this->listTruncated = true;
230
        }
231
    }
232
233
    public function isRdfList()
234
    {
235
        return $this->listItems !== null && count($this->listItems) > 0;
236
    }
237
238
    public function getRdfListItems()
239
    {
240
        return $this->listItems;
241
    }
242
243
    public function isRdfListTruncated()
244
    {
245
        return $this->listTruncated;
246
    }
247
248
}
249